77
88#include "isolate.h"
99
10+ #include <errno.h>
1011#include <limits.h>
1112#include <mntent.h>
1213#include <stdio.h>
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+
505516void
506517set_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