The Samba-Bugzilla – Attachment 7520 Details for
Bug 8841
Add MediaHarmony module
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Add media_harmony VFS module to git-latest Samba
0001-media_harmony-VFS-module-Add-and-build-by-default.patch (text/plain), 57.46 KB, created by
clawsoon
on 2012-05-03 17:56:27 UTC
(
hide
)
Description:
Add media_harmony VFS module to git-latest Samba
Filename:
MIME Type:
Creator:
clawsoon
Created:
2012-05-03 17:56:27 UTC
Size:
57.46 KB
patch
obsolete
>From 72cf3ad65ac001b558a971838df0456e8eb8e928 Mon Sep 17 00:00:00 2001 >From: Andrew Klaassen <clawsoon@yahoo.com> >Date: Thu, 3 May 2012 13:39:53 -0400 >Subject: [PATCH] media_harmony VFS module: Add and build by default. > > - Supersedes previous patch. > - Adds various fixes for fake mtime functionality. > - Requires lp_cache_locked_write_times patch (bug 8912). > - Removed various xattr functions to comply with recent VFS changes. > - Changed SMB_STRUCT_DIR to DIR and SMB_STRUCT_DIRENT to struct dirent to comply with recent VFS changes. >--- > source3/Makefile.in | 5 + > source3/configure.in | 2 + > source3/modules/vfs_media_harmony.c | 2440 +++++++++++++++++++++++++++++++++++ > source3/wscript | 2 +- > 4 files changed, 2448 insertions(+), 1 deletions(-) > create mode 100644 source3/modules/vfs_media_harmony.c > >diff --git a/source3/Makefile.in b/source3/Makefile.in >index 8b02d64..b330ac4 100644 >--- a/source3/Makefile.in >+++ b/source3/Makefile.in >@@ -893,6 +893,7 @@ VFS_SCANNEDONLY_OBJ = modules/vfs_scannedonly.o > VFS_CROSSRENAME_OBJ = modules/vfs_crossrename.o > VFS_LINUX_XFS_SGID_OBJ = modules/vfs_linux_xfs_sgid.o > VFS_TIME_AUDIT_OBJ = modules/vfs_time_audit.o >+VFS_MEDIA_HARMONY_OBJ = modules/vfs_media_harmony.o > > PAM_ERRORS_OBJ = ../libcli/auth/pam_errors.o > PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o $(PAM_ERRORS_OBJ) >@@ -3150,6 +3151,10 @@ bin/time_audit.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_TIME_AUDIT_OBJ) > @echo "Building plugin $@" > @$(SHLD_MODULE) $(VFS_TIME_AUDIT_OBJ) > >+bin/media_harmony.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_MEDIA_HARMONY_OBJ) >+ @echo "Building plugin $@" >+ @$(SHLD_MODULE) $(VFS_MEDIA_HARMONY_OBJ) >+ > ######################################################### > ## IdMap NSS plugins > >diff --git a/source3/configure.in b/source3/configure.in >index 0253e07..17d6ba3 100644 >--- a/source3/configure.in >+++ b/source3/configure.in >@@ -467,6 +467,7 @@ default_shared_modules="$default_shared_modules vfs_scannedonly" > default_shared_modules="$default_shared_modules vfs_crossrename" > default_shared_modules="$default_shared_modules vfs_linux_xfs_sgid" > default_shared_modules="$default_shared_modules vfs_time_audit" >+default_shared_modules="$default_shared_modules vfs_media_harmony" > default_shared_modules="$default_shared_modules idmap_autorid" > > if test "x$developer" = xyes; then >@@ -6547,6 +6548,7 @@ SMB_MODULE(vfs_scannedonly, \$(VFS_SCANNEDONLY_OBJ), "bin/scannedonly.$SHLIBEXT" > SMB_MODULE(vfs_crossrename, \$(VFS_CROSSRENAME_OBJ), "bin/crossrename.$SHLIBEXT", VFS) > SMB_MODULE(vfs_linux_xfs_sgid, \$(VFS_LINUX_XFS_SGID_OBJ), "bin/linux_xfs_sgid.$SHLIBEXT", VFS) > SMB_MODULE(vfs_time_audit, \$(VFS_TIME_AUDIT_OBJ), "bin/time_audit.$SHLIBEXT", VFS) >+SMB_MODULE(vfs_media_harmony, \$(VFS_MEDIA_HARMONY_OBJ), "bin/media_harmony.$SHLIBEXT", VFS) > > SMB_SUBSYSTEM(VFS,smbd/vfs.o) > >diff --git a/source3/modules/vfs_media_harmony.c b/source3/modules/vfs_media_harmony.c >new file mode 100644 >index 0000000..8bfb116 >--- /dev/null >+++ b/source3/modules/vfs_media_harmony.c >@@ -0,0 +1,2440 @@ >+/* >+ * $Id: media_harmony.c,v 1.1 2007/11/06 10:07:22 stuart_hc Exp $ >+ * >+ * Samba VFS module supporting multiple AVID clients sharing media. >+ * >+ * Copyright (C) 2005 Philip de Nier <philipn@users.sourceforge.net> >+ * Copyright (C) 2012 Andrew Klaassen <clawsoon@yahoo.com> >+ * >+ * This program is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU General Public License >+ * as published by the Free Software Foundation; either version 2 >+ * of the License, or (at your option) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program; if not, write to the Free Software >+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA >+ * 02110-1301, USA. >+ */ >+ >+ >+/* >+ * Media Harmony is a Samba VFS module that allows multiple AVID >+ * clients to share media. Each client sees their own copy of the >+ * AVID msmMMOB.mdb and msmFMID.pmr files and Creating directories. >+ * >+ * Add this module to the vfs objects option in your Samba share >+ * configuration. >+ * eg. >+ * >+ * [avid_win] >+ * path = /video >+ * vfs objects = media_harmony >+ * ... >+ * >+ * It is recommended that you separate out Samba shares for Mac >+ * and Windows clients, and add the following options to the shares >+ * for Windows clients (NOTE: replace @ with *): >+ * >+ * veto files = /.DS_Store/._@/.Trash@/.Spotlight@/.hidden/.hotfiles@/.vol/ >+ * delete veto files = yes >+ * >+ * This prevents hidden files from Mac clients interfering with Windows >+ * clients. If you find any more problem hidden files then add them to >+ * the list. >+ * >+ * >+ * Andrew Klaassen, 2012-03-14 >+ * To prevent Avid clients from interrupting each other (via Avid's habit >+ * of launching a database refresh whenever it notices an mtime update >+ * on media directories, i.e. whenever one editor adds new material to a >+ * shared share), I've added code that causes stat information for anything >+ * directly under "Avid MediaFile/MXF" to be taken from >+ * dirname_clientaddr_clientuser if it exists. These files ~aren't~ >+ * hidden, unlike the client-suffixed database files. >+ * >+ * For example, stat information for >+ * Avid MediaFiles/MXF/1 >+ * will come from >+ * Avid MediaFiles/MXF/1_192.168.1.10_dave >+ * for dave working on 192.168.1.10, but will come from >+ * Avid MediaFile/MXF/1_192.168.1.11_susan >+ * for susan working on 192.168.1.11. If those alternate >+ * directories don't exist, the user will get the actual directory's stat >+ * info. When an editor wants to force a database refresh, they update >+ * the mtime on "their" file. This will cause Avid >+ * on that client to see an updated mtime for "Avid MediaFiles/MXF/1", >+ * which will trigger an Avid database refresh just for that editor. >+ * >+ * >+ * Notes: >+ * - This module is designed to work with AVID editing applications that >+ * look in the Avid MediaFiles or OMFI MediaFiles directory for media. >+ * It is not designed to work as expected in all circumstances for >+ * general use. For example: it is possibly to open client specific >+ * files such as msmMMOB.mdb_192.168.1.10_userx even though is doesn't >+ * show up in a directory listing. >+ * >+ */ >+ >+ >+#include "includes.h" >+#include "system/filesys.h" >+#include "smbd/smbd.h" >+#include "../smbd/globals.h" >+#include "auth.h" >+#include "../lib/tsocket/tsocket.h" >+ >+#define MH_INFO_DEBUG 10 >+#define MH_ERR_DEBUG 0 >+ >+static const char* MH_MODULE_NAME = "media_harmony"; >+static const char* MDB_FILENAME = "msmMMOB.mdb"; >+static const size_t MDB_FILENAME_LEN = 11; >+static const char* PMR_FILENAME = "msmFMID.pmr"; >+static const size_t PMR_FILENAME_LEN = 11; >+static const char* CREATING_DIRNAME = "Creating"; >+static const size_t CREATING_DIRNAME_LEN = 8; >+static const char* AVID_MEDIAFILES_DIRNAME = "Avid MediaFiles"; >+static const size_t AVID_MEDIAFILES_DIRNAME_LEN = 15; >+static const char* OMFI_MEDIAFILES_DIRNAME = "OMFI MediaFiles"; >+static const size_t OMFI_MEDIAFILES_DIRNAME_LEN = 15; >+static const char* APPLE_DOUBLE_PREFIX = "._"; >+static const size_t APPLE_DOUBLE_PREFIX_LEN = 2; >+static const char* AVID_MXF_DIRNAME = "Avid MediaFiles/MXF"; >+static const size_t AVID_MXF_DIRNAME_LEN = 19; >+ >+static int vfs_mh_debug_level = DBGC_VFS; >+ >+/* supplements the directory list stream */ >+typedef struct mh_dirinfo_struct >+{ >+ DIR* dirstream; >+ char *dirpath; >+ char *clientPath; >+ bool isInMediaFiles; >+ char *clientMDBFilename; >+ char *clientPMRFilename; >+ char *clientCreatingDirname; >+} mh_dirinfo_struct; >+ >+ >+/* Add "_<ip address>_<user name>" suffix to path or filename. >+ * >+ * Success: return 0 >+ * Failure: set errno, path NULL, return -1 >+ */ >+static int alloc_append_client_suffix(vfs_handle_struct *handle, >+ char **path) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with *path '%s'\n", *path)); >+ >+ int status = 0; >+ char *raddr = NULL; >+ >+ raddr = tsocket_address_inet_addr_string( >+ handle->conn->sconn->remote_address, talloc_tos()); >+ if (raddr == NULL) >+ { >+ errno = ENOMEM; >+ status = -1; >+ goto err; >+ } >+ >+ /* talloc_asprintf_append uses talloc_realloc, which >+ * frees original 'path' memory so we don't have to. >+ */ >+ *path = talloc_asprintf_append(*path, "_%s_%s", >+ raddr, >+ handle->conn->session_info->unix_info->sanitized_username); >+ if (*path == NULL) >+ { >+ DEBUG(MH_ERR_DEBUG, ("alloc_append_client_suffix " >+ "out of memory\n")); >+ errno = ENOMEM; >+ status = -1; >+ goto err; >+ } >+ DEBUG(MH_INFO_DEBUG, ("Leaving with *path '%s'\n", *path)); >+err: >+ TALLOC_FREE(raddr); >+ return status; >+} >+ >+ >+/* Returns True if the file or directory begins with the appledouble >+ * prefix. >+ */ >+static bool is_apple_double(const char* fname) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with fname '%s'\n", fname)); >+ >+ bool ret = False; >+ >+ if (strncmp(APPLE_DOUBLE_PREFIX, fname, APPLE_DOUBLE_PREFIX_LEN) >+ == 0) >+ { >+ ret = True; >+ } >+ DEBUG(MH_INFO_DEBUG, ("Leaving with ret '%s'\n", >+ ret == True ? "True" : "False")); >+ return ret; >+} >+ >+static bool starts_with_media_dir(const char* media_dirname, >+ size_t media_dirname_len, const char* path) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with media_dirname '%s' " >+ "path '%s'\n", media_dirname, path)); >+ >+ bool ret = False; >+ char* path_start; >+ >+ /* Sometimes Samba gives us "./OMFI MediaFiles". */ >+ if (strncmp(path, "./", 2) == 0) >+ { >+ path_start = &path[2]; >+ } >+ else { >+ path_start = path; >+ } >+ >+ if (strncmp(media_dirname, path_start, media_dirname_len) == 0 >+ && >+ ( >+ path_start[media_dirname_len] == '\0' >+ || >+ path_start[media_dirname_len] == '/' >+ ) >+ ) >+ { >+ ret = True; >+ } >+ >+ DEBUG(MH_INFO_DEBUG, ("Leaving with ret '%s'\n", >+ ret == True ? "True" : "False")); >+ return ret; >+} >+ >+/* >+ * Returns True if the file or directory referenced by the path is below >+ * the AVID_MEDIAFILES_DIRNAME or OMFI_MEDIAFILES_DIRNAME directory >+ * The AVID_MEDIAFILES_DIRNAME and OMFI_MEDIAFILES_DIRNAME are assumed to >+ * be in the root directory, which is generally a safe assumption >+ * in the fixed-path world of Avid. >+ */ >+static bool is_in_media_files(const char* path) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with path '%s'\n", path)); >+ >+ bool ret = False; >+ >+ if ( >+ starts_with_media_dir(AVID_MEDIAFILES_DIRNAME, >+ AVID_MEDIAFILES_DIRNAME_LEN, path) >+ || >+ starts_with_media_dir(OMFI_MEDIAFILES_DIRNAME, >+ OMFI_MEDIAFILES_DIRNAME_LEN, path) >+ ) >+ { >+ ret = True; >+ } >+ DEBUG(MH_INFO_DEBUG, ("Leaving with ret '%s'\n", >+ ret == True ? "True" : "False")); >+ return ret; >+} >+ >+/* >+ * Returns depth of path under media directory. Deals with the >+ * occasional ..../. and ..../.. paths that get passed to stat. >+ * >+ * Assumes is_in_media_files has already been called and has returned >+ * true for the path; if it hasn't, this function will likely crash >+ * and burn. >+ * >+ * Not foolproof; something like "Avid MediaFiles/MXF/../foo/1" >+ * would fool it. Haven't seen paths like that getting to the >+ * stat function yet, so ignoring that possibility for now. >+ */ >+static int depth_from_media_dir(const char* media_dirname, >+ size_t media_dirname_len, const char* path) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with media_dirname '%s' " >+ "path '%s'\n", media_dirname, path)); >+ int transition_count = 0; >+ char* path_start; >+ char* pathPtr; >+ >+ /* Sometimes Samba gives us "./OMFI MediaFiles". */ >+ if (strncmp(path, "./", 2) == 0) >+ { >+ path_start = &path[2]; >+ } >+ else { >+ path_start = path; >+ } >+ >+ if (path_start[media_dirname_len] == '\0') >+ { >+ goto out; >+ } >+ >+ pathPtr = &path_start[media_dirname_len + 1]; >+ >+ while(1) >+ { >+ if (*pathPtr == '\0' || *pathPtr == '/') >+ { >+ if ( >+ *(pathPtr - 1) == '.' >+ && >+ *(pathPtr - 2) == '.' >+ && >+ *(pathPtr - 3) == '/' >+ ) >+ { >+ transition_count--; >+ } >+ else if ( >+ ! >+ ( >+ *(pathPtr - 1) == '/' >+ || >+ ( >+ *(pathPtr - 1) == '.' >+ && >+ *(pathPtr - 2) == '/' >+ ) >+ ) >+ ) >+ { >+ transition_count++; >+ } >+ } >+ if (*pathPtr == '\0') >+ { >+ break; >+ } >+ pathPtr++; >+ } >+ >+ DEBUG(MH_INFO_DEBUG, ("Leaving with transition_count '%i'\n", >+ transition_count)); >+out: >+ return transition_count; >+} >+ >+/* Identifies MDB and PMR files at end of path. */ >+static bool is_avid_database( >+ char *path, >+ size_t path_len, >+ const char *avid_db_filename, >+ const size_t avid_db_filename_len) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with path '%s', " >+ "avid_db_filename '%s', " >+ "path_len '%i', " >+ "avid_db_filename_len '%i'\n", >+ path, avid_db_filename, >+ path_len, avid_db_filename_len)); >+ >+ bool ret = False; >+ >+ if ( >+ path_len > avid_db_filename_len >+ && >+ strcmp(&path[path_len - avid_db_filename_len], >+ avid_db_filename) == 0 >+ && >+ ( >+ path[path_len - avid_db_filename_len - 1] == '/' >+ || >+ path_len > avid_db_filename_len >+ + APPLE_DOUBLE_PREFIX_LEN >+ && >+ path[path_len - avid_db_filename_len >+ - APPLE_DOUBLE_PREFIX_LEN - 1] == '/' >+ && >+ is_apple_double(&path[path_len >+ - avid_db_filename_len >+ - APPLE_DOUBLE_PREFIX_LEN]) >+ ) >+ ) >+ { >+ ret = True; >+ } >+ DEBUG(MH_INFO_DEBUG, ("Leaving with ret '%s'\n", >+ ret == True ? "True" : "False")); >+ return ret; >+} >+ >+ >+/* Add client suffix to paths to MDB_FILENAME, PMR_FILENAME and >+ * CREATING_SUBDIRNAME. >+ * >+ * Caller must free newPath. >+ * >+ * Success: return 0 >+ * Failure: set errno, newPath NULL, return -1 >+ */ >+static int alloc_get_client_path(vfs_handle_struct *handle, >+ TALLOC_CTX *ctx, >+ const char *path, >+ char **newPath) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with path '%s'\n", path)); >+ >+ /* replace /CREATING_DIRNAME/ or /._CREATING_DIRNAME/ >+ * directory in path - potentially in middle of path >+ * - with suffixed name. >+ */ >+ int status = 0; >+ char* pathPtr; >+ *newPath = talloc_strdup(ctx, path); >+ if (*newPath == NULL) >+ { >+ DEBUG(MH_ERR_DEBUG, ("alloc_get_client_path ENOMEM #1\n")); >+ errno = ENOMEM; >+ status = -1; >+ goto out; >+ } >+ DEBUG(MH_INFO_DEBUG, ("newPath #1 %s\n", *newPath)); >+ if ( >+ (pathPtr = strstr(path, CREATING_DIRNAME)) != NULL >+ && >+ ( >+ *(pathPtr + CREATING_DIRNAME_LEN) == '\0' >+ || >+ *(pathPtr + CREATING_DIRNAME_LEN) == '/' >+ ) >+ && >+ ( >+ pathPtr - path > 0 >+ && >+ *(pathPtr - 1) == '/' >+ || >+ pathPtr - path > APPLE_DOUBLE_PREFIX_LEN >+ && >+ *(pathPtr - APPLE_DOUBLE_PREFIX_LEN - 1) == '/' >+ && >+ is_apple_double(pathPtr - APPLE_DOUBLE_PREFIX_LEN) >+ ) >+ ) >+ { >+ /* Insert client suffix into path. */ >+ (*newPath)[pathPtr - path + CREATING_DIRNAME_LEN] = '\0'; >+ DEBUG(MH_INFO_DEBUG, ("newPath #2 %s\n", *newPath)); >+ >+ if (status = alloc_append_client_suffix(handle, newPath)) >+ { >+ goto out; >+ } >+ >+ DEBUG(MH_INFO_DEBUG, ("newPath #3 %s\n", *newPath)); >+ *newPath = talloc_strdup_append(*newPath, >+ pathPtr + CREATING_DIRNAME_LEN); >+ if (*newPath == NULL) >+ { >+ DEBUG(MH_ERR_DEBUG, ("alloc_get_client_path " >+ "ENOMEM #2\n")); >+ errno = ENOMEM; >+ status = -1; >+ goto out; >+ } >+ DEBUG(MH_INFO_DEBUG, ("newPath #4 %s\n", *newPath)); >+ } >+ >+ /* replace /MDB_FILENAME or /PMR_FILENAME or /._MDB_FILENAME >+ * or /._PMR_FILENAME at newPath end with suffixed name. >+ */ >+ size_t intermPathLen = strlen(*newPath); >+ if ( >+ is_avid_database(*newPath, intermPathLen, >+ MDB_FILENAME, MDB_FILENAME_LEN) >+ || >+ is_avid_database(*newPath, intermPathLen, >+ PMR_FILENAME, PMR_FILENAME_LEN) >+ ) >+ { >+ DEBUG(MH_INFO_DEBUG, ("newPath #5 %s\n", *newPath)); >+ if (status = alloc_append_client_suffix(handle, newPath)) >+ { >+ goto out; >+ } >+ DEBUG(MH_INFO_DEBUG, ("newPath #6 %s\n", *newPath)); >+ } >+out: >+ /* newPath must be freed in caller. */ >+ DEBUG(MH_INFO_DEBUG, ("Leaving with *newPath '%s'\n", *newPath)); >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int alloc_get_client_smb_fname(struct vfs_handle_struct *handle, >+ TALLOC_CTX *ctx, >+ const struct smb_filename *smb_fname, >+ struct smb_filename **clientFname) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with smb_fname->base_name '%s'\n", >+ smb_fname->base_name)); >+ >+ int status = 0; >+ NTSTATUS copystatus; >+ >+ copystatus = copy_smb_filename(ctx, smb_fname, clientFname); >+ if (!NT_STATUS_IS_OK(copystatus)) >+ { >+ DEBUG(MH_ERR_DEBUG, ("alloc_get_client_smb_fname " >+ "NTERR\n")); >+ errno = map_errno_from_nt_status(copystatus); >+ status = -1; >+ goto err; >+ } >+ if (status = alloc_get_client_path(handle, ctx, >+ smb_fname->base_name, >+ &(*clientFname)->base_name)) >+ { >+ goto err; >+ } >+ DEBUG(MH_INFO_DEBUG, ("Leaving with (*clientFname)->base_name " >+ "'%s'\n", (*clientFname)->base_name)); >+err: >+ return status; >+} >+ >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int alloc_set_client_dirinfo_path(struct vfs_handle_struct *handle, >+ TALLOC_CTX *ctx, >+ char **path, >+ const char *avid_db_filename) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with avid_db_filename '%s'\n", >+ avid_db_filename)); >+ >+ int status = 0; >+ >+ if ((*path = talloc_strdup(ctx, avid_db_filename)) == NULL) >+ { >+ DEBUG(MH_ERR_DEBUG, ("alloc_set_client_dirinfo_path " >+ "ENOMEM\n")); >+ errno = ENOMEM; >+ status = -1; >+ goto err; >+ } >+ if (status = alloc_append_client_suffix(handle, path)) >+ { >+ goto err; >+ } >+ DEBUG(MH_INFO_DEBUG, ("Leaving with *path '%s'\n", *path)); >+err: >+ return status; >+} >+ >+/* >+ * Replace mtime on clientFname with mtime from client-suffixed >+ * equivalent, if it exists. >+ * >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int set_fake_mtime(vfs_handle_struct *handle, >+ TALLOC_CTX *ctx, >+ struct smb_filename **clientFname, >+ int (*statFn)(const char *, SMB_STRUCT_STAT *, bool)) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with (*clientFname)->base_name " >+ "'%s', (*clientFname)->st.st_ex_mtime %s", >+ (*clientFname)->base_name, >+ ctime(&((*clientFname)->st.st_ex_mtime.tv_sec)))); >+ >+ int status = 0; >+ >+ if ( >+ depth_from_media_dir(AVID_MXF_DIRNAME, >+ AVID_MXF_DIRNAME_LEN, >+ (*clientFname)->base_name) >+ != 1 >+ && >+ depth_from_media_dir(OMFI_MEDIAFILES_DIRNAME, >+ OMFI_MEDIAFILES_DIRNAME_LEN, >+ (*clientFname)->base_name) >+ != 0 >+ ) >+ { >+ goto out; >+ } >+ >+ char *statPath; >+ SMB_STRUCT_STAT fakeStat; >+ int copy_len = strlen((*clientFname)->base_name); >+ >+ /* Hack to deal with occasional "Avid MediaFiles/MXF/1/." paths. >+ * We know we're under a media dir, so paths are at least 2 chars >+ * long. >+ */ >+ if ((*clientFname)->base_name[copy_len - 1] == '.' && >+ (*clientFname)->base_name[copy_len - 2] == '/') >+ { >+ copy_len -= 2; >+ } >+ >+ if ((statPath = talloc_strndup(ctx, >+ (*clientFname)->base_name, copy_len)) == NULL) >+ { >+ errno = ENOMEM; >+ status = -1; >+ goto err; >+ } >+ if (status = alloc_append_client_suffix(handle, &statPath)) >+ { >+ goto err; >+ } >+ >+ DEBUG(MH_INFO_DEBUG, ("Fake stat'ing '%s'\n", statPath)); >+ if (statFn(statPath, &fakeStat, >+ lp_fake_dir_create_times(SNUM(handle->conn)))) >+ { >+ /* This can fail for legitimate reasons - i.e. the >+ * fakeStat directory doesn't exist, which is okay >+ * - so we don't set status. But if it does fail, >+ * we need to skip over the mtime assignment. >+ */ >+ goto err; >+ } >+ >+ DEBUG(MH_INFO_DEBUG, ("Setting fake mtime from '%s'\n", statPath)); >+ (*clientFname)->st.st_ex_mtime = fakeStat.st_ex_mtime; >+err: >+ TALLOC_FREE(statPath); >+out: >+ DEBUG(MH_INFO_DEBUG, ("Leaving with (*clientFname)->base_name " >+ "'%s', (*clientFname)->st.st_ex_mtime %s", >+ (*clientFname)->base_name, >+ ctime(&((*clientFname)->st.st_ex_mtime.tv_sec)))); >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_statvfs(struct vfs_handle_struct *handle, >+ const char *path, >+ struct vfs_statvfs_struct *statbuf) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with path '%s'\n", path)); >+ >+ int status; >+ >+ if (!is_in_media_files(path)) >+ { >+ status = SMB_VFS_NEXT_STATVFS(handle, path, statbuf); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_STATVFS(handle, clientPath, statbuf); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ DEBUG(MH_INFO_DEBUG, ("Leaving with path '%s'\n", path)); >+ return status; >+} >+ >+static int alloc_set_client_dirinfo(vfs_handle_struct *handle, >+ const char *fname, >+ struct mh_dirinfo_struct **dirInfo) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with fname '%s'\n", fname)); >+ >+ int status = 0; >+ >+ *dirInfo = talloc(NULL, struct mh_dirinfo_struct); >+ if (*dirInfo == NULL) >+ { >+ goto err; >+ } >+ >+ (*dirInfo)->dirpath = talloc_strdup(*dirInfo, fname); >+ if ((*dirInfo)->dirpath == NULL) >+ { >+ goto err; >+ } >+ >+ if (!is_in_media_files(fname)) >+ { >+ (*dirInfo)->clientPath = NULL; >+ (*dirInfo)->clientMDBFilename = NULL; >+ (*dirInfo)->clientPMRFilename = NULL; >+ (*dirInfo)->clientCreatingDirname = NULL; >+ (*dirInfo)->isInMediaFiles = False; >+ goto out; >+ } >+ >+ (*dirInfo)->isInMediaFiles = True; >+ >+ if (alloc_set_client_dirinfo_path(handle, >+ *dirInfo, >+ &((*dirInfo)->clientMDBFilename), >+ MDB_FILENAME)) >+ { >+ goto err; >+ } >+ >+ if (alloc_set_client_dirinfo_path(handle, >+ *dirInfo, >+ &((*dirInfo)->clientPMRFilename), >+ PMR_FILENAME)) >+ { >+ goto err; >+ } >+ >+ if (alloc_set_client_dirinfo_path(handle, >+ *dirInfo, >+ &((*dirInfo)->clientCreatingDirname), >+ CREATING_DIRNAME)) >+ { >+ goto err; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (alloc_get_client_path(handle, ctx, >+ fname, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ (*dirInfo)->clientPath = talloc_strdup(*dirInfo, clientPath); >+ if ((*dirInfo)->clientPath == NULL) >+ { >+ goto err; >+ } >+ >+ TALLOC_FREE(clientPath); >+ >+out: >+ DEBUG(MH_INFO_DEBUG, ("Leaving with (*dirInfo)->dirpath '%s', " >+ "(*dirInfo)->clientPath '%s'\n", >+ (*dirInfo)->dirpath, >+ (*dirInfo)->clientPath)); >+ return status; >+ >+err: >+ DEBUG(MH_ERR_DEBUG, ("Failing with fname '%s'\n", fname)); >+ TALLOC_FREE(*dirInfo); >+ status = -1; >+ errno = ENOMEM; >+ return status; >+} >+ >+/* Success: return a mh_dirinfo_struct cast as a DIR >+ * Failure: set errno, return NULL >+ */ >+static DIR *mh_opendir(vfs_handle_struct *handle, >+ const char *fname, >+ const char *mask, >+ uint32 attr) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with fname '%s'\n", fname)); >+ >+ struct mh_dirinfo_struct *dirInfo; >+ >+ if (alloc_set_client_dirinfo(handle, fname, &dirInfo)) >+ { >+ goto err; >+ } >+ >+ if (!dirInfo->isInMediaFiles) >+ { >+ dirInfo->dirstream = SMB_VFS_NEXT_OPENDIR(handle, >+ fname, mask, attr); >+ } else { >+ dirInfo->dirstream = SMB_VFS_NEXT_OPENDIR(handle, >+ dirInfo->clientPath, mask, attr); >+ } >+ >+ if (dirInfo->dirstream == NULL) { >+ goto err; >+ } >+ >+out: >+ /* Success is freed in closedir. */ >+ DEBUG(MH_INFO_DEBUG, ("Leaving with dirInfo->dirpath '%s', " >+ "dirInfo->clientPath '%s'\n", >+ dirInfo->dirpath, >+ dirInfo->clientPath)); >+ return (DIR*)dirInfo; >+err: >+ /* Failure is freed here. */ >+ DEBUG(MH_ERR_DEBUG, ("Failing with fname '%s'\n", fname)); >+ TALLOC_FREE(dirInfo); >+ return NULL; >+} >+ >+static DIR *mh_fdopendir(vfs_handle_struct *handle, >+ files_struct *fsp, >+ const char *mask, >+ uint32 attr) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with fsp->fsp_name->base_name '%s'\n", >+ fsp->fsp_name->base_name)); >+ >+ struct mh_dirinfo_struct *dirInfo; >+ DIR *dirstream; >+ >+ dirstream = SMB_VFS_NEXT_FDOPENDIR(handle, fsp, mask, attr); >+ if (!dirstream) >+ { >+ goto err; >+ } >+ >+ if (alloc_set_client_dirinfo(handle, fsp->fsp_name->base_name, >+ &dirInfo)) >+ { >+ goto err; >+ } >+ >+ dirInfo->dirstream = dirstream; >+ >+ if (! dirInfo->isInMediaFiles) { >+ goto out; >+ } >+ >+ if (set_fake_mtime(handle, fsp, &(fsp->fsp_name), sys_stat)) >+ { >+ goto err; >+ } >+ >+out: >+ DEBUG(MH_INFO_DEBUG, ("Leaving with dirInfo->dirpath '%s', " >+ "dirInfo->clientPath '%s', " >+ "fsp->fsp_name->st.st_ex_mtime %s", >+ dirInfo->dirpath, >+ dirInfo->clientPath, >+ ctime(&(fsp->fsp_name->st.st_ex_mtime.tv_sec)))); >+ /* Success is freed in closedir. */ >+ return (DIR *) dirInfo; >+err: >+ /* Failure is freed here. */ >+ DEBUG(MH_ERR_DEBUG, ("Failing with fsp->fsp_name->base_name '%s'\n", >+ fsp->fsp_name->base_name)); >+ TALLOC_FREE(dirInfo); >+ return NULL; >+} >+ >+/* >+ * skip MDB_FILENAME and PMR_FILENAME filenames and CREATING_DIRNAME >+ * directory, skip other client's suffixed MDB_FILENAME and PMR_FILENAME >+ * filenames and CREATING_DIRNAME directory, replace this client's >+ * suffixed MDB_FILENAME and PMR_FILENAME filenames and CREATING_DIRNAME >+ * directory with non suffixed. >+ * >+ * Success: return dirent >+ * End of data: return NULL >+ * Failure: set errno, return NULL >+ */ >+static struct dirent *mh_readdir(vfs_handle_struct *handle, >+ DIR *dirp, >+ SMB_STRUCT_STAT *sbuf) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_readdir\n")); >+ >+ mh_dirinfo_struct* dirInfo = (mh_dirinfo_struct*)dirp; >+ >+ DEBUG(MH_INFO_DEBUG, ("dirInfo->dirpath '%s', " >+ "dirInfo->clientPath '%s', " >+ "dirInfo->isInMediaFiles '%s', " >+ "dirInfo->clientMDBFilename '%s', " >+ "dirInfo->clientPMRFilename '%s', " >+ "dirInfo->clientCreatingDirname '%s'\n", >+ dirInfo->dirpath, >+ dirInfo->clientPath, >+ dirInfo->isInMediaFiles ? "True" : "False", >+ dirInfo->clientMDBFilename, >+ dirInfo->clientPMRFilename, >+ dirInfo->clientCreatingDirname)); >+ >+ struct dirent *d = NULL; >+ >+ if (! dirInfo->isInMediaFiles) >+ { >+ d = SMB_VFS_NEXT_READDIR(handle, dirInfo->dirstream, sbuf); >+ goto out; >+ } >+ >+ int skip; >+ do >+ { >+ skip = False; >+ d = SMB_VFS_NEXT_READDIR(handle, dirInfo->dirstream, sbuf); >+ >+ if (d == NULL) >+ { >+ break; >+ } >+ >+ const char* dname; >+ bool isAppleDouble; >+ >+ /* ignore apple double prefix for logic below */ >+ if (is_apple_double(d->d_name)) >+ { >+ dname = &d->d_name[APPLE_DOUBLE_PREFIX_LEN]; >+ isAppleDouble = True; >+ } >+ else >+ { >+ dname = d->d_name; >+ isAppleDouble = False; >+ } >+ >+ /* skip Avid-special files with no client suffix */ >+ if ( >+ strcmp(dname, MDB_FILENAME) == 0 >+ || >+ strcmp(dname, PMR_FILENAME) == 0 >+ || >+ strcmp(dname, CREATING_DIRNAME) == 0 >+ ) >+ { >+ skip = True; >+ } >+ /* chop client suffix off this client's suffixed files */ >+ else if (strcmp(dname, dirInfo->clientMDBFilename) == 0) >+ { >+ if (isAppleDouble) >+ { >+ d->d_name[MDB_FILENAME_LEN >+ + APPLE_DOUBLE_PREFIX_LEN] = '\0'; >+ } >+ else >+ { >+ d->d_name[MDB_FILENAME_LEN] = '\0'; >+ } >+ } >+ else if (strcmp(dname, dirInfo->clientPMRFilename) == 0) >+ { >+ if (isAppleDouble) >+ { >+ d->d_name[PMR_FILENAME_LEN >+ + APPLE_DOUBLE_PREFIX_LEN] = '\0'; >+ } >+ else >+ { >+ d->d_name[PMR_FILENAME_LEN] = '\0'; >+ } >+ } >+ else if (strcmp(dname, dirInfo->clientCreatingDirname) >+ == 0) >+ { >+ if (isAppleDouble) >+ { >+ d->d_name[CREATING_DIRNAME_LEN >+ + APPLE_DOUBLE_PREFIX_LEN] = '\0'; >+ } >+ else >+ { >+ d->d_name[CREATING_DIRNAME_LEN] = '\0'; >+ } >+ } >+ /* >+ * Anything that starts as an Avid-special file >+ * that's made it this far should be skipped. This >+ * is different from the original behaviour, which >+ * only skipped other client's suffixed files. >+ */ >+ else if ( >+ strncmp(MDB_FILENAME, dname, >+ MDB_FILENAME_LEN) == 0 >+ || >+ strncmp(PMR_FILENAME, dname, >+ PMR_FILENAME_LEN) == 0 >+ || >+ strncmp(CREATING_DIRNAME, dname, >+ CREATING_DIRNAME_LEN) == 0 >+ ) >+ { >+ skip = True; >+ } >+ } >+ while (skip); >+ >+out: >+ DEBUG(MH_INFO_DEBUG, ("Leaving mh_readdir\n")); >+ return d; >+} >+ >+/* >+ * Success: no success result defined. >+ * Failure: no failure result defined. >+ */ >+static void mh_seekdir(vfs_handle_struct *handle, >+ DIR *dirp, >+ long offset) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering and leaving mh_seekdir\n")); >+ return SMB_VFS_NEXT_SEEKDIR(handle, >+ ((mh_dirinfo_struct*)dirp)->dirstream, offset); >+} >+ >+/* >+ * Success: return long >+ * Failure: no failure result defined. >+ */ >+static long mh_telldir(vfs_handle_struct *handle, >+ DIR *dirp) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering and leaving mh_telldir\n")); >+ return SMB_VFS_NEXT_TELLDIR(handle, >+ ((mh_dirinfo_struct*)dirp)->dirstream); >+} >+ >+/* >+ * Success: no success result defined. >+ * Failure: no failure result defined. >+ */ >+static void mh_rewinddir(vfs_handle_struct *handle, >+ DIR *dirp) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering and leaving mh_rewinddir\n")); >+ return SMB_VFS_NEXT_REWINDDIR(handle, >+ ((mh_dirinfo_struct*)dirp)->dirstream); >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_mkdir(vfs_handle_struct *handle, >+ const char *path, >+ mode_t mode) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with path '%s'\n", path)); >+ >+ int status; >+ >+ if (!is_in_media_files(path)) >+ { >+ status = SMB_VFS_NEXT_MKDIR(handle, path, mode); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_MKDIR(handle, clientPath, mode); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ DEBUG(MH_INFO_DEBUG, ("Leaving with path '%s'\n", path)); >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_rmdir(vfs_handle_struct *handle, >+ const char *path) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with path '%s'\n", path)); >+ >+ int status; >+ >+ if (!is_in_media_files(path)) >+ { >+ status = SMB_VFS_NEXT_RMDIR(handle, path); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_RMDIR(handle, clientPath); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ DEBUG(MH_INFO_DEBUG, ("Leaving with path '%s'\n", path)); >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_closedir(vfs_handle_struct *handle, >+ DIR *dirp) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_closedir\n")); >+ DIR *realdirp = ((mh_dirinfo_struct*)dirp)->dirstream; >+ // Will this talloc_free destroy realdirp? >+ TALLOC_FREE(dirp); >+ >+ DEBUG(MH_INFO_DEBUG, ("Leaving mh_closedir\n")); >+ return SMB_VFS_NEXT_CLOSEDIR(handle, realdirp); >+} >+ >+/* >+ * Success: no success result defined. >+ * Failure: no failure result defined. >+ */ >+static void mh_init_search_op(vfs_handle_struct *handle, >+ DIR *dirp) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering and leaving mh_init_search_op\n")); >+ return SMB_VFS_NEXT_INIT_SEARCH_OP(handle, >+ ((mh_dirinfo_struct*)dirp)->dirstream); >+} >+ >+/* >+ * Success: return non-negative file descriptor >+ * Failure: set errno, return -1 >+ */ >+static int mh_open(vfs_handle_struct *handle, >+ struct smb_filename *smb_fname, >+ files_struct *fsp, >+ int flags, >+ mode_t mode) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with smb_fname->base_name '%s'\n", >+ smb_fname->base_name)); >+ >+ int ret; >+ >+ if (!is_in_media_files(smb_fname->base_name)) >+ { >+ ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, >+ mode); >+ goto out; >+ } >+ >+ struct smb_filename *clientFname = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if(alloc_get_client_smb_fname(handle, ctx, >+ smb_fname, >+ &clientFname)) >+ { >+ ret = -1; >+ goto err; >+ } >+ >+ // What about fsp->fsp_name? >+ // We also have to get correct stat info into fsp and smb_fname >+ // for DB files, don't we? >+ >+ DEBUG(MH_INFO_DEBUG, ("Leaving with smb_fname->base_name '%s' " >+ "smb_fname->st.st_ex_mtime %s" >+ " fsp->fsp_name->st.st_ex_mtime %s", >+ smb_fname->base_name, >+ ctime(&(smb_fname->st.st_ex_mtime.tv_sec)), >+ ctime(&(fsp->fsp_name->st.st_ex_mtime.tv_sec)))); >+ >+ ret = SMB_VFS_NEXT_OPEN(handle, clientFname, fsp, flags, mode); >+err: >+ TALLOC_FREE(clientFname); >+out: >+ DEBUG(MH_INFO_DEBUG, ("Leaving with smb_fname->base_name '%s'\n", >+ smb_fname->base_name)); >+ return ret; >+} >+ >+/* >+ * Success: return non-negative file descriptor >+ * Failure: set errno, return -1 >+ */ >+static NTSTATUS mh_create_file(vfs_handle_struct *handle, >+ struct smb_request *req, >+ uint16_t root_dir_fid, >+ struct smb_filename *smb_fname, >+ uint32_t access_mask, >+ uint32_t share_access, >+ uint32_t create_disposition, >+ uint32_t create_options, >+ uint32_t file_attributes, >+ uint32_t oplock_request, >+ uint64_t allocation_size, >+ uint32_t private_flags, >+ struct security_descriptor *sd, >+ struct ea_list *ea_list, >+ files_struct **result_fsp, >+ int *pinfo) >+{ >+ NTSTATUS status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering with smb_fname->base_name '%s'\n", >+ smb_fname->base_name)); >+ if (!is_in_media_files(smb_fname->base_name)) >+ { >+ status = SMB_VFS_NEXT_CREATE_FILE( >+ handle, >+ req, >+ root_dir_fid, >+ smb_fname, >+ access_mask, >+ share_access, >+ create_disposition, >+ create_options, >+ file_attributes, >+ oplock_request, >+ allocation_size, >+ private_flags, >+ sd, >+ ea_list, >+ result_fsp, >+ pinfo); >+ goto out; >+ } >+ >+ struct smb_filename *clientFname = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (alloc_get_client_smb_fname(handle, ctx, >+ smb_fname, >+ &clientFname)) >+ { >+ status = map_nt_error_from_unix(errno); >+ goto err; >+ } >+ >+ /* This only creates files, so we don't have to worry about >+ * our fake directory stat'ing here. >+ */ >+ // But we still need to route stat calls for DB files >+ // properly, right? >+ status = SMB_VFS_NEXT_CREATE_FILE( >+ handle, >+ req, >+ root_dir_fid, >+ clientFname, >+ access_mask, >+ share_access, >+ create_disposition, >+ create_options, >+ file_attributes, >+ oplock_request, >+ allocation_size, >+ private_flags, >+ sd, >+ ea_list, >+ result_fsp, >+ pinfo); >+err: >+ TALLOC_FREE(clientFname); >+out: >+ DEBUG(MH_INFO_DEBUG, ("Leaving with smb_fname->base_name '%s'" >+ "smb_fname->st.st_ex_mtime %s" >+ " fsp->fsp_name->st.st_ex_mtime %s", >+ smb_fname->base_name, >+ ctime(&(smb_fname->st.st_ex_mtime.tv_sec)), >+ (*result_fsp) && VALID_STAT((*result_fsp)->fsp_name->st) ? >+ ctime(&((*result_fsp)->fsp_name->st.st_ex_mtime.tv_sec)) : >+ "No fsp time\n")); >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_rename(vfs_handle_struct *handle, >+ const struct smb_filename *smb_fname_src, >+ const struct smb_filename *smb_fname_dst) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with " >+ "smb_fname_src->base_name '%s', " >+ "smb_fname_dst->base_name '%s'\n", >+ smb_fname_src->base_name, >+ smb_fname_dst->base_name)); >+ >+ int status; >+ >+ if (!is_in_media_files(smb_fname_src->base_name) >+ && >+ !is_in_media_files(smb_fname_dst->base_name)) >+ { >+ status = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, >+ smb_fname_dst); >+ goto out; >+ } >+ >+ struct smb_filename *srcClientFname = NULL; >+ struct smb_filename *dstClientFname = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_smb_fname(handle, ctx, >+ smb_fname_src, >+ &srcClientFname)) >+ { >+ goto err; >+ } >+ >+ if (status = alloc_get_client_smb_fname(handle, ctx, >+ smb_fname_dst, >+ &dstClientFname)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_RENAME(handle, srcClientFname, >+ dstClientFname); >+err: >+ TALLOC_FREE(dstClientFname); >+ TALLOC_FREE(srcClientFname); >+out: >+ DEBUG(MH_INFO_DEBUG, ("Leaving with smb_fname_src->base_name '%s'," >+ " smb_fname_dst->base_name '%s'\n", >+ smb_fname_src->base_name, >+ smb_fname_dst->base_name)); >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_stat(vfs_handle_struct *handle, >+ struct smb_filename *smb_fname) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with smb_fname->base_name '%s'\n", >+ smb_fname->base_name)); >+ >+ int status = 0; >+ >+ if (!is_in_media_files(smb_fname->base_name)) >+ { >+ status = SMB_VFS_NEXT_STAT(handle, smb_fname); >+ goto out; >+ } >+ >+ struct smb_filename *clientFname = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_smb_fname(handle, ctx, >+ smb_fname, >+ &clientFname)) >+ { >+ goto err; >+ } >+ DEBUG(MH_INFO_DEBUG, ("Stat'ing clientFname->base_name '%s'\n", >+ clientFname->base_name)); >+ if (status = SMB_VFS_NEXT_STAT(handle, clientFname)) >+ { >+ goto err; >+ } >+ if (status = set_fake_mtime(handle, ctx, &clientFname, sys_stat)) >+ { >+ goto err; >+ } >+ >+ /* Unlike functions with const smb_filename, we have to >+ * modify smb_fname itself to pass our info back up. >+ */ >+ DEBUG(MH_INFO_DEBUG, ("Setting smb_fname '%s' stat " >+ "from clientFname '%s'\n", >+ smb_fname->base_name, >+ clientFname->base_name)); >+ smb_fname->st = clientFname->st; >+err: >+ TALLOC_FREE(clientFname); >+out: >+ DEBUG(MH_INFO_DEBUG, ("Leaving with smb_fname->st.st_ex_mtime %s", >+ ctime(&(smb_fname->st.st_ex_mtime.tv_sec)))); >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_lstat(vfs_handle_struct *handle, >+ struct smb_filename *smb_fname) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with smb_fname->base_name '%s'\n", >+ smb_fname->base_name)); >+ >+ int status = 0; >+ >+ if (!is_in_media_files(smb_fname->base_name)) >+ { >+ status = SMB_VFS_NEXT_LSTAT(handle, smb_fname); >+ goto out; >+ } >+ >+ struct smb_filename *clientFname = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_smb_fname(handle, ctx, >+ smb_fname, >+ &clientFname)) >+ { >+ goto err; >+ } >+ if (status = SMB_VFS_NEXT_LSTAT(handle, clientFname)) >+ { >+ goto err; >+ } >+ >+ if (status = set_fake_mtime(handle, ctx, &clientFname, sys_lstat)) >+ { >+ goto err; >+ } >+ /* Unlike functions with const smb_filename, we have to >+ * modify smb_fname itself to pass our info back up. >+ */ >+ smb_fname->st = clientFname->st; >+err: >+ TALLOC_FREE(clientFname); >+out: >+ DEBUG(MH_INFO_DEBUG, ("Leaving with smb_fname->st.st_ex_mtime %s", >+ ctime(&(smb_fname->st.st_ex_mtime.tv_sec)))); >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_fstat(vfs_handle_struct *handle, >+ files_struct *fsp, SMB_STRUCT_STAT *sbuf) >+{ >+ DEBUG(MH_INFO_DEBUG, ("Entering with fsp->fsp_name->base_name " >+ "'%s'\n", fsp_str_dbg(fsp))); >+ >+ int status = 0; >+ >+ if (status = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf)) >+ { >+ goto out; >+ } >+ >+ if (fsp->fsp_name == NULL >+ || !is_in_media_files(fsp->fsp_name->base_name)) >+ { >+ goto out; >+ } >+ >+ if (status = mh_stat(handle, fsp->fsp_name)) >+ { >+ goto out; >+ } >+ >+ *sbuf = fsp->fsp_name->st; >+out: >+ DEBUG(MH_INFO_DEBUG, ("Leaving with fsp->fsp_name->st.st_ex_mtime " >+ "%s", >+ ctime(&(fsp->fsp_name->st.st_ex_mtime.tv_sec)))); >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_unlink(vfs_handle_struct *handle, >+ const struct smb_filename *smb_fname) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_unlink\n")); >+ if (!is_in_media_files(smb_fname->base_name)) >+ { >+ status = SMB_VFS_NEXT_UNLINK(handle, smb_fname); >+ goto out; >+ } >+ >+ struct smb_filename *clientFname = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_smb_fname(handle, ctx, >+ smb_fname, >+ &clientFname)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_UNLINK(handle, clientFname); >+err: >+ TALLOC_FREE(clientFname); >+out: >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_chmod(vfs_handle_struct *handle, >+ const char *path, >+ mode_t mode) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_chmod\n")); >+ if (!is_in_media_files(path)) >+ { >+ status = SMB_VFS_NEXT_CHMOD(handle, path, mode); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_CHMOD(handle, clientPath, mode); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_chown(vfs_handle_struct *handle, >+ const char *path, >+ uid_t uid, >+ gid_t gid) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_chown\n")); >+ if (!is_in_media_files(path)) >+ { >+ status = SMB_VFS_NEXT_CHOWN(handle, path, uid, gid); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_CHOWN(handle, clientPath, uid, gid); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_lchown(vfs_handle_struct *handle, >+ const char *path, >+ uid_t uid, >+ gid_t gid) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_lchown\n")); >+ if (!is_in_media_files(path)) >+ { >+ status = SMB_VFS_NEXT_LCHOWN(handle, path, uid, gid); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_LCHOWN(handle, clientPath, uid, gid); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_chdir(vfs_handle_struct *handle, >+ const char *path) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_chdir\n")); >+ if (!is_in_media_files(path)) >+ { >+ status = SMB_VFS_NEXT_CHDIR(handle, path); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_CHDIR(handle, clientPath); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_ntimes(vfs_handle_struct *handle, >+ const struct smb_filename *smb_fname, >+ struct smb_file_time *ft) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_ntimes\n")); >+ if (!is_in_media_files(smb_fname->base_name)) >+ { >+ status = SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft); >+ goto out; >+ } >+ >+ struct smb_filename *clientFname = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_smb_fname(handle, ctx, >+ smb_fname, >+ &clientFname)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_NTIMES(handle, clientFname, ft); >+err: >+ TALLOC_FREE(clientFname); >+out: >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_symlink(vfs_handle_struct *handle, >+ const char *oldpath, >+ const char *newpath) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_symlink\n")); >+ if (!is_in_media_files(oldpath) && !is_in_media_files(newpath)) >+ { >+ status = SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath); >+ goto out; >+ } >+ >+ char *oldClientPath = NULL; >+ char *newClientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ oldpath, >+ &oldClientPath)) >+ { >+ goto err; >+ } >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ newpath, >+ &newClientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_SYMLINK(handle, >+ oldClientPath, >+ newClientPath); >+ >+err: >+ TALLOC_FREE(newClientPath); >+ TALLOC_FREE(oldClientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return byte count >+ * Failure: set errno, return -1 >+ */ >+static int mh_readlink(vfs_handle_struct *handle, >+ const char *path, >+ char *buf, >+ size_t bufsiz) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_readlink\n")); >+ if (!is_in_media_files(path)) >+ { >+ status = SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_READLINK(handle, clientPath, buf, bufsiz); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_link(vfs_handle_struct *handle, >+ const char *oldpath, >+ const char *newpath) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_link\n")); >+ if (!is_in_media_files(oldpath) && !is_in_media_files(newpath)) >+ { >+ status = SMB_VFS_NEXT_LINK(handle, oldpath, newpath); >+ goto out; >+ } >+ >+ char *oldClientPath = NULL; >+ char *newClientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ oldpath, >+ &oldClientPath)) >+ { >+ goto err; >+ } >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ newpath, >+ &newClientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_LINK(handle, oldClientPath, newClientPath); >+err: >+ TALLOC_FREE(newClientPath); >+ TALLOC_FREE(oldClientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_mknod(vfs_handle_struct *handle, >+ const char *pathname, >+ mode_t mode, >+ SMB_DEV_T dev) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_mknod\n")); >+ if (!is_in_media_files(pathname)) >+ { >+ status = SMB_VFS_NEXT_MKNOD(handle, pathname, mode, dev); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ pathname, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_MKNOD(handle, clientPath, mode, dev); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return path pointer >+ * Failure: set errno, return NULL pointer >+ */ >+static char *mh_realpath(vfs_handle_struct *handle, >+ const char *path) >+{ >+ char *buf; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_realpath\n")); >+ if (!is_in_media_files(path)) >+ { >+ buf = SMB_VFS_NEXT_REALPATH(handle, path); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ buf = NULL; >+ goto err; >+ } >+ >+ buf = SMB_VFS_NEXT_REALPATH(handle, clientPath); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return buf; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_chflags(vfs_handle_struct *handle, >+ const char *path, >+ unsigned int flags) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_chflags\n")); >+ if (!is_in_media_files(path)) >+ { >+ status = SMB_VFS_NEXT_CHFLAGS(handle, path, flags); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_CHFLAGS(handle, clientPath, flags); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return NT_STATUS_OK >+ * Failure: return NT status error >+ */ >+static NTSTATUS mh_streaminfo(struct vfs_handle_struct *handle, >+ struct files_struct *fsp, >+ const char *fname, >+ TALLOC_CTX *ctx, >+ unsigned int *num_streams, >+ struct stream_struct **streams) >+{ >+ NTSTATUS status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_streaminfo\n")); >+ if (!is_in_media_files(fname)) >+ { >+ status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, >+ ctx, num_streams, streams); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *mem_ctx = talloc_tos(); >+ >+ if (alloc_get_client_path(handle, mem_ctx, >+ fname, >+ &clientPath)) >+ { >+ status = map_nt_error_from_unix(errno); >+ goto err; >+ } >+ >+ /* This only works on files, so we don't have to worry about >+ * our fake directory stat'ing here. >+ */ >+ // But what does this function do, exactly? Does it need >+ // extra modifications for the Avid stuff? >+ status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, clientPath, >+ ctx, num_streams, streams); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return status; >+} >+ >+/* Ignoring get_real_filename function because the default >+ * doesn't do anything. >+ */ >+ >+/* >+ * Success: return NT_STATUS_OK >+ * Failure: return NT status error >+ * In this case, "name" is a path. >+ */ >+static NTSTATUS mh_get_nt_acl(vfs_handle_struct *handle, >+ const char *name, >+ uint32 security_info, >+ struct security_descriptor **ppdesc) >+{ >+ NTSTATUS status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_get_nt_acl\n")); >+ if (!is_in_media_files(name)) >+ { >+ status = SMB_VFS_NEXT_GET_NT_ACL(handle, name, >+ security_info, ppdesc); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (alloc_get_client_path(handle, ctx, >+ name, >+ &clientPath)) >+ { >+ status = map_nt_error_from_unix(errno); >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_GET_NT_ACL(handle, clientPath, >+ security_info, ppdesc); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_chmod_acl(vfs_handle_struct *handle, >+ const char *path, >+ mode_t mode) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_chmod_acl\n")); >+ if (!is_in_media_files(path)) >+ { >+ status = SMB_VFS_NEXT_CHMOD_ACL(handle, path, mode); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_CHMOD_ACL(handle, clientPath, mode); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return acl pointer >+ * Failure: set errno, return NULL >+ */ >+static SMB_ACL_T mh_sys_acl_get_file(vfs_handle_struct *handle, >+ const char *path_p, >+ SMB_ACL_TYPE_T type) >+{ >+ SMB_ACL_T ret; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_sys_acl_get_file\n")); >+ if (!is_in_media_files(path_p)) >+ { >+ ret = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, path_p, type); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (alloc_get_client_path(handle, ctx, >+ path_p, >+ &clientPath)) >+ { >+ ret = NULL; >+ goto err; >+ } >+ >+ ret = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, clientPath, type); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return ret; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ * In this case, "name" is a path. >+ */ >+static int mh_sys_acl_set_file(vfs_handle_struct *handle, >+ const char *name, >+ SMB_ACL_TYPE_T acltype, >+ SMB_ACL_T theacl) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_sys_acl_set_file\n")); >+ if (!is_in_media_files(name)) >+ { >+ status = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, name, >+ acltype, theacl); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ name, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, clientPath, >+ acltype, theacl); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ */ >+static int mh_sys_acl_delete_def_file(vfs_handle_struct *handle, >+ const char *path) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_sys_acl_delete_def_file\n")); >+ if (!is_in_media_files(path)) >+ { >+ status = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, >+ path); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, clientPath); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return positive number >+ * Failure: set errno, return -1 >+ * In this case, "name" is an attr name. >+ */ >+static ssize_t mh_getxattr(struct vfs_handle_struct *handle, >+ const char *path, >+ const char *name, >+ void *value, >+ size_t size) >+{ >+ ssize_t ret; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_getxattr\n")); >+ if (!is_in_media_files(path)) >+ { >+ ret = SMB_VFS_NEXT_GETXATTR(handle, path, name, value, >+ size); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ ret = -1; >+ goto err; >+ } >+ >+ ret = SMB_VFS_NEXT_GETXATTR(handle, clientPath, name, value, size); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return ret; >+} >+ >+/* >+ * Success: return positive number >+ * Failure: set errno, return -1 >+ */ >+static ssize_t mh_listxattr(struct vfs_handle_struct *handle, >+ const char *path, >+ char *list, >+ size_t size) >+{ >+ ssize_t ret; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_listxattr\n")); >+ if (!is_in_media_files(path)) >+ { >+ ret = SMB_VFS_NEXT_LISTXATTR(handle, path, list, size); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ ret = -1; >+ goto err; >+ } >+ >+ ret = SMB_VFS_NEXT_LISTXATTR(handle, clientPath, list, size); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return ret; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ * In this case, "name" is an attr name. >+ */ >+static int mh_removexattr(struct vfs_handle_struct *handle, >+ const char *path, >+ const char *name) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_removexattr\n")); >+ if (!is_in_media_files(path)) >+ { >+ status = SMB_VFS_NEXT_REMOVEXATTR(handle, path, name); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_REMOVEXATTR(handle, clientPath, name); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return 0 >+ * Failure: set errno, return -1 >+ * In this case, "name" is an attr name. >+ */ >+static int mh_setxattr(struct vfs_handle_struct *handle, >+ const char *path, >+ const char *name, >+ const void *value, >+ size_t size, >+ int flags) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_setxattr\n")); >+ if (!is_in_media_files(path)) >+ { >+ status = SMB_VFS_NEXT_SETXATTR(handle, path, name, value, >+ size, flags); >+ goto out; >+ } >+ >+ char *clientPath = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_path(handle, ctx, >+ path, >+ &clientPath)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_SETXATTR(handle, clientPath, name, value, >+ size, flags); >+err: >+ TALLOC_FREE(clientPath); >+out: >+ return status; >+} >+ >+/* >+ * Success: return true >+ * Failure: set errno, return false >+ */ >+static bool mh_is_offline(struct vfs_handle_struct *handle, >+ const struct smb_filename *fname, >+ SMB_STRUCT_STAT *sbuf) >+{ >+ // check if sbuf is modified further down the chain. >+ bool ret; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_is_offline\n")); >+ if (!is_in_media_files(fname->base_name)) >+ { >+ ret = SMB_VFS_NEXT_IS_OFFLINE(handle, fname, sbuf); >+ goto out; >+ } >+ >+ struct smb_filename *clientFname = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if(alloc_get_client_smb_fname(handle, ctx, >+ fname, >+ &clientFname)) >+ { >+ ret = -1; >+ goto err; >+ } >+ >+ ret = SMB_VFS_NEXT_IS_OFFLINE(handle, clientFname, sbuf); >+err: >+ TALLOC_FREE(clientFname); >+out: >+ return ret; >+} >+ >+/* >+ * Success: return 0 (?) >+ * Failure: set errno, return -1 >+ */ >+static int mh_set_offline(struct vfs_handle_struct *handle, >+ const struct smb_filename *fname) >+{ >+ int status; >+ >+ DEBUG(MH_INFO_DEBUG, ("Entering mh_set_offline\n")); >+ if (!is_in_media_files(fname->base_name)) >+ { >+ status = SMB_VFS_NEXT_SET_OFFLINE(handle, fname); >+ goto out; >+ } >+ >+ struct smb_filename *clientFname = NULL; >+ TALLOC_CTX *ctx = talloc_tos(); >+ >+ if (status = alloc_get_client_smb_fname(handle, ctx, >+ fname, >+ &clientFname)) >+ { >+ goto err; >+ } >+ >+ status = SMB_VFS_NEXT_SET_OFFLINE(handle, clientFname); >+err: >+ TALLOC_FREE(clientFname); >+out: >+ return status; >+} >+ >+/* VFS operations structure */ >+ >+static struct vfs_fn_pointers vfs_mh_fns = { >+ /* Disk operations */ >+ >+ .statvfs_fn = mh_statvfs, >+ >+ /* Directory operations */ >+ >+ .opendir_fn = mh_opendir, >+ .fdopendir_fn = mh_fdopendir, >+ .readdir_fn = mh_readdir, >+ .seekdir_fn = mh_seekdir, >+ .telldir_fn = mh_telldir, >+ .rewind_dir_fn = mh_rewinddir, >+ .mkdir_fn = mh_mkdir, >+ .rmdir_fn = mh_rmdir, >+ .closedir_fn = mh_closedir, >+ .init_search_op_fn = mh_init_search_op, >+ >+ /* File operations */ >+ >+ .open_fn = mh_open, >+ .create_file_fn = mh_create_file, >+ .rename_fn = mh_rename, >+ .stat_fn = mh_stat, >+ .lstat_fn = mh_lstat, >+ .fstat_fn = mh_fstat, >+ .unlink_fn = mh_unlink, >+ .chmod_fn = mh_chmod, >+ .chown_fn = mh_chown, >+ .lchown_fn = mh_lchown, >+ .chdir_fn = mh_chdir, >+ .ntimes_fn = mh_ntimes, >+ .symlink_fn = mh_symlink, >+ .readlink_fn = mh_readlink, >+ .link_fn = mh_link, >+ .mknod_fn = mh_mknod, >+ .realpath_fn = mh_realpath, >+ .chflags_fn = mh_chflags, >+ .streaminfo_fn = mh_streaminfo, >+ >+ /* NT ACL operations. */ >+ >+ .get_nt_acl_fn = mh_get_nt_acl, >+ >+ /* POSIX ACL operations. */ >+ >+ .chmod_acl_fn = mh_chmod_acl, >+ >+ .sys_acl_get_file_fn = mh_sys_acl_get_file, >+ .sys_acl_set_file_fn = mh_sys_acl_set_file, >+ .sys_acl_delete_def_file_fn = mh_sys_acl_delete_def_file, >+ >+ /* EA operations. */ >+ .getxattr_fn = mh_getxattr, >+ .listxattr_fn = mh_listxattr, >+ .removexattr_fn = mh_removexattr, >+ .setxattr_fn = mh_setxattr, >+ >+ /* aio operations */ >+ >+ /* offline operations */ >+ .is_offline_fn = mh_is_offline, >+ .set_offline_fn = mh_set_offline >+}; >+ >+NTSTATUS vfs_media_harmony_init(void); >+NTSTATUS vfs_media_harmony_init(void) >+{ >+ NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, >+ "media_harmony", &vfs_mh_fns); >+ if (!NT_STATUS_IS_OK(ret)) >+ { >+ goto out; >+ } >+ >+ vfs_mh_debug_level = debug_add_class("media_harmony"); >+ >+ if (vfs_mh_debug_level == -1) { >+ vfs_mh_debug_level = DBGC_VFS; >+ DEBUG(1, ("media_harmony_init: Couldn't register custom " >+ "debugging class.\n")); >+ } else { >+ DEBUG(3, ("media_harmony_init: Debug class number of " >+ "'media_harmony': %d\n", >+ vfs_mh_debug_level)); >+ } >+ >+out: >+ return ret; >+} >+ >+ >diff --git a/source3/wscript b/source3/wscript >index 46aa582..41912e4 100755 >--- a/source3/wscript >+++ b/source3/wscript >@@ -1388,7 +1388,7 @@ main() { > vfs_streams_xattr vfs_streams_depot vfs_acl_xattr vfs_acl_tdb > vfs_smb_traffic_analyzer vfs_preopen vfs_catia vfs_scannedonly > vfs_crossrename vfs_linux_xfs_sgid >- vfs_time_audit idmap_autorid''') >+ vfs_time_audit vfs_media_harmony idmap_autorid''') > > if Options.options.developer: > default_static_modules.extend(TO_LIST('pdb_ads auth_netlogond charset_weird')) >-- >1.7.9.1 >
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
Actions:
View
Attachments on
bug 8841
:
7424
|
7465
|
7518
|
7519
|
7520
|
7521