diff --git a/source3/include/proto.h b/source3/include/proto.h index be773f0bc34..cdc8e70d598 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -90,8 +90,6 @@ BOOL dos_file_exist(char *fname,SMB_STRUCT_STAT *sbuf); BOOL dos_directory_exist(char *dname,SMB_STRUCT_STAT *st); time_t dos_file_modtime(char *fname); SMB_OFF_T dos_file_size(char *file_name); -int dos_ChDir(char *path); -char *dos_GetWd(char *path); /*The following definitions come from lib/error.c */ @@ -339,7 +337,6 @@ void smb_setlen(char *buf,int len); int set_message(char *buf,int num_words,int num_bytes,BOOL zero); void dos_clean_name(char *s); void unix_clean_name(char *s); -BOOL reduce_name(char *s,char *dir,BOOL widelinks); void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,time_t date); void close_low_fds(void); int set_blocking(int fd, BOOL set); @@ -3854,23 +3851,35 @@ int vfswrap_lstat(char *path, SMB_STRUCT_STAT *sbuf); int vfswrap_unlink(char *path); int vfswrap_chmod(char *path, mode_t mode); +int vfswrap_chown(char *path, uid_t uid, gid_t gid); +int vfswrap_chdir(char *path); +char *vfswrap_getwd(char *path); int vfswrap_utime(char *path, struct utimbuf *times); int vfswrap_ftruncate(int fd, SMB_OFF_T offset); BOOL vfswrap_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type); +size_t vfswrap_get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc); +BOOL vfswrap_set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd); /*The following definitions come from smbd/vfs.c */ int vfs_init_default(connection_struct *conn); BOOL vfs_init_custom(connection_struct *conn); -BOOL vfs_directory_exist(connection_struct *conn, char *dname, - SMB_STRUCT_STAT *st); +int vfs_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *st); +BOOL vfs_directory_exist(connection_struct *conn, char *dname, SMB_STRUCT_STAT *st); int vfs_unlink(connection_struct *conn, char *fname); +int vfs_chmod(connection_struct *conn, char *fname,mode_t mode); +int vfs_chown(connection_struct *conn, char *fname, uid_t uid, gid_t gid); +int vfs_chdir(connection_struct *conn, char *fname); +char *vfs_getwd(connection_struct *conn, char *unix_path); BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf); ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N); 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); char *vfs_readdirname(connection_struct *conn, void *p); +int vfs_ChDir(connection_struct *conn, char *path); +char *vfs_GetWd(connection_struct *conn, char *path); +BOOL reduce_name(connection_struct *conn, char *s,char *dir,BOOL widelinks); /*The following definitions come from smbwrapper/realcalls.c */ diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 1312935e7f1..e657354d945 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -184,9 +184,16 @@ struct vfs_ops { int (*lstat)(char *path, SMB_STRUCT_STAT *sbuf); int (*unlink)(char *path); int (*chmod)(char *path, mode_t mode); + int (*chown)(char *path, uid_t uid, gid_t gid); + int (*chdir)(char *path); + char *(*getwd)(char *buf); int (*utime)(char *path, struct utimbuf *times); int (*ftruncate)(int fd, SMB_OFF_T offset); BOOL (*lock)(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type); +#if 0 + size_t (*get_nt_acl)(files_struct *fsp, SEC_DESC **ppdesc); + BOOL (*set_nt_acl)(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd); +#endif }; struct vfs_options { diff --git a/source3/lib/doscalls.c b/source3/lib/doscalls.c index 2bd68d30974..50c446faebf 100644 --- a/source3/lib/doscalls.c +++ b/source3/lib/doscalls.c @@ -33,6 +33,7 @@ extern int DEBUGLEVEL; +#if 0 /* Use vfs_unlink. */ /******************************************************************* Unlink wrapper that calls dos_to_unix. ********************************************************************/ @@ -41,6 +42,7 @@ int dos_unlink(char *fname) { return(unlink(dos_to_unix(fname,False))); } +#endif /******************************************************************* Open() wrapper that calls dos_to_unix. @@ -85,10 +87,12 @@ char *dos_readdirname(DIR *p) A chown() wrapper that calls dos_to_unix. ********************************************************************/ +#if 0 /* Use vfs_chown. */ int dos_chown(char *fname, uid_t uid, gid_t gid) { return(sys_chown(dos_to_unix(fname,False),uid,gid)); } +#endif /******************************************************************* A stat() wrapper that calls dos_to_unix. @@ -134,6 +138,7 @@ int dos_rmdir(char *dname) return(rmdir(dos_to_unix(dname,False))); } +#if 0 /* VFS */ /******************************************************************* chdir() - call dos_to_unix. ********************************************************************/ @@ -142,6 +147,7 @@ int dos_chdir(char *dname) { return(chdir(dos_to_unix(dname,False))); } +#endif /******************************************************************* Utime() - call dos_to_unix. @@ -282,6 +288,7 @@ int dos_chmod(char *fname,mode_t mode) return(chmod(dos_to_unix(fname,False),mode)); } +#if 0 /* VFS */ /******************************************************************* Getwd - takes a UNIX directory name and returns the name in dos format. @@ -295,6 +302,7 @@ char *dos_getwd(char *unix_path) unix_to_dos(wd, True); return wd; } +#endif /* VFS */ /******************************************************************* Check if a DOS file exists. Use vfs_file_exist function instead. @@ -333,164 +341,3 @@ SMB_OFF_T dos_file_size(char *file_name) { return get_file_size(dos_to_unix(file_name, False)); } - -/******************************************************************* - A wrapper for dos_chdir(). -********************************************************************/ - -int dos_ChDir(char *path) -{ - int res; - static pstring LastDir=""; - - if (strcsequal(path,".")) - return(0); - - if (*path == '/' && strcsequal(LastDir,path)) - return(0); - - DEBUG(3,("dos_ChDir to %s\n",path)); - - res = dos_chdir(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]; - -BOOL use_getwd_cache=True; - -/**************************************************************************** - 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,("Ahh! Can't malloc\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. -********************************************************************/ - -char *dos_GetWd(char *path) -{ - pstring s; - static BOOL getwd_cache_init = False; - SMB_STRUCT_STAT st, st2; - int i; - - *s = 0; - - if (!use_getwd_cache) - return(dos_getwd(path)); - - /* init the cache */ - if (!getwd_cache_init) - { - getwd_cache_init = True; - for (i=0;ivfs_ops.stat(dos_to_unix(fname,False),st)) return(-1); + if (vfs_stat(conn,fname,st)) return(-1); } if (S_ISDIR(st->st_mode)) dosmode |= aDIR; @@ -227,7 +227,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT * unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - return(conn->vfs_ops.chmod(dos_to_unix(fname,False),unixmode)); + return(vfs_chmod(conn,fname,unixmode)); } @@ -258,7 +258,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) (as DOS does). */ - if(conn->vfs_ops.stat(dos_to_unix(fname,False),&sb) != 0) + if(vfs_stat(conn,fname,&sb) != 0) return -1; /* Check if we have write access. */ diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 294e80250a1..67fa85d9cbd 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -419,7 +419,7 @@ BOOL check_name(char *name,connection_struct *conn) return(0); } - ret = reduce_name(name,conn->connectpath,lp_widelinks(SNUM(conn))); + ret = reduce_name(conn,name,conn->connectpath,lp_widelinks(SNUM(conn))); /* Check if we are allowing users to follow symlinks */ /* Patch from David Clerc diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index a8cdcea17da..5a2f8653103 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -51,7 +51,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, ZERO_STRUCTP(data); - if(dos_stat(path, &st) == -1) return False; + if(vfs_stat(conn,path, &st) == -1) return False; data->modify_time = st.st_mtime; data->status_time = st.st_ctime; @@ -102,7 +102,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, /* * Do the stat - but ignore errors. */ - dos_stat(full_name, &st); + vfs_stat(conn,full_name, &st); data->total_time += (st.st_mtime + st.st_ctime); } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 59c3c83f6f9..4a8260421c4 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -732,7 +732,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B */ saved_conn = fsp->conn; saved_vuid = current_user.vuid; - dos_GetWd(saved_dir); + vfs_GetWd(saved_conn,saved_dir); unbecome_user(); /* Save the chain fnum. */ file_chain_save(); @@ -814,7 +814,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B exit_server("unable to re-become user"); } /* Including the directory. */ - dos_ChDir(saved_dir); + vfs_ChDir(saved_conn,saved_dir); /* Restore the chain fnum. */ file_chain_restore(); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9dd5a9ef68d..8624bdb9b4a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1100,7 +1100,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size unix_convert(fname,conn,0,&bad_path,&sbuf); if (check_name(fname,conn)) { - if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0) + if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0) { mode = dos_mode(conn,fname,&sbuf); size = sbuf.st_size; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 272d54e3baa..e82bbefa5a8 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -56,8 +56,8 @@ BOOL become_service(connection_struct *conn,BOOL do_chdir) snum = SNUM(conn); if (do_chdir && - dos_ChDir(conn->connectpath) != 0 && - dos_ChDir(conn->origpath) != 0) { + vfs_ChDir(conn,conn->connectpath) != 0 && + vfs_ChDir(conn,conn->origpath) != 0) { DEBUG(0,("chdir (%s) failed\n", conn->connectpath)); return(False); @@ -575,7 +575,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int return NULL; } - if (dos_ChDir(conn->connectpath) != 0) { + if (vfs_ChDir(conn,conn->connectpath) != 0) { DEBUG(0,("Can't change directory to %s (%s)\n", conn->connectpath,strerror(errno))); unbecome_user(); @@ -598,9 +598,9 @@ connection_struct *make_connection(char *service,char *user,char *password, int { pstring s; pstrcpy(s,conn->connectpath); - dos_GetWd(s); + vfs_GetWd(conn,s); string_set(&conn->connectpath,s); - dos_ChDir(conn->connectpath); + vfs_ChDir(conn,conn->connectpath); } #endif diff --git a/source3/smbd/unix_acls.c b/source3/smbd/unix_acls.c index 7ab448e6a30..48f6163596d 100644 --- a/source3/smbd/unix_acls.c +++ b/source3/smbd/unix_acls.c @@ -146,8 +146,6 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p DOM_SID grp_sid; DOM_SID file_owner_sid; DOM_SID file_grp_sid; - uint32 owner_rid; - uint32 grp_rid; SEC_ACL *dacl = psd->dacl; BOOL all_aces_are_inherit_only = (is_directory ? True : False); int i; @@ -353,7 +351,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) } else { if(fsp->is_directory || fsp->fd == -1) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) { return 0; } } else { @@ -458,14 +456,14 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) */ if(fsp->is_directory) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) + if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) return False; } else { int ret; if(fsp->fd == -1) - ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); + ret = vfs_stat(fsp->conn,fsp->fsp_name,&sbuf); else ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); @@ -492,7 +490,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(3,("call_nt_transact_set_security_desc: chown %s. uid = %u, gid = %u.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); - if(dos_chown( fsp->fsp_name, user, grp) == -1) { + if(vfs_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) { DEBUG(3,("call_nt_transact_set_security_desc: chown %s, %u, %u failed. Error = %s.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); return False; @@ -504,7 +502,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) */ if(fsp->is_directory) { - if(dos_stat(fsp->fsp_name, &sbuf) != 0) { + if(vfs_stat(fsp->conn, fsp->fsp_name, &sbuf) != 0) { return False; } } else { @@ -512,7 +510,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) int ret; if(fsp->fd == -1) - ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf); + ret = vfs_stat(fsp->conn, fsp->fsp_name, &sbuf); else ret = conn->vfs_ops.fstat(fsp->fd,&sbuf); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 5db16894500..12ba9bda841 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -284,6 +284,42 @@ int vfswrap_chmod(char *path, mode_t mode) return result; } +int vfswrap_chown(char *path, uid_t uid, gid_t gid) +{ + int result; + +#ifdef VFS_CHECK_NULL + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_chown()\n"); + } +#endif + + result = sys_chown(path, uid, gid); + return result; +} + +int vfswrap_chdir(char *path) +{ +#ifdef VFS_CHECK_NULL + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_chdir()\n"); + } +#endif + + return chdir(path); +} + +char *vfswrap_getwd(char *path) +{ +#ifdef VFS_CHECK_NULL + if (path == NULL) { + smb_panic("NULL pointer passed to vfswrap_getwd()\n"); + } +#endif + + return sys_getwd(path); +} + int vfswrap_utime(char *path, struct utimbuf *times) { int result; @@ -310,3 +346,13 @@ BOOL vfswrap_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { return fcntl_lock(fd, op, offset, count,type); } + +#if 0 +size_t vfswrap_get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) +{ +} + +BOOL vfswrap_set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) +{ +} +#endif 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; - ret = S_ISDIR(st->st_mode); - if(!ret) - errno = ENOTDIR; + if (!st) + st = &st2; + + 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))); } /******************************************************************* - check if a vfs file exists + 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)); +} + +/******************************************************************* + 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