Changeset 988 for vendor/current/source3/smbd/quotas.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/smbd/quotas.c
r746 r988 52 52 #endif /* VXFS_QUOTA */ 53 53 54 #ifdef LINUX 55 56 #include <sys/types.h> 57 #include <mntent.h> 58 59 /* 60 * This shouldn't be neccessary - it should be /usr/include/sys/quota.h 61 * So we include all the files has *should* be in the system into a large, 62 * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA. 63 */ 64 65 #include "samba_linux_quota.h" 66 67 typedef struct _LINUX_SMB_DISK_QUOTA { 68 uint64_t bsize; 69 uint64_t hardlimit; /* In bsize units. */ 70 uint64_t softlimit; /* In bsize units. */ 71 uint64_t curblocks; /* In bsize units. */ 72 uint64_t ihardlimit; /* inode hard limit. */ 73 uint64_t isoftlimit; /* inode soft limit. */ 74 uint64_t curinodes; /* Current used inodes. */ 75 } LINUX_SMB_DISK_QUOTA; 76 77 78 /* 79 * nfs quota support 80 * (essentially taken from FreeBSD / SUNOS5 section) 81 */ 82 #include <rpc/rpc.h> 83 #include <rpc/types.h> 84 #include <rpcsvc/rquota.h> 85 #ifdef HAVE_RPC_NETTYPE_H 86 #include <rpc/nettype.h> 87 #endif 88 #include <rpc/xdr.h> 89 90 static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args) 91 { 92 if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN )) 93 return(0); 94 if (!xdr_int(xdrsp, &args->gqa_uid)) 95 return(0); 96 return (1); 97 } 98 99 static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr) 100 { 101 int quotastat; 102 103 if (!xdr_int(xdrsp, "astat)) { 104 DEBUG(6,("nfs_quotas: Status bad or zero\n")); 105 return 0; 106 } 107 gqr->status = quotastat; 108 109 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) { 110 DEBUG(6,("nfs_quotas: Block size bad or zero\n")); 111 return 0; 112 } 113 if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) { 114 DEBUG(6,("nfs_quotas: Active bad or zero\n")); 115 return 0; 116 } 117 if (!xdr_int(xdrsp, (int *)&gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) { 118 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n")); 119 return 0; 120 } 121 if (!xdr_int(xdrsp, (int *)&gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) { 122 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n")); 123 return 0; 124 } 125 if (!xdr_int(xdrsp, (int *)&gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) { 126 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n")); 127 return 0; 128 } 129 return 1; 130 } 131 132 static bool nfs_quotas(char *nfspath, uid_t euser_id, uint64_t *bsize, 133 uint64_t *dfree, uint64_t *dsize) 134 { 135 uid_t uid = euser_id; 136 LINUX_SMB_DISK_QUOTA D; 137 char *mnttype = nfspath; 138 CLIENT *clnt; 139 struct getquota_rslt gqr; 140 struct getquota_args args; 141 char *cutstr, *pathname, *host, *testpath; 142 int len; 143 static struct timeval timeout = {2,0}; 144 enum clnt_stat clnt_stat; 145 bool ret = True; 146 147 *bsize = *dfree = *dsize = (uint64_t)0; 148 149 len=strcspn(mnttype, ":"); 150 pathname=strstr(mnttype, ":"); 151 cutstr = (char *) SMB_MALLOC(len+1); 152 if (!cutstr) 153 return False; 154 155 memset(cutstr, '\0', len+1); 156 host = strncat(cutstr,mnttype, sizeof(char) * len ); 157 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr)); 158 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype)); 159 testpath=strchr_m(mnttype, ':'); 160 args.gqa_pathp = testpath+1; 161 args.gqa_uid = uid; 162 163 DEBUG(5, ("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers " 164 "\"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, 165 "udp")); 166 167 if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) { 168 ret = False; 169 goto out; 170 } 171 172 clnt->cl_auth = authunix_create_default(); 173 DEBUG(9,("nfs_quotas: auth_success\n")); 174 175 clnt_stat=clnt_call(clnt, 176 RQUOTAPROC_GETQUOTA, 177 (const xdrproc_t)my_xdr_getquota_args, 178 (caddr_t)&args, 179 (const xdrproc_t)my_xdr_getquota_rslt, 180 (caddr_t)&gqr, timeout); 181 182 if (clnt_stat != RPC_SUCCESS) { 183 DEBUG(9,("nfs_quotas: clnt_call fail\n")); 184 ret = False; 185 goto out; 186 } 187 188 /* 189 * gqr.status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is 190 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return 191 * something sensible. 192 */ 193 194 switch (gqr.status) { 195 case 0: 196 DEBUG(9, ("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", 197 gqr.status)); 198 ret = False; 199 goto out; 200 201 case 1: 202 DEBUG(9,("nfs_quotas: Good quota data\n")); 203 D.softlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit; 204 D.hardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit; 205 D.curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks; 206 break; 207 208 case 2: 209 case 3: 210 D.softlimit = 1; 211 D.curblocks = 1; 212 DEBUG(9, ("nfs_quotas: Remote Quotas returned \"%i\" \n", 213 gqr.status)); 214 break; 215 216 default: 217 DEBUG(9, ("nfs_quotas: Remote Quotas Questionable! " 218 "Error \"%i\" \n", gqr.status)); 219 break; 220 } 221 222 DEBUG(10, ("nfs_quotas: Let`s look at D a bit closer... " 223 "status \"%i\" bsize \"%i\" active? \"%i\" bhard " 224 "\"%i\" bsoft \"%i\" curb \"%i\" \n", 225 gqr.status, 226 gqr.getquota_rslt_u.gqr_rquota.rq_bsize, 227 gqr.getquota_rslt_u.gqr_rquota.rq_active, 228 gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit, 229 gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit, 230 gqr.getquota_rslt_u.gqr_rquota.rq_curblocks)); 231 232 if (D.softlimit == 0) 233 D.softlimit = D.hardlimit; 234 if (D.softlimit == 0) 235 return False; 236 237 *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize; 238 *dsize = D.softlimit; 239 240 if (D.curblocks == 1) 241 *bsize = DEV_BSIZE; 242 243 if (D.curblocks > D.softlimit) { 244 *dfree = 0; 245 *dsize = D.curblocks; 246 } else 247 *dfree = D.softlimit - D.curblocks; 248 249 out: 250 251 if (clnt) { 252 if (clnt->cl_auth) 253 auth_destroy(clnt->cl_auth); 254 clnt_destroy(clnt); 255 } 256 257 DEBUG(5, ("nfs_quotas: For path \"%s\" returning " 258 "bsize %.0f, dfree %.0f, dsize %.0f\n", 259 args.gqa_pathp, (double)*bsize, (double)*dfree, 260 (double)*dsize)); 261 262 SAFE_FREE(cutstr); 263 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" )); 264 return ret; 265 } 266 267 /* end of nfs quota section */ 268 269 #ifdef HAVE_LINUX_DQBLK_XFS_H 270 #include <linux/dqblk_xfs.h> 271 272 /**************************************************************************** 273 Abstract out the XFS Quota Manager quota get call. 274 ****************************************************************************/ 275 276 static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp) 277 { 278 struct fs_disk_quota D; 279 int ret; 280 281 ZERO_STRUCT(D); 282 283 ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D); 284 285 if (ret) 286 ret = quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D); 287 288 if (ret) 289 return ret; 290 291 dp->bsize = (uint64_t)512; 292 dp->softlimit = (uint64_t)D.d_blk_softlimit; 293 dp->hardlimit = (uint64_t)D.d_blk_hardlimit; 294 dp->ihardlimit = (uint64_t)D.d_ino_hardlimit; 295 dp->isoftlimit = (uint64_t)D.d_ino_softlimit; 296 dp->curinodes = (uint64_t)D.d_icount; 297 dp->curblocks = (uint64_t)D.d_bcount; 298 299 return ret; 300 } 301 #else 302 static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp) 303 { 304 DEBUG(0,("XFS quota support not available\n")); 305 errno = ENOSYS; 306 return -1; 307 } 308 #endif 309 310 311 /**************************************************************************** 312 Abstract out the old and new Linux quota get calls. 313 ****************************************************************************/ 314 315 static int get_smb_linux_v1_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp) 316 { 317 struct v1_kern_dqblk D; 318 int ret; 319 320 ZERO_STRUCT(D); 321 322 ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D); 323 324 if (ret && errno != EDQUOT) 325 ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D); 326 327 if (ret && errno != EDQUOT) 328 return ret; 329 330 dp->bsize = (uint64_t)QUOTABLOCK_SIZE; 331 dp->softlimit = (uint64_t)D.dqb_bsoftlimit; 332 dp->hardlimit = (uint64_t)D.dqb_bhardlimit; 333 dp->ihardlimit = (uint64_t)D.dqb_ihardlimit; 334 dp->isoftlimit = (uint64_t)D.dqb_isoftlimit; 335 dp->curinodes = (uint64_t)D.dqb_curinodes; 336 dp->curblocks = (uint64_t)D.dqb_curblocks; 337 338 return ret; 339 } 340 341 static int get_smb_linux_v2_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp) 342 { 343 struct v2_kern_dqblk D; 344 int ret; 345 346 ZERO_STRUCT(D); 347 348 ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D); 349 350 if (ret && errno != EDQUOT) 351 ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D); 352 353 if (ret && errno != EDQUOT) 354 return ret; 355 356 dp->bsize = (uint64_t)QUOTABLOCK_SIZE; 357 dp->softlimit = (uint64_t)D.dqb_bsoftlimit; 358 dp->hardlimit = (uint64_t)D.dqb_bhardlimit; 359 dp->ihardlimit = (uint64_t)D.dqb_ihardlimit; 360 dp->isoftlimit = (uint64_t)D.dqb_isoftlimit; 361 dp->curinodes = (uint64_t)D.dqb_curinodes; 362 dp->curblocks = ((uint64_t)D.dqb_curspace) / dp->bsize; 363 364 return ret; 365 } 366 367 /**************************************************************************** 368 Brand-new generic quota interface. 369 ****************************************************************************/ 370 371 static int get_smb_linux_gen_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp) 372 { 373 struct if_dqblk D; 374 int ret; 375 376 ZERO_STRUCT(D); 377 378 ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D); 379 380 if (ret && errno != EDQUOT) 381 ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D); 382 383 if (ret && errno != EDQUOT) 384 return ret; 385 386 dp->bsize = (uint64_t)QUOTABLOCK_SIZE; 387 dp->softlimit = (uint64_t)D.dqb_bsoftlimit; 388 dp->hardlimit = (uint64_t)D.dqb_bhardlimit; 389 dp->ihardlimit = (uint64_t)D.dqb_ihardlimit; 390 dp->isoftlimit = (uint64_t)D.dqb_isoftlimit; 391 dp->curinodes = (uint64_t)D.dqb_curinodes; 392 dp->curblocks = ((uint64_t)D.dqb_curspace) / dp->bsize; 393 394 return ret; 395 } 396 397 /**************************************************************************** 398 Try to get the disk space from disk quotas (LINUX version). 399 ****************************************************************************/ 400 401 bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize) 402 { 403 int r; 404 SMB_STRUCT_STAT S; 405 FILE *fp; 406 LINUX_SMB_DISK_QUOTA D; 407 struct mntent *mnt; 408 SMB_DEV_T devno; 409 int found; 410 uid_t euser_id; 411 gid_t egrp_id; 412 413 ZERO_STRUCT(D); 414 415 euser_id = geteuid(); 416 egrp_id = getegid(); 417 418 /* find the block device file */ 419 420 if (sys_stat(path, &S, false) == -1 ) 421 return(False) ; 422 423 devno = S.st_ex_dev ; 424 425 if ((fp = setmntent(MOUNTED,"r")) == NULL) 426 return(False) ; 427 428 found = False ; 429 430 while ((mnt = getmntent(fp))) { 431 if (sys_stat(mnt->mnt_dir, &S, false) == -1) 432 continue ; 433 434 if (S.st_ex_dev == devno) { 435 found = True ; 436 break; 437 } 438 } 439 440 endmntent(fp) ; 441 442 if (!found) 443 return(False); 444 445 become_root(); 446 447 if (strcmp(mnt->mnt_type, "nfs") == 0) { 448 bool retval; 449 retval = nfs_quotas(mnt->mnt_fsname , euser_id, bsize, dfree, dsize); 450 unbecome_root(); 451 return retval; 452 } 453 454 if (strcmp(mnt->mnt_type, "xfs")==0) { 455 r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, egrp_id, &D); 456 } else { 457 r=get_smb_linux_gen_quota(mnt->mnt_fsname, euser_id, egrp_id, &D); 458 if (r == -1 && errno != EDQUOT) { 459 r=get_smb_linux_v2_quota(mnt->mnt_fsname, euser_id, egrp_id, &D); 460 if (r == -1 && errno != EDQUOT) 461 r=get_smb_linux_v1_quota(mnt->mnt_fsname, euser_id, egrp_id, &D); 462 } 463 } 464 465 unbecome_root(); 466 467 /* Use softlimit to determine disk space, except when it has been exceeded */ 468 *bsize = D.bsize; 469 if (r == -1) { 470 if (errno == EDQUOT) { 471 *dfree =0; 472 *dsize =D.curblocks; 473 return (True); 474 } else { 475 return(False); 476 } 477 } 478 479 /* Use softlimit to determine disk space, except when it has been exceeded */ 480 if ( 481 (D.softlimit && D.curblocks >= D.softlimit) || 482 (D.hardlimit && D.curblocks >= D.hardlimit) || 483 (D.isoftlimit && D.curinodes >= D.isoftlimit) || 484 (D.ihardlimit && D.curinodes>=D.ihardlimit) 485 ) { 486 *dfree = 0; 487 *dsize = D.curblocks; 488 } else if (D.softlimit==0 && D.hardlimit==0) { 489 return(False); 490 } else { 491 if (D.softlimit == 0) 492 D.softlimit = D.hardlimit; 493 *dfree = D.softlimit - D.curblocks; 494 *dsize = D.softlimit; 495 } 496 497 return (True); 498 } 499 500 #elif defined(CRAY) 501 502 #include <sys/quota.h> 503 #include <mntent.h> 504 505 /**************************************************************************** 506 try to get the disk space from disk quotas (CRAY VERSION) 507 ****************************************************************************/ 508 509 bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize) 510 { 511 struct mntent *mnt; 512 FILE *fd; 513 SMB_STRUCT_STAT sbuf; 514 SMB_DEV_T devno ; 515 struct q_request request ; 516 struct qf_header header ; 517 int quota_default = 0 ; 518 bool found = false; 519 520 if (sys_stat(path, &sbuf, false) == -1) { 521 return false; 522 } 523 524 devno = sbuf.st_ex_dev ; 525 526 if ((fd = setmntent(KMTAB)) == NULL) { 527 return false; 528 } 529 530 while ((mnt = getmntent(fd)) != NULL) { 531 if (sys_stat(mnt->mnt_dir, &sbuf, false) == -1) { 532 continue; 533 } 534 if (sbuf.st_ex_dev == devno) { 535 found = frue ; 536 break; 537 } 538 } 539 540 name = talloc_strdup(talloc_tos(), mnt->mnt_dir); 541 endmntent(fd); 542 if (!found) { 543 return false; 544 } 545 546 if (!name) { 547 return false; 548 } 549 550 request.qf_magic = QF_MAGIC ; 551 request.qf_entry.id = geteuid() ; 552 553 if (quotactl(name, Q_GETQUOTA, &request) == -1) { 554 return false; 555 } 556 557 if (!request.user) { 558 return False; 559 } 560 561 if (request.qf_entry.user_q.f_quota == QFV_DEFAULT) { 562 if (!quota_default) { 563 if (quotactl(name, Q_GETHEADER, &header) == -1) { 564 return false; 565 } else { 566 quota_default = header.user_h.def_fq; 567 } 568 } 569 *dfree = quota_default; 570 } else if (request.qf_entry.user_q.f_quota == QFV_PREVENT) { 571 *dfree = 0; 572 } else { 573 *dfree = request.qf_entry.user_q.f_quota; 574 } 575 576 *dsize = request.qf_entry.user_q.f_use; 577 578 if (*dfree < *dsize) { 579 *dfree = 0; 580 } else { 581 *dfree -= *dsize; 582 } 583 584 *bsize = 4096 ; /* Cray blocksize */ 585 return true; 586 } 587 588 589 #elif defined(SUNOS5) || defined(SUNOS4) 54 55 #if defined(SUNOS5) || defined(SUNOS4) 590 56 591 57 #include <fcntl.h> … … 614 80 #include <rpc/xdr.h> 615 81 82 static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr) 83 { 84 int quotastat; 85 86 if (!xdr_int(xdrsp, "astat)) { 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 616 115 static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args) 617 116 { … … 620 119 if (!xdr_int(xdrsp, &args->gqa_uid)) 621 120 return(0); 622 return (1);623 }624 625 static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)626 {627 int quotastat;628 629 if (!xdr_int(xdrsp, "astat)) {630 DEBUG(6,("nfs_quotas: Status bad or zero\n"));631 return 0;632 }633 gqr->status = quotastat;634 635 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {636 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));637 return 0;638 }639 if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {640 DEBUG(6,("nfs_quotas: Active bad or zero\n"));641 return 0;642 }643 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {644 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));645 return 0;646 }647 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {648 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));649 return 0;650 }651 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {652 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));653 return 0;654 }655 121 return (1); 656 122 } … … 706 172 707 173 /* 708 * gqr.status returns 0 if the rpc call fails,1 if quotas exist, 2 if there is709 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return710 * something sensible.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. 711 177 */ 712 178 713 179 switch (gqr.status) { 714 case 0:715 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", gqr.status));716 ret = False;717 goto out;718 719 180 case 1: 720 181 DEBUG(9,("nfs_quotas: Good quota data\n")); … … 732 193 733 194 default: 734 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", gqr.status )); 735 break; 195 DEBUG(9, ("nfs_quotas: Unknown Remote Quota Status \"%i\"\n", 196 gqr.status)); 197 ret = false; 198 goto out; 736 199 } 737 200 … … 774 237 ****************************************************************************/ 775 238 776 bool disk_quotas(const char *path, 777 uint64_t *bsize, 778 uint64_t *dfree, 779 uint64_t *dsize) 239 bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize, 240 uint64_t *dfree, uint64_t *dsize) 780 241 { 781 242 uid_t euser_id; … … 805 266 path, (unsigned int)devno)); 806 267 #if defined(SUNOS5) 807 if ((fd = sys_fopen(MNTTAB, "r")) == NULL) {268 if ((fd = fopen(MNTTAB, "r")) == NULL) { 808 269 return false; 809 270 } … … 874 335 875 336 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); 876 if((file= sys_open(name, O_RDONLY,0))<0) {337 if((file=open(name, O_RDONLY,0))<0) { 877 338 unbecome_root(); 878 339 return false; … … 943 404 944 405 945 #elif defined(OSF1)946 #include <ufs/quota.h>947 948 /****************************************************************************949 try to get the disk space from disk quotas - OSF1 version950 ****************************************************************************/951 952 bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)953 {954 int r, save_errno;955 struct dqblk D;956 SMB_STRUCT_STAT S;957 uid_t euser_id;958 959 /*960 * This code presumes that OSF1 will only961 * give out quota info when the real uid962 * matches the effective uid. JRA.963 */964 euser_id = geteuid();965 save_re_uid();966 if (set_re_uid() != 0) return False;967 968 r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D);969 if (r) {970 save_errno = errno;971 }972 973 restore_re_uid();974 975 *bsize = DEV_BSIZE;976 977 if (r)978 {979 if (save_errno == EDQUOT) /* disk quota exceeded */980 {981 *dfree = 0;982 *dsize = D.dqb_curblocks;983 return (True);984 }985 else986 return (False);987 }988 989 /* If softlimit is zero, set it equal to hardlimit.990 */991 992 if (D.dqb_bsoftlimit==0)993 D.dqb_bsoftlimit = D.dqb_bhardlimit;994 995 /* Use softlimit to determine disk space, except when it has been exceeded */996 997 if (D.dqb_bsoftlimit==0)998 return(False);999 1000 if ((D.dqb_curblocks>D.dqb_bsoftlimit)) {1001 *dfree = 0;1002 *dsize = D.dqb_curblocks;1003 } else {1004 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;1005 *dsize = D.dqb_bsoftlimit;1006 }1007 return (True);1008 }1009 1010 #elif defined (IRIX6)1011 /****************************************************************************1012 try to get the disk space from disk quotas (IRIX 6.2 version)1013 ****************************************************************************/1014 1015 #include <sys/quota.h>1016 #include <mntent.h>1017 1018 bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)1019 {1020 uid_t euser_id;1021 int r;1022 struct dqblk D;1023 struct fs_disk_quota F;1024 SMB_STRUCT_STAT S;1025 FILE *fp;1026 struct mntent *mnt;1027 SMB_DEV_T devno;1028 int found;1029 1030 /* find the block device file */1031 1032 if ( sys_stat(path, &S, false) == -1 ) {1033 return(False) ;1034 }1035 1036 devno = S.st_ex_dev ;1037 1038 fp = setmntent(MOUNTED,"r");1039 found = False ;1040 1041 while ((mnt = getmntent(fp))) {1042 if ( sys_stat(mnt->mnt_dir, &S, false) == -1 )1043 continue ;1044 if (S.st_ex_dev == devno) {1045 found = True ;1046 break ;1047 }1048 }1049 endmntent(fp) ;1050 1051 if (!found) {1052 return(False);1053 }1054 1055 euser_id=geteuid();1056 become_root();1057 1058 /* Use softlimit to determine disk space, except when it has been exceeded */1059 1060 *bsize = 512;1061 1062 if ( 0 == strcmp ( mnt->mnt_type, "efs" ))1063 {1064 r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);1065 1066 unbecome_root();1067 1068 if (r==-1)1069 return(False);1070 1071 /* Use softlimit to determine disk space, except when it has been exceeded */1072 if (1073 (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||1074 (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||1075 (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) ||1076 (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit)1077 )1078 {1079 *dfree = 0;1080 *dsize = D.dqb_curblocks;1081 }1082 else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)1083 {1084 return(False);1085 }1086 else1087 {1088 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;1089 *dsize = D.dqb_bsoftlimit;1090 }1091 1092 }1093 else if ( 0 == strcmp ( mnt->mnt_type, "xfs" ))1094 {1095 r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);1096 1097 unbecome_root();1098 1099 if (r==-1)1100 {1101 DEBUG(5, ("quotactl for uid=%u: %s", euser_id, strerror(errno)));1102 return(False);1103 }1104 1105 /* No quota for this user. */1106 if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0)1107 {1108 return(False);1109 }1110 1111 /* Use softlimit to determine disk space, except when it has been exceeded */1112 if (1113 (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) ||1114 (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) ||1115 (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) ||1116 (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit)1117 )1118 {1119 *dfree = 0;1120 *dsize = F.d_bcount;1121 }1122 else1123 {1124 *dfree = (F.d_blk_softlimit - F.d_bcount);1125 *dsize = F.d_blk_softlimit ? F.d_blk_softlimit : F.d_blk_hardlimit;1126 }1127 1128 }1129 else1130 {1131 unbecome_root();1132 return(False);1133 }1134 1135 return (True);1136 1137 }1138 1139 406 #else 1140 407 1141 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) 1142 #include <ufs/ufs/quota.h> 1143 #include <machine/param.h> 1144 #elif AIX 408 #if AIX 1145 409 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */ 1146 410 #include <jfs/quota.h> … … 1153 417 #include <sys/vmount.h> 1154 418 #endif /* AIX 5.3 */ 1155 #else /* ! __FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__*/419 #else /* !AIX */ 1156 420 #include <sys/quota.h> 1157 421 #include <devnm.h> 1158 422 #endif 1159 423 1160 #if defined(__FreeBSD__) || defined(__DragonFly__)1161 1162 #include <rpc/rpc.h>1163 #include <rpc/types.h>1164 #include <rpcsvc/rquota.h>1165 #ifdef HAVE_RPC_NETTYPE_H1166 #include <rpc/nettype.h>1167 #endif1168 #include <rpc/xdr.h>1169 1170 static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)1171 {1172 if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))1173 return(0);1174 if (!xdr_int(xdrsp, &args->gqa_uid))1175 return(0);1176 return (1);1177 }1178 1179 static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)1180 {1181 int quotastat;1182 1183 if (!xdr_int(xdrsp, "astat)) {1184 DEBUG(6,("nfs_quotas: Status bad or zero\n"));1185 return 0;1186 }1187 gqr->status = quotastat;1188 1189 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {1190 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));1191 return 0;1192 }1193 if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {1194 DEBUG(6,("nfs_quotas: Active bad or zero\n"));1195 return 0;1196 }1197 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {1198 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));1199 return 0;1200 }1201 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {1202 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));1203 return 0;1204 }1205 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {1206 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));1207 return 0;1208 }1209 return (1);1210 }1211 1212 /* Works on FreeBSD, too. :-) */1213 static bool nfs_quotas(char *nfspath, uid_t euser_id, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)1214 {1215 uid_t uid = euser_id;1216 struct dqblk D;1217 char *mnttype = nfspath;1218 CLIENT *clnt;1219 struct getquota_rslt gqr;1220 struct getquota_args args;1221 char *cutstr, *pathname, *host, *testpath;1222 int len;1223 static struct timeval timeout = {2,0};1224 enum clnt_stat clnt_stat;1225 bool ret = True;1226 1227 *bsize = *dfree = *dsize = (uint64_t)0;1228 1229 len=strcspn(mnttype, ":");1230 pathname=strstr(mnttype, ":");1231 cutstr = (char *) SMB_MALLOC(len+1);1232 if (!cutstr)1233 return False;1234 1235 memset(cutstr, '\0', len+1);1236 host = strncat(cutstr,mnttype, sizeof(char) * len );1237 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));1238 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));1239 testpath=strchr_m(mnttype, ':');1240 args.gqa_pathp = testpath+1;1241 args.gqa_uid = uid;1242 1243 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));1244 1245 if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {1246 ret = False;1247 goto out;1248 }1249 1250 clnt->cl_auth = authunix_create_default();1251 DEBUG(9,("nfs_quotas: auth_success\n"));1252 1253 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);1254 1255 if (clnt_stat != RPC_SUCCESS) {1256 DEBUG(9,("nfs_quotas: clnt_call fail\n"));1257 ret = False;1258 goto out;1259 }1260 1261 /*1262 * gqr->status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is1263 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return1264 * something sensible.1265 */1266 1267 switch (gqr.status) {1268 case 0:1269 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", gqr.status));1270 ret = False;1271 goto out;1272 1273 case 1:1274 DEBUG(9,("nfs_quotas: Good quota data\n"));1275 D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;1276 D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;1277 D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;1278 break;1279 1280 case 2:1281 case 3:1282 D.dqb_bsoftlimit = 1;1283 D.dqb_curblocks = 1;1284 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr.status));1285 break;1286 1287 default:1288 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", gqr.status));1289 break;1290 }1291 1292 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",1293 gqr.status,1294 gqr.getquota_rslt_u.gqr_rquota.rq_bsize,1295 gqr.getquota_rslt_u.gqr_rquota.rq_active,1296 gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,1297 gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,1298 gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));1299 1300 if (D.dqb_bsoftlimit == 0)1301 D.dqb_bsoftlimit = D.dqb_bhardlimit;1302 if (D.dqb_bsoftlimit == 0)1303 return False;1304 1305 *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;1306 *dsize = D.dqb_bsoftlimit;1307 1308 if (D.dqb_curblocks == 1)1309 *bsize = DEV_BSIZE;1310 1311 if (D.dqb_curblocks > D.dqb_bsoftlimit) {1312 *dfree = 0;1313 *dsize = D.dqb_curblocks;1314 } else1315 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;1316 1317 out:1318 1319 if (clnt) {1320 if (clnt->cl_auth)1321 auth_destroy(clnt->cl_auth);1322 clnt_destroy(clnt);1323 }1324 1325 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));1326 1327 SAFE_FREE(cutstr);1328 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));1329 return ret;1330 }1331 1332 #endif1333 424 1334 425 /**************************************************************************** … … 1336 427 ****************************************************************************/ 1337 428 1338 bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize) 429 bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize, 430 uint64_t *dfree, uint64_t *dsize) 1339 431 { 1340 432 int r; 1341 433 struct dqblk D; 1342 434 uid_t euser_id; 1343 #if !defined( __FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__)435 #if !defined(AIX) 1344 436 char dev_disk[256]; 1345 437 SMB_STRUCT_STAT S; … … 1347 439 /* find the block device file */ 1348 440 1349 #ifdef HPUX1350 /* Need to set the cache flag to 1 for HPUX. Seems1351 * to have a significant performance boost when1352 * lstat calls on /dev access this function.1353 */1354 if ((sys_stat(path, &S, false)<0)1355 || (devnm(S_IFBLK, S.st_ex_dev, dev_disk, 256, 1)<0))1356 #else1357 441 if ((sys_stat(path, &S, false)<0) 1358 442 || (devnm(S_IFBLK, S.st_ex_dev, dev_disk, 256, 0)<0)) 1359 443 return (False); 1360 #endif /* ifdef HPUX */ 1361 1362 #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__) */ 444 445 #endif /* !defined(AIX) */ 1363 446 1364 447 euser_id = geteuid(); 1365 448 1366 #ifdef HPUX 1367 /* for HPUX, real uid must be same as euid to execute quotactl for euid */ 1368 save_re_uid(); 1369 if (set_re_uid() != 0) return False; 1370 1371 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); 1372 1373 restore_re_uid(); 1374 #else 1375 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) 1376 { 1377 /* FreeBSD patches from Marty Moll <martym@arbor.edu> */ 1378 gid_t egrp_id; 1379 #if defined(__FreeBSD__) || defined(__DragonFly__) 1380 SMB_DEV_T devno; 1381 struct statfs *mnts; 1382 SMB_STRUCT_STAT st; 1383 int mntsize, i; 1384 1385 if (sys_stat(path, &st, false) < 0) 1386 return False; 1387 devno = st.st_ex_dev; 1388 1389 mntsize = getmntinfo(&mnts,MNT_NOWAIT); 1390 if (mntsize <= 0) 1391 return False; 1392 1393 for (i = 0; i < mntsize; i++) { 1394 if (sys_stat(mnts[i].f_mntonname, &st, false) < 0) 1395 return False; 1396 if (st.st_ex_dev == devno) 1397 break; 1398 } 1399 if (i == mntsize) 1400 return False; 1401 #endif 1402 1403 become_root(); 1404 1405 #if defined(__FreeBSD__) || defined(__DragonFly__) 1406 if (strcmp(mnts[i].f_fstypename,"nfs") == 0) { 1407 bool retval; 1408 retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize); 1409 unbecome_root(); 1410 return retval; 1411 } 1412 #endif 1413 1414 egrp_id = getegid(); 1415 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); 1416 1417 /* As FreeBSD has group quotas, if getting the user 1418 quota fails, try getting the group instead. */ 1419 if (r) { 1420 r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D); 1421 } 1422 1423 unbecome_root(); 1424 } 1425 #elif defined(AIX) 449 #if defined(AIX) 1426 450 /* AIX has both USER and GROUP quotas: 1427 451 Get the USER quota (ohnielse@fysik.dtu.dk) */ … … 1460 484 } 1461 485 #endif /* AIX 5.3 */ 1462 #else /* ! __FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__*/486 #else /* !AIX */ 1463 487 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); 1464 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */ 1465 #endif /* HPUX */ 488 #endif /* !AIX */ 1466 489 1467 490 /* Use softlimit to determine disk space, except when it has been exceeded */ 1468 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)1469 *bsize = DEV_BSIZE;1470 #else /* !__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */1471 491 *bsize = 1024; 1472 #endif /*!__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */1473 492 1474 493 if (r) … … 1493 512 /* Use softlimit to determine disk space, except when it has been exceeded */ 1494 513 if ((D.dqb_curblocks>D.dqb_bsoftlimit) 1495 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__)1496 514 ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0)) 1497 #endif1498 515 ) { 1499 516 *dfree = 0; … … 1583 600 1584 601 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname)); 1585 if((file= sys_open(qfname, O_RDONLY,0))<0) {602 if((file=open(qfname, O_RDONLY,0))<0) { 1586 603 set_effective_uid(euser_id); 1587 604 return(False); … … 1641 658 #else /* WITH_QUOTAS */ 1642 659 1643 bool disk_quotas(const char *path,uint64_t *bsize,uint64_t *dfree,uint64_t *dsize) 660 bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize, 661 uint64_t *dfree, uint64_t *dsize) 1644 662 { 1645 663 (*bsize) = 512; /* This value should be ignored */ … … 1659 677 this file should be removed later 1660 678 */ 1661 bool disk_quotas(const char *path,uint64_t *bsize,uint64_t *dfree,uint64_t *dsize) 679 bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize, 680 uint64_t *dfree, uint64_t *dsize) 1662 681 { 1663 682 int r; … … 1668 687 1669 688 ZERO_STRUCT(D); 1670 r=sys_get_quota(path, SMB_USER_QUOTA_TYPE, id, &D);689 r = SMB_VFS_GET_QUOTA(conn, path, SMB_USER_QUOTA_TYPE, id, &D); 1671 690 1672 691 /* Use softlimit to determine disk space, except when it has been exceeded */ … … 1694 713 goto try_group_quota; 1695 714 } else { 1696 if (D.softlimit == 0) 715 if (D.softlimit == 0) { 1697 716 D.softlimit = D.hardlimit; 717 } 1698 718 *dfree = D.softlimit - D.curblocks; 1699 719 *dsize = D.softlimit; … … 1706 726 1707 727 ZERO_STRUCT(D); 1708 r=sys_get_quota(path, SMB_GROUP_QUOTA_TYPE, id, &D);728 r = SMB_VFS_GET_QUOTA(conn, path, SMB_GROUP_QUOTA_TYPE, id, &D); 1709 729 1710 730 /* Use softlimit to determine disk space, except when it has been exceeded */ … … 1732 752 return False; 1733 753 } else { 1734 if (D.softlimit == 0) 754 if (D.softlimit == 0) { 1735 755 D.softlimit = D.hardlimit; 756 } 1736 757 *dfree = D.softlimit - D.curblocks; 1737 758 *dsize = D.softlimit;
Note:
See TracChangeset
for help on using the changeset viewer.