}
/* 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);
}
}
{
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
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.
********************************************************************/
SMB_STRUCT_STAT st;
int ver = 0;
int i;
+ TALLOC_CTX *ctx = talloc_tos();
memset(inbuf, '\0', sizeof(inbuf));
memset(outbuf, '\0', sizeof(outbuf));
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));
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));
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));
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));
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",
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",
-/*
+/*
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/>.
*/
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) {
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);
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;
}
/****************************************************************************
DLIST_REMOVE(dirptrs, dptr);
- /*
+ /*
* Free the dnum in the bitmap. Remember the dnum value is always
* biased by one with respect to the bitmap.
*/
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);
}
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
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
/* 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. */
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.
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);
}
}
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)
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)) {
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:
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)) {
*/
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;
(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
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) ));
}
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)));
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;
}
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,
out:
+ TALLOC_FREE(ctx);
vfs_ChDir(conn,saved_dir);
+ return status;
}
/****************************************************************************
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);
}
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);
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;
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;
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. */
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);
}
****************************************************************************/
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,
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;
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)) {
}
/* 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;
}
#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
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_DESC* get_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;
}
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;
}
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));
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;
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;
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);
}
} 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);
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.
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;
}
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;
}
* 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;
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)) {
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;
}
/*
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;
}
}
if (strequal(mask,"????????.???")) {
- pstrcpy(mask,"*");
+ mask[0] = '*';
+ mask[1] = '\0';
}
status = check_name(conn, directory);
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)) {
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);
}
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);
}
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;
#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.
*/
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).
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;
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;
}
ret = False;
break;
}
+ TALLOC_FREE(fullname);
}
CloseDir(dir_hnd);
return ret;
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;
}
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*
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 */
}
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;
}
/****************************************************************************
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;
struct smb_Dir *dir_hnd = NULL;
const char *dname;
long offset = 0;
- pstring destname;
-
- *directory = *mask = 0;
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
/*
* 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().
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. */
}
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;
}
}
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) {
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);
* 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;
}
}
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);
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;
}
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)) {
* 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)
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;
}
} else {
if (!map_open_params_to_ntcreate(dest1,0,ofun,
NULL, NULL, &new_create_disposition, NULL)) {
+ TALLOC_FREE(dest);
return NT_STATUS_INVALID_PARAMETER;
}
}
NULL, &fsp1);
if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(dest);
return status;
}
INTERNAL_OPEN_ONLY,
NULL, &fsp2);
+ TALLOC_FREE(dest);
+
if (!NT_STATUS_IS_OK(status)) {
close_file(fsp1,ERROR_CLOSE);
return status;
src_sbuf.st_size = 0;
}
}
-
+
if (src_sbuf.st_size) {
ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
}
{
char *name = NULL;
char *newname = NULL;
- pstring directory;
- pstring mask;
+ char *directory = NULL;
+ char *mask = NULL;
char *p;
int count=0;
int error = ERRnoaccess;
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,
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;
}
/*
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);
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);
}
} 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)) {
END_PROFILE(SMBcopy);
return;
}
-
+
dir_hnd = OpenDir(conn, directory, mask, 0);
if (dir_hnd == NULL) {
status = map_nt_error_from_unix(errno);
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)) {
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... */
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;
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
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);
-/*
+/*
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/>.
*/
if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
continue;
-
+
listp = TALLOC_P(mem_ctx, struct ea_list);
if (!listp)
return NULL;
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;
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;
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;
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;
/* 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
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);
}
* 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))) {
}
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) {
DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
pathreal,strerror(errno)));
+ TALLOC_FREE(pathreal);
continue;
}
}
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;
}
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);
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. */
}
/* 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),
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;
break;
- default:
+ default:
return(False);
}
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;
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();
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,
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) {
return;
}
} else {
- pstrcpy(mask,p+1);
+ mask = p+1;
*p = 0;
}
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;
}
*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;
}
/* 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;
}
&conn->dirptr);
if (!NT_STATUS_IS_OK(ntstatus)) {
- talloc_destroy(ea_ctx);
reply_nterror(req, ntstatus);
return;
}
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;
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)
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)) {
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.
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;
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();
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,
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;
}
*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;
}
/* 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;
}
/* Check that the dptr is valid */
if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
- talloc_destroy(ea_ctx);
reply_doserror(req, ERRDOS, ERRnofiles);
return;
}
/* 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.
*/
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;
}
}
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)
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)) {
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;
}
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;
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;
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
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;
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;
}
*pparams = (char *)SMB_REALLOC(*pparams,2);
if (*pparams == NULL) {
- talloc_destroy(data_ctx);
reply_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
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;
}
/* 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, '/', '\\');
}
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;
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;
}
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;
}
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
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);
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);
/* !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)) {
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;
}
/* 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;
} 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);
}
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);
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);
}
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];
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;
}
}
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;
}
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. */
}
}
- /* 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;
/* 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;
}
/*******************************************************************
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
#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);
#endif
resolved_name = resolved_name_buf;
#endif
+ TALLOC_FREE(tmp_ctx);
break;
}
default:
/* 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;