Restructuring of the code to remove dos_ChDir/dos_GetWd and re-vector them
authorJeremy Allison <jra@samba.org>
Wed, 27 Sep 2000 19:09:59 +0000 (19:09 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 27 Sep 2000 19:09:59 +0000 (19:09 +0000)
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)

14 files changed:
source3/include/proto.h
source3/include/vfs.h
source3/lib/doscalls.c
source3/lib/util.c
source3/param/loadparm.c
source3/smbd/dosmode.c
source3/smbd/filename.c
source3/smbd/notify_hash.c
source3/smbd/oplock.c
source3/smbd/reply.c
source3/smbd/service.c
source3/smbd/unix_acls.c
source3/smbd/vfs-wrap.c
source3/smbd/vfs.c

index be773f0bc3467c50f3c5001ee837732425fa3342..cdc8e70d59851f75780f6a716997cf27b8632c34 100644 (file)
@@ -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  */
 
index 1312935e7f1f9358a8fa06566ee26fcf7bc5ff61..e657354d9452d28626edef8b167c21497536d525 100644 (file)
@@ -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 {
index 2bd68d309747739729d786705f14f9c41778d6ee..50c446faebf12b6086a816ae5dac0319b86c5862 100644 (file)
@@ -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;i<MAX_GETWDCACHE;i++)
-    {
-      string_set(&ino_list[i].dos_path,"");
-      ino_list[i].valid = False;
-    }
-  }
-
-  /*  Get the inode of the current directory, if this doesn't work we're
-      in trouble :-) */
-
-  if (sys_stat(".",&st) == -1)
-  {
-    DEBUG(0,("Very strange, couldn't stat \".\" path=%s\n", path));
-    return(dos_getwd(path));
-  }
-
-
-  for (i=0; i<MAX_GETWDCACHE; i++)
-    if (ino_list[i].valid)
-    {
-
-      /*  If we have found an entry with a matching inode and dev number
-          then find the inode number for the directory in the cached string.
-          If this agrees with that returned by the stat for the current
-          directory then all is o.k. (but make sure it is a directory all
-          the same...) */
-
-      if (st.st_ino == ino_list[i].inode &&
-          st.st_dev == ino_list[i].dev)
-      {
-        if (dos_stat(ino_list[i].dos_path,&st2) == 0)
-        {
-          if (st.st_ino == st2.st_ino &&
-              st.st_dev == st2.st_dev &&
-              (st2.st_mode & S_IFMT) == S_IFDIR)
-          {
-            pstrcpy (path, ino_list[i].dos_path);
-
-            /* promote it for future use */
-            array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
-            return (path);
-          }
-          else
-          {
-            /*  If the inode is different then something's changed,
-                scrub the entry and start from scratch. */
-            ino_list[i].valid = False;
-          }
-        }
-      }
-    }
-
-
-  /*  We don't have the information to hand so rely on traditional methods.
-      The very slow getcwd, which spawns a process on some systems, or the
-      not quite so bad getwd. */
-
-  if (!dos_getwd(s))
-  {
-    DEBUG(0,("dos_GetWd: dos_getwd call failed, errno %s\n",strerror(errno)));
-    return (NULL);
-  }
-
-  pstrcpy(path,s);
-
-  DEBUG(5,("dos_GetWd %s, inode %.0f, dev %.0f\n",s,(double)st.st_ino,(double)st.st_dev));
-
-  /* add it to the cache */
-  i = MAX_GETWDCACHE - 1;
-  string_set(&ino_list[i].dos_path,s);
-  ino_list[i].dev = st.st_dev;
-  ino_list[i].inode = st.st_ino;
-  ino_list[i].valid = True;
-
-  /* put it at the top of the list */
-  array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
-
-  return (path);
-}
index f2d89eebb71ebddb0cf29fbd0ccaa099aba30294..aced56bc2f7296ab041326b139ea7a6223d20028 100644 (file)
@@ -410,137 +410,6 @@ void unix_clean_name(char *s)
   trim_string(s,NULL,"/..");
 }
 
-/*******************************************************************
-reduce a file name, removing .. elements and checking that 
-it is below dir in the heirachy. This uses dos_GetWd() and so must be run
-on the system that has the referenced file system.
-
-widelinks are allowed if widelinks is true
-********************************************************************/
-
-BOOL reduce_name(char *s,char *dir,BOOL widelinks)
-{
-#ifndef REDUCE_PATHS
-  return True;
-#else
-  pstring dir2;
-  pstring wd;
-  pstring base_name;
-  pstring newname;
-  char *p=NULL;
-  BOOL relative = (*s != '/');
-
-  *dir2 = *wd = *base_name = *newname = 0;
-
-  if (widelinks)
-  {
-    unix_clean_name(s);
-    /* can't have a leading .. */
-    if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
-    {
-      DEBUG(3,("Illegal file name? (%s)\n",s));
-      return(False);
-    }
-
-    if (strlen(s) == 0)
-      pstrcpy(s,"./");
-
-    return(True);
-  }
-  
-  DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
-
-  /* remove any double slashes */
-  all_string_sub(s,"//","/",0);
-
-  pstrcpy(base_name,s);
-  p = strrchr(base_name,'/');
-
-  if (!p)
-    return(True);
-
-  if (!dos_GetWd(wd))
-  {
-    DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
-    return(False);
-  }
-
-  if (dos_ChDir(dir) != 0)
-  {
-    DEBUG(0,("couldn't chdir to %s\n",dir));
-    return(False);
-  }
-
-  if (!dos_GetWd(dir2))
-  {
-    DEBUG(0,("couldn't getwd for %s\n",dir));
-    dos_ChDir(wd);
-    return(False);
-  }
-
-  if (p && (p != base_name))
-  {
-    *p = 0;
-    if (strcmp(p+1,".")==0)
-      p[1]=0;
-    if (strcmp(p+1,"..")==0)
-      *p = '/';
-  }
-
-  if (dos_ChDir(base_name) != 0)
-  {
-    dos_ChDir(wd);
-    DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
-    return(False);
-  }
-
-  if (!dos_GetWd(newname))
-  {
-    dos_ChDir(wd);
-    DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
-    return(False);
-  }
-
-  if (p && (p != base_name))
-  {
-    pstrcat(newname,"/");
-    pstrcat(newname,p+1);
-  }
-
-  {
-    size_t l = strlen(dir2);    
-    if (dir2[l-1] == '/')
-      l--;
-
-    if (strncmp(newname,dir2,l) != 0)
-    {
-      dos_ChDir(wd);
-      DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,(int)l));
-      return(False);
-    }
-
-    if (relative)
-    {
-      if (newname[l] == '/')
-        pstrcpy(s,newname + l + 1);
-      else
-        pstrcpy(s,newname+l);
-    }
-    else
-      pstrcpy(s,newname);
-  }
-
-  dos_ChDir(wd);
-
-  if (strlen(s) == 0)
-    pstrcpy(s,"./");
-
-  DEBUG(3,("reduced to %s\n",s));
-  return(True);
-#endif
-}
-
-
 /****************************************************************************
   make a dir struct
 ****************************************************************************/
index c03e1025b188921457f9bffb79d76bd427aa5f0e..64e5908b19efbceba48041194fc726bb9a2159bd 100644 (file)
@@ -92,7 +92,7 @@ pstring global_scope = "";
 #define VALID(i) iSERVICE(i).valid
 
 int keepalive = DEFAULT_KEEPALIVE;
-extern BOOL use_getwd_cache;
+BOOL use_getwd_cache;
 
 extern int extra_time_offset;
 
index 8e2382ee9f6add32552f096b0a61e2648db7c962..269d2865176dc3bf1dfc9ab7dd09e8767bfa6e52 100644 (file)
@@ -61,7 +61,7 @@ mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname)
 
     dname = parent_dirname(fname);
     DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname));
-    if (dos_stat(dname,&sbuf) != 0) {
+    if (vfs_stat(conn,dname,&sbuf) != 0) {
       DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno)));
       return(0);      /* *** shouldn't happen! *** */
     }
@@ -191,7 +191,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT *
 
   if (!st) {
     st = &st1;
-    if (conn->vfs_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. */
index 294e80250a152232018dbc8f0d0240257408c021..67fa85d9cbd98e008494375e913ac08c541370f6 100644 (file)
@@ -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 <David.Clerc@cui.unige.ch>
index a8cdcea17da7f9c9651b63dcbfa66abe1cc85a9d..5a2f86531032d1b29fd49f5829584896e0d52f7d 100644 (file)
@@ -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);
        }
        
index 59c3c83f6f99ceba145755554f09b3cd2202047b..4a8260421c4ecea7e2ca7b45d6073b3a6a24436b 100644 (file)
@@ -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();
index 9dd5a9ef68d87d5449b3db5fd0454abe4712a4a9..8624bdb9b4a3db6085e7ca4086f5f1506bf9f685 100644 (file)
@@ -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;
index 272d54e3baadba54965aca1d7abc61fcb715482e..e82bbefa5a8b4d09385b7aaaa1a273e775cf7224 100644 (file)
@@ -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
        
index 7ab448e6a305094f86870bab82d2b59666459832..48f6163596dacbc95dca3998a3bf273a591274dc 100644 (file)
@@ -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);
   
index 5db1689450027055620c0a2a410efb9aa04742ba..12ba9bda8418088d171e28304ffee2b34af6bf03 100644 (file)
@@ -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
index 496d3e0432b8b50a448fbcea1026aef5d17d9870..631d4bedbebfcaa9bbf0e021bb3b0e712f3f58db 100644 (file)
@@ -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<MAX_GETWDCACHE;i++)
+    {
+      string_set(&ino_list[i].dos_path,"");
+      ino_list[i].valid = False;
+    }
+  }
+
+  /*  Get the inode of the current directory, if this doesn't work we're
+      in trouble :-) */
+
+  if (vfs_stat(conn, ".",&st) == -1)
+  {
+    DEBUG(0,("Very strange, couldn't stat \".\" path=%s\n", path));
+    return(vfs_getwd(conn,path));
+  }
+
+
+  for (i=0; i<MAX_GETWDCACHE; i++)
+    if (ino_list[i].valid)
+    {
+
+      /*  If we have found an entry with a matching inode and dev number
+          then find the inode number for the directory in the cached string.
+          If this agrees with that returned by the stat for the current
+          directory then all is o.k. (but make sure it is a directory all
+          the same...) */
+
+      if (st.st_ino == ino_list[i].inode &&
+          st.st_dev == ino_list[i].dev)
+      {
+        if (vfs_stat(conn,ino_list[i].dos_path,&st2) == 0)
+        {
+          if (st.st_ino == st2.st_ino &&
+              st.st_dev == st2.st_dev &&
+              (st2.st_mode & S_IFMT) == S_IFDIR)
+          {
+            pstrcpy (path, ino_list[i].dos_path);
+
+            /* promote it for future use */
+            array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
+            return (path);
+          }
+          else
+          {
+            /*  If the inode is different then something's changed,
+                scrub the entry and start from scratch. */
+            ino_list[i].valid = False;
+          }
+        }
+      }
+    }
+
+
+  /*  We don't have the information to hand so rely on traditional methods.
+      The very slow getcwd, which spawns a process on some systems, or the
+      not quite so bad getwd. */
+
+  if (!vfs_getwd(conn,s))
+  {
+    DEBUG(0,("vfs_GetWd: vfs_getwd call failed, errno %s\n",strerror(errno)));
+    return (NULL);
+  }
+
+  pstrcpy(path,s);
+
+  DEBUG(5,("vfs_GetWd %s, inode %.0f, dev %.0f\n",s,(double)st.st_ino,(double)st.st_dev));
+
+  /* add it to the cache */
+  i = MAX_GETWDCACHE - 1;
+  string_set(&ino_list[i].dos_path,s);
+  ino_list[i].dev = st.st_dev;
+  ino_list[i].inode = st.st_ino;
+  ino_list[i].valid = True;
+
+  /* put it at the top of the list */
+  array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
+
+  return (path);
+}
+
+/*******************************************************************
+ Reduce a file name, removing .. elements and checking that 
+ it is below dir in the heirachy. This uses vfs_GetWd() and so must be run
+ on the system that has the referenced file system.
+ Widelinks are allowed if widelinks is true.
+********************************************************************/
+
+BOOL reduce_name(connection_struct *conn, char *s,char *dir,BOOL widelinks)
+{
+#ifndef REDUCE_PATHS
+  return True;
+#else
+  pstring dir2;
+  pstring wd;
+  pstring base_name;
+  pstring newname;
+  char *p=NULL;
+  BOOL relative = (*s != '/');
+
+  *dir2 = *wd = *base_name = *newname = 0;
+
+  if (widelinks)
+  {
+    unix_clean_name(s);
+    /* can't have a leading .. */
+    if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
+    {
+      DEBUG(3,("Illegal file name? (%s)\n",s));
+      return(False);
+    }
+
+    if (strlen(s) == 0)
+      pstrcpy(s,"./");
+
+    return(True);
+  }
+  
+  DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
+
+  /* remove any double slashes */
+  all_string_sub(s,"//","/",0);
+
+  pstrcpy(base_name,s);
+  p = strrchr(base_name,'/');
+
+  if (!p)
+    return(True);
+
+  if (!vfs_GetWd(conn,wd))
+  {
+    DEBUG(0,("couldn't vfs_GetWd for %s %s\n",s,dir));
+    return(False);
+  }
+
+  if (vfs_ChDir(conn,dir) != 0)
+  {
+    DEBUG(0,("couldn't vfs_ChDir to %s\n",dir));
+    return(False);
+  }
+
+  if (!vfs_GetWd(conn,dir2))
+  {
+    DEBUG(0,("couldn't vfs_GetWd for %s\n",dir));
+    vfs_ChDir(conn,wd);
+    return(False);
+  }
+
+  if (p && (p != base_name))
+  {
+    *p = 0;
+    if (strcmp(p+1,".")==0)
+      p[1]=0;
+    if (strcmp(p+1,"..")==0)
+      *p = '/';
+  }
+
+  if (vfs_ChDir(conn,base_name) != 0)
+  {
+    vfs_ChDir(conn,wd);
+    DEBUG(3,("couldn't vfs_ChDir for %s %s basename=%s\n",s,dir,base_name));
+    return(False);
+  }
+
+  if (!vfs_GetWd(conn,newname))
+  {
+    vfs_ChDir(conn,wd);
+    DEBUG(2,("couldn't get vfs_GetWd for %s %s\n",s,dir2));
+    return(False);
+  }
+
+  if (p && (p != base_name))
+  {
+    pstrcat(newname,"/");
+    pstrcat(newname,p+1);
+  }
+
+  {
+    size_t l = strlen(dir2);    
+    if (dir2[l-1] == '/')
+      l--;
+
+    if (strncmp(newname,dir2,l) != 0)
+    {
+      vfs_ChDir(conn,wd);
+      DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,(int)l));
+      return(False);
+    }
+
+    if (relative)
+    {
+      if (newname[l] == '/')
+        pstrcpy(s,newname + l + 1);
+      else
+        pstrcpy(s,newname+l);
+    }
+    else
+      pstrcpy(s,newname);
+  }
+
+  vfs_ChDir(conn,wd);
+
+  if (strlen(s) == 0)
+    pstrcpy(s,"./");
+
+  DEBUG(3,("reduced to %s\n",s));
+  return(True);
+#endif
+}