2
Unix SMB/CIFS implementation.
3
System QUOTA function wrappers
4
Copyright (C) Stefan (metze) Metzmacher 2003
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 3 of the License, or
9
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program. If not, see <http://www.gnu.org/licenses/>.
24
#define DBGC_CLASS DBGC_QUOTA
26
#ifdef HAVE_SYS_QUOTAS
28
#if defined(HAVE_QUOTACTL_4A)
30
/*#endif HAVE_QUOTACTL_4A */
31
#elif defined(HAVE_QUOTACTL_4B)
33
#error HAVE_QUOTACTL_4B not implemeted
35
/*#endif HAVE_QUOTACTL_4B */
36
#elif defined(HAVE_QUOTACTL_3)
38
#error HAVE_QUOTACTL_3 not implemented
40
/* #endif HAVE_QUOTACTL_3 */
41
#else /* NO_QUOTACTL_USED */
43
#endif /* NO_QUOTACTL_USED */
46
static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
54
/* find the block device file */
56
if (!path||!mntpath||!bdev||!fs)
57
smb_panic("sys_path_to_bdev: called with NULL pointer");
63
if ( sys_stat(path, &S) == -1 )
68
fp = setmntent(MOUNTED,"r");
73
while ((mnt = getmntent(fp))) {
74
if ( sys_stat(mnt->mnt_dir,&S) == -1 )
77
if (S.st_dev == devno) {
78
(*mntpath) = SMB_STRDUP(mnt->mnt_dir);
79
(*bdev) = SMB_STRDUP(mnt->mnt_fsname);
80
(*fs) = SMB_STRDUP(mnt->mnt_type);
81
if ((*mntpath)&&(*bdev)&&(*fs)) {
98
/* #endif HAVE_MNTENT */
99
#elif defined(HAVE_DEVNM)
101
/* we have this on HPUX, ... */
102
static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
108
if (!path||!mntpath||!bdev||!fs)
109
smb_panic("sys_path_to_bdev: called with NULL pointer");
115
/* find the block device file */
117
if ((ret=sys_stat(path, &S))!=0) {
121
if ((ret=devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1))!=0) {
125
/* we should get the mntpath right...
126
* but I don't know how
129
(*mntpath) = SMB_STRDUP(path);
130
(*bdev) = SMB_STRDUP(dev_disk);
131
if ((*mntpath)&&(*bdev)) {
143
/* #endif HAVE_DEVNM */
145
/* we should fake this up...*/
146
static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
150
if (!path||!mntpath||!bdev||!fs)
151
smb_panic("sys_path_to_bdev: called with NULL pointer");
157
(*mntpath) = SMB_STRDUP(path);
169
/*********************************************************************
170
Now the list of all filesystem specific quota systems we have found
171
**********************************************************************/
174
int (*get_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
175
int (*set_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
176
} sys_quota_backends[] = {
177
#ifdef HAVE_XFS_QUOTAS
178
{"xfs", sys_get_xfs_quota, sys_set_xfs_quota},
179
#endif /* HAVE_XFS_QUOTAS */
183
static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
185
const char *get_quota_command;
188
get_quota_command = lp_get_quota_command();
189
if (get_quota_command && *get_quota_command) {
196
case SMB_USER_QUOTA_TYPE:
197
case SMB_USER_FS_QUOTA_TYPE:
200
case SMB_GROUP_QUOTA_TYPE:
201
case SMB_GROUP_FS_QUOTA_TYPE:
205
DEBUG(0,("invalid quota type.\n"));
209
if (asprintf(&syscmd, "%s \"%s\" %d %d",
210
get_quota_command, path, qtype, _id) < 0) {
214
DEBUG (3, ("get_quota: Running command %s\n", syscmd));
216
lines = file_lines_pload(syscmd, NULL);
220
char *line = lines[0];
222
DEBUG (3, ("Read output from get_quota, \"%s\"\n", line));
224
/* we need to deal with long long unsigned here, if supported */
226
dp->qflags = (enum SMB_QUOTA_TYPE)strtoul(line, &p2, 10);
228
while (p && *p && isspace(*p)) {
233
dp->curblocks = STR_TO_SMB_BIG_UINT(p, &p);
238
while (p && *p && isspace(*p)) {
243
dp->softlimit = STR_TO_SMB_BIG_UINT(p, &p);
248
while (p && *p && isspace(*p)) {
253
dp->hardlimit = STR_TO_SMB_BIG_UINT(p, &p);
258
while (p && *p && isspace(*p)) {
263
dp->curinodes = STR_TO_SMB_BIG_UINT(p, &p);
268
while (p && *p && isspace(*p)) {
273
dp->isoftlimit = STR_TO_SMB_BIG_UINT(p, &p);
278
while (p && *p && isspace(*p)) {
283
dp->ihardlimit = STR_TO_SMB_BIG_UINT(p, &p);
288
while (p && *p && isspace(*p)) {
293
dp->bsize = STR_TO_SMB_BIG_UINT(p, NULL);
301
DEBUG (3, ("Parsed output of get_quota, ...\n"));
303
#ifdef LARGE_SMB_OFF_T
305
"qflags:%u curblocks:%llu softlimit:%llu hardlimit:%llu\n"
306
"curinodes:%llu isoftlimit:%llu ihardlimit:%llu bsize:%llu\n",
307
dp->qflags,(long long unsigned)dp->curblocks,
308
(long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit,
309
(long long unsigned)dp->curinodes,
310
(long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit,
311
(long long unsigned)dp->bsize));
312
#else /* LARGE_SMB_OFF_T */
314
"qflags:%u curblocks:%lu softlimit:%lu hardlimit:%lu\n"
315
"curinodes:%lu isoftlimit:%lu ihardlimit:%lu bsize:%lu\n",
316
dp->qflags,(long unsigned)dp->curblocks,
317
(long unsigned)dp->softlimit,(long unsigned)dp->hardlimit,
318
(long unsigned)dp->curinodes,
319
(long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit,
320
(long unsigned)dp->bsize));
321
#endif /* LARGE_SMB_OFF_T */
325
DEBUG (0, ("get_quota_command failed!\n"));
335
DEBUG(0,("The output of get_quota_command is invalid!\n"));
339
static int command_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
341
const char *set_quota_command;
343
set_quota_command = lp_set_quota_command();
344
if (set_quota_command && *set_quota_command) {
350
case SMB_USER_QUOTA_TYPE:
351
case SMB_USER_FS_QUOTA_TYPE:
354
case SMB_GROUP_QUOTA_TYPE:
355
case SMB_GROUP_FS_QUOTA_TYPE:
362
#ifdef LARGE_SMB_OFF_T
363
if (asprintf(&syscmd,
367
set_quota_command, path, qtype, _id, dp->qflags,
368
(long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit,
369
(long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit,
370
(long long unsigned)dp->bsize) < 0) {
373
#else /* LARGE_SMB_OFF_T */
374
if (asprintf(&syscmd,
378
set_quota_command, path, qtype, _id, dp->qflags,
379
(long unsigned)dp->softlimit,(long unsigned)dp->hardlimit,
380
(long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit,
381
(long unsigned)dp->bsize) < 0) {
384
#endif /* LARGE_SMB_OFF_T */
386
DEBUG (3, ("get_quota: Running command %s\n", syscmd));
388
lines = file_lines_pload(syscmd, NULL);
391
char *line = lines[0];
393
DEBUG (3, ("Read output from set_quota, \"%s\"\n", line));
399
DEBUG (0, ("set_quota_command failed!\n"));
407
int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
412
char *mntpath = NULL;
417
smb_panic("sys_get_quota: called with NULL pointer");
419
if (command_get_quota(path, qtype, id, dp)==0) {
421
} else if (errno != ENOSYS) {
425
if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) {
426
DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path));
431
DEBUG(10,("sys_get_quota() uid(%u, %u)\n", (unsigned)getuid(), (unsigned)geteuid()));
433
for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].get_quota);i++) {
434
if (strcmp(fs,sys_quota_backends[i].name)==0) {
435
ret = sys_quota_backends[i].get_quota(mntpath, bdev, qtype, id, dp);
437
DEBUG(3,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
438
fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
440
DEBUG(10,("sys_get_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
441
fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
449
/* use the default vfs quota functions */
450
ret=sys_get_vfs_quota(mntpath, bdev, qtype, id, dp);
452
DEBUG(3,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s\n",
453
"vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
455
DEBUG(10,("sys_get_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
456
"vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
464
if ((ret!=0)&& (errno == EDQUOT)) {
465
DEBUG(10,("sys_get_quota() warning over quota!\n"));
472
int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
477
char *mntpath = NULL;
481
/* find the block device file */
484
smb_panic("get_smb_quota: called with NULL pointer");
486
if (command_set_quota(path, qtype, id, dp)==0) {
488
} else if (errno != ENOSYS) {
492
if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) {
493
DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path));
498
DEBUG(10,("sys_set_quota() uid(%u, %u)\n", (unsigned)getuid(), (unsigned)geteuid()));
500
for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].set_quota);i++) {
501
if (strcmp(fs,sys_quota_backends[i].name)==0) {
502
ret = sys_quota_backends[i].set_quota(mntpath, bdev, qtype, id, dp);
504
DEBUG(3,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
505
fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
507
DEBUG(10,("sys_set_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
508
fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
516
/* use the default vfs quota functions */
517
ret=sys_set_vfs_quota(mntpath, bdev, qtype, id, dp);
519
DEBUG(3,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
520
"vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
522
DEBUG(10,("sys_set_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
523
"vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
531
if ((ret!=0)&& (errno == EDQUOT)) {
532
DEBUG(10,("sys_set_quota() warning over quota!\n"));
539
#else /* HAVE_SYS_QUOTAS */
540
void dummy_sysquotas_c(void);
542
void dummy_sysquotas_c(void)
546
#endif /* HAVE_SYS_QUOTAS */