~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/smbd/quotas.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 2 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, write to the Free Software
18
 
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 
*/
20
 
 
21
 
 
22
 
/* 
23
 
 * This is one of the most system dependent parts of Samba, and its
24
 
 * done a litle differently. Each system has its own way of doing 
25
 
 * things :-(
26
 
 */
27
 
 
28
 
#include "includes.h"
29
 
 
30
 
#undef DBGC_CLASS
31
 
#define DBGC_CLASS DBGC_QUOTA
32
 
 
33
 
#ifndef HAVE_SYS_QUOTAS
34
 
 
35
 
/* just a quick hack because sysquotas.h is included before linux/quota.h */
36
 
#ifdef QUOTABLOCK_SIZE
37
 
#undef QUOTABLOCK_SIZE
38
 
#endif
39
 
 
40
 
#ifdef WITH_QUOTAS
41
 
 
42
 
#if defined(VXFS_QUOTA)
43
 
 
44
 
/*
45
 
 * In addition to their native filesystems, some systems have Veritas VxFS.
46
 
 * Declare here, define at end: reduces likely "include" interaction problems.
47
 
 *      David Lee <T.D.Lee@durham.ac.uk>
48
 
 */
49
 
BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
50
 
 
51
 
#endif /* VXFS_QUOTA */
52
 
 
53
 
#ifdef LINUX
54
 
 
55
 
#include <sys/types.h>
56
 
#include <mntent.h>
57
 
 
58
 
/*
59
 
 * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
60
 
 * So we include all the files has *should* be in the system into a large,
61
 
 * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA.
62
 
 */
63
 
 
64
 
#include "samba_linux_quota.h"
65
 
#include "samba_xfs_quota.h"
66
 
 
67
 
typedef struct _LINUX_SMB_DISK_QUOTA {
68
 
        SMB_BIG_UINT bsize;
69
 
        SMB_BIG_UINT hardlimit; /* In bsize units. */
70
 
        SMB_BIG_UINT softlimit; /* In bsize units. */
71
 
        SMB_BIG_UINT curblocks; /* In bsize units. */
72
 
        SMB_BIG_UINT ihardlimit; /* inode hard limit. */
73
 
        SMB_BIG_UINT isoftlimit; /* inode soft limit. */
74
 
        SMB_BIG_UINT curinodes; /* Current used inodes. */
75
 
} LINUX_SMB_DISK_QUOTA;
76
 
 
77
 
/****************************************************************************
78
 
 Abstract out the XFS Quota Manager quota get call.
79
 
****************************************************************************/
80
 
 
81
 
static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
82
 
{
83
 
        struct fs_disk_quota D;
84
 
        int ret;
85
 
 
86
 
        ZERO_STRUCT(D);
87
 
 
88
 
        ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
89
 
 
90
 
        if (ret)
91
 
                ret = quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
92
 
 
93
 
        if (ret)
94
 
                return ret;
95
 
 
96
 
        dp->bsize = (SMB_BIG_UINT)512;
97
 
        dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
98
 
        dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
99
 
        dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
100
 
        dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
101
 
        dp->curinodes = (SMB_BIG_UINT)D.d_icount;
102
 
        dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
103
 
 
104
 
        return ret;
105
 
}
106
 
 
107
 
/****************************************************************************
108
 
 Abstract out the old and new Linux quota get calls.
109
 
****************************************************************************/
110
 
 
111
 
static int get_smb_linux_v1_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
112
 
{
113
 
        struct v1_kern_dqblk D;
114
 
        int ret;
115
 
 
116
 
        ZERO_STRUCT(D);
117
 
 
118
 
        ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
119
 
 
120
 
        if (ret && errno != EDQUOT)
121
 
                ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
122
 
 
123
 
        if (ret && errno != EDQUOT)
124
 
                return ret;
125
 
 
126
 
        dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
127
 
        dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
128
 
        dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
129
 
        dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
130
 
        dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
131
 
        dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
132
 
        dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
133
 
 
134
 
        return ret;
135
 
}
136
 
 
137
 
static int get_smb_linux_v2_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
138
 
{
139
 
        struct v2_kern_dqblk D;
140
 
        int ret;
141
 
 
142
 
        ZERO_STRUCT(D);
143
 
 
144
 
        ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
145
 
 
146
 
        if (ret && errno != EDQUOT)
147
 
                ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
148
 
 
149
 
        if (ret && errno != EDQUOT)
150
 
                return ret;
151
 
 
152
 
        dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
153
 
        dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
154
 
        dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
155
 
        dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
156
 
        dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
157
 
        dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
158
 
        dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;
159
 
 
160
 
        return ret;
161
 
}
162
 
 
163
 
/****************************************************************************
164
 
 Brand-new generic quota interface.
165
 
****************************************************************************/
166
 
 
167
 
static int get_smb_linux_gen_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
168
 
{
169
 
        struct if_dqblk D;
170
 
        int ret;
171
 
 
172
 
        ZERO_STRUCT(D);
173
 
 
174
 
        ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
175
 
 
176
 
        if (ret && errno != EDQUOT)
177
 
                ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
178
 
 
179
 
        if (ret && errno != EDQUOT)
180
 
                return ret;
181
 
 
182
 
        dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
183
 
        dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
184
 
        dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
185
 
        dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
186
 
        dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
187
 
        dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
188
 
        dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;
189
 
 
190
 
        return ret;
191
 
}
192
 
 
193
 
/****************************************************************************
194
 
 Try to get the disk space from disk quotas (LINUX version).
195
 
****************************************************************************/
196
 
 
197
 
BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
198
 
{
199
 
        int r;
200
 
        SMB_STRUCT_STAT S;
201
 
        FILE *fp;
202
 
        LINUX_SMB_DISK_QUOTA D;
203
 
        struct mntent *mnt;
204
 
        SMB_DEV_T devno;
205
 
        int found;
206
 
        uid_t euser_id;
207
 
        gid_t egrp_id;
208
 
 
209
 
        ZERO_STRUCT(D);
210
 
 
211
 
        euser_id = geteuid();
212
 
        egrp_id = getegid();
213
 
 
214
 
        /* find the block device file */
215
 
  
216
 
        if ( sys_stat(path, &S) == -1 )
217
 
                return(False) ;
218
 
 
219
 
        devno = S.st_dev ;
220
 
  
221
 
        if ((fp = setmntent(MOUNTED,"r")) == NULL)
222
 
                return(False) ;
223
 
 
224
 
        found = False ;
225
 
  
226
 
        while ((mnt = getmntent(fp))) {
227
 
                if ( sys_stat(mnt->mnt_dir,&S) == -1 )
228
 
                        continue ;
229
 
 
230
 
                if (S.st_dev == devno) {
231
 
                        found = True ;
232
 
                        break;
233
 
                }
234
 
        }
235
 
 
236
 
        endmntent(fp) ;
237
 
  
238
 
        if (!found)
239
 
                return(False);
240
 
 
241
 
        save_re_uid();
242
 
        set_effective_uid(0);  
243
 
 
244
 
        if (strcmp(mnt->mnt_type, "xfs")==0) {
245
 
                r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
246
 
        } else {
247
 
                r=get_smb_linux_gen_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
248
 
                if (r == -1 && errno != EDQUOT) {
249
 
                        r=get_smb_linux_v2_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
250
 
                        if (r == -1 && errno != EDQUOT)
251
 
                                r=get_smb_linux_v1_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
252
 
                }
253
 
        }
254
 
 
255
 
        restore_re_uid();
256
 
 
257
 
        /* Use softlimit to determine disk space, except when it has been exceeded */
258
 
        *bsize = D.bsize;
259
 
        if (r == -1) {
260
 
                if (errno == EDQUOT) {
261
 
                        *dfree =0;
262
 
                        *dsize =D.curblocks;
263
 
                        return (True);
264
 
                } else {
265
 
                        return(False);
266
 
                }
267
 
        }
268
 
 
269
 
        /* Use softlimit to determine disk space, except when it has been exceeded */
270
 
        if (
271
 
                (D.softlimit && D.curblocks >= D.softlimit) ||
272
 
                (D.hardlimit && D.curblocks >= D.hardlimit) ||
273
 
                (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
274
 
                (D.ihardlimit && D.curinodes>=D.ihardlimit)
275
 
        ) {
276
 
                *dfree = 0;
277
 
                *dsize = D.curblocks;
278
 
        } else if (D.softlimit==0 && D.hardlimit==0) {
279
 
                return(False);
280
 
        } else {
281
 
                if (D.softlimit == 0)
282
 
                        D.softlimit = D.hardlimit;
283
 
                *dfree = D.softlimit - D.curblocks;
284
 
                *dsize = D.softlimit;
285
 
        }
286
 
 
287
 
        return (True);
288
 
}
289
 
 
290
 
#elif defined(CRAY)
291
 
 
292
 
#include <sys/quota.h>
293
 
#include <mntent.h>
294
 
 
295
 
/****************************************************************************
296
 
try to get the disk space from disk quotas (CRAY VERSION)
297
 
****************************************************************************/
298
 
 
299
 
BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
300
 
{
301
 
  struct mntent *mnt;
302
 
  FILE *fd;
303
 
  SMB_STRUCT_STAT sbuf;
304
 
  SMB_DEV_T devno ;
305
 
  static SMB_DEV_T devno_cached = 0 ;
306
 
  static pstring name;
307
 
  struct q_request request ;
308
 
  struct qf_header header ;
309
 
  static int quota_default = 0 ;
310
 
  int found ;
311
 
  
312
 
  if ( sys_stat(path,&sbuf) == -1 )
313
 
    return(False) ;
314
 
  
315
 
  devno = sbuf.st_dev ;
316
 
  
317
 
  if ( devno != devno_cached ) {
318
 
    
319
 
    devno_cached = devno ;
320
 
    
321
 
    if ((fd = setmntent(KMTAB)) == NULL)
322
 
      return(False) ;
323
 
    
324
 
    found = False ;
325
 
    
326
 
    while ((mnt = getmntent(fd)) != NULL) {
327
 
      
328
 
      if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
329
 
        continue ;
330
 
      
331
 
      if (sbuf.st_dev == devno) {
332
 
        
333
 
        found = True ;
334
 
        break ;
335
 
        
336
 
      }
337
 
      
338
 
    }
339
 
    
340
 
    pstrcpy(name,mnt->mnt_dir) ;
341
 
    endmntent(fd) ;
342
 
    
343
 
    if ( ! found )
344
 
      return(False) ;
345
 
  }
346
 
  
347
 
  request.qf_magic = QF_MAGIC ;
348
 
  request.qf_entry.id = geteuid() ;
349
 
  
350
 
  if (quotactl(name, Q_GETQUOTA, &request) == -1)
351
 
    return(False) ;
352
 
  
353
 
  if ( ! request.user )
354
 
    return(False) ;
355
 
  
356
 
  if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {
357
 
    
358
 
    if ( ! quota_default ) {
359
 
      
360
 
      if ( quotactl(name, Q_GETHEADER, &header) == -1 )
361
 
        return(False) ;
362
 
      else
363
 
        quota_default = header.user_h.def_fq ;
364
 
    }
365
 
    
366
 
    *dfree = quota_default ;
367
 
    
368
 
  }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {
369
 
    
370
 
    *dfree = 0 ;
371
 
    
372
 
  }else{
373
 
    
374
 
    *dfree = request.qf_entry.user_q.f_quota ;
375
 
    
376
 
  }
377
 
  
378
 
  *dsize = request.qf_entry.user_q.f_use ;
379
 
  
380
 
  if ( *dfree < *dsize )
381
 
    *dfree = 0 ;
382
 
  else
383
 
    *dfree -= *dsize ;
384
 
  
385
 
  *bsize = 4096 ;  /* Cray blocksize */
386
 
  
387
 
  return(True) ;
388
 
  
389
 
}
390
 
 
391
 
 
392
 
#elif defined(SUNOS5) || defined(SUNOS4)
393
 
 
394
 
#include <fcntl.h>
395
 
#include <sys/param.h>
396
 
#if defined(SUNOS5)
397
 
#include <sys/fs/ufs_quota.h>
398
 
#include <sys/mnttab.h>
399
 
#include <sys/mntent.h>
400
 
#else /* defined(SUNOS4) */
401
 
#include <ufs/quota.h>
402
 
#include <mntent.h>
403
 
#endif
404
 
 
405
 
#if defined(SUNOS5)
406
 
 
407
 
/****************************************************************************
408
 
 Allows querying of remote hosts for quotas on NFS mounted shares.
409
 
 Supports normal NFS and AMD mounts.
410
 
 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
411
 
****************************************************************************/
412
 
 
413
 
#include <rpc/rpc.h>
414
 
#include <rpc/types.h>
415
 
#include <rpcsvc/rquota.h>
416
 
#include <rpc/nettype.h>
417
 
#include <rpc/xdr.h>
418
 
 
419
 
static int quotastat;
420
 
 
421
 
static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
422
 
{
423
 
        if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
424
 
                return(0);
425
 
        if (!xdr_int(xdrsp, &args->gqa_uid))
426
 
                return(0);
427
 
        return (1);
428
 
}
429
 
 
430
 
static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
431
 
{
432
 
        if (!xdr_int(xdrsp, &quotastat)) {
433
 
                DEBUG(6,("nfs_quotas: Status bad or zero\n"));
434
 
                return 0;
435
 
        }
436
 
        if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
437
 
                DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
438
 
                return 0;
439
 
        }
440
 
        if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
441
 
                DEBUG(6,("nfs_quotas: Active bad or zero\n"));
442
 
                return 0;
443
 
        }
444
 
        if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
445
 
                DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
446
 
                return 0;
447
 
        }
448
 
        if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
449
 
                DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
450
 
                return 0;
451
 
        }
452
 
        if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
453
 
                DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
454
 
                return 0;
455
 
        }
456
 
        return (1);
457
 
}
458
 
 
459
 
/* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */ 
460
 
static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
461
 
{
462
 
        uid_t uid = euser_id;
463
 
        struct dqblk D;
464
 
        char *mnttype = nfspath;
465
 
        CLIENT *clnt;
466
 
        struct getquota_rslt gqr;
467
 
        struct getquota_args args;
468
 
        char *cutstr, *pathname, *host, *testpath;
469
 
        int len;
470
 
        static struct timeval timeout = {2,0};
471
 
        enum clnt_stat clnt_stat;
472
 
        BOOL ret = True;
473
 
 
474
 
        *bsize = *dfree = *dsize = (SMB_BIG_UINT)0;
475
 
 
476
 
        len=strcspn(mnttype, ":");
477
 
        pathname=strstr(mnttype, ":");
478
 
        cutstr = (char *) SMB_MALLOC(len+1);
479
 
        if (!cutstr)
480
 
                return False;
481
 
 
482
 
        memset(cutstr, '\0', len+1);
483
 
        host = strncat(cutstr,mnttype, sizeof(char) * len );
484
 
        DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
485
 
        DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
486
 
        testpath=strchr_m(mnttype, ':');
487
 
        args.gqa_pathp = testpath+1;
488
 
        args.gqa_uid = uid;
489
 
 
490
 
        DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
491
 
 
492
 
        if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
493
 
                ret = False;
494
 
                goto out;
495
 
        }
496
 
 
497
 
        clnt->cl_auth = authunix_create_default();
498
 
        DEBUG(9,("nfs_quotas: auth_success\n"));
499
 
 
500
 
        clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, my_xdr_getquota_args, (caddr_t)&args, my_xdr_getquota_rslt, (caddr_t)&gqr, timeout);
501
 
 
502
 
        if (clnt_stat != RPC_SUCCESS) {
503
 
                DEBUG(9,("nfs_quotas: clnt_call fail\n"));
504
 
                ret = False;
505
 
                goto out;
506
 
        }
507
 
 
508
 
        /* 
509
 
         * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
510
 
         * no quota set, and 3 if no permission to get the quota.  If 0 or 3 return
511
 
         * something sensible.
512
 
         */   
513
 
 
514
 
        switch ( quotastat ) {
515
 
        case 0:
516
 
                DEBUG(9,("nfs_quotas: Remote Quotas Failed!  Error \"%i\" \n", quotastat ));
517
 
                ret = False;
518
 
                goto out;
519
 
 
520
 
        case 1:
521
 
                DEBUG(9,("nfs_quotas: Good quota data\n"));
522
 
                D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
523
 
                D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
524
 
                D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
525
 
                break;
526
 
 
527
 
        case 2:
528
 
        case 3:
529
 
                D.dqb_bsoftlimit = 1;
530
 
                D.dqb_curblocks = 1;
531
 
                DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat ));
532
 
                break;
533
 
 
534
 
        default:
535
 
                DEBUG(9,("nfs_quotas: Remote Quotas Questionable!  Error \"%i\" \n", quotastat ));
536
 
                break;
537
 
        }
538
 
 
539
 
        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",
540
 
                        quotastat,
541
 
                        gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
542
 
                        gqr.getquota_rslt_u.gqr_rquota.rq_active,
543
 
                        gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
544
 
                        gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
545
 
                        gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
546
 
 
547
 
        *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
548
 
        *dsize = D.dqb_bsoftlimit;
549
 
 
550
 
        if (D.dqb_curblocks == D.dqb_curblocks == 1)
551
 
                *bsize = 512;
552
 
 
553
 
        if (D.dqb_curblocks > D.dqb_bsoftlimit) {
554
 
                *dfree = 0;
555
 
                *dsize = D.dqb_curblocks;
556
 
        } else
557
 
                *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
558
 
 
559
 
  out:
560
 
 
561
 
        if (clnt) {
562
 
                if (clnt->cl_auth)
563
 
                        auth_destroy(clnt->cl_auth);
564
 
                clnt_destroy(clnt);
565
 
        }
566
 
 
567
 
        DEBUG(5,("nfs_quotas: For path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
568
 
 
569
 
        SAFE_FREE(cutstr);
570
 
        DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
571
 
        return ret;
572
 
}
573
 
#endif
574
 
 
575
 
/****************************************************************************
576
 
try to get the disk space from disk quotas (SunOS & Solaris2 version)
577
 
Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
578
 
****************************************************************************/
579
 
 
580
 
BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
581
 
{
582
 
        uid_t euser_id;
583
 
        int ret;
584
 
        struct dqblk D;
585
 
#if defined(SUNOS5)
586
 
        struct quotctl command;
587
 
        int file;
588
 
        static struct mnttab mnt;
589
 
        static pstring name;
590
 
        pstring devopt;
591
 
#else /* SunOS4 */
592
 
        struct mntent *mnt;
593
 
        static pstring name;
594
 
#endif
595
 
        FILE *fd;
596
 
        SMB_STRUCT_STAT sbuf;
597
 
        SMB_DEV_T devno ;
598
 
        static SMB_DEV_T devno_cached = 0 ;
599
 
        static int found ;
600
 
 
601
 
        euser_id = geteuid();
602
 
  
603
 
        if ( sys_stat(path,&sbuf) == -1 )
604
 
                return(False) ;
605
 
  
606
 
        devno = sbuf.st_dev ;
607
 
        DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,(unsigned int)devno));
608
 
        if ( devno != devno_cached ) {
609
 
                devno_cached = devno ;
610
 
#if defined(SUNOS5)
611
 
                if ((fd = sys_fopen(MNTTAB, "r")) == NULL)
612
 
                        return(False) ;
613
 
    
614
 
                found = False ;
615
 
                slprintf(devopt, sizeof(devopt) - 1, "dev=%x", (unsigned int)devno);
616
 
                while (getmntent(fd, &mnt) == 0) {
617
 
                        if( !hasmntopt(&mnt, devopt) )
618
 
                                continue;
619
 
 
620
 
                        DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt));
621
 
 
622
 
                        /* quotas are only on vxfs, UFS or NFS */
623
 
                        if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
624
 
                                strcmp( mnt.mnt_fstype, "nfs" ) == 0    ||
625
 
                                strcmp( mnt.mnt_fstype, "vxfs" ) == 0  ) { 
626
 
                                        found = True ;
627
 
                                        break;
628
 
                        }
629
 
                }
630
 
    
631
 
                pstrcpy(name,mnt.mnt_mountp) ;
632
 
                pstrcat(name,"/quotas") ;
633
 
                fclose(fd) ;
634
 
#else /* SunOS4 */
635
 
                if ((fd = setmntent(MOUNTED, "r")) == NULL)
636
 
                        return(False) ;
637
 
    
638
 
                found = False ;
639
 
                while ((mnt = getmntent(fd)) != NULL) {
640
 
                        if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
641
 
                                continue ;
642
 
                        DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt->mnt_dir,(unsigned int)sbuf.st_dev));
643
 
                        if (sbuf.st_dev == devno) {
644
 
                                found = True ;
645
 
                                break;
646
 
                        }
647
 
                }
648
 
    
649
 
                pstrcpy(name,mnt->mnt_fsname) ;
650
 
                endmntent(fd) ;
651
 
#endif
652
 
        }
653
 
 
654
 
        if ( ! found )
655
 
                return(False) ;
656
 
 
657
 
        save_re_uid();
658
 
        set_effective_uid(0);
659
 
 
660
 
#if defined(SUNOS5)
661
 
        if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) {
662
 
                BOOL retval;
663
 
                DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special));
664
 
                retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize);
665
 
                restore_re_uid();
666
 
                return retval;
667
 
        }
668
 
 
669
 
        DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
670
 
        if((file=sys_open(name, O_RDONLY,0))<0) {
671
 
                restore_re_uid();
672
 
                return(False);
673
 
        }
674
 
        command.op = Q_GETQUOTA;
675
 
        command.uid = euser_id;
676
 
        command.addr = (caddr_t) &D;
677
 
        ret = ioctl(file, Q_QUOTACTL, &command);
678
 
        close(file);
679
 
#else
680
 
        DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
681
 
        ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
682
 
#endif
683
 
 
684
 
        restore_re_uid();
685
 
 
686
 
        if (ret < 0) {
687
 
                DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) ));
688
 
 
689
 
#if defined(SUNOS5) && defined(VXFS_QUOTA)
690
 
                /* If normal quotactl() fails, try vxfs private calls */
691
 
                set_effective_uid(euser_id);
692
 
                DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
693
 
                if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
694
 
                        BOOL retval;
695
 
                        retval = disk_quotas_vxfs(name, path, bsize, dfree, dsize);
696
 
                        return(retval);
697
 
                }
698
 
#else
699
 
                return(False);
700
 
#endif
701
 
        }
702
 
 
703
 
        /* If softlimit is zero, set it equal to hardlimit.
704
 
         */
705
 
  
706
 
        if (D.dqb_bsoftlimit==0)
707
 
                D.dqb_bsoftlimit = D.dqb_bhardlimit;
708
 
 
709
 
        /* Use softlimit to determine disk space. A user exceeding the quota is told
710
 
         * that there's no space left. Writes might actually work for a bit if the
711
 
         * hardlimit is set higher than softlimit. Effectively the disk becomes
712
 
         * made of rubber latex and begins to expand to accommodate the user :-)
713
 
         */
714
 
 
715
 
        if (D.dqb_bsoftlimit==0)
716
 
                return(False);
717
 
        *bsize = DEV_BSIZE;
718
 
        *dsize = D.dqb_bsoftlimit;
719
 
 
720
 
        if (D.dqb_curblocks > D.dqb_bsoftlimit) {
721
 
                *dfree = 0;
722
 
                *dsize = D.dqb_curblocks;
723
 
        } else
724
 
                *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
725
 
      
726
 
        DEBUG(5,("disk_quotas for path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",
727
 
                path,(double)*bsize,(double)*dfree,(double)*dsize));
728
 
 
729
 
        return(True);
730
 
}
731
 
 
732
 
 
733
 
#elif defined(OSF1)
734
 
#include <ufs/quota.h>
735
 
 
736
 
/****************************************************************************
737
 
try to get the disk space from disk quotas - OSF1 version
738
 
****************************************************************************/
739
 
 
740
 
BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
741
 
{
742
 
  int r, save_errno;
743
 
  struct dqblk D;
744
 
  SMB_STRUCT_STAT S;
745
 
  uid_t euser_id;
746
 
 
747
 
  /*
748
 
   * This code presumes that OSF1 will only
749
 
   * give out quota info when the real uid 
750
 
   * matches the effective uid. JRA.
751
 
   */
752
 
  euser_id = geteuid();
753
 
  save_re_uid();
754
 
  if (set_re_uid() != 0) return False;
755
 
 
756
 
  r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D);
757
 
  if (r) {
758
 
     save_errno = errno;
759
 
  }
760
 
 
761
 
  restore_re_uid();
762
 
 
763
 
  *bsize = DEV_BSIZE;
764
 
 
765
 
  if (r)
766
 
  {
767
 
      if (save_errno == EDQUOT)   /* disk quota exceeded */
768
 
      {
769
 
         *dfree = 0;
770
 
         *dsize = D.dqb_curblocks;
771
 
         return (True);
772
 
      }
773
 
      else
774
 
         return (False);  
775
 
  }
776
 
 
777
 
  /* If softlimit is zero, set it equal to hardlimit.
778
 
   */
779
 
 
780
 
  if (D.dqb_bsoftlimit==0)
781
 
    D.dqb_bsoftlimit = D.dqb_bhardlimit;
782
 
 
783
 
  /* Use softlimit to determine disk space, except when it has been exceeded */
784
 
 
785
 
  if (D.dqb_bsoftlimit==0)
786
 
    return(False);
787
 
 
788
 
  if ((D.dqb_curblocks>D.dqb_bsoftlimit)) {
789
 
    *dfree = 0;
790
 
    *dsize = D.dqb_curblocks;
791
 
  } else {
792
 
    *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
793
 
    *dsize = D.dqb_bsoftlimit;
794
 
  }
795
 
  return (True);
796
 
}
797
 
 
798
 
#elif defined (IRIX6)
799
 
/****************************************************************************
800
 
try to get the disk space from disk quotas (IRIX 6.2 version)
801
 
****************************************************************************/
802
 
 
803
 
#include <sys/quota.h>
804
 
#include <mntent.h>
805
 
 
806
 
BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
807
 
{
808
 
  uid_t euser_id;
809
 
  int r;
810
 
  struct dqblk D;
811
 
  struct fs_disk_quota        F;
812
 
  SMB_STRUCT_STAT S;
813
 
  FILE *fp;
814
 
  struct mntent *mnt;
815
 
  SMB_DEV_T devno;
816
 
  int found;
817
 
  
818
 
  /* find the block device file */
819
 
  
820
 
  if ( sys_stat(path, &S) == -1 ) {
821
 
    return(False) ;
822
 
  }
823
 
 
824
 
  devno = S.st_dev ;
825
 
  
826
 
  fp = setmntent(MOUNTED,"r");
827
 
  found = False ;
828
 
  
829
 
  while ((mnt = getmntent(fp))) {
830
 
    if ( sys_stat(mnt->mnt_dir,&S) == -1 )
831
 
      continue ;
832
 
    if (S.st_dev == devno) {
833
 
      found = True ;
834
 
      break ;
835
 
    }
836
 
  }
837
 
  endmntent(fp) ;
838
 
  
839
 
  if (!found) {
840
 
    return(False);
841
 
  }
842
 
 
843
 
  euser_id=geteuid();
844
 
  save_re_uid();
845
 
  set_effective_uid(0);  
846
 
 
847
 
  /* Use softlimit to determine disk space, except when it has been exceeded */
848
 
 
849
 
  *bsize = 512;
850
 
 
851
 
  if ( 0 == strcmp ( mnt->mnt_type, "efs" ))
852
 
  {
853
 
    r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);
854
 
 
855
 
    restore_re_uid();
856
 
 
857
 
    if (r==-1)
858
 
      return(False);
859
 
        
860
 
    /* Use softlimit to determine disk space, except when it has been exceeded */
861
 
    if (
862
 
        (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||
863
 
        (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||
864
 
        (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) ||
865
 
        (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit)
866
 
       )
867
 
    {
868
 
      *dfree = 0;
869
 
      *dsize = D.dqb_curblocks;
870
 
    }
871
 
    else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
872
 
    {
873
 
      return(False);
874
 
    }
875
 
    else 
876
 
    {
877
 
      *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
878
 
      *dsize = D.dqb_bsoftlimit;
879
 
    }
880
 
 
881
 
  }
882
 
  else if ( 0 == strcmp ( mnt->mnt_type, "xfs" ))
883
 
  {
884
 
    r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);
885
 
 
886
 
    restore_re_uid();
887
 
 
888
 
    if (r==-1)
889
 
    {
890
 
      DEBUG(5, ("quotactl for uid=%u: %s", euser_id, strerror(errno)));
891
 
      return(False);
892
 
    }
893
 
        
894
 
    /* No quota for this user. */
895
 
    if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0)
896
 
    {
897
 
      return(False);
898
 
    }
899
 
 
900
 
    /* Use softlimit to determine disk space, except when it has been exceeded */
901
 
    if (
902
 
        (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) ||
903
 
        (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) ||
904
 
        (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) ||
905
 
        (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit)
906
 
       )
907
 
    {
908
 
      *dfree = 0;
909
 
      *dsize = F.d_bcount;
910
 
    }
911
 
    else 
912
 
    {
913
 
      *dfree = (F.d_blk_softlimit - F.d_bcount);
914
 
      *dsize = F.d_blk_softlimit ? F.d_blk_softlimit : F.d_blk_hardlimit;
915
 
    }
916
 
 
917
 
  }
918
 
  else
919
 
  {
920
 
          restore_re_uid();
921
 
          return(False);
922
 
  }
923
 
 
924
 
  return (True);
925
 
 
926
 
}
927
 
 
928
 
#else
929
 
 
930
 
#if    defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
931
 
#include <ufs/ufs/quota.h>
932
 
#include <machine/param.h>
933
 
#elif         AIX
934
 
/* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
935
 
#include <jfs/quota.h>
936
 
/* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
937
 
#define dqb_curfiles dqb_curinodes
938
 
#define dqb_fhardlimit dqb_ihardlimit
939
 
#define dqb_fsoftlimit dqb_isoftlimit
940
 
#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
941
 
#include <sys/quota.h>
942
 
#include <devnm.h>
943
 
#endif
944
 
 
945
 
#if defined(__FreeBSD__) || defined(__DragonFly__)
946
 
 
947
 
#include <rpc/rpc.h>
948
 
#include <rpc/types.h>
949
 
#include <rpcsvc/rquota.h>
950
 
#ifdef HAVE_RPC_NETTYPE_H
951
 
#include <rpc/nettype.h>
952
 
#endif
953
 
#include <rpc/xdr.h>
954
 
 
955
 
static int quotastat;
956
 
 
957
 
static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
958
 
{
959
 
        if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
960
 
                return(0);
961
 
        if (!xdr_int(xdrsp, &args->gqa_uid))
962
 
                return(0);
963
 
        return (1);
964
 
}
965
 
 
966
 
static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
967
 
{
968
 
        if (!xdr_int(xdrsp, &quotastat)) {
969
 
                DEBUG(6,("nfs_quotas: Status bad or zero\n"));
970
 
                return 0;
971
 
        }
972
 
        if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
973
 
                DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
974
 
                return 0;
975
 
        }
976
 
        if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
977
 
                DEBUG(6,("nfs_quotas: Active bad or zero\n"));
978
 
                return 0;
979
 
        }
980
 
        if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
981
 
                DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
982
 
                return 0;
983
 
        }
984
 
        if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
985
 
                DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
986
 
                return 0;
987
 
        }
988
 
        if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
989
 
                DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
990
 
                return 0;
991
 
        }
992
 
        return (1);
993
 
}
994
 
 
995
 
/* Works on FreeBSD, too. :-) */
996
 
static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
997
 
{
998
 
        uid_t uid = euser_id;
999
 
        struct dqblk D;
1000
 
        char *mnttype = nfspath;
1001
 
        CLIENT *clnt;
1002
 
        struct getquota_rslt gqr;
1003
 
        struct getquota_args args;
1004
 
        char *cutstr, *pathname, *host, *testpath;
1005
 
        int len;
1006
 
        static struct timeval timeout = {2,0};
1007
 
        enum clnt_stat clnt_stat;
1008
 
        BOOL ret = True;
1009
 
 
1010
 
        *bsize = *dfree = *dsize = (SMB_BIG_UINT)0;
1011
 
 
1012
 
        len=strcspn(mnttype, ":");
1013
 
        pathname=strstr(mnttype, ":");
1014
 
        cutstr = (char *) SMB_MALLOC(len+1);
1015
 
        if (!cutstr)
1016
 
                return False;
1017
 
 
1018
 
        memset(cutstr, '\0', len+1);
1019
 
        host = strncat(cutstr,mnttype, sizeof(char) * len );
1020
 
        DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
1021
 
        DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
1022
 
        testpath=strchr_m(mnttype, ':');
1023
 
        args.gqa_pathp = testpath+1;
1024
 
        args.gqa_uid = uid;
1025
 
 
1026
 
        DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
1027
 
 
1028
 
        if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
1029
 
                ret = False;
1030
 
                goto out;
1031
 
        }
1032
 
 
1033
 
        clnt->cl_auth = authunix_create_default();
1034
 
        DEBUG(9,("nfs_quotas: auth_success\n"));
1035
 
 
1036
 
        clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, (const xdrproc_t) my_xdr_getquota_args, (caddr_t)&args, (const xdrproc_t) my_xdr_getquota_rslt, (caddr_t)&gqr, timeout);
1037
 
 
1038
 
        if (clnt_stat != RPC_SUCCESS) {
1039
 
                DEBUG(9,("nfs_quotas: clnt_call fail\n"));
1040
 
                ret = False;
1041
 
                goto out;
1042
 
        }
1043
 
 
1044
 
        /* 
1045
 
         * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
1046
 
         * no quota set, and 3 if no permission to get the quota.  If 0 or 3 return
1047
 
         * something sensible.
1048
 
         */   
1049
 
 
1050
 
        switch ( quotastat ) {
1051
 
        case 0:
1052
 
                DEBUG(9,("nfs_quotas: Remote Quotas Failed!  Error \"%i\" \n", quotastat ));
1053
 
                ret = False;
1054
 
                goto out;
1055
 
 
1056
 
        case 1:
1057
 
                DEBUG(9,("nfs_quotas: Good quota data\n"));
1058
 
                D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
1059
 
                D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
1060
 
                D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
1061
 
                break;
1062
 
 
1063
 
        case 2:
1064
 
        case 3:
1065
 
                D.dqb_bsoftlimit = 1;
1066
 
                D.dqb_curblocks = 1;
1067
 
                DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat ));
1068
 
                break;
1069
 
 
1070
 
        default:
1071
 
                DEBUG(9,("nfs_quotas: Remote Quotas Questionable!  Error \"%i\" \n", quotastat ));
1072
 
                break;
1073
 
        }
1074
 
 
1075
 
        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",
1076
 
                        quotastat,
1077
 
                        gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
1078
 
                        gqr.getquota_rslt_u.gqr_rquota.rq_active,
1079
 
                        gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
1080
 
                        gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
1081
 
                        gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
1082
 
 
1083
 
        if (D.dqb_bsoftlimit == 0)
1084
 
                D.dqb_bsoftlimit = D.dqb_bhardlimit;
1085
 
        if (D.dqb_bsoftlimit == 0)
1086
 
                return False;
1087
 
 
1088
 
        *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
1089
 
        *dsize = D.dqb_bsoftlimit;
1090
 
 
1091
 
        if (D.dqb_curblocks == D.dqb_curblocks == 1)
1092
 
                *bsize = DEV_BSIZE;
1093
 
 
1094
 
        if (D.dqb_curblocks > D.dqb_bsoftlimit) {
1095
 
                *dfree = 0;
1096
 
                *dsize = D.dqb_curblocks;
1097
 
        } else
1098
 
                *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
1099
 
 
1100
 
  out:
1101
 
 
1102
 
        if (clnt) {
1103
 
                if (clnt->cl_auth)
1104
 
                        auth_destroy(clnt->cl_auth);
1105
 
                clnt_destroy(clnt);
1106
 
        }
1107
 
 
1108
 
        DEBUG(5,("nfs_quotas: For path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
1109
 
 
1110
 
        SAFE_FREE(cutstr);
1111
 
        DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
1112
 
        return ret;
1113
 
}
1114
 
 
1115
 
#endif
1116
 
 
1117
 
/****************************************************************************
1118
 
try to get the disk space from disk quotas - default version
1119
 
****************************************************************************/
1120
 
 
1121
 
BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
1122
 
{
1123
 
  int r;
1124
 
  struct dqblk D;
1125
 
  uid_t euser_id;
1126
 
#if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__)
1127
 
  char dev_disk[256];
1128
 
  SMB_STRUCT_STAT S;
1129
 
 
1130
 
  /* find the block device file */
1131
 
 
1132
 
#ifdef HPUX
1133
 
  /* Need to set the cache flag to 1 for HPUX. Seems
1134
 
   * to have a significant performance boost when
1135
 
   * lstat calls on /dev access this function.
1136
 
   */
1137
 
  if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0))
1138
 
#else
1139
 
  if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) 
1140
 
        return (False);
1141
 
#endif /* ifdef HPUX */
1142
 
 
1143
 
#endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__) */
1144
 
 
1145
 
  euser_id = geteuid();
1146
 
 
1147
 
#ifdef HPUX
1148
 
  /* for HPUX, real uid must be same as euid to execute quotactl for euid */
1149
 
  save_re_uid();
1150
 
  if (set_re_uid() != 0) return False;
1151
 
  
1152
 
  r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
1153
 
 
1154
 
  restore_re_uid();
1155
 
#else 
1156
 
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1157
 
  {
1158
 
    /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
1159
 
    gid_t egrp_id;
1160
 
#if defined(__FreeBSD__) || defined(__DragonFly__)
1161
 
    SMB_DEV_T devno;
1162
 
    struct statfs *mnts;
1163
 
    SMB_STRUCT_STAT st;
1164
 
    int mntsize, i;
1165
 
    
1166
 
    if (sys_stat(path,&st) < 0)
1167
 
        return False;
1168
 
    devno = st.st_dev;
1169
 
 
1170
 
    mntsize = getmntinfo(&mnts,MNT_NOWAIT);
1171
 
    if (mntsize <= 0)
1172
 
        return False;
1173
 
 
1174
 
    for (i = 0; i < mntsize; i++) {
1175
 
        if (sys_stat(mnts[i].f_mntonname,&st) < 0)
1176
 
            return False;
1177
 
        if (st.st_dev == devno)
1178
 
            break;
1179
 
    }
1180
 
    if (i == mntsize)
1181
 
        return False;
1182
 
#endif
1183
 
    
1184
 
    save_re_uid();
1185
 
    set_effective_uid(0);
1186
 
 
1187
 
#if defined(__FreeBSD__) || defined(__DragonFly__)
1188
 
    if (strcmp(mnts[i].f_fstypename,"nfs") == 0) {
1189
 
        BOOL retval;
1190
 
        retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize);
1191
 
        restore_re_uid();
1192
 
        return retval;
1193
 
    }
1194
 
#endif
1195
 
 
1196
 
    egrp_id = getegid();
1197
 
    r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
1198
 
 
1199
 
    /* As FreeBSD has group quotas, if getting the user
1200
 
       quota fails, try getting the group instead. */
1201
 
    if (r) {
1202
 
            r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D);
1203
 
    }
1204
 
 
1205
 
    restore_re_uid();
1206
 
  }
1207
 
#elif defined(AIX)
1208
 
  /* AIX has both USER and GROUP quotas: 
1209
 
     Get the USER quota (ohnielse@fysik.dtu.dk) */
1210
 
  save_re_uid();
1211
 
  if (set_re_uid() != 0) 
1212
 
    return False;
1213
 
  r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
1214
 
  restore_re_uid();
1215
 
#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1216
 
  r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
1217
 
#endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1218
 
#endif /* HPUX */
1219
 
 
1220
 
  /* Use softlimit to determine disk space, except when it has been exceeded */
1221
 
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1222
 
  *bsize = DEV_BSIZE;
1223
 
#else /* !__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */
1224
 
  *bsize = 1024;
1225
 
#endif /*!__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */
1226
 
 
1227
 
  if (r)
1228
 
    {
1229
 
      if (errno == EDQUOT) 
1230
 
        {
1231
 
          *dfree =0;
1232
 
          *dsize =D.dqb_curblocks;
1233
 
          return (True);
1234
 
        }
1235
 
      else return(False);
1236
 
    }
1237
 
 
1238
 
  /* If softlimit is zero, set it equal to hardlimit.
1239
 
   */
1240
 
 
1241
 
  if (D.dqb_bsoftlimit==0)
1242
 
    D.dqb_bsoftlimit = D.dqb_bhardlimit;
1243
 
 
1244
 
  if (D.dqb_bsoftlimit==0)
1245
 
    return(False);
1246
 
  /* Use softlimit to determine disk space, except when it has been exceeded */
1247
 
  if ((D.dqb_curblocks>D.dqb_bsoftlimit)
1248
 
#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__)
1249
 
||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
1250
 
#endif
1251
 
    ) {
1252
 
      *dfree = 0;
1253
 
      *dsize = D.dqb_curblocks;
1254
 
    }
1255
 
  else {
1256
 
    *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
1257
 
    *dsize = D.dqb_bsoftlimit;
1258
 
  }
1259
 
  return (True);
1260
 
}
1261
 
 
1262
 
#endif
1263
 
 
1264
 
#if defined(VXFS_QUOTA)
1265
 
 
1266
 
/****************************************************************************
1267
 
Try to get the disk space from Veritas disk quotas.
1268
 
    David Lee <T.D.Lee@durham.ac.uk> August 1999.
1269
 
 
1270
 
Background assumptions:
1271
 
    Potentially under many Operating Systems.  Initially Solaris 2.
1272
 
 
1273
 
    My guess is that Veritas is largely, though not entirely,
1274
 
    independent of OS.  So I have separated it out.
1275
 
 
1276
 
    There may be some details.  For example, OS-specific "include" files.
1277
 
 
1278
 
    It is understood that HPUX 10 somehow gets Veritas quotas without
1279
 
    any special effort; if so, this routine need not be compiled in.
1280
 
        Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
1281
 
 
1282
 
Warning:
1283
 
    It is understood that Veritas do not publicly support this ioctl interface.
1284
 
    Rather their preference would be for the user (us) to call the native
1285
 
    OS and then for the OS itself to call through to the VxFS filesystem.
1286
 
    Presumably HPUX 10, see above, does this.
1287
 
 
1288
 
Hints for porting:
1289
 
    Add your OS to "IFLIST" below.
1290
 
    Get it to compile successfully:
1291
 
        Almost certainly "include"s require attention: see SUNOS5.
1292
 
    In the main code above, arrange for it to be called: see SUNOS5.
1293
 
    Test!
1294
 
    
1295
 
****************************************************************************/
1296
 
 
1297
 
/* "IFLIST"
1298
 
 * This "if" is a list of ports:
1299
 
 *      if defined(OS1) || defined(OS2) || ...
1300
 
 */
1301
 
#if defined(SUNOS5)
1302
 
 
1303
 
#if defined(SUNOS5)
1304
 
#include <sys/fs/vx_solaris.h>
1305
 
#endif
1306
 
#include <sys/fs/vx_machdep.h>
1307
 
#include <sys/fs/vx_layout.h>
1308
 
#include <sys/fs/vx_quota.h>
1309
 
#include <sys/fs/vx_aioctl.h>
1310
 
#include <sys/fs/vx_ioctl.h>
1311
 
 
1312
 
BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
1313
 
{
1314
 
  uid_t user_id, euser_id;
1315
 
  int ret;
1316
 
  struct vx_dqblk D;
1317
 
  struct vx_quotctl quotabuf;
1318
 
  struct vx_genioctl genbuf;
1319
 
  pstring qfname;
1320
 
  int file;
1321
 
 
1322
 
  /*
1323
 
   * "name" may or may not include a trailing "/quotas".
1324
 
   * Arranging consistency of calling here in "quotas.c" may not be easy and
1325
 
   * it might be easier to examine and adjust it here.
1326
 
   * Fortunately, VxFS seems not to mind at present.
1327
 
   */
1328
 
  pstrcpy(qfname, name) ;
1329
 
  /* pstrcat(qfname, "/quotas") ; */    /* possibly examine and adjust "name" */
1330
 
 
1331
 
  euser_id = geteuid();
1332
 
  set_effective_uid(0);
1333
 
 
1334
 
  DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname));
1335
 
  if((file=sys_open(qfname, O_RDONLY,0))<0) {
1336
 
    set_effective_uid(euser_id);
1337
 
    return(False);
1338
 
  }
1339
 
  genbuf.ioc_cmd = VX_QUOTACTL;
1340
 
  genbuf.ioc_up = (void *) &quotabuf;
1341
 
 
1342
 
  quotabuf.cmd = VX_GETQUOTA;
1343
 
  quotabuf.uid = euser_id;
1344
 
  quotabuf.addr = (caddr_t) &D;
1345
 
  ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf);
1346
 
  close(file);
1347
 
 
1348
 
  set_effective_uid(euser_id);
1349
 
 
1350
 
  if (ret < 0) {
1351
 
    DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) ));
1352
 
    return(False);
1353
 
  }
1354
 
 
1355
 
  /* If softlimit is zero, set it equal to hardlimit.
1356
 
   */
1357
 
 
1358
 
  if (D.dqb_bsoftlimit==0)
1359
 
    D.dqb_bsoftlimit = D.dqb_bhardlimit;
1360
 
 
1361
 
  /* Use softlimit to determine disk space. A user exceeding the quota is told
1362
 
   * that there's no space left. Writes might actually work for a bit if the
1363
 
   * hardlimit is set higher than softlimit. Effectively the disk becomes
1364
 
   * made of rubber latex and begins to expand to accommodate the user :-)
1365
 
   */
1366
 
  DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
1367
 
         path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit,
1368
 
         D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit));
1369
 
 
1370
 
  if (D.dqb_bsoftlimit==0)
1371
 
    return(False);
1372
 
  *bsize = DEV_BSIZE;
1373
 
  *dsize = D.dqb_bsoftlimit;
1374
 
 
1375
 
  if (D.dqb_curblocks > D.dqb_bsoftlimit) {
1376
 
     *dfree = 0;
1377
 
     *dsize = D.dqb_curblocks;
1378
 
  } else
1379
 
    *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
1380
 
      
1381
 
  DEBUG(5,("disk_quotas for path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",
1382
 
         path,(double)*bsize,(double)*dfree,(double)*dsize));
1383
 
 
1384
 
  return(True);
1385
 
}
1386
 
 
1387
 
#endif /* SUNOS5 || ... */
1388
 
 
1389
 
#endif /* VXFS_QUOTA */
1390
 
 
1391
 
#else /* WITH_QUOTAS */
1392
 
 
1393
 
BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
1394
 
{
1395
 
  (*bsize) = 512; /* This value should be ignored */
1396
 
 
1397
 
  /* And just to be sure we set some values that hopefully */
1398
 
  /* will be larger that any possible real-world value     */
1399
 
  (*dfree) = (SMB_BIG_UINT)-1;
1400
 
  (*dsize) = (SMB_BIG_UINT)-1;
1401
 
 
1402
 
  /* As we have select not to use quotas, allways fail */
1403
 
  return False;
1404
 
}
1405
 
#endif /* WITH_QUOTAS */
1406
 
 
1407
 
#else /* HAVE_SYS_QUOTAS */
1408
 
/* wrapper to the new sys_quota interface 
1409
 
   this file should be removed later
1410
 
   */
1411
 
BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
1412
 
{
1413
 
        int r;
1414
 
        SMB_DISK_QUOTA D;
1415
 
        unid_t id;
1416
 
 
1417
 
        id.uid = geteuid();
1418
 
 
1419
 
        ZERO_STRUCT(D);
1420
 
        r=sys_get_quota(path, SMB_USER_QUOTA_TYPE, id, &D);
1421
 
 
1422
 
        /* Use softlimit to determine disk space, except when it has been exceeded */
1423
 
        *bsize = D.bsize;
1424
 
        if (r == -1) {
1425
 
                if (errno == EDQUOT) {
1426
 
                        *dfree =0;
1427
 
                        *dsize =D.curblocks;
1428
 
                        return (True);
1429
 
                } else {
1430
 
                        goto try_group_quota;
1431
 
                }
1432
 
        }
1433
 
 
1434
 
        /* Use softlimit to determine disk space, except when it has been exceeded */
1435
 
        if (
1436
 
                (D.softlimit && D.curblocks >= D.softlimit) ||
1437
 
                (D.hardlimit && D.curblocks >= D.hardlimit) ||
1438
 
                (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
1439
 
                (D.ihardlimit && D.curinodes>=D.ihardlimit)
1440
 
        ) {
1441
 
                *dfree = 0;
1442
 
                *dsize = D.curblocks;
1443
 
        } else if (D.softlimit==0 && D.hardlimit==0) {
1444
 
                goto try_group_quota;
1445
 
        } else {
1446
 
                if (D.softlimit == 0)
1447
 
                        D.softlimit = D.hardlimit;
1448
 
                *dfree = D.softlimit - D.curblocks;
1449
 
                *dsize = D.softlimit;
1450
 
        }
1451
 
 
1452
 
        return True;
1453
 
        
1454
 
try_group_quota:
1455
 
        id.gid = getegid();
1456
 
 
1457
 
        ZERO_STRUCT(D);
1458
 
        r=sys_get_quota(path, SMB_GROUP_QUOTA_TYPE, id, &D);
1459
 
 
1460
 
        /* Use softlimit to determine disk space, except when it has been exceeded */
1461
 
        *bsize = D.bsize;
1462
 
        if (r == -1) {
1463
 
                if (errno == EDQUOT) {
1464
 
                        *dfree =0;
1465
 
                        *dsize =D.curblocks;
1466
 
                        return (True);
1467
 
                } else {
1468
 
                        return False;
1469
 
                }
1470
 
        }
1471
 
 
1472
 
        /* Use softlimit to determine disk space, except when it has been exceeded */
1473
 
        if (
1474
 
                (D.softlimit && D.curblocks >= D.softlimit) ||
1475
 
                (D.hardlimit && D.curblocks >= D.hardlimit) ||
1476
 
                (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
1477
 
                (D.ihardlimit && D.curinodes>=D.ihardlimit)
1478
 
        ) {
1479
 
                *dfree = 0;
1480
 
                *dsize = D.curblocks;
1481
 
        } else if (D.softlimit==0 && D.hardlimit==0) {
1482
 
                return False;
1483
 
        } else {
1484
 
                if (D.softlimit == 0)
1485
 
                        D.softlimit = D.hardlimit;
1486
 
                *dfree = D.softlimit - D.curblocks;
1487
 
                *dsize = D.softlimit;
1488
 
        }
1489
 
 
1490
 
        return (True);
1491
 
}
1492
 
#endif /* HAVE_SYS_QUOTAS */