2 * $Id: media_harmony.c,v 1.1 2007/11/06 10:07:22 stuart_hc Exp $
4 * Samba VFS module supporting multiple AVID clients sharing media.
6 * Copyright (C) 2005 Philip de Nier <philipn@users.sourceforge.net>
7 * Copyright (C) 2012 Andrew Klaassen <clawsoon@yahoo.com>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 * Media Harmony is a Samba VFS module that allows multiple AVID
28 * clients to share media. Each client sees their own copy of the
29 * AVID msmMMOB.mdb and msmFMID.pmr files and Creating directories.
31 * Add this module to the vfs objects option in your Samba share
37 * vfs objects = media_harmony
40 * It is recommended that you separate out Samba shares for Mac
41 * and Windows clients, and add the following options to the shares
42 * for Windows clients (NOTE: replace @ with *):
44 * veto files = /.DS_Store/._@/.Trash@/.Spotlight@/.hidden/.hotfiles@/.vol/
45 * delete veto files = yes
47 * This prevents hidden files from Mac clients interfering with Windows
48 * clients. If you find any more problem hidden files then add them to
52 * Andrew Klaassen, 2012-03-14
53 * To prevent Avid clients from interrupting each other (via Avid's habit
54 * of launching a database refresh whenever it notices an mtime update
55 * on media directories, i.e. whenever one editor adds new material to a
56 * shared share), I've added code that causes stat information for anything
57 * directly under "Avid MediaFile/MXF" to be taken from
58 * dirname_clientaddr_clientuser if it exists. These files ~aren't~
59 * hidden, unlike the client-suffixed database files.
61 * For example, stat information for
62 * Avid MediaFiles/MXF/1
64 * Avid MediaFiles/MXF/1_192.168.1.10_dave
65 * for dave working on 192.168.1.10, but will come from
66 * Avid MediaFile/MXF/1_192.168.1.11_susan
67 * for susan working on 192.168.1.11. If those alternate
68 * directories don't exist, the user will get the actual directory's stat
69 * info. When an editor wants to force a database refresh, they update
70 * the mtime on "their" file. This will cause Avid
71 * on that client to see an updated mtime for "Avid MediaFiles/MXF/1",
72 * which will trigger an Avid database refresh just for that editor.
76 * - This module is designed to work with AVID editing applications that
77 * look in the Avid MediaFiles or OMFI MediaFiles directory for media.
78 * It is not designed to work as expected in all circumstances for
79 * general use. For example: it is possibly to open client specific
80 * files such as msmMMOB.mdb_192.168.1.10_userx even though is doesn't
81 * show up in a directory listing.
87 #include "system/filesys.h"
88 #include "smbd/smbd.h"
89 #include "../smbd/globals.h"
91 #include "../lib/tsocket/tsocket.h"
93 #define MH_INFO_DEBUG 10
94 #define MH_ERR_DEBUG 0
96 static const char* MH_MODULE_NAME = "media_harmony";
97 static const char* MDB_FILENAME = "msmMMOB.mdb";
98 static const size_t MDB_FILENAME_LEN = 11;
99 static const char* PMR_FILENAME = "msmFMID.pmr";
100 static const size_t PMR_FILENAME_LEN = 11;
101 static const char* CREATING_DIRNAME = "Creating";
102 static const size_t CREATING_DIRNAME_LEN = 8;
103 static const char* AVID_MEDIAFILES_DIRNAME = "Avid MediaFiles";
104 static const size_t AVID_MEDIAFILES_DIRNAME_LEN = 15;
105 static const char* OMFI_MEDIAFILES_DIRNAME = "OMFI MediaFiles";
106 static const size_t OMFI_MEDIAFILES_DIRNAME_LEN = 15;
107 static const char* APPLE_DOUBLE_PREFIX = "._";
108 static const size_t APPLE_DOUBLE_PREFIX_LEN = 2;
109 static const char* AVID_MXF_DIRNAME = "Avid MediaFiles/MXF";
110 static const size_t AVID_MXF_DIRNAME_LEN = 19;
112 static int vfs_mh_debug_level = DBGC_VFS;
114 /* supplements the directory list stream */
115 typedef struct mh_dirinfo_struct
121 char *clientMDBFilename;
122 char *clientPMRFilename;
123 char *clientCreatingDirname;
127 /* Add "_<ip address>_<user name>" suffix to path or filename.
130 * Failure: set errno, path NULL, return -1
132 static int alloc_append_client_suffix(vfs_handle_struct *handle,
135 DEBUG(MH_INFO_DEBUG, ("Entering with *path '%s'\n", *path));
140 raddr = tsocket_address_inet_addr_string(
141 handle->conn->sconn->remote_address, talloc_tos());
149 /* talloc_asprintf_append uses talloc_realloc, which
150 * frees original 'path' memory so we don't have to.
152 *path = talloc_asprintf_append(*path, "_%s_%s",
154 handle->conn->session_info->unix_info->sanitized_username);
157 DEBUG(MH_ERR_DEBUG, ("alloc_append_client_suffix "
163 DEBUG(MH_INFO_DEBUG, ("Leaving with *path '%s'\n", *path));
170 /* Returns True if the file or directory begins with the appledouble
173 static bool is_apple_double(const char* fname)
175 DEBUG(MH_INFO_DEBUG, ("Entering with fname '%s'\n", fname));
179 if (strncmp(APPLE_DOUBLE_PREFIX, fname, APPLE_DOUBLE_PREFIX_LEN)
184 DEBUG(MH_INFO_DEBUG, ("Leaving with ret '%s'\n",
185 ret == True ? "True" : "False"));
189 static bool starts_with_media_dir(const char* media_dirname,
190 size_t media_dirname_len, const char* path)
192 DEBUG(MH_INFO_DEBUG, ("Entering with media_dirname '%s' "
193 "path '%s'\n", media_dirname, path));
198 /* Sometimes Samba gives us "./OMFI MediaFiles". */
199 if (strncmp(path, "./", 2) == 0)
201 path_start = &path[2];
207 if (strncmp(media_dirname, path_start, media_dirname_len) == 0
210 path_start[media_dirname_len] == '\0'
212 path_start[media_dirname_len] == '/'
219 DEBUG(MH_INFO_DEBUG, ("Leaving with ret '%s'\n",
220 ret == True ? "True" : "False"));
225 * Returns True if the file or directory referenced by the path is below
226 * the AVID_MEDIAFILES_DIRNAME or OMFI_MEDIAFILES_DIRNAME directory
227 * The AVID_MEDIAFILES_DIRNAME and OMFI_MEDIAFILES_DIRNAME are assumed to
228 * be in the root directory, which is generally a safe assumption
229 * in the fixed-path world of Avid.
231 static bool is_in_media_files(const char* path)
233 DEBUG(MH_INFO_DEBUG, ("Entering with path '%s'\n", path));
238 starts_with_media_dir(AVID_MEDIAFILES_DIRNAME,
239 AVID_MEDIAFILES_DIRNAME_LEN, path)
241 starts_with_media_dir(OMFI_MEDIAFILES_DIRNAME,
242 OMFI_MEDIAFILES_DIRNAME_LEN, path)
247 DEBUG(MH_INFO_DEBUG, ("Leaving with ret '%s'\n",
248 ret == True ? "True" : "False"));
253 * Returns depth of path under media directory. Deals with the
254 * occasional ..../. and ..../.. paths that get passed to stat.
256 * Assumes is_in_media_files has already been called and has returned
257 * true for the path; if it hasn't, this function will likely crash
260 * Not foolproof; something like "Avid MediaFiles/MXF/../foo/1"
261 * would fool it. Haven't seen paths like that getting to the
262 * stat function yet, so ignoring that possibility for now.
264 static int depth_from_media_dir(const char* media_dirname,
265 size_t media_dirname_len, const char* path)
267 DEBUG(MH_INFO_DEBUG, ("Entering with media_dirname '%s' "
268 "path '%s'\n", media_dirname, path));
269 int transition_count = 0;
273 /* Sometimes Samba gives us "./OMFI MediaFiles". */
274 if (strncmp(path, "./", 2) == 0)
276 path_start = &path[2];
282 if (path_start[media_dirname_len] == '\0')
287 pathPtr = &path_start[media_dirname_len + 1];
291 if (*pathPtr == '\0' || *pathPtr == '/')
294 *(pathPtr - 1) == '.'
296 *(pathPtr - 2) == '.'
298 *(pathPtr - 3) == '/'
306 *(pathPtr - 1) == '/'
309 *(pathPtr - 1) == '.'
311 *(pathPtr - 2) == '/'
319 if (*pathPtr == '\0')
326 DEBUG(MH_INFO_DEBUG, ("Leaving with transition_count '%i'\n",
329 return transition_count;
332 /* Identifies MDB and PMR files at end of path. */
333 static bool is_avid_database(
336 const char *avid_db_filename,
337 const size_t avid_db_filename_len)
339 DEBUG(MH_INFO_DEBUG, ("Entering with path '%s', "
340 "avid_db_filename '%s', "
342 "avid_db_filename_len '%i'\n",
343 path, avid_db_filename,
344 path_len, avid_db_filename_len));
349 path_len > avid_db_filename_len
351 strcmp(&path[path_len - avid_db_filename_len],
352 avid_db_filename) == 0
355 path[path_len - avid_db_filename_len - 1] == '/'
357 path_len > avid_db_filename_len
358 + APPLE_DOUBLE_PREFIX_LEN
360 path[path_len - avid_db_filename_len
361 - APPLE_DOUBLE_PREFIX_LEN - 1] == '/'
363 is_apple_double(&path[path_len
364 - avid_db_filename_len
365 - APPLE_DOUBLE_PREFIX_LEN])
371 DEBUG(MH_INFO_DEBUG, ("Leaving with ret '%s'\n",
372 ret == True ? "True" : "False"));
377 /* Add client suffix to paths to MDB_FILENAME, PMR_FILENAME and
378 * CREATING_SUBDIRNAME.
380 * Caller must free newPath.
383 * Failure: set errno, newPath NULL, return -1
385 static int alloc_get_client_path(vfs_handle_struct *handle,
390 DEBUG(MH_INFO_DEBUG, ("Entering with path '%s'\n", path));
392 /* replace /CREATING_DIRNAME/ or /._CREATING_DIRNAME/
393 * directory in path - potentially in middle of path
394 * - with suffixed name.
398 *newPath = talloc_strdup(ctx, path);
399 if (*newPath == NULL)
401 DEBUG(MH_ERR_DEBUG, ("alloc_get_client_path ENOMEM #1\n"));
406 DEBUG(MH_INFO_DEBUG, ("newPath #1 %s\n", *newPath));
408 (pathPtr = strstr(path, CREATING_DIRNAME)) != NULL
411 *(pathPtr + CREATING_DIRNAME_LEN) == '\0'
413 *(pathPtr + CREATING_DIRNAME_LEN) == '/'
419 *(pathPtr - 1) == '/'
421 pathPtr - path > APPLE_DOUBLE_PREFIX_LEN
423 *(pathPtr - APPLE_DOUBLE_PREFIX_LEN - 1) == '/'
425 is_apple_double(pathPtr - APPLE_DOUBLE_PREFIX_LEN)
429 /* Insert client suffix into path. */
430 (*newPath)[pathPtr - path + CREATING_DIRNAME_LEN] = '\0';
431 DEBUG(MH_INFO_DEBUG, ("newPath #2 %s\n", *newPath));
433 if (status = alloc_append_client_suffix(handle, newPath))
438 DEBUG(MH_INFO_DEBUG, ("newPath #3 %s\n", *newPath));
439 *newPath = talloc_strdup_append(*newPath,
440 pathPtr + CREATING_DIRNAME_LEN);
441 if (*newPath == NULL)
443 DEBUG(MH_ERR_DEBUG, ("alloc_get_client_path "
449 DEBUG(MH_INFO_DEBUG, ("newPath #4 %s\n", *newPath));
452 /* replace /MDB_FILENAME or /PMR_FILENAME or /._MDB_FILENAME
453 * or /._PMR_FILENAME at newPath end with suffixed name.
455 size_t intermPathLen = strlen(*newPath);
457 is_avid_database(*newPath, intermPathLen,
458 MDB_FILENAME, MDB_FILENAME_LEN)
460 is_avid_database(*newPath, intermPathLen,
461 PMR_FILENAME, PMR_FILENAME_LEN)
464 DEBUG(MH_INFO_DEBUG, ("newPath #5 %s\n", *newPath));
465 if (status = alloc_append_client_suffix(handle, newPath))
469 DEBUG(MH_INFO_DEBUG, ("newPath #6 %s\n", *newPath));
472 /* newPath must be freed in caller. */
473 DEBUG(MH_INFO_DEBUG, ("Leaving with *newPath '%s'\n", *newPath));
479 * Failure: set errno, return -1
481 static int alloc_get_client_smb_fname(struct vfs_handle_struct *handle,
483 const struct smb_filename *smb_fname,
484 struct smb_filename **clientFname)
486 DEBUG(MH_INFO_DEBUG, ("Entering with smb_fname->base_name '%s'\n",
487 smb_fname->base_name));
492 copystatus = copy_smb_filename(ctx, smb_fname, clientFname);
493 if (!NT_STATUS_IS_OK(copystatus))
495 DEBUG(MH_ERR_DEBUG, ("alloc_get_client_smb_fname "
497 errno = map_errno_from_nt_status(copystatus);
501 if (status = alloc_get_client_path(handle, ctx,
502 smb_fname->base_name,
503 &(*clientFname)->base_name))
507 DEBUG(MH_INFO_DEBUG, ("Leaving with (*clientFname)->base_name "
508 "'%s'\n", (*clientFname)->base_name));
516 * Failure: set errno, return -1
518 static int alloc_set_client_dirinfo_path(struct vfs_handle_struct *handle,
521 const char *avid_db_filename)
523 DEBUG(MH_INFO_DEBUG, ("Entering with avid_db_filename '%s'\n",
528 if ((*path = talloc_strdup(ctx, avid_db_filename)) == NULL)
530 DEBUG(MH_ERR_DEBUG, ("alloc_set_client_dirinfo_path "
536 if (status = alloc_append_client_suffix(handle, path))
540 DEBUG(MH_INFO_DEBUG, ("Leaving with *path '%s'\n", *path));
546 * Replace mtime on clientFname with mtime from client-suffixed
547 * equivalent, if it exists.
550 * Failure: set errno, return -1
552 static int set_fake_mtime(vfs_handle_struct *handle,
554 struct smb_filename **clientFname,
555 int (*statFn)(const char *, SMB_STRUCT_STAT *, bool))
557 DEBUG(MH_INFO_DEBUG, ("Entering with (*clientFname)->base_name "
558 "'%s', (*clientFname)->st.st_ex_mtime %s",
559 (*clientFname)->base_name,
560 ctime(&((*clientFname)->st.st_ex_mtime.tv_sec))));
565 depth_from_media_dir(AVID_MXF_DIRNAME,
566 AVID_MXF_DIRNAME_LEN,
567 (*clientFname)->base_name)
570 depth_from_media_dir(OMFI_MEDIAFILES_DIRNAME,
571 OMFI_MEDIAFILES_DIRNAME_LEN,
572 (*clientFname)->base_name)
580 SMB_STRUCT_STAT fakeStat;
581 int copy_len = strlen((*clientFname)->base_name);
583 /* Hack to deal with occasional "Avid MediaFiles/MXF/1/." paths.
584 * We know we're under a media dir, so paths are at least 2 chars
587 if ((*clientFname)->base_name[copy_len - 1] == '.' &&
588 (*clientFname)->base_name[copy_len - 2] == '/')
593 if ((statPath = talloc_strndup(ctx,
594 (*clientFname)->base_name, copy_len)) == NULL)
600 if (status = alloc_append_client_suffix(handle, &statPath))
605 DEBUG(MH_INFO_DEBUG, ("Fake stat'ing '%s'\n", statPath));
606 if (statFn(statPath, &fakeStat,
607 lp_fake_dir_create_times(SNUM(handle->conn))))
609 /* This can fail for legitimate reasons - i.e. the
610 * fakeStat directory doesn't exist, which is okay
611 * - so we don't set status. But if it does fail,
612 * we need to skip over the mtime assignment.
617 DEBUG(MH_INFO_DEBUG, ("Setting fake mtime from '%s'\n", statPath));
618 (*clientFname)->st.st_ex_mtime = fakeStat.st_ex_mtime;
620 TALLOC_FREE(statPath);
622 DEBUG(MH_INFO_DEBUG, ("Leaving with (*clientFname)->base_name "
623 "'%s', (*clientFname)->st.st_ex_mtime %s",
624 (*clientFname)->base_name,
625 ctime(&((*clientFname)->st.st_ex_mtime.tv_sec))));
631 * Failure: set errno, return -1
633 static int mh_statvfs(struct vfs_handle_struct *handle,
635 struct vfs_statvfs_struct *statbuf)
637 DEBUG(MH_INFO_DEBUG, ("Entering with path '%s'\n", path));
641 if (!is_in_media_files(path))
643 status = SMB_VFS_NEXT_STATVFS(handle, path, statbuf);
647 char *clientPath = NULL;
648 TALLOC_CTX *ctx = talloc_tos();
650 if (status = alloc_get_client_path(handle, ctx,
657 status = SMB_VFS_NEXT_STATVFS(handle, clientPath, statbuf);
659 TALLOC_FREE(clientPath);
661 DEBUG(MH_INFO_DEBUG, ("Leaving with path '%s'\n", path));
665 static int alloc_set_client_dirinfo(vfs_handle_struct *handle,
667 struct mh_dirinfo_struct **dirInfo)
669 DEBUG(MH_INFO_DEBUG, ("Entering with fname '%s'\n", fname));
673 *dirInfo = talloc(NULL, struct mh_dirinfo_struct);
674 if (*dirInfo == NULL)
679 (*dirInfo)->dirpath = talloc_strdup(*dirInfo, fname);
680 if ((*dirInfo)->dirpath == NULL)
685 if (!is_in_media_files(fname))
687 (*dirInfo)->clientPath = NULL;
688 (*dirInfo)->clientMDBFilename = NULL;
689 (*dirInfo)->clientPMRFilename = NULL;
690 (*dirInfo)->clientCreatingDirname = NULL;
691 (*dirInfo)->isInMediaFiles = False;
695 (*dirInfo)->isInMediaFiles = True;
697 if (alloc_set_client_dirinfo_path(handle,
699 &((*dirInfo)->clientMDBFilename),
705 if (alloc_set_client_dirinfo_path(handle,
707 &((*dirInfo)->clientPMRFilename),
713 if (alloc_set_client_dirinfo_path(handle,
715 &((*dirInfo)->clientCreatingDirname),
721 char *clientPath = NULL;
722 TALLOC_CTX *ctx = talloc_tos();
724 if (alloc_get_client_path(handle, ctx,
731 (*dirInfo)->clientPath = talloc_strdup(*dirInfo, clientPath);
732 if ((*dirInfo)->clientPath == NULL)
737 TALLOC_FREE(clientPath);
740 DEBUG(MH_INFO_DEBUG, ("Leaving with (*dirInfo)->dirpath '%s', "
741 "(*dirInfo)->clientPath '%s'\n",
743 (*dirInfo)->clientPath));
747 DEBUG(MH_ERR_DEBUG, ("Failing with fname '%s'\n", fname));
748 TALLOC_FREE(*dirInfo);
754 /* Success: return a mh_dirinfo_struct cast as a DIR
755 * Failure: set errno, return NULL
757 static DIR *mh_opendir(vfs_handle_struct *handle,
762 DEBUG(MH_INFO_DEBUG, ("Entering with fname '%s'\n", fname));
764 struct mh_dirinfo_struct *dirInfo;
766 if (alloc_set_client_dirinfo(handle, fname, &dirInfo))
771 if (!dirInfo->isInMediaFiles)
773 dirInfo->dirstream = SMB_VFS_NEXT_OPENDIR(handle,
776 dirInfo->dirstream = SMB_VFS_NEXT_OPENDIR(handle,
777 dirInfo->clientPath, mask, attr);
780 if (dirInfo->dirstream == NULL) {
785 /* Success is freed in closedir. */
786 DEBUG(MH_INFO_DEBUG, ("Leaving with dirInfo->dirpath '%s', "
787 "dirInfo->clientPath '%s'\n",
789 dirInfo->clientPath));
790 return (DIR*)dirInfo;
792 /* Failure is freed here. */
793 DEBUG(MH_ERR_DEBUG, ("Failing with fname '%s'\n", fname));
794 TALLOC_FREE(dirInfo);
798 static DIR *mh_fdopendir(vfs_handle_struct *handle,
803 DEBUG(MH_INFO_DEBUG, ("Entering with fsp->fsp_name->base_name '%s'\n",
804 fsp->fsp_name->base_name));
806 struct mh_dirinfo_struct *dirInfo;
809 dirstream = SMB_VFS_NEXT_FDOPENDIR(handle, fsp, mask, attr);
815 if (alloc_set_client_dirinfo(handle, fsp->fsp_name->base_name,
821 dirInfo->dirstream = dirstream;
823 if (! dirInfo->isInMediaFiles) {
827 if (set_fake_mtime(handle, fsp, &(fsp->fsp_name), sys_stat))
833 DEBUG(MH_INFO_DEBUG, ("Leaving with dirInfo->dirpath '%s', "
834 "dirInfo->clientPath '%s', "
835 "fsp->fsp_name->st.st_ex_mtime %s",
838 ctime(&(fsp->fsp_name->st.st_ex_mtime.tv_sec))));
839 /* Success is freed in closedir. */
840 return (DIR *) dirInfo;
842 /* Failure is freed here. */
843 DEBUG(MH_ERR_DEBUG, ("Failing with fsp->fsp_name->base_name '%s'\n",
844 fsp->fsp_name->base_name));
845 TALLOC_FREE(dirInfo);
850 * skip MDB_FILENAME and PMR_FILENAME filenames and CREATING_DIRNAME
851 * directory, skip other client's suffixed MDB_FILENAME and PMR_FILENAME
852 * filenames and CREATING_DIRNAME directory, replace this client's
853 * suffixed MDB_FILENAME and PMR_FILENAME filenames and CREATING_DIRNAME
854 * directory with non suffixed.
856 * Success: return dirent
857 * End of data: return NULL
858 * Failure: set errno, return NULL
860 static struct dirent *mh_readdir(vfs_handle_struct *handle,
862 SMB_STRUCT_STAT *sbuf)
864 DEBUG(MH_INFO_DEBUG, ("Entering mh_readdir\n"));
866 mh_dirinfo_struct* dirInfo = (mh_dirinfo_struct*)dirp;
868 DEBUG(MH_INFO_DEBUG, ("dirInfo->dirpath '%s', "
869 "dirInfo->clientPath '%s', "
870 "dirInfo->isInMediaFiles '%s', "
871 "dirInfo->clientMDBFilename '%s', "
872 "dirInfo->clientPMRFilename '%s', "
873 "dirInfo->clientCreatingDirname '%s'\n",
876 dirInfo->isInMediaFiles ? "True" : "False",
877 dirInfo->clientMDBFilename,
878 dirInfo->clientPMRFilename,
879 dirInfo->clientCreatingDirname));
881 struct dirent *d = NULL;
883 if (! dirInfo->isInMediaFiles)
885 d = SMB_VFS_NEXT_READDIR(handle, dirInfo->dirstream, sbuf);
893 d = SMB_VFS_NEXT_READDIR(handle, dirInfo->dirstream, sbuf);
903 /* ignore apple double prefix for logic below */
904 if (is_apple_double(d->d_name))
906 dname = &d->d_name[APPLE_DOUBLE_PREFIX_LEN];
907 isAppleDouble = True;
912 isAppleDouble = False;
915 /* skip Avid-special files with no client suffix */
917 strcmp(dname, MDB_FILENAME) == 0
919 strcmp(dname, PMR_FILENAME) == 0
921 strcmp(dname, CREATING_DIRNAME) == 0
926 /* chop client suffix off this client's suffixed files */
927 else if (strcmp(dname, dirInfo->clientMDBFilename) == 0)
931 d->d_name[MDB_FILENAME_LEN
932 + APPLE_DOUBLE_PREFIX_LEN] = '\0';
936 d->d_name[MDB_FILENAME_LEN] = '\0';
939 else if (strcmp(dname, dirInfo->clientPMRFilename) == 0)
943 d->d_name[PMR_FILENAME_LEN
944 + APPLE_DOUBLE_PREFIX_LEN] = '\0';
948 d->d_name[PMR_FILENAME_LEN] = '\0';
951 else if (strcmp(dname, dirInfo->clientCreatingDirname)
956 d->d_name[CREATING_DIRNAME_LEN
957 + APPLE_DOUBLE_PREFIX_LEN] = '\0';
961 d->d_name[CREATING_DIRNAME_LEN] = '\0';
965 * Anything that starts as an Avid-special file
966 * that's made it this far should be skipped. This
967 * is different from the original behaviour, which
968 * only skipped other client's suffixed files.
971 strncmp(MDB_FILENAME, dname,
972 MDB_FILENAME_LEN) == 0
974 strncmp(PMR_FILENAME, dname,
975 PMR_FILENAME_LEN) == 0
977 strncmp(CREATING_DIRNAME, dname,
978 CREATING_DIRNAME_LEN) == 0
987 DEBUG(MH_INFO_DEBUG, ("Leaving mh_readdir\n"));
992 * Success: no success result defined.
993 * Failure: no failure result defined.
995 static void mh_seekdir(vfs_handle_struct *handle,
999 DEBUG(MH_INFO_DEBUG, ("Entering and leaving mh_seekdir\n"));
1000 SMB_VFS_NEXT_SEEKDIR(handle,
1001 ((mh_dirinfo_struct*)dirp)->dirstream, offset);
1006 * Success: return long
1007 * Failure: no failure result defined.
1009 static long mh_telldir(vfs_handle_struct *handle,
1012 DEBUG(MH_INFO_DEBUG, ("Entering and leaving mh_telldir\n"));
1013 return SMB_VFS_NEXT_TELLDIR(handle,
1014 ((mh_dirinfo_struct*)dirp)->dirstream);
1018 * Success: no success result defined.
1019 * Failure: no failure result defined.
1021 static void mh_rewinddir(vfs_handle_struct *handle,
1024 DEBUG(MH_INFO_DEBUG, ("Entering and leaving mh_rewinddir\n"));
1025 SMB_VFS_NEXT_REWINDDIR(handle,
1026 ((mh_dirinfo_struct*)dirp)->dirstream);
1032 * Failure: set errno, return -1
1034 static int mh_mkdir(vfs_handle_struct *handle,
1038 DEBUG(MH_INFO_DEBUG, ("Entering with path '%s'\n", path));
1042 if (!is_in_media_files(path))
1044 status = SMB_VFS_NEXT_MKDIR(handle, path, mode);
1048 char *clientPath = NULL;
1049 TALLOC_CTX *ctx = talloc_tos();
1051 if (status = alloc_get_client_path(handle, ctx,
1058 status = SMB_VFS_NEXT_MKDIR(handle, clientPath, mode);
1060 TALLOC_FREE(clientPath);
1062 DEBUG(MH_INFO_DEBUG, ("Leaving with path '%s'\n", path));
1068 * Failure: set errno, return -1
1070 static int mh_rmdir(vfs_handle_struct *handle,
1073 DEBUG(MH_INFO_DEBUG, ("Entering with path '%s'\n", path));
1077 if (!is_in_media_files(path))
1079 status = SMB_VFS_NEXT_RMDIR(handle, path);
1083 char *clientPath = NULL;
1084 TALLOC_CTX *ctx = talloc_tos();
1086 if (status = alloc_get_client_path(handle, ctx,
1093 status = SMB_VFS_NEXT_RMDIR(handle, clientPath);
1095 TALLOC_FREE(clientPath);
1097 DEBUG(MH_INFO_DEBUG, ("Leaving with path '%s'\n", path));
1103 * Failure: set errno, return -1
1105 static int mh_closedir(vfs_handle_struct *handle,
1108 DEBUG(MH_INFO_DEBUG, ("Entering mh_closedir\n"));
1109 DIR *realdirp = ((mh_dirinfo_struct*)dirp)->dirstream;
1110 // Will this talloc_free destroy realdirp?
1113 DEBUG(MH_INFO_DEBUG, ("Leaving mh_closedir\n"));
1114 return SMB_VFS_NEXT_CLOSEDIR(handle, realdirp);
1118 * Success: no success result defined.
1119 * Failure: no failure result defined.
1121 static void mh_init_search_op(vfs_handle_struct *handle,
1124 DEBUG(MH_INFO_DEBUG, ("Entering and leaving mh_init_search_op\n"));
1125 SMB_VFS_NEXT_INIT_SEARCH_OP(handle,
1126 ((mh_dirinfo_struct*)dirp)->dirstream);
1131 * Success: return non-negative file descriptor
1132 * Failure: set errno, return -1
1134 static int mh_open(vfs_handle_struct *handle,
1135 struct smb_filename *smb_fname,
1140 DEBUG(MH_INFO_DEBUG, ("Entering with smb_fname->base_name '%s'\n",
1141 smb_fname->base_name));
1145 if (!is_in_media_files(smb_fname->base_name))
1147 ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags,
1152 struct smb_filename *clientFname = NULL;
1153 TALLOC_CTX *ctx = talloc_tos();
1155 if(alloc_get_client_smb_fname(handle, ctx,
1163 // What about fsp->fsp_name?
1164 // We also have to get correct stat info into fsp and smb_fname
1165 // for DB files, don't we?
1167 DEBUG(MH_INFO_DEBUG, ("Leaving with smb_fname->base_name '%s' "
1168 "smb_fname->st.st_ex_mtime %s"
1169 " fsp->fsp_name->st.st_ex_mtime %s",
1170 smb_fname->base_name,
1171 ctime(&(smb_fname->st.st_ex_mtime.tv_sec)),
1172 ctime(&(fsp->fsp_name->st.st_ex_mtime.tv_sec))));
1174 ret = SMB_VFS_NEXT_OPEN(handle, clientFname, fsp, flags, mode);
1176 TALLOC_FREE(clientFname);
1178 DEBUG(MH_INFO_DEBUG, ("Leaving with smb_fname->base_name '%s'\n",
1179 smb_fname->base_name));
1184 * Success: return non-negative file descriptor
1185 * Failure: set errno, return -1
1187 static NTSTATUS mh_create_file(vfs_handle_struct *handle,
1188 struct smb_request *req,
1189 uint16_t root_dir_fid,
1190 struct smb_filename *smb_fname,
1191 uint32_t access_mask,
1192 uint32_t share_access,
1193 uint32_t create_disposition,
1194 uint32_t create_options,
1195 uint32_t file_attributes,
1196 uint32_t oplock_request,
1197 uint64_t allocation_size,
1198 uint32_t private_flags,
1199 struct security_descriptor *sd,
1200 struct ea_list *ea_list,
1201 files_struct **result_fsp,
1206 DEBUG(MH_INFO_DEBUG, ("Entering with smb_fname->base_name '%s'\n",
1207 smb_fname->base_name));
1208 if (!is_in_media_files(smb_fname->base_name))
1210 status = SMB_VFS_NEXT_CREATE_FILE(
1230 struct smb_filename *clientFname = NULL;
1231 TALLOC_CTX *ctx = talloc_tos();
1233 if (alloc_get_client_smb_fname(handle, ctx,
1237 status = map_nt_error_from_unix(errno);
1241 /* This only creates files, so we don't have to worry about
1242 * our fake directory stat'ing here.
1244 // But we still need to route stat calls for DB files
1246 status = SMB_VFS_NEXT_CREATE_FILE(
1264 TALLOC_FREE(clientFname);
1266 DEBUG(MH_INFO_DEBUG, ("Leaving with smb_fname->base_name '%s'"
1267 "smb_fname->st.st_ex_mtime %s"
1268 " fsp->fsp_name->st.st_ex_mtime %s",
1269 smb_fname->base_name,
1270 ctime(&(smb_fname->st.st_ex_mtime.tv_sec)),
1271 (*result_fsp) && VALID_STAT((*result_fsp)->fsp_name->st) ?
1272 ctime(&((*result_fsp)->fsp_name->st.st_ex_mtime.tv_sec)) :
1279 * Failure: set errno, return -1
1281 static int mh_rename(vfs_handle_struct *handle,
1282 const struct smb_filename *smb_fname_src,
1283 const struct smb_filename *smb_fname_dst)
1285 DEBUG(MH_INFO_DEBUG, ("Entering with "
1286 "smb_fname_src->base_name '%s', "
1287 "smb_fname_dst->base_name '%s'\n",
1288 smb_fname_src->base_name,
1289 smb_fname_dst->base_name));
1293 if (!is_in_media_files(smb_fname_src->base_name)
1295 !is_in_media_files(smb_fname_dst->base_name))
1297 status = SMB_VFS_NEXT_RENAME(handle, smb_fname_src,
1302 struct smb_filename *srcClientFname = NULL;
1303 struct smb_filename *dstClientFname = NULL;
1304 TALLOC_CTX *ctx = talloc_tos();
1306 if (status = alloc_get_client_smb_fname(handle, ctx,
1313 if (status = alloc_get_client_smb_fname(handle, ctx,
1320 status = SMB_VFS_NEXT_RENAME(handle, srcClientFname,
1323 TALLOC_FREE(dstClientFname);
1324 TALLOC_FREE(srcClientFname);
1326 DEBUG(MH_INFO_DEBUG, ("Leaving with smb_fname_src->base_name '%s',"
1327 " smb_fname_dst->base_name '%s'\n",
1328 smb_fname_src->base_name,
1329 smb_fname_dst->base_name));
1335 * Failure: set errno, return -1
1337 static int mh_stat(vfs_handle_struct *handle,
1338 struct smb_filename *smb_fname)
1340 DEBUG(MH_INFO_DEBUG, ("Entering with smb_fname->base_name '%s'\n",
1341 smb_fname->base_name));
1345 if (!is_in_media_files(smb_fname->base_name))
1347 status = SMB_VFS_NEXT_STAT(handle, smb_fname);
1351 struct smb_filename *clientFname = NULL;
1352 TALLOC_CTX *ctx = talloc_tos();
1354 if (status = alloc_get_client_smb_fname(handle, ctx,
1360 DEBUG(MH_INFO_DEBUG, ("Stat'ing clientFname->base_name '%s'\n",
1361 clientFname->base_name));
1362 if (status = SMB_VFS_NEXT_STAT(handle, clientFname))
1366 if (status = set_fake_mtime(handle, ctx, &clientFname, sys_stat))
1371 /* Unlike functions with const smb_filename, we have to
1372 * modify smb_fname itself to pass our info back up.
1374 DEBUG(MH_INFO_DEBUG, ("Setting smb_fname '%s' stat "
1375 "from clientFname '%s'\n",
1376 smb_fname->base_name,
1377 clientFname->base_name));
1378 smb_fname->st = clientFname->st;
1380 TALLOC_FREE(clientFname);
1382 DEBUG(MH_INFO_DEBUG, ("Leaving with smb_fname->st.st_ex_mtime %s",
1383 ctime(&(smb_fname->st.st_ex_mtime.tv_sec))));
1389 * Failure: set errno, return -1
1391 static int mh_lstat(vfs_handle_struct *handle,
1392 struct smb_filename *smb_fname)
1394 DEBUG(MH_INFO_DEBUG, ("Entering with smb_fname->base_name '%s'\n",
1395 smb_fname->base_name));
1399 if (!is_in_media_files(smb_fname->base_name))
1401 status = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
1405 struct smb_filename *clientFname = NULL;
1406 TALLOC_CTX *ctx = talloc_tos();
1408 if (status = alloc_get_client_smb_fname(handle, ctx,
1414 if (status = SMB_VFS_NEXT_LSTAT(handle, clientFname))
1419 if (status = set_fake_mtime(handle, ctx, &clientFname, sys_lstat))
1423 /* Unlike functions with const smb_filename, we have to
1424 * modify smb_fname itself to pass our info back up.
1426 smb_fname->st = clientFname->st;
1428 TALLOC_FREE(clientFname);
1430 DEBUG(MH_INFO_DEBUG, ("Leaving with smb_fname->st.st_ex_mtime %s",
1431 ctime(&(smb_fname->st.st_ex_mtime.tv_sec))));
1437 * Failure: set errno, return -1
1439 static int mh_fstat(vfs_handle_struct *handle,
1440 files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1442 DEBUG(MH_INFO_DEBUG, ("Entering with fsp->fsp_name->base_name "
1443 "'%s'\n", fsp_str_dbg(fsp)));
1447 if (status = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf))
1452 if (fsp->fsp_name == NULL
1453 || !is_in_media_files(fsp->fsp_name->base_name))
1458 if (status = mh_stat(handle, fsp->fsp_name))
1463 *sbuf = fsp->fsp_name->st;
1465 DEBUG(MH_INFO_DEBUG, ("Leaving with fsp->fsp_name->st.st_ex_mtime "
1467 ctime(&(fsp->fsp_name->st.st_ex_mtime.tv_sec))));
1473 * Failure: set errno, return -1
1475 static int mh_unlink(vfs_handle_struct *handle,
1476 const struct smb_filename *smb_fname)
1480 DEBUG(MH_INFO_DEBUG, ("Entering mh_unlink\n"));
1481 if (!is_in_media_files(smb_fname->base_name))
1483 status = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
1487 struct smb_filename *clientFname = NULL;
1488 TALLOC_CTX *ctx = talloc_tos();
1490 if (status = alloc_get_client_smb_fname(handle, ctx,
1497 status = SMB_VFS_NEXT_UNLINK(handle, clientFname);
1499 TALLOC_FREE(clientFname);
1506 * Failure: set errno, return -1
1508 static int mh_chmod(vfs_handle_struct *handle,
1514 DEBUG(MH_INFO_DEBUG, ("Entering mh_chmod\n"));
1515 if (!is_in_media_files(path))
1517 status = SMB_VFS_NEXT_CHMOD(handle, path, mode);
1521 char *clientPath = NULL;
1522 TALLOC_CTX *ctx = talloc_tos();
1524 if (status = alloc_get_client_path(handle, ctx,
1531 status = SMB_VFS_NEXT_CHMOD(handle, clientPath, mode);
1533 TALLOC_FREE(clientPath);
1540 * Failure: set errno, return -1
1542 static int mh_chown(vfs_handle_struct *handle,
1549 DEBUG(MH_INFO_DEBUG, ("Entering mh_chown\n"));
1550 if (!is_in_media_files(path))
1552 status = SMB_VFS_NEXT_CHOWN(handle, path, uid, gid);
1556 char *clientPath = NULL;
1557 TALLOC_CTX *ctx = talloc_tos();
1559 if (status = alloc_get_client_path(handle, ctx,
1566 status = SMB_VFS_NEXT_CHOWN(handle, clientPath, uid, gid);
1568 TALLOC_FREE(clientPath);
1575 * Failure: set errno, return -1
1577 static int mh_lchown(vfs_handle_struct *handle,
1584 DEBUG(MH_INFO_DEBUG, ("Entering mh_lchown\n"));
1585 if (!is_in_media_files(path))
1587 status = SMB_VFS_NEXT_LCHOWN(handle, path, uid, gid);
1591 char *clientPath = NULL;
1592 TALLOC_CTX *ctx = talloc_tos();
1594 if (status = alloc_get_client_path(handle, ctx,
1601 status = SMB_VFS_NEXT_LCHOWN(handle, clientPath, uid, gid);
1603 TALLOC_FREE(clientPath);
1610 * Failure: set errno, return -1
1612 static int mh_chdir(vfs_handle_struct *handle,
1617 DEBUG(MH_INFO_DEBUG, ("Entering mh_chdir\n"));
1618 if (!is_in_media_files(path))
1620 status = SMB_VFS_NEXT_CHDIR(handle, path);
1624 char *clientPath = NULL;
1625 TALLOC_CTX *ctx = talloc_tos();
1627 if (status = alloc_get_client_path(handle, ctx,
1634 status = SMB_VFS_NEXT_CHDIR(handle, clientPath);
1636 TALLOC_FREE(clientPath);
1643 * Failure: set errno, return -1
1645 static int mh_ntimes(vfs_handle_struct *handle,
1646 const struct smb_filename *smb_fname,
1647 struct smb_file_time *ft)
1651 DEBUG(MH_INFO_DEBUG, ("Entering mh_ntimes\n"));
1652 if (!is_in_media_files(smb_fname->base_name))
1654 status = SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft);
1658 struct smb_filename *clientFname = NULL;
1659 TALLOC_CTX *ctx = talloc_tos();
1661 if (status = alloc_get_client_smb_fname(handle, ctx,
1668 status = SMB_VFS_NEXT_NTIMES(handle, clientFname, ft);
1670 TALLOC_FREE(clientFname);
1677 * Failure: set errno, return -1
1679 static int mh_symlink(vfs_handle_struct *handle,
1680 const char *oldpath,
1681 const char *newpath)
1685 DEBUG(MH_INFO_DEBUG, ("Entering mh_symlink\n"));
1686 if (!is_in_media_files(oldpath) && !is_in_media_files(newpath))
1688 status = SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath);
1692 char *oldClientPath = NULL;
1693 char *newClientPath = NULL;
1694 TALLOC_CTX *ctx = talloc_tos();
1696 if (status = alloc_get_client_path(handle, ctx,
1703 if (status = alloc_get_client_path(handle, ctx,
1710 status = SMB_VFS_NEXT_SYMLINK(handle,
1715 TALLOC_FREE(newClientPath);
1716 TALLOC_FREE(oldClientPath);
1722 * Success: return byte count
1723 * Failure: set errno, return -1
1725 static int mh_readlink(vfs_handle_struct *handle,
1732 DEBUG(MH_INFO_DEBUG, ("Entering mh_readlink\n"));
1733 if (!is_in_media_files(path))
1735 status = SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz);
1739 char *clientPath = NULL;
1740 TALLOC_CTX *ctx = talloc_tos();
1742 if (status = alloc_get_client_path(handle, ctx,
1749 status = SMB_VFS_NEXT_READLINK(handle, clientPath, buf, bufsiz);
1751 TALLOC_FREE(clientPath);
1758 * Failure: set errno, return -1
1760 static int mh_link(vfs_handle_struct *handle,
1761 const char *oldpath,
1762 const char *newpath)
1766 DEBUG(MH_INFO_DEBUG, ("Entering mh_link\n"));
1767 if (!is_in_media_files(oldpath) && !is_in_media_files(newpath))
1769 status = SMB_VFS_NEXT_LINK(handle, oldpath, newpath);
1773 char *oldClientPath = NULL;
1774 char *newClientPath = NULL;
1775 TALLOC_CTX *ctx = talloc_tos();
1777 if (status = alloc_get_client_path(handle, ctx,
1784 if (status = alloc_get_client_path(handle, ctx,
1791 status = SMB_VFS_NEXT_LINK(handle, oldClientPath, newClientPath);
1793 TALLOC_FREE(newClientPath);
1794 TALLOC_FREE(oldClientPath);
1801 * Failure: set errno, return -1
1803 static int mh_mknod(vfs_handle_struct *handle,
1804 const char *pathname,
1810 DEBUG(MH_INFO_DEBUG, ("Entering mh_mknod\n"));
1811 if (!is_in_media_files(pathname))
1813 status = SMB_VFS_NEXT_MKNOD(handle, pathname, mode, dev);
1817 char *clientPath = NULL;
1818 TALLOC_CTX *ctx = talloc_tos();
1820 if (status = alloc_get_client_path(handle, ctx,
1827 status = SMB_VFS_NEXT_MKNOD(handle, clientPath, mode, dev);
1829 TALLOC_FREE(clientPath);
1835 * Success: return path pointer
1836 * Failure: set errno, return NULL pointer
1838 static char *mh_realpath(vfs_handle_struct *handle,
1843 DEBUG(MH_INFO_DEBUG, ("Entering mh_realpath\n"));
1844 if (!is_in_media_files(path))
1846 buf = SMB_VFS_NEXT_REALPATH(handle, path);
1850 char *clientPath = NULL;
1851 TALLOC_CTX *ctx = talloc_tos();
1853 if (alloc_get_client_path(handle, ctx,
1861 buf = SMB_VFS_NEXT_REALPATH(handle, clientPath);
1863 TALLOC_FREE(clientPath);
1870 * Failure: set errno, return -1
1872 static int mh_chflags(vfs_handle_struct *handle,
1878 DEBUG(MH_INFO_DEBUG, ("Entering mh_chflags\n"));
1879 if (!is_in_media_files(path))
1881 status = SMB_VFS_NEXT_CHFLAGS(handle, path, flags);
1885 char *clientPath = NULL;
1886 TALLOC_CTX *ctx = talloc_tos();
1888 if (status = alloc_get_client_path(handle, ctx,
1895 status = SMB_VFS_NEXT_CHFLAGS(handle, clientPath, flags);
1897 TALLOC_FREE(clientPath);
1903 * Success: return NT_STATUS_OK
1904 * Failure: return NT status error
1906 static NTSTATUS mh_streaminfo(struct vfs_handle_struct *handle,
1907 struct files_struct *fsp,
1910 unsigned int *num_streams,
1911 struct stream_struct **streams)
1915 DEBUG(MH_INFO_DEBUG, ("Entering mh_streaminfo\n"));
1916 if (!is_in_media_files(fname))
1918 status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname,
1919 ctx, num_streams, streams);
1923 char *clientPath = NULL;
1924 TALLOC_CTX *mem_ctx = talloc_tos();
1926 if (alloc_get_client_path(handle, mem_ctx,
1930 status = map_nt_error_from_unix(errno);
1934 /* This only works on files, so we don't have to worry about
1935 * our fake directory stat'ing here.
1937 // But what does this function do, exactly? Does it need
1938 // extra modifications for the Avid stuff?
1939 status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, clientPath,
1940 ctx, num_streams, streams);
1942 TALLOC_FREE(clientPath);
1947 /* Ignoring get_real_filename function because the default
1948 * doesn't do anything.
1952 * Success: return NT_STATUS_OK
1953 * Failure: return NT status error
1954 * In this case, "name" is a path.
1956 static NTSTATUS mh_get_nt_acl(vfs_handle_struct *handle,
1958 uint32 security_info,
1959 struct security_descriptor **ppdesc)
1963 DEBUG(MH_INFO_DEBUG, ("Entering mh_get_nt_acl\n"));
1964 if (!is_in_media_files(name))
1966 status = SMB_VFS_NEXT_GET_NT_ACL(handle, name,
1967 security_info, ppdesc);
1971 char *clientPath = NULL;
1972 TALLOC_CTX *ctx = talloc_tos();
1974 if (alloc_get_client_path(handle, ctx,
1978 status = map_nt_error_from_unix(errno);
1982 status = SMB_VFS_NEXT_GET_NT_ACL(handle, clientPath,
1983 security_info, ppdesc);
1985 TALLOC_FREE(clientPath);
1992 * Failure: set errno, return -1
1994 static int mh_chmod_acl(vfs_handle_struct *handle,
2000 DEBUG(MH_INFO_DEBUG, ("Entering mh_chmod_acl\n"));
2001 if (!is_in_media_files(path))
2003 status = SMB_VFS_NEXT_CHMOD_ACL(handle, path, mode);
2007 char *clientPath = NULL;
2008 TALLOC_CTX *ctx = talloc_tos();
2010 if (status = alloc_get_client_path(handle, ctx,
2017 status = SMB_VFS_NEXT_CHMOD_ACL(handle, clientPath, mode);
2019 TALLOC_FREE(clientPath);
2025 * Success: return acl pointer
2026 * Failure: set errno, return NULL
2028 static SMB_ACL_T mh_sys_acl_get_file(vfs_handle_struct *handle,
2030 SMB_ACL_TYPE_T type)
2034 DEBUG(MH_INFO_DEBUG, ("Entering mh_sys_acl_get_file\n"));
2035 if (!is_in_media_files(path_p))
2037 ret = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, path_p, type);
2041 char *clientPath = NULL;
2042 TALLOC_CTX *ctx = talloc_tos();
2044 if (alloc_get_client_path(handle, ctx,
2052 ret = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, clientPath, type);
2054 TALLOC_FREE(clientPath);
2061 * Failure: set errno, return -1
2062 * In this case, "name" is a path.
2064 static int mh_sys_acl_set_file(vfs_handle_struct *handle,
2066 SMB_ACL_TYPE_T acltype,
2071 DEBUG(MH_INFO_DEBUG, ("Entering mh_sys_acl_set_file\n"));
2072 if (!is_in_media_files(name))
2074 status = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, name,
2079 char *clientPath = NULL;
2080 TALLOC_CTX *ctx = talloc_tos();
2082 if (status = alloc_get_client_path(handle, ctx,
2089 status = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, clientPath,
2092 TALLOC_FREE(clientPath);
2099 * Failure: set errno, return -1
2101 static int mh_sys_acl_delete_def_file(vfs_handle_struct *handle,
2106 DEBUG(MH_INFO_DEBUG, ("Entering mh_sys_acl_delete_def_file\n"));
2107 if (!is_in_media_files(path))
2109 status = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle,
2114 char *clientPath = NULL;
2115 TALLOC_CTX *ctx = talloc_tos();
2117 if (status = alloc_get_client_path(handle, ctx,
2124 status = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, clientPath);
2126 TALLOC_FREE(clientPath);
2132 * Success: return positive number
2133 * Failure: set errno, return -1
2134 * In this case, "name" is an attr name.
2136 static ssize_t mh_getxattr(struct vfs_handle_struct *handle,
2144 DEBUG(MH_INFO_DEBUG, ("Entering mh_getxattr\n"));
2145 if (!is_in_media_files(path))
2147 ret = SMB_VFS_NEXT_GETXATTR(handle, path, name, value,
2152 char *clientPath = NULL;
2153 TALLOC_CTX *ctx = talloc_tos();
2155 if (alloc_get_client_path(handle, ctx,
2163 ret = SMB_VFS_NEXT_GETXATTR(handle, clientPath, name, value, size);
2165 TALLOC_FREE(clientPath);
2171 * Success: return positive number
2172 * Failure: set errno, return -1
2174 static ssize_t mh_listxattr(struct vfs_handle_struct *handle,
2181 DEBUG(MH_INFO_DEBUG, ("Entering mh_listxattr\n"));
2182 if (!is_in_media_files(path))
2184 ret = SMB_VFS_NEXT_LISTXATTR(handle, path, list, size);
2188 char *clientPath = NULL;
2189 TALLOC_CTX *ctx = talloc_tos();
2191 if (alloc_get_client_path(handle, ctx,
2199 ret = SMB_VFS_NEXT_LISTXATTR(handle, clientPath, list, size);
2201 TALLOC_FREE(clientPath);
2208 * Failure: set errno, return -1
2209 * In this case, "name" is an attr name.
2211 static int mh_removexattr(struct vfs_handle_struct *handle,
2217 DEBUG(MH_INFO_DEBUG, ("Entering mh_removexattr\n"));
2218 if (!is_in_media_files(path))
2220 status = SMB_VFS_NEXT_REMOVEXATTR(handle, path, name);
2224 char *clientPath = NULL;
2225 TALLOC_CTX *ctx = talloc_tos();
2227 if (status = alloc_get_client_path(handle, ctx,
2234 status = SMB_VFS_NEXT_REMOVEXATTR(handle, clientPath, name);
2236 TALLOC_FREE(clientPath);
2243 * Failure: set errno, return -1
2244 * In this case, "name" is an attr name.
2246 static int mh_setxattr(struct vfs_handle_struct *handle,
2255 DEBUG(MH_INFO_DEBUG, ("Entering mh_setxattr\n"));
2256 if (!is_in_media_files(path))
2258 status = SMB_VFS_NEXT_SETXATTR(handle, path, name, value,
2263 char *clientPath = NULL;
2264 TALLOC_CTX *ctx = talloc_tos();
2266 if (status = alloc_get_client_path(handle, ctx,
2273 status = SMB_VFS_NEXT_SETXATTR(handle, clientPath, name, value,
2276 TALLOC_FREE(clientPath);
2282 * Success: return true
2283 * Failure: set errno, return false
2285 static bool mh_is_offline(struct vfs_handle_struct *handle,
2286 const struct smb_filename *fname,
2287 SMB_STRUCT_STAT *sbuf)
2289 // check if sbuf is modified further down the chain.
2292 DEBUG(MH_INFO_DEBUG, ("Entering mh_is_offline\n"));
2293 if (!is_in_media_files(fname->base_name))
2295 ret = SMB_VFS_NEXT_IS_OFFLINE(handle, fname, sbuf);
2299 struct smb_filename *clientFname = NULL;
2300 TALLOC_CTX *ctx = talloc_tos();
2302 if(alloc_get_client_smb_fname(handle, ctx,
2310 ret = SMB_VFS_NEXT_IS_OFFLINE(handle, clientFname, sbuf);
2312 TALLOC_FREE(clientFname);
2318 * Success: return 0 (?)
2319 * Failure: set errno, return -1
2321 static int mh_set_offline(struct vfs_handle_struct *handle,
2322 const struct smb_filename *fname)
2326 DEBUG(MH_INFO_DEBUG, ("Entering mh_set_offline\n"));
2327 if (!is_in_media_files(fname->base_name))
2329 status = SMB_VFS_NEXT_SET_OFFLINE(handle, fname);
2333 struct smb_filename *clientFname = NULL;
2334 TALLOC_CTX *ctx = talloc_tos();
2336 if (status = alloc_get_client_smb_fname(handle, ctx,
2343 status = SMB_VFS_NEXT_SET_OFFLINE(handle, clientFname);
2345 TALLOC_FREE(clientFname);
2350 /* VFS operations structure */
2352 static struct vfs_fn_pointers vfs_mh_fns = {
2353 /* Disk operations */
2355 .statvfs_fn = mh_statvfs,
2357 /* Directory operations */
2359 .opendir_fn = mh_opendir,
2360 .fdopendir_fn = mh_fdopendir,
2361 .readdir_fn = mh_readdir,
2362 .seekdir_fn = mh_seekdir,
2363 .telldir_fn = mh_telldir,
2364 .rewind_dir_fn = mh_rewinddir,
2365 .mkdir_fn = mh_mkdir,
2366 .rmdir_fn = mh_rmdir,
2367 .closedir_fn = mh_closedir,
2368 .init_search_op_fn = mh_init_search_op,
2370 /* File operations */
2373 .create_file_fn = mh_create_file,
2374 .rename_fn = mh_rename,
2376 .lstat_fn = mh_lstat,
2377 .fstat_fn = mh_fstat,
2378 .unlink_fn = mh_unlink,
2379 .chmod_fn = mh_chmod,
2380 .chown_fn = mh_chown,
2381 .lchown_fn = mh_lchown,
2382 .chdir_fn = mh_chdir,
2383 .ntimes_fn = mh_ntimes,
2384 .symlink_fn = mh_symlink,
2385 .readlink_fn = mh_readlink,
2387 .mknod_fn = mh_mknod,
2388 .realpath_fn = mh_realpath,
2389 .chflags_fn = mh_chflags,
2390 .streaminfo_fn = mh_streaminfo,
2392 /* NT ACL operations. */
2394 .get_nt_acl_fn = mh_get_nt_acl,
2396 /* POSIX ACL operations. */
2398 .chmod_acl_fn = mh_chmod_acl,
2400 .sys_acl_get_file_fn = mh_sys_acl_get_file,
2401 .sys_acl_set_file_fn = mh_sys_acl_set_file,
2402 .sys_acl_delete_def_file_fn = mh_sys_acl_delete_def_file,
2404 /* EA operations. */
2405 .getxattr_fn = mh_getxattr,
2406 .listxattr_fn = mh_listxattr,
2407 .removexattr_fn = mh_removexattr,
2408 .setxattr_fn = mh_setxattr,
2410 /* aio operations */
2412 /* offline operations */
2413 .is_offline_fn = mh_is_offline,
2414 .set_offline_fn = mh_set_offline
2417 NTSTATUS vfs_media_harmony_init(void);
2418 NTSTATUS vfs_media_harmony_init(void)
2420 NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2421 "media_harmony", &vfs_mh_fns);
2422 if (!NT_STATUS_IS_OK(ret))
2427 vfs_mh_debug_level = debug_add_class("media_harmony");
2429 if (vfs_mh_debug_level == -1) {
2430 vfs_mh_debug_level = DBGC_VFS;
2431 DEBUG(1, ("media_harmony_init: Couldn't register custom "
2432 "debugging class.\n"));
2434 DEBUG(3, ("media_harmony_init: Debug class number of "
2435 "'media_harmony': %d\n",
2436 vfs_mh_debug_level));