#include <TargetConditionals.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/quota.h>
#include <sys/stat.h>
#include "hfs-tests.h"
#include "disk-image.h"
#include "test-utils.h"
#define QUOTA_DMG "/tmp/quota-test.sparseimage"
#define QUOTA_DMG_MOUNT_POINT "/tmp/quota-test-mount"
TEST(quotas, .run_as_root = true)
char quota_file[] = {
0xff, 0x31, 0xff, 0x35, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x09, 0x3a, 0x80, 0x00, 0x09, 0x3a, 0x80,
0x51, 0x55, 0x4f, 0x54, 0x41, 0x20, 0x48, 0x41,
0x53, 0x48, 0x20, 0x46, 0x49, 0x4c, 0x45, 0x00,
};
int run_quotas(__unused test_ctx_t *ctx)
{
disk_image_t *di = disk_image_create(QUOTA_DMG,
&(disk_image_opts_t) {
#if TARGET_OS_EMBEDDED
.mount_point = QUOTA_DMG_MOUNT_POINT,
#endif
.size = 64 * 1024 * 1024,
.enable_owners = true
});
char *path;
asprintf(&path, "%s/.quota.ops.user", di->mount_point);
int fd = open(path, O_CREAT | O_RDWR, 0777);
assert_with_errno(fd >= 0);
free(path);
assert_no_err(close(fd));
asprintf(&path, "%s/.quota.user", di->mount_point);
fd = open(path, O_CREAT | O_RDWR, 0777);
assert_with_errno(fd >= 0);
check_io(write(fd, quota_file, lengthof(quota_file)), lengthof(quota_file));
assert_no_err(ftruncate(fd, 131136));
assert_no_err(close(fd));
assert_no_err(quotactl(di->mount_point, QCMD(Q_QUOTAON, USRQUOTA), 0, path));
free(path);
struct dqblk dqb = {
.dqb_bhardlimit = 1024 * 1024,
.dqb_ihardlimit = 10,
.dqb_isoftlimit = 10,
};
assert_no_err(quotactl(di->mount_point, QCMD(Q_SETQUOTA, USRQUOTA),
501, (caddr_t)&dqb));
assert_no_err(chmod(di->mount_point, 0777));
assert_no_err(seteuid(501));
asprintf(&path, "%s/test-file", di->mount_point);
fd = open(path, O_CREAT | O_RDWR, 0777);
assert_with_errno(fd >= 0);
free(path);
assert_no_err(ftruncate(fd, 1024 * 1024 - 4096));
assert(ftruncate(fd, 2 * 1024 * 1024) == -1 && errno == EDQUOT);
assert_no_err(close(fd));
for (int i = 0; i < 10; ++i) {
asprintf(&path, "%s/test-file.%u", di->mount_point, i);
fd = open(path, O_CREAT | O_RDWR, 0777);
if (fd == -1) {
assert(i >= 8);
assert_with_errno(errno == EDQUOT);
} else {
assert(i < 8);
free(path);
assert_no_err(close(fd));
}
}
return 0;
}