0

I have a filesystem that should be mounted with the prjquota flag. But due to human factors, someone might forget to do that, so I need to check that quota was enabled on application startup. I thought that it's possible to check using quotactl with Q_GETFMT as the subcmd argument. But it always sets the flag to 0. What am I doing wrong?

I've tried device as an absolute path to the file under XFS and as a path to the actual device. But no results.

bool isQuotaEnabled(const std::filesystem::path &device)
{
    uint32_t buff{};
    quotactl(QCMD(Q_GETFMT, PRJQUOTA), device.c_str(), 0, (caddr_t)&buff);
    return buff;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nolv
  • 63
  • 8
  • 1
    `buff` should be a `caddr_t`, not a `uint32_t`, for starters. And you should check `quotactl()`'s return value to see if it succeeded or not, and if not, inspect `errno` to find out why. – Shawn Jun 02 '22 at 16:23
  • It most defenetly should not be `caddr_t` accoring to docs. But thanks fro advice about `errno` – Nolv Jun 02 '22 at 20:08
  • Re *"...is XFS"*: Do you mean *"...in XFS"*? Or something else? – Peter Mortensen Jun 27 '22 at 12:30
  • Re *"...not be caddr_t"*: But the ***fourth*** argument in [the documentation you linked to](https://man7.org/linux/man-pages/man2/quotactl.2.html) says "`caddr_t addr`" - `int quotactl(int cmd, const char *special, int id, caddr_t addr);`. In your code, 'buf' is used in the ***fourth*** argument: `quotactl(QCMD(Q_GETFMT, PRJQUOTA), device.c_str(), 0, (caddr_t)&buff);`. Can you elaborate? – Peter Mortensen Jun 27 '22 at 12:54
  • @PeterMortensen from the docs to `Q_GETFMT` command: The addr argument should be a pointer to a 4-byte buffer where the format number will be stored. That's why it's either using 4 byte type or `caddr_t buff[4]`. I think the second option is ugly, especially if you take into account that the buffer is gonna be filled with just a simple number representing quota type, that would probably require type casting later. – Nolv Jun 29 '22 at 06:10

1 Answers1

0
// The argument is something like "/dev/loop1"
bool isQuotaEnabled(const std::filesystem::device& device)
{
    fs_quota_stat info{};
    if (quotactl(QCMD(Q_XGETQSTAT, PRJQUOTA), device.data(), 0, (caddr_t)&info) == -1) {
        throw std::system_error(errno, std::system_category(), "quotactl");
    }

    return static_cast<bool>(info.qs_flags & (XFS_QUOTA_PDQ_ACCT | XFS_QUOTA_PDQ_ENFD));
}

PRJQUOTA is for project quota. Replace it with the one you need.

       Q_XGETQSTAT
              Returns XFS filesystem-specific quota information in the
              fs_quota_stat structure pointed by addr.
Quota enabling flags (of format XFS_QUOTA_[UGP]DQ_{ACCT,ENFD})
          are defined without a leading "X", as
          FS_QUOTA_[UGP]DQ_{ACCT,ENFD}.
                  XFS_QUOTA_PDQ_ACCT  /* Project quota accounting */
                  XFS_QUOTA_PDQ_ENFD  /* Project quota limits enforcement */
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nolv
  • 63
  • 8