diff options
-rw-r--r-- | source3/modules/onefs.h | 10 | ||||
-rw-r--r-- | source3/modules/onefs_open.c | 376 | ||||
-rw-r--r-- | source3/modules/onefs_streams.c | 137 | ||||
-rw-r--r-- | source3/modules/vfs_onefs_shadow_copy.c | 20 |
4 files changed, 322 insertions, 221 deletions
diff --git a/source3/modules/onefs.h b/source3/modules/onefs.h index 3e6cd29b51..6cb8036e85 100644 --- a/source3/modules/onefs.h +++ b/source3/modules/onefs.h @@ -64,14 +64,12 @@ int onefs_close(vfs_handle_struct *handle, struct files_struct *fsp); int onefs_rename(vfs_handle_struct *handle, const char *oldname, const char *newname); -int onefs_stat(vfs_handle_struct *handle, const char *fname, - SMB_STRUCT_STAT *sbuf); +int onefs_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname); int onefs_fstat(vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_STAT *sbuf); -int onefs_lstat(vfs_handle_struct *handle, const char *path, - SMB_STRUCT_STAT *sbuf); +int onefs_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname); int onefs_unlink(vfs_handle_struct *handle, const char *path); @@ -141,6 +139,10 @@ NTSTATUS onefs_samba_sd_to_sd(uint32_t security_info_sent, SEC_DESC *psd, NTSTATUS onefs_split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname, char **pbase, char **pstream); +NTSTATUS onefs_stream_prep_smb_fname(TALLOC_CTX *ctx, + const struct smb_filename *smb_fname_in, + struct smb_filename **smb_fname_out); + int onefs_rdp_add_dir_state(connection_struct *conn, SMB_STRUCT_DIR *dirp); /* diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c index 8b6ae20520..5aade2c562 100644 --- a/source3/modules/onefs_open.c +++ b/source3/modules/onefs_open.c @@ -46,7 +46,7 @@ struct onefs_fsp_data { static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, struct smb_request *req, - const char *fname, + struct smb_filename *smb_fname, uint32_t access_mask, uint32_t share_access, uint32_t create_disposition, @@ -58,8 +58,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, struct ea_list *ea_list, files_struct **result, int *pinfo, - struct onefs_fsp_data *fsp_data, - SMB_STRUCT_STAT *psbuf); + struct onefs_fsp_data *fsp_data); /**************************************************************************** Open a file. @@ -69,9 +68,7 @@ static NTSTATUS onefs_open_file(files_struct *fsp, connection_struct *conn, struct smb_request *req, const char *parent_dir, - const char *name, - const char *path, - SMB_STRUCT_STAT *psbuf, + struct smb_filename *smb_fname, int flags, mode_t unx_mode, uint32 access_mask, @@ -84,18 +81,24 @@ static NTSTATUS onefs_open_file(files_struct *fsp, struct security_descriptor *sd, int *granted_oplock) { + char *path = NULL; + struct smb_filename *smb_fname_onefs = NULL; NTSTATUS status = NT_STATUS_OK; int accmode = (flags & O_ACCMODE); int local_flags = flags; - bool file_existed = VALID_STAT(*psbuf); + bool file_existed = VALID_STAT(smb_fname->st); const char *wild; - char *base = NULL; - char *stream = NULL; int base_fd = -1; fsp->fh->fd = -1; errno = EPERM; + status = get_full_smb_filename(talloc_tos(), smb_fname, + &path); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /* Check permissions */ /* @@ -111,7 +114,8 @@ static NTSTATUS onefs_open_file(files_struct *fsp, if (!CAN_WRITE(conn)) { /* It's a read-only share - fail if we wanted to write. */ if(accmode != O_RDONLY) { - DEBUG(3,("Permission denied opening %s\n", path)); + DEBUG(3, ("Permission denied opening %s\n", + smb_fname_str_dbg(smb_fname))); return NT_STATUS_ACCESS_DENIED; } else if(flags & O_CREAT) { /* We don't want to write - but we must make sure that @@ -137,7 +141,7 @@ static NTSTATUS onefs_open_file(files_struct *fsp, if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) { DEBUG(10,("onefs_open_file: truncate requested on read-only " - "open for file %s\n", path)); + "open for file %s\n", smb_fname_str_dbg(smb_fname))); local_flags = (flags & ~O_ACCMODE)|O_RDWR; } @@ -148,7 +152,7 @@ static NTSTATUS onefs_open_file(files_struct *fsp, * open flags. JRA. */ - if (file_existed && S_ISFIFO(psbuf->st_ex_mode)) { + if (file_existed && S_ISFIFO(smb_fname->st.st_ex_mode)) { local_flags |= O_NONBLOCK; } #endif @@ -174,7 +178,7 @@ static NTSTATUS onefs_open_file(files_struct *fsp, * then was copied via Samba. */ DEBUG(1, ("onefs_open_file: creating file with wildcard: %s\n", - path)); + smb_fname_str_dbg(smb_fname))); return NT_STATUS_OBJECT_NAME_INVALID; } @@ -190,25 +194,30 @@ static NTSTATUS onefs_open_file(files_struct *fsp, flags |= O_NOFOLLOW; } #endif - /* Stream handling */ - if (is_ntfs_stream_name(path)) { - status = onefs_split_ntfs_stream_name(talloc_tos(), path, - &base, &stream); + /* Setup a onefs-style smb_fname struct. */ + status = onefs_stream_prep_smb_fname(talloc_tos(), smb_fname, + &smb_fname_onefs); + if (!NT_STATUS_IS_OK(status)) { + return status; } - /* It's a stream, so pass in the base_fd */ - if ((conn->fs_capabilities & FILE_NAMED_STREAMS) && stream != NULL) { + + /* If it's a stream pass in the base_fd */ + if ((conn->fs_capabilities & FILE_NAMED_STREAMS) && + is_ntfs_stream_smb_fname(smb_fname_onefs)) { SMB_ASSERT(fsp->base_fsp); - DEBUG(10,("Opening a stream: base=%s(%d), stream=%s\n", - base, fsp->base_fsp->fh->fd, stream)); + DEBUG(10, ("Opening a stream: base=%s(%d), stream=%s\n", + smb_fname_onefs->base_name, fsp->base_fsp->fh->fd, + smb_fname_onefs->stream_name)); base_fd = fsp->base_fsp->fh->fd; } fsp->fh->fd = onefs_sys_create_file(conn, base_fd, - stream != NULL ? stream : - (base != NULL ? base : path), + smb_fname_onefs->stream_name != NULL ? + smb_fname_onefs->stream_name : + smb_fname_onefs->base_name, access_mask, open_access_mask, share_access, @@ -220,6 +229,7 @@ static NTSTATUS onefs_open_file(files_struct *fsp, sd, new_dos_attributes, granted_oplock); + TALLOC_FREE(smb_fname_onefs); if (fsp->fh->fd == -1) { if (errno == EMFILE) { @@ -237,9 +247,9 @@ static NTSTATUS onefs_open_file(files_struct *fsp, } status = map_nt_error_from_unix(errno); - DEBUG(3,("Error opening file %s (%s) (local_flags=%d) " - "(flags=%d)\n", - path, strerror(errno), local_flags, flags)); + DEBUG(3, ("Error opening file %s (%s) (local_flags=%d) " + "(flags=%d)\n", smb_fname_str_dbg(smb_fname), + strerror(errno), local_flags, flags)); return status; } @@ -265,13 +275,15 @@ static NTSTATUS onefs_open_file(files_struct *fsp, int ret; if (fsp->fh->fd == -1) { - ret = SMB_VFS_STAT(conn, path, psbuf); + ret = SMB_VFS_STAT(conn, smb_fname); } else { - ret = SMB_VFS_FSTAT(fsp, psbuf); + ret = SMB_VFS_FSTAT(fsp, &smb_fname->st); /* If we have an fd, this stat should succeed. */ if (ret == -1) { - DEBUG(0,("Error doing fstat on open file %s " - "(%s)\n", path,strerror(errno) )); + DEBUG(0, ("Error doing fstat on open file %s " + "(%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno) )); } } @@ -289,14 +301,14 @@ static NTSTATUS onefs_open_file(files_struct *fsp, * so catch a directory open and return an EISDIR. JRA. */ - if(S_ISDIR(psbuf->st_ex_mode)) { + if(S_ISDIR(smb_fname->st.st_ex_mode)) { fd_close(fsp); errno = EISDIR; return NT_STATUS_FILE_IS_A_DIRECTORY; } - fsp->mode = psbuf->st_ex_mode; - fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); + fsp->mode = smb_fname->st.st_ex_mode; + fsp->file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st); fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; fsp->file_pid = req ? req->smbpid : 0; fsp->can_lock = True; @@ -419,7 +431,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, ****************************************************************************/ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, struct smb_request *req, - const char *fname, + struct smb_filename *smb_fname, uint32 access_mask, uint32 share_access, uint32 create_disposition, @@ -429,12 +441,11 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, struct security_descriptor *sd, files_struct *fsp, int *pinfo, - struct onefs_fsp_data *fsp_data, - SMB_STRUCT_STAT *psbuf) + struct onefs_fsp_data *fsp_data) { int flags=0; int flags2=0; - bool file_existed = VALID_STAT(*psbuf); + bool file_existed = VALID_STAT(smb_fname->st); bool def_acl = False; bool posix_open = False; bool new_file_created = False; @@ -451,13 +462,19 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, NTSTATUS status; int ret_flock; char *parent_dir; - const char *newname; int granted_oplock; uint64_t oplock_callback_id = 0; uint32 createfile_attributes = 0; + char *fname = NULL; ZERO_STRUCT(id); + status = get_full_smb_filename(talloc_tos(), smb_fname, + &fname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (conn->printer) { /* * Printers are handled completely differently. @@ -469,12 +486,14 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, } DEBUG(10, ("onefs_open_file_ntcreate: printer open fname=%s\n", - fname)); + smb_fname_str_dbg(smb_fname))); - return print_fsp_open(req, conn, fname, req->vuid, fsp, psbuf); + return print_fsp_open(req, conn, fname, req->vuid, fsp, + &smb_fname->st); } - if (!parent_dirname(talloc_tos(), fname, &parent_dir, &newname)) { + if (!parent_dirname(talloc_tos(), smb_fname->base_name, &parent_dir, + NULL)) { return NT_STATUS_NO_MEMORY; } @@ -493,9 +512,9 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, "access_mask=0x%x share_access=0x%x " "create_disposition = 0x%x create_options=0x%x " "unix mode=0%o oplock_request=0x%x\n", - fname, new_dos_attributes, access_mask, share_access, - create_disposition, create_options, unx_mode, - oplock_request)); + smb_fname_str_dbg(smb_fname), new_dos_attributes, + access_mask, share_access, create_disposition, + create_options, unx_mode, oplock_request)); /* * Any non-stat-only open has the potential to contend oplocks, which @@ -514,7 +533,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, * it off, but if a customer were to turn it on it would be * bad. */ - if (req == NULL && !is_stat_open(access_mask) && !is_ntfs_stream_name(fname)) { + if (req == NULL && !is_stat_open(access_mask) && + !is_ntfs_stream_smb_fname(smb_fname)) { smb_panic("NULL req on a non-stat-open!"); } @@ -563,7 +583,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, } } - status = check_name(conn, fname); + status = check_name(conn, smb_fname->base_name); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -571,7 +591,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, if (!posix_open) { new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; if (file_existed) { - existing_dos_attributes = dos_mode(conn, fname, psbuf); + existing_dos_attributes = dos_mode(conn, fname, + &smb_fname->st); } } @@ -583,13 +604,13 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, /* Ignore oplock requests if oplocks are disabled. */ if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break || - IS_VETO_OPLOCK_PATH(conn, fname)) { + IS_VETO_OPLOCK_PATH(conn, smb_fname->base_name)) { /* Mask off everything except the private Samba bits. */ oplock_request &= SAMBA_PRIVATE_OPLOCK_MASK; } /* this is for OS/2 long file names - say we don't support them */ - if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) { + if (!lp_posix_pathnames() && strstr(smb_fname->base_name,".+,;=[].")) { /* OS/2 Workplace shell fix may be main code stream in a later * release. */ DEBUG(5,("onefs_open_file_ntcreate: OS/2 long filenames are " @@ -632,7 +653,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, if (!file_existed) { DEBUG(5,("onefs_open_file_ntcreate: FILE_OPEN " "requested for file %s and file " - "doesn't exist.\n", fname )); + "doesn't exist.\n", + smb_fname_str_dbg(smb_fname))); errno = ENOENT; return NT_STATUS_OBJECT_NAME_NOT_FOUND; } @@ -645,7 +667,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, DEBUG(5, ("onefs_open_file_ntcreate: " "FILE_OVERWRITE requested for file " "%s and file doesn't exist.\n", - fname)); + smb_fname_str_dbg(smb_fname))); errno = ENOENT; return NT_STATUS_OBJECT_NAME_NOT_FOUND; } @@ -660,8 +682,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, DEBUG(5, ("onefs_open_file_ntcreate: " "FILE_CREATE requested for file %s " "and file already exists.\n", - fname)); - if (S_ISDIR(psbuf->st_ex_mode)) { + smb_fname_str_dbg(smb_fname))); + if (S_ISDIR(smb_fname->st.st_ex_mode)) { errno = EISDIR; } else { errno = EEXIST; @@ -686,13 +708,15 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, ((create_disposition == FILE_OVERWRITE) || (create_disposition == FILE_OVERWRITE_IF))) { if (!open_match_attributes(conn, existing_dos_attributes, - new_dos_attributes, psbuf->st_ex_mode, + new_dos_attributes, + smb_fname->st.st_ex_mode, unx_mode, &new_unx_mode)) { DEBUG(5, ("onefs_open_file_ntcreate: attributes " "missmatch for file %s (%x %x) (0%o, 0%o)\n", - fname, existing_dos_attributes, + smb_fname_str_dbg(smb_fname), + existing_dos_attributes, new_dos_attributes, - (unsigned int)psbuf->st_ex_mode, + (unsigned int)smb_fname->st.st_ex_mode, (unsigned int)unx_mode )); errno = EACCES; return NT_STATUS_ACCESS_DENIED; @@ -720,7 +744,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, DEBUG(10, ("onefs_open_file_ntcreate: fname=%s, after mapping " "open_access_mask=%#x, access_mask=0x%x\n", - fname, open_access_mask, access_mask)); + smb_fname_str_dbg(smb_fname), open_access_mask, + access_mask)); /* * Note that we ignore the append flag as append does not @@ -792,14 +817,15 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_attributes))) { DEBUG(5, ("onefs_open_file_ntcreate: write access requested " "for file %s on read only %s\n", - fname, !CAN_WRITE(conn) ? "share" : "file" )); + smb_fname_str_dbg(smb_fname), + !CAN_WRITE(conn) ? "share" : "file" )); errno = EACCES; return NT_STATUS_ACCESS_DENIED; } DEBUG(10, ("fsp = %p\n", fsp)); - fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); + fsp->file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st); fsp->share_access = share_access; fsp->fh->private_options = create_options; fsp->access_mask = open_access_mask; /* We change this to the @@ -815,8 +841,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, } if (file_existed) { - struct timespec old_write_time = psbuf->st_ex_mtime; - id = vfs_file_id_from_sbuf(conn, psbuf); + struct timespec old_write_time = smb_fname->st.st_ex_mtime; + id = vfs_file_id_from_sbuf(conn, &smb_fname->st); lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, @@ -874,9 +900,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, conn, req, parent_dir, - newname, - fname, - psbuf, + smb_fname, flags|flags2, unx_mode, access_mask, @@ -899,18 +923,19 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, struct deferred_open_record state; struct timespec old_write_time; - old_write_time = psbuf->st_ex_mtime; + old_write_time = smb_fname->st.st_ex_mtime; DEBUG(3, ("Someone created file %s with an " "oplock after we looked: Retrying\n", - fname)); + smb_fname_str_dbg(smb_fname))); /* * We hit the race that when we did the stat * on the file it did not exist, and someone * has created it in between the stat and the * open_file() call. Just retry immediately. */ - id = vfs_file_id_from_sbuf(conn, psbuf); + id = vfs_file_id_from_sbuf(conn, + &smb_fname->st); if (!(lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, fname, &old_write_time))) { @@ -919,7 +944,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, */ DEBUG(0, ("onefs_open_file_ntcreate: " "Could not get share mode " - "lock for %s\n", fname)); + "lock for %s\n", + smb_fname_str_dbg(smb_fname))); status = NT_STATUS_SHARING_VIOLATION; goto cleanup_destroy; } @@ -935,7 +961,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, } /* Waiting for an oplock */ DEBUG(5,("Async createfile because a client has an " - "oplock on %s\n", fname)); + "oplock on %s\n", + smb_fname_str_dbg(smb_fname))); SMB_ASSERT(req); schedule_defer_open(lck, request_time, req); @@ -1002,8 +1029,10 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, can_access_mask = FILE_READ_DATA; } - if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) || - !can_access_file_data(conn,fname,psbuf,can_access_mask)) { + if (((can_access_mask & FILE_WRITE_DATA) && + !CAN_WRITE(conn)) || + !can_access_file_data(conn, smb_fname, + can_access_mask)) { can_access = False; } @@ -1088,7 +1117,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, } if (!file_existed) { - struct timespec old_write_time = psbuf->st_ex_mtime; + struct timespec old_write_time = smb_fname->st.st_ex_mtime; /* * Deal with the race condition where two smbd's detect the * file doesn't exist and do the create at the same time. One @@ -1112,7 +1141,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, if (lck == NULL) { DEBUG(0, ("onefs_open_file_ntcreate: Could not get " - "share mode lock for %s\n", fname)); + "share mode lock for %s\n", + smb_fname_str_dbg(smb_fname))); fd_close(fsp); return NT_STATUS_SHARING_VIOLATION; } @@ -1153,8 +1183,9 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, SMB_ASSERT(lck != NULL); /* Delete streams if create_disposition requires it */ - if (file_existed && clear_ads && !is_ntfs_stream_name(fname)) { - status = delete_all_streams(conn, fname); + if (file_existed && clear_ads && + !is_ntfs_stream_smb_fname(smb_fname)) { + status = delete_all_streams(conn, smb_fname->base_name); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(lck); fd_close(fsp); @@ -1265,8 +1296,9 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, * selected. * May be necessary depending on acl policies. */ - if (!posix_open && !file_existed && !def_acl && !(VALID_STAT(*psbuf) - && (psbuf->st_ex_flags & SF_HASNTFSACL))) { + if (!posix_open && !file_existed && !def_acl && + !(VALID_STAT(smb_fname->st) && + (smb_fname->st.st_ex_flags & SF_HASNTFSACL))) { int saved_errno = errno; /* We might get ENOSYS in the next * call.. */ @@ -1292,7 +1324,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, } else { DEBUG(5, ("onefs_open_file_ntcreate: reset " "attributes of file %s to 0%o\n", - fname, (unsigned int)new_unx_mode)); + smb_fname_str_dbg(smb_fname), + (unsigned int)new_unx_mode)); ret = 0; /* Don't do the fchmod below. */ } } @@ -1301,7 +1334,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, (SMB_VFS_FCHMOD(fsp, new_unx_mode) == -1)) DEBUG(5, ("onefs_open_file_ntcreate: failed to reset " "attributes of file %s to 0%o\n", - fname, (unsigned int)new_unx_mode)); + smb_fname_str_dbg(smb_fname), + (unsigned int)new_unx_mode)); } /* If this is a successful open, we must remove any deferred open @@ -1320,7 +1354,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, ****************************************************************************/ static NTSTATUS onefs_open_directory(connection_struct *conn, struct smb_request *req, - const char *fname, + struct smb_filename *smb_dname, uint32 access_mask, uint32 share_access, uint32 create_disposition, @@ -1328,8 +1362,7 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, uint32 file_attributes, struct security_descriptor *sd, files_struct **result, - int *pinfo, - SMB_STRUCT_STAT *psbuf) + int *pinfo) { files_struct *fsp = NULL; struct share_mode_lock *lck = NULL; @@ -1346,14 +1379,16 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, "access_mask = 0x%x, " "share_access = 0x%x create_options = 0x%x, " "create_disposition = 0x%x, file_attributes = 0x%x\n", - fname, (unsigned int)access_mask, (unsigned int)share_access, - (unsigned int)create_options, (unsigned int)create_disposition, + smb_fname_str_dbg(smb_dname), (unsigned int)access_mask, + (unsigned int)share_access, (unsigned int)create_options, + (unsigned int)create_disposition, (unsigned int)file_attributes)); if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS) && (conn->fs_capabilities & FILE_NAMED_STREAMS) && - is_ntfs_stream_name(fname)) { - DEBUG(2, ("onefs_open_directory: %s is a stream name!\n", fname)); + is_ntfs_stream_smb_fname(smb_dname)) { + DEBUG(2, ("onefs_open_directory: %s is a stream name!\n", + smb_fname_str_dbg(smb_dname))); return NT_STATUS_NOT_A_DIRECTORY; } @@ -1386,7 +1421,8 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, default: DEBUG(5, ("onefs_open_directory: invalid " "create_disposition 0x%x for directory %s\n", - (unsigned int)create_disposition, fname)); + (unsigned int)create_disposition, + smb_fname_str_dbg(smb_dname))); return NT_STATUS_INVALID_PARAMETER; } @@ -1399,7 +1435,8 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, } /* Get parent dirname */ - if (!parent_dirname(talloc_tos(), fname, &parent_dir, &dirname)) { + if (!parent_dirname(talloc_tos(), smb_dname->base_name, &parent_dir, + &dirname)) { return NT_STATUS_NO_MEMORY; } @@ -1408,7 +1445,7 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS); file_attributes = 0; } else { - mode = unix_mode(conn, aDIR, fname, parent_dir); + mode = unix_mode(conn, aDIR, smb_dname->base_name, parent_dir); } /* @@ -1431,7 +1468,7 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, retry_open: fsp->fh->fd = onefs_sys_create_file(conn, -1, - fname, + smb_dname->base_name, access_mask, access_mask, share_access, @@ -1445,7 +1482,8 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, NULL); if (fsp->fh->fd == -1) { - DEBUG(3, ("Error opening %s. Errno=%d (%s).\n", fname, errno, + DEBUG(3, ("Error opening %s. Errno=%d (%s).\n", + smb_fname_str_dbg(smb_dname), errno, strerror(errno))); SMB_ASSERT(errno != EINPROGRESS); @@ -1467,15 +1505,16 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, file_free(req, fsp); if ((errno == ENOENT) && (create_disposition == FILE_OPEN)) { - DEBUG(5,("onefs_open_directory: FILE_OPEN requested " + DEBUG(5, ("onefs_open_directory: FILE_OPEN requested " "for directory %s and it doesn't " - "exist.\n", fname )); + "exist.\n", smb_fname_str_dbg(smb_dname))); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } else if ((errno == EEXIST) && (create_disposition == FILE_CREATE)) { - DEBUG(5,("onefs_open_directory: FILE_CREATE " + DEBUG(5, ("onefs_open_directory: FILE_CREATE " "requested for directory %s and it " - "already exists.\n", fname )); + "already exists.\n", + smb_fname_str_dbg(smb_dname))); return NT_STATUS_OBJECT_NAME_COLLISION; } else if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { /* Catch sharing violations. */ @@ -1488,15 +1527,18 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, if (info == FILE_WAS_CREATED) { /* Pulled from mkdir_internal() */ - if (SMB_VFS_LSTAT(conn, fname, psbuf) == -1) { + if (SMB_VFS_LSTAT(conn, smb_dname) == -1) { DEBUG(2, ("Could not stat directory '%s' just " - "created: %s\n",fname, strerror(errno))); + "created: %s\n", + smb_fname_str_dbg(smb_dname), + strerror(errno))); return map_nt_error_from_unix(errno); } - if (!S_ISDIR(psbuf->st_ex_mode)) { + if (!S_ISDIR(smb_dname->st.st_ex_mode)) { DEBUG(0, ("Directory just '%s' created is not a " - "directory\n", fname)); + "directory\n", + smb_fname_str_dbg(smb_dname))); return NT_STATUS_ACCESS_DENIED; } @@ -1508,32 +1550,35 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, * parent dir. */ if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && - (mode & ~psbuf->st_ex_mode)) { - SMB_VFS_CHMOD(conn, fname, (psbuf->st_ex_mode | - (mode & ~psbuf->st_ex_mode))); + (mode & ~smb_dname->st.st_ex_mode)) { + SMB_VFS_CHMOD(conn, smb_dname->base_name, + (smb_dname->st.st_ex_mode | + (mode & ~smb_dname->st.st_ex_mode))); } } /* Change the owner if required. */ if (lp_inherit_owner(SNUM(conn))) { - change_dir_owner_to_parent(conn, parent_dir, fname, - psbuf); + change_dir_owner_to_parent(conn, parent_dir, + smb_dname->base_name, + &smb_dname->st); } notify_fname(conn, NOTIFY_ACTION_ADDED, - FILE_NOTIFY_CHANGE_DIR_NAME, fname); + FILE_NOTIFY_CHANGE_DIR_NAME, + smb_dname->base_name); } /* Stat the fd for Samba bookkeeping. */ - if(SMB_VFS_FSTAT(fsp, psbuf) != 0) { + if(SMB_VFS_FSTAT(fsp, &smb_dname->st) != 0) { fd_close(fsp); file_free(req, fsp); return map_nt_error_from_unix(errno); } /* Setup the files_struct for it. */ - fsp->mode = psbuf->st_ex_mode; - fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); + fsp->mode = smb_dname->st.st_ex_mode; + fsp->file_id = vfs_file_id_from_sbuf(conn, &smb_dname->st); fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; fsp->file_pid = req ? req->smbpid : 0; fsp->can_lock = False; @@ -1553,21 +1598,21 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, fsp->is_directory = True; fsp->posix_open = posix_open; - string_set(&fsp->fsp_name,fname); + string_set(&fsp->fsp_name, smb_dname->base_name); - mtimespec = psbuf->st_ex_mtime; + mtimespec = smb_dname->st.st_ex_mtime; /* * Still set the samba share mode lock for correct delete-on-close * semantics and to make smbstatus more useful. */ lck = get_share_mode_lock(talloc_tos(), fsp->file_id, - conn->connectpath, - fname, &mtimespec); + conn->connectpath, smb_dname->base_name, + &mtimespec); if (lck == NULL) { DEBUG(0, ("onefs_open_directory: Could not get share mode " - "lock for %s\n", fname)); + "lock for %s\n", smb_fname_str_dbg(smb_dname))); fd_close(fsp); file_free(req, fsp); return NT_STATUS_SHARING_VIOLATION; @@ -1618,7 +1663,7 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, */ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, struct smb_request *req, - const char *fname, + struct smb_filename *smb_fname, uint32_t access_mask, uint32_t share_access, uint32_t create_disposition, @@ -1630,10 +1675,8 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, struct ea_list *ea_list, files_struct **result, int *pinfo, - struct onefs_fsp_data *fsp_data, - SMB_STRUCT_STAT *psbuf) + struct onefs_fsp_data *fsp_data) { - SMB_STRUCT_STAT sbuf; int info = FILE_WAS_OPENED; files_struct *base_fsp = NULL; files_struct *fsp = NULL; @@ -1650,7 +1693,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, (unsigned int)create_disposition, (unsigned int)create_options, (unsigned int)oplock_request, - ea_list, sd, fname)); + ea_list, sd, smb_fname_str_dbg(smb_fname))); if (create_options & FILE_OPEN_BY_FILE_ID) { status = NT_STATUS_NOT_SUPPORTED; @@ -1668,15 +1711,6 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, oplock_request |= INTERNAL_OPEN_ONLY; } - if (psbuf != NULL) { - sbuf = *psbuf; - } - else { - if (SMB_VFS_STAT(conn, fname, &sbuf) == -1) { - SET_STAT_INVALID(sbuf); - } - } - if (lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE, PARM_IGNORE_SACLS, PARM_IGNORE_SACLS_DEFAULT)) { access_mask &= ~SYSTEM_SECURITY_ACCESS; @@ -1684,12 +1718,12 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, if ((conn->fs_capabilities & FILE_NAMED_STREAMS) && (access_mask & DELETE_ACCESS) - && !is_ntfs_stream_name(fname)) { + && !is_ntfs_stream_smb_fname(smb_fname)) { /* * We can't open a file with DELETE access if any of the * streams is open without FILE_SHARE_DELETE */ - status = open_streams_for_delete(conn, fname); + status = open_streams_for_delete(conn, smb_fname->base_name); if (!NT_STATUS_IS_OK(status)) { goto fail; @@ -1697,26 +1731,15 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, } if ((conn->fs_capabilities & FILE_NAMED_STREAMS) - && is_ntfs_stream_name(fname)) { - char *base; + && is_ntfs_stream_smb_fname(smb_fname)) { uint32 base_create_disposition; + struct smb_filename *smb_fname_base = NULL; if (create_options & FILE_DIRECTORY_FILE) { status = NT_STATUS_NOT_A_DIRECTORY; goto fail; } - status = onefs_split_ntfs_stream_name(talloc_tos(), fname, - &base, NULL); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("onefs_create_file_unixpath: " - "split_ntfs_stream_name failed: %s\n", - nt_errstr(status))); - goto fail; - } - - SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */ - switch (create_disposition) { case FILE_OPEN: base_create_disposition = FILE_OPEN; @@ -1726,10 +1749,24 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, break; } + /* Create an smb_filename with stream_name == NULL. */ + status = create_synthetic_smb_fname(talloc_tos(), + smb_fname->base_name, + NULL, NULL, + &smb_fname_base); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + if (SMB_VFS_STAT(conn, smb_fname_base) == -1) { + DEBUG(10, ("Unable to stat stream: %s\n", + smb_fname_str_dbg(smb_fname_base))); + } + status = onefs_create_file_unixpath( conn, /* conn */ NULL, /* req */ - base, /* fname */ + smb_fname_base, /* fname */ SYNCHRONIZE_ACCESS, /* access_mask */ (FILE_SHARE_READ | FILE_SHARE_WRITE | @@ -1743,12 +1780,14 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, NULL, /* ea_list */ &base_fsp, /* result */ NULL, /* pinfo */ - NULL, /* fsp_data */ - NULL); /* psbuf */ + NULL); /* fsp_data */ + + TALLOC_FREE(smb_fname_base); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("onefs_create_file_unixpath for base %s " - "failed: %s\n", base, nt_errstr(status))); + "failed: %s\n", smb_fname->base_name, + nt_errstr(status))); goto fail; } @@ -1762,7 +1801,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, DEBUG(5, ("Oplock(%d) being requested on a stream! " "Ignoring oplock request: fname=%s\n", oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK, - fname)); + smb_fname_str_dbg(smb_fname))); /* Request NO_OPLOCK instead. */ oplock_request &= SAMBA_PRIVATE_OPLOCK_MASK; } @@ -1801,7 +1840,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, status = onefs_open_directory( conn, /* conn */ req, /* req */ - fname, /* fname */ + smb_fname, /* fname */ access_mask, /* access_mask */ share_access, /* share_access */ create_disposition, /* create_disposition*/ @@ -1809,8 +1848,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, file_attributes, /* file_attributes */ sd, /* sd */ &fsp, /* result */ - &info, /* pinfo */ - &sbuf); /* psbuf */ + &info); /* pinfo */ } else { /* @@ -1833,7 +1871,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, status = onefs_open_file_ntcreate( conn, /* conn */ req, /* req */ - fname, /* fname */ + smb_fname, /* fname */ access_mask, /* access_mask */ share_access, /* share_access */ create_disposition, /* create_disposition*/ @@ -1843,8 +1881,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, sd, /* sd */ fsp, /* result */ &info, /* pinfo */ - fsp_data, /* fsp_data */ - &sbuf); /* psbuf */ + fsp_data); /* fsp_data */ if(!NT_STATUS_IS_OK(status)) { file_free(req, fsp); @@ -1875,7 +1912,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, status = onefs_open_directory( conn, /* conn */ req, /* req */ - fname, /* fname */ + smb_fname, /* fname */ access_mask, /* access_mask */ share_access, /* share_access */ create_disposition, /* create_disposition*/ @@ -1883,8 +1920,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, file_attributes, /* file_attributes */ sd, /* sd */ &fsp, /* result */ - &info, /* pinfo */ - &sbuf); /* psbuf */ + &info); /* pinfo */ } } @@ -1897,13 +1933,13 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, SMB_ASSERT(fsp); if ((ea_list != NULL) && (info == FILE_WAS_CREATED)) { - status = set_ea(conn, fsp, fname, ea_list); + status = set_ea(conn, fsp, smb_fname, ea_list); if (!NT_STATUS_IS_OK(status)) { goto fail; } } - if (!fsp->is_directory && S_ISDIR(sbuf.st_ex_mode)) { + if (!fsp->is_directory && S_ISDIR(smb_fname->st.st_ex_mode)) { status = NT_STATUS_ACCESS_DENIED; goto fail; } @@ -1911,7 +1947,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, /* Save the requested allocation size. */ if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { if (allocation_size - && (allocation_size > sbuf.st_ex_size)) { + && (allocation_size > smb_fname->st.st_ex_size)) { fsp->initial_allocation_size = smb_roundup( fsp->conn, allocation_size); if (fsp->is_directory) { @@ -1926,7 +1962,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, } } else { fsp->initial_allocation_size = smb_roundup( - fsp->conn, (uint64_t)sbuf.st_ex_size); + fsp->conn, (uint64_t)smb_fname->st.st_ex_size); } } @@ -1936,13 +1972,8 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, if (pinfo != NULL) { *pinfo = info; } - if (psbuf != NULL) { - if ((fsp->fh == NULL) || (fsp->fh->fd == -1)) { - *psbuf = sbuf; - } - else { - SMB_VFS_FSTAT(fsp, psbuf); - } + if ((fsp->fh != NULL) && (fsp->fh->fd != -1)) { + SMB_VFS_FSTAT(fsp, &smb_fname->st); } return NT_STATUS_OK; @@ -1997,7 +2028,6 @@ NTSTATUS onefs_create_file(vfs_handle_struct *handle, struct onefs_fsp_data fsp_data = {}; int info = FILE_WAS_OPENED; files_struct *fsp = NULL; - char *fname = NULL; NTSTATUS status; DEBUG(10,("onefs_create_file: access_mask = 0x%x " @@ -2024,11 +2054,6 @@ NTSTATUS onefs_create_file(vfs_handle_struct *handle, } } - status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - /* All file access must go through check_name() */ status = check_name(conn, smb_fname->base_name); if (!NT_STATUS_IS_OK(status)) { @@ -2038,7 +2063,7 @@ NTSTATUS onefs_create_file(vfs_handle_struct *handle, status = onefs_create_file_unixpath( conn, /* conn */ req, /* req */ - fname, /* fname */ + smb_fname, /* fname */ access_mask, /* access_mask */ share_access, /* share_access */ create_disposition, /* create_disposition*/ @@ -2050,8 +2075,7 @@ NTSTATUS onefs_create_file(vfs_handle_struct *handle, ea_list, /* ea_list */ &fsp, /* result */ &info, /* pinfo */ - &fsp_data, /* fsp_data */ - &smb_fname->st); /* psbuf */ + &fsp_data); /* psbuf */ if (!NT_STATUS_IS_OK(status)) { goto fail; diff --git a/source3/modules/onefs_streams.c b/source3/modules/onefs_streams.c index 284e199fc5..a4c6146fb0 100644 --- a/source3/modules/onefs_streams.c +++ b/source3/modules/onefs_streams.c @@ -54,6 +54,52 @@ NTSTATUS onefs_split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname, return NT_STATUS_OK; } +NTSTATUS onefs_stream_prep_smb_fname(TALLOC_CTX *ctx, + const struct smb_filename *smb_fname_in, + struct smb_filename **smb_fname_out) +{ + char *stream_name = NULL; + NTSTATUS status; + + /* + * Only attempt to strip off the trailing :$DATA if there is an actual + * stream there. If it is the default stream, the smb_fname_out will + * just have a NULL stream so the base file is opened. + */ + if (smb_fname_in->stream_name && + !is_ntfs_default_stream_smb_fname(smb_fname_in)) { + char *str_tmp = smb_fname_in->stream_name; + + /* First strip off the leading ':' */ + if (str_tmp[0] == ':') { + str_tmp++; + } + + /* Create a new copy of the stream_name. */ + stream_name = talloc_strdup(ctx, str_tmp); + if (stream_name == NULL) { + return NT_STATUS_NO_MEMORY; + } + + /* Strip off the :$DATA if one exists. */ + str_tmp = strrchr_m(stream_name, ':'); + if (str_tmp) { + str_tmp[0] = '\0'; + } + } + + /* + * If there was a stream that wasn't the default stream the leading + * colon and trailing :$DATA has now been stripped off. Create a new + * smb_filename to pass back. + */ + status = create_synthetic_smb_fname(ctx, smb_fname_in->base_name, + stream_name, &smb_fname_in->st, + smb_fname_out); + TALLOC_FREE(stream_name); + return status; +} + int onefs_is_stream(const char *path, char **pbase, char **pstream, bool *is_stream) { @@ -312,28 +358,37 @@ static int stat_stream(struct connection_struct *conn, const char *base, return ret; } -int onefs_stat(vfs_handle_struct *handle, const char *path, - SMB_STRUCT_STAT *sbuf) +int onefs_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname) { + struct smb_filename *smb_fname_onefs = NULL; + NTSTATUS status; int ret; - bool is_stream; - char *base = NULL; - char *stream = NULL; - ret = onefs_is_stream(path, &base, &stream, &is_stream); - if (ret) - return ret; + status = onefs_stream_prep_smb_fname(talloc_tos(), smb_fname, + &smb_fname_onefs); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } - if (!is_stream) { - ret = onefs_sys_stat(path, sbuf); - } else if (!stream) { - /* If it's the ::$DATA stream just stat the base file name. */ - ret = onefs_sys_stat(base, sbuf); + /* + * If the smb_fname has no stream or is :$DATA, then just stat the + * base stream. Otherwise stat the stream. + */ + if (!is_ntfs_stream_smb_fname(smb_fname_onefs)) { + ret = onefs_sys_stat(smb_fname_onefs->base_name, + &smb_fname->st); } else { - ret = stat_stream(handle->conn, base, stream, sbuf, 0); + ret = stat_stream(handle->conn, smb_fname_onefs->base_name, + smb_fname_onefs->stream_name, &smb_fname->st, + 0); } - onefs_adjust_stat_time(handle->conn, path, sbuf); + onefs_adjust_stat_time(handle->conn, smb_fname->base_name, + &smb_fname->st); + + TALLOC_FREE(smb_fname_onefs); + return ret; } @@ -361,29 +416,37 @@ int onefs_fstat(vfs_handle_struct *handle, struct files_struct *fsp, return ret; } -int onefs_lstat(vfs_handle_struct *handle, const char *path, - SMB_STRUCT_STAT *sbuf) +int onefs_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname) { + struct smb_filename *smb_fname_onefs = NULL; + NTSTATUS status; int ret; - bool is_stream; - char *base = NULL; - char *stream = NULL; - ret = onefs_is_stream(path, &base, &stream, &is_stream); - if (ret) - return ret; + status = onefs_stream_prep_smb_fname(talloc_tos(), smb_fname, + &smb_fname_onefs); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } - if (!is_stream) { - ret = onefs_sys_lstat(path, sbuf); - } else if (!stream) { - /* If it's the ::$DATA stream just stat the base file name. */ - ret = onefs_sys_lstat(base, sbuf); + /* + * If the smb_fname has no stream or is :$DATA, then just stat the + * base stream. Otherwise stat the stream. + */ + if (!is_ntfs_stream_smb_fname(smb_fname_onefs)) { + ret = onefs_sys_lstat(smb_fname_onefs->base_name, + &smb_fname->st); } else { - ret = stat_stream(handle->conn, base, stream, sbuf, + ret = stat_stream(handle->conn, smb_fname_onefs->base_name, + smb_fname_onefs->stream_name, &smb_fname->st, AT_SYMLINK_NOFOLLOW); } - onefs_adjust_stat_time(handle->conn, path, sbuf); + onefs_adjust_stat_time(handle->conn, smb_fname->base_name, + &smb_fname->st); + + TALLOC_FREE(smb_fname_onefs); + return ret; } @@ -661,10 +724,22 @@ NTSTATUS onefs_streaminfo(vfs_handle_struct *handle, } ret = SMB_VFS_FSTAT(fsp, &sbuf); } else { + struct smb_filename *smb_fname = NULL; + if (is_ntfs_stream_name(fname)) { return NT_STATUS_INVALID_PARAMETER; } - ret = SMB_VFS_STAT(handle->conn, fname, &sbuf); + + status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, + NULL, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + ret = SMB_VFS_STAT(handle->conn, smb_fname); + + sbuf = smb_fname->st; + + TALLOC_FREE(smb_fname); } if (ret == -1) { diff --git a/source3/modules/vfs_onefs_shadow_copy.c b/source3/modules/vfs_onefs_shadow_copy.c index 45860fa90d..3eca664c8a 100644 --- a/source3/modules/vfs_onefs_shadow_copy.c +++ b/source3/modules/vfs_onefs_shadow_copy.c @@ -278,21 +278,21 @@ onefs_shadow_copy_rename(vfs_handle_struct *handle, const char *old_name, } static int -onefs_shadow_copy_stat(vfs_handle_struct *handle, const char *path, - SMB_STRUCT_STAT *sbuf) +onefs_shadow_copy_stat(vfs_handle_struct *handle, + struct smb_filename *smb_fname) { - SHADOW_NEXT(STAT, - (handle, cpath ?: path, sbuf), - int); + SHADOW_NEXT_SMB_FNAME(STAT, + (handle, smb_fname), + int); } static int -onefs_shadow_copy_lstat(vfs_handle_struct *handle, const char *path, - SMB_STRUCT_STAT *sbuf) +onefs_shadow_copy_lstat(vfs_handle_struct *handle, + struct smb_filename *smb_fname) { - SHADOW_NEXT(LSTAT, - (handle, cpath ?: path, sbuf), - int); + SHADOW_NEXT_SMB_FNAME(LSTAT, + (handle, smb_fname), + int); } static int |