]> git.saurik.com Git - apple/hfs.git/blob - tests/cases/test-quotas.c
hfs-366.1.1.tar.gz
[apple/hfs.git] / tests / cases / test-quotas.c
1 //
2 // quotas.c
3 // hfs
4 //
5 // Created by Chris Suter on 8/13/15.
6 //
7 //
8
9 #include <TargetConditionals.h>
10
11 #include <unistd.h>
12 #include <stdio.h>
13 #include <fcntl.h>
14 #include <sys/types.h>
15 #include <sys/quota.h>
16 #include <sys/stat.h>
17
18 #include "hfs-tests.h"
19 #include "disk-image.h"
20 #include "test-utils.h"
21
22 #define QUOTA_DMG "/tmp/quota-test.sparseimage"
23 #define QUOTA_DMG_MOUNT_POINT "/tmp/quota-test-mount"
24
25 TEST(quotas, .run_as_root = true)
26
27 // This is what the quota file looks like after running edquota
28 char quota_file[] = {
29 0xff, 0x31, 0xff, 0x35, 0x00, 0x00, 0x00, 0x01,
30 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32 0x00, 0x09, 0x3a, 0x80, 0x00, 0x09, 0x3a, 0x80,
33 0x51, 0x55, 0x4f, 0x54, 0x41, 0x20, 0x48, 0x41,
34 0x53, 0x48, 0x20, 0x46, 0x49, 0x4c, 0x45, 0x00,
35 // Zero padding up to 131136 bytes
36 };
37
38 int run_quotas(__unused test_ctx_t *ctx)
39 {
40 disk_image_t *di = disk_image_create(QUOTA_DMG,
41 &(disk_image_opts_t) {
42 #if TARGET_OS_EMBEDDED
43 .mount_point = QUOTA_DMG_MOUNT_POINT,
44 #endif
45 .size = 64 * 1024 * 1024,
46 .enable_owners = true
47 });
48
49 char *path;
50 asprintf(&path, "%s/.quota.ops.user", di->mount_point);
51 int fd = open(path, O_CREAT | O_RDWR, 0777);
52 assert_with_errno(fd >= 0);
53 free(path);
54 assert_no_err(close(fd));
55
56 asprintf(&path, "%s/.quota.user", di->mount_point);
57 fd = open(path, O_CREAT | O_RDWR, 0777);
58 assert_with_errno(fd >= 0);
59 check_io(write(fd, quota_file, lengthof(quota_file)), lengthof(quota_file));
60 assert_no_err(ftruncate(fd, 131136));
61 assert_no_err(close(fd));
62
63 assert_no_err(quotactl(di->mount_point, QCMD(Q_QUOTAON, USRQUOTA), 0, path));
64 free(path);
65
66 struct dqblk dqb = {
67 .dqb_bhardlimit = 1024 * 1024,
68 .dqb_ihardlimit = 10,
69 .dqb_isoftlimit = 10,
70 };
71
72 assert_no_err(quotactl(di->mount_point, QCMD(Q_SETQUOTA, USRQUOTA),
73 501, (caddr_t)&dqb));
74
75 assert_no_err(chmod(di->mount_point, 0777));
76
77 // Now try and create a 2 MB file as UID 501
78 assert_no_err(seteuid(501));
79
80 asprintf(&path, "%s/test-file", di->mount_point);
81
82 fd = open(path, O_CREAT | O_RDWR, 0777);
83 assert_with_errno(fd >= 0);
84 free(path);
85
86 /*
87 * Not sure why we can't do the full 4 KB, but it's not a big deal
88 * so let's not worry about it.
89 */
90 assert_no_err(ftruncate(fd, 1024 * 1024 - 4096));
91
92 assert(ftruncate(fd, 2 * 1024 * 1024) == -1 && errno == EDQUOT);
93
94 assert_no_err(close(fd));
95
96 for (int i = 0; i < 10; ++i) {
97 asprintf(&path, "%s/test-file.%u", di->mount_point, i);
98 /*
99 * There might be an off by one error. It's not a big deal,
100 * so we let it go for now.
101 */
102 fd = open(path, O_CREAT | O_RDWR, 0777);
103 if (fd == -1) {
104 assert(i >= 8);
105 assert_with_errno(errno == EDQUOT);
106 } else {
107 assert(i < 8);
108 free(path);
109 assert_no_err(close(fd));
110 }
111 }
112
113 return 0;
114 }