r25117: The mega-patch Jerry was waiting for. Remove all pstrings from
authorJeremy Allison <jra@samba.org>
Wed, 12 Sep 2007 21:48:20 +0000 (21:48 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:30:41 +0000 (12:30 -0500)
the main server code paths. We should now be able to cope with
paths up to PATH_MAX length now.
Final job will be to add the TALLOC_CTX * parameter to
unix_convert to make it explicit (for Volker).
Jeremy.
(This used to be commit 7f0db75fb0f24873577dcb758a2ecee74fdc4297)

15 files changed:
source3/lib/charcnv.c
source3/lib/system.c
source3/lib/util.c
source3/printing/nt_printing.c
source3/smbd/close.c
source3/smbd/dir.c
source3/smbd/mangle.c
source3/smbd/nttrans.c
source3/smbd/open.c
source3/smbd/posix_acls.c
source3/smbd/process.c
source3/smbd/reply.c
source3/smbd/service.c
source3/smbd/trans2.c
source3/smbd/vfs.c

index 4e3b7cba62fc268b6f3fb6947e4006376328c24a..5e265234e69286f2e2f8b6e43324e86f116dc353 100644 (file)
@@ -1106,7 +1106,11 @@ static size_t pull_ascii_base_talloc(TALLOC_CTX *ctx,
                }
                /* Ensure we don't use an insane length from the client. */
                if (src_len >= 1024*1024) {
-                       smb_panic("Bad src length in pull_ascii_base_talloc\n");
+                       char *msg = talloc_asprintf(ctx,
+                                       "Bad src length (%u) in "
+                                       "pull_ascii_base_talloc",
+                                       src_len);
+                       smb_panic(msg);
                }
        }
 
index 9cef818fab213a6411c3e46d342e55405b5855d2..6c79b362a86db6b5340a99589168652b8abbe8cd 100644 (file)
@@ -573,7 +573,11 @@ char *sys_getwd(char *s)
 {
        char *wd;
 #ifdef HAVE_GETCWD
+#ifdef PATH_MAX
+       wd = (char *)getcwd(s, PATH_MAX);
+#else
        wd = (char *)getcwd(s, sizeof (pstring));
+#endif
 #else
        wd = (char *)getwd(s);
 #endif
index 5314239e07ce6d4c5e180035596d26823951da65..2d34371ab3a055254fb437ac98b8be9156deee1b 100644 (file)
@@ -1578,20 +1578,22 @@ BOOL process_exists_by_pid(pid_t pid)
 
 const char *uidtoname(uid_t uid)
 {
-       fstring name;
-       struct passwd *pass;
+       TALLOC_CTX *ctx = talloc_tos();
+       char *name = NULL;
+       struct passwd *pass = NULL;
 
-       pass = getpwuid_alloc(talloc_tos(), uid);
+       pass = getpwuid_alloc(ctx,uid);
        if (pass) {
-               fstrcpy(name, pass->pw_name);
+               name = talloc_strdup(ctx,pass->pw_name);
                TALLOC_FREE(pass);
        } else {
-               slprintf(name, sizeof(name) - 1, "%ld",(long int)uid);
+               name = talloc_asprintf(ctx,
+                               "%ld",
+                               (long int)uid);
        }
-       return talloc_strdup(talloc_tos(), name);
+       return name;
 }
 
-
 /*******************************************************************
  Convert a gid into a group name.
 ********************************************************************/
index 24729c715b7acdf0bca4f30e7cf386eb211b3e43..087af929559f711c72af2af677006c61604f21e8 100644 (file)
@@ -1746,6 +1746,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
        SMB_STRUCT_STAT st;
        int ver = 0;
        int i;
+       TALLOC_CTX *ctx = talloc_tos();
 
        memset(inbuf, '\0', sizeof(inbuf));
        memset(outbuf, '\0', sizeof(outbuf));
@@ -1825,7 +1826,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);   
                if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                        driver_unix_convert(conn,new_name,&st);
-                       if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
+                       if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
                                                OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                new_name, old_name));
@@ -1841,7 +1842,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);     
                        if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                driver_unix_convert(conn,new_name,&st);
-                               if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
+                               if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
                                                OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                        DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                        new_name, old_name));
@@ -1859,7 +1860,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);   
                        if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                driver_unix_convert(conn,new_name,&st);
-                               if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
+                               if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
                                                OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                        DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                        new_name, old_name));
@@ -1878,7 +1879,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);     
                        if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                driver_unix_convert(conn,new_name,&st);
-                               if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
+                               if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
                                                OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                        DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                        new_name, old_name));
@@ -1906,7 +1907,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                                slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);    
                                if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                        driver_unix_convert(conn,new_name,&st);
-                                       if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name,
+                                       if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name,
                                                        OPENX_FILE_EXISTS_TRUNCATE|
                                                        OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                                DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
index 4eb1a3034269d87f047aaae615d4d14e9f3d8307..40db9f9b7f72a21fa082b71b951ef8f6aae1aae7 100644 (file)
@@ -478,7 +478,8 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty
 
                TALLOC_FREE(lck);
 
-               status = rmdir_internals(fsp->conn, fsp->fsp_name);
+               status = rmdir_internals(talloc_tos(),
+                               fsp->conn, fsp->fsp_name);
 
                DEBUG(5,("close_directory: %s. Delete on close was set - "
                         "deleting directory returned %s.\n",
index 7a6815b680633a5fd9b04d7bc751adf42f73d5fb..a7b1b020b8357b60cd5684e404a4a73fd7478253 100644 (file)
@@ -1,18 +1,19 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
    Directory handling routines
    Copyright (C) Andrew Tridgell 1992-1998
-   
+   Copyright (C) Jeremy Allison 2007
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -72,15 +73,25 @@ static int dirhandles_open = 0;
  Make a dir struct.
 ****************************************************************************/
 
-void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,uint32 mode,time_t date, BOOL uc)
-{  
+BOOL make_dir_struct(TALLOC_CTX *ctx,
+                       char *buf,
+                       const char *mask,
+                       const char *fname,
+                       SMB_OFF_T size,
+                       uint32 mode,
+                       time_t date,
+                       BOOL uc)
+{
        char *p;
-       pstring mask2;
+       char *mask2 = talloc_strdup(ctx, mask);
 
-       pstrcpy(mask2,mask);
+       if (!mask2) {
+               return False;
+       }
 
-       if ((mode & aDIR) != 0)
+       if ((mode & aDIR) != 0) {
                size = 0;
+       }
 
        memset(buf+1,' ',11);
        if ((p = strchr_m(mask2,'.')) != NULL) {
@@ -88,8 +99,9 @@ void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T si
                push_ascii(buf+1,mask2,8, 0);
                push_ascii(buf+9,p+1,3, 0);
                *p = '.';
-       } else
+       } else {
                push_ascii(buf+1,mask2,11, 0);
+       }
 
        memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
        SCVAL(buf,21,mode);
@@ -100,6 +112,7 @@ void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T si
           Strange, but verified on W2K3. Needed for OS/2. JRA. */
        push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
        DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
+       return True;
 }
 
 /****************************************************************************
@@ -238,7 +251,7 @@ static void dptr_close_internal(struct dptr_struct *dptr)
 
        DLIST_REMOVE(dirptrs, dptr);
 
-       /* 
+       /*
         * Free the dnum in the bitmap. Remember the dnum value is always 
         * biased by one with respect to the bitmap.
         */
@@ -563,7 +576,10 @@ static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffs
  Return the next visible file name, skipping veto'd and invisible files.
 ****************************************************************************/
 
-const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
+const char *dptr_ReadDirName(TALLOC_CTX *ctx,
+                       struct dptr_struct *dptr,
+                       long *poffset,
+                       SMB_STRUCT_STAT *pst)
 {
        SET_STAT_INVALID(*pst);
 
@@ -578,7 +594,7 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT
        }
 
        if (!dptr->did_stat) {
-               pstring pathreal;
+               char *pathreal = NULL;
 
                /* We know the stored wcard contains no wildcard characters. See if we can match
                   with a stat call. If we can't, then set did_stat to true to
@@ -602,14 +618,19 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT
                        return dptr->wcard;
                }
 
-               pstrcpy(pathreal,dptr->path);
-               pstrcat(pathreal,"/");
-               pstrcat(pathreal,dptr->wcard);
+               pathreal = talloc_asprintf(ctx,
+                                       "%s/%s",
+                                       dptr->path,
+                                       dptr->wcard);
+               if (!pathreal) {
+                       return NULL;
+               }
 
                if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
                        /* We need to set the underlying dir_hnd offset to -1 also as
                           this function is usually called with the output from TellDir. */
                        dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
+                       TALLOC_FREE(pathreal);
                        return dptr->wcard;
                } else {
                        /* If we get any other error than ENOENT or ENOTDIR
@@ -618,10 +639,13 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT
                                /* We need to set the underlying dir_hdn offset to -1 also as
                                   this function is usually called with the output from TellDir. */
                                dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
+                               TALLOC_FREE(pathreal);
                                return dptr->wcard;
                        }
                }
 
+               TALLOC_FREE(pathreal);
+
                /* In case sensitive mode we don't search - we know if it doesn't exist 
                   with a stat we will fail. */
 
@@ -768,35 +792,43 @@ static BOOL mangle_mask_match(connection_struct *conn,
  Get an 8.3 directory entry.
 ****************************************************************************/
 
-BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fname,
-                   SMB_OFF_T *size,uint32 *mode,time_t *date,BOOL check_descend)
+BOOL get_dir_entry(TALLOC_CTX *ctx,
+               connection_struct *conn,
+               const char *mask,
+               uint32 dirtype,
+               char **pp_fname_out,
+               SMB_OFF_T *size,
+               uint32 *mode,
+               time_t *date,
+               BOOL check_descend)
 {
-       const char *dname;
+       const char *dname = NULL;
        BOOL found = False;
        SMB_STRUCT_STAT sbuf;
-       pstring path;
-       pstring pathreal;
-       pstring filename;
+       char *pathreal = NULL;
+       const char *filename = NULL;
        BOOL needslash;
 
-       *path = *pathreal = *filename = 0;
+       *pp_fname_out = NULL;
 
        needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
 
-       if (!conn->dirptr)
+       if (!conn->dirptr) {
                return(False);
+       }
 
        while (!found) {
                long curoff = dptr_TellDir(conn->dirptr);
-               dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
+               dname = dptr_ReadDirName(ctx, conn->dirptr, &curoff, &sbuf);
 
                DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
                        (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
 
-               if (dname == NULL)
+               if (dname == NULL) {
                        return(False);
+               }
 
-               pstrcpy(filename,dname);
+               filename = dname;
 
                /* notice the special *.* handling. This appears to be the only difference
                        between the wildcard handling in this routine and in the trans2 routines.
@@ -805,44 +837,65 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fn
                if ((strcmp(mask,"*.*") == 0) ||
                    mask_match_search(filename,mask,False) ||
                    mangle_mask_match(conn,filename,mask)) {
+                       char mname[13];
 
                        if (!mangle_is_8_3(filename, False, conn->params)) {
-                               char mname[13];
                                if (!name_to_8_3(filename,mname,False,
                                           conn->params)) {
                                        continue;
                                }
-                               pstrcpy(filename,mname);
+                               filename = mname;
+                       }
+
+                       if (needslash) {
+                               pathreal = talloc_asprintf(ctx,
+                                               "%s/%s",
+                                               conn->dirpath,
+                                               dname);
+                       } else {
+                               pathreal = talloc_asprintf(ctx,
+                                               "%s%s",
+                                               conn->dirpath,
+                                               dname);
+                       }
+                       if (!pathreal) {
+                               return False;
                        }
 
-                       pstrcpy(fname,filename);
-                       *path = 0;
-                       pstrcpy(path,conn->dirpath);
-                       if(needslash)
-                               pstrcat(path,"/");
-                       pstrcpy(pathreal,path);
-                       pstrcat(path,fname);
-                       pstrcat(pathreal,dname);
                        if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
-                               DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
+                               DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",
+                                       pathreal, strerror(errno) ));
+                               TALLOC_FREE(pathreal);
                                continue;
                        }
-         
+
                        *mode = dos_mode(conn,pathreal,&sbuf);
 
                        if (!dir_check_ftype(conn,*mode,dirtype)) {
                                DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype));
+                               TALLOC_FREE(pathreal);
                                continue;
                        }
 
                        *size = sbuf.st_size;
                        *date = sbuf.st_mtime;
 
-                       DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
+                       DEBUG(3,("get_dir_entry mask=[%s] found %s "
+                               "fname=%s (%s)\n",
+                               mask,
+                               pathreal,
+                               dname,
+                               filename));
 
                        found = True;
 
+                       *pp_fname_out = talloc_strdup(ctx, filename);
+                       if (!*pp_fname_out) {
+                               return False;
+                       }
+
                        DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff);
+                       TALLOC_FREE(pathreal);
                }
        }
 
@@ -1198,7 +1251,7 @@ void SeekDir(struct smb_Dir *dirp, long offset)
        if (offset != dirp->offset) {
                if (offset == START_OF_DIRECTORY_OFFSET) {
                        RewindDir(dirp, &offset);
-                       /* 
+                       /*
                         * Ok we should really set the file number here
                         * to 1 to enable ".." to be returned next. Trouble
                         * is I'm worried about callers using SeekDir(dirp,0)
index 61490c444eb8262ae55f93d64eb6ca8c3e1f20c8..4c00f6d14ab9f9bd436077ba3e2dfa072084b960 100644 (file)
@@ -135,6 +135,8 @@ BOOL name_to_8_3(const char *in,
                BOOL cache83,
                const struct share_params *p)
 {
+       memset(out,'\0',13);
+
        /* name mangling can be disabled for speed, in which case
           we just truncate the string */
        if (!lp_manglednames(p)) {
index 7886ee86ce92f2978007a22b5a1fbb0fad5bf28b..c40fbc763c586bcb6e2265962cb4a45848b9a6a7 100644 (file)
@@ -2050,16 +2050,18 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req)
 
        switch(rename_type) {
                case RENAME_FLAG_RENAME:
-                       status = rename_internals(conn, req, oldname, newname,
-                                                 attrs, False, src_has_wcard,
-                                                 dest_has_wcard);
+                       status = rename_internals(ctx, conn, req, oldname,
+                                       newname, attrs, False, src_has_wcard,
+                                       dest_has_wcard);
                        break;
                case RENAME_FLAG_HARD_LINK:
                        if (src_has_wcard || dest_has_wcard) {
                                /* No wildcards. */
                                status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
                        } else {
-                               status = hardlink_internals(conn, oldname, newname);
+                               status = hardlink_internals(conn,
+                                               oldname,
+                                               newname);
                        }
                        break;
                case RENAME_FLAG_COPY:
@@ -2235,8 +2237,15 @@ static void call_nt_transact_rename(connection_struct *conn,
                return;
        }
 
-       status = rename_internals(conn, req, fsp->fsp_name,
-                                 new_name, 0, replace_if_exists, False, dest_has_wcard);
+       status = rename_internals(ctx,
+                       conn,
+                       req,
+                       fsp->fsp_name,
+                       new_name,
+                       0,
+                       replace_if_exists,
+                       False,
+                       dest_has_wcard);
 
        if (!NT_STATUS_IS_OK(status)) {
                if (open_was_deferred(req->mid)) {
@@ -2252,7 +2261,7 @@ static void call_nt_transact_rename(connection_struct *conn,
         */
        send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0);
 
-       DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", 
+       DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n",
                 fsp->fsp_name, new_name));
 
        return;
index 691599ca972e114c852d05a5464c2d7be6511a7d..8e1068e708e641277743d4b4a063b8b694c5f0d1 100644 (file)
@@ -117,22 +117,26 @@ static void change_file_owner_to_parent(connection_struct *conn,
                  (unsigned int)parent_st.st_uid ));
 }
 
-static void change_dir_owner_to_parent(connection_struct *conn,
+static NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
                                       const char *inherit_from_dir,
                                       const char *fname,
                                       SMB_STRUCT_STAT *psbuf)
 {
-       pstring saved_dir;
+       char *saved_dir = NULL;
        SMB_STRUCT_STAT sbuf;
        SMB_STRUCT_STAT parent_st;
+       TALLOC_CTX *ctx = talloc_stackframe();
+       NTSTATUS status = NT_STATUS_OK;
        int ret;
 
        ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
        if (ret == -1) {
+               status = map_nt_error_from_unix(errno);
                DEBUG(0,("change_dir_owner_to_parent: failed to stat parent "
                         "directory %s. Error was %s\n",
                         inherit_from_dir, strerror(errno) ));
-               return;
+               TALLOC_FREE(ctx);
+               return status;
        }
 
        /* We've already done an lstat into psbuf, and we know it's a
@@ -142,14 +146,19 @@ static void change_dir_owner_to_parent(connection_struct *conn,
           should work on any UNIX (thanks tridge :-). JRA.
        */
 
-       if (!vfs_GetWd(conn,saved_dir)) {
+       saved_dir = vfs_GetWd(ctx,conn);
+       if (!saved_dir) {
+               status = map_nt_error_from_unix(errno);
                DEBUG(0,("change_dir_owner_to_parent: failed to get "
-                        "current working directory\n"));
-               return;
+                        "current working directory. Error was %s\n",
+                        strerror(errno)));
+               TALLOC_FREE(ctx);
+               return status;
        }
 
        /* Chdir into the new path. */
        if (vfs_ChDir(conn, fname) == -1) {
+               status = map_nt_error_from_unix(errno);
                DEBUG(0,("change_dir_owner_to_parent: failed to change "
                         "current working directory to %s. Error "
                         "was %s\n", fname, strerror(errno) ));
@@ -157,6 +166,7 @@ static void change_dir_owner_to_parent(connection_struct *conn,
        }
 
        if (SMB_VFS_STAT(conn,".",&sbuf) == -1) {
+               status = map_nt_error_from_unix(errno);
                DEBUG(0,("change_dir_owner_to_parent: failed to stat "
                         "directory '.' (%s) Error was %s\n",
                         fname, strerror(errno)));
@@ -170,6 +180,7 @@ static void change_dir_owner_to_parent(connection_struct *conn,
                DEBUG(0,("change_dir_owner_to_parent: "
                         "device/inode/mode on directory %s changed. "
                         "Refusing to chown !\n", fname ));
+               status = NT_STATUS_ACCESS_DENIED;
                goto out;
        }
 
@@ -177,6 +188,7 @@ static void change_dir_owner_to_parent(connection_struct *conn,
        ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1);
        unbecome_root();
        if (ret == -1) {
+               status = map_nt_error_from_unix(errno);
                DEBUG(10,("change_dir_owner_to_parent: failed to chown "
                          "directory %s to parent directory uid %u. "
                          "Error was %s\n", fname,
@@ -190,7 +202,9 @@ static void change_dir_owner_to_parent(connection_struct *conn,
 
  out:
 
+       TALLOC_FREE(ctx);
        vfs_ChDir(conn,saved_dir);
+       return status;
 }
 
 /****************************************************************************
@@ -500,9 +514,10 @@ static void validate_my_share_entries(int num,
 
        if (is_deferred_open_entry(share_entry) &&
            !open_was_deferred(share_entry->op_mid)) {
-               pstring str;
-               pstr_sprintf(str, "Got a deferred entry without a request: "
-                            "PANIC: %s\n", share_mode_str(num, share_entry));
+               char *str = talloc_asprintf(talloc_tos(),
+                       "Got a deferred entry without a request: "
+                       "PANIC: %s\n",
+                       share_mode_str(num, share_entry));
                smb_panic(str);
        }
 
@@ -539,11 +554,12 @@ static void validate_my_share_entries(int num,
 
  panic:
        {
-               pstring str;
+               char *str;
                DEBUG(0,("validate_my_share_entries: PANIC : %s\n",
                         share_mode_str(num, share_entry) ));
-               slprintf(str, sizeof(str)-1, "validate_my_share_entries: "
-                        "file %s, oplock_type = 0x%x, op_type = 0x%x\n",
+               str = talloc_asprintf(talloc_tos(),
+                       "validate_my_share_entries: "
+                       "file %s, oplock_type = 0x%x, op_type = 0x%x\n",
                         fsp->fsp_name, (unsigned int)fsp->oplock_type,
                         (unsigned int)share_entry->op_type );
                smb_panic(str);
index 64051d23b1291205734091d0b3ca2f76fe8cc338..f7cadeec3ebc57cb04d5dfab78ad604ff4bfec82 100644 (file)
@@ -79,9 +79,9 @@ typedef struct canon_ace {
 struct pai_entry {
        struct pai_entry *next, *prev;
        enum ace_owner owner_type;
-       posix_id unix_ug; 
+       posix_id unix_ug;
 };
-       
+
 struct pai_val {
        BOOL pai_protected;
        unsigned int num_entries;
@@ -1001,7 +1001,7 @@ NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_i
  Ensure the enforced permissions for this share apply.
 ****************************************************************************/
 
-static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type)
+static void apply_default_perms(const files_struct *fsp, canon_ace *pace, mode_t type)
 {
        int snum = SNUM(fsp->conn);
        mode_t and_bits = (mode_t)0;
@@ -1047,7 +1047,7 @@ static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type)
 
 static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
 {
-       fstring u_name;
+       const char *u_name = NULL;
 
        /* "Everyone" always matches every uid. */
 
@@ -1059,7 +1059,11 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
        if (uid_ace->unix_ug.uid == current_user.ut.uid && group_ace->unix_ug.gid == current_user.ut.gid)
                return True;
 
-       fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid));
+       /* u_name talloc'ed off tos. */
+       u_name = uidtoname(uid_ace->unix_ug.uid);
+       if (!u_name) {
+               return False;
+       }
        return user_in_group_sid(u_name, &group_ace->trustee);
 }
 
@@ -1074,7 +1078,7 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
 ****************************************************************************/
 
 static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
-                                                       files_struct *fsp,
+                                                       const files_struct *fsp,
                                                        const DOM_SID *pfile_owner_sid,
                                                        const DOM_SID *pfile_grp_sid,
                                                        SMB_STRUCT_STAT *pst,
@@ -2106,7 +2110,7 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head)
  Create a linked list of canonical ACE entries.
 ****************************************************************************/
 
-static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf,
+static canon_ace *canonicalise_acl( const files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf,
                                        const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type)
 {
        connection_struct *conn = fsp->conn;
@@ -4416,8 +4420,9 @@ static int check_posix_acl_group_access(connection_struct *conn, const char *fna
 
 BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
 {
-       SMB_STRUCT_STAT sbuf;  
-       pstring dname;
+       SMB_STRUCT_STAT sbuf;
+       TALLOC_CTX *ctx = talloc_tos();
+       char *dname = NULL;
        int ret;
 
        if (!CAN_WRITE(conn)) {
@@ -4425,7 +4430,12 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
        }
 
        /* Get the parent directory permission mask and owners. */
-       pstrcpy(dname, parent_dirname(fname));
+       if (!parent_dirname_talloc(ctx,
+                               fname,
+                               &dname,
+                               NULL)) {
+               return False;
+       }
        if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) {
                return False;
        }
@@ -4445,7 +4455,7 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
 #ifdef S_ISVTX
        /* sticky bit means delete only by owner or root. */
        if (sbuf.st_mode & S_ISVTX) {
-               SMB_STRUCT_STAT sbuf_file;  
+               SMB_STRUCT_STAT sbuf_file;
                if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) {
                        if (errno == ENOENT) {
                                /* If the file doesn't already exist then
@@ -4563,21 +4573,19 @@ BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_ST
  descriptor via TALLOC_FREE().  This is designed for dealing with 
  user space access checks in smbd outside of the VFS.  For example,
  checking access rights in OpenEventlog().
+
  Assume we are dealing with files (for now)
 ********************************************************************/
 
-SEC_DESCget_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
+SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
 {
        SEC_DESC *psd, *ret_sd;
        connection_struct conn;
        files_struct finfo;
        struct fd_handle fh;
-       pstring path;
-       pstring filename;
-       
+
        ZERO_STRUCT( conn );
-       
+
        if ( !(conn.mem_ctx = talloc_init( "novfs_get_nt_acl" )) ) {
                DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
                return NULL;
@@ -4590,35 +4598,33 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
        }
 
        conn.params->service = -1;
-       
-       pstrcpy( path, "/" );
-       set_conn_connectpath(&conn, path);
-       
+
+       set_conn_connectpath(&conn, "/");
+
        if (!smbd_vfs_init(&conn)) {
                DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n"));
                conn_free_internal( &conn );
                return NULL;
         }
-       
+
        ZERO_STRUCT( finfo );
        ZERO_STRUCT( fh );
-       
+
        finfo.fnum = -1;
        finfo.conn = &conn;
        finfo.fh = &fh;
        finfo.fh->fd = -1;
-       pstrcpy( filename, fname );
-       finfo.fsp_name = filename;
-       
+       finfo.fsp_name = CONST_DISCARD(char *,fname);
+
        if (get_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd ) == 0) {
                DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n"));
                conn_free_internal( &conn );
                return NULL;
        }
-       
+
        ret_sd = dup_sec_desc( ctx, psd );
-       
+
        conn_free_internal( &conn );
-       
+
        return ret_sd;
 }
index 8b3e85f4b41e8d72fd58c088ff1e9b09c25d5902..29b942de81cc17e472873bf9319fb098f5de05b8 100644 (file)
@@ -1227,7 +1227,7 @@ void remove_from_common_flags2(uint32 v)
 void construct_reply_common(const char *inbuf, char *outbuf)
 {
        set_message(inbuf,outbuf,0,0,False);
-       
+
        SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
        SIVAL(outbuf,smb_rcls,0);
        SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); 
index 7ac6c4699fb3573d7f2a7a6342830b5f52c59aa9..b94c91fe8ea30c8a16aefc1b37fb0fc664b7d0ce 100644 (file)
@@ -1193,9 +1193,9 @@ void reply_dskattr(connection_struct *conn, struct smb_request *req)
 
 void reply_search(connection_struct *conn, struct smb_request *req)
 {
-       pstring mask;
+       char *mask = NULL;
        char *directory = NULL;
-       pstring fname;
+       char *fname = NULL;
        SMB_OFF_T size;
        uint32 mode;
        time_t date;
@@ -1229,8 +1229,6 @@ void reply_search(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       *mask = *fname = 0;
-
        /* If we were called as SMBffirst then we must expect close. */
        if(CVAL(req->inbuf,smb_com) == SMBffirst) {
                expect_close = True;
@@ -1297,8 +1295,8 @@ void reply_search(connection_struct *conn, struct smb_request *req)
 
                p = strrchr_m(directory,'/');
                if (!p) {
-                       pstrcpy(mask,directory);
-                       directory = talloc_strdup(talloc_tos(),".");
+                       mask = directory;
+                       directory = talloc_strdup(ctx,".");
                        if (!directory) {
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                END_PROFILE(SMBsearch);
@@ -1306,11 +1304,11 @@ void reply_search(connection_struct *conn, struct smb_request *req)
                        }
                } else {
                        *p = 0;
-                       pstrcpy(mask,p+1);
+                       mask = p+1;
                }
 
                if (*directory == '\0') {
-                       directory = talloc_strdup(talloc_tos(),".");
+                       directory = talloc_strdup(ctx,".");
                        if (!directory) {
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                END_PROFILE(SMBsearch);
@@ -1349,7 +1347,10 @@ void reply_search(connection_struct *conn, struct smb_request *req)
                        goto SearchEmpty;
                }
                string_set(&conn->dirpath,dptr_path(dptr_num));
-               pstrcpy(mask, dptr_wcard(dptr_num));
+               mask = dptr_wcard(dptr_num);
+               if (!mask) {
+                       goto SearchEmpty;
+               }
                /*
                 * For a 'continue' search we have no string. So
                 * check from the initial saved string.
@@ -1363,8 +1364,12 @@ void reply_search(connection_struct *conn, struct smb_request *req)
        if ((dirtype&0x1F) == aVOLID) {
                char buf[DIR_STRUCT_SIZE];
                memcpy(buf,status,21);
-               make_dir_struct(buf,"???????????",volume_label(SNUM(conn)),
-                               0,aVOLID,0,!allow_long_path_components);
+               if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
+                               0,aVOLID,0,!allow_long_path_components)) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       END_PROFILE(SMBsearch);
+                       return;
+               }
                dptr_fill(buf+12,dptr_num);
                if (dptr_zero(buf+12) && (status_len==0)) {
                        numentries = 1;
@@ -1393,12 +1398,23 @@ void reply_search(connection_struct *conn, struct smb_request *req)
                }
 
                for (i=numentries;(i<maxentries) && !finished;i++) {
-                       finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
+                       finished = !get_dir_entry(ctx,conn,mask,dirtype,&fname,
+                                       &size,&mode,&date,check_descend);
                        if (!finished) {
                                char buf[DIR_STRUCT_SIZE];
                                memcpy(buf,status,21);
-                               make_dir_struct(buf,mask,fname,size, mode,date,
-                                               !allow_long_path_components);
+                               if (!make_dir_struct(ctx,
+                                               buf,
+                                               mask,
+                                               fname,
+                                               size,
+                                               mode,
+                                               date,
+                                               !allow_long_path_components)) {
+                                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                                       END_PROFILE(SMBsearch);
+                                       return;
+                               }
                                if (!dptr_fill(buf+12,dptr_num)) {
                                        break;
                                }
@@ -2237,8 +2253,10 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
  * unlink a file with all relevant access checks
  *******************************************************************/
 
-static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
-                         char *fname, uint32 dirtype)
+static NTSTATUS do_unlink(connection_struct *conn,
+                       struct smb_request *req,
+                       const char *fname,
+                       uint32 dirtype)
 {
        SMB_STRUCT_STAT sbuf;
        uint32 fattr;
@@ -2362,15 +2380,14 @@ static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                          uint32 dirtype, const char *name_in, BOOL has_wild)
 {
-       pstring directory;
-       pstring mask;
+       const char *directory = NULL;
+       char *mask = NULL;
        char *name = NULL;
-       char *p;
+       char *p = NULL;
        int count=0;
        NTSTATUS status = NT_STATUS_OK;
        SMB_STRUCT_STAT sbuf;
-
-       *directory = *mask = 0;
+       TALLOC_CTX *ctx = talloc_tos();
 
        status = unix_convert(conn, name_in, has_wild, &name, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
@@ -2379,12 +2396,15 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
 
        p = strrchr_m(name,'/');
        if (!p) {
-               pstrcpy(directory,".");
-               pstrcpy(mask,name);
+               directory = talloc_strdup(ctx, ".");
+               if (!directory) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               mask = name;
        } else {
                *p = 0;
-               pstrcpy(directory,name);
-               pstrcpy(mask,p+1);
+               directory = name;
+               mask = p+1;
        }
 
        /*
@@ -2398,18 +2418,23 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
 
        if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
                char *new_mask = NULL;
-               mangle_lookup_name_from_8_3(talloc_tos(),
+               mangle_lookup_name_from_8_3(ctx,
                                mask,
                                &new_mask,
                                conn->params );
                if (new_mask) {
-                       pstrcpy(mask, new_mask);
+                       mask = new_mask;
                }
        }
 
        if (!has_wild) {
-               pstrcat(directory,"/");
-               pstrcat(directory,mask);
+               directory = talloc_asprintf(ctx,
+                               "%s/%s",
+                               directory,
+                               mask);
+               if (!directory) {
+                       return NT_STATUS_NO_MEMORY;
+               }
                if (dirtype == 0) {
                        dirtype = FILE_ATTRIBUTE_NORMAL;
                }
@@ -2435,7 +2460,8 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                }
 
                if (strequal(mask,"????????.???")) {
-                       pstrcpy(mask,"*");
+                       mask[0] = '*';
+                       mask[1] = '\0';
                }
 
                status = check_name(conn, directory);
@@ -2447,35 +2473,37 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                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
                */
-               
+
                status = NT_STATUS_NO_SUCH_FILE;
 
                while ((dname = ReadDirName(dir_hnd, &offset))) {
                        SMB_STRUCT_STAT st;
-                       pstring fname;
-                       pstrcpy(fname,dname);
+                       char *fname = NULL;
 
                        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;
-                               }
+                       if (ISDOT(dname) || ISDOTDOT(dname)) {
+                               continue;
                        }
 
-                       if(!mask_match(fname, mask, conn->case_sensitive)) {
+                       if(!mask_match(dname, mask, conn->case_sensitive)) {
                                continue;
                        }
-                               
-                       slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+
+                       fname = talloc_asprintf(ctx, "%s/%s",
+                                       directory,
+                                       dname);
+                       if (!fname) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
 
                        status = check_name(conn, fname);
                        if (!NT_STATUS_IS_OK(status)) {
@@ -2485,16 +2513,19 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
 
                        status = do_unlink(conn, req, fname, dirtype);
                        if (!NT_STATUS_IS_OK(status)) {
+                               TALLOC_FREE(fname);
                                continue;
                        }
 
                        count++;
                        DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
                                 fname));
+
+                       TALLOC_FREE(fname);
                }
                CloseDir(dir_hnd);
        }
-       
+
        if (count == 0 && NT_STATUS_IS_OK(status)) {
                status = map_nt_error_from_unix(errno);
        }
@@ -2577,9 +2608,12 @@ void reply_unlink(connection_struct *conn, struct smb_request *req)
 
 static void fail_readraw(void)
 {
-       pstring errstr;
-       slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
-               strerror(errno) );
+       const char *errstr = talloc_asprintf(talloc_tos(),
+                       "FAIL ! reply_readbraw: socket write fail (%s)",
+                       strerror(errno));
+       if (!errstr) {
+               errstr = "";
+       }
        exit_server_cleanly(errstr);
 }
 
@@ -3097,12 +3131,14 @@ static int setup_readX_header(const uint8 *inbuf, uint8 *outbuf,
                              False);
        data = smb_buf(outbuf);
 
+       memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
+
+       SCVAL(outbuf,smb_vwv0,0xFF);
        SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
        SSVAL(outbuf,smb_vwv5,smb_maxcnt);
        SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
        SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
        SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
-       SCVAL(outbuf,smb_vwv0,0xFF);
        /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
        _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
        return outsize;
@@ -3136,7 +3172,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
 
 #if defined(WITH_SENDFILE)
        /*
-        * We can only use sendfile on a non-chained packet 
+        * We can only use sendfile on a non-chained packet
         * but we can use on a non-oplocked file. tridge proved this
         * on a train in Germany :-). JRA.
         */
@@ -3146,7 +3182,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
                uint8 headerbuf[smb_size + 12 * 2];
                DATA_BLOB header;
 
-               /* 
+               /*
                 * Set up the packet header before send. We
                 * assume here the sendfile will work (get the
                 * correct amount of data).
@@ -4790,7 +4826,9 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)
  tree recursively. Return True on ok, False on fail.
 ****************************************************************************/
 
-static BOOL recursive_rmdir(connection_struct *conn, char *directory)
+static BOOL recursive_rmdir(TALLOC_CTX *ctx,
+                       connection_struct *conn,
+                       char *directory)
 {
        const char *dname = NULL;
        BOOL ret = True;
@@ -4801,33 +4839,35 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
                return False;
 
        while((dname = ReadDirName(dir_hnd, &offset))) {
-               pstring fullname;
+               char *fullname = NULL;
                SMB_STRUCT_STAT st;
 
-               if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
+               if (ISDOT(dname) || ISDOTDOT(dname)) {
                        continue;
+               }
 
-               if (!is_visible_file(conn, directory, dname, &st, False))
+               if (!is_visible_file(conn, directory, dname, &st, False)) {
                        continue;
+               }
 
                /* Construct the full name. */
-               if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
+               fullname = talloc_asprintf(ctx,
+                               "%s/%s",
+                               directory,
+                               dname);
+               if (!fullname) {
                        errno = ENOMEM;
                        ret = False;
                        break;
                }
 
-               pstrcpy(fullname, directory);
-               pstrcat(fullname, "/");
-               pstrcat(fullname, dname);
-
                if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
                        ret = False;
                        break;
                }
 
                if(st.st_mode & S_IFDIR) {
-                       if(!recursive_rmdir(conn, fullname)) {
+                       if(!recursive_rmdir(ctx, conn, fullname)) {
                                ret = False;
                                break;
                        }
@@ -4839,6 +4879,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
                        ret = False;
                        break;
                }
+               TALLOC_FREE(fullname);
        }
        CloseDir(dir_hnd);
        return ret;
@@ -4848,7 +4889,9 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
  The internals of the rmdir code - called elsewhere.
 ****************************************************************************/
 
-NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
+NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
+                       connection_struct *conn,
+                       const char *directory)
 {
        int ret;
        SMB_STRUCT_STAT st;
@@ -4878,7 +4921,7 @@ NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
        }
 
        if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
-               /* 
+               /*
                 * Check to see if the only thing in this directory are
                 * vetoed files/directories. If so then delete them and
                 * retry. If we fail to delete any of them (and we *don't*
@@ -4909,34 +4952,40 @@ NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
 
                RewindDir(dir_hnd,&dirpos);
                while ((dname = ReadDirName(dir_hnd,&dirpos))) {
-                       pstring fullname;
+                       char *fullname = NULL;
 
-                       if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
+                       if (ISDOT(dname) || ISDOTDOT(dname)) {
                                continue;
-                       if (!is_visible_file(conn, directory, dname, &st, False))
+                       }
+                       if (!is_visible_file(conn, directory, dname, &st, False)) {
                                continue;
+                       }
+
+                       fullname = talloc_asprintf(ctx,
+                                       "%s/%s",
+                                       directory,
+                                       dname);
 
-                       /* Construct the full name. */
-                       if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
+                       if(!fullname) {
                                errno = ENOMEM;
                                break;
                        }
 
-                       pstrcpy(fullname, directory);
-                       pstrcat(fullname, "/");
-                       pstrcat(fullname, dname);
-                   
-                       if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
+                       if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
                                break;
+                       }
                        if(st.st_mode & S_IFDIR) {
                                if(lp_recursive_veto_delete(SNUM(conn))) {
-                                       if(!recursive_rmdir(conn, fullname))
+                                       if(!recursive_rmdir(ctx, conn, fullname))
                                                break;
                                }
-                               if(SMB_VFS_RMDIR(conn,fullname) != 0)
+                               if(SMB_VFS_RMDIR(conn,fullname) != 0) {
                                        break;
-                       } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
+                               }
+                       } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
                                break;
+                       }
+                       TALLOC_FREE(fullname);
                }
                CloseDir(dir_hnd);
                /* Retry the rmdir */
@@ -5012,17 +5061,17 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req)
        }
 
        dptr_closepath(directory, req->smbpid);
-       status = rmdir_internals(conn, directory);
+       status = rmdir_internals(ctx, conn, directory);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
                END_PROFILE(SMBrmdir);
                return;
        }
+
        reply_outbuf(req, 0, 0);
-  
+
        DEBUG( 3, ( "rmdir %s\n", directory ) );
-  
+
        END_PROFILE(SMBrmdir);
        return;
 }
@@ -5451,19 +5500,21 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
 
 /****************************************************************************
  The guts of the rename command, split out so it may be called by the NT SMB
- code. 
+ code.
 ****************************************************************************/
 
-NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
-                               const char *name_in,
-                               const char *newname_in,
-                               uint32 attrs,
-                               BOOL replace_if_exists,
-                               BOOL src_has_wild,
-                               BOOL dest_has_wild)
+NTSTATUS rename_internals(TALLOC_CTX *ctx,
+                       connection_struct *conn,
+                       struct smb_request *req,
+                       const char *name_in,
+                       const char *newname_in,
+                       uint32 attrs,
+                       BOOL replace_if_exists,
+                       BOOL src_has_wild,
+                       BOOL dest_has_wild)
 {
-       pstring directory;
-       pstring mask;
+       char *directory = NULL;
+       char *mask = NULL;
        char *last_component_src = NULL;
        char *last_component_dest = NULL;
        char *name = NULL;
@@ -5475,9 +5526,6 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
        struct smb_Dir *dir_hnd = NULL;
        const char *dname;
        long offset = 0;
-       pstring destname;
-
-       *directory = *mask = 0;
 
        ZERO_STRUCT(sbuf1);
        ZERO_STRUCT(sbuf2);
@@ -5496,8 +5544,8 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
 
        /*
         * Split the old name into directory and last component
-        * strings. Note that unix_convert may have stripped off a 
-        * leading ./ from both name and newname if the rename is 
+        * strings. Note that unix_convert may have stripped off a
+        * leading ./ from both name and newname if the rename is
         * at the root of the share. We need to make sure either both
         * name and newname contain a / character or neither of them do
         * as this is checked in resolve_wildcards().
@@ -5505,12 +5553,18 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
 
        p = strrchr_m(name,'/');
        if (!p) {
-               pstrcpy(directory,".");
-               pstrcpy(mask,name);
+               directory = talloc_strdup(ctx, ".");
+               if (!directory) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               mask = name;
        } else {
                *p = 0;
-               pstrcpy(directory,name);
-               pstrcpy(mask,p+1);
+               directory = talloc_strdup(ctx, name);
+               if (!directory) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               mask = p+1;
                *p = '/'; /* Replace needed for exceptional test below. */
        }
 
@@ -5525,12 +5579,12 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
 
        if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
                char *new_mask = NULL;
-               mangle_lookup_name_from_8_3(talloc_tos(),
+               mangle_lookup_name_from_8_3(ctx,
                                        mask,
                                        &new_mask,
                                        conn->params );
                if (new_mask) {
-                       pstrcpy(mask, new_mask);
+                       mask = new_mask;
                }
        }
 
@@ -5543,12 +5597,16 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
                BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
 
                /* Add a terminating '/' to the directory name. */
-               pstrcat(directory,"/");
-               pstrcat(directory,mask);
+               directory = talloc_asprintf_append(directory,
+                               "/%s",
+                               mask);
+               if (!directory) {
+                       return NT_STATUS_NO_MEMORY;
+               }
 
                /* Ensure newname contains a '/' also */
                if(strrchr_m(newname,'/') == 0) {
-                       newname = talloc_asprintf(talloc_tos(),
+                       newname = talloc_asprintf(ctx,
                                                "./%s",
                                                newname);
                        if (!newname) {
@@ -5559,23 +5617,25 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
                DEBUG(3, ("rename_internals: case_sensitive = %d, "
                          "case_preserve = %d, short case preserve = %d, "
                          "directory = %s, newname = %s, "
-                         "last_component_dest = %s, is_8_3 = %d\n", 
+                         "last_component_dest = %s, is_8_3 = %d\n",
                          conn->case_sensitive, conn->case_preserve,
-                         conn->short_case_preserve, directory, 
+                         conn->short_case_preserve, directory,
                          newname, last_component_dest, is_short_name));
 
                /* The dest name still may have wildcards. */
                if (dest_has_wild) {
                        char *mod_newname = NULL;
-                       if (!resolve_wildcards(talloc_tos(),
+                       if (!resolve_wildcards(ctx,
                                        directory,newname,&mod_newname)) {
-                               DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n", 
-                                         directory,newname));
+                               DEBUG(6, ("rename_internals: resolve_wildcards "
+                                       "%s %s failed\n",
+                                       directory,
+                                       newname));
                                return NT_STATUS_NO_MEMORY;
                        }
                        newname = mod_newname;
                }
-                               
+
                ZERO_STRUCT(sbuf1);
                SMB_VFS_STAT(conn, directory, &sbuf1);
 
@@ -5613,41 +5673,38 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
         * Wildcards - process each file that matches.
         */
        if (strequal(mask,"????????.???")) {
-               pstrcpy(mask,"*");
+               mask[0] = '*';
+               mask[1] = '\0';
        }
-                       
+
        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);
        }
-               
+
        status = NT_STATUS_NO_SUCH_FILE;
        /*
         * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
         * - gentest fix. JRA
         */
-                       
+
        while ((dname = ReadDirName(dir_hnd, &offset))) {
-               files_struct *fsp;
-               pstring fname;
+               files_struct *fsp = NULL;
+               char *fname = NULL;
+               char *destname = NULL;
                BOOL sysdir_entry = False;
-               char *mod_destname = NULL;
 
-               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;
-                               }
+               if (ISDOT(dname) || ISDOTDOT(dname)) {
+                       if (attrs & aDIR) {
+                               sysdir_entry = True;
+                       } else {
+                               continue;
                        }
                }
 
@@ -5655,27 +5712,34 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
                        continue;
                }
 
-               if(!mask_match(fname, mask, conn->case_sensitive)) {
+               if(!mask_match(dname, mask, conn->case_sensitive)) {
                        continue;
                }
-                               
+
                if (sysdir_entry) {
                        status = NT_STATUS_OBJECT_NAME_INVALID;
                        break;
                }
 
-               slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
+               fname = talloc_asprintf(ctx,
+                               "%s/%s",
+                               directory,
+                               dname);
+               if (!fname) {
+                       return NT_STATUS_NO_MEMORY;
+               }
 
-               pstrcpy(destname,newname);
-                       
-               if (!resolve_wildcards(talloc_tos(),
-                               fname,destname,&mod_destname)) {
-                       DEBUG(6, ("resolve_wildcards %s %s failed\n", 
+               if (!resolve_wildcards(ctx,
+                               fname,newname,&destname)) {
+                       DEBUG(6, ("resolve_wildcards %s %s failed\n",
                                  fname, destname));
+                       TALLOC_FREE(fname);
                        continue;
                }
-               pstrcpy(destname,mod_destname);
-                               
+               if (!destname) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
                ZERO_STRUCT(sbuf1);
                SMB_VFS_STAT(conn, fname, &sbuf1);
 
@@ -5714,13 +5778,16 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
 
                DEBUG(3,("rename_internals: doing rename on %s -> "
                         "%s\n",fname,destname));
+
+               TALLOC_FREE(fname);
+               TALLOC_FREE(destname);
        }
        CloseDir(dir_hnd);
 
        if (count == 0 && NT_STATUS_IS_OK(status)) {
                status = map_nt_error_from_unix(errno);
        }
-       
+
        return status;
 }
 
@@ -5804,7 +5871,7 @@ void reply_mv(connection_struct *conn, struct smb_request *req)
 
        DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
 
-       status = rename_internals(conn, req, name, newname, attrs, False,
+       status = rename_internals(ctx, conn, req, name, newname, attrs, False,
                                  src_has_wcard, dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                if (open_was_deferred(req->mid)) {
@@ -5831,9 +5898,10 @@ void reply_mv(connection_struct *conn, struct smb_request *req)
  * TODO: check error codes on all callers
  */
 
-NTSTATUS copy_file(connection_struct *conn,
-                       char *src,
-                       char *dest1,
+NTSTATUS copy_file(TALLOC_CTX *ctx,
+                       connection_struct *conn,
+                       const char *src,
+                       const char *dest1,
                        int ofun,
                        int count,
                        BOOL target_is_directory)
@@ -5841,24 +5909,32 @@ NTSTATUS copy_file(connection_struct *conn,
        SMB_STRUCT_STAT src_sbuf, sbuf2;
        SMB_OFF_T ret=-1;
        files_struct *fsp1,*fsp2;
-       pstring dest;
+       char *dest = NULL;
        uint32 dosattrs;
        uint32 new_create_disposition;
        NTSTATUS status;
-       pstrcpy(dest,dest1);
+
+       dest = talloc_strdup(ctx, dest1);
+       if (!dest) {
+               return NT_STATUS_NO_MEMORY;
+       }
        if (target_is_directory) {
-               char *p = strrchr_m(src,'/');
+               const char *p = strrchr_m(src,'/');
                if (p) {
                        p++;
                } else {
                        p = src;
                }
-               pstrcat(dest,"/");
-               pstrcat(dest,p);
+               dest = talloc_asprintf_append(dest,
+                               "/%s",
+                               p);
+               if (!dest) {
+                       return NT_STATUS_NO_MEMORY;
+               }
        }
 
        if (!vfs_file_exist(conn,src,&src_sbuf)) {
+               TALLOC_FREE(dest);
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
@@ -5867,6 +5943,7 @@ NTSTATUS copy_file(connection_struct *conn,
        } else {
                if (!map_open_params_to_ntcreate(dest1,0,ofun,
                                NULL, NULL, &new_create_disposition, NULL)) {
+                       TALLOC_FREE(dest);
                        return NT_STATUS_INVALID_PARAMETER;
                }
        }
@@ -5881,6 +5958,7 @@ NTSTATUS copy_file(connection_struct *conn,
                        NULL, &fsp1);
 
        if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(dest);
                return status;
        }
 
@@ -5898,6 +5976,8 @@ NTSTATUS copy_file(connection_struct *conn,
                        INTERNAL_OPEN_ONLY,
                        NULL, &fsp2);
 
+       TALLOC_FREE(dest);
+
        if (!NT_STATUS_IS_OK(status)) {
                close_file(fsp1,ERROR_CLOSE);
                return status;
@@ -5913,7 +5993,7 @@ NTSTATUS copy_file(connection_struct *conn,
                        src_sbuf.st_size = 0;
                }
        }
-  
+
        if (src_sbuf.st_size) {
                ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
        }
@@ -5950,8 +6030,8 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
 {
        char *name = NULL;
        char *newname = NULL;
-       pstring directory;
-       pstring mask;
+       char *directory = NULL;
+       char *mask = NULL;
        char *p;
        int count=0;
        int error = ERRnoaccess;
@@ -5978,8 +6058,6 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
        ofun = SVAL(req->inbuf,smb_vwv1);
        flags = SVAL(req->inbuf,smb_vwv2);
 
-       *directory = *mask = 0;
-
        p = smb_buf(req->inbuf);
        p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
                                   0, STR_TERMINATE, &status,
@@ -6080,12 +6158,22 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
 
        p = strrchr_m(name,'/');
        if (!p) {
-               pstrcpy(directory,"./");
-               pstrcpy(mask,name);
+               directory = talloc_strdup(ctx, "./");
+               if (!directory) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       END_PROFILE(SMBcopy);
+                       return;
+               }
+               mask = name;
        } else {
                *p = 0;
-               pstrcpy(directory,name);
-               pstrcpy(mask,p+1);
+               directory = talloc_strdup(ctx, name);
+               if (!directory) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       END_PROFILE(SMBcopy);
+                       return;
+               }
+               mask = p+1;
        }
 
        /*
@@ -6099,21 +6187,22 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
 
        if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
                char *new_mask = NULL;
-               mangle_lookup_name_from_8_3( talloc_tos(),
+               mangle_lookup_name_from_8_3(ctx,
                                        mask,
                                        &new_mask,
                                        conn->params );
                if (new_mask) {
-                       pstrcpy(mask, new_mask);
+                       mask = new_mask;
                }
        }
 
        if (!source_has_wild) {
-               pstrcat(directory,"/");
-               pstrcat(directory,mask);
+               directory = talloc_asprintf_append(directory,
+                               "/%s",
+                               mask);
                if (dest_has_wild) {
                        char *mod_newname = NULL;
-                       if (!resolve_wildcards(talloc_tos(),
+                       if (!resolve_wildcards(ctx,
                                        directory,newname,&mod_newname)) {
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                END_PROFILE(SMBcopy);
@@ -6135,9 +6224,9 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
                        END_PROFILE(SMBcopy);
                        return;
                }
-               
-               status = copy_file(conn,directory,newname,ofun,
-                                       count,target_is_directory);
+
+               status = copy_file(ctx,conn,directory,newname,ofun,
+                               count,target_is_directory);
 
                if(!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
@@ -6148,12 +6237,13 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
                }
        } else {
                struct smb_Dir *dir_hnd = NULL;
-               const char *dname;
+               const char *dname = NULL;
                long offset = 0;
-               pstring destname;
 
-               if (strequal(mask,"????????.???"))
-                       pstrcpy(mask,"*");
+               if (strequal(mask,"????????.???")) {
+                       mask[0] = '*';
+                       mask[1] = '\0';
+               }
 
                status = check_name(conn, directory);
                if (!NT_STATUS_IS_OK(status)) {
@@ -6161,7 +6251,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
                        END_PROFILE(SMBcopy);
                        return;
                }
-               
+
                dir_hnd = OpenDir(conn, directory, mask, 0);
                if (dir_hnd == NULL) {
                        status = map_nt_error_from_unix(errno);
@@ -6173,26 +6263,41 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
                error = ERRbadfile;
 
                while ((dname = ReadDirName(dir_hnd, &offset))) {
-                       char *mod_destname = NULL;
-                       pstring fname;
-                       pstrcpy(fname,dname);
-    
+                       char *destname = NULL;
+                       char *fname = NULL;
+
+                       if (ISDOT(dname) || ISDOTDOT(dname)) {
+                               continue;
+                       }
+
                        if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
                                continue;
                        }
 
-                       if(!mask_match(fname, mask, conn->case_sensitive)) {
+                       if(!mask_match(dname, mask, conn->case_sensitive)) {
                                continue;
                        }
 
                        error = ERRnoaccess;
-                       slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
-                       pstrcpy(destname,newname);
-                       if (!resolve_wildcards(talloc_tos(),
-                                       fname,destname,&mod_destname)) {
+                       fname = talloc_asprintf(ctx,
+                                       "%s/%s",
+                                       directory,
+                                       dname);
+                       if (!fname) {
+                               reply_nterror(req, NT_STATUS_NO_MEMORY);
+                               END_PROFILE(SMBcopy);
+                               return;
+                       }
+
+                       if (!resolve_wildcards(ctx,
+                                       fname,newname,&destname)) {
                                continue;
                        }
-                       pstrcpy(destname,mod_destname);
+                       if (!destname) {
+                               reply_nterror(req, NT_STATUS_NO_MEMORY);
+                               END_PROFILE(SMBcopy);
+                               return;
+                       }
 
                        status = check_name(conn, fname);
                        if (!NT_STATUS_IS_OK(status)) {
@@ -6200,25 +6305,27 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
                                END_PROFILE(SMBcopy);
                                return;
                        }
-               
+
                        status = check_name(conn, destname);
                        if (!NT_STATUS_IS_OK(status)) {
                                reply_nterror(req, status);
                                END_PROFILE(SMBcopy);
                                return;
                        }
-               
+
                        DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
 
-                       status = copy_file(conn,fname,destname,ofun,
+                       status = copy_file(ctx,conn,fname,destname,ofun,
                                        count,target_is_directory);
                        if (NT_STATUS_IS_OK(status)) {
                                count++;
                        }
+                       TALLOC_FREE(fname);
+                       TALLOC_FREE(destname);
                }
                CloseDir(dir_hnd);
        }
-  
+
        if (count == 0) {
                if(err) {
                        /* Error on close... */
index aeb0e0f31d059364c18222329ecfd1a17aa233fd..4daa2924a27ac4566a9ddcee8fa2d9d932551593 100644 (file)
@@ -52,7 +52,7 @@ static BOOL canonicalize_path(connection_struct *conn, pstring path)
  Observent people will notice a similarity between this and check_path_syntax :-).
 ****************************************************************************/
 
-void set_conn_connectpath(connection_struct *conn, const pstring connectpath)
+void set_conn_connectpath(connection_struct *conn, const char *connectpath)
 {
        pstring destname;
        char *d = destname;
@@ -1117,27 +1117,31 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                                 strerror(errno) ));
                }
                change_to_root_user();
-               /* Call VFS disconnect hook */    
+               /* Call VFS disconnect hook */
                SMB_VFS_DISCONNECT(conn);
                yield_connection(conn, lp_servicename(snum));
                conn_free(conn);
                *status = NT_STATUS_BAD_NETWORK_NAME;
                return NULL;
        }
-       
+
        string_set(&conn->origpath,conn->connectpath);
-       
+
 #if SOFTLINK_OPTIMISATION
        /* resolve any soft links early if possible */
        if (vfs_ChDir(conn,conn->connectpath) == 0) {
-               pstring s;
-               pstrcpy(s,conn->connectpath);
-               vfs_GetWd(conn,s);
+               TALLOC_CTX *ctx = talloc_stackframe();
+               char *s = vfs_GetWd(ctx,s);
+               if (!s) {
+                       *status = map_nt_error_from_unix(errno);
+                       return NULL;
+               }
                set_conn_connectpath(conn,s);
                vfs_ChDir(conn,conn->connectpath);
+               TALLOC_FREE(ctx);
        }
 #endif
-       
+
        /*
         * Print out the 'connected as' stuff here as we need
         * to know the effective uid and gid we will be using
@@ -1153,7 +1157,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
                dbgtext( "(pid %d)\n", (int)sys_getpid() );
        }
-       
+
        /* we've finished with the user stuff - go back to root */
        change_to_root_user();
        return(conn);
index 8e03094aef5c95669e69515f052c895771106bfe..63dcb06f5dc28e23e008e51375e2b2229bafbe5e 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
    SMB transaction2 handling
    Copyright (C) Jeremy Allison                        1994-2007
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -211,7 +211,7 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str
 
                        if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
                                continue;
-               
+
                        listp = TALLOC_P(mem_ctx, struct ea_list);
                        if (!listp)
                                return NULL;
@@ -1008,7 +1008,9 @@ static void call_trans2open(connection_struct *conn,
  Case can be significant or not.
 **********************************************************/
 
-static BOOL exact_match(connection_struct *conn, char *str, char *mask)
+static BOOL exact_match(connection_struct *conn,
+               const char *str,
+               const char *mask)
 {
        if (mask[0] == '.' && mask[1] == 0)
                return False;
@@ -1134,21 +1136,29 @@ static NTSTATUS unix_perms_from_wire( connection_struct *conn,
  Get a level dependent lanman2 dir entry.
 ****************************************************************************/
 
-static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
-                                char *path_mask,uint32 dirtype,int info_level,
-                                int requires_resume_key,
-                                BOOL dont_descend,char **ppdata, 
-                                char *base_data, char *end_data,
-                                int space_remaining,
-                                BOOL *out_of_space, BOOL *got_exact_match,
-                                int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
+static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx,
+                               connection_struct *conn,
+                               uint16 flags2,
+                               const char *path_mask,
+                               uint32 dirtype,
+                               int info_level,
+                               int requires_resume_key,
+                               BOOL dont_descend,
+                               char **ppdata,
+                               char *base_data,
+                               char *end_data,
+                               int space_remaining,
+                               BOOL *out_of_space,
+                               BOOL *got_exact_match,
+                               int *last_entry_off,
+                               struct ea_list *name_list)
 {
        const char *dname;
        BOOL found = False;
        SMB_STRUCT_STAT sbuf;
-       pstring mask;
-       pstring pathreal;
-       pstring fname;
+       const char *mask = NULL;
+       char *pathreal = NULL;
+       const char *fname = NULL;
        char *p, *q, *pdata = *ppdata;
        uint32 reskey=0;
        long prev_dirpos=0;
@@ -1166,7 +1176,6 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
        BOOL check_mangled_names = lp_manglednames(conn->params);
        char mangled_name[13]; /* mangled 8.3 name. */
 
-       *fname = 0;
        *out_of_space = False;
        *got_exact_match = False;
 
@@ -1174,18 +1183,20 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
        ZERO_STRUCT(adate_ts);
        ZERO_STRUCT(create_date_ts);
 
-       if (!conn->dirptr)
+       if (!conn->dirptr) {
                return(False);
+       }
 
        p = strrchr_m(path_mask,'/');
        if(p != NULL) {
-               if(p[1] == '\0')
-                       pstrcpy(mask,"*.*");
-               else
-                       pstrcpy(mask, p+1);
-       } else
-               pstrcpy(mask, path_mask);
-
+               if(p[1] == '\0') {
+                       mask = talloc_strdup(ctx,"*.*");
+               } else {
+                       mask = p+1;
+               }
+       } else {
+               mask = path_mask;
+       }
 
        while (!found) {
                BOOL got_match;
@@ -1193,7 +1204,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
 
                /* Needed if we run out of space */
                long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
-               dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
+               dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
 
                /*
                 * Due to bugs in NT client redirectors we are not using
@@ -1206,7 +1217,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
 
                DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
                        (long)conn->dirptr,curr_dirpos));
-      
+
                if (!dname) {
                        return(False);
                }
@@ -1217,14 +1228,15 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
                 * pathreal which is composed from dname.
                 */
 
-               pstrcpy(fname,dname);
+               pathreal = NULL;
+               fname = dname;
 
                /* Mangle fname if it's an illegal name. */
-               if (mangle_must_mangle(fname,conn->params)) {
-                       if (!name_to_8_3(fname,mangled_name,True,conn->params)) {
+               if (mangle_must_mangle(dname,conn->params)) {
+                       if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
                                continue; /* Error - couldn't mangle. */
                        }
-                       pstrcpy(fname,mangled_name);
+                       fname = mangled_name;
                }
 
                if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
@@ -1250,21 +1262,34 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
                }
 
                if (got_match) {
-                       BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
+                       BOOL isdots = (ISDOT(dname) || ISDOTDOT(dname));
+
                        if (dont_descend && !isdots) {
                                continue;
                        }
-         
-                       pstrcpy(pathreal,conn->dirpath);
-                       if(needslash) {
-                               pstrcat(pathreal,"/");
+
+                       if (needslash) {
+                               pathreal = NULL;
+                               pathreal = talloc_asprintf(ctx,
+                                       "%s/%s",
+                                       conn->dirpath,
+                                       dname);
+                       } else {
+                               pathreal = talloc_asprintf(ctx,
+                                       "%s%s",
+                                       conn->dirpath,
+                                       dname);
+                       }
+
+                       if (!pathreal) {
+                               return False;
                        }
-                       pstrcat(pathreal,dname);
 
                        if (INFO_LEVEL_IS_UNIX(info_level)) {
                                if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
                                        DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
                                                pathreal,strerror(errno)));
+                                       TALLOC_FREE(pathreal);
                                        continue;
                                }
                        } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
@@ -1283,6 +1308,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
 
                                        DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
                                                pathreal,strerror(errno)));
+                                       TALLOC_FREE(pathreal);
                                        continue;
                                }
                        }
@@ -1295,6 +1321,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
 
                        if (!dir_check_ftype(conn,mode,dirtype)) {
                                DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
+                               TALLOC_FREE(pathreal);
                                continue;
                        }
 
@@ -1316,9 +1343,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
                        create_date = convert_timespec_to_time_t(create_date_ts);
                        mdate = convert_timespec_to_time_t(mdate_ts);
                        adate = convert_timespec_to_time_t(adate_ts);
-                       
+
                        DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
-         
+
                        found = True;
 
                        dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
@@ -1425,7 +1452,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
                        SSVAL(p,20,mode);
                        p += 22; /* p now points to the EA area. */
 
-                       file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
+                       file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
                        name_list = ea_list_union(name_list, file_list, &ea_len);
 
                        /* We need to determine if this entry will fit in the space available. */
@@ -1439,7 +1466,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
                        }
 
                        /* Push the ea_data followed by the name. */
-                       p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
+                       p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
                        nameptr = p;
                        len = srvstr_push(base_data, flags2,
                                          p + 1, fname, PTR_DIFF(end_data, p),
@@ -1537,7 +1564,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
                        SIVAL(pdata,0,len);
                        p = pdata + len;
                        break;
-      
+
                case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
                        DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
                        p += 4;
@@ -1713,7 +1740,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
 
                        break;
 
-               default:      
+               default:
                        return(False);
        }
 
@@ -1760,7 +1787,7 @@ static void call_trans2findfirst(connection_struct *conn,
        BOOL requires_resume_key;
        int info_level;
        char *directory = NULL;
-       pstring mask;
+       const char *mask = NULL;
        char *p;
        int last_entry_off=0;
        int dptr_num = -1;
@@ -1772,7 +1799,6 @@ static void call_trans2findfirst(connection_struct *conn,
        int space_remaining;
        BOOL mask_contains_wcard = False;
        SMB_STRUCT_STAT sbuf;
-       TALLOC_CTX *ea_ctx = NULL;
        struct ea_list *ea_list = NULL;
        NTSTATUS ntstatus = NT_STATUS_OK;
        TALLOC_CTX *ctx = talloc_tos();
@@ -1790,8 +1816,6 @@ static void call_trans2findfirst(connection_struct *conn,
        requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
        info_level = SVAL(params,6);
 
-       *mask = 0;
-
        DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
@@ -1864,10 +1888,10 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
        if(p == NULL) {
                /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
                if((directory[0] == '.') && (directory[1] == '\0')) {
-                       pstrcpy(mask,"*");
+                       mask = "*";
                        mask_contains_wcard = True;
                } else {
-                       pstrcpy(mask,directory);
+                       mask = directory;
                }
                directory = talloc_strdup(talloc_tos(), "./");
                if (!directory) {
@@ -1875,7 +1899,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                        return;
                }
        } else {
-               pstrcpy(mask,p+1);
+               mask = p+1;
                *p = 0;
        }
 
@@ -1901,16 +1925,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        reply_doserror(req, ERRDOS, ERReasnotsupported);
                        return;
                }
-                                                                                                                                                        
-               if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
-                       reply_nterror(req, NT_STATUS_NO_MEMORY);
-                       return;
-               }
 
                /* Pull out the list of names. */
-               ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
+               ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
                if (!ea_list) {
-                       talloc_destroy(ea_ctx);
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                        return;
                }
@@ -1919,7 +1937,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        *ppdata = (char *)SMB_REALLOC(
                *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
        if(*ppdata == NULL ) {
-               talloc_destroy(ea_ctx);
                reply_nterror(req, NT_STATUS_NO_MEMORY);
                return;
        }
@@ -1929,7 +1946,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        /* Realloc the params space */
        *pparams = (char *)SMB_REALLOC(*pparams, 10);
        if (*pparams == NULL) {
-               talloc_destroy(ea_ctx);
                reply_nterror(req, NT_STATUS_NO_MEMORY);
                return;
        }
@@ -1949,7 +1965,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                &conn->dirptr);
 
        if (!NT_STATUS_IS_OK(ntstatus)) {
-               talloc_destroy(ea_ctx);
                reply_nterror(req, ntstatus);
                return;
        }
@@ -1957,13 +1972,13 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        dptr_num = dptr_dnum(conn->dirptr);
        DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
 
-       /* We don't need to check for VOL here as this is returned by 
+       /* We don't need to check for VOL here as this is returned by
                a different TRANS2 call. */
-  
+
        DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
        if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
                dont_descend = True;
-    
+
        p = pdata;
        space_remaining = max_data_bytes;
        out_of_space = False;
@@ -1977,14 +1992,19 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        out_of_space = True;
                        finished = False;
                } else {
-                       finished = !get_lanman2_dir_entry(conn,
+                       TALLOC_CTX *sub_ctx = talloc_stackframe();
+
+                       finished = !get_lanman2_dir_entry(sub_ctx,
+                                       conn,
                                        req->flags2,
                                        mask,dirtype,info_level,
                                        requires_resume_key,dont_descend,
                                        &p,pdata,data_end,
                                        space_remaining, &out_of_space,
                                        &got_exact_match,
-                                       &last_entry_off, ea_list, ea_ctx);
+                                       &last_entry_off, ea_list);
+
+                       TALLOC_FREE(sub_ctx);
                }
 
                if (finished && out_of_space)
@@ -2005,8 +2025,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
        }
-  
-       talloc_destroy(ea_ctx);
 
        /* Check if we can close the dirptr */
        if(close_after_first || (finished && close_if_end)) {
@@ -2014,8 +2032,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                dptr_close(&dptr_num);
        }
 
-       /* 
-        * If there are no matching entries we must return ERRDOS/ERRbadfile - 
+       /*
+        * If there are no matching entries we must return ERRDOS/ERRbadfile -
         * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
         * the protocol level is less than NT1. Tested with smbclient. JRA.
         * This should fix the OS/2 client bug #2335.
@@ -2101,9 +2119,9 @@ static void call_trans2findnext(connection_struct *conn,
        BOOL continue_bit;
        BOOL mask_contains_wcard = False;
        char *resume_name = NULL;
-       pstring mask;
-       pstring directory;
-       char *p;
+       const char *mask = NULL;
+       const char *directory = NULL;
+       char *p = NULL;
        uint16 dirtype;
        int numentries = 0;
        int i, last_entry_off=0;
@@ -2111,7 +2129,6 @@ static void call_trans2findnext(connection_struct *conn,
        BOOL dont_descend = False;
        BOOL out_of_space = False;
        int space_remaining;
-       TALLOC_CTX *ea_ctx = NULL;
        struct ea_list *ea_list = NULL;
        NTSTATUS ntstatus = NT_STATUS_OK;
        TALLOC_CTX *ctx = talloc_tos();
@@ -2131,8 +2148,6 @@ static void call_trans2findnext(connection_struct *conn,
        requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
        continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
 
-       *mask = *directory = 0;
-
        srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
                              params+12,
                              total_params - 12, STR_TERMINATE, &ntstatus,
@@ -2202,21 +2217,15 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                        return;
                }
-                                                                                                                                                     
+
                if (!lp_ea_support(SNUM(conn))) {
                        reply_doserror(req, ERRDOS, ERReasnotsupported);
                        return;
                }
-                                                                                                                                                     
-               if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
-                       reply_nterror(req, NT_STATUS_NO_MEMORY);
-                       return;
-               }
 
                /* Pull out the list of names. */
-               ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
+               ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
                if (!ea_list) {
-                       talloc_destroy(ea_ctx);
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                        return;
                }
@@ -2225,7 +2234,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        *ppdata = (char *)SMB_REALLOC(
                *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
        if(*ppdata == NULL) {
-               talloc_destroy(ea_ctx);
                reply_nterror(req, NT_STATUS_NO_MEMORY);
                return;
        }
@@ -2236,7 +2244,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        /* Realloc the params space */
        *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
        if(*pparams == NULL ) {
-               talloc_destroy(ea_ctx);
                reply_nterror(req, NT_STATUS_NO_MEMORY);
                return;
        }
@@ -2245,7 +2252,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
        /* Check that the dptr is valid */
        if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
-               talloc_destroy(ea_ctx);
                reply_doserror(req, ERRDOS, ERRnofiles);
                return;
        }
@@ -2255,34 +2261,33 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        /* Get the wildcard mask from the dptr */
        if((p = dptr_wcard(dptr_num))== NULL) {
                DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
-               talloc_destroy(ea_ctx);
                reply_doserror(req, ERRDOS, ERRnofiles);
                return;
        }
 
-       pstrcpy(mask, p);
-       pstrcpy(directory,conn->dirpath);
+       mask = p;
+       directory = conn->dirpath;
 
        /* Get the attr mask from the dptr */
        dirtype = dptr_attr(dptr_num);
 
        DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
-               dptr_num, mask, dirtype, 
+               dptr_num, mask, dirtype,
                (long)conn->dirptr,
                dptr_TellDir(conn->dirptr)));
 
-       /* We don't need to check for VOL here as this is returned by 
+       /* We don't need to check for VOL here as this is returned by
                a different TRANS2 call. */
 
        DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
        if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
                dont_descend = True;
-    
+
        p = pdata;
        space_remaining = max_data_bytes;
        out_of_space = False;
 
-       /* 
+       /*
         * Seek to the correct position. We no longer use the resume key but
         * depend on the last file name instead.
         */
@@ -2299,12 +2304,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                if (mangle_is_mangled(resume_name, conn->params)) {
                        char *new_resume_name = NULL;
-                       mangle_lookup_name_from_8_3(talloc_tos(),
+                       mangle_lookup_name_from_8_3(ctx,
                                                resume_name,
                                                &new_resume_name,
                                                conn->params);
                        if (new_resume_name) {
-                               pstrcpy(resume_name, new_resume_name);
+                               resume_name = new_resume_name;
                        }
                }
 
@@ -2329,14 +2334,19 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        out_of_space = True;
                        finished = False;
                } else {
-                       finished = !get_lanman2_dir_entry(conn,
+                       TALLOC_CTX *sub_ctx = talloc_stackframe();
+
+                       finished = !get_lanman2_dir_entry(sub_ctx,
+                                               conn,
                                                req->flags2,
                                                mask,dirtype,info_level,
                                                requires_resume_key,dont_descend,
                                                &p,pdata,data_end,
                                                space_remaining, &out_of_space,
                                                &got_exact_match,
-                                               &last_entry_off, ea_list, ea_ctx);
+                                               &last_entry_off, ea_list);
+
+                       TALLOC_FREE(sub_ctx);
                }
 
                if (finished && out_of_space)
@@ -2357,8 +2367,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
        }
-  
-       talloc_destroy(ea_ctx);
+
+       DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
+               smb_fn_name(CVAL(req->inbuf,smb_com)),
+               mask, directory, dirtype, numentries ) );
 
        /* Check if we can close the dirptr */
        if(close_after_request || (finished && close_if_end)) {
@@ -2375,13 +2387,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
                            max_data_bytes);
 
-       if ((! *directory) && dptr_path(dptr_num))
-               slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
-
-       DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
-               smb_fn_name(CVAL(req->inbuf,smb_com)),
-               mask, directory, dirtype, numentries ) );
-
        return;
 }
 
@@ -3511,7 +3516,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
        unsigned int data_size = 0;
        unsigned int param_size = 2;
        SMB_STRUCT_STAT sbuf;
-       pstring dos_fname;
+       char *dos_fname = NULL;
        char *fname = NULL;
        char *fullpathname;
        char *base_name;
@@ -3523,7 +3528,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
        struct timespec create_time_ts, mtime_ts, atime_ts;
        files_struct *fsp = NULL;
        struct file_id fileid;
-       TALLOC_CTX *data_ctx = NULL;
        struct ea_list *ea_list = NULL;
        uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
        char *lock_data = NULL;
@@ -3712,7 +3716,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
        DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
                fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
 
-       p = strrchr_m(fname,'/'); 
+       p = strrchr_m(fname,'/');
        if (!p)
                base_name = fname;
        else
@@ -3754,15 +3758,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                return;
                        }
 
-                       if ((data_ctx = talloc_init("ea_list")) == NULL) {
-                               reply_nterror(req, NT_STATUS_NO_MEMORY);
-                               return;
-                       }
-
                        /* Pull out the list of names. */
-                       ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
+                       ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
                        if (!ea_list) {
-                               talloc_destroy(data_ctx);
                                reply_nterror(
                                        req, NT_STATUS_INVALID_PARAMETER);
                                return;
@@ -3783,16 +3781,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                return;
                        }
 
-                       if ((data_ctx = talloc_init("lock_request")) == NULL) {
-                               reply_nterror(req, NT_STATUS_NO_MEMORY);
-                               return;
-                       }
-
                        /* Copy the lock range data. */
                        lock_data = (char *)TALLOC_MEMDUP(
-                               data_ctx, pdata, total_data);
+                               ctx, pdata, total_data);
                        if (!lock_data) {
-                               talloc_destroy(data_ctx);
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                return;
                        }
@@ -3803,7 +3795,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
        *pparams = (char *)SMB_REALLOC(*pparams,2);
        if (*pparams == NULL) {
-               talloc_destroy(data_ctx);
                reply_nterror(req, NT_STATUS_NO_MEMORY);
                return;
        }
@@ -3812,7 +3803,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
        *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
        if (*ppdata == NULL ) {
-               talloc_destroy(data_ctx);
                reply_nterror(req, NT_STATUS_NO_MEMORY);
                return;
        }
@@ -3857,10 +3847,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
        /* NT expects the name to be in an exact form of the *full*
           filename. See the trans2 torture test */
-       if (strequal(base_name,".")) {
-               pstrcpy(dos_fname, "\\");
+       if (ISDOT(base_name)) {
+               dos_fname = talloc_strdup(ctx, "\\");
+               if (!dos_fname) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
+               }
        } else {
-               pstr_sprintf(dos_fname, "\\%s", fname);
+               dos_fname = talloc_asprintf(ctx,
+                               "\\%s",
+                               fname);
+               if (!dos_fname) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
+               }
                string_replace(dos_fname, '/', '\\');
        }
 
@@ -3894,14 +3894,14 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                case SMB_INFO_IS_NAME_VALID:
                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
                        if (tran_call == TRANSACT2_QFILEINFO) {
-                               /* os/2 needs this ? really ?*/      
+                               /* os/2 needs this ? really ?*/
                                reply_doserror(req, ERRDOS, ERRbadfunc);
                                return;
                        }
                        data_size = 0;
                        param_size = 0;
                        break;
-                       
+
                case SMB_INFO_QUERY_EAS_FROM_LIST:
                {
                        size_t total_ea_len = 0;
@@ -3909,18 +3909,16 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
 
-                       ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
+                       ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
                        ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
 
                        if (!ea_list || (total_ea_len > data_size)) {
-                               talloc_destroy(data_ctx);
                                data_size = 4;
                                SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
                                break;
                        }
 
-                       data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
-                       talloc_destroy(data_ctx);
+                       data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
                        break;
                }
 
@@ -3931,22 +3929,14 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
 
-                       data_ctx = talloc_init("ea_ctx");
-                       if (!data_ctx) {
-                               reply_nterror(req, NT_STATUS_NO_MEMORY);
-                               return;
-                       }
-
-                       ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
+                       ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
                        if (!ea_list || (total_ea_len > data_size)) {
-                               talloc_destroy(data_ctx);
                                data_size = 4;
                                SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
                                break;
                        }
 
-                       data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
-                       talloc_destroy(data_ctx);
+                       data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
                        break;
                }
 
@@ -4219,7 +4209,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                case SMB_QUERY_FILE_UNIX_LINK:
                        {
-                               pstring buffer;
+                               char *buffer = TALLOC_SIZE(ctx, 1024);
+
+                               if (!buffer) {
+                                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                                       return;
+                               }
 
                                DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
 #ifdef S_ISLNK
@@ -4232,7 +4227,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                reply_unixerror(req, ERRDOS, ERRbadlink);
                                return;
 #endif
-                               len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
+                               len = SMB_VFS_READLINK(conn,fullpathname,
+                                               buffer, 1023);
                                if (len == -1) {
                                        reply_unixerror(req, ERRDOS,
                                                        ERRnoaccess);
@@ -4364,7 +4360,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                case POSIX_LOCK_TYPE_UNLOCK:
                                default:
                                        /* There's no point in asking for an unlock... */
-                                       talloc_destroy(data_ctx);
                                        reply_nterror(
                                                req,
                                                NT_STATUS_INVALID_PARAMETER);
@@ -4860,21 +4855,32 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
        /* !widelinks forces the target path to be within the share. */
        /* This means we can interpret the target as a pathname. */
        if (!lp_widelinks(SNUM(conn))) {
-               pstring rel_name;
+               char *rel_name = NULL;
                char *last_dirp = NULL;
 
                if (*link_target == '/') {
                        /* No absolute paths allowed. */
                        return NT_STATUS_ACCESS_DENIED;
                }
-               pstrcpy(rel_name, newname);
+               rel_name = talloc_strdup(ctx,newname);
+               if (!rel_name) {
+                       return NT_STATUS_NO_MEMORY;
+               }
                last_dirp = strrchr_m(rel_name, '/');
                if (last_dirp) {
                        last_dirp[1] = '\0';
                } else {
-                       pstrcpy(rel_name, "./");
+                       rel_name = talloc_strdup(ctx,"./");
+                       if (!rel_name) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+               }
+               rel_name = talloc_asprintf_append(ctx,
+                               "%s",
+                               link_target);
+               if (!rel_name) {
+                       return NT_STATUS_NO_MEMORY;
                }
-               pstrcat(rel_name, link_target);
 
                status = check_name(conn, rel_name);
                if (!NT_STATUS_IS_OK(status)) {
@@ -4945,7 +4951,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
        uint32 root_fid;
        uint32 len;
        char *newname = NULL;
-       pstring base_name;
+       char *base_name = NULL;
        BOOL dest_has_wcard = False;
        NTSTATUS status = NT_STATUS_OK;
        char *p;
@@ -4988,15 +4994,26 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
        }
 
        /* Create the base directory. */
-       pstrcpy(base_name, fname);
+       base_name = talloc_strdup(ctx, fname);
+       if (!base_name) {
+               return NT_STATUS_NO_MEMORY;
+       }
        p = strrchr_m(base_name, '/');
        if (p) {
                p[1] = '\0';
        } else {
-               pstrcpy(base_name, "./");
+               base_name = talloc_strdup(ctx, "./");
+               if (!base_name) {
+                       return NT_STATUS_NO_MEMORY;
+               }
        }
        /* Append the new name. */
-       pstrcat(base_name, newname);
+       base_name = talloc_asprintf_append(base_name,
+                       "%s",
+                       newname);
+       if (!base_name) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
        if (fsp) {
                SMB_STRUCT_STAT sbuf;
@@ -5026,7 +5043,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
        } else {
                DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
                        fname, base_name ));
-               status = rename_internals(conn, req, fname, base_name, 0,
+               status = rename_internals(ctx, conn, req, fname, base_name, 0,
                                          overwrite, False, dest_has_wcard);
        }
 
index f9a5ba5ed6cd7224c753885299fe745dbd66b73e..d9c772d6b146f2ddb38d0e86ebd036bc4b56837e 100644 (file)
@@ -653,7 +653,11 @@ char *vfs_readdirname(connection_struct *conn, void *p)
 int vfs_ChDir(connection_struct *conn, const char *path)
 {
        int res;
-       static pstring LastDir="";
+       static char *LastDir = NULL;
+
+       if (!LastDir) {
+               LastDir = SMB_STRDUP("");
+       }
 
        if (strcsequal(path,"."))
                return(0);
@@ -664,8 +668,10 @@ int vfs_ChDir(connection_struct *conn, const char *path)
        DEBUG(4,("vfs_ChDir to %s\n",path));
 
        res = SMB_VFS_CHDIR(conn,path);
-       if (!res)
-               pstrcpy(LastDir,path);
+       if (!res) {
+               SAFE_FREE(LastDir);
+               LastDir = SMB_STRDUP(path);
+       }
        return(res);
 }
 
@@ -675,7 +681,7 @@ int vfs_ChDir(connection_struct *conn, const char *path)
 static 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. */
+       char *path; /* The pathname. */
        BOOL valid;
 } ino_list[MAX_GETWDCACHE];
 
@@ -710,23 +716,36 @@ static void array_promote(char *array,int elsize,int element)
  format. Note this can be called with conn == NULL.
 ********************************************************************/
 
-char *vfs_GetWd(connection_struct *conn, char *path)
+char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
 {
+#ifdef PATH_MAX
+        char s[PATH_MAX+1];
+#else
        pstring s;
+#endif
        static BOOL getwd_cache_init = False;
        SMB_STRUCT_STAT st, st2;
        int i;
+       char *ret = NULL;
 
        *s = 0;
 
-       if (!use_getwd_cache)
-               return(SMB_VFS_GETWD(conn,path));
+       if (!use_getwd_cache) {
+ nocache:
+               ret = SMB_VFS_GETWD(conn,s);
+               if (!ret) {
+                       DEBUG(0,("vfs_GetWd: SMB_VFS_GETWD call failed, "
+                               "errno %s\n",strerror(errno)));
+                       return NULL;
+               }
+               return talloc_strdup(ctx, ret);
+       }
 
        /* 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,"");
+                       string_set(&ino_list[i].path,"");
                        ino_list[i].valid = False;
                }
        }
@@ -737,8 +756,10 @@ char *vfs_GetWd(connection_struct *conn, char *path)
        if (SMB_VFS_STAT(conn, ".",&st) == -1) {
                /* Known to fail for root: the directory may be
                 * NFS-mounted and exported with root_squash (so has no root access). */
-               DEBUG(1,("vfs_GetWd: couldn't stat \".\" path=%s error %s (NFS problem ?)\n", path, strerror(errno) ));
-               return(SMB_VFS_GETWD(conn,path));
+               DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
+                       "(NFS problem ?)\n",
+                       strerror(errno) ));
+               goto nocache;
        }
 
 
@@ -752,14 +773,19 @@ char *vfs_GetWd(connection_struct *conn, char *path)
                                the same...) */
 
                        if (st.st_ino == ino_list[i].inode && st.st_dev == ino_list[i].dev) {
-                               if (SMB_VFS_STAT(conn,ino_list[i].dos_path,&st2) == 0) {
+                               if (SMB_VFS_STAT(conn,ino_list[i].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);
+
+                                               ret = talloc_strdup(ctx,
+                                                       ino_list[i].path);
 
                                                /* promote it for future use */
                                                array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
-                                               return (path);
+                                               if (ret == NULL) {
+                                                       errno = ENOMEM;
+                                               }
+                                               return ret;
                                        } else {
                                                /*  If the inode is different then something's changed,
                                                        scrub the entry and start from scratch. */
@@ -770,22 +796,24 @@ char *vfs_GetWd(connection_struct *conn, char *path)
                }
        }
 
-       /*  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. */
+       /*  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 (!SMB_VFS_GETWD(conn,s)) {
-               DEBUG(0,("vfs_GetWd: SMB_VFS_GETWD call failed, errno %s\n",strerror(errno)));
+               DEBUG(0,("vfs_GetWd: SMB_VFS_GETWD call failed, errno %s\n",
+                               strerror(errno)));
                return (NULL);
        }
 
-       pstrcpy(path,s);
+       ret = talloc_strdup(ctx,s);
 
-       DEBUG(5,("vfs_GetWd %s, inode %.0f, dev %.0f\n",s,(double)st.st_ino,(double)st.st_dev));
+       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);
+       string_set(&ino_list[i].path,s);
        ino_list[i].dev = st.st_dev;
        ino_list[i].inode = st.st_ino;
        ino_list[i].valid = True;
@@ -793,7 +821,10 @@ char *vfs_GetWd(connection_struct *conn, char *path)
        /* put it at the top of the list */
        array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
 
-       return (path);
+       if (ret == NULL) {
+               errno = ENOMEM;
+       }
+       return ret;
 }
 
 /*******************************************************************
@@ -832,18 +863,28 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
                                return map_nt_error_from_unix(errno);
                        case ENOENT:
                        {
-                               pstring tmp_fname;
-                               fstring last_component;
+                               TALLOC_CTX *tmp_ctx = talloc_stackframe();
+                               char *tmp_fname = NULL;
+                               char *last_component = NULL;
                                /* Last component didn't exist. Remove it and try and canonicalise the directory. */
 
-                               pstrcpy(tmp_fname, fname);
+                               tmp_fname = talloc_strdup(tmp_ctx, fname);
+                               if (!tmp_fname) {
+                                       TALLOC_FREE(tmp_ctx);
+                                       return NT_STATUS_NO_MEMORY;
+                               }
                                p = strrchr_m(tmp_fname, '/');
                                if (p) {
                                        *p++ = '\0';
-                                       fstrcpy(last_component, p);
+                                       last_component = p;
                                } else {
-                                       fstrcpy(last_component, tmp_fname);
-                                       pstrcpy(tmp_fname, ".");
+                                       last_component = tmp_fname;
+                                       tmp_fname = talloc_strdup(tmp_ctx,
+                                                       ".");
+                                       if (!tmp_fname) {
+                                               TALLOC_FREE(tmp_ctx);
+                                               return NT_STATUS_NO_MEMORY;
+                                       }
                                }
 
 #ifdef REALPATH_TAKES_NULL
@@ -853,11 +894,17 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
 #endif
                                if (!resolved_name) {
                                        DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname));
+                                       TALLOC_FREE(tmp_ctx);
                                        return map_nt_error_from_unix(errno);
                                }
-                               pstrcpy(tmp_fname, resolved_name);
-                               pstrcat(tmp_fname, "/");
-                               pstrcat(tmp_fname, last_component);
+                               tmp_fname = talloc_asprintf(tmp_ctx,
+                                               "%s/%s",
+                                               resolved_name,
+                                               last_component);
+                               if (!tmp_fname) {
+                                       TALLOC_FREE(tmp_ctx);
+                                       return NT_STATUS_NO_MEMORY;
+                               }
 #ifdef REALPATH_TAKES_NULL
                                SAFE_FREE(resolved_name);
                                resolved_name = SMB_STRDUP(tmp_fname);
@@ -873,6 +920,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
 #endif
                                resolved_name = resolved_name_buf;
 #endif
+                               TALLOC_FREE(tmp_ctx);
                                break;
                        }
                        default:
@@ -903,7 +951,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
         /* Check if we are allowing users to follow symlinks */
         /* Patch from David Clerc <David.Clerc@cui.unige.ch>
                 University of Geneva */
-                                                                                                                                                    
+
 #ifdef S_ISLNK
         if (!lp_symlinks(SNUM(conn))) {
                 SMB_STRUCT_STAT statbuf;