データ構造 | |
struct | deferred_open_record |
関数 | |
static NTSTATUS | fd_open (struct connection_struct *conn, const char *fname, files_struct *fsp, int flags, mode_t mode) |
NTSTATUS | fd_close (struct connection_struct *conn, files_struct *fsp) |
static void | change_file_owner_to_parent (connection_struct *conn, const char *inherit_from_dir, files_struct *fsp) |
static void | change_dir_owner_to_parent (connection_struct *conn, const char *inherit_from_dir, const char *fname, SMB_STRUCT_STAT *psbuf) |
static NTSTATUS | open_file (files_struct *fsp, connection_struct *conn, const char *parent_dir, const char *name, const char *path, SMB_STRUCT_STAT *psbuf, int flags, mode_t unx_mode, uint32 access_mask, uint32 open_access_mask) |
static BOOL | is_executable (const char *fname) |
static BOOL | share_conflict (struct share_mode_entry *entry, uint32 access_mask, uint32 share_access) |
static void | validate_my_share_entries (int num, struct share_mode_entry *share_entry) |
static BOOL | is_stat_open (uint32 access_mask) |
static NTSTATUS | open_mode_check (connection_struct *conn, const char *fname, struct share_mode_lock *lck, uint32 access_mask, uint32 share_access, uint32 create_options, BOOL *file_existed) |
static BOOL | is_delete_request (files_struct *fsp) |
static BOOL | delay_for_oplocks (struct share_mode_lock *lck, files_struct *fsp, int pass_number, int oplock_request) |
static BOOL | request_timed_out (struct timeval request_time, struct timeval timeout) |
static void | defer_open (struct share_mode_lock *lck, struct timeval request_time, struct timeval timeout, struct deferred_open_record *state) |
static BOOL | open_match_attributes (connection_struct *conn, const char *path, uint32 old_dos_attr, uint32 new_dos_attr, mode_t existing_unx_mode, mode_t new_unx_mode, mode_t *returned_unx_mode) |
static files_struct * | fcb_or_dos_open (connection_struct *conn, const char *fname, SMB_DEV_T dev, SMB_INO_T inode, uint32 access_mask, uint32 share_access, uint32 create_options) |
BOOL | map_open_params_to_ntcreate (const char *fname, int deny_mode, int open_func, uint32 *paccess_mask, uint32 *pshare_mode, uint32 *pcreate_disposition, uint32 *pcreate_options) |
static void | schedule_defer_open (struct share_mode_lock *lck, struct timeval request_time) |
NTSTATUS | open_file_ntcreate (connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask, uint32 share_access, uint32 create_disposition, uint32 create_options, uint32 new_dos_attributes, int oplock_request, int *pinfo, files_struct **result) |
NTSTATUS | open_file_fchmod (connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, files_struct **result) |
NTSTATUS | close_file_fchmod (files_struct *fsp) |
static NTSTATUS | mkdir_internal (connection_struct *conn, const char *name, uint32 file_attributes, SMB_STRUCT_STAT *psbuf) |
NTSTATUS | open_directory (connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask, uint32 share_access, uint32 create_disposition, uint32 create_options, uint32 file_attributes, int *pinfo, files_struct **result) |
NTSTATUS | create_directory (connection_struct *conn, const char *directory) |
NTSTATUS | open_file_stat (connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, files_struct **result) |
void | msg_file_was_renamed (int msg_type, struct process_id src, void *buf, size_t len, void *private_data) |
変数 | |
generic_mapping | file_generic_mapping |
current_user | current_user |
userdom_struct | current_user_info |
uint16 | global_smbpid |
BOOL | global_client_failed_oplock_break |
static NTSTATUS fd_open | ( | struct connection_struct * | conn, | |
const char * | fname, | |||
files_struct * | fsp, | |||
int | flags, | |||
mode_t | mode | |||
) | [static] |
参照先 errno・fd_handle::fd・files_struct::fh・map_nt_error_from_unix()・files_struct::posix_open・status・strerror().
参照元 open_file().
00046 { 00047 NTSTATUS status = NT_STATUS_OK; 00048 00049 #ifdef O_NOFOLLOW 00050 /* 00051 * Never follow symlinks on a POSIX client. The 00052 * client should be doing this. 00053 */ 00054 00055 if (fsp->posix_open || !lp_symlinks(SNUM(conn))) { 00056 flags |= O_NOFOLLOW; 00057 } 00058 #endif 00059 00060 fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode); 00061 if (fsp->fh->fd == -1) { 00062 status = map_nt_error_from_unix(errno); 00063 } 00064 00065 DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", 00066 fname, flags, (int)mode, fsp->fh->fd, 00067 (fsp->fh->fd == -1) ? strerror(errno) : "" )); 00068 00069 return status; 00070 }
NTSTATUS fd_close | ( | struct connection_struct * | conn, | |
files_struct * | fsp | |||
) |
参照先 fd_handle::fd・fd_close_posix()・files_struct::fh・fd_handle::ref_count.
参照元 close_file_fchmod()・close_normal_file()・open_file()・open_file_ntcreate().
00077 { 00078 if (fsp->fh->fd == -1) { 00079 return NT_STATUS_OK; /* What we used to call a stat open. */ 00080 } 00081 if (fsp->fh->ref_count > 1) { 00082 return NT_STATUS_OK; /* Shared handle. Only close last reference. */ 00083 } 00084 return fd_close_posix(conn, fsp); 00085 }
static void change_file_owner_to_parent | ( | connection_struct * | conn, | |
const char * | inherit_from_dir, | |||
files_struct * | fsp | |||
) | [static] |
参照先 become_root()・errno・fd_handle::fd・files_struct::fh・files_struct::fsp_name・strerror()・unbecome_root().
参照元 open_file().
00095 { 00096 SMB_STRUCT_STAT parent_st; 00097 int ret; 00098 00099 ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st); 00100 if (ret == -1) { 00101 DEBUG(0,("change_file_owner_to_parent: failed to stat parent " 00102 "directory %s. Error was %s\n", 00103 inherit_from_dir, strerror(errno) )); 00104 return; 00105 } 00106 00107 become_root(); 00108 ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1); 00109 unbecome_root(); 00110 if (ret == -1) { 00111 DEBUG(0,("change_file_owner_to_parent: failed to fchown " 00112 "file %s to parent directory uid %u. Error " 00113 "was %s\n", fsp->fsp_name, 00114 (unsigned int)parent_st.st_uid, 00115 strerror(errno) )); 00116 } 00117 00118 DEBUG(10,("change_file_owner_to_parent: changed new file %s to " 00119 "parent directory uid %u.\n", fsp->fsp_name, 00120 (unsigned int)parent_st.st_uid )); 00121 }
static void change_dir_owner_to_parent | ( | connection_struct * | conn, | |
const char * | inherit_from_dir, | |||
const char * | fname, | |||
SMB_STRUCT_STAT * | psbuf | |||
) | [static] |
参照先 become_root()・errno・strerror()・unbecome_root()・vfs_ChDir()・vfs_GetWd().
参照元 mkdir_internal().
00127 { 00128 pstring saved_dir; 00129 SMB_STRUCT_STAT sbuf; 00130 SMB_STRUCT_STAT parent_st; 00131 int ret; 00132 00133 ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st); 00134 if (ret == -1) { 00135 DEBUG(0,("change_dir_owner_to_parent: failed to stat parent " 00136 "directory %s. Error was %s\n", 00137 inherit_from_dir, strerror(errno) )); 00138 return; 00139 } 00140 00141 /* We've already done an lstat into psbuf, and we know it's a 00142 directory. If we can cd into the directory and the dev/ino 00143 are the same then we can safely chown without races as 00144 we're locking the directory in place by being in it. This 00145 should work on any UNIX (thanks tridge :-). JRA. 00146 */ 00147 00148 if (!vfs_GetWd(conn,saved_dir)) { 00149 DEBUG(0,("change_dir_owner_to_parent: failed to get " 00150 "current working directory\n")); 00151 return; 00152 } 00153 00154 /* Chdir into the new path. */ 00155 if (vfs_ChDir(conn, fname) == -1) { 00156 DEBUG(0,("change_dir_owner_to_parent: failed to change " 00157 "current working directory to %s. Error " 00158 "was %s\n", fname, strerror(errno) )); 00159 goto out; 00160 } 00161 00162 if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { 00163 DEBUG(0,("change_dir_owner_to_parent: failed to stat " 00164 "directory '.' (%s) Error was %s\n", 00165 fname, strerror(errno))); 00166 goto out; 00167 } 00168 00169 /* Ensure we're pointing at the same place. */ 00170 if (sbuf.st_dev != psbuf->st_dev || 00171 sbuf.st_ino != psbuf->st_ino || 00172 sbuf.st_mode != psbuf->st_mode ) { 00173 DEBUG(0,("change_dir_owner_to_parent: " 00174 "device/inode/mode on directory %s changed. " 00175 "Refusing to chown !\n", fname )); 00176 goto out; 00177 } 00178 00179 become_root(); 00180 ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); 00181 unbecome_root(); 00182 if (ret == -1) { 00183 DEBUG(10,("change_dir_owner_to_parent: failed to chown " 00184 "directory %s to parent directory uid %u. " 00185 "Error was %s\n", fname, 00186 (unsigned int)parent_st.st_uid, strerror(errno) )); 00187 goto out; 00188 } 00189 00190 DEBUG(10,("change_dir_owner_to_parent: changed ownership of new " 00191 "directory %s to parent directory uid %u.\n", 00192 fname, (unsigned int)parent_st.st_uid )); 00193 00194 out: 00195 00196 vfs_ChDir(conn,saved_dir); 00197 }
static NTSTATUS open_file | ( | files_struct * | fsp, | |
connection_struct * | conn, | |||
const char * | parent_dir, | |||
const char * | name, | |||
const char * | path, | |||
SMB_STRUCT_STAT * | psbuf, | |||
int | flags, | |||
mode_t | unx_mode, | |||
uint32 | access_mask, | |||
uint32 | open_access_mask | |||
) | [static] |
参照先 files_struct::aio_write_behind・connection_struct::aio_write_behind_list・files_struct::can_lock・files_struct::can_read・files_struct::can_write・connection_struct::case_sensitive・change_file_owner_to_parent()・current_user・current_user_info・files_struct::dev・errno・fd_handle::fd・fd_close()・fd_open()・files_struct::fh・files_struct::file_pid・files_struct::fsp_name・global_smbpid・inherit_access_acl()・files_struct::inode・files_struct::is_directory・is_in_path()・files_struct::is_stat・map_nt_error_from_unix()・files_struct::mode・files_struct::modified・ms_has_wild()・notify_fname()・nt_errstr()・connection_struct::num_files_open・files_struct::print_file・files_struct::sent_oplock_break・userdom_struct::smb_name・status・strerror()・string_set()・connection_struct::user・current_user::vuid・files_struct::vuid・files_struct::wcp.
参照元 open_file_fchmod()・open_file_ntcreate().
00213 { 00214 NTSTATUS status = NT_STATUS_OK; 00215 int accmode = (flags & O_ACCMODE); 00216 int local_flags = flags; 00217 BOOL file_existed = VALID_STAT(*psbuf); 00218 00219 fsp->fh->fd = -1; 00220 errno = EPERM; 00221 00222 /* Check permissions */ 00223 00224 /* 00225 * This code was changed after seeing a client open request 00226 * containing the open mode of (DENY_WRITE/read-only) with 00227 * the 'create if not exist' bit set. The previous code 00228 * would fail to open the file read only on a read-only share 00229 * as it was checking the flags parameter directly against O_RDONLY, 00230 * this was failing as the flags parameter was set to O_RDONLY|O_CREAT. 00231 * JRA. 00232 */ 00233 00234 if (!CAN_WRITE(conn)) { 00235 /* It's a read-only share - fail if we wanted to write. */ 00236 if(accmode != O_RDONLY) { 00237 DEBUG(3,("Permission denied opening %s\n", path)); 00238 return NT_STATUS_ACCESS_DENIED; 00239 } else if(flags & O_CREAT) { 00240 /* We don't want to write - but we must make sure that 00241 O_CREAT doesn't create the file if we have write 00242 access into the directory. 00243 */ 00244 flags &= ~O_CREAT; 00245 local_flags &= ~O_CREAT; 00246 } 00247 } 00248 00249 /* 00250 * This little piece of insanity is inspired by the 00251 * fact that an NT client can open a file for O_RDONLY, 00252 * but set the create disposition to FILE_EXISTS_TRUNCATE. 00253 * If the client *can* write to the file, then it expects to 00254 * truncate the file, even though it is opening for readonly. 00255 * Quicken uses this stupid trick in backup file creation... 00256 * Thanks *greatly* to "David W. Chapman Jr." <dwcjr@inethouston.net> 00257 * for helping track this one down. It didn't bite us in 2.0.x 00258 * as we always opened files read-write in that release. JRA. 00259 */ 00260 00261 if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) { 00262 DEBUG(10,("open_file: truncate requested on read-only open " 00263 "for file %s\n", path)); 00264 local_flags = (flags & ~O_ACCMODE)|O_RDWR; 00265 } 00266 00267 if ((open_access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || 00268 (!file_existed && (local_flags & O_CREAT)) || 00269 ((local_flags & O_TRUNC) == O_TRUNC) ) { 00270 00271 /* 00272 * We can't actually truncate here as the file may be locked. 00273 * open_file_ntcreate will take care of the truncate later. JRA. 00274 */ 00275 00276 local_flags &= ~O_TRUNC; 00277 00278 #if defined(O_NONBLOCK) && defined(S_ISFIFO) 00279 /* 00280 * We would block on opening a FIFO with no one else on the 00281 * other end. Do what we used to do and add O_NONBLOCK to the 00282 * open flags. JRA. 00283 */ 00284 00285 if (file_existed && S_ISFIFO(psbuf->st_mode)) { 00286 local_flags |= O_NONBLOCK; 00287 } 00288 #endif 00289 00290 /* Don't create files with Microsoft wildcard characters. */ 00291 if ((local_flags & O_CREAT) && !file_existed && 00292 ms_has_wild(path)) { 00293 return NT_STATUS_OBJECT_NAME_INVALID; 00294 } 00295 00296 /* Actually do the open */ 00297 status = fd_open(conn, path, fsp, local_flags, unx_mode); 00298 if (!NT_STATUS_IS_OK(status)) { 00299 DEBUG(3,("Error opening file %s (%s) (local_flags=%d) " 00300 "(flags=%d)\n", 00301 path,nt_errstr(status),local_flags,flags)); 00302 return status; 00303 } 00304 00305 if ((local_flags & O_CREAT) && !file_existed) { 00306 00307 /* Inherit the ACL if required */ 00308 if (lp_inherit_perms(SNUM(conn))) { 00309 inherit_access_acl(conn, parent_dir, path, 00310 unx_mode); 00311 } 00312 00313 /* Change the owner if required. */ 00314 if (lp_inherit_owner(SNUM(conn))) { 00315 change_file_owner_to_parent(conn, parent_dir, 00316 fsp); 00317 } 00318 00319 notify_fname(conn, NOTIFY_ACTION_ADDED, 00320 FILE_NOTIFY_CHANGE_FILE_NAME, path); 00321 } 00322 00323 } else { 00324 fsp->fh->fd = -1; /* What we used to call a stat open. */ 00325 } 00326 00327 if (!file_existed) { 00328 int ret; 00329 00330 if (fsp->fh->fd == -1) { 00331 ret = SMB_VFS_STAT(conn, path, psbuf); 00332 } else { 00333 ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf); 00334 /* If we have an fd, this stat should succeed. */ 00335 if (ret == -1) { 00336 DEBUG(0,("Error doing fstat on open file %s " 00337 "(%s)\n", path,strerror(errno) )); 00338 } 00339 } 00340 00341 /* For a non-io open, this stat failing means file not found. JRA */ 00342 if (ret == -1) { 00343 status = map_nt_error_from_unix(errno); 00344 fd_close(conn, fsp); 00345 return status; 00346 } 00347 } 00348 00349 /* 00350 * POSIX allows read-only opens of directories. We don't 00351 * want to do this (we use a different code path for this) 00352 * so catch a directory open and return an EISDIR. JRA. 00353 */ 00354 00355 if(S_ISDIR(psbuf->st_mode)) { 00356 fd_close(conn, fsp); 00357 errno = EISDIR; 00358 return NT_STATUS_FILE_IS_A_DIRECTORY; 00359 } 00360 00361 fsp->mode = psbuf->st_mode; 00362 fsp->inode = psbuf->st_ino; 00363 fsp->dev = psbuf->st_dev; 00364 fsp->vuid = current_user.vuid; 00365 fsp->file_pid = global_smbpid; 00366 fsp->can_lock = True; 00367 fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False; 00368 if (!CAN_WRITE(conn)) { 00369 fsp->can_write = False; 00370 } else { 00371 fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? 00372 True : False; 00373 } 00374 fsp->print_file = False; 00375 fsp->modified = False; 00376 fsp->sent_oplock_break = NO_BREAK_SENT; 00377 fsp->is_directory = False; 00378 fsp->is_stat = False; 00379 if (conn->aio_write_behind_list && 00380 is_in_path(path, conn->aio_write_behind_list, conn->case_sensitive)) { 00381 fsp->aio_write_behind = True; 00382 } 00383 00384 string_set(&fsp->fsp_name, path); 00385 fsp->wcp = NULL; /* Write cache pointer. */ 00386 00387 DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", 00388 *current_user_info.smb_name ? 00389 current_user_info.smb_name : conn->user,fsp->fsp_name, 00390 BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), 00391 conn->num_files_open + 1)); 00392 00393 errno = 0; 00394 return NT_STATUS_OK; 00395 }
static BOOL is_executable | ( | const char * | fname | ) | [static] |
参照先 strequal()・strrchr_m().
参照元 fcb_or_dos_open()・map_open_params_to_ntcreate().
00402 { 00403 if ((fname = strrchr_m(fname,'.'))) { 00404 if (strequal(fname,".com") || 00405 strequal(fname,".dll") || 00406 strequal(fname,".exe") || 00407 strequal(fname,".sym")) { 00408 return True; 00409 } 00410 } 00411 return False; 00412 }
static BOOL share_conflict | ( | struct share_mode_entry * | entry, | |
uint32 | access_mask, | |||
uint32 | share_access | |||
) | [static] |
参照先 share_mode_entry::access_mask・share_mode_entry::private_options・share_mode_entry::share_access.
参照元 open_mode_check().
00422 { 00423 DEBUG(10,("share_conflict: entry->access_mask = 0x%x, " 00424 "entry->share_access = 0x%x, " 00425 "entry->private_options = 0x%x\n", 00426 (unsigned int)entry->access_mask, 00427 (unsigned int)entry->share_access, 00428 (unsigned int)entry->private_options)); 00429 00430 DEBUG(10,("share_conflict: access_mask = 0x%x, share_access = 0x%x\n", 00431 (unsigned int)access_mask, (unsigned int)share_access)); 00432 00433 if ((entry->access_mask & (FILE_WRITE_DATA| 00434 FILE_APPEND_DATA| 00435 FILE_READ_DATA| 00436 FILE_EXECUTE| 00437 DELETE_ACCESS)) == 0) { 00438 DEBUG(10,("share_conflict: No conflict due to " 00439 "entry->access_mask = 0x%x\n", 00440 (unsigned int)entry->access_mask )); 00441 return False; 00442 } 00443 00444 if ((access_mask & (FILE_WRITE_DATA| 00445 FILE_APPEND_DATA| 00446 FILE_READ_DATA| 00447 FILE_EXECUTE| 00448 DELETE_ACCESS)) == 0) { 00449 DEBUG(10,("share_conflict: No conflict due to " 00450 "access_mask = 0x%x\n", 00451 (unsigned int)access_mask )); 00452 return False; 00453 } 00454 00455 #if 1 /* JRA TEST - Superdebug. */ 00456 #define CHECK_MASK(num, am, right, sa, share) \ 00457 DEBUG(10,("share_conflict: [%d] am (0x%x) & right (0x%x) = 0x%x\n", \ 00458 (unsigned int)(num), (unsigned int)(am), \ 00459 (unsigned int)(right), (unsigned int)(am)&(right) )); \ 00460 DEBUG(10,("share_conflict: [%d] sa (0x%x) & share (0x%x) = 0x%x\n", \ 00461 (unsigned int)(num), (unsigned int)(sa), \ 00462 (unsigned int)(share), (unsigned int)(sa)&(share) )); \ 00463 if (((am) & (right)) && !((sa) & (share))) { \ 00464 DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \ 00465 sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \ 00466 (unsigned int)(share) )); \ 00467 return True; \ 00468 } 00469 #else 00470 #define CHECK_MASK(num, am, right, sa, share) \ 00471 if (((am) & (right)) && !((sa) & (share))) { \ 00472 DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \ 00473 sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \ 00474 (unsigned int)(share) )); \ 00475 return True; \ 00476 } 00477 #endif 00478 00479 CHECK_MASK(1, entry->access_mask, FILE_WRITE_DATA | FILE_APPEND_DATA, 00480 share_access, FILE_SHARE_WRITE); 00481 CHECK_MASK(2, access_mask, FILE_WRITE_DATA | FILE_APPEND_DATA, 00482 entry->share_access, FILE_SHARE_WRITE); 00483 00484 CHECK_MASK(3, entry->access_mask, FILE_READ_DATA | FILE_EXECUTE, 00485 share_access, FILE_SHARE_READ); 00486 CHECK_MASK(4, access_mask, FILE_READ_DATA | FILE_EXECUTE, 00487 entry->share_access, FILE_SHARE_READ); 00488 00489 CHECK_MASK(5, entry->access_mask, DELETE_ACCESS, 00490 share_access, FILE_SHARE_DELETE); 00491 CHECK_MASK(6, access_mask, DELETE_ACCESS, 00492 entry->share_access, FILE_SHARE_DELETE); 00493 00494 DEBUG(10,("share_conflict: No conflict.\n")); 00495 return False; 00496 }
static void validate_my_share_entries | ( | int | num, | |
struct share_mode_entry * | share_entry | |||
) | [static] |
参照先 share_mode_entry::dev・file_find_dif()・files_struct::fsp_name・share_mode_entry::inode・is_deferred_open_entry()・is_unused_share_mode_entry()・is_valid_share_mode_entry()・share_mode_entry::op_mid・share_mode_entry::op_type・open_was_deferred()・files_struct::oplock_type・share_mode_entry::pid・procid_is_me()・pstr_sprintf()・share_mode_entry::share_file_id・share_mode_str()・smb_panic().
参照元 open_mode_check().
00501 { 00502 files_struct *fsp; 00503 00504 if (!procid_is_me(&share_entry->pid)) { 00505 return; 00506 } 00507 00508 if (is_deferred_open_entry(share_entry) && 00509 !open_was_deferred(share_entry->op_mid)) { 00510 pstring str; 00511 pstr_sprintf(str, "Got a deferred entry without a request: " 00512 "PANIC: %s\n", share_mode_str(num, share_entry)); 00513 smb_panic(str); 00514 } 00515 00516 if (!is_valid_share_mode_entry(share_entry)) { 00517 return; 00518 } 00519 00520 fsp = file_find_dif(share_entry->dev, share_entry->inode, 00521 share_entry->share_file_id); 00522 if (!fsp) { 00523 DEBUG(0,("validate_my_share_entries: PANIC : %s\n", 00524 share_mode_str(num, share_entry) )); 00525 smb_panic("validate_my_share_entries: Cannot match a " 00526 "share entry with an open file\n"); 00527 } 00528 00529 if (is_deferred_open_entry(share_entry) || 00530 is_unused_share_mode_entry(share_entry)) { 00531 goto panic; 00532 } 00533 00534 if ((share_entry->op_type == NO_OPLOCK) && 00535 (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK)) { 00536 /* Someone has already written to it, but I haven't yet 00537 * noticed */ 00538 return; 00539 } 00540 00541 if (((uint16)fsp->oplock_type) != share_entry->op_type) { 00542 goto panic; 00543 } 00544 00545 return; 00546 00547 panic: 00548 { 00549 pstring str; 00550 DEBUG(0,("validate_my_share_entries: PANIC : %s\n", 00551 share_mode_str(num, share_entry) )); 00552 slprintf(str, sizeof(str)-1, "validate_my_share_entries: " 00553 "file %s, oplock_type = 0x%x, op_type = 0x%x\n", 00554 fsp->fsp_name, (unsigned int)fsp->oplock_type, 00555 (unsigned int)share_entry->op_type ); 00556 smb_panic(str); 00557 } 00558 }
static BOOL is_stat_open | ( | uint32 | access_mask | ) | [static] |
参照元 delay_for_oplocks()・open_file_ntcreate()・open_mode_check().
00562 { 00563 return (access_mask && 00564 ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES| 00565 FILE_WRITE_ATTRIBUTES))==0) && 00566 ((access_mask & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES| 00567 FILE_WRITE_ATTRIBUTES)) != 0)); 00568 }
static NTSTATUS open_mode_check | ( | connection_struct * | conn, | |
const char * | fname, | |||
struct share_mode_lock * | lck, | |||
uint32 | access_mask, | |||
uint32 | share_access, | |||
uint32 | create_options, | |||
BOOL * | file_existed | |||
) | [static] |
参照先 share_mode_lock::delete_on_close・is_stat_open()・is_valid_share_mode_entry()・share_mode_lock::num_share_modes・share_conflict()・share_mode_lock::share_modes・validate_my_share_entries().
参照元 open_directory()・open_file_ntcreate().
00583 { 00584 int i; 00585 00586 if(lck->num_share_modes == 0) { 00587 return NT_STATUS_OK; 00588 } 00589 00590 *file_existed = True; 00591 00592 if (is_stat_open(access_mask)) { 00593 /* Stat open that doesn't trigger oplock breaks or share mode 00594 * checks... ! JRA. */ 00595 return NT_STATUS_OK; 00596 } 00597 00598 /* A delete on close prohibits everything */ 00599 00600 if (lck->delete_on_close) { 00601 return NT_STATUS_DELETE_PENDING; 00602 } 00603 00604 /* 00605 * Check if the share modes will give us access. 00606 */ 00607 00608 #if defined(DEVELOPER) 00609 for(i = 0; i < lck->num_share_modes; i++) { 00610 validate_my_share_entries(i, &lck->share_modes[i]); 00611 } 00612 #endif 00613 00614 if (!lp_share_modes(SNUM(conn))) { 00615 return NT_STATUS_OK; 00616 } 00617 00618 /* Now we check the share modes, after any oplock breaks. */ 00619 for(i = 0; i < lck->num_share_modes; i++) { 00620 00621 if (!is_valid_share_mode_entry(&lck->share_modes[i])) { 00622 continue; 00623 } 00624 00625 /* someone else has a share lock on it, check to see if we can 00626 * too */ 00627 if (share_conflict(&lck->share_modes[i], 00628 access_mask, share_access)) { 00629 return NT_STATUS_SHARING_VIOLATION; 00630 } 00631 } 00632 00633 return NT_STATUS_OK; 00634 }
static BOOL is_delete_request | ( | files_struct * | fsp | ) | [static] |
参照先 files_struct::access_mask・files_struct::oplock_type.
00636 { 00637 return ((fsp->access_mask == DELETE_ACCESS) && 00638 (fsp->oplock_type == NO_OPLOCK)); 00639 }
static BOOL delay_for_oplocks | ( | struct share_mode_lock * | lck, | |
files_struct * | fsp, | |||
int | pass_number, | |||
int | oplock_request | |||
) | [static] |
参照先 files_struct::access_mask・is_stat_open()・is_valid_share_mode_entry()・share_mode_lock::num_share_modes・share_mode_entry::op_type・files_struct::oplock_type・share_mode_lock::share_modes・status.
参照元 open_file_ntcreate().
00655 { 00656 int i; 00657 struct share_mode_entry *exclusive = NULL; 00658 BOOL valid_entry = False; 00659 BOOL delay_it = False; 00660 BOOL have_level2 = False; 00661 NTSTATUS status; 00662 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; 00663 00664 if (oplock_request & INTERNAL_OPEN_ONLY) { 00665 fsp->oplock_type = NO_OPLOCK; 00666 } 00667 00668 if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) { 00669 return False; 00670 } 00671 00672 for (i=0; i<lck->num_share_modes; i++) { 00673 00674 if (!is_valid_share_mode_entry(&lck->share_modes[i])) { 00675 continue; 00676 } 00677 00678 /* At least one entry is not an invalid or deferred entry. */ 00679 valid_entry = True; 00680 00681 if (pass_number == 1) { 00682 if (BATCH_OPLOCK_TYPE(lck->share_modes[i].op_type)) { 00683 SMB_ASSERT(exclusive == NULL); 00684 exclusive = &lck->share_modes[i]; 00685 } 00686 } else { 00687 if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) { 00688 SMB_ASSERT(exclusive == NULL); 00689 exclusive = &lck->share_modes[i]; 00690 } 00691 } 00692 00693 if (lck->share_modes[i].op_type == LEVEL_II_OPLOCK) { 00694 SMB_ASSERT(exclusive == NULL); 00695 have_level2 = True; 00696 } 00697 } 00698 00699 if (!valid_entry) { 00700 /* All entries are placeholders or deferred. 00701 * Directly grant whatever the client wants. */ 00702 if (fsp->oplock_type == NO_OPLOCK) { 00703 /* Store a level2 oplock, but don't tell the client */ 00704 fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; 00705 } 00706 return False; 00707 } 00708 00709 if (exclusive != NULL) { /* Found an exclusive oplock */ 00710 SMB_ASSERT(!have_level2); 00711 delay_it = is_delete_request(fsp) ? 00712 BATCH_OPLOCK_TYPE(exclusive->op_type) : True; 00713 } 00714 00715 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { 00716 /* We can at most grant level2 as there are other 00717 * level2 or NO_OPLOCK entries. */ 00718 fsp->oplock_type = LEVEL_II_OPLOCK; 00719 } 00720 00721 if ((fsp->oplock_type == NO_OPLOCK) && have_level2) { 00722 /* Store a level2 oplock, but don't tell the client */ 00723 fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; 00724 } 00725 00726 if (!delay_it) { 00727 return False; 00728 } 00729 00730 /* 00731 * Send a break message to the oplock holder and delay the open for 00732 * our client. 00733 */ 00734 00735 DEBUG(10, ("Sending break request to PID %s\n", 00736 procid_str_static(&exclusive->pid))); 00737 exclusive->op_mid = get_current_mid(); 00738 00739 /* Create the message. */ 00740 share_mode_entry_to_message(msg, exclusive); 00741 00742 /* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We 00743 don't want this set in the share mode struct pointed to by lck. */ 00744 00745 if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) { 00746 SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE); 00747 } 00748 00749 status = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, 00750 msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); 00751 if (!NT_STATUS_IS_OK(status)) { 00752 DEBUG(3, ("Could not send oplock break message: %s\n", 00753 nt_errstr(status))); 00754 } 00755 00756 return True; 00757 }
static BOOL request_timed_out | ( | struct timeval | request_time, | |
struct timeval | timeout | |||
) | [static] |
参照先 GetTimeOfDay()・timeval_compare()・timeval_sum().
参照元 open_file_ntcreate()・schedule_defer_open().
00761 { 00762 struct timeval now, end_time; 00763 GetTimeOfDay(&now); 00764 end_time = timeval_sum(&request_time, &timeout); 00765 return (timeval_compare(&end_time, &now) < 0); 00766 }
static void defer_open | ( | struct share_mode_lock * | lck, | |
struct timeval | request_time, | |||
struct timeval | timeout, | |||
struct deferred_open_record * | state | |||
) | [static] |
参照先 exit_server()・get_current_mid()・is_deferred_open_entry()・share_mode_lock::num_share_modes・procid_is_me()・share_mode_lock::share_modes.
参照元 open_file_ntcreate()・schedule_defer_open().
00776 { 00777 uint16 mid = get_current_mid(); 00778 int i; 00779 00780 /* Paranoia check */ 00781 00782 for (i=0; i<lck->num_share_modes; i++) { 00783 struct share_mode_entry *e = &lck->share_modes[i]; 00784 00785 if (!is_deferred_open_entry(e)) { 00786 continue; 00787 } 00788 00789 if (procid_is_me(&e->pid) && (e->op_mid == mid)) { 00790 DEBUG(0, ("Trying to defer an already deferred " 00791 "request: mid=%d, exiting\n", mid)); 00792 exit_server("attempt to defer a deferred request"); 00793 } 00794 } 00795 00796 /* End paranoia check */ 00797 00798 DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred " 00799 "open entry for mid %u\n", 00800 (unsigned int)request_time.tv_sec, 00801 (unsigned int)request_time.tv_usec, 00802 (unsigned int)mid)); 00803 00804 if (!push_deferred_smb_message(mid, request_time, timeout, 00805 (char *)state, sizeof(*state))) { 00806 exit_server("push_deferred_smb_message failed"); 00807 } 00808 add_deferred_open(lck, mid, request_time, state->dev, state->inode); 00809 00810 /* 00811 * Push the MID of this packet on the signing queue. 00812 * We only do this once, the first time we push the packet 00813 * onto the deferred open queue, as this has a side effect 00814 * of incrementing the response sequence number. 00815 */ 00816 00817 srv_defer_sign_response(mid); 00818 }
static BOOL open_match_attributes | ( | connection_struct * | conn, | |
const char * | path, | |||
uint32 | old_dos_attr, | |||
uint32 | new_dos_attr, | |||
mode_t | existing_unx_mode, | |||
mode_t | new_unx_mode, | |||
mode_t * | returned_unx_mode | |||
) | [static] |
参照元 open_file_ntcreate().
00832 { 00833 uint32 noarch_old_dos_attr, noarch_new_dos_attr; 00834 00835 noarch_old_dos_attr = (old_dos_attr & ~FILE_ATTRIBUTE_ARCHIVE); 00836 noarch_new_dos_attr = (new_dos_attr & ~FILE_ATTRIBUTE_ARCHIVE); 00837 00838 if((noarch_old_dos_attr == 0 && noarch_new_dos_attr != 0) || 00839 (noarch_old_dos_attr != 0 && ((noarch_old_dos_attr & noarch_new_dos_attr) == noarch_old_dos_attr))) { 00840 *returned_unx_mode = new_unx_mode; 00841 } else { 00842 *returned_unx_mode = (mode_t)0; 00843 } 00844 00845 DEBUG(10,("open_match_attributes: file %s old_dos_attr = 0x%x, " 00846 "existing_unx_mode = 0%o, new_dos_attr = 0x%x " 00847 "returned_unx_mode = 0%o\n", 00848 path, 00849 (unsigned int)old_dos_attr, 00850 (unsigned int)existing_unx_mode, 00851 (unsigned int)new_dos_attr, 00852 (unsigned int)*returned_unx_mode )); 00853 00854 /* If we're mapping SYSTEM and HIDDEN ensure they match. */ 00855 if (lp_map_system(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { 00856 if ((old_dos_attr & FILE_ATTRIBUTE_SYSTEM) && 00857 !(new_dos_attr & FILE_ATTRIBUTE_SYSTEM)) { 00858 return False; 00859 } 00860 } 00861 if (lp_map_hidden(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { 00862 if ((old_dos_attr & FILE_ATTRIBUTE_HIDDEN) && 00863 !(new_dos_attr & FILE_ATTRIBUTE_HIDDEN)) { 00864 return False; 00865 } 00866 } 00867 return True; 00868 }
static files_struct* fcb_or_dos_open | ( | connection_struct * | conn, | |
const char * | fname, | |||
SMB_DEV_T | dev, | |||
SMB_INO_T | inode, | |||
uint32 | access_mask, | |||
uint32 | share_access, | |||
uint32 | create_options | |||
) | [static] |
参照先 files_struct::access_mask・current_user・dup_file_fsp()・fd_handle::fd・files_struct::fh・file_find_di_first()・file_find_di_next()・files_struct::file_pid・files_struct::fsp_name・global_smbpid・is_executable()・fd_handle::private_options・strequal()・current_user::vuid・files_struct::vuid.
参照元 open_file_ntcreate().
00881 { 00882 files_struct *fsp; 00883 files_struct *dup_fsp; 00884 00885 DEBUG(5,("fcb_or_dos_open: attempting old open semantics for " 00886 "file %s.\n", fname )); 00887 00888 for(fsp = file_find_di_first(dev, inode); fsp; 00889 fsp = file_find_di_next(fsp)) { 00890 00891 DEBUG(10,("fcb_or_dos_open: checking file %s, fd = %d, " 00892 "vuid = %u, file_pid = %u, private_options = 0x%x " 00893 "access_mask = 0x%x\n", fsp->fsp_name, 00894 fsp->fh->fd, (unsigned int)fsp->vuid, 00895 (unsigned int)fsp->file_pid, 00896 (unsigned int)fsp->fh->private_options, 00897 (unsigned int)fsp->access_mask )); 00898 00899 if (fsp->fh->fd != -1 && 00900 fsp->vuid == current_user.vuid && 00901 fsp->file_pid == global_smbpid && 00902 (fsp->fh->private_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | 00903 NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) && 00904 (fsp->access_mask & FILE_WRITE_DATA) && 00905 strequal(fsp->fsp_name, fname)) { 00906 DEBUG(10,("fcb_or_dos_open: file match\n")); 00907 break; 00908 } 00909 } 00910 00911 if (!fsp) { 00912 return NULL; 00913 } 00914 00915 /* quite an insane set of semantics ... */ 00916 if (is_executable(fname) && 00917 (fsp->fh->private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) { 00918 DEBUG(10,("fcb_or_dos_open: file fail due to is_executable.\n")); 00919 return NULL; 00920 } 00921 00922 /* We need to duplicate this fsp. */ 00923 if (!NT_STATUS_IS_OK(dup_file_fsp(fsp, access_mask, share_access, 00924 create_options, &dup_fsp))) { 00925 return NULL; 00926 } 00927 00928 return dup_fsp; 00929 }
BOOL map_open_params_to_ntcreate | ( | const char * | fname, | |
int | deny_mode, | |||
int | open_func, | |||
uint32 * | paccess_mask, | |||
uint32 * | pshare_mode, | |||
uint32 * | pcreate_disposition, | |||
uint32 * | pcreate_options | |||
) |
参照先 is_executable().
参照元 call_trans2open()・copy_file()・reply_open()・reply_open_and_X().
00940 { 00941 uint32 access_mask; 00942 uint32 share_mode; 00943 uint32 create_disposition; 00944 uint32 create_options = 0; 00945 00946 DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, " 00947 "open_func = 0x%x\n", 00948 fname, (unsigned int)deny_mode, (unsigned int)open_func )); 00949 00950 /* Create the NT compatible access_mask. */ 00951 switch (GET_OPENX_MODE(deny_mode)) { 00952 case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */ 00953 case DOS_OPEN_RDONLY: 00954 access_mask = FILE_GENERIC_READ; 00955 break; 00956 case DOS_OPEN_WRONLY: 00957 access_mask = FILE_GENERIC_WRITE; 00958 break; 00959 case DOS_OPEN_RDWR: 00960 case DOS_OPEN_FCB: 00961 access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE; 00962 break; 00963 default: 00964 DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n", 00965 (unsigned int)GET_OPENX_MODE(deny_mode))); 00966 return False; 00967 } 00968 00969 /* Create the NT compatible create_disposition. */ 00970 switch (open_func) { 00971 case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST: 00972 create_disposition = FILE_CREATE; 00973 break; 00974 00975 case OPENX_FILE_EXISTS_OPEN: 00976 create_disposition = FILE_OPEN; 00977 break; 00978 00979 case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST: 00980 create_disposition = FILE_OPEN_IF; 00981 break; 00982 00983 case OPENX_FILE_EXISTS_TRUNCATE: 00984 create_disposition = FILE_OVERWRITE; 00985 break; 00986 00987 case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST: 00988 create_disposition = FILE_OVERWRITE_IF; 00989 break; 00990 00991 default: 00992 /* From samba4 - to be confirmed. */ 00993 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) { 00994 create_disposition = FILE_CREATE; 00995 break; 00996 } 00997 DEBUG(10,("map_open_params_to_ntcreate: bad " 00998 "open_func 0x%x\n", (unsigned int)open_func)); 00999 return False; 01000 } 01001 01002 /* Create the NT compatible share modes. */ 01003 switch (GET_DENY_MODE(deny_mode)) { 01004 case DENY_ALL: 01005 share_mode = FILE_SHARE_NONE; 01006 break; 01007 01008 case DENY_WRITE: 01009 share_mode = FILE_SHARE_READ; 01010 break; 01011 01012 case DENY_READ: 01013 share_mode = FILE_SHARE_WRITE; 01014 break; 01015 01016 case DENY_NONE: 01017 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; 01018 break; 01019 01020 case DENY_DOS: 01021 create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS; 01022 if (is_executable(fname)) { 01023 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; 01024 } else { 01025 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) { 01026 share_mode = FILE_SHARE_READ; 01027 } else { 01028 share_mode = FILE_SHARE_NONE; 01029 } 01030 } 01031 break; 01032 01033 case DENY_FCB: 01034 create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB; 01035 share_mode = FILE_SHARE_NONE; 01036 break; 01037 01038 default: 01039 DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n", 01040 (unsigned int)GET_DENY_MODE(deny_mode) )); 01041 return False; 01042 } 01043 01044 DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, " 01045 "share_mode = 0x%x, create_disposition = 0x%x, " 01046 "create_options = 0x%x\n", 01047 fname, 01048 (unsigned int)access_mask, 01049 (unsigned int)share_mode, 01050 (unsigned int)create_disposition, 01051 (unsigned int)create_options )); 01052 01053 if (paccess_mask) { 01054 *paccess_mask = access_mask; 01055 } 01056 if (pshare_mode) { 01057 *pshare_mode = share_mode; 01058 } 01059 if (pcreate_disposition) { 01060 *pcreate_disposition = create_disposition; 01061 } 01062 if (pcreate_options) { 01063 *pcreate_options = create_options; 01064 } 01065 01066 return True; 01067 01068 }
static void schedule_defer_open | ( | struct share_mode_lock * | lck, | |
struct timeval | request_time | |||
) | [static] |
参照先 defer_open()・deferred_open_record::delayed_for_oplocks・share_mode_lock::dev・deferred_open_record::dev・share_mode_lock::ino・deferred_open_record::inode・request_timed_out()・timeval_set().
参照元 open_file_ntcreate().
01071 { 01072 struct deferred_open_record state; 01073 01074 /* This is a relative time, added to the absolute 01075 request_time value to get the absolute timeout time. 01076 Note that if this is the second or greater time we enter 01077 this codepath for this particular request mid then 01078 request_time is left as the absolute time of the *first* 01079 time this request mid was processed. This is what allows 01080 the request to eventually time out. */ 01081 01082 struct timeval timeout; 01083 01084 /* Normally the smbd we asked should respond within 01085 * OPLOCK_BREAK_TIMEOUT seconds regardless of whether 01086 * the client did, give twice the timeout as a safety 01087 * measure here in case the other smbd is stuck 01088 * somewhere else. */ 01089 01090 timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0); 01091 01092 /* Nothing actually uses state.delayed_for_oplocks 01093 but it's handy to differentiate in debug messages 01094 between a 30 second delay due to oplock break, and 01095 a 1 second delay for share mode conflicts. */ 01096 01097 state.delayed_for_oplocks = True; 01098 state.dev = lck->dev; 01099 state.inode = lck->ino; 01100 01101 if (!request_timed_out(request_time, timeout)) { 01102 defer_open(lck, request_time, timeout, &state); 01103 } 01104 }
NTSTATUS open_file_ntcreate | ( | connection_struct * | conn, | |
const char * | fname, | |||
SMB_STRUCT_STAT * | psbuf, | |||
uint32 | access_mask, | |||
uint32 | share_access, | |||
uint32 | create_disposition, | |||
uint32 | create_options, | |||
uint32 | new_dos_attributes, | |||
int | oplock_request, | |||
int * | pinfo, | |||
files_struct ** | result | |||
) |
参照先 files_struct::access_mask・can_access_file()・can_set_delete_on_close()・can_set_initial_delete_on_close()・check_name()・connection_struct::connectpath・current_user・data_blob_::data・defer_open()・del_deferred_open_entry()・del_share_mode()・delay_for_oplocks()・deferred_open_record::delayed_for_oplocks・files_struct::dev・deferred_open_record::dev・dev・directory_has_default_acl()・errno・fcb_or_dos_open()・fd_handle::fd・fd_close()・files_struct::fh・file_free()・file_generic_mapping・file_new()・flags・get_current_mid()・get_open_deferred_message()・get_share_mode_lock()・global_client_failed_oplock_break・files_struct::initial_delete_on_close・files_struct::inode・deferred_open_record::inode・inode・is_stat_open()・lp_parm_int()・map_nt_error_from_unix()・connection_struct::num_files_open・open_file()・open_match_attributes()・open_mode_check()・files_struct::open_time・files_struct::oplock_type・parent_dirname_talloc()・files_struct::posix_open・print_fsp_open()・connection_struct::printer・pending_message_list::private_data・fd_handle::private_options・remove_deferred_open_smb_message()・pending_message_list::request_time・request_timed_out()・result・schedule_defer_open()・se_map_generic()・set_file_oplock()・set_share_mode()・files_struct::share_access・status・timeval_is_zero()・timeval_set()・timeval_zero()・tmp_talloc_ctx()・_unix_token::uid・unix_mode()・use_nt_status()・current_user::ut.
参照元 call_nt_transact_create()・call_trans2open()・can_delete()・can_rename()・copy_file()・copy_internals()・file_version_is_newer()・get_correct_cversion()・reply_ctemp()・reply_mknew()・reply_ntcreate_and_X()・reply_open()・reply_open_and_X()・smb_posix_open()・smb_posix_unlink()・smb_set_file_allocation_info()・smb_set_file_size()・user_can_write_file().
01122 { 01123 int flags=0; 01124 int flags2=0; 01125 BOOL file_existed = VALID_STAT(*psbuf); 01126 BOOL def_acl = False; 01127 BOOL posix_open = False; 01128 BOOL new_file_created = False; 01129 SMB_DEV_T dev = 0; 01130 SMB_INO_T inode = 0; 01131 NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; 01132 files_struct *fsp = NULL; 01133 mode_t new_unx_mode = (mode_t)0; 01134 mode_t unx_mode = (mode_t)0; 01135 int info; 01136 uint32 existing_dos_attributes = 0; 01137 struct pending_message_list *pml = NULL; 01138 uint16 mid = get_current_mid(); 01139 struct timeval request_time = timeval_zero(); 01140 struct share_mode_lock *lck = NULL; 01141 uint32 open_access_mask = access_mask; 01142 NTSTATUS status; 01143 int ret_flock; 01144 char *parent_dir; 01145 const char *newname; 01146 01147 if (conn->printer) { 01148 /* 01149 * Printers are handled completely differently. 01150 * Most of the passed parameters are ignored. 01151 */ 01152 01153 if (pinfo) { 01154 *pinfo = FILE_WAS_CREATED; 01155 } 01156 01157 DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname)); 01158 01159 return print_fsp_open(conn, fname, result); 01160 } 01161 01162 if (!parent_dirname_talloc(tmp_talloc_ctx(), fname, &parent_dir, 01163 &newname)) { 01164 return NT_STATUS_NO_MEMORY; 01165 } 01166 01167 if (new_dos_attributes & FILE_FLAG_POSIX_SEMANTICS) { 01168 posix_open = True; 01169 unx_mode = (mode_t)(new_dos_attributes & ~FILE_FLAG_POSIX_SEMANTICS); 01170 new_dos_attributes = 0; 01171 } else { 01172 /* We add aARCH to this as this mode is only used if the file is 01173 * created new. */ 01174 unx_mode = unix_mode(conn, new_dos_attributes | aARCH, fname, 01175 parent_dir); 01176 } 01177 01178 DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x " 01179 "access_mask=0x%x share_access=0x%x " 01180 "create_disposition = 0x%x create_options=0x%x " 01181 "unix mode=0%o oplock_request=%d\n", 01182 fname, new_dos_attributes, access_mask, share_access, 01183 create_disposition, create_options, unx_mode, 01184 oplock_request)); 01185 01186 if ((pml = get_open_deferred_message(mid)) != NULL) { 01187 struct deferred_open_record *state = 01188 (struct deferred_open_record *)pml->private_data.data; 01189 01190 /* Remember the absolute time of the original 01191 request with this mid. We'll use it later to 01192 see if this has timed out. */ 01193 01194 request_time = pml->request_time; 01195 01196 /* Remove the deferred open entry under lock. */ 01197 lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL); 01198 if (lck == NULL) { 01199 DEBUG(0, ("could not get share mode lock\n")); 01200 } else { 01201 del_deferred_open_entry(lck, mid); 01202 TALLOC_FREE(lck); 01203 } 01204 01205 /* Ensure we don't reprocess this message. */ 01206 remove_deferred_open_smb_message(mid); 01207 } 01208 01209 status = check_name(conn, fname); 01210 if (!NT_STATUS_IS_OK(status)) { 01211 return status; 01212 } 01213 01214 if (!posix_open) { 01215 new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; 01216 if (file_existed) { 01217 existing_dos_attributes = dos_mode(conn, fname, psbuf); 01218 } 01219 } 01220 01221 /* ignore any oplock requests if oplocks are disabled */ 01222 if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break || 01223 IS_VETO_OPLOCK_PATH(conn, fname)) { 01224 /* Mask off everything except the private Samba bits. */ 01225 oplock_request &= SAMBA_PRIVATE_OPLOCK_MASK; 01226 } 01227 01228 /* this is for OS/2 long file names - say we don't support them */ 01229 if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) { 01230 /* OS/2 Workplace shell fix may be main code stream in a later 01231 * release. */ 01232 DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not " 01233 "supported.\n")); 01234 if (use_nt_status()) { 01235 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 01236 } 01237 return NT_STATUS_DOS(ERRDOS, ERRcannotopen); 01238 } 01239 01240 switch( create_disposition ) { 01241 /* 01242 * Currently we're using FILE_SUPERSEDE as the same as 01243 * FILE_OVERWRITE_IF but they really are 01244 * different. FILE_SUPERSEDE deletes an existing file 01245 * (requiring delete access) then recreates it. 01246 */ 01247 case FILE_SUPERSEDE: 01248 /* If file exists replace/overwrite. If file doesn't 01249 * exist create. */ 01250 flags2 |= (O_CREAT | O_TRUNC); 01251 break; 01252 01253 case FILE_OVERWRITE_IF: 01254 /* If file exists replace/overwrite. If file doesn't 01255 * exist create. */ 01256 flags2 |= (O_CREAT | O_TRUNC); 01257 break; 01258 01259 case FILE_OPEN: 01260 /* If file exists open. If file doesn't exist error. */ 01261 if (!file_existed) { 01262 DEBUG(5,("open_file_ntcreate: FILE_OPEN " 01263 "requested for file %s and file " 01264 "doesn't exist.\n", fname )); 01265 errno = ENOENT; 01266 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 01267 } 01268 break; 01269 01270 case FILE_OVERWRITE: 01271 /* If file exists overwrite. If file doesn't exist 01272 * error. */ 01273 if (!file_existed) { 01274 DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE " 01275 "requested for file %s and file " 01276 "doesn't exist.\n", fname )); 01277 errno = ENOENT; 01278 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 01279 } 01280 flags2 |= O_TRUNC; 01281 break; 01282 01283 case FILE_CREATE: 01284 /* If file exists error. If file doesn't exist 01285 * create. */ 01286 if (file_existed) { 01287 DEBUG(5,("open_file_ntcreate: FILE_CREATE " 01288 "requested for file %s and file " 01289 "already exists.\n", fname )); 01290 if (S_ISDIR(psbuf->st_mode)) { 01291 errno = EISDIR; 01292 } else { 01293 errno = EEXIST; 01294 } 01295 return map_nt_error_from_unix(errno); 01296 } 01297 flags2 |= (O_CREAT|O_EXCL); 01298 break; 01299 01300 case FILE_OPEN_IF: 01301 /* If file exists open. If file doesn't exist 01302 * create. */ 01303 flags2 |= O_CREAT; 01304 break; 01305 01306 default: 01307 return NT_STATUS_INVALID_PARAMETER; 01308 } 01309 01310 /* We only care about matching attributes on file exists and 01311 * overwrite. */ 01312 01313 if (!posix_open && file_existed && ((create_disposition == FILE_OVERWRITE) || 01314 (create_disposition == FILE_OVERWRITE_IF))) { 01315 if (!open_match_attributes(conn, fname, 01316 existing_dos_attributes, 01317 new_dos_attributes, psbuf->st_mode, 01318 unx_mode, &new_unx_mode)) { 01319 DEBUG(5,("open_file_ntcreate: attributes missmatch " 01320 "for file %s (%x %x) (0%o, 0%o)\n", 01321 fname, existing_dos_attributes, 01322 new_dos_attributes, 01323 (unsigned int)psbuf->st_mode, 01324 (unsigned int)unx_mode )); 01325 errno = EACCES; 01326 return NT_STATUS_ACCESS_DENIED; 01327 } 01328 } 01329 01330 /* This is a nasty hack - must fix... JRA. */ 01331 if (access_mask == MAXIMUM_ALLOWED_ACCESS) { 01332 open_access_mask = access_mask = FILE_GENERIC_ALL; 01333 } 01334 01335 /* 01336 * Convert GENERIC bits to specific bits. 01337 */ 01338 01339 se_map_generic(&access_mask, &file_generic_mapping); 01340 open_access_mask = access_mask; 01341 01342 if (flags2 & O_TRUNC) { 01343 open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ 01344 } 01345 01346 DEBUG(10, ("open_file_ntcreate: fname=%s, after mapping " 01347 "access_mask=0x%x\n", fname, access_mask )); 01348 01349 /* 01350 * Note that we ignore the append flag as append does not 01351 * mean the same thing under DOS and Unix. 01352 */ 01353 01354 if (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) { 01355 /* DENY_DOS opens are always underlying read-write on the 01356 file handle, no matter what the requested access mask 01357 says. */ 01358 if ((create_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) || 01359 access_mask & (FILE_READ_ATTRIBUTES|FILE_READ_DATA|FILE_READ_EA|FILE_EXECUTE)) { 01360 flags = O_RDWR; 01361 } else { 01362 flags = O_WRONLY; 01363 } 01364 } else { 01365 flags = O_RDONLY; 01366 } 01367 01368 /* 01369 * Currently we only look at FILE_WRITE_THROUGH for create options. 01370 */ 01371 01372 #if defined(O_SYNC) 01373 if ((create_options & FILE_WRITE_THROUGH) && lp_strict_sync(SNUM(conn))) { 01374 flags2 |= O_SYNC; 01375 } 01376 #endif /* O_SYNC */ 01377 01378 if (posix_open && (access_mask & FILE_APPEND_DATA)) { 01379 flags2 |= O_APPEND; 01380 } 01381 01382 if (!posix_open && !CAN_WRITE(conn)) { 01383 /* 01384 * We should really return a permission denied error if either 01385 * O_CREAT or O_TRUNC are set, but for compatibility with 01386 * older versions of Samba we just AND them out. 01387 */ 01388 flags2 &= ~(O_CREAT|O_TRUNC); 01389 } 01390 01391 /* 01392 * Ensure we can't write on a read-only share or file. 01393 */ 01394 01395 if (flags != O_RDONLY && file_existed && 01396 (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_attributes))) { 01397 DEBUG(5,("open_file_ntcreate: write access requested for " 01398 "file %s on read only %s\n", 01399 fname, !CAN_WRITE(conn) ? "share" : "file" )); 01400 errno = EACCES; 01401 return NT_STATUS_ACCESS_DENIED; 01402 } 01403 01404 status = file_new(conn, &fsp); 01405 if(!NT_STATUS_IS_OK(status)) { 01406 return status; 01407 } 01408 01409 fsp->dev = psbuf->st_dev; 01410 fsp->inode = psbuf->st_ino; 01411 fsp->share_access = share_access; 01412 fsp->fh->private_options = create_options; 01413 fsp->access_mask = open_access_mask; /* We change this to the 01414 * requested access_mask after 01415 * the open is done. */ 01416 fsp->posix_open = posix_open; 01417 01418 /* Ensure no SAMBA_PRIVATE bits can be set. */ 01419 fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK); 01420 01421 if (timeval_is_zero(&request_time)) { 01422 request_time = fsp->open_time; 01423 } 01424 01425 if (file_existed) { 01426 dev = psbuf->st_dev; 01427 inode = psbuf->st_ino; 01428 01429 lck = get_share_mode_lock(NULL, dev, inode, 01430 conn->connectpath, 01431 fname); 01432 01433 if (lck == NULL) { 01434 file_free(fsp); 01435 DEBUG(0, ("Could not get share mode lock\n")); 01436 return NT_STATUS_SHARING_VIOLATION; 01437 } 01438 01439 /* First pass - send break only on batch oplocks. */ 01440 if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { 01441 schedule_defer_open(lck, request_time); 01442 TALLOC_FREE(lck); 01443 file_free(fsp); 01444 return NT_STATUS_SHARING_VIOLATION; 01445 } 01446 01447 /* Use the client requested access mask here, not the one we 01448 * open with. */ 01449 status = open_mode_check(conn, fname, lck, 01450 access_mask, share_access, 01451 create_options, &file_existed); 01452 01453 if (NT_STATUS_IS_OK(status)) { 01454 /* We might be going to allow this open. Check oplock 01455 * status again. */ 01456 /* Second pass - send break for both batch or 01457 * exclusive oplocks. */ 01458 if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { 01459 schedule_defer_open(lck, request_time); 01460 TALLOC_FREE(lck); 01461 file_free(fsp); 01462 return NT_STATUS_SHARING_VIOLATION; 01463 } 01464 } 01465 01466 if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { 01467 /* DELETE_PENDING is not deferred for a second */ 01468 TALLOC_FREE(lck); 01469 file_free(fsp); 01470 return status; 01471 } 01472 01473 if (!NT_STATUS_IS_OK(status)) { 01474 uint32 can_access_mask; 01475 BOOL can_access = True; 01476 01477 SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)); 01478 01479 /* Check if this can be done with the deny_dos and fcb 01480 * calls. */ 01481 if (create_options & 01482 (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| 01483 NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { 01484 files_struct *fsp_dup; 01485 01486 /* Use the client requested access mask here, 01487 * not the one we open with. */ 01488 fsp_dup = fcb_or_dos_open(conn, fname, dev, 01489 inode, access_mask, 01490 share_access, 01491 create_options); 01492 01493 if (fsp_dup) { 01494 TALLOC_FREE(lck); 01495 file_free(fsp); 01496 if (pinfo) { 01497 *pinfo = FILE_WAS_OPENED; 01498 } 01499 conn->num_files_open++; 01500 *result = fsp_dup; 01501 return NT_STATUS_OK; 01502 } 01503 } 01504 01505 /* 01506 * This next line is a subtlety we need for 01507 * MS-Access. If a file open will fail due to share 01508 * permissions and also for security (access) reasons, 01509 * we need to return the access failed error, not the 01510 * share error. We can't open the file due to kernel 01511 * oplock deadlock (it's possible we failed above on 01512 * the open_mode_check()) so use a userspace check. 01513 */ 01514 01515 if (flags & O_RDWR) { 01516 can_access_mask = FILE_READ_DATA|FILE_WRITE_DATA; 01517 } else if (flags & O_WRONLY) { 01518 can_access_mask = FILE_WRITE_DATA; 01519 } else { 01520 can_access_mask = FILE_READ_DATA; 01521 } 01522 01523 if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) || 01524 !can_access_file(conn,fname,psbuf,can_access_mask)) { 01525 can_access = False; 01526 } 01527 01528 /* 01529 * If we're returning a share violation, ensure we 01530 * cope with the braindead 1 second delay. 01531 */ 01532 01533 if (!(oplock_request & INTERNAL_OPEN_ONLY) && 01534 lp_defer_sharing_violations()) { 01535 struct timeval timeout; 01536 struct deferred_open_record state; 01537 int timeout_usecs; 01538 01539 /* this is a hack to speed up torture tests 01540 in 'make test' */ 01541 timeout_usecs = lp_parm_int(SNUM(conn), 01542 "smbd","sharedelay", 01543 SHARING_VIOLATION_USEC_WAIT); 01544 01545 /* This is a relative time, added to the absolute 01546 request_time value to get the absolute timeout time. 01547 Note that if this is the second or greater time we enter 01548 this codepath for this particular request mid then 01549 request_time is left as the absolute time of the *first* 01550 time this request mid was processed. This is what allows 01551 the request to eventually time out. */ 01552 01553 timeout = timeval_set(0, timeout_usecs); 01554 01555 /* Nothing actually uses state.delayed_for_oplocks 01556 but it's handy to differentiate in debug messages 01557 between a 30 second delay due to oplock break, and 01558 a 1 second delay for share mode conflicts. */ 01559 01560 state.delayed_for_oplocks = False; 01561 state.dev = dev; 01562 state.inode = inode; 01563 01564 if (!request_timed_out(request_time, 01565 timeout)) { 01566 defer_open(lck, request_time, timeout, 01567 &state); 01568 } 01569 } 01570 01571 TALLOC_FREE(lck); 01572 if (can_access) { 01573 /* 01574 * We have detected a sharing violation here 01575 * so return the correct error code 01576 */ 01577 status = NT_STATUS_SHARING_VIOLATION; 01578 } else { 01579 status = NT_STATUS_ACCESS_DENIED; 01580 } 01581 file_free(fsp); 01582 return status; 01583 } 01584 01585 /* 01586 * We exit this block with the share entry *locked*..... 01587 */ 01588 } 01589 01590 SMB_ASSERT(!file_existed || (lck != NULL)); 01591 01592 /* 01593 * Ensure we pay attention to default ACLs on directories if required. 01594 */ 01595 01596 if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) && 01597 (def_acl = directory_has_default_acl(conn, parent_dir))) { 01598 unx_mode = 0777; 01599 } 01600 01601 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o, " 01602 "access_mask = 0x%x, open_access_mask = 0x%x\n", 01603 (unsigned int)flags, (unsigned int)flags2, 01604 (unsigned int)unx_mode, (unsigned int)access_mask, 01605 (unsigned int)open_access_mask)); 01606 01607 /* 01608 * open_file strips any O_TRUNC flags itself. 01609 */ 01610 01611 fsp_open = open_file(fsp, conn, parent_dir, newname, fname, psbuf, 01612 flags|flags2, unx_mode, access_mask, 01613 open_access_mask); 01614 01615 if (!NT_STATUS_IS_OK(fsp_open)) { 01616 if (lck != NULL) { 01617 TALLOC_FREE(lck); 01618 } 01619 file_free(fsp); 01620 return fsp_open; 01621 } 01622 01623 if (!file_existed) { 01624 01625 /* 01626 * Deal with the race condition where two smbd's detect the 01627 * file doesn't exist and do the create at the same time. One 01628 * of them will win and set a share mode, the other (ie. this 01629 * one) should check if the requested share mode for this 01630 * create is allowed. 01631 */ 01632 01633 /* 01634 * Now the file exists and fsp is successfully opened, 01635 * fsp->dev and fsp->inode are valid and should replace the 01636 * dev=0,inode=0 from a non existent file. Spotted by 01637 * Nadav Danieli <nadavd@exanet.com>. JRA. 01638 */ 01639 01640 dev = fsp->dev; 01641 inode = fsp->inode; 01642 01643 lck = get_share_mode_lock(NULL, dev, inode, 01644 conn->connectpath, 01645 fname); 01646 01647 if (lck == NULL) { 01648 DEBUG(0, ("open_file_ntcreate: Could not get share " 01649 "mode lock for %s\n", fname)); 01650 fd_close(conn, fsp); 01651 file_free(fsp); 01652 return NT_STATUS_SHARING_VIOLATION; 01653 } 01654 01655 /* First pass - send break only on batch oplocks. */ 01656 if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { 01657 schedule_defer_open(lck, request_time); 01658 TALLOC_FREE(lck); 01659 fd_close(conn, fsp); 01660 file_free(fsp); 01661 return NT_STATUS_SHARING_VIOLATION; 01662 } 01663 01664 status = open_mode_check(conn, fname, lck, 01665 access_mask, share_access, 01666 create_options, &file_existed); 01667 01668 if (NT_STATUS_IS_OK(status)) { 01669 /* We might be going to allow this open. Check oplock 01670 * status again. */ 01671 /* Second pass - send break for both batch or 01672 * exclusive oplocks. */ 01673 if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { 01674 schedule_defer_open(lck, request_time); 01675 TALLOC_FREE(lck); 01676 fd_close(conn, fsp); 01677 file_free(fsp); 01678 return NT_STATUS_SHARING_VIOLATION; 01679 } 01680 } 01681 01682 if (!NT_STATUS_IS_OK(status)) { 01683 struct deferred_open_record state; 01684 01685 fd_close(conn, fsp); 01686 file_free(fsp); 01687 01688 state.delayed_for_oplocks = False; 01689 state.dev = dev; 01690 state.inode = inode; 01691 01692 /* Do it all over again immediately. In the second 01693 * round we will find that the file existed and handle 01694 * the DELETE_PENDING and FCB cases correctly. No need 01695 * to duplicate the code here. Essentially this is a 01696 * "goto top of this function", but don't tell 01697 * anybody... */ 01698 01699 defer_open(lck, request_time, timeval_zero(), 01700 &state); 01701 TALLOC_FREE(lck); 01702 return status; 01703 } 01704 01705 /* 01706 * We exit this block with the share entry *locked*..... 01707 */ 01708 01709 } 01710 01711 SMB_ASSERT(lck != NULL); 01712 01713 /* note that we ignore failure for the following. It is 01714 basically a hack for NFS, and NFS will never set one of 01715 these only read them. Nobody but Samba can ever set a deny 01716 mode and we have already checked our more authoritative 01717 locking database for permission to set this deny mode. If 01718 the kernel refuses the operations then the kernel is wrong. 01719 note that GPFS supports it as well - jmcd */ 01720 01721 ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, fsp->fh->fd, share_access); 01722 if(ret_flock == -1 ){ 01723 01724 TALLOC_FREE(lck); 01725 fd_close(conn, fsp); 01726 file_free(fsp); 01727 01728 return NT_STATUS_SHARING_VIOLATION; 01729 } 01730 01731 /* 01732 * At this point onwards, we can guarentee that the share entry 01733 * is locked, whether we created the file or not, and that the 01734 * deny mode is compatible with all current opens. 01735 */ 01736 01737 /* 01738 * If requested, truncate the file. 01739 */ 01740 01741 if (flags2&O_TRUNC) { 01742 /* 01743 * We are modifing the file after open - update the stat 01744 * struct.. 01745 */ 01746 if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || 01747 (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { 01748 status = map_nt_error_from_unix(errno); 01749 TALLOC_FREE(lck); 01750 fd_close(conn,fsp); 01751 file_free(fsp); 01752 return status; 01753 } 01754 } 01755 01756 /* Record the options we were opened with. */ 01757 fsp->share_access = share_access; 01758 fsp->fh->private_options = create_options; 01759 fsp->access_mask = access_mask; 01760 01761 if (file_existed) { 01762 /* stat opens on existing files don't get oplocks. */ 01763 if (is_stat_open(open_access_mask)) { 01764 fsp->oplock_type = NO_OPLOCK; 01765 } 01766 01767 if (!(flags2 & O_TRUNC)) { 01768 info = FILE_WAS_OPENED; 01769 } else { 01770 info = FILE_WAS_OVERWRITTEN; 01771 } 01772 } else { 01773 info = FILE_WAS_CREATED; 01774 } 01775 01776 if (pinfo) { 01777 *pinfo = info; 01778 } 01779 01780 /* 01781 * Setup the oplock info in both the shared memory and 01782 * file structs. 01783 */ 01784 01785 if ((fsp->oplock_type != NO_OPLOCK) && 01786 (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) { 01787 if (!set_file_oplock(fsp, fsp->oplock_type)) { 01788 /* Could not get the kernel oplock */ 01789 fsp->oplock_type = NO_OPLOCK; 01790 } 01791 } 01792 01793 if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || info == FILE_WAS_SUPERSEDED) { 01794 new_file_created = True; 01795 } 01796 01797 set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type, new_file_created); 01798 01799 /* Handle strange delete on close create semantics. */ 01800 if ((create_options & FILE_DELETE_ON_CLOSE) && can_set_initial_delete_on_close(lck)) { 01801 status = can_set_delete_on_close(fsp, True, new_dos_attributes); 01802 01803 if (!NT_STATUS_IS_OK(status)) { 01804 /* Remember to delete the mode we just added. */ 01805 del_share_mode(lck, fsp); 01806 TALLOC_FREE(lck); 01807 fd_close(conn,fsp); 01808 file_free(fsp); 01809 return status; 01810 } 01811 /* Note that here we set the *inital* delete on close flag, 01812 not the regular one. The magic gets handled in close. */ 01813 fsp->initial_delete_on_close = True; 01814 } 01815 01816 if (new_file_created) { 01817 /* Files should be initially set as archive */ 01818 if (lp_map_archive(SNUM(conn)) || 01819 lp_store_dos_attributes(SNUM(conn))) { 01820 if (!posix_open) { 01821 SMB_STRUCT_STAT tmp_sbuf; 01822 SET_STAT_INVALID(tmp_sbuf); 01823 if (file_set_dosmode( 01824 conn, fname, 01825 new_dos_attributes | aARCH, 01826 &tmp_sbuf, 01827 parent_dir) == 0) { 01828 unx_mode = tmp_sbuf.st_mode; 01829 } 01830 } 01831 } 01832 } 01833 01834 /* 01835 * Take care of inherited ACLs on created files - if default ACL not 01836 * selected. 01837 */ 01838 01839 if (!posix_open && !file_existed && !def_acl) { 01840 01841 int saved_errno = errno; /* We might get ENOSYS in the next 01842 * call.. */ 01843 01844 if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, unx_mode) == -1 && 01845 errno == ENOSYS) { 01846 errno = saved_errno; /* Ignore ENOSYS */ 01847 } 01848 01849 } else if (new_unx_mode) { 01850 01851 int ret = -1; 01852 01853 /* Attributes need changing. File already existed. */ 01854 01855 { 01856 int saved_errno = errno; /* We might get ENOSYS in the 01857 * next call.. */ 01858 ret = SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, 01859 new_unx_mode); 01860 01861 if (ret == -1 && errno == ENOSYS) { 01862 errno = saved_errno; /* Ignore ENOSYS */ 01863 } else { 01864 DEBUG(5, ("open_file_ntcreate: reset " 01865 "attributes of file %s to 0%o\n", 01866 fname, (unsigned int)new_unx_mode)); 01867 ret = 0; /* Don't do the fchmod below. */ 01868 } 01869 } 01870 01871 if ((ret == -1) && 01872 (SMB_VFS_FCHMOD(fsp, fsp->fh->fd, new_unx_mode) == -1)) 01873 DEBUG(5, ("open_file_ntcreate: failed to reset " 01874 "attributes of file %s to 0%o\n", 01875 fname, (unsigned int)new_unx_mode)); 01876 } 01877 01878 /* If this is a successful open, we must remove any deferred open 01879 * records. */ 01880 del_deferred_open_entry(lck, mid); 01881 TALLOC_FREE(lck); 01882 01883 conn->num_files_open++; 01884 01885 *result = fsp; 01886 return NT_STATUS_OK; 01887 }
NTSTATUS open_file_fchmod | ( | connection_struct * | conn, | |
const char * | fname, | |||
SMB_STRUCT_STAT * | psbuf, | |||
files_struct ** | result | |||
) |
参照先 file_free()・file_new()・open_file()・result・status.
参照元 set_ea_dos_attribute()・try_chown().
01895 { 01896 files_struct *fsp = NULL; 01897 NTSTATUS status; 01898 01899 if (!VALID_STAT(*psbuf)) { 01900 return NT_STATUS_INVALID_PARAMETER; 01901 } 01902 01903 status = file_new(conn, &fsp); 01904 if(!NT_STATUS_IS_OK(status)) { 01905 return status; 01906 } 01907 01908 /* note! we must use a non-zero desired access or we don't get 01909 a real file descriptor. Oh what a twisted web we weave. */ 01910 status = open_file(fsp, conn, NULL, NULL, fname, psbuf, O_WRONLY, 0, 01911 FILE_WRITE_DATA, FILE_WRITE_DATA); 01912 01913 /* 01914 * This is not a user visible file open. 01915 * Don't set a share mode and don't increment 01916 * the conn->num_files_open. 01917 */ 01918 01919 if (!NT_STATUS_IS_OK(status)) { 01920 file_free(fsp); 01921 return status; 01922 } 01923 01924 *result = fsp; 01925 return NT_STATUS_OK; 01926 }
NTSTATUS close_file_fchmod | ( | files_struct * | fsp | ) |
参照先 files_struct::conn・fd_close()・file_free()・status.
参照元 set_ea_dos_attribute()・try_chown().
01933 { 01934 NTSTATUS status = fd_close(fsp->conn, fsp); 01935 file_free(fsp); 01936 return status; 01937 }
static NTSTATUS mkdir_internal | ( | connection_struct * | conn, | |
const char * | name, | |||
uint32 | file_attributes, | |||
SMB_STRUCT_STAT * | psbuf | |||
) | [static] |
参照先 change_dir_owner_to_parent()・check_name()・errno・inherit_access_acl()・map_nt_error_from_unix()・mode・notify_fname()・parent_dirname_talloc()・status・strerror()・tmp_talloc_ctx()・unix_mode().
参照元 open_directory().
01943 { 01944 mode_t mode; 01945 char *parent_dir; 01946 const char *dirname; 01947 NTSTATUS status; 01948 BOOL posix_open = False; 01949 01950 if(!CAN_WRITE(conn)) { 01951 DEBUG(5,("mkdir_internal: failing create on read-only share " 01952 "%s\n", lp_servicename(SNUM(conn)))); 01953 return NT_STATUS_ACCESS_DENIED; 01954 } 01955 01956 status = check_name(conn, name); 01957 if (!NT_STATUS_IS_OK(status)) { 01958 return status; 01959 } 01960 01961 if (!parent_dirname_talloc(tmp_talloc_ctx(), name, &parent_dir, 01962 &dirname)) { 01963 return NT_STATUS_NO_MEMORY; 01964 } 01965 01966 if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { 01967 posix_open = True; 01968 mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS); 01969 } else { 01970 mode = unix_mode(conn, aDIR, name, parent_dir); 01971 } 01972 01973 if (SMB_VFS_MKDIR(conn, name, mode) != 0) { 01974 return map_nt_error_from_unix(errno); 01975 } 01976 01977 /* Ensure we're checking for a symlink here.... */ 01978 /* We don't want to get caught by a symlink racer. */ 01979 01980 if (SMB_VFS_LSTAT(conn, name, psbuf) == -1) { 01981 DEBUG(2, ("Could not stat directory '%s' just created: %s\n", 01982 name, strerror(errno))); 01983 return map_nt_error_from_unix(errno); 01984 } 01985 01986 if (!S_ISDIR(psbuf->st_mode)) { 01987 DEBUG(0, ("Directory just '%s' created is not a directory\n", 01988 name)); 01989 return NT_STATUS_ACCESS_DENIED; 01990 } 01991 01992 if (lp_store_dos_attributes(SNUM(conn))) { 01993 if (!posix_open) { 01994 file_set_dosmode(conn, name, 01995 file_attributes | aDIR, NULL, 01996 parent_dir); 01997 } 01998 } 01999 02000 if (lp_inherit_perms(SNUM(conn))) { 02001 inherit_access_acl(conn, parent_dir, name, mode); 02002 } 02003 02004 if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) { 02005 /* 02006 * Check if high bits should have been set, 02007 * then (if bits are missing): add them. 02008 * Consider bits automagically set by UNIX, i.e. SGID bit from parent 02009 * dir. 02010 */ 02011 if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_mode)) { 02012 SMB_VFS_CHMOD(conn, name, 02013 psbuf->st_mode | (mode & ~psbuf->st_mode)); 02014 } 02015 } 02016 02017 /* Change the owner if required. */ 02018 if (lp_inherit_owner(SNUM(conn))) { 02019 change_dir_owner_to_parent(conn, parent_dir, name, psbuf); 02020 } 02021 02022 notify_fname(conn, NOTIFY_ACTION_ADDED, FILE_NOTIFY_CHANGE_DIR_NAME, 02023 name); 02024 02025 return NT_STATUS_OK; 02026 }
NTSTATUS open_directory | ( | connection_struct * | conn, | |
const char * | fname, | |||
SMB_STRUCT_STAT * | psbuf, | |||
uint32 | access_mask, | |||
uint32 | share_access, | |||
uint32 | create_disposition, | |||
uint32 | create_options, | |||
uint32 | file_attributes, | |||
int * | pinfo, | |||
files_struct ** | result | |||
) |
参照先 files_struct::access_mask・files_struct::can_lock・files_struct::can_read・can_set_delete_on_close()・files_struct::can_write・connection_struct::connectpath・current_user・files_struct::dev・errno・files_struct::fh・file_free()・file_new()・files_struct::file_pid・files_struct::fsp_name・get_share_mode_lock()・global_smbpid・files_struct::initial_delete_on_close・files_struct::inode・files_struct::is_directory・is_ntfs_stream_name()・files_struct::is_stat・map_nt_error_from_unix()・mkdir_internal()・files_struct::mode・files_struct::modified・nt_errstr()・connection_struct::num_files_open・open_mode_check()・files_struct::oplock_type・files_struct::posix_open・files_struct::print_file・fd_handle::private_options・result・files_struct::sent_oplock_break・set_share_mode()・files_struct::share_access・status・string_set()・_unix_token::uid・current_user::ut・current_user::vuid・files_struct::vuid.
参照元 _srv_net_file_query_secdesc()・_srv_net_file_set_secdesc()・append_parent_acl()・call_nt_transact_create()・conn_get_nt_acl()・create_directory()・reply_ntcreate_and_X()・smb_posix_mkdir()・smb_posix_unlink()・user_can_read_file().
02042 { 02043 files_struct *fsp = NULL; 02044 BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; 02045 struct share_mode_lock *lck = NULL; 02046 NTSTATUS status; 02047 int info = 0; 02048 02049 DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, " 02050 "share_access = 0x%x create_options = 0x%x, " 02051 "create_disposition = 0x%x, file_attributes = 0x%x\n", 02052 fname, 02053 (unsigned int)access_mask, 02054 (unsigned int)share_access, 02055 (unsigned int)create_options, 02056 (unsigned int)create_disposition, 02057 (unsigned int)file_attributes)); 02058 02059 if (is_ntfs_stream_name(fname)) { 02060 DEBUG(0,("open_directory: %s is a stream name!\n", fname )); 02061 return NT_STATUS_NOT_A_DIRECTORY; 02062 } 02063 02064 switch( create_disposition ) { 02065 case FILE_OPEN: 02066 02067 info = FILE_WAS_OPENED; 02068 02069 /* 02070 * We want to follow symlinks here. 02071 */ 02072 02073 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) { 02074 return map_nt_error_from_unix(errno); 02075 } 02076 02077 break; 02078 02079 case FILE_CREATE: 02080 02081 /* If directory exists error. If directory doesn't 02082 * exist create. */ 02083 02084 status = mkdir_internal(conn, 02085 fname, 02086 file_attributes, 02087 psbuf); 02088 02089 if (!NT_STATUS_IS_OK(status)) { 02090 DEBUG(2, ("open_directory: unable to create " 02091 "%s. Error was %s\n", fname, 02092 nt_errstr(status))); 02093 return status; 02094 } 02095 02096 info = FILE_WAS_CREATED; 02097 break; 02098 02099 case FILE_OPEN_IF: 02100 /* 02101 * If directory exists open. If directory doesn't 02102 * exist create. 02103 */ 02104 02105 status = mkdir_internal(conn, 02106 fname, 02107 file_attributes, 02108 psbuf); 02109 02110 if (NT_STATUS_IS_OK(status)) { 02111 info = FILE_WAS_CREATED; 02112 } 02113 02114 if (NT_STATUS_EQUAL(status, 02115 NT_STATUS_OBJECT_NAME_COLLISION)) { 02116 info = FILE_WAS_OPENED; 02117 status = NT_STATUS_OK; 02118 } 02119 02120 break; 02121 02122 case FILE_SUPERSEDE: 02123 case FILE_OVERWRITE: 02124 case FILE_OVERWRITE_IF: 02125 default: 02126 DEBUG(5,("open_directory: invalid create_disposition " 02127 "0x%x for directory %s\n", 02128 (unsigned int)create_disposition, fname)); 02129 return NT_STATUS_INVALID_PARAMETER; 02130 } 02131 02132 if(!S_ISDIR(psbuf->st_mode)) { 02133 DEBUG(5,("open_directory: %s is not a directory !\n", 02134 fname )); 02135 return NT_STATUS_NOT_A_DIRECTORY; 02136 } 02137 02138 status = file_new(conn, &fsp); 02139 if(!NT_STATUS_IS_OK(status)) { 02140 return status; 02141 } 02142 02143 /* 02144 * Setup the files_struct for it. 02145 */ 02146 02147 fsp->mode = psbuf->st_mode; 02148 fsp->inode = psbuf->st_ino; 02149 fsp->dev = psbuf->st_dev; 02150 fsp->vuid = current_user.vuid; 02151 fsp->file_pid = global_smbpid; 02152 fsp->can_lock = False; 02153 fsp->can_read = False; 02154 fsp->can_write = False; 02155 02156 fsp->share_access = share_access; 02157 fsp->fh->private_options = create_options; 02158 fsp->access_mask = access_mask; 02159 02160 fsp->print_file = False; 02161 fsp->modified = False; 02162 fsp->oplock_type = NO_OPLOCK; 02163 fsp->sent_oplock_break = NO_BREAK_SENT; 02164 fsp->is_directory = True; 02165 fsp->is_stat = False; 02166 fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False; 02167 02168 string_set(&fsp->fsp_name,fname); 02169 02170 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, 02171 conn->connectpath, 02172 fname); 02173 02174 if (lck == NULL) { 02175 DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname)); 02176 file_free(fsp); 02177 return NT_STATUS_SHARING_VIOLATION; 02178 } 02179 02180 status = open_mode_check(conn, fname, lck, 02181 access_mask, share_access, 02182 create_options, &dir_existed); 02183 02184 if (!NT_STATUS_IS_OK(status)) { 02185 TALLOC_FREE(lck); 02186 file_free(fsp); 02187 return status; 02188 } 02189 02190 set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK, True); 02191 02192 /* For directories the delete on close bit at open time seems 02193 always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ 02194 if (create_options & FILE_DELETE_ON_CLOSE) { 02195 status = can_set_delete_on_close(fsp, True, 0); 02196 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) { 02197 TALLOC_FREE(lck); 02198 file_free(fsp); 02199 return status; 02200 } 02201 02202 if (NT_STATUS_IS_OK(status)) { 02203 /* Note that here we set the *inital* delete on close flag, 02204 not the regular one. The magic gets handled in close. */ 02205 fsp->initial_delete_on_close = True; 02206 } 02207 } 02208 02209 TALLOC_FREE(lck); 02210 02211 if (pinfo) { 02212 *pinfo = info; 02213 } 02214 02215 conn->num_files_open++; 02216 02217 *result = fsp; 02218 return NT_STATUS_OK; 02219 }
NTSTATUS create_directory | ( | connection_struct * | conn, | |
const char * | directory | |||
) |
参照先 close_file()・NORMAL_CLOSE・open_directory()・status.
参照元 call_trans2mkdir()・move_driver_to_download_area()・reply_mkdir().
02222 { 02223 NTSTATUS status; 02224 SMB_STRUCT_STAT sbuf; 02225 files_struct *fsp; 02226 02227 SET_STAT_INVALID(sbuf); 02228 02229 status = open_directory(conn, directory, &sbuf, 02230 FILE_READ_ATTRIBUTES, /* Just a stat open */ 02231 FILE_SHARE_NONE, /* Ignored for stat opens */ 02232 FILE_CREATE, 02233 0, 02234 FILE_ATTRIBUTE_DIRECTORY, 02235 NULL, 02236 &fsp); 02237 02238 if (NT_STATUS_IS_OK(status)) { 02239 close_file(fsp, NORMAL_CLOSE); 02240 } 02241 02242 return status; 02243 }
NTSTATUS open_file_stat | ( | connection_struct * | conn, | |
const char * | fname, | |||
SMB_STRUCT_STAT * | psbuf, | |||
files_struct ** | result | |||
) |
参照先 files_struct::can_lock・files_struct::can_read・files_struct::can_write・current_user・files_struct::dev・file_new()・files_struct::file_pid・files_struct::fsp_name・global_smbpid・files_struct::inode・files_struct::is_directory・files_struct::is_stat・files_struct::mode・files_struct::modified・connection_struct::num_files_open・files_struct::oplock_type・files_struct::print_file・result・files_struct::sent_oplock_break・status・string_set()・current_user::vuid・files_struct::vuid.
参照元 _srv_net_file_query_secdesc()・_srv_net_file_set_secdesc()・conn_get_nt_acl()・user_can_read_file().
02251 { 02252 files_struct *fsp = NULL; 02253 NTSTATUS status; 02254 02255 if (!VALID_STAT(*psbuf)) { 02256 return NT_STATUS_INVALID_PARAMETER; 02257 } 02258 02259 /* Can't 'stat' open directories. */ 02260 if(S_ISDIR(psbuf->st_mode)) { 02261 return NT_STATUS_FILE_IS_A_DIRECTORY; 02262 } 02263 02264 status = file_new(conn, &fsp); 02265 if(!NT_STATUS_IS_OK(status)) { 02266 return status; 02267 } 02268 02269 DEBUG(5,("open_file_stat: 'opening' file %s\n", fname)); 02270 02271 /* 02272 * Setup the files_struct for it. 02273 */ 02274 02275 fsp->mode = psbuf->st_mode; 02276 fsp->inode = psbuf->st_ino; 02277 fsp->dev = psbuf->st_dev; 02278 fsp->vuid = current_user.vuid; 02279 fsp->file_pid = global_smbpid; 02280 fsp->can_lock = False; 02281 fsp->can_read = False; 02282 fsp->can_write = False; 02283 fsp->print_file = False; 02284 fsp->modified = False; 02285 fsp->oplock_type = NO_OPLOCK; 02286 fsp->sent_oplock_break = NO_BREAK_SENT; 02287 fsp->is_directory = False; 02288 fsp->is_stat = True; 02289 string_set(&fsp->fsp_name,fname); 02290 02291 conn->num_files_open++; 02292 02293 *result = fsp; 02294 return NT_STATUS_OK; 02295 }
void msg_file_was_renamed | ( | int | msg_type, | |
struct process_id | src, | |||
void * | buf, | |||
size_t | len, | |||
void * | private_data | |||
) |
参照先 files_struct::conn・connection_struct::connectpath・dev・file_find_di_first()・file_find_di_next()・files_struct::fnum・files_struct::fsp_name・inode・string_set().
参照元 open_sockets_smbd().
02304 { 02305 files_struct *fsp; 02306 char *frm = (char *)buf; 02307 SMB_DEV_T dev; 02308 SMB_INO_T inode; 02309 const char *sharepath; 02310 const char *newname; 02311 size_t sp_len; 02312 02313 if (buf == NULL || len < MSG_FILE_RENAMED_MIN_SIZE + 2) { 02314 DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", (int)len)); 02315 return; 02316 } 02317 02318 /* Unpack the message. */ 02319 dev = DEV_T_VAL(frm,0); 02320 inode = INO_T_VAL(frm,8); 02321 sharepath = &frm[16]; 02322 newname = sharepath + strlen(sharepath) + 1; 02323 sp_len = strlen(sharepath); 02324 02325 DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, " 02326 "dev %x, inode %.0f\n", 02327 sharepath, newname, (unsigned int)dev, (double)inode )); 02328 02329 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { 02330 if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) { 02331 DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n", 02332 fsp->fnum, fsp->fsp_name, newname )); 02333 string_set(&fsp->fsp_name, newname); 02334 } else { 02335 /* TODO. JRA. */ 02336 /* Now we have the complete path we can work out if this is 02337 actually within this share and adjust newname accordingly. */ 02338 DEBUG(10,("msg_file_was_renamed: share mismatch (sharepath %s " 02339 "not sharepath %s) " 02340 "fnum %d from %s -> %s\n", 02341 fsp->conn->connectpath, 02342 sharepath, 02343 fsp->fnum, 02344 fsp->fsp_name, 02345 newname )); 02346 } 02347 } 02348 }
struct current_user current_user |
substitute.c の 29 行で定義されています。
uint16 global_smbpid |