📄 open.c
字号:
inode = fsp->inode; lck = get_share_mode_lock(NULL, dev, inode, conn->connectpath, fname); if (lck == NULL) { DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); fd_close(conn, fsp); file_free(fsp); set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); return NULL; } status = open_mode_check(conn, fname, lck, access_mask, share_access, create_options, &file_existed); if (!NT_STATUS_IS_OK(status)) { struct deferred_open_record state; fd_close(conn, fsp); file_free(fsp); state.delayed_for_oplocks = False; state.dev = dev; state.inode = inode; /* Do it all over again immediately. In the second * round we will find that the file existed and handle * the DELETE_PENDING and FCB cases correctly. No need * to duplicate the code here. Essentially this is a * "goto top of this function", but don't tell * anybody... */ defer_open(lck, request_time, timeval_zero(), &state); talloc_free(lck); return NULL; } /* * We exit this block with the share entry *locked*..... */ } SMB_ASSERT(lck != NULL); /* note that we ignore failure for the following. It is basically a hack for NFS, and NFS will never set one of these only read them. Nobody but Samba can ever set a deny mode and we have already checked our more authoritative locking database for permission to set this deny mode. If the kernel refuses the operations then the kernel is wrong */ kernel_flock(fsp, share_access); /* * At this point onwards, we can guarentee that the share entry * is locked, whether we created the file or not, and that the * deny mode is compatible with all current opens. */ /* * If requested, truncate the file. */ if (flags2&O_TRUNC) { /* * We are modifing the file after open - update the stat * struct.. */ if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { talloc_free(lck); fd_close(conn,fsp); file_free(fsp); return NULL; } } /* Record the options we were opened with. */ fsp->share_access = share_access; fsp->fh->private_options = create_options; fsp->access_mask = access_mask; if (file_existed) { if (!(flags2 & O_TRUNC)) { info = FILE_WAS_OPENED; } else { info = FILE_WAS_OVERWRITTEN; } } else { info = FILE_WAS_CREATED; /* Change the owner if required. */ if (lp_inherit_owner(SNUM(conn))) { change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); } } if (pinfo) { *pinfo = info; } /* * Setup the oplock info in both the shared memory and * file structs. */ if ((fsp->oplock_type != NO_OPLOCK) && (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) { if (!set_file_oplock(fsp, fsp->oplock_type)) { /* Could not get the kernel oplock */ fsp->oplock_type = NO_OPLOCK; } } set_share_mode(lck, fsp, 0, fsp->oplock_type); if (create_options & FILE_DELETE_ON_CLOSE) { uint32 dosattr= existing_dos_attributes; NTSTATUS result; if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || info == FILE_WAS_SUPERSEDED) { dosattr = new_dos_attributes; } result = can_set_delete_on_close(fsp, True, dosattr); if (!NT_STATUS_IS_OK(result)) { /* Remember to delete the mode we just added. */ del_share_mode(lck, fsp); talloc_free(lck); fd_close(conn,fsp); file_free(fsp); set_saved_ntstatus(result); return NULL; } lck->delete_on_close = True; lck->modified = True; } if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || info == FILE_WAS_SUPERSEDED) { /* Files should be initially set as archive */ if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { file_set_dosmode(conn, fname, new_dos_attributes | aARCH, NULL, True); } } /* * Take care of inherited ACLs on created files - if default ACL not * selected. */ if (!file_existed && !def_acl) { int saved_errno = errno; /* We might get ENOSYS in the next * call.. */ if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, unx_mode) == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ } } else if (new_unx_mode) { int ret = -1; /* Attributes need changing. File already existed. */ { int saved_errno = errno; /* We might get ENOSYS in the * next call.. */ ret = SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, new_unx_mode); if (ret == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ } else { DEBUG(5, ("open_file_shared: reset " "attributes of file %s to 0%o\n", fname, (unsigned int)new_unx_mode)); ret = 0; /* Don't do the fchmod below. */ } } if ((ret == -1) && (SMB_VFS_FCHMOD(fsp, fsp->fh->fd, new_unx_mode) == -1)) DEBUG(5, ("open_file_shared: failed to reset " "attributes of file %s to 0%o\n", fname, (unsigned int)new_unx_mode)); } /* If this is a successful open, we must remove any deferred open * records. */ del_deferred_open_entry(lck, mid); talloc_free(lck); conn->num_files_open++; return fsp;}/**************************************************************************** Open a file for for write to ensure that we can fchmod it.****************************************************************************/files_struct *open_file_fchmod(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf){ files_struct *fsp = NULL; BOOL fsp_open; if (!VALID_STAT(*psbuf)) { return NULL; } fsp = file_new(conn); if(!fsp) { return NULL; } /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA); /* * This is not a user visible file open. * Don't set a share mode and don't increment * the conn->num_files_open. */ if (!fsp_open) { file_free(fsp); return NULL; } return fsp;}/**************************************************************************** Close the fchmod file fd - ensure no locks are lost.****************************************************************************/int close_file_fchmod(files_struct *fsp){ int ret = fd_close(fsp->conn, fsp); file_free(fsp); return ret;}/**************************************************************************** Open a directory from an NT SMB call.****************************************************************************/files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask, uint32 share_access, uint32 create_disposition, uint32 create_options, int *pinfo){ files_struct *fsp = NULL; BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; BOOL create_dir = False; struct share_mode_lock *lck = NULL; NTSTATUS status; int info = 0; DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, " "share_access = 0x%x create_options = 0x%x, " "create_disposition = 0x%x\n", fname, (unsigned int)access_mask, (unsigned int)share_access, (unsigned int)create_options, (unsigned int)create_disposition)); if (is_ntfs_stream_name(fname)) { DEBUG(0,("open_directory: %s is a stream name!\n", fname )); set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY); return NULL; } switch( create_disposition ) { case FILE_OPEN: /* If directory exists open. If directory doesn't * exist error. */ if (!dir_existed) { DEBUG(5,("open_directory: FILE_OPEN requested " "for directory %s and it doesn't " "exist.\n", fname )); set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); return NULL; } info = FILE_WAS_OPENED; break; case FILE_CREATE: /* If directory exists error. If directory doesn't * exist create. */ if (dir_existed) { DEBUG(5,("open_directory: FILE_CREATE " "requested for directory %s and it " "already exists.\n", fname )); set_saved_error_triple(ERRDOS, ERRfilexists, NT_STATUS_OBJECT_NAME_COLLISION); return NULL; } create_dir = True; info = FILE_WAS_CREATED; break; case FILE_OPEN_IF: /* If directory exists open. If directory doesn't * exist create. */ if (!dir_existed) { create_dir = True; info = FILE_WAS_CREATED; } else { info = FILE_WAS_OPENED; } break; case FILE_SUPERSEDE: case FILE_OVERWRITE: case FILE_OVERWRITE_IF: default: DEBUG(5,("open_directory: invalid create_disposition " "0x%x for directory %s\n", (unsigned int)create_disposition, fname)); file_free(fsp); set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); return NULL; } if (create_dir) { /* * Try and create the directory. */ /* We know bad_path is false as it's caught earlier. */ status = mkdir_internal(conn, fname, False); if (!NT_STATUS_IS_OK(status)) { DEBUG(2,("open_directory: unable to create %s. " "Error was %s\n", fname, strerror(errno) )); /* Ensure we return the correct NT status to the * client. */ set_saved_error_triple(0, 0, status); return NULL; } /* Ensure we're checking for a symlink here.... */ /* We don't want to get caught by a symlink racer. */ if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { return NULL; } if(!S_ISDIR(psbuf->st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); return NULL; } } fsp = file_new(conn); if(!fsp) { return NULL; } /* * Setup the files_struct for it. */ fsp->mode = psbuf->st_mode; fsp->inode = psbuf->st_ino; fsp->dev = psbuf->st_dev; fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = True; fsp->can_read = False; fsp->can_write = False; fsp->share_access = share_access; fsp->fh->private_options = create_options; fsp->access_mask = access_mask; fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = True; fsp->is_stat = False; string_set(&fsp->fsp_name,fname); lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, conn->connectpath, fname); if (lck == NULL) { DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname)); file_free(fsp); set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); return NULL; } status = open_mode_check(conn, fname, lck, access_mask, share_access, create_options, &dir_existed); if (!NT_STATUS_IS_OK(status)) { set_saved_ntstatus(status); talloc_free(lck); file_free(fsp); return NULL; } set_share_mode(lck, fsp, 0, NO_OPLOCK); if (create_options & FILE_DELETE_ON_CLOSE) { status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { set_saved_ntstatus(status); talloc_free(lck); file_free(fsp); return NULL; } lck->delete_on_close = True; lck->modified = True; } talloc_free(lck); /* Change the owner if required. */ if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); } if (pinfo) { *pinfo = info; } conn->num_files_open++; return fsp;}/**************************************************************************** Open a pseudo-file (no locking checks - a 'stat' open).****************************************************************************/files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf){ files_struct *fsp = NULL; if (!VALID_STAT(*psbuf)) return NULL; /* Can't 'stat' open directories. */ if(S_ISDIR(psbuf->st_mode)) return NULL; fsp = file_new(conn); if(!fsp) return NULL; DEBUG(5,("open_file_stat: 'opening' file %s\n", fname)); /* * Setup the files_struct for it. */ fsp->mode = psbuf->st_mode; fsp->inode = psbuf->st_ino; fsp->dev = psbuf->st_dev; fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; fsp->is_stat = True; string_set(&fsp->fsp_name,fname); conn->num_files_open++; return fsp;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -