smbd: free talloc context if no quota records are available
[metze/samba/wip.git] / source3 / smbd / ntquotas.c
index fcccf9d9fc02a2c4dda848f95c89ff3a10ece8e8..4acfa5057ed0201f17271c08d7bb0e742d8a2b95 100644 (file)
 */
 
 #include "includes.h"
+#include "smbd/smbd.h"
+#include "../lib/util/util_pw.h"
+#include "system/passwd.h"
+#include "passdb/lookup_sid.h"
+#include "libsmb/libsmb.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_QUOTA
 
-static SMB_BIG_UINT limit_nt2unix(SMB_BIG_UINT in, SMB_BIG_UINT bsize)
+static uint64_t limit_nt2unix(uint64_t in, uint64_t bsize)
 {
-       SMB_BIG_UINT ret = (SMB_BIG_UINT)0;
+       uint64_t ret = (uint64_t)0;
 
-       ret =   (SMB_BIG_UINT)(in/bsize);
+       ret =   (uint64_t)(in/bsize);
        if (in>0 && ret==0) {
                /* we have to make sure that a overflow didn't set NO_LIMIT */
-               ret = (SMB_BIG_UINT)1;
+               ret = (uint64_t)1;
        }
 
        if (in == SMB_NTQUOTAS_NO_LIMIT)
@@ -42,36 +47,29 @@ static SMB_BIG_UINT limit_nt2unix(SMB_BIG_UINT in, SMB_BIG_UINT bsize)
        return ret;
 }
 
-static SMB_BIG_UINT limit_unix2nt(SMB_BIG_UINT in, SMB_BIG_UINT bsize)
+static uint64_t limit_unix2nt(uint64_t in, uint64_t bsize)
 {
-       SMB_BIG_UINT ret = (SMB_BIG_UINT)0;
+       uint64_t ret = (uint64_t)0;
 
-       ret = (SMB_BIG_UINT)(in*bsize);
+       ret = (uint64_t)(in*bsize);
        
-       if (ret < in) {
-               /* we overflow */
-               ret = SMB_NTQUOTAS_NO_LIMIT;
-       }
-
-       if (in == SMB_QUOTAS_NO_LIMIT)
-               ret = SMB_NTQUOTAS_NO_LIMIT;
-
        return ret;
 }
 
-static SMB_BIG_UINT limit_blk2inodes(SMB_BIG_UINT in)
+static uint64_t limit_blk2inodes(uint64_t in)
 {
-       SMB_BIG_UINT ret = (SMB_BIG_UINT)0;
+       uint64_t ret = (uint64_t)0;
        
-       ret = (SMB_BIG_UINT)(in/2);
+       ret = (uint64_t)(in/2);
        
        if (ret == 0 && in != 0)
-               ret = (SMB_BIG_UINT)1;
+               ret = (uint64_t)1;
 
        return ret;     
 }
 
-int vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, SMB_NTQUOTA_STRUCT *qt)
+NTSTATUS vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype,
+                        struct dom_sid *psid, SMB_NTQUOTA_STRUCT *qt)
 {
        int ret;
        SMB_DISK_QUOTA D;
@@ -79,8 +77,9 @@ int vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid,
 
        ZERO_STRUCT(D);
 
-       if (!fsp||!fsp->conn||!qt)
-               return (-1);
+       if (!fsp || !fsp->conn || !qt) {
+               return NT_STATUS_INTERNAL_ERROR;
+       }
 
        ZERO_STRUCT(*qt);
 
@@ -89,27 +88,27 @@ int vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid,
        if (psid && !sid_to_uid(psid, &id.uid)) {
                DEBUG(0,("sid_to_uid: failed, SID[%s]\n",
                         sid_string_dbg(psid)));
+               return NT_STATUS_NO_SUCH_USER;
        }
 
-       ret = SMB_VFS_GET_QUOTA(fsp->conn, qtype, id, &D);
+       ret = SMB_VFS_GET_QUOTA(fsp->conn, ".", qtype, id, &D);
 
        if (psid)
                qt->sid    = *psid;
 
        if (ret!=0) {
-               return ret;
+               return map_nt_error_from_unix(errno);
        }
                
-       qt->usedspace = (SMB_BIG_UINT)D.curblocks*D.bsize;
+       qt->usedspace = (uint64_t)D.curblocks*D.bsize;
        qt->softlim = limit_unix2nt(D.softlimit, D.bsize);
        qt->hardlim = limit_unix2nt(D.hardlimit, D.bsize);
        qt->qflags = D.qflags;
 
-       
-       return 0;
+       return NT_STATUS_OK;
 }
 
-int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, SMB_NTQUOTA_STRUCT *qt)
+int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, struct dom_sid *psid, SMB_NTQUOTA_STRUCT *qt)
 {
        int ret;
        SMB_DISK_QUOTA D;
@@ -121,7 +120,7 @@ int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid,
 
        id.uid = -1;
 
-       D.bsize     = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+       D.bsize     = (uint64_t)QUOTABLOCK_SIZE;
 
        D.softlimit = limit_nt2unix(qt->softlim,D.bsize);
        D.hardlimit = limit_nt2unix(qt->hardlim,D.bsize);
@@ -171,11 +170,12 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list)
                return (-1);
        }
 
-       sys_setpwent();
-       while ((usr = sys_getpwent()) != NULL) {
+       setpwent();
+       while ((usr = getpwent()) != NULL) {
                SMB_NTQUOTA_STRUCT tmp_qt;
                SMB_NTQUOTA_LIST *tmp_list_ent;
-               DOM_SID sid;
+               struct dom_sid  sid;
+               NTSTATUS status;
 
                ZERO_STRUCT(tmp_qt);
 
@@ -186,7 +186,14 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list)
 
                uid_to_sid(&sid, usr->pw_uid);
 
-               if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &tmp_qt)!=0) {
+               status =
+                   vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &tmp_qt);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(5, ("failed getting quota for uid[%ld] - %s\n",
+                                 (long)usr->pw_uid, nt_errstr(status)));
+                       continue;
+               }
+               if (tmp_qt.softlim == 0 && tmp_qt.hardlim == 0) {
                        DEBUG(5,("no quota entry for sid[%s] path[%s]\n",
                                 sid_string_dbg(&sid),
                                 fsp->conn->connectpath));
@@ -196,14 +203,14 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list)
                DEBUG(15,("quota entry for id[%s] path[%s]\n",
                          sid_string_dbg(&sid), fsp->conn->connectpath));
 
-               if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
+               if ((tmp_list_ent=talloc_zero(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
                        DEBUG(0,("TALLOC_ZERO() failed\n"));
                        *qt_list = NULL;
                        talloc_destroy(mem_ctx);
                        return (-1);
                }
 
-               if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
+               if ((tmp_list_ent->quotas=talloc_zero(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
                        DEBUG(0,("TALLOC_ZERO() failed\n"));
                        *qt_list = NULL;
                        talloc_destroy(mem_ctx);
@@ -217,8 +224,17 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list)
                DLIST_ADD((*qt_list),tmp_list_ent);
                
        }
-       sys_endpwent();
+       endpwent();
 
+       if (*qt_list == NULL) {
+               TALLOC_FREE(mem_ctx);
+       }
+       return 0;
+}
+
+static int quota_handle_destructor(SMB_NTQUOTA_HANDLE *handle)
+{
+       free_ntquota_list(&handle->quota_list);
        return 0;
 }
 
@@ -227,32 +243,14 @@ void *init_quota_handle(TALLOC_CTX *mem_ctx)
        SMB_NTQUOTA_HANDLE *qt_handle;
 
        if (!mem_ctx)
-               return False;
+               return NULL;
 
-       qt_handle = TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_HANDLE);
+       qt_handle = talloc_zero(mem_ctx,SMB_NTQUOTA_HANDLE);
        if (qt_handle==NULL) {
                DEBUG(0,("TALLOC_ZERO() failed\n"));
                return NULL;
        }
 
-       return (void *)qt_handle;       
-}
-
-void destroy_quota_handle(void **pqt_handle)
-{
-       SMB_NTQUOTA_HANDLE *qt_handle = NULL;
-       if (!pqt_handle||!(*pqt_handle))
-               return;
-       
-       qt_handle = (SMB_NTQUOTA_HANDLE *)(*pqt_handle);
-       
-       
-       if (qt_handle->quota_list)
-               free_ntquota_list(&qt_handle->quota_list);
-
-       qt_handle->quota_list = NULL;
-       qt_handle->tmp_list = NULL;
-       qt_handle = NULL;
-
-       return;
+       talloc_set_destructor(qt_handle, quota_handle_destructor);
+       return (void *)qt_handle;
 }