📄 nttrans.c
字号:
restore_case_semantics(conn, file_attributes); return ERROR_NT(status); } fsp->access_mask = saved_access_mask; } if (ea_len && (info == FILE_WAS_CREATED)) { status = set_ea(conn, fsp, fname, ea_list); talloc_destroy(ctx); if (!NT_STATUS_IS_OK(status)) { close_file(fsp,False); restore_case_semantics(conn, file_attributes); return ERROR_NT(status); } } restore_case_semantics(conn, file_attributes); file_len = sbuf.st_size; fattr = dos_mode(conn,fname,&sbuf); if(fattr == 0) { fattr = FILE_ATTRIBUTE_NORMAL; } if (!fsp->is_directory && (fattr & aDIR)) { close_file(fsp,False); return ERROR_DOS(ERRDOS,ERRnoaccess); } /* Save the requested allocation size. */ if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(params,12);#ifdef LARGE_SMB_OFF_T allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32);#endif if (allocation_size && (allocation_size > file_len)) { fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (fsp->is_directory) { close_file(fsp,False); /* Can't set allocation size on a directory. */ return ERROR_NT(NT_STATUS_ACCESS_DENIED); } if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { close_file(fsp,False); return ERROR_NT(NT_STATUS_DISK_FULL); } } else { fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len); } } /* * If the caller set the extended oplock request bit * and we granted one (by whatever means) - set the * correct bit for extended oplock reply. */ if (oplock_request && lp_fake_oplocks(SNUM(conn))) { extended_oplock_granted = True; } if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { extended_oplock_granted = True; } /* Realloc the size of parameters and data we will return */ params = nttrans_realloc(ppparams, 69); if(params == NULL) { return ERROR_DOS(ERRDOS,ERRnomem); } p = params; if (extended_oplock_granted) { SCVAL(p,0, BATCH_OPLOCK_RETURN); } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); } else { SCVAL(p,0,NO_OPLOCK_RETURN); } p += 2; SSVAL(p,0,fsp->fnum); p += 2; if ((create_disposition == FILE_SUPERSEDE) && (info == FILE_WAS_OVERWRITTEN)) { SIVAL(p,0,FILE_WAS_SUPERSEDED); } else { SIVAL(p,0,info); } p += 8; /* Create time. */ c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); if (lp_dos_filetime_resolution(SNUM(conn))) { c_time &= ~1; sbuf.st_atime &= ~1; sbuf.st_mtime &= ~1; sbuf.st_mtime &= ~1; } put_long_date(p,c_time); p += 8; put_long_date(p,sbuf.st_atime); /* access time */ p += 8; put_long_date(p,sbuf.st_mtime); /* write time */ p += 8; put_long_date(p,sbuf.st_mtime); /* change time */ p += 8; SIVAL(p,0,fattr); /* File Attributes. */ p += 4; SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); p += 8; if (flags & EXTENDED_RESPONSE_REQUIRED) { SSVAL(p,2,0x7); } p += 4; SCVAL(p,0,fsp->is_directory ? 1 : 0); DEBUG(5,("call_nt_transact_create: open name = %s\n", fname)); /* Send the required number of replies */ send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0); return -1;}/**************************************************************************** Reply to a NT CANCEL request.****************************************************************************/int reply_ntcancel(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize){ /* * Go through and cancel any pending change notifies. */ int mid = SVAL(inbuf,smb_mid); START_PROFILE(SMBntcancel); remove_pending_change_notify_requests_by_mid(mid); remove_pending_lock_requests_by_mid(mid); srv_cancel_sign_response(mid); DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", mid)); END_PROFILE(SMBntcancel); return(-1);}/**************************************************************************** Copy a file.****************************************************************************/static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint32 attrs){ BOOL bad_path_oldname = False; BOOL bad_path_newname = False; SMB_STRUCT_STAT sbuf1, sbuf2; pstring last_component_oldname; pstring last_component_newname; files_struct *fsp1,*fsp2; uint32 fattr; int info; SMB_OFF_T ret=-1; int close_ret; NTSTATUS status = NT_STATUS_OK; ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); /* No wildcards. */ if (ms_has_wild(newname) || ms_has_wild(oldname)) { return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED; unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1); if (bad_path_oldname) { return NT_STATUS_OBJECT_PATH_NOT_FOUND; } /* Quick check for "." and ".." */ if (last_component_oldname[0] == '.') { if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) { return NT_STATUS_OBJECT_NAME_INVALID; } } /* Source must already exist. */ if (!VALID_STAT(sbuf1)) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } if (!check_name(oldname,conn)) { return NT_STATUS_ACCESS_DENIED; } /* Ensure attributes match. */ fattr = dos_mode(conn,oldname,&sbuf1); if ((fattr & ~attrs) & (aHIDDEN | aSYSTEM)) { return NT_STATUS_NO_SUCH_FILE; } unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2); if (bad_path_newname) { return NT_STATUS_OBJECT_PATH_NOT_FOUND; } /* Quick check for "." and ".." */ if (last_component_newname[0] == '.') { if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) { return NT_STATUS_OBJECT_NAME_INVALID; } } /* Disallow if newname already exists. */ if (VALID_STAT(sbuf2)) { return NT_STATUS_OBJECT_NAME_COLLISION; } if (!check_name(newname,conn)) { return NT_STATUS_ACCESS_DENIED; } /* No links from a directory. */ if (S_ISDIR(sbuf1.st_mode)) { return NT_STATUS_FILE_IS_A_DIRECTORY; } /* Ensure this is within the share. */ if (!reduce_name(conn, oldname) != 0) { return NT_STATUS_ACCESS_DENIED; } DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname)); fsp1 = open_file_ntcreate(conn,oldname,&sbuf1, FILE_READ_DATA, /* Read-only. */ 0, /* No sharing. */ FILE_OPEN, 0, /* No create options. */ FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &info); if (!fsp1) { status = get_saved_ntstatus(); if (NT_STATUS_IS_OK(status)) { status = NT_STATUS_ACCESS_DENIED; } set_saved_ntstatus(NT_STATUS_OK); return status; } fsp2 = open_file_ntcreate(conn,newname,&sbuf2, FILE_WRITE_DATA, /* Read-only. */ 0, /* No sharing. */ FILE_CREATE, 0, /* No create options. */ fattr, INTERNAL_OPEN_ONLY, &info); if (!fsp2) { status = get_saved_ntstatus(); if (NT_STATUS_IS_OK(status)) { status = NT_STATUS_ACCESS_DENIED; } set_saved_ntstatus(NT_STATUS_OK); close_file(fsp1,False); return status; } if (sbuf1.st_size) { ret = vfs_transfer_file(fsp1, fsp2, sbuf1.st_size); } /* * As we are opening fsp1 read-only we only expect * an error on close on fsp2 if we are out of space. * Thus we don't look at the error return from the * close of fsp1. */ close_file(fsp1,False); /* Ensure the modtime is set correctly on the destination file. */ fsp_set_pending_modtime(fsp2, sbuf1.st_mtime); close_ret = close_file(fsp2,False); /* Grrr. We have to do this as open_file_shared1 adds aARCH when it creates the file. This isn't the correct thing to do in the copy case. JRA */ file_set_dosmode(conn, newname, fattr, &sbuf2, True); if (ret < (SMB_OFF_T)sbuf1.st_size) { return NT_STATUS_DISK_FULL; } if (close_ret != 0) { status = map_nt_error_from_unix(close_ret); DEBUG(3,("copy_internals: Error %s copy file %s to %s\n", nt_errstr(status), oldname, newname)); } return status;}/**************************************************************************** Reply to a NT rename request.****************************************************************************/int reply_ntrename(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize){ int outsize = 0; pstring oldname; pstring newname; char *p; NTSTATUS status; BOOL path_contains_wcard = False; uint32 attrs = SVAL(inbuf,smb_vwv0); uint16 rename_type = SVAL(inbuf,smb_vwv1); START_PROFILE(SMBntrename); p = smb_buf(inbuf) + 1; p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); } if( is_ntfs_stream_name(oldname)) { /* Can't rename a stream. */ END_PROFILE(SMBntrename); return ERROR_NT(NT_STATUS_ACCESS_DENIED); } if (ms_has_wild(oldname)) { END_PROFILE(SMBntrename); return ERROR_NT(NT_STATUS_OBJECT_PATH_SYNTAX_BAD); } p++; p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); return ERROR_NT(status); } RESOLVE_DFSPATH(oldname, conn, inbuf, outbuf); RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname)); switch(rename_type) { case RENAME_FLAG_RENAME: status = rename_internals(conn, oldname, newname, attrs, False, path_contains_wcard); break; case RENAME_FLAG_HARD_LINK: status = hardlink_internals(conn, oldname, newname); break; case RENAME_FLAG_COPY: if (path_contains_wcard) { /* No wildcards. */ status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } else { status = copy_internals(conn, oldname, newname, attrs); } break; case RENAME_FLAG_MOVE_CLUSTER_INFORMATION: status = NT_STATUS_INVALID_PARAMETER; break; default: status = NT_STATUS_ACCESS_DENIED; /* Default error. */ break; } if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntrename); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; } return ERROR_NT(status); } /* * Win2k needs a changenotify request response before it will * update after a rename.. */ process_pending_change_notify_queue((time_t)0); outsize = set_message(outbuf,0,0,True); END_PROFILE(SMBntrename); return(outsize);}/**************************************************************************** Reply to an unsolicited SMBNTtranss - just ignore it!****************************************************************************/int reply_nttranss(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize){ START_PROFILE(SMBnttranss); DEBUG(4,("Ignoring nttranss of length %d\n",length)); END_PROFILE(SMBnttranss); return(-1);}/**************************************************************************** Reply to a notify change - queue the request and don't allow a directory to be opened.****************************************************************************/static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count, uint32 max_data_count){ char *setup = *ppsetup; files_struct *fsp; uint32 flags; if(setup_count < 6) { return ERROR_DOS(ERRDOS,ERRbadfunc); } fsp = file_fsp(setup,4); flags = IVAL(setup, 0); DEBUG(3,("call_nt_transact_notify_change\n")); if(!fsp) { return ERROR_DOS(ERRDOS,ERRbadfid); } if((!fsp->is_directory) || (conn != fsp->conn)) { return ERROR_DOS(ERRDOS,ERRbadfid); } if (!change_notify_set(inbuf, fsp, conn, flags)) { return(UNIXERROR(ERRDOS,ERRbadfid)); } DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \name = %s\n", fsp->fsp_name )); return -1;}/**************************************************************************** Reply to an NT transact rename command.****************************************************************************/static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count, uint32 max_data_count){ char *params = *ppparams; pstring new_name; files_struct *fsp = NULL; BOOL replace_if_exists = False; BOOL path_contains_wcard = False; NTSTATUS status; if(parameter_count < 4) { return ERROR_DOS(ERRDOS,ERRbadfunc); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -