📄 open.c
字号:
DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) )); slprintf(str, sizeof(str)-1, "validate_my_share_entries: " "file %s, oplock_type = 0x%x, op_type = 0x%x\n", fsp->fsp_name, (unsigned int)fsp->oplock_type, (unsigned int)share_entry->op_type ); smb_panic(str); }}#endifstatic BOOL is_stat_open(uint32 access_mask){ return (access_mask && ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES| FILE_WRITE_ATTRIBUTES))==0) && ((access_mask & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES| FILE_WRITE_ATTRIBUTES)) != 0));}/**************************************************************************** Deal with share modes Invarient: Share mode must be locked on entry and exit. Returns -1 on error, or number of share modes on success (may be zero).****************************************************************************/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){ int i; if(lck->num_share_modes == 0) { return NT_STATUS_OK; } *file_existed = True; if (is_stat_open(access_mask)) { /* Stat open that doesn't trigger oplock breaks or share mode * checks... ! JRA. */ return NT_STATUS_OK; } /* A delete on close prohibits everything */ if (lck->delete_on_close) { return NT_STATUS_DELETE_PENDING; } /* * Check if the share modes will give us access. */ #if defined(DEVELOPER) for(i = 0; i < lck->num_share_modes; i++) { validate_my_share_entries(i, &lck->share_modes[i]); }#endif if (!lp_share_modes(SNUM(conn))) { return NT_STATUS_OK; } /* Now we check the share modes, after any oplock breaks. */ for(i = 0; i < lck->num_share_modes; i++) { if (!is_valid_share_mode_entry(&lck->share_modes[i])) { continue; } /* someone else has a share lock on it, check to see if we can * too */ if (share_conflict(&lck->share_modes[i], access_mask, share_access)) { return NT_STATUS_SHARING_VIOLATION; } } return NT_STATUS_OK;}static BOOL is_delete_request(files_struct *fsp) { return ((fsp->access_mask == DELETE_ACCESS) && (fsp->oplock_type == NO_OPLOCK));}/* * 1) No files open at all: Grant whatever the client wants. * * 2) Exclusive (or batch) oplock around: If the requested access is a delete * request, break if the oplock around is a batch oplock. If it's another * requested access type, break. * * 3) Only level2 around: Grant level2 and do nothing else. */static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp){ int i; struct share_mode_entry *exclusive = NULL; BOOL delay_it = False; BOOL have_level2 = False; if (is_stat_open(fsp->access_mask)) { fsp->oplock_type = NO_OPLOCK; return False; } if (lck->num_share_modes == 0) { /* No files open at all: Directly grant whatever the client * wants. */ if (fsp->oplock_type == NO_OPLOCK) { /* Store a level2 oplock, but don't tell the client */ fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; } return False; } for (i=0; i<lck->num_share_modes; i++) { if (!is_valid_share_mode_entry(&lck->share_modes[i])) { continue; } if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) { SMB_ASSERT(exclusive == NULL); exclusive = &lck->share_modes[i]; } if (lck->share_modes[i].op_type == LEVEL_II_OPLOCK) { have_level2 = True; } } if (exclusive != NULL) { /* Found an exclusive oplock */ SMB_ASSERT(!have_level2); delay_it = is_delete_request(fsp) ? BATCH_OPLOCK_TYPE(exclusive->op_type) : True; } if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { /* We can at most grant level2 */ fsp->oplock_type = LEVEL_II_OPLOCK; } if ((fsp->oplock_type == NO_OPLOCK) && have_level2) { /* Store a level2 oplock, but don't tell the client */ fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; } if (delay_it) { BOOL ret; char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; DEBUG(10, ("Sending break request to PID %s\n", procid_str_static(&exclusive->pid))); exclusive->op_mid = get_current_mid(); share_mode_entry_to_message(msg, exclusive); become_root(); ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); unbecome_root(); if (!ret) { DEBUG(3, ("Could not send oplock break message\n")); } file_free(fsp); } return delay_it;}static BOOL request_timed_out(struct timeval request_time, struct timeval timeout){ struct timeval now, end_time; GetTimeOfDay(&now); end_time = timeval_sum(&request_time, &timeout); return (timeval_compare(&end_time, &now) < 0);}/**************************************************************************** Handle the 1 second delay in returning a SHARING_VIOLATION error.****************************************************************************/static void defer_open(struct share_mode_lock *lck, struct timeval request_time, struct timeval timeout, struct deferred_open_record *state){ uint16 mid = get_current_mid(); int i; /* Paranoia check */ for (i=0; i<lck->num_share_modes; i++) { struct share_mode_entry *e = &lck->share_modes[i]; if (!is_deferred_open_entry(e)) { continue; } if (procid_is_me(&e->pid) && (e->op_mid == mid)) { DEBUG(0, ("Trying to defer an already deferred " "request: mid=%d, exiting\n", mid)); exit_server("exiting"); } } /* End paranoia check */ DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred " "open entry for mid %u\n", (unsigned int)request_time.tv_sec, (unsigned int)request_time.tv_usec, (unsigned int)mid)); if (!push_deferred_smb_message(mid, request_time, timeout, (char *)state, sizeof(*state))) { exit_server("push_deferred_smb_message failed\n"); } add_deferred_open(lck, mid, request_time, state->dev, state->inode); /* * Push the MID of this packet on the signing queue. * We only do this once, the first time we push the packet * onto the deferred open queue, as this has a side effect * of incrementing the response sequence number. */ srv_defer_sign_response(mid);}/**************************************************************************** Set a kernel flock on a file for NFS interoperability. This requires a patch to Linux.****************************************************************************/static void kernel_flock(files_struct *fsp, uint32 share_mode){#if HAVE_KERNEL_SHARE_MODES int kernel_mode = 0; if (share_mode == FILE_SHARE_WRITE) { kernel_mode = LOCK_MAND|LOCK_WRITE; } else if (share_mode == FILE_SHARE_READ) { kernel_mode = LOCK_MAND|LOCK_READ; } else if (share_mode == FILE_SHARE_NONE) { kernel_mode = LOCK_MAND; } if (kernel_mode) { flock(fsp->fh->fd, kernel_mode); }#endif ;}/**************************************************************************** On overwrite open ensure that the attributes match.****************************************************************************/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){ uint32 noarch_old_dos_attr, noarch_new_dos_attr; noarch_old_dos_attr = (old_dos_attr & ~FILE_ATTRIBUTE_ARCHIVE); noarch_new_dos_attr = (new_dos_attr & ~FILE_ATTRIBUTE_ARCHIVE); if((noarch_old_dos_attr == 0 && noarch_new_dos_attr != 0) || (noarch_old_dos_attr != 0 && ((noarch_old_dos_attr & noarch_new_dos_attr) == noarch_old_dos_attr))) { *returned_unx_mode = new_unx_mode; } else { *returned_unx_mode = (mode_t)0; } DEBUG(10,("open_match_attributes: file %s old_dos_attr = 0x%x, " "existing_unx_mode = 0%o, new_dos_attr = 0x%x " "returned_unx_mode = 0%o\n", path, (unsigned int)old_dos_attr, (unsigned int)existing_unx_mode, (unsigned int)new_dos_attr, (unsigned int)*returned_unx_mode )); /* If we're mapping SYSTEM and HIDDEN ensure they match. */ if (lp_map_system(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { if ((old_dos_attr & FILE_ATTRIBUTE_SYSTEM) && !(new_dos_attr & FILE_ATTRIBUTE_SYSTEM)) { return False; } } if (lp_map_hidden(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { if ((old_dos_attr & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_attr & FILE_ATTRIBUTE_HIDDEN)) { return False; } } return True;}/**************************************************************************** Special FCB or DOS processing in the case of a sharing violation. Try and find a duplicated file handle.****************************************************************************/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){ files_struct *fsp; files_struct *dup_fsp; DEBUG(5,("fcb_or_dos_open: attempting old open semantics for " "file %s.\n", fname )); for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { DEBUG(10,("fcb_or_dos_open: checking file %s, fd = %d, " "vuid = %u, file_pid = %u, private_options = 0x%x " "access_mask = 0x%x\n", fsp->fsp_name, fsp->fh->fd, (unsigned int)fsp->vuid, (unsigned int)fsp->file_pid, (unsigned int)fsp->fh->private_options, (unsigned int)fsp->access_mask )); if (fsp->fh->fd != -1 && fsp->vuid == current_user.vuid && fsp->file_pid == global_smbpid && (fsp->fh->private_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) && (fsp->access_mask & FILE_WRITE_DATA) && strequal(fsp->fsp_name, fname)) { DEBUG(10,("fcb_or_dos_open: file match\n")); break; } } if (!fsp) { return NULL; } /* quite an insane set of semantics ... */ if (is_executable(fname) && (fsp->fh->private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) { DEBUG(10,("fcb_or_dos_open: file fail due to is_executable.\n")); return NULL; } /* We need to duplicate this fsp. */ dup_fsp = dup_file_fsp(fsp, access_mask, share_access, create_options); if (!dup_fsp) { return NULL; } return dup_fsp;}/**************************************************************************** Open a file with a share mode - old openX method - map into NTCreate.****************************************************************************/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){ uint32 access_mask; uint32 share_mode; uint32 create_disposition; uint32 create_options = 0; DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, " "open_func = 0x%x\n", fname, (unsigned int)deny_mode, (unsigned int)open_func )); /* Create the NT compatible access_mask. */ switch (GET_OPENX_MODE(deny_mode)) { case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */ case DOS_OPEN_RDONLY: access_mask = FILE_GENERIC_READ; break; case DOS_OPEN_WRONLY: access_mask = FILE_GENERIC_WRITE; break; case DOS_OPEN_RDWR: case DOS_OPEN_FCB: access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE; break; default: DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n", (unsigned int)GET_OPENX_MODE(deny_mode))); return False; } /* Create the NT compatible create_disposition. */ switch (open_func) { case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST: create_disposition = FILE_CREATE; break; case OPENX_FILE_EXISTS_OPEN: create_disposition = FILE_OPEN; break; case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST: create_disposition = FILE_OPEN_IF; break; case OPENX_FILE_EXISTS_TRUNCATE: create_disposition = FILE_OVERWRITE; break; case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST: create_disposition = FILE_OVERWRITE_IF; break; default: /* From samba4 - to be confirmed. */ if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) { create_disposition = FILE_CREATE; break; } DEBUG(10,("map_open_params_to_ntcreate: bad " "open_func 0x%x\n", (unsigned int)open_func)); return False; } /* Create the NT compatible share modes. */ switch (GET_DENY_MODE(deny_mode)) { case DENY_ALL: share_mode = FILE_SHARE_NONE; break; case DENY_WRITE: share_mode = FILE_SHARE_READ; break; case DENY_READ: share_mode = FILE_SHARE_WRITE; break; case DENY_NONE: share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; break; case DENY_DOS: create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS; if (is_executable(fname)) { share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; } else { if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) { share_mode = FILE_SHARE_READ; } else { share_mode = FILE_SHARE_NONE; } } break; case DENY_FCB: create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB; share_mode = FILE_SHARE_NONE; break; default: DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n", (unsigned int)GET_DENY_MODE(deny_mode) )); return False; } DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, " "share_mode = 0x%x, create_disposition = 0x%x, " "create_options = 0x%x\n", fname, (unsigned int)access_mask, (unsigned int)share_mode, (unsigned int)create_disposition, (unsigned int)create_options )); if (paccess_mask) { *paccess_mask = access_mask; } if (pshare_mode) { *pshare_mode = share_mode; } if (pcreate_disposition) { *pcreate_disposition = create_disposition; } if (pcreate_options) { *pcreate_options = create_options; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -