lib/sysquotas.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    System QUOTA function wrappers
00004    Copyright (C) Stefan (metze) Metzmacher      2003
00005    
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 
00022 #include "includes.h"
00023 
00024 #undef DBGC_CLASS
00025 #define DBGC_CLASS DBGC_QUOTA
00026 
00027 #ifdef HAVE_SYS_QUOTAS
00028 
00029 #if defined(HAVE_QUOTACTL_4A) 
00030 
00031 /*#endif HAVE_QUOTACTL_4A */
00032 #elif defined(HAVE_QUOTACTL_4B)
00033 
00034 #error HAVE_QUOTACTL_4B not implemeted
00035 
00036 /*#endif HAVE_QUOTACTL_4B */
00037 #elif defined(HAVE_QUOTACTL_3)
00038 
00039 #error HAVE_QUOTACTL_3 not implemented
00040 
00041 /* #endif  HAVE_QUOTACTL_3 */
00042 #else /* NO_QUOTACTL_USED */
00043 
00044 #endif /* NO_QUOTACTL_USED */
00045 
00046 #ifdef HAVE_MNTENT
00047 static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
00048 {
00049         int ret = -1;
00050         SMB_STRUCT_STAT S;
00051         FILE *fp;
00052         struct mntent *mnt;
00053         SMB_DEV_T devno;
00054 
00055         /* find the block device file */
00056 
00057         if (!path||!mntpath||!bdev||!fs)
00058                 smb_panic("sys_path_to_bdev: called with NULL pointer");
00059 
00060         (*mntpath) = NULL;
00061         (*bdev) = NULL;
00062         (*fs) = NULL;
00063         
00064         if ( sys_stat(path, &S) == -1 )
00065                 return (-1);
00066 
00067         devno = S.st_dev ;
00068 
00069         fp = setmntent(MOUNTED,"r");
00070         if (fp == NULL) {
00071                 return -1;
00072         }
00073   
00074         while ((mnt = getmntent(fp))) {
00075                 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
00076                         continue ;
00077 
00078                 if (S.st_dev == devno) {
00079                         (*mntpath) = SMB_STRDUP(mnt->mnt_dir);
00080                         (*bdev) = SMB_STRDUP(mnt->mnt_fsname);
00081                         (*fs)   = SMB_STRDUP(mnt->mnt_type);
00082                         if ((*mntpath)&&(*bdev)&&(*fs)) {
00083                                 ret = 0;
00084                         } else {
00085                                 SAFE_FREE(*mntpath);
00086                                 SAFE_FREE(*bdev);
00087                                 SAFE_FREE(*fs);
00088                                 ret = -1;
00089                         }
00090 
00091                         break;
00092                 }
00093         }
00094 
00095         endmntent(fp) ;
00096 
00097         return ret;
00098 }
00099 /* #endif HAVE_MNTENT */
00100 #elif defined(HAVE_DEVNM)
00101 
00102 /* we have this on HPUX, ... */
00103 static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
00104 {
00105         int ret = -1;
00106         char dev_disk[256];
00107         SMB_STRUCT_STAT S;
00108 
00109         if (!path||!mntpath||!bdev||!fs)
00110                 smb_panic("sys_path_to_bdev: called with NULL pointer");
00111 
00112         (*mntpath) = NULL;
00113         (*bdev) = NULL;
00114         (*fs) = NULL;
00115         
00116         /* find the block device file */
00117 
00118         if ((ret=sys_stat(path, &S))!=0) {
00119                 return ret;
00120         }
00121         
00122         if ((ret=devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1))!=0) {
00123                 return ret;     
00124         }
00125 
00126         /* we should get the mntpath right...
00127          * but I don't know how
00128          * --metze
00129          */
00130         (*mntpath) = SMB_STRDUP(path);
00131         (*bdev) = SMB_STRDUP(dev_disk);
00132         if ((*mntpath)&&(*bdev)) {
00133                 ret = 0;
00134         } else {
00135                 SAFE_FREE(*mntpath);
00136                 SAFE_FREE(*bdev);
00137                 ret = -1;
00138         }       
00139         
00140         
00141         return ret;     
00142 }
00143 
00144 /* #endif HAVE_DEVNM */
00145 #else
00146 /* we should fake this up...*/
00147 static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
00148 {
00149         int ret = -1;
00150 
00151         if (!path||!mntpath||!bdev||!fs)
00152                 smb_panic("sys_path_to_bdev: called with NULL pointer");
00153 
00154         (*mntpath) = NULL;
00155         (*bdev) = NULL;
00156         (*fs) = NULL;
00157         
00158         (*mntpath) = SMB_STRDUP(path);
00159         if (*mntpath) {
00160                 ret = 0;
00161         } else {
00162                 SAFE_FREE(*mntpath);
00163                 ret = -1;
00164         }
00165 
00166         return ret;
00167 }
00168 #endif
00169 
00170 /*********************************************************************
00171  Now the list of all filesystem specific quota systems we have found
00172 **********************************************************************/
00173 static struct {
00174         const char *name;
00175         int (*get_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
00176         int (*set_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
00177 } sys_quota_backends[] = {
00178 #ifdef HAVE_XFS_QUOTAS
00179         {"xfs", sys_get_xfs_quota,      sys_set_xfs_quota},
00180 #endif /* HAVE_XFS_QUOTAS */
00181         {NULL,  NULL,                   NULL}   
00182 };
00183 
00184 static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
00185 {
00186         const char *get_quota_command;
00187         char **lines = NULL;
00188         
00189         get_quota_command = lp_get_quota_command();
00190         if (get_quota_command && *get_quota_command) {
00191                 const char *p;
00192                 char *p2;
00193                 pstring syscmd;
00194                 int _id = -1;
00195 
00196                 switch(qtype) {
00197                         case SMB_USER_QUOTA_TYPE:
00198                         case SMB_USER_FS_QUOTA_TYPE:
00199                                 _id = id.uid;
00200                                 break;
00201                         case SMB_GROUP_QUOTA_TYPE:
00202                         case SMB_GROUP_FS_QUOTA_TYPE:
00203                                 _id = id.gid;
00204                                 break;
00205                         default:
00206                                 DEBUG(0,("invalid quota type.\n"));
00207                                 return -1;
00208                 }
00209 
00210                 slprintf(syscmd, sizeof(syscmd)-1, 
00211                         "%s \"%s\" %d %d", 
00212                         get_quota_command, path, qtype, _id);
00213 
00214                 DEBUG (3, ("get_quota: Running command %s\n", syscmd));
00215 
00216                 lines = file_lines_pload(syscmd, NULL);
00217                 if (lines) {
00218                         char *line = lines[0];
00219 
00220                         DEBUG (3, ("Read output from get_quota, \"%s\"\n", line));
00221 
00222                         /* we need to deal with long long unsigned here, if supported */
00223 
00224                         dp->qflags = (enum SMB_QUOTA_TYPE)strtoul(line, &p2, 10);
00225                         p = p2;
00226                         while (p && *p && isspace(*p)) {
00227                                 p++;
00228                         }
00229 
00230                         if (p && *p) {
00231                                 dp->curblocks = STR_TO_SMB_BIG_UINT(p, &p);
00232                         } else {
00233                                 goto invalid_param;
00234                         }
00235 
00236                         while (p && *p && isspace(*p)) {
00237                                 p++;
00238                         }
00239 
00240                         if (p && *p) {
00241                                 dp->softlimit = STR_TO_SMB_BIG_UINT(p, &p);
00242                         } else {
00243                                 goto invalid_param;
00244                         }
00245 
00246                         while (p && *p && isspace(*p)) {
00247                                 p++;
00248                         }
00249 
00250                         if (p && *p) {
00251                                 dp->hardlimit = STR_TO_SMB_BIG_UINT(p, &p);
00252                         } else {
00253                                 goto invalid_param;
00254                         }
00255 
00256                         while (p && *p && isspace(*p)) {
00257                                 p++;
00258                         }
00259 
00260                         if (p && *p) {
00261                                 dp->curinodes = STR_TO_SMB_BIG_UINT(p, &p);
00262                         } else {
00263                                 goto invalid_param;
00264                         }
00265 
00266                         while (p && *p && isspace(*p)) {
00267                                 p++;
00268                         }
00269 
00270                         if (p && *p) {
00271                                 dp->isoftlimit = STR_TO_SMB_BIG_UINT(p, &p);
00272                         } else {
00273                                 goto invalid_param;
00274                         }
00275 
00276                         while (p && *p && isspace(*p)) {
00277                                 p++;
00278                         }
00279 
00280                         if (p && *p) {
00281                                 dp->ihardlimit = STR_TO_SMB_BIG_UINT(p, &p);
00282                         } else {
00283                                 goto invalid_param;     
00284                         }
00285 
00286                         while (p && *p && isspace(*p)) {
00287                                 p++;
00288                         }
00289 
00290                         if (p && *p) {
00291                                 dp->bsize = STR_TO_SMB_BIG_UINT(p, NULL);
00292                         } else {
00293                                 dp->bsize = 1024;
00294                         }
00295 
00296                         file_lines_free(lines);
00297                         lines = NULL;
00298 
00299                         DEBUG (3, ("Parsed output of get_quota, ...\n"));
00300 
00301 #ifdef LARGE_SMB_OFF_T
00302                         DEBUGADD (5,( 
00303                                 "qflags:%u curblocks:%llu softlimit:%llu hardlimit:%llu\n"
00304                                 "curinodes:%llu isoftlimit:%llu ihardlimit:%llu bsize:%llu\n", 
00305                                 dp->qflags,(long long unsigned)dp->curblocks,
00306                                 (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit,
00307                                 (long long unsigned)dp->curinodes,
00308                                 (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit,
00309                                 (long long unsigned)dp->bsize));
00310 #else /* LARGE_SMB_OFF_T */
00311                         DEBUGADD (5,( 
00312                                 "qflags:%u curblocks:%lu softlimit:%lu hardlimit:%lu\n"
00313                                 "curinodes:%lu isoftlimit:%lu ihardlimit:%lu bsize:%lu\n", 
00314                                 dp->qflags,(long unsigned)dp->curblocks,
00315                                 (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit,
00316                                 (long unsigned)dp->curinodes,
00317                                 (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit,
00318                                 (long unsigned)dp->bsize));
00319 #endif /* LARGE_SMB_OFF_T */
00320                         return 0;
00321                 }
00322 
00323                 DEBUG (0, ("get_quota_command failed!\n"));
00324                 return -1;
00325         }
00326 
00327         errno = ENOSYS;
00328         return -1;
00329         
00330 invalid_param:
00331 
00332         file_lines_free(lines);
00333         DEBUG(0,("The output of get_quota_command is invalid!\n"));
00334         return -1;
00335 }
00336 
00337 static int command_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
00338 {
00339         const char *set_quota_command;
00340         
00341         set_quota_command = lp_set_quota_command();
00342         if (set_quota_command && *set_quota_command) {
00343                 char **lines;
00344                 pstring syscmd;
00345                 int _id = -1;
00346 
00347                 switch(qtype) {
00348                         case SMB_USER_QUOTA_TYPE:
00349                         case SMB_USER_FS_QUOTA_TYPE:
00350                                 _id = id.uid;
00351                                 break;
00352                         case SMB_GROUP_QUOTA_TYPE:
00353                         case SMB_GROUP_FS_QUOTA_TYPE:
00354                                 _id = id.gid;
00355                                 break;
00356                         default:
00357                                 return -1;
00358                 }
00359 
00360 #ifdef LARGE_SMB_OFF_T
00361                 slprintf(syscmd, sizeof(syscmd)-1, 
00362                         "%s \"%s\" %d %d "
00363                         "%u %llu %llu "
00364                         "%llu %llu %llu ", 
00365                         set_quota_command, path, qtype, _id, dp->qflags,
00366                         (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit,
00367                         (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit,
00368                         (long long unsigned)dp->bsize);
00369 #else /* LARGE_SMB_OFF_T */
00370                 slprintf(syscmd, sizeof(syscmd)-1, 
00371                         "%s \"%s\" %d %d "
00372                         "%u %lu %lu "
00373                         "%lu %lu %lu ", 
00374                         set_quota_command, path, qtype, _id, dp->qflags,
00375                         (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit,
00376                         (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit,
00377                         (long unsigned)dp->bsize);
00378 #endif /* LARGE_SMB_OFF_T */
00379 
00380 
00381 
00382                 DEBUG (3, ("get_quota: Running command %s\n", syscmd));
00383 
00384                 lines = file_lines_pload(syscmd, NULL);
00385                 if (lines) {
00386                         char *line = lines[0];
00387 
00388                         DEBUG (3, ("Read output from set_quota, \"%s\"\n", line));
00389 
00390                         file_lines_free(lines);
00391                         
00392                         return 0;
00393                 }
00394                 DEBUG (0, ("set_quota_command failed!\n"));
00395                 return -1;
00396         }
00397 
00398         errno = ENOSYS;
00399         return -1;
00400 }
00401 
00402 int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
00403 {
00404         int ret = -1;
00405         int i;
00406         BOOL ready = False;
00407         char *mntpath = NULL;
00408         char *bdev = NULL;
00409         char *fs = NULL;
00410 
00411         if (!path||!dp)
00412                 smb_panic("sys_get_quota: called with NULL pointer");
00413 
00414         if (command_get_quota(path, qtype, id, dp)==0) {        
00415                 return 0;
00416         } else if (errno != ENOSYS) {
00417                 return -1;
00418         }
00419 
00420         if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) {
00421                 DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path));
00422                 return ret;
00423         }
00424 
00425         errno = 0;
00426         DEBUG(10,("sys_get_quota() uid(%u, %u)\n", (unsigned)getuid(), (unsigned)geteuid()));
00427 
00428         for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].get_quota);i++) {
00429                 if (strcmp(fs,sys_quota_backends[i].name)==0) {
00430                         ret = sys_quota_backends[i].get_quota(mntpath, bdev, qtype, id, dp);
00431                         if (ret!=0) {
00432                                 DEBUG(3,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
00433                                         fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
00434                         } else {
00435                                 DEBUG(10,("sys_get_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
00436                                         fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
00437                         }
00438                         ready = True;
00439                         break;  
00440                 }               
00441         }
00442 
00443         if (!ready) {
00444                 /* use the default vfs quota functions */
00445                 ret=sys_get_vfs_quota(mntpath, bdev, qtype, id, dp);
00446                 if (ret!=0) {
00447                         DEBUG(3,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s\n",
00448                                 "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
00449                 } else {
00450                         DEBUG(10,("sys_get_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
00451                                 "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
00452                 }
00453         }
00454 
00455         SAFE_FREE(mntpath);
00456         SAFE_FREE(bdev);
00457         SAFE_FREE(fs);
00458 
00459         if ((ret!=0)&& (errno == EDQUOT)) {
00460                 DEBUG(10,("sys_get_quota() warning over quota!\n"));
00461                 return 0;
00462         }
00463 
00464         return ret;
00465 }
00466 
00467 int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
00468 {
00469         int ret = -1;
00470         int i;
00471         BOOL ready = False;
00472         char *mntpath = NULL;
00473         char *bdev = NULL;
00474         char *fs = NULL;
00475 
00476         /* find the block device file */
00477 
00478         if (!path||!dp)
00479                 smb_panic("get_smb_quota: called with NULL pointer");
00480 
00481         if (command_set_quota(path, qtype, id, dp)==0) {        
00482                 return 0;
00483         } else if (errno != ENOSYS) {
00484                 return -1;
00485         }
00486 
00487         if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) {
00488                 DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path));
00489                 return ret;
00490         }
00491 
00492         errno = 0;
00493         DEBUG(10,("sys_set_quota() uid(%u, %u)\n", (unsigned)getuid(), (unsigned)geteuid())); 
00494 
00495         for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].set_quota);i++) {
00496                 if (strcmp(fs,sys_quota_backends[i].name)==0) {
00497                         ret = sys_quota_backends[i].set_quota(mntpath, bdev, qtype, id, dp);
00498                         if (ret!=0) {
00499                                 DEBUG(3,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
00500                                         fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
00501                         } else {
00502                                 DEBUG(10,("sys_set_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
00503                                         fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
00504                         }
00505                         ready = True;
00506                         break;
00507                 }               
00508         }
00509 
00510         if (!ready) {
00511                 /* use the default vfs quota functions */
00512                 ret=sys_set_vfs_quota(mntpath, bdev, qtype, id, dp);
00513                 if (ret!=0) {
00514                         DEBUG(3,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
00515                                 "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
00516                 } else {
00517                         DEBUG(10,("sys_set_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
00518                                 "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
00519                 }
00520         }
00521 
00522         SAFE_FREE(mntpath);
00523         SAFE_FREE(bdev);
00524         SAFE_FREE(fs);
00525 
00526         if ((ret!=0)&& (errno == EDQUOT)) {
00527                 DEBUG(10,("sys_set_quota() warning over quota!\n"));
00528                 return 0;
00529         }
00530 
00531         return ret;             
00532 }
00533 
00534 #else /* HAVE_SYS_QUOTAS */
00535  void dummy_sysquotas_c(void);
00536 
00537  void dummy_sysquotas_c(void)
00538 {
00539         return;
00540 }
00541 #endif /* HAVE_SYS_QUOTAS */
00542 

Sambaに対してSat Aug 29 21:22:59 2009に生成されました。  doxygen 1.4.7