root/source3/lib/sysquotas.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sys_path_to_bdev
  2. sys_path_to_bdev
  3. sys_path_to_bdev
  4. command_get_quota
  5. command_set_quota
  6. sys_get_quota
  7. sys_set_quota
  8. dummy_sysquotas_c

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    System QUOTA function wrappers
   4    Copyright (C) Stefan (metze) Metzmacher      2003
   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 #include "includes.h"
  22 
  23 #undef DBGC_CLASS
  24 #define DBGC_CLASS DBGC_QUOTA
  25 
  26 #ifdef HAVE_SYS_QUOTAS
  27 
  28 #if defined(HAVE_QUOTACTL_4A) 
  29 
  30 /*#endif HAVE_QUOTACTL_4A */
  31 #elif defined(HAVE_QUOTACTL_4B)
  32 
  33 #error HAVE_QUOTACTL_4B not implemeted
  34 
  35 /*#endif HAVE_QUOTACTL_4B */
  36 #elif defined(HAVE_QUOTACTL_3)
  37 
  38 #error HAVE_QUOTACTL_3 not implemented
  39 
  40 /* #endif  HAVE_QUOTACTL_3 */
  41 #else /* NO_QUOTACTL_USED */
  42 
  43 #endif /* NO_QUOTACTL_USED */
  44 
  45 #ifdef HAVE_MNTENT
  46 static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
     /* [<][>][^][v][top][bottom][index][help] */
  47 {
  48         int ret = -1;
  49         SMB_STRUCT_STAT S;
  50         FILE *fp;
  51         struct mntent *mnt;
  52         SMB_DEV_T devno;
  53 
  54         /* find the block device file */
  55 
  56         if (!path||!mntpath||!bdev||!fs)
  57                 smb_panic("sys_path_to_bdev: called with NULL pointer");
  58 
  59         (*mntpath) = NULL;
  60         (*bdev) = NULL;
  61         (*fs) = NULL;
  62         
  63         if ( sys_stat(path, &S) == -1 )
  64                 return (-1);
  65 
  66         devno = S.st_dev ;
  67 
  68         fp = setmntent(MOUNTED,"r");
  69         if (fp == NULL) {
  70                 return -1;
  71         }
  72   
  73         while ((mnt = getmntent(fp))) {
  74                 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
  75                         continue ;
  76 
  77                 if (S.st_dev == devno) {
  78                         (*mntpath) = SMB_STRDUP(mnt->mnt_dir);
  79                         (*bdev) = SMB_STRDUP(mnt->mnt_fsname);
  80                         (*fs)   = SMB_STRDUP(mnt->mnt_type);
  81                         if ((*mntpath)&&(*bdev)&&(*fs)) {
  82                                 ret = 0;
  83                         } else {
  84                                 SAFE_FREE(*mntpath);
  85                                 SAFE_FREE(*bdev);
  86                                 SAFE_FREE(*fs);
  87                                 ret = -1;
  88                         }
  89 
  90                         break;
  91                 }
  92         }
  93 
  94         endmntent(fp) ;
  95 
  96         return ret;
  97 }
  98 /* #endif HAVE_MNTENT */
  99 #elif defined(HAVE_DEVNM)
 100 
 101 /* we have this on HPUX, ... */
 102 static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
     /* [<][>][^][v][top][bottom][index][help] */
 103 {
 104         int ret = -1;
 105         char dev_disk[256];
 106         SMB_STRUCT_STAT S;
 107 
 108         if (!path||!mntpath||!bdev||!fs)
 109                 smb_panic("sys_path_to_bdev: called with NULL pointer");
 110 
 111         (*mntpath) = NULL;
 112         (*bdev) = NULL;
 113         (*fs) = NULL;
 114         
 115         /* find the block device file */
 116 
 117         if ((ret=sys_stat(path, &S))!=0) {
 118                 return ret;
 119         }
 120         
 121         if ((ret=devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1))!=0) {
 122                 return ret;     
 123         }
 124 
 125         /* we should get the mntpath right...
 126          * but I don't know how
 127          * --metze
 128          */
 129         (*mntpath) = SMB_STRDUP(path);
 130         (*bdev) = SMB_STRDUP(dev_disk);
 131         if ((*mntpath)&&(*bdev)) {
 132                 ret = 0;
 133         } else {
 134                 SAFE_FREE(*mntpath);
 135                 SAFE_FREE(*bdev);
 136                 ret = -1;
 137         }       
 138         
 139         
 140         return ret;     
 141 }
 142 
 143 /* #endif HAVE_DEVNM */
 144 #else
 145 /* we should fake this up...*/
 146 static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
     /* [<][>][^][v][top][bottom][index][help] */
 147 {
 148         int ret = -1;
 149 
 150         if (!path||!mntpath||!bdev||!fs)
 151                 smb_panic("sys_path_to_bdev: called with NULL pointer");
 152 
 153         (*mntpath) = NULL;
 154         (*bdev) = NULL;
 155         (*fs) = NULL;
 156         
 157         (*mntpath) = SMB_STRDUP(path);
 158         if (*mntpath) {
 159                 ret = 0;
 160         } else {
 161                 SAFE_FREE(*mntpath);
 162                 ret = -1;
 163         }
 164 
 165         return ret;
 166 }
 167 #endif
 168 
 169 /*********************************************************************
 170  Now the list of all filesystem specific quota systems we have found
 171 **********************************************************************/
 172 static struct {
 173         const char *name;
 174         int (*get_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
 175         int (*set_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
 176 } sys_quota_backends[] = {
 177 #ifdef HAVE_XFS_QUOTAS
 178         {"xfs", sys_get_xfs_quota,      sys_set_xfs_quota},
 179 #endif /* HAVE_XFS_QUOTAS */
 180         {NULL,  NULL,                   NULL}
 181 };
 182 
 183 static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
     /* [<][>][^][v][top][bottom][index][help] */
 184 {
 185         const char *get_quota_command;
 186         char **lines = NULL;
 187 
 188         get_quota_command = lp_get_quota_command();
 189         if (get_quota_command && *get_quota_command) {
 190                 const char *p;
 191                 char *p2;
 192                 char *syscmd = NULL;
 193                 int _id = -1;
 194 
 195                 switch(qtype) {
 196                         case SMB_USER_QUOTA_TYPE:
 197                         case SMB_USER_FS_QUOTA_TYPE:
 198                                 _id = id.uid;
 199                                 break;
 200                         case SMB_GROUP_QUOTA_TYPE:
 201                         case SMB_GROUP_FS_QUOTA_TYPE:
 202                                 _id = id.gid;
 203                                 break;
 204                         default:
 205                                 DEBUG(0,("invalid quota type.\n"));
 206                                 return -1;
 207                 }
 208 
 209                 if (asprintf(&syscmd, "%s \"%s\" %d %d",
 210                         get_quota_command, path, qtype, _id) < 0) {
 211                         return -1;
 212                 }
 213 
 214                 DEBUG (3, ("get_quota: Running command %s\n", syscmd));
 215 
 216                 lines = file_lines_pload(syscmd, NULL);
 217                 SAFE_FREE(syscmd);
 218 
 219                 if (lines) {
 220                         char *line = lines[0];
 221 
 222                         DEBUG (3, ("Read output from get_quota, \"%s\"\n", line));
 223 
 224                         /* we need to deal with long long unsigned here, if supported */
 225 
 226                         dp->qflags = (enum SMB_QUOTA_TYPE)strtoul(line, &p2, 10);
 227                         p = p2;
 228                         while (p && *p && isspace(*p)) {
 229                                 p++;
 230                         }
 231 
 232                         if (p && *p) {
 233                                 dp->curblocks = STR_TO_SMB_BIG_UINT(p, &p);
 234                         } else {
 235                                 goto invalid_param;
 236                         }
 237 
 238                         while (p && *p && isspace(*p)) {
 239                                 p++;
 240                         }
 241 
 242                         if (p && *p) {
 243                                 dp->softlimit = STR_TO_SMB_BIG_UINT(p, &p);
 244                         } else {
 245                                 goto invalid_param;
 246                         }
 247 
 248                         while (p && *p && isspace(*p)) {
 249                                 p++;
 250                         }
 251 
 252                         if (p && *p) {
 253                                 dp->hardlimit = STR_TO_SMB_BIG_UINT(p, &p);
 254                         } else {
 255                                 goto invalid_param;
 256                         }
 257 
 258                         while (p && *p && isspace(*p)) {
 259                                 p++;
 260                         }
 261 
 262                         if (p && *p) {
 263                                 dp->curinodes = STR_TO_SMB_BIG_UINT(p, &p);
 264                         } else {
 265                                 goto invalid_param;
 266                         }
 267 
 268                         while (p && *p && isspace(*p)) {
 269                                 p++;
 270                         }
 271 
 272                         if (p && *p) {
 273                                 dp->isoftlimit = STR_TO_SMB_BIG_UINT(p, &p);
 274                         } else {
 275                                 goto invalid_param;
 276                         }
 277 
 278                         while (p && *p && isspace(*p)) {
 279                                 p++;
 280                         }
 281 
 282                         if (p && *p) {
 283                                 dp->ihardlimit = STR_TO_SMB_BIG_UINT(p, &p);
 284                         } else {
 285                                 goto invalid_param;     
 286                         }
 287 
 288                         while (p && *p && isspace(*p)) {
 289                                 p++;
 290                         }
 291 
 292                         if (p && *p) {
 293                                 dp->bsize = STR_TO_SMB_BIG_UINT(p, NULL);
 294                         } else {
 295                                 dp->bsize = 1024;
 296                         }
 297 
 298                         TALLOC_FREE(lines);
 299                         lines = NULL;
 300 
 301                         DEBUG (3, ("Parsed output of get_quota, ...\n"));
 302 
 303 #ifdef LARGE_SMB_OFF_T
 304                         DEBUGADD (5,( 
 305                                 "qflags:%u curblocks:%llu softlimit:%llu hardlimit:%llu\n"
 306                                 "curinodes:%llu isoftlimit:%llu ihardlimit:%llu bsize:%llu\n", 
 307                                 dp->qflags,(long long unsigned)dp->curblocks,
 308                                 (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit,
 309                                 (long long unsigned)dp->curinodes,
 310                                 (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit,
 311                                 (long long unsigned)dp->bsize));
 312 #else /* LARGE_SMB_OFF_T */
 313                         DEBUGADD (5,( 
 314                                 "qflags:%u curblocks:%lu softlimit:%lu hardlimit:%lu\n"
 315                                 "curinodes:%lu isoftlimit:%lu ihardlimit:%lu bsize:%lu\n", 
 316                                 dp->qflags,(long unsigned)dp->curblocks,
 317                                 (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit,
 318                                 (long unsigned)dp->curinodes,
 319                                 (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit,
 320                                 (long unsigned)dp->bsize));
 321 #endif /* LARGE_SMB_OFF_T */
 322                         return 0;
 323                 }
 324 
 325                 DEBUG (0, ("get_quota_command failed!\n"));
 326                 return -1;
 327         }
 328 
 329         errno = ENOSYS;
 330         return -1;
 331 
 332 invalid_param:
 333 
 334         TALLOC_FREE(lines);
 335         DEBUG(0,("The output of get_quota_command is invalid!\n"));
 336         return -1;
 337 }
 338 
 339 static int command_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
     /* [<][>][^][v][top][bottom][index][help] */
 340 {
 341         const char *set_quota_command;
 342 
 343         set_quota_command = lp_set_quota_command();
 344         if (set_quota_command && *set_quota_command) {
 345                 char **lines = NULL;
 346                 char *syscmd = NULL;
 347                 int _id = -1;
 348 
 349                 switch(qtype) {
 350                         case SMB_USER_QUOTA_TYPE:
 351                         case SMB_USER_FS_QUOTA_TYPE:
 352                                 _id = id.uid;
 353                                 break;
 354                         case SMB_GROUP_QUOTA_TYPE:
 355                         case SMB_GROUP_FS_QUOTA_TYPE:
 356                                 _id = id.gid;
 357                                 break;
 358                         default:
 359                                 return -1;
 360                 }
 361 
 362 #ifdef LARGE_SMB_OFF_T
 363                 if (asprintf(&syscmd,
 364                         "%s \"%s\" %d %d "
 365                         "%u %llu %llu "
 366                         "%llu %llu %llu ",
 367                         set_quota_command, path, qtype, _id, dp->qflags,
 368                         (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit,
 369                         (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit,
 370                         (long long unsigned)dp->bsize) < 0) {
 371                         return -1;
 372                 }
 373 #else /* LARGE_SMB_OFF_T */
 374                 if (asprintf(&syscmd,
 375                         "%s \"%s\" %d %d "
 376                         "%u %lu %lu "
 377                         "%lu %lu %lu ",
 378                         set_quota_command, path, qtype, _id, dp->qflags,
 379                         (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit,
 380                         (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit,
 381                         (long unsigned)dp->bsize) < 0) {
 382                         return -1;
 383                 }
 384 #endif /* LARGE_SMB_OFF_T */
 385 
 386                 DEBUG (3, ("get_quota: Running command %s\n", syscmd));
 387 
 388                 lines = file_lines_pload(syscmd, NULL);
 389                 SAFE_FREE(syscmd);
 390                 if (lines) {
 391                         char *line = lines[0];
 392 
 393                         DEBUG (3, ("Read output from set_quota, \"%s\"\n", line));
 394 
 395                         TALLOC_FREE(lines);
 396 
 397                         return 0;
 398                 }
 399                 DEBUG (0, ("set_quota_command failed!\n"));
 400                 return -1;
 401         }
 402 
 403         errno = ENOSYS;
 404         return -1;
 405 }
 406 
 407 int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
     /* [<][>][^][v][top][bottom][index][help] */
 408 {
 409         int ret = -1;
 410         int i;
 411         bool ready = False;
 412         char *mntpath = NULL;
 413         char *bdev = NULL;
 414         char *fs = NULL;
 415 
 416         if (!path||!dp)
 417                 smb_panic("sys_get_quota: called with NULL pointer");
 418 
 419         if (command_get_quota(path, qtype, id, dp)==0) {        
 420                 return 0;
 421         } else if (errno != ENOSYS) {
 422                 return -1;
 423         }
 424 
 425         if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) {
 426                 DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path));
 427                 return ret;
 428         }
 429 
 430         errno = 0;
 431         DEBUG(10,("sys_get_quota() uid(%u, %u)\n", (unsigned)getuid(), (unsigned)geteuid()));
 432 
 433         for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].get_quota);i++) {
 434                 if (strcmp(fs,sys_quota_backends[i].name)==0) {
 435                         ret = sys_quota_backends[i].get_quota(mntpath, bdev, qtype, id, dp);
 436                         if (ret!=0) {
 437                                 DEBUG(3,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
 438                                         fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
 439                         } else {
 440                                 DEBUG(10,("sys_get_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
 441                                         fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
 442                         }
 443                         ready = True;
 444                         break;  
 445                 }               
 446         }
 447 
 448         if (!ready) {
 449                 /* use the default vfs quota functions */
 450                 ret=sys_get_vfs_quota(mntpath, bdev, qtype, id, dp);
 451                 if (ret!=0) {
 452                         DEBUG(3,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s\n",
 453                                 "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
 454                 } else {
 455                         DEBUG(10,("sys_get_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
 456                                 "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
 457                 }
 458         }
 459 
 460         SAFE_FREE(mntpath);
 461         SAFE_FREE(bdev);
 462         SAFE_FREE(fs);
 463 
 464         if ((ret!=0)&& (errno == EDQUOT)) {
 465                 DEBUG(10,("sys_get_quota() warning over quota!\n"));
 466                 return 0;
 467         }
 468 
 469         return ret;
 470 }
 471 
 472 int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
     /* [<][>][^][v][top][bottom][index][help] */
 473 {
 474         int ret = -1;
 475         int i;
 476         bool ready = False;
 477         char *mntpath = NULL;
 478         char *bdev = NULL;
 479         char *fs = NULL;
 480 
 481         /* find the block device file */
 482 
 483         if (!path||!dp)
 484                 smb_panic("get_smb_quota: called with NULL pointer");
 485 
 486         if (command_set_quota(path, qtype, id, dp)==0) {        
 487                 return 0;
 488         } else if (errno != ENOSYS) {
 489                 return -1;
 490         }
 491 
 492         if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) {
 493                 DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path));
 494                 return ret;
 495         }
 496 
 497         errno = 0;
 498         DEBUG(10,("sys_set_quota() uid(%u, %u)\n", (unsigned)getuid(), (unsigned)geteuid())); 
 499 
 500         for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].set_quota);i++) {
 501                 if (strcmp(fs,sys_quota_backends[i].name)==0) {
 502                         ret = sys_quota_backends[i].set_quota(mntpath, bdev, qtype, id, dp);
 503                         if (ret!=0) {
 504                                 DEBUG(3,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
 505                                         fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
 506                         } else {
 507                                 DEBUG(10,("sys_set_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
 508                                         fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
 509                         }
 510                         ready = True;
 511                         break;
 512                 }               
 513         }
 514 
 515         if (!ready) {
 516                 /* use the default vfs quota functions */
 517                 ret=sys_set_vfs_quota(mntpath, bdev, qtype, id, dp);
 518                 if (ret!=0) {
 519                         DEBUG(3,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
 520                                 "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
 521                 } else {
 522                         DEBUG(10,("sys_set_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
 523                                 "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
 524                 }
 525         }
 526 
 527         SAFE_FREE(mntpath);
 528         SAFE_FREE(bdev);
 529         SAFE_FREE(fs);
 530 
 531         if ((ret!=0)&& (errno == EDQUOT)) {
 532                 DEBUG(10,("sys_set_quota() warning over quota!\n"));
 533                 return 0;
 534         }
 535 
 536         return ret;             
 537 }
 538 
 539 #else /* HAVE_SYS_QUOTAS */
 540  void dummy_sysquotas_c(void);
 541 
 542  void dummy_sysquotas_c(void)
     /* [<][>][^][v][top][bottom][index][help] */
 543 {
 544         return;
 545 }
 546 #endif /* HAVE_SYS_QUOTAS */
 547 

/* [<][>][^][v][top][bottom][index][help] */