Skip to content

Commit 484b2d8

Browse files
authored
Use quotactl_fd syscall when available (#180)
1 parent a6fcf2b commit 484b2d8

File tree

1 file changed

+43
-10
lines changed

1 file changed

+43
-10
lines changed

rules.c

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "isolate.h"
99

10+
#include <errno.h>
1011
#include <limits.h>
1112
#include <mntent.h>
1213
#include <stdio.h>
@@ -16,6 +17,7 @@
1617
#include <sys/mount.h>
1718
#include <sys/quota.h>
1819
#include <sys/stat.h>
20+
#include <sys/syscall.h>
1921
#include <sys/vfs.h>
2022
#include <unistd.h>
2123

@@ -502,12 +504,47 @@ find_device(char *path)
502504
return best_dev;
503505
}
504506

507+
static void
508+
quotactl_error(void)
509+
{
510+
// This errno has an outstandingly unhelpful message of "no such process".
511+
if (errno == ESRCH)
512+
die("Cannot set disk quota: quotas have not been enabled for this filesystem");
513+
die("Cannot set disk quota: %m");
514+
}
515+
505516
void
506517
set_quota(void)
507518
{
508519
if (!block_quota)
509520
return;
510521

522+
struct dqblk dq = {
523+
.dqb_bhardlimit = block_quota,
524+
.dqb_bsoftlimit = block_quota,
525+
.dqb_ihardlimit = inode_quota,
526+
.dqb_isoftlimit = inode_quota,
527+
.dqb_valid = QIF_LIMITS,
528+
};
529+
void *dq_ptr = (void*)&dq;
530+
int quota_op = QCMD(Q_SETQUOTA, USRQUOTA);
531+
532+
#ifdef SYS_quotactl_fd
533+
534+
// silence warning about unused function
535+
(void)find_device;
536+
537+
int cwd_fd = open(".", O_DIRECTORY | O_PATH);
538+
if (cwd_fd < 0)
539+
die("open: %m");
540+
541+
if (syscall(SYS_quotactl_fd, cwd_fd, quota_op, box_uid, dq_ptr) < 0)
542+
quotactl_error();
543+
544+
close(cwd_fd);
545+
546+
#else
547+
511548
char cwd[PATH_MAX];
512549
if (!getcwd(cwd, sizeof(cwd)))
513550
die("getcwd: %m");
@@ -528,16 +565,12 @@ set_quota(void)
528565
if (cwd_st.st_dev != dev_st.st_rdev)
529566
die("Identified %s as a filesystem on %s, but it is obviously false", cwd, dev);
530567

531-
struct dqblk dq = {
532-
.dqb_bhardlimit = block_quota,
533-
.dqb_bsoftlimit = block_quota,
534-
.dqb_ihardlimit = inode_quota,
535-
.dqb_isoftlimit = inode_quota,
536-
.dqb_valid = QIF_LIMITS,
537-
};
538-
if (quotactl(QCMD(Q_SETQUOTA, USRQUOTA), dev, box_uid, (caddr_t) &dq) < 0)
539-
die("Cannot set disk quota: %m");
540-
msg("Quota: Set block quota %d and inode quota %d\n", block_quota, inode_quota);
568+
if (quotactl(quota_op, dev, box_uid, dq_ptr) < 0)
569+
quotactl_error();
541570

542571
free(dev);
572+
573+
#endif
574+
575+
msg("Quota: Set block quota %d and inode quota %d\n", block_quota, inode_quota);
543576
}

0 commit comments

Comments
 (0)