r20844: Somewhat radical change - this may break the build (I will
authorJeremy Allison <jra@samba.org>
Wed, 17 Jan 2007 02:09:37 +0000 (02:09 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:17:12 +0000 (12:17 -0500)
watch carefully - so I'm doing it in one transaction so I can
roll back).

Change check_name(), reduce_name() and dptr_create() to
return NTSTATUS. This helps a lot in error path processing
and especially in reduce_name() allows us to ditch the flaky
and error-prone saving of errno and return errors directly.

Jeremy.
(This used to be commit 6133a694aa429d638320e39ffe1c49d172583ccf)

source3/rpc_server/srv_srvsvc_nt.c
source3/smbd/dir.c
source3/smbd/filename.c
source3/smbd/nttrans.c
source3/smbd/reply.c
source3/smbd/trans2.c
source3/smbd/vfs.c

index 646a414cdad603cf49989e1ebcbc893d47c4bf19..a9adaf3200e6058c35cff011e91fa3d616b71a78 100644 (file)
@@ -2073,7 +2073,8 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, const char *server_unc, const
                goto error_exit;
        }
 
-       if (!check_name(file,conn)) {
+       nt_status = check_name(conn, file);
+       if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(3,("_srv_net_file_query_secdesc: can't access %s\n", file));
                status = WERR_ACCESS_DENIED;
                goto error_exit;
@@ -2176,7 +2177,8 @@ WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, const char *server_unc, const
                goto error_exit;
        }
 
-       if (!check_name(file,conn)) {
+       nt_status = check_name(conn, file);
+       if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(3,("_srv_net_file_set_secdesc: can't access %s\n", file));
                status = WERR_ACCESS_DENIED;
                goto error_exit;
index 5a6b9713e5b16d52b64567c7d9d9ae62dbf8593c..7be5c03f1b345d6c706c6315c56cd5d5ce3f038d 100644 (file)
@@ -382,21 +382,26 @@ static void dptr_close_oldest(BOOL old)
  wcard must not be zero.
 ****************************************************************************/
 
-int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
-               const char *wcard, BOOL wcard_has_wild, uint32 attr)
+NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
+               const char *wcard, BOOL wcard_has_wild, uint32 attr, int *dptr_hnd_ret)
 {
        struct dptr_struct *dptr = NULL;
        struct smb_Dir *dir_hnd;
         const char *dir2;
+       NTSTATUS status;
 
        DEBUG(5,("dptr_create dir=%s\n", path));
 
+       *dptr_hnd_ret = -1;
+
        if (!wcard) {
-               return -1;
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (!check_name(path,conn))
-               return(-2); /* Code to say use a unix error return code. */
+       status = check_name(conn,path);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
        /* use a const pointer from here on */
        dir2 = path;
@@ -405,19 +410,20 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
 
        dir_hnd = OpenDir(conn, dir2, wcard, attr);
        if (!dir_hnd) {
-               return (-2);
+               return map_nt_error_from_unix(errno);
        }
 
        string_set(&conn->dirpath,dir2);
 
-       if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
+       if (dirhandles_open >= MAX_OPEN_DIRECTORIES) {
                dptr_idleoldest();
+       }
 
        dptr = SMB_MALLOC_P(struct dptr_struct);
        if(!dptr) {
                DEBUG(0,("malloc fail in dptr_create.\n"));
                CloseDir(dir_hnd);
-               return -1;
+               return NT_STATUS_NO_MEMORY;
        }
 
        ZERO_STRUCTP(dptr);
@@ -447,7 +453,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
                                DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
                                SAFE_FREE(dptr);
                                CloseDir(dir_hnd);
-                               return -1;
+                               return NT_STATUS_TOO_MANY_OPENED_FILES;
                        }
                }
        } else {
@@ -477,7 +483,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
                                DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
                                SAFE_FREE(dptr);
                                CloseDir(dir_hnd);
-                               return -1;
+                               return NT_STATUS_TOO_MANY_OPENED_FILES;
                        }
                }
        }
@@ -496,7 +502,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
                bitmap_clear(dptr_bmap, dptr->dnum - 1);
                SAFE_FREE(dptr);
                CloseDir(dir_hnd);
-               return -1;
+               return NT_STATUS_NO_MEMORY;
        }
        if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
                dptr->has_wild = True;
@@ -513,7 +519,8 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
 
        conn->dirptr = dptr;
 
-       return(dptr->dnum);
+       *dptr_hnd_ret = dptr->dnum;
+       return NT_STATUS_OK;
 }
 
 
index a36b7ff28211a4cdccfb9ae0897284b918b5a8eb..b69d2f3e5e7932f678927d515a70932c4e59ee82 100644 (file)
@@ -512,28 +512,25 @@ NTSTATUS unix_convert(connection_struct *conn,
  a valid one for the user to access.
 ****************************************************************************/
 
-BOOL check_name(const pstring name,connection_struct *conn)
+NTSTATUS check_name(connection_struct *conn, const pstring name)
 {
-       BOOL ret = True;
-
        if (IS_VETO_PATH(conn, name))  {
                /* Is it not dot or dot dot. */
                if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) {
-                       DEBUG(5,("file path name %s vetoed\n",name));
-                       errno = ENOENT;
-                       return False;
+                       DEBUG(5,("check_name: file path name %s vetoed\n",name));
+                       return map_nt_error_from_unix(ENOENT);
                }
        }
 
        if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
-               ret = reduce_name(conn,name);
-       }
-
-       if (!ret) {
-               DEBUG(5,("check_name on %s failed\n",name));
+               NTSTATUS status = reduce_name(conn,name);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(5,("check_name: name %s failed with %s\n",name, nt_errstr(status)));
+                       return status;
+               }
        }
 
-       return(ret);
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
index df65ad7da6ec84229a8b3428afce4db211aceb75..f4d622059276dda186597780af38457df2eb234e 100644 (file)
@@ -634,10 +634,11 @@ int reply_ntcreate_and_X(connection_struct *conn,
                return ERROR_NT(status);
        }
        /* All file access must go through check_name() */
-       if (!check_name(fname,conn)) {
+       status = check_name(conn, fname);
+       if (!NT_STATUS_IS_OK(status)) {
                restore_case_semantics(conn, file_attributes);
                END_PROFILE(SMBntcreateX);
-               return UNIXERROR(ERRDOS,ERRbadpath);
+               return ERROR_NT(status);
        }
 
        /* This is the correct thing to do (check every time) but can_delete is
@@ -1259,9 +1260,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                return ERROR_NT(status);
        }
        /* All file access must go through check_name() */
-       if (!check_name(fname,conn)) {
+       status = check_name(conn, fname);
+       if (!NT_STATUS_IS_OK(status)) {
                restore_case_semantics(conn, file_attributes);
-               return UNIXERROR(ERRDOS,ERRbadpath);
+               return ERROR_NT(status);
        }
     
        /* This is the correct thing to do (check every time) but can_delete is
@@ -1570,8 +1572,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
        ZERO_STRUCT(sbuf1);
        ZERO_STRUCT(sbuf2);
 
-       if (!CAN_WRITE(conn))
+       if (!CAN_WRITE(conn)) {
                return NT_STATUS_MEDIA_WRITE_PROTECTED;
+       }
 
        status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1582,8 +1585,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
        if (!VALID_STAT(sbuf1)) {
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
-       if (!check_name(oldname,conn)) {
-               return NT_STATUS_ACCESS_DENIED;
+       status = check_name(conn, oldname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        /* Ensure attributes match. */
@@ -1602,8 +1606,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
 
-       if (!check_name(newname,conn)) {
-               return NT_STATUS_ACCESS_DENIED;
+       status = check_name(conn, newname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        /* No links from a directory. */
@@ -1612,8 +1617,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
        }
 
        /* Ensure this is within the share. */
-       if (!reduce_name(conn, oldname) != 0) {
-               return NT_STATUS_ACCESS_DENIED;
+       status = reduce_name(conn, oldname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname));
index 9a0e544e380446e4dff260d366867a7917126903..2d11b3db989f8cfa1bd02c58e54f65b224d5cf68 100644 (file)
@@ -638,42 +638,53 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s
 
        status = unix_convert(conn, name, False, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBcheckpath);
-               status = map_checkpath_error(inbuf, status);
-               return ERROR_NT(status);
+               goto path_err;
        }
 
-       if (check_name(name,conn) && (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)) {
-               if (!S_ISDIR(sbuf.st_mode)) {
-                       END_PROFILE(SMBcheckpath);
-                       return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
-               }
-       } else {
-               /* We special case this - as when a Windows machine
-                       is parsing a path is steps through the components
-                       one at a time - if a component fails it expects
-                       ERRbadpath, not ERRbadfile.
-               */
-               if(errno == ENOENT) {
-                       /*
-                        * Windows returns different error codes if
-                        * the parent directory is valid but not the
-                        * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
-                        * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
-                        * if the path is invalid.
-                        */
-                       END_PROFILE(SMBcheckpath);
-                       return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
-               }
+       status = check_name(conn, name);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
+               goto path_err;
+       }
+
+       if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
+               DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
+               status = map_nt_error_from_unix(errno);
+               goto path_err;
+       }
 
+       if (!S_ISDIR(sbuf.st_mode)) {
                END_PROFILE(SMBcheckpath);
-               return(UNIXERROR(ERRDOS,ERRbadpath));
+               return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
        }
 
        outsize = set_message(outbuf,0,0,False);
 
        END_PROFILE(SMBcheckpath);
        return outsize;
+
+  path_err:
+
+       END_PROFILE(SMBcheckpath);
+
+       /* We special case this - as when a Windows machine
+               is parsing a path is steps through the components
+               one at a time - if a component fails it expects
+               ERRbadpath, not ERRbadfile.
+       */
+       status = map_checkpath_error(inbuf, status);
+       if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+               /*
+                * Windows returns different error codes if
+                * the parent directory is valid but not the
+                * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
+                * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
+                * if the path is invalid.
+                */
+               return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
+       }
+
+       return ERROR_NT(status);
 }
 
 /****************************************************************************
@@ -717,19 +728,23 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                        END_PROFILE(SMBgetatr);
                        return ERROR_NT(status);
                }
-               if (check_name(fname,conn) &&
-                               (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0)) {
-                       mode = dos_mode(conn,fname,&sbuf);
-                       size = sbuf.st_size;
-                       mtime = sbuf.st_mtime;
-                       if (mode & aDIR) {
-                               size = 0;
-                       }
-               } else {
-                       DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
+               status = check_name(conn, fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
                        END_PROFILE(SMBgetatr);
+                       return ERROR_NT(status);
+               }
+               if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
+                       DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
                        return UNIXERROR(ERRDOS,ERRbadfile);
                }
+
+               mode = dos_mode(conn,fname,&sbuf);
+               size = sbuf.st_size;
+               mtime = sbuf.st_mtime;
+               if (mode & aDIR) {
+                       size = 0;
+               }
        }
   
        outsize = set_message(outbuf,10,0,True);
@@ -792,9 +807,10 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return ERROR_NT(NT_STATUS_ACCESS_DENIED);
        }
 
-       if (!check_name(fname,conn)) {
+       status = check_name(conn, fname);
+       if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBsetatr);
-               return UNIXERROR(ERRDOS, ERRnoaccess);
+               return ERROR_NT(status);
        }
 
        mode = SVAL(inbuf,smb_vwv0);
@@ -950,9 +966,10 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                }
                unix_format(dir2);
 
-               if (!check_name(directory,conn)) {
+               nt_status = check_name(conn, directory);
+               if (!NT_STATUS_IS_OK(nt_status)) {
                        END_PROFILE(SMBsearch);
-                       return UNIXERROR(ERRDOS, ERRnoaccess);
+                       return ERROR_NT(nt_status);
                }
 
                p = strrchr_m(dir2,'/');
@@ -996,14 +1013,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        p = smb_buf(outbuf) + 3;
      
        if (status_len == 0) {
-               dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
-               if (dptr_num < 0) {
-                       if(dptr_num == -2) {
-                               END_PROFILE(SMBsearch);
-                               return UNIXERROR(ERRDOS, ERRnofids);
-                       }
-                       END_PROFILE(SMBsearch);
-                       return ERROR_DOS(ERRDOS,ERRnofids);
+               nt_status = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype,&dptr_num);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       return ERROR_NT(nt_status);
                }
        } else {
                dirtype = dptr_attr(dptr_num);
@@ -1839,66 +1851,73 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
                        dirtype = FILE_ATTRIBUTE_NORMAL;
                }
                status = can_delete(conn,directory,dirtype,can_defer);
-               if (!NT_STATUS_IS_OK(status))
+               if (!NT_STATUS_IS_OK(status)) {
                        return status;
+               }
 
                if (SMB_VFS_UNLINK(conn,directory) == 0) {
                        count++;
                }
        } else {
                struct smb_Dir *dir_hnd = NULL;
+               long offset = 0;
                const char *dname;
                
                if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
                        return NT_STATUS_OBJECT_NAME_INVALID;
                }
 
-               if (strequal(mask,"????????.???"))
+               if (strequal(mask,"????????.???")) {
                        pstrcpy(mask,"*");
+               }
+
+               status = check_name(conn, directory);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
 
-               if (check_name(directory,conn))
-                       dir_hnd = OpenDir(conn, directory, mask, dirtype);
+               dir_hnd = OpenDir(conn, directory, mask, dirtype);
+               if (dir_hnd == NULL) {
+                       return map_nt_error_from_unix(errno);
+               }
                
                /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
                   the pattern matches against the long name, otherwise the short name 
                   We don't implement this yet XXXX
                */
                
-               if (dir_hnd) {
-                       long offset = 0;
-                       status = NT_STATUS_NO_SUCH_FILE;
+               status = NT_STATUS_NO_SUCH_FILE;
 
-                       while ((dname = ReadDirName(dir_hnd, &offset))) {
-                               SMB_STRUCT_STAT st;
-                               pstring fname;
-                               pstrcpy(fname,dname);
+               while ((dname = ReadDirName(dir_hnd, &offset))) {
+                       SMB_STRUCT_STAT st;
+                       pstring fname;
+                       pstrcpy(fname,dname);
 
-                               if (!is_visible_file(conn, directory, dname, &st, True)) {
-                                       continue;
-                               }
+                       if (!is_visible_file(conn, directory, dname, &st, True)) {
+                               continue;
+                       }
 
-                               /* Quick check for "." and ".." */
-                               if (fname[0] == '.') {
-                                       if (!fname[1] || (fname[1] == '.' && !fname[2])) {
-                                               continue;
-                                       }
+                       /* Quick check for "." and ".." */
+                       if (fname[0] == '.') {
+                               if (!fname[1] || (fname[1] == '.' && !fname[2])) {
+                                       continue;
                                }
+                       }
 
-                               if(!mask_match(fname, mask, conn->case_sensitive))
-                                       continue;
+                       if(!mask_match(fname, mask, conn->case_sensitive)) {
+                               continue;
+                       }
                                
-                               slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
-                               status = can_delete(conn, fname, dirtype,
-                                                   can_defer);
-                               if (!NT_STATUS_IS_OK(status)) {
-                                       continue;
-                               }
-                               if (SMB_VFS_UNLINK(conn,fname) == 0)
-                                       count++;
-                               DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
+                       slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+                       status = can_delete(conn, fname, dirtype, can_defer);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               continue;
                        }
-                       CloseDir(dir_hnd);
+                       if (SMB_VFS_UNLINK(conn,fname) == 0)
+                               count++;
+                       DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
                }
+               CloseDir(dir_hnd);
        }
        
        if (count == 0 && NT_STATUS_IS_OK(status)) {
@@ -3789,9 +3808,10 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
   
-       if (!check_name(directory,conn)) {
+       status = check_name(conn, directory);
+       if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBrmdir);
-               return UNIXERROR(ERRDOS, ERRbadpath);
+               return ERROR_NT(status);
        }
 
        dptr_closepath(directory,SVAL(inbuf,smb_pid));
@@ -4267,10 +4287,11 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                }
 
                TALLOC_FREE(lck);
-               if (errno == ENOTDIR || errno == EISDIR)
+               if (errno == ENOTDIR || errno == EISDIR) {
                        status = NT_STATUS_OBJECT_NAME_COLLISION;
-               else
+               } else {
                        status = map_nt_error_from_unix(errno);
+               }
                
                DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
                        nt_errstr(status), directory,newname));
@@ -4282,98 +4303,105 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                 */
                struct smb_Dir *dir_hnd = NULL;
                const char *dname;
+               long offset = 0;
                pstring destname;
                
                if (strequal(mask,"????????.???"))
                        pstrcpy(mask,"*");
                        
-               if (check_name(directory,conn))
-                       dir_hnd = OpenDir(conn, directory, mask, attrs);
+               status = check_name(conn, directory);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+       
+               dir_hnd = OpenDir(conn, directory, mask, attrs);
+               if (dir_hnd == NULL) {
+                       return map_nt_error_from_unix(errno);
+               }
                
-               if (dir_hnd) {
-                       long offset = 0;
-                       status = NT_STATUS_NO_SUCH_FILE;
-/*                     Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
+               status = NT_STATUS_NO_SUCH_FILE;
+/*             Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
                        
-                       while ((dname = ReadDirName(dir_hnd, &offset))) {
-                               pstring fname;
-                               BOOL sysdir_entry = False;
+               while ((dname = ReadDirName(dir_hnd, &offset))) {
+                       pstring fname;
+                       BOOL sysdir_entry = False;
 
-                               pstrcpy(fname,dname);
+                       pstrcpy(fname,dname);
                                
-                               /* Quick check for "." and ".." */
-                               if (fname[0] == '.') {
-                                       if (!fname[1] || (fname[1] == '.' && !fname[2])) {
-                                               if (attrs & aDIR) {
-                                                       sysdir_entry = True;
-                                               } else {
-                                                       continue;
-                                               }
+                       /* Quick check for "." and ".." */
+                       if (fname[0] == '.') {
+                               if (!fname[1] || (fname[1] == '.' && !fname[2])) {
+                                       if (attrs & aDIR) {
+                                               sysdir_entry = True;
+                                       } else {
+                                               continue;
                                        }
                                }
+                       }
 
-                               if (!is_visible_file(conn, directory, dname, &sbuf1, False))
-                                       continue;
+                       if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
+                               continue;
+                       }
 
-                               if(!mask_match(fname, mask, conn->case_sensitive))
-                                       continue;
+                       if(!mask_match(fname, mask, conn->case_sensitive)) {
+                               continue;
+                       }
                                
-                               if (sysdir_entry) {
-                                       status = NT_STATUS_OBJECT_NAME_INVALID;
-                                       break;
-                               }
+                       if (sysdir_entry) {
+                               status = NT_STATUS_OBJECT_NAME_INVALID;
+                               break;
+                       }
 
-                               status = NT_STATUS_ACCESS_DENIED;
-                               slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
-                               if (!vfs_object_exist(conn, fname, &sbuf1)) {
-                                       status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
-                                       DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(status)));
-                                       continue;
-                               }
-                               status = can_rename(conn,fname,attrs,&sbuf1);
-                               if (!NT_STATUS_IS_OK(status)) {
-                                       DEBUG(6,("rename %s refused\n", fname));
-                                       continue;
-                               }
-                               pstrcpy(destname,newname);
-                               
-                               if (!resolve_wildcards(fname,destname)) {
-                                       DEBUG(6,("resolve_wildcards %s %s failed\n", 
-                                                 fname, destname));
-                                       continue;
-                               }
+                       status = NT_STATUS_ACCESS_DENIED;
+                       slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
+                       if (!vfs_object_exist(conn, fname, &sbuf1)) {
+                               status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+                               DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(status)));
+                               continue;
+                       }
+                       status = can_rename(conn,fname,attrs,&sbuf1);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               DEBUG(6,("rename %s refused\n", fname));
+                               continue;
+                       }
+                       pstrcpy(destname,newname);
+                       
+                       if (!resolve_wildcards(fname,destname)) {
+                               DEBUG(6,("resolve_wildcards %s %s failed\n", 
+                                                fname, destname));
+                               continue;
+                       }
                                
-                               if (strcsequal(fname,destname)) {
-                                       rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
-                                       DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
-                                       count++;
-                                       status = NT_STATUS_OK;
-                                       continue;
-                               }
+                       if (strcsequal(fname,destname)) {
+                               rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
+                               DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
+                               count++;
+                               status = NT_STATUS_OK;
+                               continue;
+                       }
 
-                               if (!replace_if_exists && 
-                                    vfs_file_exist(conn,destname, NULL)) {
-                                       DEBUG(6,("file_exist %s\n", destname));
-                                       status = NT_STATUS_OBJECT_NAME_COLLISION;
-                                       continue;
-                               }
+                       if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
+                               DEBUG(6,("file_exist %s\n", destname));
+                               status = NT_STATUS_OBJECT_NAME_COLLISION;
+                               continue;
+                       }
                                
-                               if (rename_path_prefix_equal(fname, destname)) {
-                                       return NT_STATUS_SHARING_VIOLATION;
-                               }
+                       if (rename_path_prefix_equal(fname, destname)) {
+                               return NT_STATUS_SHARING_VIOLATION;
+                       }
 
-                               lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
+                       lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
 
-                               if (!SMB_VFS_RENAME(conn,fname,destname)) {
-                                       rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
-                                       count++;
-                                       status = NT_STATUS_OK;
-                               }
-                               TALLOC_FREE(lck);
-                               DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
+                       if (!SMB_VFS_RENAME(conn,fname,destname)) {
+                               rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
+                               count++;
+                               status = NT_STATUS_OK;
                        }
-                       CloseDir(dir_hnd);
+                       TALLOC_FREE(lck);
+                       DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
                }
+               CloseDir(dir_hnd);
+       }
 
 #if 0
        /* Don't think needed any more - JRA. */
@@ -4386,8 +4414,6 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                }
 #endif
 
-       }
-       
        if (count == 0 && NT_STATUS_IS_OK(status)) {
                status = map_nt_error_from_unix(errno);
        }
@@ -4693,40 +4719,49 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        } else {
                struct smb_Dir *dir_hnd = NULL;
                const char *dname;
+               long offset = 0;
                pstring destname;
 
                if (strequal(mask,"????????.???"))
                        pstrcpy(mask,"*");
 
-               if (check_name(directory,conn))
-                       dir_hnd = OpenDir(conn, directory, mask, 0);
+               status = check_name(conn, directory);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return ERROR_NT(status);
+               }
+               
+               dir_hnd = OpenDir(conn, directory, mask, 0);
+               if (dir_hnd == NULL) {
+                       status = map_nt_error_from_unix(errno);
+                       return ERROR_NT(status);
+               }
 
-               if (dir_hnd) {
-                       long offset = 0;
-                       error = ERRbadfile;
+               error = ERRbadfile;
 
-                       while ((dname = ReadDirName(dir_hnd, &offset))) {
-                               pstring fname;
-                               pstrcpy(fname,dname);
+               while ((dname = ReadDirName(dir_hnd, &offset))) {
+                       pstring fname;
+                       pstrcpy(fname,dname);
     
-                               if (!is_visible_file(conn, directory, dname, &sbuf1, False))
-                                       continue;
+                       if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
+                               continue;
+                       }
 
-                               if(!mask_match(fname, mask, conn->case_sensitive))
-                                       continue;
+                       if(!mask_match(fname, mask, conn->case_sensitive)) {
+                               continue;
+                       }
 
-                               error = ERRnoaccess;
-                               slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
-                               pstrcpy(destname,newname);
-                               if (resolve_wildcards(fname,destname)
-                                   && NT_STATUS_IS_OK(status = copy_file(
-                                                              fname,destname,conn,ofun,
-                                                              count,target_is_directory)))
-                                       count++;
-                               DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
+                       error = ERRnoaccess;
+                       slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+                       pstrcpy(destname,newname);
+                       if (resolve_wildcards(fname,destname) &&
+                                       NT_STATUS_IS_OK(status = copy_file(
+                                               fname,destname,conn,ofun,
+                                               count,target_is_directory))) {
+                               count++;
                        }
-                       CloseDir(dir_hnd);
+                       DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
                }
+               CloseDir(dir_hnd);
        }
   
        if (count == 0) {
index 48a5a0c1ac56d11ca6b8fb4da0674b0029b80167..e91a2134fd66ca4d25e50d37caf596b7e3bad629 100644 (file)
@@ -805,8 +805,9 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
                return ERROR_NT(status);
        }
     
-       if (!check_name(fname,conn)) {
-               return UNIXERROR(ERRDOS,ERRnoaccess);
+       status = check_name(conn, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return ERROR_NT(status);
        }
 
        if (open_ofun == 0) {
@@ -1722,8 +1723,9 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
        if (!NT_STATUS_IS_OK(ntstatus)) {
                return ERROR_NT(ntstatus);
        }
-       if(!check_name(directory,conn)) {
-               return UNIXERROR(ERRDOS,ERRbadpath);
+       ntstatus = check_name(conn, directory);
+       if (!NT_STATUS_IS_OK(ntstatus)) {
+               return ERROR_NT(ntstatus);
        }
 
        p = strrchr_m(directory,'/');
@@ -1764,7 +1766,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
                        return ERROR_NT(NT_STATUS_NO_MEMORY);
                }
-                                                                                                                                                        
+
                /* Pull out the list of names. */
                ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
                if (!ea_list) {
@@ -1792,10 +1794,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        /* Save the wildcard match and attribs we are using on this directory - 
                needed as lanman2 assumes these are being saved between calls */
 
-       dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
-       if (dptr_num < 0) {
+       ntstatus = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype, &dptr_num);
+       if (!NT_STATUS_IS_OK(ntstatus)) {
                talloc_destroy(ea_ctx);
-               return(UNIXERROR(ERRDOS,ERRbadfile));
+               return ERROR_NT(ntstatus);
        }
 
        DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
@@ -2934,9 +2936,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
                if (!NT_STATUS_IS_OK(status)) {
                        return ERROR_NT(status);
                }
-               if (!check_name(fname,conn)) {
-                       DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
-                       return UNIXERROR(ERRDOS,ERRbadpath);
+               status = check_name(conn, fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
+                       return ERROR_NT(status);
                }
 
                if (INFO_LEVEL_IS_UNIX(info_level)) {
@@ -3686,7 +3689,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
-       if (!check_name(oldname,conn)) {
+       status = check_name(conn, oldname);
+       if (!NT_STATUS_IS_OK(status)) {
                return NT_STATUS_ACCESS_DENIED;
        }
 
@@ -3700,7 +3704,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
 
-       if (!check_name(newname,conn)) {
+       status = check_name(conn, newname);
+       if (!NT_STATUS_IS_OK(status)) {
                return NT_STATUS_ACCESS_DENIED;
        }
 
@@ -3710,8 +3715,10 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
        }
 
        /* Ensure this is within the share. */
-       if (!reduce_name(conn, oldname) != 0)
-               return NT_STATUS_ACCESS_DENIED;
+       status = reduce_name(conn, oldname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
        DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
 
@@ -3826,8 +3833,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                        return UNIXERROR(ERRDOS,ERRbadpath);
                }    
 
-               if(!check_name(fname, conn)) {
-                       return UNIXERROR(ERRDOS,ERRbadpath);
+               status = check_name(conn, fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return ERROR_NT(status);
                }
 
        }
@@ -4366,8 +4374,9 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                                }
                                pstrcat(rel_name, link_target);
 
-                               if (!check_name(rel_name, conn)) {
-                                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+                               status = check_name(conn, rel_name);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       return ERROR_NT(status);
                                }
                        }
 
@@ -4823,9 +4832,10 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
        }
 
-       if (!check_name(directory,conn)) {
-               DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
-               return UNIXERROR(ERRDOS, ERRnoaccess);
+       status = check_name(conn, directory);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
+               return ERROR_NT(status);
        }
 
        status = create_directory(conn, directory);
index a4ecff921af665142b4b49712c27dda9aa719030..47ac9ef4619f00508ee4889714d31abda92fad16 100644 (file)
@@ -821,7 +821,7 @@ BOOL canonicalize_path(connection_struct *conn, pstring path)
  it is below dir in the heirachy. This uses realpath.
 ********************************************************************/
 
-BOOL reduce_name(connection_struct *conn, const pstring fname)
+NTSTATUS reduce_name(connection_struct *conn, const pstring fname)
 {
 #ifdef REALPATH_TAKES_NULL
        BOOL free_resolved_name = True;
@@ -836,7 +836,6 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
        char *resolved_name = NULL;
        size_t con_path_len = strlen(conn->connectpath);
        char *p = NULL;
-       int saved_errno = errno;
 
        DEBUG(3,("reduce_name [%s] [%s]\n", fname, conn->connectpath));
 
@@ -850,8 +849,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
                switch (errno) {
                        case ENOTDIR:
                                DEBUG(3,("reduce_name: Component not a directory in getting realpath for %s\n", fname));
-                               errno = saved_errno;
-                               return False;
+                               return map_nt_error_from_unix(errno);
                        case ENOENT:
                        {
                                pstring tmp_fname;
@@ -875,8 +873,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
 #endif
                                if (!resolved_name) {
                                        DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname));
-                                       errno = saved_errno;
-                                       return False;
+                                       return map_nt_error_from_unix(errno);
                                }
                                pstrcpy(tmp_fname, resolved_name);
                                pstrcat(tmp_fname, "/");
@@ -886,8 +883,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
                                resolved_name = SMB_STRDUP(tmp_fname);
                                if (!resolved_name) {
                                        DEBUG(0,("reduce_name: malloc fail for %s\n", tmp_fname));
-                                       errno = saved_errno;
-                                       return False;
+                                       return NT_STATUS_NO_MEMORY;
                                }
 #else
 #ifdef PATH_MAX
@@ -901,9 +897,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
                        }
                        default:
                                DEBUG(1,("reduce_name: couldn't get realpath for %s\n", fname));
-                               /* Don't restore the saved errno. We need to return the error that
-                                  realpath caused here as it was not one of the cases we handle. JRA. */
-                               return False;
+                               return map_nt_error_from_unix(errno);
                }
        }
 
@@ -911,19 +905,19 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
 
        if (*resolved_name != '/') {
                DEBUG(0,("reduce_name: realpath doesn't return absolute paths !\n"));
-               if (free_resolved_name)
+               if (free_resolved_name) {
                        SAFE_FREE(resolved_name);
-               errno = saved_errno;
-               return False;
+               }
+               return NT_STATUS_OBJECT_NAME_INVALID;
        }
 
        /* Check for widelinks allowed. */
        if (!lp_widelinks(SNUM(conn)) && (strncmp(conn->connectpath, resolved_name, con_path_len) != 0)) {
                DEBUG(2, ("reduce_name: Bad access attempt: %s is a symlink outside the share path", fname));
-               if (free_resolved_name)
+               if (free_resolved_name) {
                        SAFE_FREE(resolved_name);
-               errno = EACCES;
-               return False;
+               }
+               return NT_STATUS_ACCESS_DENIED;
        }
 
         /* Check if we are allowing users to follow symlinks */
@@ -935,18 +929,18 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
                 SMB_STRUCT_STAT statbuf;
                 if ( (SMB_VFS_LSTAT(conn,fname,&statbuf) != -1) &&
                                 (S_ISLNK(statbuf.st_mode)) ) {
-                       if (free_resolved_name)
+                       if (free_resolved_name) {
                                SAFE_FREE(resolved_name);
+                       }
                         DEBUG(3,("reduce_name: denied: file path name %s is a symlink\n",resolved_name));
-                        errno = EACCES;
-                       return False;
+                       return NT_STATUS_ACCESS_DENIED;
                 }
         }
 #endif
 
        DEBUG(3,("reduce_name: %s reduced to %s\n", fname, resolved_name));
-       if (free_resolved_name)
+       if (free_resolved_name) {
                SAFE_FREE(resolved_name);
-       errno = saved_errno;
-       return(True);
+       }
+       return NT_STATUS_OK;
 }