summaryrefslogtreecommitdiff
path: root/source3/smbd/dir.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2007-09-12 21:48:20 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:30:41 -0500
commit12f61e09d943ea7fc4149166077507b5b0b3b4e7 (patch)
tree8382cf512a97b3159c3cda38eb952c85f8f2237f /source3/smbd/dir.c
parent4754b0ec65a3be4380f3216bd3f59c1906db259b (diff)
downloadsamba-12f61e09d943ea7fc4149166077507b5b0b3b4e7.tar.gz
samba-12f61e09d943ea7fc4149166077507b5b0b3b4e7.tar.bz2
samba-12f61e09d943ea7fc4149166077507b5b0b3b4e7.zip
r25117: The mega-patch Jerry was waiting for. Remove all pstrings from
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)
Diffstat (limited to 'source3/smbd/dir.c')
-rw-r--r--source3/smbd/dir.c135
1 files changed, 94 insertions, 41 deletions
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index 7a6815b680..a7b1b020b8 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -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)