source: vendor/current/source3/smbd/quotas.c

Last change on this file was 989, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.7

File size: 21.2 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 support for quotas
4 Copyright (C) Andrew Tridgell 1992-1998
5
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.
10
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.
15
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/>.
18*/
19
20
21/*
22 * This is one of the most system dependent parts of Samba, and its
23 * done a litle differently. Each system has its own way of doing
24 * things :-(
25 */
26
27#include "includes.h"
28#include "smbd/smbd.h"
29#include "system/filesys.h"
30
31#undef DBGC_CLASS
32#define DBGC_CLASS DBGC_QUOTA
33
34#ifndef HAVE_SYS_QUOTAS
35
36/* just a quick hack because sysquotas.h is included before linux/quota.h */
37#ifdef QUOTABLOCK_SIZE
38#undef QUOTABLOCK_SIZE
39#endif
40
41#ifdef WITH_QUOTAS
42
43#if defined(VXFS_QUOTA)
44
45/*
46 * In addition to their native filesystems, some systems have Veritas VxFS.
47 * Declare here, define at end: reduces likely "include" interaction problems.
48 * David Lee <T.D.Lee@durham.ac.uk>
49 */
50bool disk_quotas_vxfs(const char *name, char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize);
51
52#endif /* VXFS_QUOTA */
53
54
55#if defined(SUNOS5) || defined(SUNOS4)
56
57#include <fcntl.h>
58#include <sys/param.h>
59#if defined(SUNOS5)
60#include <sys/fs/ufs_quota.h>
61#include <sys/mnttab.h>
62#include <sys/mntent.h>
63#else /* defined(SUNOS4) */
64#include <ufs/quota.h>
65#include <mntent.h>
66#endif
67
68#if defined(SUNOS5)
69
70/****************************************************************************
71 Allows querying of remote hosts for quotas on NFS mounted shares.
72 Supports normal NFS and AMD mounts.
73 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
74****************************************************************************/
75
76#include <rpc/rpc.h>
77#include <rpc/types.h>
78#include <rpcsvc/rquota.h>
79#include <rpc/nettype.h>
80#include <rpc/xdr.h>
81
82static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
83{
84 int quotastat;
85
86 if (!xdr_int(xdrsp, &quotastat)) {
87 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
88 return 0;
89 }
90 gqr->status = quotastat;
91
92 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
93 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
94 return 0;
95 }
96 if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
97 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
98 return 0;
99 }
100 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
101 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
102 return 0;
103 }
104 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
105 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
106 return 0;
107 }
108 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
109 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
110 return 0;
111 }
112 return (1);
113}
114
115static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
116{
117 if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
118 return(0);
119 if (!xdr_int(xdrsp, &args->gqa_uid))
120 return(0);
121 return (1);
122}
123
124/* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
125static bool nfs_quotas(char *nfspath, uid_t euser_id, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
126{
127 uid_t uid = euser_id;
128 struct dqblk D;
129 char *mnttype = nfspath;
130 CLIENT *clnt;
131 struct getquota_rslt gqr;
132 struct getquota_args args;
133 char *cutstr, *pathname, *host, *testpath;
134 int len;
135 static struct timeval timeout = {2,0};
136 enum clnt_stat clnt_stat;
137 bool ret = True;
138
139 *bsize = *dfree = *dsize = (uint64_t)0;
140
141 len=strcspn(mnttype, ":");
142 pathname=strstr(mnttype, ":");
143 cutstr = (char *) SMB_MALLOC(len+1);
144 if (!cutstr)
145 return False;
146
147 memset(cutstr, '\0', len+1);
148 host = strncat(cutstr,mnttype, sizeof(char) * len );
149 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
150 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
151 testpath=strchr_m(mnttype, ':');
152 args.gqa_pathp = testpath+1;
153 args.gqa_uid = uid;
154
155 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
156
157 if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
158 ret = False;
159 goto out;
160 }
161
162 clnt->cl_auth = authunix_create_default();
163 DEBUG(9,("nfs_quotas: auth_success\n"));
164
165 clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, my_xdr_getquota_args, (caddr_t)&args, my_xdr_getquota_rslt, (caddr_t)&gqr, timeout);
166
167 if (clnt_stat != RPC_SUCCESS) {
168 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
169 ret = False;
170 goto out;
171 }
172
173 /*
174 * gqr.status returns 1 if quotas exist, 2 if there is
175 * no quota set, and 3 if no permission to get the quota.
176 * If 3, return something sensible.
177 */
178
179 switch (gqr.status) {
180 case 1:
181 DEBUG(9,("nfs_quotas: Good quota data\n"));
182 D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
183 D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
184 D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
185 break;
186
187 case 2:
188 case 3:
189 D.dqb_bsoftlimit = 1;
190 D.dqb_curblocks = 1;
191 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr.status));
192 break;
193
194 default:
195 DEBUG(9, ("nfs_quotas: Unknown Remote Quota Status \"%i\"\n",
196 gqr.status));
197 ret = false;
198 goto out;
199 }
200
201 DEBUG(10,("nfs_quotas: Let`s look at D a bit closer... status \"%i\" bsize \"%i\" active? \"%i\" bhard \"%i\" bsoft \"%i\" curb \"%i\" \n",
202 gqr.status,
203 gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
204 gqr.getquota_rslt_u.gqr_rquota.rq_active,
205 gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
206 gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
207 gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
208
209 *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
210 *dsize = D.dqb_bsoftlimit;
211
212 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
213 *dfree = 0;
214 *dsize = D.dqb_curblocks;
215 } else
216 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
217
218 out:
219
220 if (clnt) {
221 if (clnt->cl_auth)
222 auth_destroy(clnt->cl_auth);
223 clnt_destroy(clnt);
224 }
225
226 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
227
228 SAFE_FREE(cutstr);
229 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
230 return ret;
231}
232#endif
233
234/****************************************************************************
235try to get the disk space from disk quotas (SunOS & Solaris2 version)
236Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
237****************************************************************************/
238
239bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
240 uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
241{
242 uid_t euser_id;
243 int ret;
244 struct dqblk D;
245#if defined(SUNOS5)
246 struct quotctl command;
247 int file;
248 struct mnttab mnt;
249#else /* SunOS4 */
250 struct mntent *mnt;
251#endif
252 char *name = NULL;
253 FILE *fd;
254 SMB_STRUCT_STAT sbuf;
255 SMB_DEV_T devno;
256 bool found = false;
257 const char *path = fname->base_name;
258
259 euser_id = geteuid();
260
261 devno = fname->st.st_ex_dev;
262 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
263 path, (unsigned int)devno));
264#if defined(SUNOS5)
265 if ((fd = fopen(MNTTAB, "r")) == NULL) {
266 return false;
267 }
268
269 while (getmntent(fd, &mnt) == 0) {
270 if (sys_stat(mnt.mnt_mountp, &sbuf, false) == -1) {
271 continue;
272 }
273
274 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
275 mnt.mnt_mountp, (unsigned int)devno));
276
277 /* quotas are only on vxfs, UFS or NFS */
278 if ((sbuf.st_ex_dev == devno) && (
279 strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
280 strcmp( mnt.mnt_fstype, "nfs" ) == 0 ||
281 strcmp( mnt.mnt_fstype, "vxfs" ) == 0 )) {
282 found = true;
283 name = talloc_asprintf(talloc_tos(),
284 "%s/quotas",
285 mnt.mnt_mountp);
286 break;
287 }
288 }
289
290 fclose(fd);
291#else /* SunOS4 */
292 if ((fd = setmntent(MOUNTED, "r")) == NULL) {
293 return false;
294 }
295
296 while ((mnt = getmntent(fd)) != NULL) {
297 if (sys_stat(mnt->mnt_dir, &sbuf, false) == -1) {
298 continue;
299 }
300 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
301 mnt->mnt_dir,
302 (unsigned int)sbuf.st_ex_dev));
303 if (sbuf.st_ex_dev == devno) {
304 found = true;
305 name = talloc_strdup(talloc_tos(),
306 mnt->mnt_fsname);
307 break;
308 }
309 }
310
311 endmntent(fd);
312#endif
313 if (!found) {
314 return false;
315 }
316
317 if (!name) {
318 return false;
319 }
320 become_root();
321
322#if defined(SUNOS5)
323 if (strcmp(mnt.mnt_fstype, "nfs") == 0) {
324 bool retval;
325 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n",
326 mnt.mnt_special));
327 retval = nfs_quotas(mnt.mnt_special,
328 euser_id, bsize, dfree, dsize);
329 unbecome_root();
330 return retval;
331 }
332
333 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
334 if((file=open(name, O_RDONLY,0))<0) {
335 unbecome_root();
336 return false;
337 }
338 command.op = Q_GETQUOTA;
339 command.uid = euser_id;
340 command.addr = (caddr_t) &D;
341 ret = ioctl(file, Q_QUOTACTL, &command);
342 close(file);
343#else
344 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
345 ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
346#endif
347
348 unbecome_root();
349
350 if (ret < 0) {
351 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n",
352 strerror(errno) ));
353
354#if defined(SUNOS5) && defined(VXFS_QUOTA)
355 /* If normal quotactl() fails, try vxfs private calls */
356 set_effective_uid(euser_id);
357 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
358 if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
359 bool retval;
360 retval = disk_quotas_vxfs(name, path,
361 bsize, dfree, dsize);
362 return retval;
363 }
364#else
365 return false;
366#endif
367 }
368
369 /* If softlimit is zero, set it equal to hardlimit.
370 */
371
372 if (D.dqb_bsoftlimit==0) {
373 D.dqb_bsoftlimit = D.dqb_bhardlimit;
374 }
375
376 /* Use softlimit to determine disk space. A user exceeding the quota
377 * is told that there's no space left. Writes might actually work for
378 * a bit if the hardlimit is set higher than softlimit. Effectively
379 * the disk becomes made of rubber latex and begins to expand to
380 * accommodate the user :-)
381 */
382
383 if (D.dqb_bsoftlimit==0)
384 return(False);
385 *bsize = DEV_BSIZE;
386 *dsize = D.dqb_bsoftlimit;
387
388 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
389 *dfree = 0;
390 *dsize = D.dqb_curblocks;
391 } else {
392 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
393 }
394
395 DEBUG(5,("disk_quotas for path \"%s\" returning "
396 "bsize %.0f, dfree %.0f, dsize %.0f\n",
397 path,(double)*bsize,(double)*dfree,(double)*dsize));
398
399 return true;
400}
401
402
403#else
404
405#if AIX
406/* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
407#include <jfs/quota.h>
408/* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
409#define dqb_curfiles dqb_curinodes
410#define dqb_fhardlimit dqb_ihardlimit
411#define dqb_fsoftlimit dqb_isoftlimit
412#ifdef _AIXVERSION_530
413#include <sys/statfs.h>
414#include <sys/vmount.h>
415#endif /* AIX 5.3 */
416#else /* !AIX */
417#include <sys/quota.h>
418#include <devnm.h>
419#endif
420
421
422/****************************************************************************
423try to get the disk space from disk quotas - default version
424****************************************************************************/
425
426bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
427 uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
428{
429 int r;
430 struct dqblk D;
431 uid_t euser_id;
432 const char *path = fname->base_name;
433#if !defined(AIX)
434 char dev_disk[256];
435 SMB_STRUCT_STAT S = fname->st;
436
437 /* find the block device file */
438
439 if ((sys_stat(path, &S, false)<0)
440 || (devnm(S_IFBLK, S.st_ex_dev, dev_disk, 256, 0)<0))
441 return (False);
442
443#endif /* !defined(AIX) */
444
445 euser_id = geteuid();
446
447#if defined(AIX)
448 /* AIX has both USER and GROUP quotas:
449 Get the USER quota (ohnielse@fysik.dtu.dk) */
450#ifdef _AIXVERSION_530
451 {
452 struct statfs statbuf;
453 quota64_t user_quota;
454 if (statfs(path,&statbuf) != 0)
455 return False;
456 if(statbuf.f_vfstype == MNT_J2)
457 {
458 /* For some reason we need to be root for jfs2 */
459 become_root();
460 r = quotactl(path,QCMD(Q_J2GETQUOTA,USRQUOTA),euser_id,(char *) &user_quota);
461 unbecome_root();
462 /* Copy results to old struct to let the following code work as before */
463 D.dqb_curblocks = user_quota.bused;
464 D.dqb_bsoftlimit = user_quota.bsoft;
465 D.dqb_bhardlimit = user_quota.bhard;
466 D.dqb_curfiles = user_quota.iused;
467 D.dqb_fsoftlimit = user_quota.isoft;
468 D.dqb_fhardlimit = user_quota.ihard;
469 }
470 else if(statbuf.f_vfstype == MNT_JFS)
471 {
472#endif /* AIX 5.3 */
473 save_re_uid();
474 if (set_re_uid() != 0)
475 return False;
476 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
477 restore_re_uid();
478#ifdef _AIXVERSION_530
479 }
480 else
481 r = 1; /* Fail for other FS-types */
482 }
483#endif /* AIX 5.3 */
484#else /* !AIX */
485 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
486#endif /* !AIX */
487
488 /* Use softlimit to determine disk space, except when it has been exceeded */
489 *bsize = 1024;
490
491 if (r)
492 {
493 if (errno == EDQUOT)
494 {
495 *dfree =0;
496 *dsize =D.dqb_curblocks;
497 return (True);
498 }
499 else return(False);
500 }
501
502 /* If softlimit is zero, set it equal to hardlimit.
503 */
504
505 if (D.dqb_bsoftlimit==0)
506 D.dqb_bsoftlimit = D.dqb_bhardlimit;
507
508 if (D.dqb_bsoftlimit==0)
509 return(False);
510 /* Use softlimit to determine disk space, except when it has been exceeded */
511 if ((D.dqb_curblocks>D.dqb_bsoftlimit)
512||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
513 ) {
514 *dfree = 0;
515 *dsize = D.dqb_curblocks;
516 }
517 else {
518 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
519 *dsize = D.dqb_bsoftlimit;
520 }
521 return (True);
522}
523
524#endif
525
526#if defined(VXFS_QUOTA)
527
528/****************************************************************************
529Try to get the disk space from Veritas disk quotas.
530 David Lee <T.D.Lee@durham.ac.uk> August 1999.
531
532Background assumptions:
533 Potentially under many Operating Systems. Initially Solaris 2.
534
535 My guess is that Veritas is largely, though not entirely,
536 independent of OS. So I have separated it out.
537
538 There may be some details. For example, OS-specific "include" files.
539
540 It is understood that HPUX 10 somehow gets Veritas quotas without
541 any special effort; if so, this routine need not be compiled in.
542 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
543
544Warning:
545 It is understood that Veritas do not publicly support this ioctl interface.
546 Rather their preference would be for the user (us) to call the native
547 OS and then for the OS itself to call through to the VxFS filesystem.
548 Presumably HPUX 10, see above, does this.
549
550Hints for porting:
551 Add your OS to "IFLIST" below.
552 Get it to compile successfully:
553 Almost certainly "include"s require attention: see SUNOS5.
554 In the main code above, arrange for it to be called: see SUNOS5.
555 Test!
556
557****************************************************************************/
558
559/* "IFLIST"
560 * This "if" is a list of ports:
561 * if defined(OS1) || defined(OS2) || ...
562 */
563#if defined(SUNOS5)
564
565#if defined(SUNOS5)
566#include <sys/fs/vx_solaris.h>
567#endif
568#include <sys/fs/vx_machdep.h>
569#include <sys/fs/vx_layout.h>
570#include <sys/fs/vx_quota.h>
571#include <sys/fs/vx_aioctl.h>
572#include <sys/fs/vx_ioctl.h>
573
574bool disk_quotas_vxfs(const char *name, char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
575{
576 uid_t user_id, euser_id;
577 int ret;
578 struct vx_dqblk D;
579 struct vx_quotctl quotabuf;
580 struct vx_genioctl genbuf;
581 char *qfname;
582 int file;
583
584 /*
585 * "name" may or may not include a trailing "/quotas".
586 * Arranging consistency of calling here in "quotas.c" may not be easy and
587 * it might be easier to examine and adjust it here.
588 * Fortunately, VxFS seems not to mind at present.
589 */
590 qfname = talloc_strdup(talloc_tos(), name);
591 if (!qfname) {
592 return false;
593 }
594 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
595
596 euser_id = geteuid();
597 set_effective_uid(0);
598
599 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname));
600 if((file=open(qfname, O_RDONLY,0))<0) {
601 set_effective_uid(euser_id);
602 return(False);
603 }
604 genbuf.ioc_cmd = VX_QUOTACTL;
605 genbuf.ioc_up = (void *) &quotabuf;
606
607 quotabuf.cmd = VX_GETQUOTA;
608 quotabuf.uid = euser_id;
609 quotabuf.addr = (caddr_t) &D;
610 ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf);
611 close(file);
612
613 set_effective_uid(euser_id);
614
615 if (ret < 0) {
616 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) ));
617 return(False);
618 }
619
620 /* If softlimit is zero, set it equal to hardlimit.
621 */
622
623 if (D.dqb_bsoftlimit==0)
624 D.dqb_bsoftlimit = D.dqb_bhardlimit;
625
626 /* Use softlimit to determine disk space. A user exceeding the quota is told
627 * that there's no space left. Writes might actually work for a bit if the
628 * hardlimit is set higher than softlimit. Effectively the disk becomes
629 * made of rubber latex and begins to expand to accommodate the user :-)
630 */
631 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
632 path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit,
633 D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit));
634
635 if (D.dqb_bsoftlimit==0)
636 return(False);
637 *bsize = DEV_BSIZE;
638 *dsize = D.dqb_bsoftlimit;
639
640 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
641 *dfree = 0;
642 *dsize = D.dqb_curblocks;
643 } else
644 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
645
646 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
647 path,(double)*bsize,(double)*dfree,(double)*dsize));
648
649 return(True);
650}
651
652#endif /* SUNOS5 || ... */
653
654#endif /* VXFS_QUOTA */
655
656#else /* WITH_QUOTAS */
657
658bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
659 uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
660{
661 (*bsize) = 512; /* This value should be ignored */
662
663 /* And just to be sure we set some values that hopefully */
664 /* will be larger that any possible real-world value */
665 (*dfree) = (uint64_t)-1;
666 (*dsize) = (uint64_t)-1;
667
668 /* As we have select not to use quotas, allways fail */
669 return false;
670}
671#endif /* WITH_QUOTAS */
672
673#else /* HAVE_SYS_QUOTAS */
674/* wrapper to the new sys_quota interface
675 this file should be removed later
676 */
677bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
678 uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
679{
680 int r;
681 SMB_DISK_QUOTA D;
682 unid_t id;
683
684 /*
685 * First of all, check whether user quota is
686 * enforced. If the call fails, assume it is
687 * not enforced.
688 */
689 ZERO_STRUCT(D);
690 id.uid = -1;
691 r = SMB_VFS_GET_QUOTA(conn, fname->base_name, SMB_USER_FS_QUOTA_TYPE,
692 id, &D);
693 if (r == -1 && errno != ENOSYS) {
694 goto try_group_quota;
695 }
696 if (r == 0 && (D.qflags & QUOTAS_DENY_DISK) == 0) {
697 goto try_group_quota;
698 }
699
700 ZERO_STRUCT(D);
701 id.uid = geteuid();
702
703 /* if new files created under this folder get this
704 * folder's UID, then available space is governed by
705 * the quota of the folder's UID, not the creating user.
706 */
707 if (lp_inherit_owner(SNUM(conn)) &&
708 id.uid != fname->st.st_ex_uid && id.uid != sec_initial_uid()) {
709 int save_errno;
710
711 id.uid = fname->st.st_ex_uid;
712 become_root();
713 r = SMB_VFS_GET_QUOTA(conn, fname->base_name,
714 SMB_USER_QUOTA_TYPE, id, &D);
715 save_errno = errno;
716 unbecome_root();
717 errno = save_errno;
718 } else {
719 r = SMB_VFS_GET_QUOTA(conn, fname->base_name,
720 SMB_USER_QUOTA_TYPE, id, &D);
721 }
722
723 /* Use softlimit to determine disk space, except when it has been exceeded */
724 *bsize = D.bsize;
725 if (r == -1) {
726 if (errno == EDQUOT) {
727 *dfree =0;
728 *dsize =D.curblocks;
729 return (True);
730 } else {
731 goto try_group_quota;
732 }
733 }
734
735 /* Use softlimit to determine disk space, except when it has been exceeded */
736 if (
737 (D.softlimit && D.curblocks >= D.softlimit) ||
738 (D.hardlimit && D.curblocks >= D.hardlimit) ||
739 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
740 (D.ihardlimit && D.curinodes>=D.ihardlimit)
741 ) {
742 *dfree = 0;
743 *dsize = D.curblocks;
744 } else if (D.softlimit==0 && D.hardlimit==0) {
745 goto try_group_quota;
746 } else {
747 if (D.softlimit == 0) {
748 D.softlimit = D.hardlimit;
749 }
750 *dfree = D.softlimit - D.curblocks;
751 *dsize = D.softlimit;
752 }
753
754 return True;
755
756try_group_quota:
757 /*
758 * First of all, check whether group quota is
759 * enforced. If the call fails, assume it is
760 * not enforced.
761 */
762 ZERO_STRUCT(D);
763 id.gid = -1;
764 r = SMB_VFS_GET_QUOTA(conn, fname->base_name, SMB_GROUP_FS_QUOTA_TYPE,
765 id, &D);
766 if (r == -1 && errno != ENOSYS) {
767 return false;
768 }
769 if (r == 0 && (D.qflags & QUOTAS_DENY_DISK) == 0) {
770 return false;
771 }
772
773 id.gid = getegid();
774
775 ZERO_STRUCT(D);
776 r = SMB_VFS_GET_QUOTA(conn, fname->base_name, SMB_GROUP_QUOTA_TYPE, id,
777 &D);
778
779 /* Use softlimit to determine disk space, except when it has been exceeded */
780 *bsize = D.bsize;
781 if (r == -1) {
782 if (errno == EDQUOT) {
783 *dfree =0;
784 *dsize =D.curblocks;
785 return (True);
786 } else {
787 return False;
788 }
789 }
790
791 /* Use softlimit to determine disk space, except when it has been exceeded */
792 if (
793 (D.softlimit && D.curblocks >= D.softlimit) ||
794 (D.hardlimit && D.curblocks >= D.hardlimit) ||
795 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
796 (D.ihardlimit && D.curinodes>=D.ihardlimit)
797 ) {
798 *dfree = 0;
799 *dsize = D.curblocks;
800 } else if (D.softlimit==0 && D.hardlimit==0) {
801 return False;
802 } else {
803 if (D.softlimit == 0) {
804 D.softlimit = D.hardlimit;
805 }
806 *dfree = D.softlimit - D.curblocks;
807 *dsize = D.softlimit;
808 }
809
810 return (True);
811}
812#endif /* HAVE_SYS_QUOTAS */
Note: See TracBrowser for help on using the repository browser.