diff options
author | Jeremy Allison <jra@samba.org> | 2005-03-22 02:14:38 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 10:56:09 -0500 |
commit | 442b9f3e87ee7f9fe8c100cd37c9591733e290e6 (patch) | |
tree | 48b82139432a30df11afc0a74a4e7c05774fd9cd /source3 | |
parent | b824fcb0813b9ec5e2ca2b7f5208f9857f46108a (diff) | |
download | samba-442b9f3e87ee7f9fe8c100cd37c9591733e290e6.tar.gz samba-442b9f3e87ee7f9fe8c100cd37c9591733e290e6.tar.bz2 samba-442b9f3e87ee7f9fe8c100cd37c9591733e290e6.zip |
r5933: We were handling setting of EA's incorrectly - we should be able to set
a list. Also not converting names from DOS CP to UNIX CP correctly. This
code doesn't quite work yet but it's a work in progress to be fixed
tomorrow (don't want to lose it).
Jeremy.
(This used to be commit 22fca746576810c5408540031a9603625a66cd75)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/lib/charcnv.c | 15 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 453 |
2 files changed, 340 insertions, 128 deletions
diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index b9b9d90db6..4fbad0f3d1 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -1269,6 +1269,21 @@ size_t pull_utf8_allocate(char **dest, const char *src) } /** + * Copy a string from a DOS src to a unix char * destination, allocating a buffer using talloc + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +size_t pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + *dest = NULL; + return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest, True); +} + +/** Copy a string from a char* src to a unicode or ascii dos codepage destination choosing unicode or ascii based on the flags in the SMB buffer starting at base_ptr. diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9455f138cc..d09231dd83 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -313,106 +313,78 @@ static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, con Set or delete an extended attribute. ****************************************************************************/ -static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, - char *pdata, int total_data) +static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list) { - unsigned int namelen; - unsigned int ealen; - int ret; - fstring unix_ea_name; - if (!lp_ea_support(SNUM(conn))) { return NT_STATUS_EAS_NOT_SUPPORTED; } - if (total_data < 8) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (IVAL(pdata,0) > total_data) { - DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data)); - return NT_STATUS_INVALID_PARAMETER; - } - - pdata += 4; - namelen = CVAL(pdata,1); - ealen = SVAL(pdata,2); - pdata += 4; - if (total_data < 8 + namelen + 1 + ealen) { - DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n", - (unsigned int)total_data, namelen, ealen)); - return NT_STATUS_INVALID_PARAMETER; - } - - if (pdata[namelen] != '\0') { - DEBUG(10,("set_ea: ea name not null terminated\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */ - pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE); - pdata += (namelen + 1); + while (ea_list) { + int ret; + fstring unix_ea_name; - canonicalize_ea_name(conn, fsp, fname, unix_ea_name); + fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */ + fstrcat(unix_ea_name, ea_list->ea.name); - DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen)); - if (ealen) { - DEBUG(10,("set_ea: data :\n")); - dump_data(10, pdata, ealen); - } + canonicalize_ea_name(conn, fsp, fname, unix_ea_name); - if (samba_private_attr_name(unix_ea_name)) { - DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name)); - return NT_STATUS_ACCESS_DENIED; - } + DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ea_list->ea.value.length)); - if (ealen == 0) { - /* Remove the attribute. */ - if (fsp && (fsp->fd != -1)) { - DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n", - unix_ea_name, fsp->fsp_name)); - ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name); - } else { - DEBUG(10,("set_ea: deleting ea name %s on file %s.\n", - unix_ea_name, fname)); - ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name); + if (samba_private_attr_name(unix_ea_name)) { + DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name)); + return NT_STATUS_ACCESS_DENIED; } + + if (ea_list->ea.value.length == 0) { + /* Remove the attribute. */ + if (fsp && (fsp->fd != -1)) { + DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n", + unix_ea_name, fsp->fsp_name)); + ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name); + } else { + DEBUG(10,("set_ea: deleting ea name %s on file %s.\n", + unix_ea_name, fname)); + ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name); + } #ifdef ENOATTR - /* Removing a non existent attribute always succeeds. */ - if (ret == -1 && errno == ENOATTR) { - DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name)); - ret = 0; - } + /* Removing a non existent attribute always succeeds. */ + if (ret == -1 && errno == ENOATTR) { + DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", + unix_ea_name)); + ret = 0; + } #endif - } else { - if (fsp && (fsp->fd != -1)) { - DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n", - unix_ea_name, fsp->fsp_name)); - ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0); } else { - DEBUG(10,("set_ea: setting ea name %s on file %s.\n", - unix_ea_name, fname)); - ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0); + if (fsp && (fsp->fd != -1)) { + DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n", + unix_ea_name, fsp->fsp_name)); + ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, + ea_list->ea.value.data, ea_list->ea.value.length, 0); + } else { + DEBUG(10,("set_ea: setting ea name %s on file %s.\n", + unix_ea_name, fname)); + ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, + ea_list->ea.value.data, ea_list->ea.value.length, 0); + } } - } - if (ret == -1) { + if (ret == -1) { #ifdef ENOTSUP - if (errno == ENOTSUP) { - return NT_STATUS_EAS_NOT_SUPPORTED; - } + if (errno == ENOTSUP) { + return NT_STATUS_EAS_NOT_SUPPORTED; + } #endif - return map_nt_error_from_unix(errno); - } + return map_nt_error_from_unix(errno); + } + } return NT_STATUS_OK; } - /**************************************************************************** - Read a list of EA's from an incoming data buffer. Create an ea_list with them. + Read a list of EA names from an incoming data buffer. Create an ea_list with them. ****************************************************************************/ -static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) +static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) { struct ea_list *ea_list_head = NULL; size_t offset = 4; @@ -426,15 +398,83 @@ static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t d if (offset + namelen >= data_size) { break; } - eal->ea.name = TALLOC_ARRAY(ctx, char, namelen + 1); + /* Ensure the name is null terminated. */ + if (pdata[offset + namelen] != '\0') { + return NULL; + } + pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]); if (!eal->ea.name) { - break; + return NULL; } - memcpy(eal->ea.name, pdata + offset, namelen); - eal->ea.name[namelen] = '\0'; offset += (namelen + 1); /* Go past the name + terminating zero. */ DLIST_ADD_END(ea_list_head, eal, tmp); + DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name)); + } + + return ea_list_head; +} + +/**************************************************************************** + Read a list of EA names and data from an incoming data buffer. Create an ea_list with them. +****************************************************************************/ + +static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) +{ + struct ea_list *ea_list_head = NULL; + size_t offset = 4; + + if (data_size < 10) { + return NULL; + } + + if (IVAL(pdata,0) > data_size) { + DEBUG(10,("read_ea_list: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)data_size)); + return NULL; + } + + /* Each entry must be at least 6 bytes in length. */ + while (offset + 6 <= data_size) { + struct ea_list *tmp; + struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list); + uint16 val_len; + unsigned int namelen; + + eal->ea.flags = CVAL(pdata,offset); + namelen = CVAL(pdata,offset + 1); + val_len = SVAL(pdata,offset + 2); + + if (offset + 4 + namelen + 1 + val_len > data_size) { + return NULL; + } + + /* Ensure the name is null terminated. */ + if (pdata[offset + 4 + namelen] != '\0') { + return NULL; + } + pull_ascii_talloc(ctx, &eal->ea.name, pdata + offset); + if (!eal->ea.name) { + return NULL; + } + + eal->ea.value = data_blob(NULL, (size_t)val_len + 1); + if (!eal->ea.value.data) { + break; + } + + memcpy(eal->ea.value.data, pdata + offset + 4 + namelen + 1, val_len); + + /* Ensure we're null terminated just in case we print the value. */ + eal->ea.value.data[val_len] = '\0'; + /* But don't count the null. */ + eal->ea.value.length--; + + offset += 4 + namelen + 1 + val_len; + + DLIST_ADD_END(ea_list_head, eal, tmp); + + DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name)); + dump_data(10, eal->ea.value.data, eal->ea.value.length); } return ea_list_head; @@ -464,31 +504,34 @@ static size_t ea_list_size(struct ea_list *ealist) /**************************************************************************** Return a union of EA's from a file list and a list of names. + The TALLOC context for the two lists *MUST* be identical as we steal + memory from one list to another. JRA. ****************************************************************************/ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len) { struct ea_list *nlistp, *flistp; - for (flistp = file_list; flistp;) { - struct ea_list *rem_entry = flistp; - - for (nlistp = name_list; nlistp; nlistp = nlistp->next) { + for (nlistp = name_list; nlistp; nlistp = nlistp->next) { + for (flistp = file_list; flistp; flistp = flistp->next) { if (strequal(nlistp->ea.name, flistp->ea.name)) { break; } } - flistp = flistp->next; - - if (nlistp == NULL) { - /* Remove this entry from file ea list. */ - DLIST_REMOVE(file_list, rem_entry); + if (flistp) { + /* Copy the data from this entry. */ + nlistp->ea.flags = flistp->ea.flags; + nlistp->ea.value = flistp->ea.value; + } else { + /* Null entry. */ + nlistp->ea.flags = 0; + ZERO_STRUCT(nlistp->ea.value); } } - *total_ea_len = ea_list_size(file_list); - return file_list; + *total_ea_len = ea_list_size(name_list); + return name_list; } /**************************************************************************** @@ -737,8 +780,9 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i /* Realloc the size of parameters and data we will return */ params = SMB_REALLOC(*pparams, 28); - if( params == NULL ) - return(ERROR_DOS(ERRDOS,ERRnomem)); + if( params == NULL ) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; memset((char *)params,'\0',28); @@ -876,7 +920,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, BOOL dont_descend,char **ppdata, char *base_data, int space_remaining, BOOL *out_of_space, BOOL *got_exact_match, - int *last_entry_off) + int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx) { const char *dname; BOOL found = False; @@ -1104,14 +1148,62 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ break; -#if 0 case SMB_FIND_EA_LIST: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n")); + { + struct ea_list *file_list = NULL; + size_t ea_len = 0; + + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n")); + if (!name_list) { + return False; + } if(requires_resume_key) { SIVAL(p,0,reskey); p += 4; } -#endif + put_dos_date2(p,l2_fdateCreation,cdate); + put_dos_date2(p,l2_fdateLastAccess,adate); + put_dos_date2(p,l2_fdateLastWrite,mdate); + SIVAL(p,l2_cbFile,(uint32)file_size); + SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size); + SSVAL(p,l2_attrFile,mode); + p += l2_cbList; /* p now points to the EA area. */ + + file_list = get_ea_list_from_file(ea_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. */ + /* Max string size is 255 bytes. */ + if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) { + /* Move the dirptr back to prev_dirpos */ + dptr_SeekDir(conn->dirptr, prev_dirpos); + *out_of_space = True; + DEBUG(9,("get_lanman2_dir_entry: out of space\n")); + return False; /* Not finished - just out of space */ + } + + /* Push the ea_data followed by the name. */ + p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list); + nameptr = p; + len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN); + if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) { + if (len > 2) { + len -= 2; + } else { + len = 0; + } + } else { + if (len > 1) { + len -= 1; + } else { + len = 0; + } + } + SCVAL(nameptr,0,len); + p += len + 1; + SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ + break; + } case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); @@ -1412,6 +1504,8 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb int space_remaining; BOOL bad_path = False; SMB_STRUCT_STAT sbuf; + TALLOC_CTX *ea_ctx = NULL; + struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; if (total_params < 12) { @@ -1433,6 +1527,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", switch (info_level) { case SMB_FIND_INFO_STANDARD: case SMB_FIND_EA_SIZE: + case SMB_FIND_EA_LIST: case SMB_FIND_FILE_DIRECTORY_INFO: case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_NAMES_INFO: @@ -1478,29 +1573,66 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", DEBUG(5,("dir=%s, mask = %s\n",directory, mask)); + if (info_level == SMB_FIND_EA_LIST) { + uint32 ea_size; + + if (total_data < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + ea_size = IVAL(pdata,0); + if (ea_size != total_data) { + DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \ +total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (!lp_ea_support(SNUM(conn))) { + return ERROR_DOS(ERRDOS,ERReasnotsupported); + } + + if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + /* Pull out the list of names. */ + ea_list = read_ea_name_list(ea_ctx, pdata, ea_size); + if (!ea_list) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); - if( pdata == NULL ) - return(ERROR_DOS(ERRDOS,ERRnomem)); + if( pdata == NULL ) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); /* Realloc the params space */ params = SMB_REALLOC(*pparams, 10); - if (params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if (params == NULL) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid)); - if (dptr_num < 0) + if (dptr_num < 0) { + talloc_destroy(ea_ctx); return(UNIXERROR(ERRDOS,ERRbadfile)); + } /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) { dptr_close(&dptr_num); - return ERROR_DOS(ERRDOS,ERRnomem); + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); } DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype)); @@ -1530,7 +1662,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,space_remaining, &out_of_space, &got_exact_match, - &last_entry_off); + &last_entry_off, ea_list, ea_ctx); } if (finished && out_of_space) @@ -1552,6 +1684,8 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", 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)) { DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num)); @@ -1641,6 +1775,8 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu 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; if (total_params < 12) { @@ -1678,6 +1814,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", switch (info_level) { case SMB_FIND_INFO_STANDARD: case SMB_FIND_EA_SIZE: + case SMB_FIND_EA_LIST: case SMB_FIND_FILE_DIRECTORY_INFO: case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_NAMES_INFO: @@ -1691,29 +1828,66 @@ resume_key = %d resume name = %s continue=%d level = %d\n", return ERROR_DOS(ERRDOS,ERRunknownlevel); } + if (info_level == SMB_FIND_EA_LIST) { + uint32 ea_size; + + if (total_data < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + ea_size = IVAL(pdata,0); + if (ea_size != total_data) { + DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \ +total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (!lp_ea_support(SNUM(conn))) { + return ERROR_DOS(ERRDOS,ERReasnotsupported); + } + + if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + /* Pull out the list of names. */ + ea_list = read_ea_name_list(ea_ctx, pdata, ea_size); + if (!ea_list) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); - if(pdata == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(pdata == NULL) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); /* Realloc the params space */ params = SMB_REALLOC(*pparams, 6*SIZEOFWORD); - if( params == NULL ) - return ERROR_DOS(ERRDOS,ERRnomem); + if( params == NULL ) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; /* Check that the dptr is valid */ - if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) + if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) { + talloc_destroy(ea_ctx); return ERROR_DOS(ERRDOS,ERRnofiles); + } string_set(&conn->dirpath,dptr_path(dptr_num)); /* 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); return ERROR_DOS(ERRDOS,ERRnofiles); } @@ -1784,7 +1958,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,space_remaining, &out_of_space, &got_exact_match, - &last_entry_off); + &last_entry_off, ea_list, ea_ctx); } if (finished && out_of_space) @@ -1806,6 +1980,8 @@ resume_key = %d resume name = %s continue=%d level = %d\n", space_remaining = max_data_bytes - PTR_DIFF(p,pdata); } + talloc_destroy(ea_ctx); + /* Check if we can close the dirptr */ if(close_after_request || (finished && close_if_end)) { DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num)); @@ -1856,8 +2032,9 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf } pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); - if ( pdata == NULL ) - return ERROR_DOS(ERRDOS,ERRnomem); + if ( pdata == NULL ) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); @@ -2570,7 +2747,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } /* Pull out the list of names. */ - ea_list = read_ea_list(ea_ctx, pdata, ea_size); + ea_list = read_ea_name_list(ea_ctx, pdata, ea_size); if (!ea_list) { talloc_destroy(ea_ctx); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); @@ -3408,10 +3585,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n", tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data)); - /* Realloc the parameter and data sizes */ + /* Realloc the parameter size */ params = SMB_REALLOC(*pparams,2); - if(params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(params == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; SSVAL(params,0,0); @@ -3445,10 +3623,25 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } case SMB_INFO_SET_EA: - status = set_ea(conn, fsp, fname, pdata, total_data); - if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) + { + struct ea_list *ea_list = NULL; + TALLOC_CTX *ctx = talloc_init("SMB_INFO_SET_EA"); + if (!ctx) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + ea_list = read_ea_list(ctx, pdata, total_data); + if (!ea_list) { + talloc_destroy(ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + status = set_ea(conn, fsp, fname, ea_list); + talloc_destroy(ctx); + + if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) { return ERROR_NT(status); + } break; + } #if 0 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */ @@ -4179,8 +4372,9 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, /* Realloc the parameter and data sizes */ params = SMB_REALLOC(*pparams,2); - if(params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(params == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; SSVAL(params,0,0); @@ -4220,8 +4414,9 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char /* Realloc the parameter and data sizes */ params = SMB_REALLOC(*pparams,6); - if(params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(params == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; SSVAL(params,0,fnf_handle); @@ -4253,8 +4448,9 @@ static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char /* Realloc the parameter and data sizes */ params = SMB_REALLOC(*pparams,4); - if(params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(params == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; SSVAL(params,0,0); /* No changes */ @@ -4321,8 +4517,9 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { pdata = SMB_REALLOC(*ppdata, 32); - if(pdata == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(pdata == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *ppdata = pdata; /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2 @@ -4480,7 +4677,7 @@ int reply_trans2(connection_struct *conn, SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBtrans2); - return ERROR_DOS(ERRDOS,ERRnomem); + return ERROR_NT(NT_STATUS_NO_MEMORY); } /* Copy the param and data bytes sent with this request into |