The Samba-Bugzilla – Attachment 7016 Details for
Bug 8398
Patch: Enhance VFS rename op to rename AppleDouble file
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
atalk_build_paths() rewrite and VFS rename op implementation
0001-Rewrite-atalk_build_paths-to-make-use-of-struct-smb_.patch (text/plain), 16.42 KB, created by
franklahm
on 2011-10-21 14:02:38 UTC
(
hide
)
Description:
atalk_build_paths() rewrite and VFS rename op implementation
Filename:
MIME Type:
Creator:
franklahm
Created:
2011-10-21 14:02:38 UTC
Size:
16.42 KB
patch
obsolete
>From 951329e07d92afacdebfb85bfc950c760a7bd524 Mon Sep 17 00:00:00 2001 >From: Frank Lahm <franklahm@googlemail.com> >Date: Fri, 21 Oct 2011 15:57:32 +0200 >Subject: [PATCH] Rewrite atalk_build_paths() to make use of struct smb_filename instead of plain char *. > Rewrite all callers of atalk_build_paths() to accomodate this. > Also fixed: > Implement rename() VFS function. > Instead of using individual TALLOC contexts, use talloc_tos() context. > atalk_lchown() called SMB_VFS_NEXT_CHOWN instead of SMB_VFS_NEXT_LCHOWN. > Avoid excessive gotos. > >--- > source3/modules/vfs_netatalk.c | 411 ++++++++++++++++++++++----------------- > 1 files changed, 232 insertions(+), 179 deletions(-) > >diff --git a/source3/modules/vfs_netatalk.c b/source3/modules/vfs_netatalk.c >index 8d2c9b7..1a0a1d0 100644 >--- a/source3/modules/vfs_netatalk.c >+++ b/source3/modules/vfs_netatalk.c >@@ -22,89 +22,126 @@ > #include "smbd/smbd.h" > #include "system/filesys.h" > >+#include <libgen.h> >+ > #undef DBGC_CLASS > #define DBGC_CLASS DBGC_VFS > > #define APPLEDOUBLE ".AppleDouble" >+#define ADOUBLEPARENT ".Parent" > #define ADOUBLEMODE 0777 > >-/* atalk functions */ >- >-static int atalk_build_paths(TALLOC_CTX *ctx, const char *path, >- const char *fname, >- char **adbl_path, char **orig_path, >- SMB_STRUCT_STAT *adbl_info, >- SMB_STRUCT_STAT *orig_info, >- bool fake_dir_create_times); >+/* atalk_build_paths() flags */ >+#define ADOUBLE_PATH_STAT (1 << 0) >+#define ADOUBLE_PATH_FILE (1 << 1) >+#define ADOUBLE_PATH_DIR (1 << 2) >+#define ADOUBLE_PATH_DIR_FOR_FILE (1 << 3) >+#define ADOUBLE_PATH_PARENT (1 << 4) > >-static int atalk_unlink_file(const char *path); > >-static int atalk_get_path_ptr(char *path) >+/** >+ * Construct path to AppleDouble file or directory >+ * >+ * The path to the AppleDouble object is constructed according to the >+ * parameter "adflags". Example given "example/path": >+ * >+ * ADOUBLE_PATH_STAT: >+ * stat() the object in order to determine whether it is a file or directory, >+ * then build path accordingly: >+ * file: example/.AppleDouble/path >+ * directory: example/path/.AppleDouble/ >+ * >+ * ADOUBLE_PATH_STAT | ADOUBLE_PATH_PARENT: >+ * stat() the object in order to determine whether it is a file or directory, >+ * then build path accordingly: >+ * file: example/.AppleDouble/path >+ * directory: example/path/.AppleDouble/.Parent >+ * >+ * ADOUBLE_DIR_FOR_FILE: >+ * Assume object is a file, build path to AppleDouble directory which contains >+ * it's AppleDouble file: >+ * example/.AppleDouble/ >+ * >+ * ADOUBLE_PATH_FILE: >+ * Assume object is a file, build path for a file: >+ * example/.AppleDouble/path >+ * >+ * ADOUBLE_PATH_DIR: >+ * Assume object is a directory, uild AppleDouble directory path for a directory: >+ * example/path/.AppleDouble/ >+ * >+ * ADOUBLE_PATH_DIR | ADOUBLE_PATH_PARENT: >+ * Build path to AppleDouble file of the directory itself: >+ * example/path/.AppleDouble/.Parent >+ * >+ * @param handle (r) VFS handle >+ * @param ctx (rw) TALLOC_CTX >+ * @param path (r) pathname to filesystem object >+ * @param adflags (r) Conversion flags, see above >+ * >+ * @return AppleDouble path on sucess, NULL on error >+ **/ >+static struct smb_filename * >+atalk_build_paths(const struct vfs_handle_struct *handle, >+ TALLOC_CTX *ctx, >+ const struct smb_filename *path, >+ unsigned int adflags) > { >- int i = 0; >- int ptr = 0; >- >- for (i = 0; path[i]; i ++) { >- if (path[i] == '/') >- ptr = i; >- /* get out some 'spam';) from win32's file name */ >- else if (path[i] == ':') { >- path[i] = '\0'; >- break; >- } >- } >- >- return ptr; >-} >+ NTSTATUS status; >+ struct smb_filename *adpath = NULL; >+ char *dname; >+ char *bname; >+ SMB_STRUCT_STAT *st; > >-static int atalk_build_paths(TALLOC_CTX *ctx, const char *path, >- const char *fname, >- char **adbl_path, char **orig_path, >- SMB_STRUCT_STAT *adbl_info, >- SMB_STRUCT_STAT *orig_info, >- bool fake_dir_create_times) >-{ >- int ptr0 = 0; >- int ptr1 = 0; >- char *dname = 0; >- char *name = 0; >- >- if (!ctx || !path || !fname || !adbl_path || !orig_path || >- !adbl_info || !orig_info) >- return -1; >-#if 0 >- DEBUG(3, ("ATALK: PATH: %s[%s]\n", path, fname)); >-#endif >- if (strstr(path, APPLEDOUBLE) || strstr(fname, APPLEDOUBLE)) { >- DEBUG(3, ("ATALK: path %s[%s] already contains %s\n", path, fname, APPLEDOUBLE)); >- return -1; >- } >+ if (!handle || !ctx || !path) >+ return NULL; > >- if (fname[0] == '.') ptr0 ++; >- if (fname[1] == '/') ptr0 ++; >+ if ((st = talloc_zero(ctx, SMB_STRUCT_STAT)) == NULL) >+ return NULL; > >- *orig_path = talloc_asprintf(ctx, "%s/%s", path, &fname[ptr0]); >+ if (!NT_STATUS_IS_OK(status = create_synthetic_smb_fname(ctx, NULL, NULL, st, &adpath))) >+ return NULL; > >- /* get pointer to last '/' */ >- ptr1 = atalk_get_path_ptr(*orig_path); >+ if ((dname = dirname(talloc_strdup(ctx, path->base_name))) == NULL) >+ return NULL; >+ if (dname[0] == '.' && dname[1] == 0) >+ dname = NULL; > >- sys_lstat(*orig_path, orig_info, fake_dir_create_times); >+ if ((bname = basename(talloc_strdup(ctx, path->base_name))) == NULL) >+ return NULL; > >- if (S_ISDIR(orig_info->st_ex_mode)) { >- *adbl_path = talloc_asprintf(ctx, "%s/%s/%s/", >- path, &fname[ptr0], APPLEDOUBLE); >- } else { >- dname = talloc_strdup(ctx, *orig_path); >- dname[ptr1] = '\0'; >- name = *orig_path; >- *adbl_path = talloc_asprintf(ctx, "%s/%s/%s", >- dname, APPLEDOUBLE, &name[ptr1 + 1]); >+ if ((adflags & ADOUBLE_PATH_STAT) && (!VALID_STAT(path->st))) { >+ DEBUG(0, ("invalid stat: %s\n", path->base_name)); >+ return NULL; > } >-#if 0 >- DEBUG(3, ("ATALK: DEBUG:\n%s\n%s\n", *orig_path, *adbl_path)); >-#endif >- sys_lstat(*adbl_path, adbl_info, fake_dir_create_times); >- return 0; >+ >+ if (((adflags & ADOUBLE_PATH_STAT) && S_ISDIR(path->st.st_ex_mode)) >+ || (adflags & ADOUBLE_PATH_DIR)) { >+ if (adflags & ADOUBLE_PATH_PARENT) { >+ adpath->base_name = talloc_asprintf(ctx, "%s%s%s/%s/%s", >+ dname ? dname : "", dname ? "/" : "", >+ bname, APPLEDOUBLE, ADOUBLEPARENT); >+ } else { >+ adpath->base_name = talloc_asprintf(ctx, "%s%s%s/%s/", >+ dname ? dname : "", dname ? "/" : "", >+ bname, >+ APPLEDOUBLE); >+ } >+ } else if ((adflags & ADOUBLE_PATH_STAT) || (adflags & ADOUBLE_PATH_FILE)) { >+ adpath->base_name = talloc_asprintf(ctx, "%s%s%s/%s", >+ dname ? dname : "", dname ? "/" : "", >+ APPLEDOUBLE, bname); >+ } else if (adflags & ADOUBLE_PATH_DIR_FOR_FILE) { >+ adpath->base_name = talloc_asprintf(ctx, "%s%s%s/", >+ dname ? dname : "", dname ? "/" : "", >+ APPLEDOUBLE); >+ } >+ >+ (void)SMB_VFS_STAT(handle->conn, adpath); >+ >+ DEBUG(3, ("in: \"%s\"\nout: \"%s\"\n", path->base_name, adpath->base_name)); >+ >+ return adpath; > } > > static int atalk_unlink_file(const char *path) >@@ -228,7 +265,6 @@ static SMB_STRUCT_DIR *atalk_fdopendir(struct vfs_handle_struct *handle, files_s > static int atalk_rmdir(struct vfs_handle_struct *handle, const char *path) > { > bool add = False; >- TALLOC_CTX *ctx = 0; > char *dpath; > > if (!handle->conn->origpath || !path) goto exit_rmdir; >@@ -239,17 +275,13 @@ static int atalk_rmdir(struct vfs_handle_struct *handle, const char *path) > > strstr(path, APPLEDOUBLE) ? (add = False) : (add = True); > >- if (!(ctx = talloc_init("remove_directory"))) >- goto exit_rmdir; >- >- if (!(dpath = talloc_asprintf(ctx, "%s/%s%s", >+ if (!(dpath = talloc_asprintf(talloc_tos(), "%s/%s%s", > handle->conn->origpath, path, add ? "/"APPLEDOUBLE : ""))) > goto exit_rmdir; > >- atalk_rrmdir(ctx, dpath); >+ atalk_rrmdir(talloc_tos(), dpath); > > exit_rmdir: >- talloc_destroy(ctx); > return SMB_VFS_NEXT_RMDIR(handle, path); > } > >@@ -260,36 +292,73 @@ static int atalk_rename(struct vfs_handle_struct *handle, > const struct smb_filename *smb_fname_dst) > { > int ret = 0; >- char *oldname = NULL; >- char *adbl_path = NULL; >- char *orig_path = NULL; >- SMB_STRUCT_STAT adbl_info; >- SMB_STRUCT_STAT orig_info; >- NTSTATUS status; >+ >+ /* src */ >+ struct smb_filename *src_adpath; >+ >+ /* dst */ >+ struct smb_filename *dst_adpath; >+ struct smb_filename *dst_addirpath; > > ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst); > >- status = get_full_smb_filename(talloc_tos(), smb_fname_src, &oldname); >- if (!NT_STATUS_IS_OK(status)) { >- return ret; >+ if (is_ntfs_stream_smb_fname(smb_fname_src) >+ || is_ntfs_stream_smb_fname(smb_fname_dst)) { >+ DEBUG(3, ("stream detected, ignoring\n")); >+ return 0; > } > >- if (atalk_build_paths(talloc_tos(), handle->conn->origpath, oldname, >- &adbl_path, &orig_path, &adbl_info, >- &orig_info, false) != 0) >- goto exit_rename; >+ DEBUG(3, ("src: \"%s/%s\"\ndst: \"%s\"\n", >+ handle->conn->origpath, smb_fname_src->base_name, >+ smb_fname_dst->base_name)); > >- if (S_ISDIR(orig_info.st_ex_mode) || S_ISREG(orig_info.st_ex_mode)) { >- DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); >- goto exit_rename; >- } >+ if (strstr_m(smb_fname_src->base_name, APPLEDOUBLE) >+ || strstr_m(smb_fname_dst->base_name, APPLEDOUBLE)) >+ return ret; >+ >+ if ((src_adpath = atalk_build_paths(handle, >+ talloc_tos(), >+ smb_fname_src, >+ ADOUBLE_PATH_STAT)) == NULL) >+ return ret; > >- atalk_unlink_file(adbl_path); >+ if ((ret == 0) && S_ISREG(smb_fname_src->st.st_ex_mode)) { >+ /* Only rename AppleDouble files of files */ >+ if (!VALID_STAT(src_adpath->st)) { >+ DEBUG(1, ("can't stat: \"%s\"\n", src_adpath->base_name)); >+ return ret; >+ } > >-exit_rename: >- TALLOC_FREE(oldname); >- TALLOC_FREE(adbl_path); >- TALLOC_FREE(orig_path); >+ /* build path for destination adouble file */ >+ if ((dst_adpath = atalk_build_paths(handle, >+ talloc_tos(), >+ smb_fname_dst, >+ ADOUBLE_PATH_FILE)) == NULL) >+ return ret; >+ >+ /* Check .AppleDouble directory exists, create if necessary */ >+ if ((dst_addirpath = atalk_build_paths(handle, >+ talloc_tos(), >+ smb_fname_dst, >+ ADOUBLE_PATH_DIR_FOR_FILE) >+ ) == NULL) >+ return ret; >+ >+ if (!VALID_STAT(dst_addirpath->st) && (errno == ENOENT)) { >+ DEBUG(3, ("creating adouble dir: \"%s\"\n", >+ dst_addirpath->base_name)); >+ if ((ret = SMB_VFS_MKDIR(handle->conn, dst_addirpath->base_name, 02777)) != 0) >+ goto exit; >+ >+ } >+ >+ DEBUG(3, ("src: \"%s\"\ndst: \"%s\"\n", >+ src_adpath->base_name, dst_adpath->base_name)); >+ >+ ret = rename(src_adpath->base_name, dst_adpath->base_name); >+ } >+ >+exit: > return ret; > } > >@@ -297,19 +366,12 @@ static int atalk_unlink(struct vfs_handle_struct *handle, > const struct smb_filename *smb_fname) > { > int ret = 0, i; >- char *path = NULL; >- char *adbl_path = NULL; >- char *orig_path = NULL; >- SMB_STRUCT_STAT adbl_info; >- SMB_STRUCT_STAT orig_info; >- NTSTATUS status; >+ struct smb_filename *adpath; > > ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname); > >- status = get_full_smb_filename(talloc_tos(), smb_fname, &path); >- if (!NT_STATUS_IS_OK(status)) { >+ if (!smb_fname || strstr_m(smb_fname->base_name, APPLEDOUBLE)) > return ret; >- } > > /* no .AppleDouble sync if veto or hide list is empty, > * otherwise "Cannot find the specified file" error will be caused >@@ -330,130 +392,121 @@ static int atalk_unlink(struct vfs_handle_struct *handle, > else { > DEBUG(3, ("ATALK: %s is not hidden, skipped..\n", > APPLEDOUBLE)); >- goto exit_unlink; >+ return ret; > } > } > } > >- if (atalk_build_paths(talloc_tos(), handle->conn->origpath, path, >- &adbl_path, &orig_path, >- &adbl_info, &orig_info, false) != 0) >- goto exit_unlink; >- >- if (S_ISDIR(orig_info.st_ex_mode) || S_ISREG(orig_info.st_ex_mode)) { >- DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); >- goto exit_unlink; >- } >+ if ((adpath = atalk_build_paths(handle, talloc_tos(), smb_fname, >+ ADOUBLE_PATH_STAT)) == NULL) >+ return ret; >+ if (!VALID_STAT(adpath->st)) >+ return ret; > >- atalk_unlink_file(adbl_path); >+ (void)atalk_unlink_file(adpath->base_name); > >-exit_unlink: >- TALLOC_FREE(path); >- TALLOC_FREE(adbl_path); >- TALLOC_FREE(orig_path); > return ret; > } > > static int atalk_chmod(struct vfs_handle_struct *handle, const char *path, mode_t mode) > { >- int ret = 0; >- char *adbl_path = 0; >- char *orig_path = 0; >- SMB_STRUCT_STAT adbl_info; >- SMB_STRUCT_STAT orig_info; >- TALLOC_CTX *ctx; >+ NTSTATUS status; >+ int ret; >+ struct smb_filename *srcpath; >+ struct smb_filename *adpath; >+ SMB_STRUCT_STAT st; > > ret = SMB_VFS_NEXT_CHMOD(handle, path, mode); > >- if (!path) return ret; >+ if (!path || strstr_m(path, APPLEDOUBLE)) >+ return ret; >+ >+ if (!NT_STATUS_IS_OK(status = create_synthetic_smb_fname(handle, talloc_tos(), >+ NULL, &st, &srcpath))) >+ return ret; > >- if (!(ctx = talloc_init("chmod_file"))) >+ if ((adpath = atalk_build_paths(handle, talloc_tos(), srcpath, ADOUBLE_PATH_STAT)) == NULL) > return ret; > >- if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, >- &orig_path, &adbl_info, &orig_info, >- false) != 0) >- goto exit_chmod; >+ if (!VALID_STAT(adpath->st)) >+ return ret; > >- if (!S_ISDIR(orig_info.st_ex_mode) && !S_ISREG(orig_info.st_ex_mode)) { >- DEBUG(3, ("ATALK: %s has passed..\n", orig_path)); >- goto exit_chmod; >+ if (!S_ISDIR(adpath->st.st_ex_mode) && !S_ISREG(adpath->st.st_ex_mode)) { >+ DEBUG(3, ("ATALK: %s has passed..\n", adpath->base_name)); >+ return ret; > } > >- chmod(adbl_path, ADOUBLEMODE); >+ if (chmod(adpath->base_name, ADOUBLEMODE) != 0) >+ DEBUG(3, ("chmod(\"%s\"): %s\n", adpath->base_name, strerror(errno))); > >-exit_chmod: >- talloc_destroy(ctx); > return ret; > } > > static int atalk_chown(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid) > { >- int ret = 0; >- char *adbl_path = 0; >- char *orig_path = 0; >- SMB_STRUCT_STAT adbl_info; >- SMB_STRUCT_STAT orig_info; >- TALLOC_CTX *ctx; >+ NTSTATUS status; >+ int ret; >+ struct smb_filename *srcpath; >+ struct smb_filename *adpath; >+ SMB_STRUCT_STAT st; > > ret = SMB_VFS_NEXT_CHOWN(handle, path, uid, gid); > >- if (!path) return ret; >+ if (!path || strstr_m(path, APPLEDOUBLE)) >+ return ret; > >- if (!(ctx = talloc_init("chown_file"))) >+ if (!NT_STATUS_IS_OK(status = create_synthetic_smb_fname(handle, talloc_tos(), >+ NULL, &st, &srcpath))) > return ret; > >- if (atalk_build_paths(ctx, handle->conn->origpath, path, >- &adbl_path, &orig_path, >- &adbl_info, &orig_info, false) != 0) >- goto exit_chown; >+ if ((adpath = atalk_build_paths(handle, talloc_tos(), srcpath, ADOUBLE_PATH_STAT)) == NULL) >+ return ret; > >- if (!S_ISDIR(orig_info.st_ex_mode) && !S_ISREG(orig_info.st_ex_mode)) { >- DEBUG(3, ("ATALK: %s has passed..\n", orig_path)); >- goto exit_chown; >- } >+ if (!VALID_STAT(adpath->st)) >+ return ret; > >- if (chown(adbl_path, uid, gid) == -1) { >- DEBUG(3, ("ATALK: chown error %s\n", strerror(errno))); >+ if (!S_ISDIR(adpath->st.st_ex_mode) && !S_ISREG(adpath->st.st_ex_mode)) { >+ DEBUG(3, ("ATALK: %s has passed..\n", path)); >+ return ret; > } > >-exit_chown: >- talloc_destroy(ctx); >+ if (chown(adpath->base_name, uid, gid) == -1) >+ DEBUG(3, ("chown(\"%s\"): %s\n", adpath->base_name, strerror(errno))); >+ > return ret; > } > > static int atalk_lchown(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid) > { >- int ret = 0; >- char *adbl_path = 0; >- char *orig_path = 0; >- SMB_STRUCT_STAT adbl_info; >- SMB_STRUCT_STAT orig_info; >- TALLOC_CTX *ctx; >+ NTSTATUS status; >+ int ret; >+ struct smb_filename *srcpath; >+ struct smb_filename *adpath; >+ SMB_STRUCT_STAT st; > >- ret = SMB_VFS_NEXT_CHOWN(handle, path, uid, gid); >+ ret = SMB_VFS_NEXT_LCHOWN(handle, path, uid, gid); > >- if (!path) return ret; >+ if (!path || strstr_m(path, APPLEDOUBLE)) >+ return ret; > >- if (!(ctx = talloc_init("lchown_file"))) >+ if (!NT_STATUS_IS_OK(status = create_synthetic_smb_fname(handle, talloc_tos(), >+ NULL, &st, &srcpath))) > return ret; > >- if (atalk_build_paths(ctx, handle->conn->origpath, path, >- &adbl_path, &orig_path, >- &adbl_info, &orig_info, false) != 0) >- goto exit_lchown; >+ if ((adpath = atalk_build_paths(handle, talloc_tos(), srcpath, ADOUBLE_PATH_STAT)) == NULL) >+ return ret; > >- if (!S_ISDIR(orig_info.st_ex_mode) && !S_ISREG(orig_info.st_ex_mode)) { >- DEBUG(3, ("ATALK: %s has passed..\n", orig_path)); >- goto exit_lchown; >- } >+ if (!VALID_STAT(adpath->st)) >+ return ret; > >- if (lchown(adbl_path, uid, gid) == -1) { >- DEBUG(3, ("ATALK: lchown error %s\n", strerror(errno))); >+ if (!S_ISDIR(adpath->st.st_ex_mode) && !S_ISREG(adpath->st.st_ex_mode)) { >+ DEBUG(3, ("ATALK: %s has passed..\n", path)); >+ return ret; > } > >-exit_lchown: >- talloc_destroy(ctx); >+ if (lchown(adpath->base_name, uid, gid) != 0) >+ DEBUG(3, ("lchown(\"%s\"): %s\n", adpath->base_name, strerror(errno))); >+ > return ret; > } > >-- >1.7.0.5 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
franklahm:
review?
(
jra
)
Actions:
View
Attachments on
bug 8398
:
6802
|
6928
| 7016