Fix bug #7080 - Quota only shown when logged as root.
[ira/wip.git] / source3 / smbd / fake_file.c
index fc874dc0867fde27af748f7a3fcebed9e81802ba..9917481351a6b1849af438402fa441dd49fbc6d0 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"
 
+struct fake_file_type {
+       const char *name;
+       enum FAKE_FILE_TYPE type;
+       void *(*init_pd)(TALLOC_CTX *mem_ctx);
+};
+
+static const struct fake_file_type fake_files[] = {
+#ifdef WITH_QUOTAS
+       {FAKE_FILE_NAME_QUOTA_UNIX, FAKE_FILE_TYPE_QUOTA, init_quota_handle},
+#endif /* WITH_QUOTAS */
+       {NULL, FAKE_FILE_TYPE_NONE, NULL}
+};
+
 /****************************************************************************
- Open a file with a share mode.
+ Create a fake file handle
 ****************************************************************************/
-files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connection_struct *conn,char *fname,
-                               SMB_STRUCT_STAT *psbuf, 
-                               uint32 desired_access, 
-                               int share_mode,int ofun, uint32 new_dos_attr, int oplock_request, 
-                               int *Access,int *action)
+
+static struct fake_file_handle *init_fake_file_handle(enum FAKE_FILE_TYPE type)
 {
-       extern struct current_user current_user;
-       int flags=0;
-       files_struct *fsp = NULL;
+       struct fake_file_handle *fh = NULL;
+       int i;
 
-       if (fake_file_type == 0) {
-               return open_file_shared1(conn,fname,psbuf,desired_access,
-                                       share_mode,ofun,new_dos_attr,
-                                       oplock_request,Access,action);  
+       for (i=0; fake_files[i].name!=NULL; i++) {
+               if (fake_files[i].type==type) {
+                       break;
+               }
        }
 
-       /* access check */
-       if (current_user.uid != 0) {
-               DEBUG(1,("access_denied to service[%s] file[%s] user[%s]\n",
-                       lp_servicename(SNUM(conn)),fname,conn->user));
-               errno = EACCES;
+       if (fake_files[i].name == NULL) {
                return NULL;
        }
 
-       fsp = file_new(conn);
-       if(!fsp)
-               return NULL;
-
-       DEBUG(5,("open_fake_file_shared1: fname = %s, FID = %d, share_mode = %x, ofun = %x, oplock request = %d\n",
-               fname, fsp->fnum, share_mode, ofun, oplock_request ));
+       DEBUG(5,("init_fake_file_handle: for [%s]\n",fake_files[i].name));
 
-       if (!check_name(fname,conn)) {
-               file_free(fsp);
-               return NULL;
-       } 
-
-       fsp->fd = -1;
-       fsp->mode = psbuf->st_mode;
-       fsp->inode = psbuf->st_ino;
-       fsp->dev = psbuf->st_dev;
-       fsp->vuid = current_user.vuid;
-       fsp->size = psbuf->st_size;
-       fsp->pos = -1;
-       fsp->can_lock = True;
-       fsp->can_read = ((flags & O_WRONLY)==0);
-       fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
-       fsp->share_mode = 0;
-       fsp->desired_access = desired_access;
-       fsp->print_file = False;
-       fsp->modified = False;
-       fsp->oplock_type = NO_OPLOCK;
-       fsp->sent_oplock_break = NO_BREAK_SENT;
-       fsp->is_directory = False;
-       fsp->is_stat = False;
-       fsp->directory_delete_on_close = False;
-       fsp->conn = conn;
-       string_set(&fsp->fsp_name,fname);
-       fsp->wcp = NULL; /* Write cache pointer. */
-       
-       fsp->fake_file_handle = init_fake_file_handle(fake_file_type);
-       
-       if (fsp->fake_file_handle==NULL) {
-               file_free(fsp);
+       fh = talloc(NULL, struct fake_file_handle);
+       if (fh == NULL) {
+               DEBUG(0,("TALLOC_ZERO() failed.\n"));
                return NULL;
        }
 
-       conn->num_files_open++;
-       return fsp;
+       fh->type = type;
+
+       if (fake_files[i].init_pd) {
+               fh->private_data = fake_files[i].init_pd(fh);
+       }
+       return fh;
 }
 
-static FAKE_FILE fake_files[] = {
-#ifdef WITH_QUOTAS
-       {FAKE_FILE_NAME_QUOTA_UNIX,     FAKE_FILE_TYPE_QUOTA,   init_quota_handle,      destroy_quota_handle},
-#endif /* WITH_QUOTAS */
-       {NULL,                          FAKE_FILE_TYPE_NONE,    NULL,                   NULL }
-};
+/****************************************************************************
+ Does this name match a fake filename ?
+****************************************************************************/
 
-int is_fake_file(char *fname)
+enum FAKE_FILE_TYPE is_fake_file_path(const char *path)
 {
        int i;
 
-       if (!fname)
-               return 0;
+       if (!path) {
+               return FAKE_FILE_TYPE_NONE;
+       }
 
        for (i=0;fake_files[i].name!=NULL;i++) {
-               if (strncmp(fname,fake_files[i].name,strlen(fake_files[i].name))==0) {
-                       DEBUG(5,("is_fake_file: [%s] is a fake file\n",fname));
+               if (strncmp(path,fake_files[i].name,strlen(fake_files[i].name))==0) {
+                       DEBUG(5,("is_fake_file: [%s] is a fake file\n",path));
                        return fake_files[i].type;
                }
        }
@@ -117,50 +89,87 @@ int is_fake_file(char *fname)
        return FAKE_FILE_TYPE_NONE;
 }
 
-struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type)
+enum FAKE_FILE_TYPE is_fake_file(const struct smb_filename *smb_fname)
 {
-       TALLOC_CTX *mem_ctx = NULL;
-       FAKE_FILE_HANDLE *fh = NULL;
-       int i;
+       char *fname = NULL;
+       NTSTATUS status;
+       enum FAKE_FILE_TYPE ret;
 
-       for (i=0;fake_files[i].name!=NULL;i++) {
-               if (fake_files[i].type==type) {
-                       DEBUG(5,("init_fake_file_handle: for [%s]\n",fake_files[i].name));
+       if (!smb_fname) {
+               return FAKE_FILE_TYPE_NONE;
+       }
+
+       status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return FAKE_FILE_TYPE_NONE;
+       }
+
+       ret = is_fake_file_path(fname);
 
-                       if ((mem_ctx=talloc_init("fake_file_handle"))==NULL) {
-                               DEBUG(0,("talloc_init(fake_file_handle) failed.\n"));
-                               return NULL;    
-                       }
+       TALLOC_FREE(fname);
 
-                       if ((fh =(FAKE_FILE_HANDLE *)talloc_zero(mem_ctx, sizeof(FAKE_FILE_HANDLE)))==NULL) {
-                               DEBUG(0,("talloc_zero() failed.\n"));
-                               talloc_destroy(mem_ctx);
-                               return NULL;
-                       }
+       return ret;
+}
 
-                       fh->type = type;
-                       fh->mem_ctx = mem_ctx;
+/****************************************************************************
+ Open a fake quota file with a share mode.
+****************************************************************************/
 
-                       if (fake_files[i].init_pd)
-                               fh->pd = fake_files[i].init_pd(fh->mem_ctx);
+NTSTATUS open_fake_file(struct smb_request *req, connection_struct *conn,
+                               uint16_t current_vuid,
+                               enum FAKE_FILE_TYPE fake_file_type,
+                               const struct smb_filename *smb_fname,
+                               uint32 access_mask,
+                               files_struct **result)
+{
+       files_struct *fsp = NULL;
+       NTSTATUS status;
 
-                       fh->free_pd = fake_files[i].free_pd;
+       /* access check */
+       if (geteuid() == sec_initial_uid()) {
+               DEBUG(3, ("open_fake_file_shared: access_denied to "
+                         "service[%s] file[%s] user[%s]\n",
+                         lp_servicename(SNUM(conn)),
+                         smb_fname_str_dbg(smb_fname),
+                         conn->server_info->unix_name));
+               return NT_STATUS_ACCESS_DENIED;
 
-                       return fh;
-               }
        }
 
-       return NULL;    
-}
+       status = file_new(req, conn, &fsp);
+       if(!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
-void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh)
-{
-       if (!fh||!(*fh))
-               return;
+       DEBUG(5,("open_fake_file_shared: fname = %s, FID = %d, access_mask = 0x%x\n",
+                smb_fname_str_dbg(smb_fname), fsp->fnum,
+                (unsigned int)access_mask));
 
-       if ((*fh)->free_pd)
-               (*fh)->free_pd(&(*fh)->pd);             
+       fsp->conn = conn;
+       fsp->fh->fd = -1;
+       fsp->vuid = current_vuid;
+       fsp->fh->pos = -1;
+       fsp->can_lock = False; /* Should this be true ? - No, JRA */
+       fsp->access_mask = access_mask;
+       status = fsp_set_smb_fname(fsp, smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               file_free(req, fsp);
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       talloc_destroy((*fh)->mem_ctx);
-       (*fh) = NULL;
+       fsp->fake_file_handle = init_fake_file_handle(fake_file_type);
+       
+       if (fsp->fake_file_handle==NULL) {
+               file_free(req, fsp);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       *result = fsp;
+       return NT_STATUS_OK;
+}
+
+NTSTATUS close_fake_file(struct smb_request *req, files_struct *fsp)
+{
+       file_free(req, fsp);
+       return NT_STATUS_OK;
 }