2 * Samba VFS module supporting multiple AVID clients sharing media.
4 * Copyright (C) 2005 Philip de Nier <philipn@users.sourceforge.net>
5 * Copyright (C) 2012 Andrew Klaassen <clawsoon@yahoo.com>
6 * Copyright (C) 2013 Milos Lukacek
7 * Copyright (C) 2013 Ralph Boehme <slow@samba.org>
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
26 * Unityed Media is a Samba VFS module that allows multiple AVID
27 * clients to share media.
29 * Add this module to the vfs objects option in your Samba share
35 * vfs objects = unityed_media
38 * It is recommended that you separate out Samba shares for Mac
39 * and Windows clients, and add the following options to the shares
40 * for Windows clients (NOTE: replace @ with *):
42 * veto files = /.DS_Store/._@/.Trash@/.Spotlight@/.hidden/.hotfiles@/.vol/
43 * delete veto files = yes
45 * This prevents hidden files from Mac clients interfering with Windows
46 * clients. If you find any more problem hidden files then add them to
50 * This module is designed to work with AVID editing applications that
51 * look in the Avid MediaFiles or OMFI MediaFiles directory for media.
52 * It is not designed to work as expected in all circumstances for
58 #include "system/filesys.h"
59 #include "smbd/smbd.h"
60 #include "../smbd/globals.h"
62 #include "../lib/tsocket/tsocket.h"
65 #define UM_PARAM_TYPE_NAME "unityed_media"
67 static const char *AVID_MXF_DIRNAME
= "Avid MediaFiles/MXF";
68 static const size_t AVID_MXF_DIRNAME_LEN
= 19;
69 static const char *OMFI_MEDIAFILES_DIRNAME
= "OMFI MediaFiles";
70 static const size_t OMFI_MEDIAFILES_DIRNAME_LEN
= 15;
71 static const char *APPLE_DOUBLE_PREFIX
= "._";
72 static const size_t APPLE_DOUBLE_PREFIX_LEN
= 2;
73 static int vfs_um_debug_level
= DBGC_VFS
;
75 enum um_clientid
{UM_CLIENTID_NAME
, UM_CLIENTID_IP
, UM_CLIENTID_HOSTNAME
};
77 struct um_config_data
{
78 enum um_clientid clientid
;
81 static const struct enum_list um_clientid
[] = {
82 {UM_CLIENTID_NAME
, "user"},
83 {UM_CLIENTID_IP
, "ip"},
84 {UM_CLIENTID_HOSTNAME
, "hostname"},
88 /* supplements the directory list stream */
89 typedef struct um_dirinfo_struct
{
94 char *clientSubDirname
;
98 * Returns true and first group of digits in path, false and 0 otherwise
100 static bool get_digit_group(const char *path
, uintmax_t *digit
)
102 const char *p
= path
;
107 DEBUG(10, ("get_digit_group entering with path '%s'\n",
111 * Delibiretly initialize to 0 because callers use this result
112 * even though the string doesn't contain any number and we
118 cp
= next_codepoint(p
, &size
);
122 if ((size
== 1) && (isdigit(cp
))) {
123 *digit
= (uintmax_t)strtoul(p
, &endp
, 10);
124 DEBUG(10, ("num_suffix = '%ju'\n",
134 /* Add "_<remote_name>.<number>" suffix to path or filename.
137 * Failure: set errno, path NULL, return -1
140 static int alloc_append_client_suffix(vfs_handle_struct
*handle
,
145 const char *clientid
;
146 struct um_config_data
*config
;
148 DEBUG(10, ("Entering with path '%s'\n", *path
));
150 SMB_VFS_HANDLE_GET_DATA(handle
, config
,
151 struct um_config_data
,
154 (void)get_digit_group(*path
, &number
);
156 switch (config
->clientid
) {
159 clientid
= tsocket_address_inet_addr_string(
160 handle
->conn
->sconn
->remote_address
, talloc_tos());
161 if (clientid
== NULL
) {
168 case UM_CLIENTID_HOSTNAME
:
169 clientid
= get_remote_machine_name();
172 case UM_CLIENTID_NAME
:
174 clientid
= get_current_username();
178 *path
= talloc_asprintf_append(*path
, "_%s.%ju",
181 DEBUG(1, ("alloc_append_client_suffix "
187 DEBUG(10, ("Leaving with *path '%s'\n", *path
));
192 /* Returns true if the file or directory begins with the appledouble
195 static bool is_apple_double(const char* fname
)
199 DEBUG(10, ("Entering with fname '%s'\n", fname
));
201 if (strnequal(APPLE_DOUBLE_PREFIX
, fname
, APPLE_DOUBLE_PREFIX_LEN
)) {
204 DEBUG(10, ("Leaving with ret '%s'\n",
205 ret
== true ? "true" : "false"));
209 static bool starts_with_media_dir(const char* media_dirname
,
210 size_t media_dirname_len
,
214 const char *path_start
= path
;
216 DEBUG(10, ("Entering with media_dirname '%s' "
217 "path '%s'\n", media_dirname
, path
));
219 /* Sometimes Samba gives us "./OMFI MediaFiles". */
220 if (strnequal(path
, "./", 2)) {
224 if (strnequal(media_dirname
, path_start
, media_dirname_len
)
226 ((path_start
[media_dirname_len
] == '\0') ||
227 (path_start
[media_dirname_len
] == '/'))) {
231 DEBUG(10, ("Leaving with ret '%s'\n",
232 ret
== true ? "true" : "false"));
237 * Returns true if the file or directory referenced by the path is ONE
238 * LEVEL below the AVID_MXF_DIRNAME or OMFI_MEDIAFILES_DIRNAME
241 static bool is_in_media_dir(const char *path
)
243 int transition_count
= 0;
244 const char *path_start
= path
;
246 const char *media_dirname
;
247 size_t media_dirname_len
;
249 DEBUG(10, ("Entering with path'%s' ", path
));
251 /* Sometimes Samba gives us "./OMFI MediaFiles". */
252 if (strnequal(path
, "./", 2)) {
256 if (strnequal(path_start
, AVID_MXF_DIRNAME
, AVID_MXF_DIRNAME_LEN
)) {
257 media_dirname
= AVID_MXF_DIRNAME
;
258 media_dirname_len
= AVID_MXF_DIRNAME_LEN
;
259 } else if (strnequal(path_start
,
260 OMFI_MEDIAFILES_DIRNAME
,
261 OMFI_MEDIAFILES_DIRNAME_LEN
)) {
262 media_dirname
= OMFI_MEDIAFILES_DIRNAME
;
263 media_dirname_len
= OMFI_MEDIAFILES_DIRNAME_LEN
;
268 if (path_start
[media_dirname_len
] == '\0') {
272 p
= path_start
+ media_dirname_len
+ 1;
275 if (*p
== '\0' || *p
== '/') {
276 if (strnequal(p
- 3, "/..", 3)) {
278 } else if ((p
[-1] != '/') || !strnequal(p
- 2, "/.", 2)) {
289 DEBUG(10, ("Going out with transition_count '%i'\n",
291 if (((transition_count
== 1) && (media_dirname
== AVID_MXF_DIRNAME
))
293 ((transition_count
== 0) && (media_dirname
== OMFI_MEDIAFILES_DIRNAME
))) {
300 * Returns true if the file or directory referenced by the path is
301 * below the AVID_MEDIAFILES_DIRNAME or OMFI_MEDIAFILES_DIRNAME
302 * directory The AVID_MEDIAFILES_DIRNAME and OMFI_MEDIAFILES_DIRNAME
303 * are assumed to be in the root directory, which is generally a safe
304 * assumption in the fixed-path world of Avid.
306 static bool is_in_media_files(const char *path
)
310 DEBUG(10, ("Entering with path '%s'\n", path
));
312 if (starts_with_media_dir(AVID_MXF_DIRNAME
,
313 AVID_MXF_DIRNAME_LEN
, path
) ||
314 starts_with_media_dir(OMFI_MEDIAFILES_DIRNAME
,
315 OMFI_MEDIAFILES_DIRNAME_LEN
, path
)) {
318 DEBUG(10, ("Leaving with ret '%s'\n",
319 ret
== true ? "true" : "false"));
324 /* Add client suffix to "pure-number" path.
326 * Caller must free newPath.
329 * Failure: set errno, newPath NULL, return -1
331 static int alloc_get_client_path(vfs_handle_struct
*handle
,
342 *path_out
= talloc_strdup(ctx
, path_in
);
343 if (*path_out
== NULL
) {
344 DEBUG(1, ("alloc_get_client_path ENOMEM\n"));
348 (void)get_digit_group(*path_out
, &number
);
350 digits
= talloc_asprintf(NULL
, "%ju", number
);
351 if (digits
== NULL
) {
352 DEBUG(1, ("alloc_get_client_path ENOMEM\n"));
355 digits_len
= strlen(digits
);
357 p
= strstr_m(path_in
, digits
);
360 ((p
[digits_len
] == '\0') || (p
[digits_len
] == '/'))
362 (((p
- path_in
> 0) && (p
[-1] == '/'))
364 (((p
- path_in
) > APPLE_DOUBLE_PREFIX_LEN
)
366 is_apple_double(p
- APPLE_DOUBLE_PREFIX_LEN
)
368 (p
[-(APPLE_DOUBLE_PREFIX_LEN
+ 1)] == '/'))))
370 (*path_out
)[p
- path_in
+ digits_len
] = '\0';
372 status
= alloc_append_client_suffix(handle
, path_out
);
377 *path_out
= talloc_strdup_append(*path_out
, p
+ digits_len
);
378 if (*path_out
== NULL
) {
379 DEBUG(1, ("alloc_get_client_path ENOMEM\n"));
385 /* path_out must be freed in caller. */
386 DEBUG(10, ("Result:'%s'\n", *path_out
));
392 * Failure: set errno, return -1
394 static int alloc_get_client_smb_fname(struct vfs_handle_struct
*handle
,
396 const struct smb_filename
*smb_fname
,
397 struct smb_filename
**client_fname
)
401 DEBUG(10, ("Entering with smb_fname->base_name '%s'\n",
402 smb_fname
->base_name
));
404 *client_fname
= cp_smb_filename(ctx
, smb_fname
);
405 if (*client_fname
== NULL
) {
406 DEBUG(1, ("cp_smb_filename returned NULL\n"));
409 status
= alloc_get_client_path(handle
, ctx
,
410 smb_fname
->base_name
,
411 &(*client_fname
)->base_name
);
416 DEBUG(10, ("Leaving with (*client_fname)->base_name "
417 "'%s'\n", (*client_fname
)->base_name
));
425 * Failure: set errno, return -1
427 static int alloc_set_client_dirinfo_path(struct vfs_handle_struct
*handle
,
430 const char *suffix_number
)
434 DEBUG(10, ("Entering with suffix_number '%s'\n",
437 *path
= talloc_strdup(ctx
, suffix_number
);
439 DEBUG(1, ("alloc_set_client_dirinfo_path ENOMEM\n"));
442 status
= alloc_append_client_suffix(handle
, path
);
447 DEBUG(10, ("Leaving with *path '%s'\n", *path
));
452 static int alloc_set_client_dirinfo(vfs_handle_struct
*handle
,
454 struct um_dirinfo_struct
**di_result
)
459 struct um_dirinfo_struct
*dip
;
461 DEBUG(10, ("Entering with fname '%s'\n", fname
));
463 *di_result
= talloc(NULL
, struct um_dirinfo_struct
);
464 if (*di_result
== NULL
) {
469 dip
->dirpath
= talloc_strdup(dip
, fname
);
470 if (dip
->dirpath
== NULL
) {
474 if (!is_in_media_files(fname
)) {
475 dip
->isInMediaFiles
= false;
476 dip
->clientPath
= NULL
;
477 dip
->clientSubDirname
= NULL
;
481 dip
->isInMediaFiles
= true;
483 (void)get_digit_group(fname
, &number
);
484 digits
= talloc_asprintf(talloc_tos(), "%ju", number
);
485 if (digits
== NULL
) {
489 status
= alloc_set_client_dirinfo_path(handle
, dip
,
490 &dip
->clientSubDirname
,
496 status
= alloc_get_client_path(handle
, dip
, fname
,
498 if (status
!= 0 || dip
->clientPath
== NULL
) {
503 DEBUG(10, ("Leaving with (*dirInfo)->dirpath '%s', "
504 "(*dirInfo)->clientPath '%s'\n",
505 dip
->dirpath
, dip
->clientPath
));
509 DEBUG(1, ("Failing with fname '%s'\n", fname
));
510 TALLOC_FREE(*di_result
);
516 /**********************************************************************
518 **********************************************************************/
522 * Failure: set errno, return -1
524 static int um_statvfs(struct vfs_handle_struct
*handle
,
525 const struct smb_filename
*smb_fname
,
526 struct vfs_statvfs_struct
*statbuf
)
529 struct smb_filename
*client_fname
= NULL
;
531 DEBUG(10, ("Entering with path '%s'\n", smb_fname
->base_name
));
533 if (!is_in_media_files(smb_fname
->base_name
)) {
534 return SMB_VFS_NEXT_STATVFS(handle
, smb_fname
, statbuf
);
537 status
= alloc_get_client_smb_fname(handle
,
545 status
= SMB_VFS_NEXT_STATVFS(handle
, client_fname
, statbuf
);
547 TALLOC_FREE(client_fname
);
548 DEBUG(10, ("Leaving with path '%s'\n", smb_fname
->base_name
));
552 /* Success: return a um_dirinfo_struct cast as a DIR
553 * Failure: set errno, return NULL
555 static DIR *um_opendir(vfs_handle_struct
*handle
,
556 const struct smb_filename
*smb_fname
,
560 struct um_dirinfo_struct
*dirInfo
;
562 DEBUG(10, ("Entering with fname '%s'\n", smb_fname
->base_name
));
564 if (alloc_set_client_dirinfo(handle
, smb_fname
->base_name
, &dirInfo
)) {
568 if (!dirInfo
->isInMediaFiles
) {
569 dirInfo
->dirstream
= SMB_VFS_NEXT_OPENDIR(
570 handle
, smb_fname
, mask
, attr
);
572 struct smb_filename
*client_smb_fname
=
573 synthetic_smb_fname(talloc_tos(),
578 if (client_smb_fname
== NULL
) {
582 dirInfo
->dirstream
= SMB_VFS_NEXT_OPENDIR(
583 handle
, client_smb_fname
, mask
, attr
);
585 TALLOC_FREE(client_smb_fname
);
588 if (dirInfo
->dirstream
== NULL
) {
592 DEBUG(10, ("Leaving with dirInfo->dirpath '%s', "
593 "dirInfo->clientPath '%s'\n",
595 dirInfo
->clientPath
));
596 return (DIR*)dirInfo
;
599 DEBUG(1, ("Failing with fname '%s'\n", smb_fname
->base_name
));
600 TALLOC_FREE(dirInfo
);
604 static DIR *um_fdopendir(vfs_handle_struct
*handle
,
609 struct um_dirinfo_struct
*dirInfo
= NULL
;
612 DEBUG(10, ("Entering with fsp->fsp_name->base_name '%s'\n",
613 fsp
->fsp_name
->base_name
));
615 dirstream
= SMB_VFS_NEXT_FDOPENDIR(handle
, fsp
, mask
, attr
);
620 if (alloc_set_client_dirinfo(handle
,
621 fsp
->fsp_name
->base_name
,
626 dirInfo
->dirstream
= dirstream
;
628 if (!dirInfo
->isInMediaFiles
) {
630 * FIXME: this is the original code, something must be
631 * missing here, but what? -slow
637 DEBUG(10, ("Leaving with dirInfo->dirpath '%s', "
638 "dirInfo->clientPath '%s', "
639 "fsp->fsp_name->st.st_ex_mtime %s",
642 ctime(&(fsp
->fsp_name
->st
.st_ex_mtime
.tv_sec
))));
643 return (DIR *) dirInfo
;
646 DEBUG(1, ("Failing with fsp->fsp_name->base_name '%s'\n",
647 fsp
->fsp_name
->base_name
));
648 TALLOC_FREE(dirInfo
);
653 * skip own suffixed directory
654 * replace own suffixed directory with non suffixed.
656 * Success: return dirent
657 * End of data: return NULL
658 * Failure: set errno, return NULL
660 static struct dirent
*um_readdir(vfs_handle_struct
*handle
,
662 SMB_STRUCT_STAT
*sbuf
)
664 um_dirinfo_struct
* dirInfo
= (um_dirinfo_struct
*)dirp
;
665 struct dirent
*d
= NULL
;
668 DEBUG(10, ("dirInfo->dirpath '%s', "
669 "dirInfo->clientPath '%s', "
670 "dirInfo->isInMediaFiles '%s', "
671 "dirInfo->clientSubDirname '%s'\n",
674 dirInfo
->isInMediaFiles
? "true" : "false",
675 dirInfo
->clientSubDirname
));
677 if (!dirInfo
->isInMediaFiles
) {
678 return SMB_VFS_NEXT_READDIR(handle
, dirInfo
->dirstream
, sbuf
);
689 d
= SMB_VFS_NEXT_READDIR(handle
, dirInfo
->dirstream
, sbuf
);
695 /* ignore apple double prefix for logic below */
696 if (is_apple_double(d
->d_name
)) {
697 dname
= &d
->d_name
[APPLE_DOUBLE_PREFIX_LEN
];
698 isAppleDouble
= true;
701 isAppleDouble
= false;
704 DEBUG(10, ("dname = '%s'\n", dname
));
706 (void)get_digit_group(dname
, &number
);
707 digits
= talloc_asprintf(talloc_tos(), "%ju", number
);
708 if (digits
== NULL
) {
709 DEBUG(1, ("out of memory"));
712 digits_len
= strlen(digits
);
714 if (alloc_set_client_dirinfo_path(handle
,
716 &((dirInfo
)->clientSubDirname
),
722 * If set to "true", vfs shows digits-only
723 * non-suffixed subdirectories. Normally, such
724 * subdirectories can exists only in non-media
725 * directories, so we set it to "false". Otherwise,
726 * if we have such subdirectories (probably created
727 * over not "unityed" connection), it can be little
730 if (strequal(dname
, digits
)) {
732 } else if (strequal(dname
, dirInfo
->clientSubDirname
)) {
734 * Remove suffix of this client's suffixed
738 d
->d_name
[digits_len
+ APPLE_DOUBLE_PREFIX_LEN
] = '\0';
740 d
->d_name
[digits_len
] = '\0';
742 } else if (strnequal(digits
, dname
, digits_len
)) {
744 * Set to false to see another clients subdirectories
750 DEBUG(10, ("Leaving um_readdir\n"));
753 TALLOC_FREE(dirInfo
);
757 static void um_seekdir(vfs_handle_struct
*handle
,
761 DEBUG(10, ("Entering and leaving um_seekdir\n"));
762 SMB_VFS_NEXT_SEEKDIR(handle
,
763 ((um_dirinfo_struct
*)dirp
)->dirstream
, offset
);
766 static long um_telldir(vfs_handle_struct
*handle
,
769 DEBUG(10, ("Entering and leaving um_telldir\n"));
770 return SMB_VFS_NEXT_TELLDIR(handle
,
771 ((um_dirinfo_struct
*)dirp
)->dirstream
);
774 static void um_rewinddir(vfs_handle_struct
*handle
,
777 DEBUG(10, ("Entering and leaving um_rewinddir\n"));
778 SMB_VFS_NEXT_REWINDDIR(handle
,
779 ((um_dirinfo_struct
*)dirp
)->dirstream
);
782 static int um_mkdir(vfs_handle_struct
*handle
,
783 const struct smb_filename
*smb_fname
,
787 const char *path
= smb_fname
->base_name
;
788 struct smb_filename
*client_fname
= NULL
;
790 DEBUG(10, ("Entering with path '%s'\n", path
));
792 if (!is_in_media_files(path
) || !is_in_media_dir(path
)) {
793 return SMB_VFS_NEXT_MKDIR(handle
, smb_fname
, mode
);
796 status
= alloc_get_client_smb_fname(handle
,
804 status
= SMB_VFS_NEXT_MKDIR(handle
, client_fname
, mode
);
806 TALLOC_FREE(client_fname
);
807 DEBUG(10, ("Leaving with path '%s'\n", path
));
811 static int um_rmdir(vfs_handle_struct
*handle
,
812 const struct smb_filename
*smb_fname
)
815 const char *path
= smb_fname
->base_name
;
816 struct smb_filename
*client_fname
= NULL
;
818 DEBUG(10, ("Entering with path '%s'\n", path
));
820 if (!is_in_media_files(path
)) {
821 return SMB_VFS_NEXT_RMDIR(handle
, smb_fname
);
824 status
= alloc_get_client_smb_fname(handle
,
832 status
= SMB_VFS_NEXT_RMDIR(handle
, client_fname
);
834 TALLOC_FREE(client_fname
);
835 DEBUG(10, ("Leaving with path '%s'\n", path
));
839 static int um_closedir(vfs_handle_struct
*handle
,
842 DIR *realdirp
= ((um_dirinfo_struct
*)dirp
)->dirstream
;
846 return SMB_VFS_NEXT_CLOSEDIR(handle
, realdirp
);
849 static void um_init_search_op(vfs_handle_struct
*handle
,
852 DEBUG(10, ("Entering and leaving um_init_search_op\n"));
854 SMB_VFS_NEXT_INIT_SEARCH_OP(handle
,
855 ((um_dirinfo_struct
*)dirp
)->dirstream
);
858 static int um_open(vfs_handle_struct
*handle
,
859 struct smb_filename
*smb_fname
,
865 struct smb_filename
*client_fname
= NULL
;
867 DEBUG(10, ("Entering with smb_fname->base_name '%s'\n",
868 smb_fname
->base_name
));
870 if (!is_in_media_files(smb_fname
->base_name
)) {
871 return SMB_VFS_NEXT_OPEN(handle
, smb_fname
, fsp
, flags
, mode
);
874 if (alloc_get_client_smb_fname(handle
, talloc_tos(),
883 * What about fsp->fsp_name? We also have to get correct stat
884 * info into fsp and smb_fname for DB files, don't we?
887 DEBUG(10, ("Leaving with smb_fname->base_name '%s' "
888 "smb_fname->st.st_ex_mtime %s"
889 "fsp->fsp_name->st.st_ex_mtime %s",
890 smb_fname
->base_name
,
891 ctime(&(smb_fname
->st
.st_ex_mtime
.tv_sec
)),
892 ctime(&(fsp
->fsp_name
->st
.st_ex_mtime
.tv_sec
))));
894 ret
= SMB_VFS_NEXT_OPEN(handle
, client_fname
, fsp
, flags
, mode
);
896 TALLOC_FREE(client_fname
);
897 DEBUG(10, ("Leaving with smb_fname->base_name '%s'\n",
898 smb_fname
->base_name
));
902 static NTSTATUS
um_create_file(vfs_handle_struct
*handle
,
903 struct smb_request
*req
,
904 uint16_t root_dir_fid
,
905 struct smb_filename
*smb_fname
,
906 uint32_t access_mask
,
907 uint32_t share_access
,
908 uint32_t create_disposition
,
909 uint32_t create_options
,
910 uint32_t file_attributes
,
911 uint32_t oplock_request
,
912 struct smb2_lease
*lease
,
913 uint64_t allocation_size
,
914 uint32_t private_flags
,
915 struct security_descriptor
*sd
,
916 struct ea_list
*ea_list
,
917 files_struct
**result_fsp
,
919 const struct smb2_create_blobs
*in_context_blobs
,
920 struct smb2_create_blobs
*out_context_blobs
)
923 struct smb_filename
*client_fname
= NULL
;
925 DEBUG(10, ("Entering with smb_fname->base_name '%s'\n",
926 smb_fname
->base_name
));
928 if (!is_in_media_files(smb_fname
->base_name
)) {
929 return SMB_VFS_NEXT_CREATE_FILE(
951 if (alloc_get_client_smb_fname(handle
, talloc_tos(),
954 status
= map_nt_error_from_unix(errno
);
960 * This only creates files, so we don't have to worry about
961 * our fake directory stat'ing here. But we still need to
962 * route stat calls for DB files properly, right?
964 status
= SMB_VFS_NEXT_CREATE_FILE(
985 TALLOC_FREE(client_fname
);
986 DEBUG(10, ("Leaving with smb_fname->base_name '%s'"
987 "smb_fname->st.st_ex_mtime %s"
988 " fsp->fsp_name->st.st_ex_mtime %s",
989 smb_fname
->base_name
,
990 ctime(&(smb_fname
->st
.st_ex_mtime
.tv_sec
)),
991 (*result_fsp
) && VALID_STAT((*result_fsp
)->fsp_name
->st
) ?
992 ctime(&((*result_fsp
)->fsp_name
->st
.st_ex_mtime
.tv_sec
)) :
997 static int um_rename(vfs_handle_struct
*handle
,
998 const struct smb_filename
*smb_fname_src
,
999 const struct smb_filename
*smb_fname_dst
)
1002 struct smb_filename
*src_client_fname
= NULL
;
1003 struct smb_filename
*dst_client_fname
= NULL
;
1005 DEBUG(10, ("Entering with "
1006 "smb_fname_src->base_name '%s', "
1007 "smb_fname_dst->base_name '%s'\n",
1008 smb_fname_src
->base_name
,
1009 smb_fname_dst
->base_name
));
1011 if (!is_in_media_files(smb_fname_src
->base_name
)
1013 !is_in_media_files(smb_fname_dst
->base_name
)) {
1014 return SMB_VFS_NEXT_RENAME(handle
, smb_fname_src
,
1018 status
= alloc_get_client_smb_fname(handle
, talloc_tos(),
1025 status
= alloc_get_client_smb_fname(handle
, talloc_tos(),
1033 status
= SMB_VFS_NEXT_RENAME(handle
, src_client_fname
,
1036 TALLOC_FREE(dst_client_fname
);
1037 TALLOC_FREE(src_client_fname
);
1038 DEBUG(10, ("Leaving with smb_fname_src->base_name '%s',"
1039 " smb_fname_dst->base_name '%s'\n",
1040 smb_fname_src
->base_name
,
1041 smb_fname_dst
->base_name
));
1047 * Failure: set errno, return -1
1049 static int um_stat(vfs_handle_struct
*handle
,
1050 struct smb_filename
*smb_fname
)
1053 struct smb_filename
*client_fname
= NULL
;
1055 DEBUG(10, ("Entering with smb_fname->base_name '%s'\n",
1056 smb_fname
->base_name
));
1058 if (!is_in_media_files(smb_fname
->base_name
)) {
1059 return SMB_VFS_NEXT_STAT(handle
, smb_fname
);
1062 status
= alloc_get_client_smb_fname(handle
, talloc_tos(),
1068 DEBUG(10, ("Stat'ing client_fname->base_name '%s'\n",
1069 client_fname
->base_name
));
1071 status
= SMB_VFS_NEXT_STAT(handle
, client_fname
);
1077 * Unlike functions with const smb_filename, we have to modify
1078 * smb_fname itself to pass our info back up.
1080 DEBUG(10, ("Setting smb_fname '%s' stat from client_fname '%s'\n",
1081 smb_fname
->base_name
, client_fname
->base_name
));
1082 smb_fname
->st
= client_fname
->st
;
1085 TALLOC_FREE(client_fname
);
1086 DEBUG(10, ("Leaving with smb_fname->st.st_ex_mtime %s",
1087 ctime(&(smb_fname
->st
.st_ex_mtime
.tv_sec
))));
1091 static int um_lstat(vfs_handle_struct
*handle
,
1092 struct smb_filename
*smb_fname
)
1095 struct smb_filename
*client_fname
= NULL
;
1097 DEBUG(10, ("Entering with smb_fname->base_name '%s'\n",
1098 smb_fname
->base_name
));
1100 if (!is_in_media_files(smb_fname
->base_name
)) {
1101 return SMB_VFS_NEXT_LSTAT(handle
, smb_fname
);
1104 client_fname
= NULL
;
1106 status
= alloc_get_client_smb_fname(handle
, talloc_tos(),
1112 status
= SMB_VFS_NEXT_LSTAT(handle
, client_fname
);
1117 smb_fname
->st
= client_fname
->st
;
1120 TALLOC_FREE(client_fname
);
1121 DEBUG(10, ("Leaving with smb_fname->st.st_ex_mtime %s",
1122 ctime(&(smb_fname
->st
.st_ex_mtime
.tv_sec
))));
1126 static int um_fstat(vfs_handle_struct
*handle
,
1127 files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
1131 DEBUG(10, ("Entering with fsp->fsp_name->base_name "
1132 "'%s'\n", fsp_str_dbg(fsp
)));
1134 status
= SMB_VFS_NEXT_FSTAT(handle
, fsp
, sbuf
);
1139 if ((fsp
->fsp_name
== NULL
) ||
1140 !is_in_media_files(fsp
->fsp_name
->base_name
)) {
1144 status
= um_stat(handle
, fsp
->fsp_name
);
1149 *sbuf
= fsp
->fsp_name
->st
;
1152 DEBUG(10, ("Leaving with fsp->fsp_name->st.st_ex_mtime %s\n",
1153 fsp
->fsp_name
!= NULL
?
1154 ctime(&(fsp
->fsp_name
->st
.st_ex_mtime
.tv_sec
)) : "0"));
1158 static int um_unlink(vfs_handle_struct
*handle
,
1159 const struct smb_filename
*smb_fname
)
1162 struct smb_filename
*client_fname
= NULL
;
1164 DEBUG(10, ("Entering um_unlink\n"));
1166 if (!is_in_media_files(smb_fname
->base_name
)) {
1167 return SMB_VFS_NEXT_UNLINK(handle
, smb_fname
);
1170 status
= alloc_get_client_smb_fname(handle
, talloc_tos(),
1177 status
= SMB_VFS_NEXT_UNLINK(handle
, client_fname
);
1180 TALLOC_FREE(client_fname
);
1184 static int um_chmod(vfs_handle_struct
*handle
,
1185 const struct smb_filename
*smb_fname
,
1189 struct smb_filename
*client_fname
= NULL
;
1191 DEBUG(10, ("Entering um_chmod\n"));
1193 if (!is_in_media_files(smb_fname
->base_name
)) {
1194 return SMB_VFS_NEXT_CHMOD(handle
, smb_fname
, mode
);
1197 status
= alloc_get_client_smb_fname(handle
,
1205 status
= SMB_VFS_NEXT_CHMOD(handle
, client_fname
, mode
);
1208 TALLOC_FREE(client_fname
);
1212 static int um_chown(vfs_handle_struct
*handle
,
1213 const struct smb_filename
*smb_fname
,
1218 struct smb_filename
*client_fname
= NULL
;
1220 DEBUG(10, ("Entering um_chown\n"));
1222 if (!is_in_media_files(smb_fname
->base_name
)) {
1223 return SMB_VFS_NEXT_CHOWN(handle
, smb_fname
, uid
, gid
);
1226 status
= alloc_get_client_smb_fname(handle
,
1234 status
= SMB_VFS_NEXT_CHOWN(handle
, client_fname
, uid
, gid
);
1237 TALLOC_FREE(client_fname
);
1241 static int um_lchown(vfs_handle_struct
*handle
,
1242 const struct smb_filename
*smb_fname
,
1247 struct smb_filename
*client_fname
= NULL
;
1249 DEBUG(10, ("Entering um_lchown\n"));
1250 if (!is_in_media_files(smb_fname
->base_name
)) {
1251 return SMB_VFS_NEXT_LCHOWN(handle
, smb_fname
, uid
, gid
);
1254 status
= alloc_get_client_smb_fname(handle
,
1262 status
= SMB_VFS_NEXT_LCHOWN(handle
, client_fname
, uid
, gid
);
1265 TALLOC_FREE(client_fname
);
1269 static int um_chdir(vfs_handle_struct
*handle
,
1270 const struct smb_filename
*smb_fname
)
1273 struct smb_filename
*client_fname
= NULL
;
1275 DEBUG(10, ("Entering um_chdir\n"));
1277 if (!is_in_media_files(smb_fname
->base_name
)) {
1278 return SMB_VFS_NEXT_CHDIR(handle
, smb_fname
);
1281 status
= alloc_get_client_smb_fname(handle
,
1289 status
= SMB_VFS_NEXT_CHDIR(handle
, client_fname
);
1292 TALLOC_FREE(client_fname
);
1296 static int um_ntimes(vfs_handle_struct
*handle
,
1297 const struct smb_filename
*smb_fname
,
1298 struct smb_file_time
*ft
)
1301 struct smb_filename
*client_fname
= NULL
;
1303 DEBUG(10, ("Entering um_ntimes\n"));
1305 if (!is_in_media_files(smb_fname
->base_name
)) {
1306 return SMB_VFS_NEXT_NTIMES(handle
, smb_fname
, ft
);
1309 status
= alloc_get_client_smb_fname(handle
, talloc_tos(),
1310 smb_fname
, &client_fname
);
1315 status
= SMB_VFS_NEXT_NTIMES(handle
, client_fname
, ft
);
1318 TALLOC_FREE(client_fname
);
1322 static int um_symlink(vfs_handle_struct
*handle
,
1323 const char *link_contents
,
1324 const struct smb_filename
*new_smb_fname
)
1327 char *client_link_contents
= NULL
;
1328 struct smb_filename
*new_client_fname
= NULL
;
1330 DEBUG(10, ("Entering um_symlink\n"));
1332 if (!is_in_media_files(link_contents
) &&
1333 !is_in_media_files(new_smb_fname
->base_name
)) {
1334 return SMB_VFS_NEXT_SYMLINK(handle
,
1339 status
= alloc_get_client_path(handle
, talloc_tos(),
1340 link_contents
, &client_link_contents
);
1344 status
= alloc_get_client_smb_fname(handle
, talloc_tos(),
1345 new_smb_fname
, &new_client_fname
);
1350 status
= SMB_VFS_NEXT_SYMLINK(handle
,
1351 client_link_contents
,
1355 TALLOC_FREE(client_link_contents
);
1356 TALLOC_FREE(new_client_fname
);
1360 static int um_readlink(vfs_handle_struct
*handle
,
1361 const struct smb_filename
*smb_fname
,
1366 struct smb_filename
*client_fname
= NULL
;
1368 DEBUG(10, ("Entering um_readlink\n"));
1370 if (!is_in_media_files(smb_fname
->base_name
)) {
1371 return SMB_VFS_NEXT_READLINK(handle
, smb_fname
,
1375 status
= alloc_get_client_smb_fname(handle
, talloc_tos(),
1376 smb_fname
, &client_fname
);
1381 status
= SMB_VFS_NEXT_READLINK(handle
, client_fname
, buf
, bufsiz
);
1384 TALLOC_FREE(client_fname
);
1388 static int um_link(vfs_handle_struct
*handle
,
1389 const struct smb_filename
*old_smb_fname
,
1390 const struct smb_filename
*new_smb_fname
)
1393 struct smb_filename
*old_client_fname
= NULL
;
1394 struct smb_filename
*new_client_fname
= NULL
;
1396 DEBUG(10, ("Entering um_link\n"));
1397 if (!is_in_media_files(old_smb_fname
->base_name
) &&
1398 !is_in_media_files(new_smb_fname
->base_name
)) {
1399 return SMB_VFS_NEXT_LINK(handle
, old_smb_fname
, new_smb_fname
);
1402 status
= alloc_get_client_smb_fname(handle
, talloc_tos(),
1403 old_smb_fname
, &old_client_fname
);
1407 status
= alloc_get_client_smb_fname(handle
, talloc_tos(),
1408 new_smb_fname
, &new_client_fname
);
1413 status
= SMB_VFS_NEXT_LINK(handle
, old_client_fname
, new_client_fname
);
1416 TALLOC_FREE(old_client_fname
);
1417 TALLOC_FREE(new_client_fname
);
1421 static int um_mknod(vfs_handle_struct
*handle
,
1422 const struct smb_filename
*smb_fname
,
1427 struct smb_filename
*client_fname
= NULL
;
1429 DEBUG(10, ("Entering um_mknod\n"));
1430 if (!is_in_media_files(smb_fname
->base_name
)) {
1431 return SMB_VFS_NEXT_MKNOD(handle
, smb_fname
, mode
, dev
);
1434 status
= alloc_get_client_smb_fname(handle
, talloc_tos(),
1435 smb_fname
, &client_fname
);
1440 status
= SMB_VFS_NEXT_MKNOD(handle
, client_fname
, mode
, dev
);
1443 TALLOC_FREE(client_fname
);
1447 static struct smb_filename
*um_realpath(vfs_handle_struct
*handle
,
1449 const struct smb_filename
*smb_fname
)
1451 struct smb_filename
*client_fname
= NULL
;
1452 struct smb_filename
*result_fname
= NULL
;
1455 DEBUG(10, ("Entering um_realpath\n"));
1457 if (!is_in_media_files(smb_fname
->base_name
)) {
1458 return SMB_VFS_NEXT_REALPATH(handle
, ctx
, smb_fname
);
1461 status
= alloc_get_client_smb_fname(handle
, talloc_tos(),
1462 smb_fname
, &client_fname
);
1467 result_fname
= SMB_VFS_NEXT_REALPATH(handle
, ctx
, client_fname
);
1470 TALLOC_FREE(client_fname
);
1471 return result_fname
;
1474 static int um_chflags(vfs_handle_struct
*handle
,
1475 const struct smb_filename
*smb_fname
,
1479 struct smb_filename
*client_fname
= NULL
;
1481 DEBUG(10, ("Entering um_mknod\n"));
1482 if (!is_in_media_files(smb_fname
->base_name
)) {
1483 return SMB_VFS_NEXT_CHFLAGS(handle
, smb_fname
, flags
);
1486 status
= alloc_get_client_smb_fname(handle
, talloc_tos(),
1487 smb_fname
, &client_fname
);
1492 status
= SMB_VFS_NEXT_CHFLAGS(handle
, client_fname
, flags
);
1495 TALLOC_FREE(client_fname
);
1499 static NTSTATUS
um_streaminfo(struct vfs_handle_struct
*handle
,
1500 struct files_struct
*fsp
,
1501 const struct smb_filename
*smb_fname
,
1503 unsigned int *num_streams
,
1504 struct stream_struct
**streams
)
1508 struct smb_filename
*client_fname
= NULL
;
1510 DEBUG(10, ("Entering um_streaminfo\n"));
1512 if (!is_in_media_files(smb_fname
->base_name
)) {
1513 return SMB_VFS_NEXT_STREAMINFO(handle
, fsp
, smb_fname
,
1514 ctx
, num_streams
, streams
);
1517 ret
= alloc_get_client_smb_fname(handle
,
1522 status
= NT_STATUS_NO_MEMORY
;
1527 * This only works on files, so we don't have to worry about
1528 * our fake directory stat'ing here. But what does this
1529 * function do, exactly? Does it need extra modifications for
1532 status
= SMB_VFS_NEXT_STREAMINFO(handle
, fsp
, client_fname
,
1533 ctx
, num_streams
, streams
);
1535 TALLOC_FREE(client_fname
);
1540 * Ignoring get_real_filename function because the default doesn't do
1544 static NTSTATUS
um_get_nt_acl(vfs_handle_struct
*handle
,
1545 const struct smb_filename
*smb_fname
,
1546 uint32_t security_info
,
1547 TALLOC_CTX
*mem_ctx
,
1548 struct security_descriptor
**ppdesc
)
1551 char *client_path
= NULL
;
1552 struct smb_filename
*client_smb_fname
= NULL
;
1555 DEBUG(10, ("Entering um_get_nt_acl\n"));
1557 if (!is_in_media_files(smb_fname
->base_name
)) {
1558 return SMB_VFS_NEXT_GET_NT_ACL(handle
, smb_fname
,
1563 ret
= alloc_get_client_path(handle
, talloc_tos(),
1564 smb_fname
->base_name
, &client_path
);
1566 status
= map_nt_error_from_unix(errno
);
1570 client_smb_fname
= synthetic_smb_fname(talloc_tos(),
1575 if (client_smb_fname
== NULL
) {
1576 TALLOC_FREE(client_path
);
1577 return NT_STATUS_NO_MEMORY
;
1580 status
= SMB_VFS_NEXT_GET_NT_ACL(handle
, client_smb_fname
,
1584 TALLOC_FREE(client_smb_fname
);
1585 TALLOC_FREE(client_path
);
1589 static int um_chmod_acl(vfs_handle_struct
*handle
,
1590 const struct smb_filename
*smb_fname
,
1595 struct smb_filename
*client_fname
= NULL
;
1597 DEBUG(10, ("Entering um_chmod_acl\n"));
1599 if (!is_in_media_files(smb_fname
->base_name
)) {
1600 return SMB_VFS_NEXT_CHMOD_ACL(handle
, smb_fname
, mode
);
1603 status
= alloc_get_client_smb_fname(handle
,
1610 status
= SMB_VFS_NEXT_CHMOD_ACL(handle
, client_fname
, mode
);
1613 saved_errno
= errno
;
1614 TALLOC_FREE(client_fname
);
1615 errno
= saved_errno
;
1619 static SMB_ACL_T
um_sys_acl_get_file(vfs_handle_struct
*handle
,
1620 const struct smb_filename
*smb_fname
,
1621 SMB_ACL_TYPE_T type
,
1622 TALLOC_CTX
*mem_ctx
)
1625 int saved_errno
= 0;
1626 struct smb_filename
*client_fname
= NULL
;
1629 DEBUG(10, ("Entering um_sys_acl_get_file\n"));
1631 if (!is_in_media_files(smb_fname
->base_name
)) {
1632 return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle
, smb_fname
,
1636 status
= alloc_get_client_smb_fname(handle
,
1641 ret
= (SMB_ACL_T
)NULL
;
1645 ret
= SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle
, client_fname
,
1649 if (ret
== (SMB_ACL_T
)NULL
) {
1650 saved_errno
= errno
;
1652 TALLOC_FREE(client_fname
);
1653 if (saved_errno
!= 0) {
1654 errno
= saved_errno
;
1659 static int um_sys_acl_set_file(vfs_handle_struct
*handle
,
1660 const struct smb_filename
*smb_fname
,
1661 SMB_ACL_TYPE_T acltype
,
1665 int saved_errno
= 0;
1666 struct smb_filename
*client_fname
= NULL
;
1668 DEBUG(10, ("Entering um_sys_acl_set_file\n"));
1670 if (!is_in_media_files(smb_fname
->base_name
)) {
1671 return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle
, smb_fname
,
1675 status
= alloc_get_client_smb_fname(handle
,
1683 status
= SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle
, client_fname
,
1688 saved_errno
= errno
;
1690 TALLOC_FREE(client_fname
);
1691 if (saved_errno
!= 0) {
1692 errno
= saved_errno
;
1697 static int um_sys_acl_delete_def_file(vfs_handle_struct
*handle
,
1698 const struct smb_filename
*smb_fname
)
1701 int saved_errno
= 0;
1702 struct smb_filename
*client_fname
= NULL
;
1704 DEBUG(10, ("Entering um_sys_acl_delete_def_file\n"));
1706 if (!is_in_media_files(smb_fname
->base_name
)) {
1707 return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle
,
1711 status
= alloc_get_client_smb_fname(handle
,
1719 status
= SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle
, client_fname
);
1723 saved_errno
= errno
;
1725 TALLOC_FREE(client_fname
);
1726 if (saved_errno
!= 0) {
1727 errno
= saved_errno
;
1732 static ssize_t
um_getxattr(struct vfs_handle_struct
*handle
,
1733 const struct smb_filename
*smb_fname
,
1739 struct smb_filename
*client_fname
= NULL
;
1742 DEBUG(10, ("Entering um_getxattr\n"));
1743 if (!is_in_media_files(smb_fname
->base_name
)) {
1744 return SMB_VFS_NEXT_GETXATTR(handle
, smb_fname
,
1748 status
= alloc_get_client_smb_fname(handle
,
1757 ret
= SMB_VFS_NEXT_GETXATTR(handle
, client_fname
, name
, value
, size
);
1759 TALLOC_FREE(client_fname
);
1763 static ssize_t
um_listxattr(struct vfs_handle_struct
*handle
,
1764 const struct smb_filename
*smb_fname
,
1769 struct smb_filename
*client_fname
= NULL
;
1772 DEBUG(10, ("Entering um_listxattr\n"));
1774 if (!is_in_media_files(smb_fname
->base_name
)) {
1775 return SMB_VFS_NEXT_LISTXATTR(handle
, smb_fname
, list
, size
);
1778 status
= alloc_get_client_smb_fname(handle
,
1787 ret
= SMB_VFS_NEXT_LISTXATTR(handle
, client_fname
, list
, size
);
1790 TALLOC_FREE(client_fname
);
1794 static int um_removexattr(struct vfs_handle_struct
*handle
,
1795 const struct smb_filename
*smb_fname
,
1799 struct smb_filename
*client_fname
= NULL
;
1801 DEBUG(10, ("Entering um_removexattr\n"));
1803 if (!is_in_media_files(smb_fname
->base_name
)) {
1804 return SMB_VFS_NEXT_REMOVEXATTR(handle
, smb_fname
, name
);
1807 status
= alloc_get_client_smb_fname(handle
,
1815 status
= SMB_VFS_NEXT_REMOVEXATTR(handle
, client_fname
, name
);
1818 TALLOC_FREE(client_fname
);
1822 static int um_setxattr(struct vfs_handle_struct
*handle
,
1823 const struct smb_filename
*smb_fname
,
1830 struct smb_filename
*client_fname
= NULL
;
1832 DEBUG(10, ("Entering um_setxattr\n"));
1834 if (!is_in_media_files(smb_fname
->base_name
)) {
1835 return SMB_VFS_NEXT_SETXATTR(handle
, smb_fname
, name
, value
,
1839 status
= alloc_get_client_smb_fname(handle
,
1847 status
= SMB_VFS_NEXT_SETXATTR(handle
, client_fname
, name
, value
,
1851 TALLOC_FREE(client_fname
);
1855 static int um_connect(vfs_handle_struct
*handle
,
1856 const char *service
,
1860 struct um_config_data
*config
;
1863 rc
= SMB_VFS_NEXT_CONNECT(handle
, service
, user
);
1868 config
= talloc_zero(handle
->conn
, struct um_config_data
);
1870 DEBUG(1, ("talloc_zero() failed\n"));
1875 enumval
= lp_parm_enum(SNUM(handle
->conn
), UM_PARAM_TYPE_NAME
,
1876 "clientid", um_clientid
, UM_CLIENTID_NAME
);
1877 if (enumval
== -1) {
1878 DEBUG(1, ("value for %s: type unknown\n",
1879 UM_PARAM_TYPE_NAME
));
1882 config
->clientid
= (enum um_clientid
)enumval
;
1884 SMB_VFS_HANDLE_SET_DATA(handle
, config
,
1885 NULL
, struct um_config_data
,
1891 /* VFS operations structure */
1893 static struct vfs_fn_pointers vfs_um_fns
= {
1894 .connect_fn
= um_connect
,
1896 /* Disk operations */
1898 .statvfs_fn
= um_statvfs
,
1900 /* Directory operations */
1902 .opendir_fn
= um_opendir
,
1903 .fdopendir_fn
= um_fdopendir
,
1904 .readdir_fn
= um_readdir
,
1905 .seekdir_fn
= um_seekdir
,
1906 .telldir_fn
= um_telldir
,
1907 .rewind_dir_fn
= um_rewinddir
,
1908 .mkdir_fn
= um_mkdir
,
1909 .rmdir_fn
= um_rmdir
,
1910 .closedir_fn
= um_closedir
,
1911 .init_search_op_fn
= um_init_search_op
,
1913 /* File operations */
1916 .create_file_fn
= um_create_file
,
1917 .rename_fn
= um_rename
,
1919 .lstat_fn
= um_lstat
,
1920 .fstat_fn
= um_fstat
,
1921 .unlink_fn
= um_unlink
,
1922 .chmod_fn
= um_chmod
,
1923 .chown_fn
= um_chown
,
1924 .lchown_fn
= um_lchown
,
1925 .chdir_fn
= um_chdir
,
1926 .ntimes_fn
= um_ntimes
,
1927 .symlink_fn
= um_symlink
,
1928 .readlink_fn
= um_readlink
,
1930 .mknod_fn
= um_mknod
,
1931 .realpath_fn
= um_realpath
,
1932 .chflags_fn
= um_chflags
,
1933 .streaminfo_fn
= um_streaminfo
,
1935 /* NT ACL operations. */
1937 .get_nt_acl_fn
= um_get_nt_acl
,
1939 /* POSIX ACL operations. */
1941 .chmod_acl_fn
= um_chmod_acl
,
1943 .sys_acl_get_file_fn
= um_sys_acl_get_file
,
1944 .sys_acl_set_file_fn
= um_sys_acl_set_file
,
1945 .sys_acl_delete_def_file_fn
= um_sys_acl_delete_def_file
,
1947 /* EA operations. */
1948 .getxattr_fn
= um_getxattr
,
1949 .listxattr_fn
= um_listxattr
,
1950 .removexattr_fn
= um_removexattr
,
1951 .setxattr_fn
= um_setxattr
,
1954 NTSTATUS
vfs_unityed_media_init(TALLOC_CTX
*);
1955 NTSTATUS
vfs_unityed_media_init(TALLOC_CTX
*ctx
)
1957 NTSTATUS ret
= smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
1958 "unityed_media", &vfs_um_fns
);
1959 if (!NT_STATUS_IS_OK(ret
)) {
1963 vfs_um_debug_level
= debug_add_class("unityed_media");
1965 if (vfs_um_debug_level
== -1) {
1966 vfs_um_debug_level
= DBGC_VFS
;
1967 DEBUG(1, ("unityed_media_init: Couldn't register custom "
1968 "debugging class.\n"));