From: Volker Lendecke Date: Thu, 2 Oct 2025 19:56:59 +0000 (+0200) Subject: vfs_fruit: Call fruit_fstatat() from fruit_[l]stat() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8aaa73e5e90ce8ae82d6c88a1ac4d8b77df44d31;p=thirdparty%2Fsamba.git vfs_fruit: Call fruit_fstatat() from fruit_[l]stat() Signed-off-by: Volker Lendecke Reviewed-by: Ralph Boehme Autobuild-User(master): Volker Lendecke Autobuild-Date(master): Wed Oct 8 09:02:25 UTC 2025 on atb-devel-224 --- diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index b2460ab47d6..4ef7a68a30f 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -485,47 +485,6 @@ static bool ai_empty_finderinfo(const AfpInfo *ai) return all_zero(&ai->afpi_FinderInfo[0], ADEDLEN_FINDERI); } -/** - * Update btime with btime from Netatalk - **/ -static void update_btime(vfs_handle_struct *handle, - struct smb_filename *smb_fname) -{ - uint32_t t; - struct timespec creation_time = {0}; - struct adouble *ad; - struct fruit_config_data *config = NULL; - - SMB_VFS_HANDLE_GET_DATA(handle, config, struct fruit_config_data, - return); - - switch (config->meta) { - case FRUIT_META_STREAM: - return; - case FRUIT_META_NETATALK: - /* Handled below */ - break; - default: - DBG_ERR("Unexpected meta config [%d]\n", config->meta); - return; - } - - ad = ad_get_meta_fsp(talloc_tos(), handle, smb_fname); - if (ad == NULL) { - return; - } - if (ad_getdate(ad, AD_DATE_UNIX | AD_DATE_CREATE, &t) != 0) { - TALLOC_FREE(ad); - return; - } - TALLOC_FREE(ad); - - creation_time.tv_sec = convert_uint32_t_to_time_t(t); - update_stat_ex_create_time(&smb_fname->st, creation_time); - - return; -} - /** * Map an access mask to a Netatalk single byte byte range lock **/ @@ -3548,275 +3507,44 @@ static int fruit_stat_base(vfs_handle_struct *handle, return rc; } -static int fruit_stat_meta_stream(vfs_handle_struct *handle, - struct smb_filename *smb_fname, - bool follow_links) +static int fruit_stat(vfs_handle_struct *handle, + struct smb_filename *smb_fname) { + struct stat_ex st = {}; int ret; - ino_t ino; - ret = fruit_stat_base(handle, smb_fname, false); - if (ret != 0) { - return -1; - } - - ino = hash_inode(&smb_fname->st, smb_fname->stream_name); - - if (follow_links) { - ret = SMB_VFS_NEXT_STAT(handle, smb_fname); - } else { - ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname); - } - - smb_fname->st.st_ex_ino = ino; - - return ret; -} - -static int fruit_stat_meta_netatalk(vfs_handle_struct *handle, - struct smb_filename *smb_fname, - bool follow_links) -{ - struct adouble *ad = NULL; - - /* Populate the stat struct with info from the base file. */ - if (fruit_stat_base(handle, smb_fname, follow_links) == -1) { - return -1; - } + DBG_DEBUG("called for %s\n", smb_fname_str_dbg(smb_fname)); - ad = ad_get_meta_fsp(talloc_tos(), handle, smb_fname); - if (ad == NULL) { - DBG_INFO("fruit_stat_meta %s: %s\n", - smb_fname_str_dbg(smb_fname), strerror(errno)); - errno = ENOENT; + ret = fruit_fstatat(handle, handle->conn->cwd_fsp, smb_fname, &st, 0); + if (ret == -1) { return -1; } - TALLOC_FREE(ad); - smb_fname->st.st_ex_size = AFP_INFO_SIZE; - smb_fname->st.st_ex_ino = hash_inode(&smb_fname->st, - smb_fname->stream_name); + smb_fname->st = st; return 0; } -static int fruit_stat_meta(vfs_handle_struct *handle, - struct smb_filename *smb_fname, - bool follow_links) -{ - struct fruit_config_data *config = NULL; - int ret; - - SMB_VFS_HANDLE_GET_DATA(handle, config, - struct fruit_config_data, return -1); - - switch (config->meta) { - case FRUIT_META_STREAM: - ret = fruit_stat_meta_stream(handle, smb_fname, follow_links); - break; - - case FRUIT_META_NETATALK: - ret = fruit_stat_meta_netatalk(handle, smb_fname, follow_links); - break; - - default: - DBG_ERR("Unexpected meta config [%d]\n", config->meta); - return -1; - } - - return ret; -} - -static int fruit_stat_rsrc_netatalk(vfs_handle_struct *handle, - struct smb_filename *smb_fname, - bool follow_links) +static int fruit_lstat(vfs_handle_struct *handle, + struct smb_filename *smb_fname) { - struct adouble *ad = NULL; + struct stat_ex st = {}; int ret; - ad = ad_get(talloc_tos(), handle, smb_fname, ADOUBLE_RSRC); - if (ad == NULL) { - errno = ENOENT; - return -1; - } + DBG_DEBUG("called for %s\n", smb_fname_str_dbg(smb_fname)); - /* Populate the stat struct with info from the base file. */ - ret = fruit_stat_base(handle, smb_fname, follow_links); - if (ret != 0) { - TALLOC_FREE(ad); + ret = fruit_fstatat(handle, + handle->conn->cwd_fsp, + smb_fname, + &st, + AT_SYMLINK_NOFOLLOW); + if (ret == -1) { return -1; } - smb_fname->st.st_ex_size = ad_getentrylen(ad, ADEID_RFORK); - smb_fname->st.st_ex_ino = hash_inode(&smb_fname->st, - smb_fname->stream_name); - TALLOC_FREE(ad); + smb_fname->st = st; return 0; } -static int fruit_stat_rsrc_stream(vfs_handle_struct *handle, - struct smb_filename *smb_fname, - bool follow_links) -{ - int ret; - - if (follow_links) { - ret = SMB_VFS_NEXT_STAT(handle, smb_fname); - } else { - ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname); - } - - return ret; -} - -static int fruit_stat_rsrc_xattr(vfs_handle_struct *handle, - struct smb_filename *smb_fname, - bool follow_links) -{ -#ifdef HAVE_ATTROPEN - int ret; - int fd = -1; - - /* Populate the stat struct with info from the base file. */ - ret = fruit_stat_base(handle, smb_fname, follow_links); - if (ret != 0) { - return -1; - } - - fd = attropen(smb_fname->base_name, - AFPRESOURCE_EA_NETATALK, - O_RDONLY); - if (fd == -1) { - return 0; - } - - ret = sys_fstat(fd, &smb_fname->st, false); - if (ret != 0) { - close(fd); - DBG_ERR("fstat [%s:%s] failed\n", smb_fname->base_name, - AFPRESOURCE_EA_NETATALK); - return -1; - } - close(fd); - fd = -1; - - smb_fname->st.st_ex_ino = hash_inode(&smb_fname->st, - smb_fname->stream_name); - - return ret; - -#else - errno = ENOSYS; - return -1; -#endif -} - -static int fruit_stat_rsrc(vfs_handle_struct *handle, - struct smb_filename *smb_fname, - bool follow_links) -{ - struct fruit_config_data *config = NULL; - int ret; - - DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname)); - - SMB_VFS_HANDLE_GET_DATA(handle, config, - struct fruit_config_data, return -1); - - switch (config->rsrc) { - case FRUIT_RSRC_STREAM: - ret = fruit_stat_rsrc_stream(handle, smb_fname, follow_links); - break; - - case FRUIT_RSRC_XATTR: - ret = fruit_stat_rsrc_xattr(handle, smb_fname, follow_links); - break; - - case FRUIT_RSRC_ADFILE: - ret = fruit_stat_rsrc_netatalk(handle, smb_fname, follow_links); - break; - - default: - DBG_ERR("Unexpected rsrc config [%d]\n", config->rsrc); - return -1; - } - - return ret; -} - -static int fruit_stat(vfs_handle_struct *handle, - struct smb_filename *smb_fname) -{ - int rc = -1; - - DBG_DEBUG("called for %s\n", smb_fname_str_dbg(smb_fname)); - - if (!is_named_stream(smb_fname)) { - rc = SMB_VFS_NEXT_STAT(handle, smb_fname); - if (rc == 0) { - update_btime(handle, smb_fname); - } - return rc; - } - - /* - * Note if lp_posix_paths() is true, we can never - * get here as is_ntfs_stream_smb_fname() is - * always false. So we never need worry about - * not following links here. - */ - - if (is_afpinfo_stream(smb_fname->stream_name)) { - rc = fruit_stat_meta(handle, smb_fname, true); - } else if (is_afpresource_stream(smb_fname->stream_name)) { - rc = fruit_stat_rsrc(handle, smb_fname, true); - } else { - return SMB_VFS_NEXT_STAT(handle, smb_fname); - } - - if (rc == 0) { - update_btime(handle, smb_fname); - smb_fname->st.st_ex_mode &= ~S_IFMT; - smb_fname->st.st_ex_mode |= S_IFREG; - smb_fname->st.st_ex_blocks = - smb_fname->st.st_ex_size / STAT_ST_BLOCKSIZE + 1; - } - return rc; -} - -static int fruit_lstat(vfs_handle_struct *handle, - struct smb_filename *smb_fname) -{ - int rc = -1; - - DEBUG(10, ("fruit_lstat called for %s\n", - smb_fname_str_dbg(smb_fname))); - - if (!is_named_stream(smb_fname)) { - rc = SMB_VFS_NEXT_LSTAT(handle, smb_fname); - if (rc == 0) { - update_btime(handle, smb_fname); - } - return rc; - } - - if (is_afpinfo_stream(smb_fname->stream_name)) { - rc = fruit_stat_meta(handle, smb_fname, false); - } else if (is_afpresource_stream(smb_fname->stream_name)) { - rc = fruit_stat_rsrc(handle, smb_fname, false); - } else { - return SMB_VFS_NEXT_LSTAT(handle, smb_fname); - } - - if (rc == 0) { - update_btime(handle, smb_fname); - smb_fname->st.st_ex_mode &= ~S_IFMT; - smb_fname->st.st_ex_mode |= S_IFREG; - smb_fname->st.st_ex_blocks = - smb_fname->st.st_ex_size / STAT_ST_BLOCKSIZE + 1; - } - return rc; -} - static int fruit_fstat_meta_stream(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)