s3:smbd: add a nfs backend for sysquotas.
[amitay/samba.git] / source3 / lib / sysquotas.c
index 6883444e005d6d3b47d43508ba8126321ba131bb..6abafbd768c3542a40d24fd29456d3a156c11659 100644 (file)
@@ -5,7 +5,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 
 #include "includes.h"
 
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_QUOTA
+
 #ifdef HAVE_SYS_QUOTAS
 
 #if defined(HAVE_QUOTACTL_4A) 
@@ -58,21 +60,24 @@ static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char
        (*bdev) = NULL;
        (*fs) = NULL;
        
-       if ( sys_stat(path, &S) == -1 )
+       if ( sys_stat(path, &S, false) == -1 )
                return (-1);
 
-       devno = S.st_dev ;
+       devno = S.st_ex_dev ;
 
        fp = setmntent(MOUNTED,"r");
+       if (fp == NULL) {
+               return -1;
+       }
   
        while ((mnt = getmntent(fp))) {
-               if ( sys_stat(mnt->mnt_dir,&S) == -1 )
+               if ( sys_stat(mnt->mnt_dir, &S, false) == -1 )
                        continue ;
 
-               if (S.st_dev == devno) {
-                       (*mntpath) = strdup(mnt->mnt_dir);
-                       (*bdev) = strdup(mnt->mnt_fsname);
-                       (*fs)   = strdup(mnt->mnt_type);
+               if (S.st_ex_dev == devno) {
+                       (*mntpath) = SMB_STRDUP(mnt->mnt_dir);
+                       (*bdev) = SMB_STRDUP(mnt->mnt_fsname);
+                       (*fs)   = SMB_STRDUP(mnt->mnt_type);
                        if ((*mntpath)&&(*bdev)&&(*fs)) {
                                ret = 0;
                        } else {
@@ -109,11 +114,11 @@ static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char
        
        /* find the block device file */
 
-       if ((ret=sys_stat(path, &S))!=0) {
+       if ((ret=sys_stat(path, &S, false))!=0) {
                return ret;
        }
        
-       if ((ret=devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1))!=0) {
+       if ((ret=devnm(S_IFBLK, S.st_ex_dev, dev_disk, 256, 1))!=0) {
                return ret;     
        }
 
@@ -121,8 +126,8 @@ static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char
         * but I don't know how
         * --metze
         */
-       (*mntpath) = strdup(path);
-       (*bdev) = strdup(dev_disk);
+       (*mntpath) = SMB_STRDUP(path);
+       (*bdev) = SMB_STRDUP(dev_disk);
        if ((*mntpath)&&(*bdev)) {
                ret = 0;
        } else {
@@ -149,7 +154,7 @@ static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char
        (*bdev) = NULL;
        (*fs) = NULL;
        
-       (*mntpath) = strdup(path);
+       (*mntpath) = SMB_STRDUP(path);
        if (*mntpath) {
                ret = 0;
        } else {
@@ -169,22 +174,25 @@ static struct {
        int (*get_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
        int (*set_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
 } sys_quota_backends[] = {
-#ifdef HAVE_XFS_QUOTA
+#ifdef HAVE_XFS_QUOTAS
        {"xfs", sys_get_xfs_quota,      sys_set_xfs_quota},
-#endif /* HAVE_XFS_QUOTA */
-       {NULL,  NULL,                   NULL}   
+#endif /* HAVE_XFS_QUOTAS */
+#ifdef HAVE_NFS_QUOTAS
+       {"nfs", sys_get_nfs_quota,      sys_set_nfs_quota},
+#endif /* HAVE_NFS_QUOTAS */
+       {NULL,  NULL,                   NULL}
 };
 
 static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
 {
        const char *get_quota_command;
-       
+       char **lines = NULL;
+
        get_quota_command = lp_get_quota_command();
        if (get_quota_command && *get_quota_command) {
                const char *p;
                char *p2;
-               char **lines;
-               pstring syscmd;
+               char *syscmd = NULL;
                int _id = -1;
 
                switch(qtype) {
@@ -201,13 +209,16 @@ static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t
                                return -1;
                }
 
-               slprintf(syscmd, sizeof(syscmd)-1, 
-                       "%s \"%s\" %d %d", 
-                       get_quota_command, path, qtype, _id);
+               if (asprintf(&syscmd, "%s \"%s\" %d %d",
+                       get_quota_command, path, qtype, _id) < 0) {
+                       return -1;
+               }
 
                DEBUG (3, ("get_quota: Running command %s\n", syscmd));
 
                lines = file_lines_pload(syscmd, NULL);
+               SAFE_FREE(syscmd);
+
                if (lines) {
                        char *line = lines[0];
 
@@ -217,49 +228,79 @@ static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t
 
                        dp->qflags = (enum SMB_QUOTA_TYPE)strtoul(line, &p2, 10);
                        p = p2;
-                       while (p && *p && isspace(*p))
+                       while (p && *p && isspace(*p)) {
                                p++;
-                       if (p && *p)
+                       }
+
+                       if (p && *p) {
                                dp->curblocks = STR_TO_SMB_BIG_UINT(p, &p);
-                       else 
+                       } else {
                                goto invalid_param;
-                       while (p && *p && isspace(*p))
+                       }
+
+                       while (p && *p && isspace(*p)) {
                                p++;
-                       if (p && *p)
+                       }
+
+                       if (p && *p) {
                                dp->softlimit = STR_TO_SMB_BIG_UINT(p, &p);
-                       else
+                       } else {
                                goto invalid_param;
-                       while (p && *p && isspace(*p))
+                       }
+
+                       while (p && *p && isspace(*p)) {
                                p++;
-                       if (p && *p)
+                       }
+
+                       if (p && *p) {
                                dp->hardlimit = STR_TO_SMB_BIG_UINT(p, &p);
-                       else 
+                       } else {
                                goto invalid_param;
-                       while (p && *p && isspace(*p))
+                       }
+
+                       while (p && *p && isspace(*p)) {
                                p++;
-                       if (p && *p)
+                       }
+
+                       if (p && *p) {
                                dp->curinodes = STR_TO_SMB_BIG_UINT(p, &p);
-                       else
+                       } else {
                                goto invalid_param;
-                       while (p && *p && isspace(*p))
+                       }
+
+                       while (p && *p && isspace(*p)) {
                                p++;
-                       if (p && *p)
+                       }
+
+                       if (p && *p) {
                                dp->isoftlimit = STR_TO_SMB_BIG_UINT(p, &p);
-                       else
+                       } else {
                                goto invalid_param;
-                       while (p && *p && isspace(*p))
+                       }
+
+                       while (p && *p && isspace(*p)) {
                                p++;
-                       if (p && *p)
+                       }
+
+                       if (p && *p) {
                                dp->ihardlimit = STR_TO_SMB_BIG_UINT(p, &p);
-                       else
+                       } else {
                                goto invalid_param;     
-                       while (p && *p && isspace(*p))
+                       }
+
+                       while (p && *p && isspace(*p)) {
                                p++;
-                       if (p && *p)
+                       }
+
+                       if (p && *p) {
                                dp->bsize = STR_TO_SMB_BIG_UINT(p, NULL);
-                       else
+                       } else {
                                dp->bsize = 1024;
-                       file_lines_free(lines);
+                       }
+
+                       TALLOC_FREE(lines);
+                       lines = NULL;
+
                        DEBUG (3, ("Parsed output of get_quota, ...\n"));
 
 #ifdef LARGE_SMB_OFF_T
@@ -290,8 +331,10 @@ static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t
 
        errno = ENOSYS;
        return -1;
-       
+
 invalid_param:
+
+       TALLOC_FREE(lines);
        DEBUG(0,("The output of get_quota_command is invalid!\n"));
        return -1;
 }
@@ -299,11 +342,11 @@ invalid_param:
 static int command_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
 {
        const char *set_quota_command;
-       
+
        set_quota_command = lp_set_quota_command();
        if (set_quota_command && *set_quota_command) {
-               char **lines;
-               pstring syscmd;
+               char **lines = NULL;
+               char *syscmd = NULL;
                int _id = -1;
 
                switch(qtype) {
@@ -320,37 +363,40 @@ static int command_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t
                }
 
 #ifdef LARGE_SMB_OFF_T
-               slprintf(syscmd, sizeof(syscmd)-1, 
+               if (asprintf(&syscmd,
                        "%s \"%s\" %d %d "
                        "%u %llu %llu "
-                       "%llu %llu %llu ", 
+                       "%llu %llu %llu ",
                        set_quota_command, path, qtype, _id, dp->qflags,
                        (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit,
                        (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit,
-                       (long long unsigned)dp->bsize);
+                       (long long unsigned)dp->bsize) < 0) {
+                       return -1;
+               }
 #else /* LARGE_SMB_OFF_T */
-               slprintf(syscmd, sizeof(syscmd)-1, 
+               if (asprintf(&syscmd,
                        "%s \"%s\" %d %d "
                        "%u %lu %lu "
-                       "%lu %lu %lu ", 
+                       "%lu %lu %lu ",
                        set_quota_command, path, qtype, _id, dp->qflags,
                        (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit,
                        (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit,
-                       (long unsigned)dp->bsize);
+                       (long unsigned)dp->bsize) < 0) {
+                       return -1;
+               }
 #endif /* LARGE_SMB_OFF_T */
 
-
-
                DEBUG (3, ("get_quota: Running command %s\n", syscmd));
 
                lines = file_lines_pload(syscmd, NULL);
+               SAFE_FREE(syscmd);
                if (lines) {
                        char *line = lines[0];
 
                        DEBUG (3, ("Read output from set_quota, \"%s\"\n", line));
 
-                       file_lines_free(lines);
-                       
+                       TALLOC_FREE(lines);
+
                        return 0;
                }
                DEBUG (0, ("set_quota_command failed!\n"));
@@ -365,7 +411,7 @@ int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI
 {
        int ret = -1;
        int i;
-       BOOL ready = False;
+       bool ready = False;
        char *mntpath = NULL;
        char *bdev = NULL;
        char *fs = NULL;
@@ -384,12 +430,18 @@ int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI
                return ret;
        }
 
+       errno = 0;
+       DEBUG(10,("sys_get_quota() uid(%u, %u)\n", (unsigned)getuid(), (unsigned)geteuid()));
+
        for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].get_quota);i++) {
                if (strcmp(fs,sys_quota_backends[i].name)==0) {
                        ret = sys_quota_backends[i].get_quota(mntpath, bdev, qtype, id, dp);
                        if (ret!=0) {
-                               DEBUG(10,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n",
-                                       fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret));
+                               DEBUG(3,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
+                                       fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
+                       } else {
+                               DEBUG(10,("sys_get_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
+                                       fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
                        }
                        ready = True;
                        break;  
@@ -400,8 +452,11 @@ int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI
                /* use the default vfs quota functions */
                ret=sys_get_vfs_quota(mntpath, bdev, qtype, id, dp);
                if (ret!=0) {
-                       DEBUG(10,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n",
-                               "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret));
+                       DEBUG(3,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s\n",
+                               "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
+               } else {
+                       DEBUG(10,("sys_get_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
+                               "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
                }
        }
 
@@ -410,6 +465,7 @@ int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI
        SAFE_FREE(fs);
 
        if ((ret!=0)&& (errno == EDQUOT)) {
+               DEBUG(10,("sys_get_quota() warning over quota!\n"));
                return 0;
        }
 
@@ -420,7 +476,7 @@ int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI
 {
        int ret = -1;
        int i;
-       BOOL ready = False;
+       bool ready = False;
        char *mntpath = NULL;
        char *bdev = NULL;
        char *fs = NULL;
@@ -441,12 +497,18 @@ int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI
                return ret;
        }
 
+       errno = 0;
+       DEBUG(10,("sys_set_quota() uid(%u, %u)\n", (unsigned)getuid(), (unsigned)geteuid())); 
+
        for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].set_quota);i++) {
                if (strcmp(fs,sys_quota_backends[i].name)==0) {
                        ret = sys_quota_backends[i].set_quota(mntpath, bdev, qtype, id, dp);
                        if (ret!=0) {
-                               DEBUG(10,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n",
-                                       fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret));
+                               DEBUG(3,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
+                                       fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
+                       } else {
+                               DEBUG(10,("sys_set_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
+                                       fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
                        }
                        ready = True;
                        break;
@@ -457,8 +519,11 @@ int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI
                /* use the default vfs quota functions */
                ret=sys_set_vfs_quota(mntpath, bdev, qtype, id, dp);
                if (ret!=0) {
-                       DEBUG(10,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n",
-                               "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret));
+                       DEBUG(3,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
+                               "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
+               } else {
+                       DEBUG(10,("sys_set_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
+                               "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
                }
        }
 
@@ -467,6 +532,7 @@ int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI
        SAFE_FREE(fs);
 
        if ((ret!=0)&& (errno == EDQUOT)) {
+               DEBUG(10,("sys_set_quota() warning over quota!\n"));
                return 0;
        }
 
@@ -474,6 +540,8 @@ int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI
 }
 
 #else /* HAVE_SYS_QUOTAS */
+ void dummy_sysquotas_c(void);
+
  void dummy_sysquotas_c(void)
 {
        return;