fprintf(stderr, "usage: vquota [-Dhn] check directory\n");
fprintf(stderr, " vquota [-Dhn] lsfs\n");
fprintf(stderr, " vquota [-Dhn] limit mount_point size\n");
+ fprintf(stderr, " vquota [-Dhn] ulim mount_point user size\n");
fprintf(stderr, " vquota [-Dhn] show mount_point\n");
fprintf(stderr, " vquota [-Dhn] sync mount_point\n");
exit(retcode);
return rv;
}
+static int
+cmd_limit_uid(char *dirname, uid_t uid, uint64_t limit)
+{
+ prop_dictionary_t res, args;
+ int rv = 0;
+
+ args = prop_dictionary_create();
+ if (args == NULL)
+ printf("cmd_limit_uid(): couldn't create args dictionary\n");
+ res = prop_dictionary_create();
+ if (res == NULL)
+ printf("cmd_limit_uid(): couldn't create res dictionary\n");
+
+ (void) prop_dictionary_set_uint32(args, "uid", uid);
+ (void) prop_dictionary_set_uint64(args, "limit", limit);
+
+ if (send_command(dirname, "set limit uid", args, &res) == false) {
+ printf("Failed to send message to kernel\n");
+ rv = 1;
+ }
+
+ prop_object_release(args);
+ prop_object_release(res);
+
+ return rv;
+}
+
int
main(int argc, char **argv)
{
int ch;
+ uint64_t limit;
while ((ch = getopt(argc, argv, "Dhn")) != -1) {
switch(ch) {
return get_fslist();
}
if (strcmp(argv[0], "limit") == 0) {
- uint64_t limit;
if (argc != 3)
usage(1);
if (dehumanize_number(argv[2], &limit) < 0)
usage(1);
return cmd_sync(argv[1]);
}
+ if (strcmp(argv[0], "ulim") == 0) {
+ struct passwd *pwd;
+ if (argc != 4)
+ usage(1);
+ if ((pwd = getpwnam(argv[2])) == NULL)
+ errx(1, "%s: no such user", argv[2]);
+ if (dehumanize_number(argv[3], &limit) < 0)
+ err(1, "bad number for option: %s", argv[2]);
+
+ return cmd_limit_uid(argv[1], pwd->pw_uid, limit);
+ }
usage(0);
}
return 0;
}
+static int
+cmd_set_limit_uid(struct mount *mp, prop_dictionary_t args)
+{
+ uint64_t limit;
+ uid_t uid;
+ struct ac_unode ufind, *unp;
+
+ prop_dictionary_get_uint32(args, "uid", &uid);
+ prop_dictionary_get_uint64(args, "limit", &limit);
+
+ ufind.left_bits = (uid >> ACCT_CHUNK_BITS);
+
+ spin_lock(&mp->mnt_acct.ac_spin);
+ if ((unp = RB_FIND(ac_utree, &mp->mnt_acct.ac_uroot, &ufind)) == NULL)
+ unp = unode_insert(mp, uid);
+ unp->uid_chunk[(uid & ACCT_CHUNK_MASK)].limit = limit;
+ spin_unlock(&mp->mnt_acct.ac_spin);
+
+ return 0;
+}
+
int
sys_vquotactl(struct vquotactl_args *vqa)
/* const char *path, struct plistref *pref */
error = cmd_set_limit(mp, args);
goto done;
}
+ if (strcmp(cmd, "set limit uid") == 0) {
+ error = cmd_set_limit_uid(mp, args);
+ goto done;
+ }
return EINVAL;
done: