From b43b2e4f8a4be30e3f7aca6f570f5376fd508e3d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Sep 2000 19:09:59 +0000 Subject: Restructuring of the code to remove dos_ChDir/dos_GetWd and re-vector them through the VFS. All file access/directory access code in smbd should now go via the vfs. Added vfs_chown/vfs_chmod calls. Still looking at vfs_get_nt_acl() vfs_set_nt_acl() call API design. Jeremy. (This used to be commit f96625ec124adb6e110dc54632e006b3620a962b) --- source3/smbd/vfs.c | 413 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 388 insertions(+), 25 deletions(-) (limited to 'source3/smbd/vfs.c') diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 496d3e0432b..631d4bedbeb 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -64,9 +64,16 @@ struct vfs_ops default_vfs_ops = { vfswrap_lstat, vfswrap_unlink, vfswrap_chmod, + vfswrap_chown, + vfswrap_chdir, + vfswrap_getwd, vfswrap_utime, vfswrap_ftruncate, - vfswrap_lock + vfswrap_lock, +#if 0 + vfswrap_get_nt_acl, + vfswrap_set_nt_acl +#endif }; /**************************************************************************** @@ -208,6 +215,10 @@ BOOL vfs_init_custom(connection_struct *conn) conn->vfs_ops.chmod = default_vfs_ops.chmod; } + if (conn->vfs_ops.chown == NULL) { + conn->vfs_ops.chown = default_vfs_ops.chown; + } + if (conn->vfs_ops.utime == NULL) { conn->vfs_ops.utime = default_vfs_ops.utime; } @@ -224,20 +235,33 @@ BOOL vfs_init_custom(connection_struct *conn) } #endif -BOOL vfs_directory_exist(connection_struct *conn, char *dname, - SMB_STRUCT_STAT *st) +/******************************************************************* + vfs stat wrapper that calls dos_to_unix. +********************************************************************/ + +int vfs_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *st) { - SMB_STRUCT_STAT st2; - BOOL ret; + return(conn->vfs_ops.stat(dos_to_unix(fname,False),st)); +} - if (!st) st = &st2; +/******************************************************************* + Check if directory exists. +********************************************************************/ - if (conn->vfs_ops.stat(dos_to_unix(dname,False),st) != 0) - return(False); +BOOL vfs_directory_exist(connection_struct *conn, char *dname, SMB_STRUCT_STAT *st) +{ + SMB_STRUCT_STAT st2; + BOOL ret; + + if (!st) + st = &st2; - ret = S_ISDIR(st->st_mode); - if(!ret) - errno = ENOTDIR; + if (vfs_stat(conn,dname,st) != 0) + return(False); + + ret = S_ISDIR(st->st_mode); + if(!ret) + errno = ENOTDIR; return ret; } @@ -248,26 +272,70 @@ BOOL vfs_directory_exist(connection_struct *conn, char *dname, int vfs_unlink(connection_struct *conn, char *fname) { - return(conn->vfs_ops.unlink(dos_to_unix(fname,False))); + return(conn->vfs_ops.unlink(dos_to_unix(fname,False))); +} + +/******************************************************************* + vfs chmod wrapper that calls dos_to_unix. +********************************************************************/ + +int vfs_chmod(connection_struct *conn, char *fname,mode_t mode) +{ + return(conn->vfs_ops.chmod(dos_to_unix(fname,False), mode)); +} + +/******************************************************************* + vfs chown wrapper that calls dos_to_unix. +********************************************************************/ + +int vfs_chown(connection_struct *conn, char *fname, uid_t uid, gid_t gid) +{ + return(conn->vfs_ops.chown(dos_to_unix(fname,False), uid, gid)); } /******************************************************************* - check if a vfs file exists + A wrapper for vfs_chdir(). +********************************************************************/ + +int vfs_chdir(connection_struct *conn, char *fname) +{ + return(conn->vfs_ops.chdir(dos_to_unix(fname,False))); +} + +/******************************************************************* + vfs getwd wrapper that calls dos_to_unix. +********************************************************************/ + +char *vfs_getwd(connection_struct *conn, char *unix_path) +{ + char *wd; + wd = conn->vfs_ops.getwd(unix_path); + if (wd) + unix_to_dos(wd, True); + return wd; +} + +/******************************************************************* + Check if a vfs file exists. ********************************************************************/ + BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf) { - SMB_STRUCT_STAT st; - if (!sbuf) sbuf = &st; - - if (conn->vfs_ops.stat(dos_to_unix(fname,False),sbuf) != 0) - return(False); + SMB_STRUCT_STAT st; - return(S_ISREG(sbuf->st_mode)); + if (!sbuf) + sbuf = &st; + + if (vfs_stat(conn,fname,sbuf) != 0) + return(False); + + return(S_ISREG(sbuf->st_mode)); } /**************************************************************************** - write data to a fd on the vfs + Write data to a fd on the vfs. ****************************************************************************/ + ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N) { size_t total=0; @@ -286,8 +354,9 @@ ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N) } /**************************************************************************** -transfer some data between two file_struct's + Transfer some data between two file_struct's. ****************************************************************************/ + SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp, int out_fd, files_struct *out_fsp, SMB_OFF_T n, char *header, int headlen, int align) @@ -376,22 +445,26 @@ SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp, } /******************************************************************* -a vfs_readdir wrapper which just returns the file name + A vfs_readdir wrapper which just returns the file name. ********************************************************************/ + char *vfs_readdirname(connection_struct *conn, void *p) { struct dirent *ptr; char *dname; - if (!p) return(NULL); + if (!p) + return(NULL); ptr = (struct dirent *)conn->vfs_ops.readdir(p); - if (!ptr) return(NULL); + if (!ptr) + return(NULL); dname = ptr->d_name; #ifdef NEXT2 - if (telldir(p) < 0) return(NULL); + if (telldir(p) < 0) + return(NULL); #endif #ifdef HAVE_BROKEN_READDIR @@ -474,3 +547,293 @@ static BOOL handle_vfs_option(char *pszParmValue, char **ptr) #endif + +/******************************************************************* + A wrapper for vfs_chdir(). +********************************************************************/ + +int vfs_ChDir(connection_struct *conn, char *path) +{ + int res; + static pstring LastDir=""; + + if (strcsequal(path,".")) + return(0); + + if (*path == '/' && strcsequal(LastDir,path)) + return(0); + + DEBUG(3,("vfs_ChDir to %s\n",path)); + + res = vfs_chdir(conn,path); + if (!res) + pstrcpy(LastDir,path); + return(res); +} + +/* number of list structures for a caching GetWd function. */ +#define MAX_GETWDCACHE (50) + +struct +{ + SMB_DEV_T dev; /* These *must* be compatible with the types returned in a stat() call. */ + SMB_INO_T inode; /* These *must* be compatible with the types returned in a stat() call. */ + char *dos_path; /* The pathname in DOS format. */ + BOOL valid; +} ino_list[MAX_GETWDCACHE]; + +extern BOOL use_getwd_cache; + +/**************************************************************************** + Prompte a ptr (to make it recently used) +****************************************************************************/ + +static void array_promote(char *array,int elsize,int element) +{ + char *p; + if (element == 0) + return; + + p = (char *)malloc(elsize); + + if (!p) { + DEBUG(5,("array_promote: malloc fail\n")); + return; + } + + memcpy(p,array + element * elsize, elsize); + memmove(array + elsize,array,elsize*element); + memcpy(array,p,elsize); + free(p); +} + +/******************************************************************* + Return the absolute current directory path - given a UNIX pathname. + Note that this path is returned in DOS format, not UNIX + format. Note this can be called with conn == NULL. +********************************************************************/ + +char *vfs_GetWd(connection_struct *conn, char *path) +{ + pstring s; + static BOOL getwd_cache_init = False; + SMB_STRUCT_STAT st, st2; + int i; + + *s = 0; + + if (!use_getwd_cache) + return(vfs_getwd(conn,path)); + + /* init the cache */ + if (!getwd_cache_init) + { + getwd_cache_init = True; + for (i=0;i