- if (next_offset == 0) {
- break;
- }
- offset += next_offset;
- }
-
- return ea_list_head;
-}
-
-/****************************************************************************
- Reply to a NT_TRANSACT_CREATE call (needs to process SD's).
-****************************************************************************/
-
-static void call_nt_transact_create(connection_struct *conn,
- struct smb_request *req,
- uint16 **ppsetup, uint32 setup_count,
- char **ppparams, uint32 parameter_count,
- char **ppdata, uint32 data_count,
- uint32 max_data_count)
-{
- char *fname = NULL;
- char *params = *ppparams;
- char *data = *ppdata;
- /* Breakout the oplock request bits so we can set the reply bits separately. */
- int oplock_request = 0;
- uint32 fattr=0;
- SMB_OFF_T file_len = 0;
- SMB_STRUCT_STAT sbuf;
- int info = 0;
- files_struct *fsp = NULL;
- char *p = NULL;
- bool extended_oplock_granted = False;
- uint32 flags;
- uint32 access_mask;
- uint32 file_attributes;
- uint32 share_access;
- uint32 create_disposition;
- uint32 create_options;
- uint32 sd_len;
- uint32 ea_len;
- uint16 root_dir_fid;
- struct timespec c_timespec;
- struct timespec a_timespec;
- struct timespec m_timespec;
- struct ea_list *ea_list = NULL;
- char *pdata = NULL;
- NTSTATUS status;
- size_t param_len;
- struct case_semantics_state *case_state = NULL;
- TALLOC_CTX *ctx = talloc_tos();
-
- DEBUG(5,("call_nt_transact_create\n"));
-
- /*
- * If it's an IPC, use the pipe handler.
- */
-
- if (IS_IPC(conn)) {
- if (lp_nt_pipe_support()) {
- do_nt_transact_create_pipe(
- conn, req,
- ppsetup, setup_count,
- ppparams, parameter_count,
- ppdata, data_count);
- return;
- } else {
- reply_doserror(req, ERRDOS, ERRnoaccess);
- return;
- }
- }
-
- /*
- * Ensure minimum number of parameters sent.
- */
-
- if(parameter_count < 54) {
- DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count));
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- flags = IVAL(params,0);
- access_mask = IVAL(params,8);
- file_attributes = IVAL(params,20);
- share_access = IVAL(params,24);
- create_disposition = IVAL(params,28);
- create_options = IVAL(params,32);
- sd_len = IVAL(params,36);
- ea_len = IVAL(params,40);
- root_dir_fid = (uint16)IVAL(params,4);
-
- /* Ensure the data_len is correct for the sd and ea values given. */
- if ((ea_len + sd_len > data_count) ||
- (ea_len > data_count) || (sd_len > data_count) ||
- (ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) {
- DEBUG(10,("call_nt_transact_create - ea_len = %u, sd_len = %u, data_count = %u\n",
- (unsigned int)ea_len, (unsigned int)sd_len, (unsigned int)data_count ));
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- if (ea_len) {
- if (!lp_ea_support(SNUM(conn))) {
- DEBUG(10,("call_nt_transact_create - ea_len = %u but EA's not supported.\n",
- (unsigned int)ea_len ));
- reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
- return;
- }
-
- if (ea_len < 10) {
- DEBUG(10,("call_nt_transact_create - ea_len = %u - too small (should be more than 10)\n",
- (unsigned int)ea_len ));
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
- }
-
- if (create_options & FILE_OPEN_BY_FILE_ID) {
- reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
- return;
- }
-
- /*
- * Get the file name.
- */
-
- if(root_dir_fid != 0) {
- /*
- * This filename is relative to a directory fid.
- */
- char *tmpname = NULL;
- files_struct *dir_fsp = file_fsp(SVAL(params,4));
-
- if(!dir_fsp) {
- reply_doserror(req, ERRDOS, ERRbadfid);
- return;
- }
-
- if(!dir_fsp->is_directory) {
- srvstr_get_path(ctx, params, req->flags2, &fname,
- params+53,
- parameter_count-53, STR_TERMINATE,
- &status);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- return;
- }
-
- /*
- * Check to see if this is a mac fork of some kind.
- */
-
- if( is_ntfs_stream_name(fname)) {
- reply_nterror(req,
- NT_STATUS_OBJECT_PATH_NOT_FOUND);
- return;
- }
-
- reply_doserror(req, ERRDOS, ERRbadfid);
- return;
- }
-
- if (ISDOT(dir_fsp->fsp_name)) {
- /*
- * We're at the toplevel dir, the final file name
- * must not contain ./, as this is filtered out
- * normally by srvstr_get_path and unix_convert
- * explicitly rejects paths containing ./.
- */
- fname = talloc_strdup(ctx,"");
- if (!fname) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- return;
- }
- } else {
- size_t dir_name_len = strlen(dir_fsp->fsp_name);
-
- /*
- * Copy in the base directory name.
- */
-
- fname = TALLOC_ARRAY(ctx, char, dir_name_len+2);
- if (!fname) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- return;
- }
- memcpy(fname, dir_fsp->fsp_name, dir_name_len+1);
-
- /*
- * Ensure it ends in a '/'.
- * We used TALLOC_SIZE +2 to add space for the '/'.
- */
-
- if(dir_name_len &&
- (fname[dir_name_len-1] != '\\') &&
- (fname[dir_name_len-1] != '/')) {
- fname[dir_name_len] = '/';
- fname[dir_name_len+1] = '\0';
- }
- }
-
- srvstr_get_path(ctx, params, req->flags2, &tmpname,
- params+53,
- parameter_count-53, STR_TERMINATE,
- &status);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- return;
- }
- fname = talloc_asprintf(ctx, "%s%s",
- fname,
- tmpname);
- if (!fname) {
- reply_nterror(
- req, NT_STATUS_NO_MEMORY);
- return;
- }
- } else {
- srvstr_get_path(ctx, params, req->flags2, &fname, params+53,
- parameter_count-53,
- STR_TERMINATE, &status);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- return;
- }
-
- /*
- * Check to see if this is a mac fork of some kind.
- */
-
- if( is_ntfs_stream_name(fname)) {
- reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
- return;