-
Notifications
You must be signed in to change notification settings - Fork 1
/
pquota.cc
133 lines (107 loc) · 2.65 KB
/
pquota.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#define ENABLE_GETTEXT
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <sysexits.h>
#include <string>
#include <linux/quota.h>
#include <sys/quota.h>
#include <xfs/xfs.h>
#include <xfs/xqm.h>
// Usr libblkid to map dev_t to device paths.
#include <blkid/blkid.h>
typedef int errno_t;
errno_t
xfs_enable_quota(int * dirfd)
{
return 0;
}
errno_t
xfs_getattr(int fd, struct fsxattr& attr)
{
if (xfsctl(nullptr, fd, XFS_IOC_FSGETXATTR, &attr) == -1) {
return errno;
}
return 0;
}
errno_t
xfs_setattr(int fd, struct fsxattr& attr)
{
if (xfsctl(nullptr, fd, XFS_IOC_FSSETXATTR, &attr) == -1) {
return errno;
}
return 0;
}
errno_t
xfs_setquota(const std::string& directory, prid_t projid, off_t nbytes)
{
struct stat statbuf;
char * devname = nullptr;
if (::stat(directory.c_str(), &statbuf) == -1) {
return errno;
}
if (!S_ISDIR(statbuf.st_mode)) {
return ENOTDIR;
}
devname = blkid_devno_to_devname(statbuf.st_dev);
if (devname == nullptr) {
return ENODEV;
}
fs_disk_quota_t quota = {0};
quota.d_version = FS_DQUOT_VERSION;
quota.d_flags = XFS_PROJ_QUOTA;
quota.d_fieldmask = FS_DQ_BSOFT | FS_DQ_BHARD;
quota.d_id = projid;
// Space limits are in basic blocks (512 bytes).
quota.d_blk_hardlimit = nbytes / 512;
quota.d_blk_softlimit = nbytes / 512;
if (::quotactl(QCMD(Q_XSETQLIM, PRJQUOTA), devname,
projid, reinterpret_cast<caddr_t>("a)) == -1) {
free(devname);
return errno;
}
free(devname);
return 0;
}
errno_t
xfs_setproject(int dirfd, prid_t projid)
{
struct fsxattr attr;
errno_t error;
error = xfs_getattr(dirfd, attr);
if (error != 0) {
perror("xfs getattr");
return error;
}
// Set the project inherit flag on this directory.
attr.fsx_xflags |= XFS_XFLAG_PROJINHERIT;
attr.fsx_projid = projid;
error = xfs_setattr(dirfd, attr);
if (error != 0) {
fprintf(stderr, "XFS setattr failed: %s (%d)\n", strerror(error), error);
return error;
}
return ENOSYS;
}
int main(int argc, const char ** argv)
{
prid_t projid = 4;
off_t nbytes = 345 * 512;
for (int i = 1; i < argc; ++i) {
int dirfd = open(argv[i], O_RDONLY | O_DIRECTORY);
if (dirfd == -1) {
perror("open");
continue;
}
if (platform_test_xfs_fd(dirfd) == 0) {
fprintf(stderr, "%s is not XFS\n", argv[i]);
close(dirfd);
continue;
}
xfs_setproject(dirfd, projid);
xfs_setquota(argv[i], projid, nbytes);
xfs_setquota(argv[i], projid, 0);
close(dirfd);
}
return EX_OK;
}