LCOV - code coverage report
Current view: top level - source3/modules - vfs_unityed_media.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 6 590 1.0 %
Date: 2024-06-13 04:01:37 Functions: 1 34 2.9 %

          Line data    Source code
       1             : /*
       2             :  * Samba VFS module supporting multiple AVID clients sharing media.
       3             :  *
       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>
       8             :  *
       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.
      13             :  *
      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.
      18             :  *
      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
      22             :  * 02110-1301, USA.
      23             :  */
      24             : 
      25             : /*
      26             :  * Unityed Media is a Samba VFS module that allows multiple AVID
      27             :  * clients to share media.
      28             :  *
      29             :  * Add this module to the vfs objects option in your Samba share
      30             :  * configuration.
      31             :  * eg.
      32             :  *
      33             :  *   [avid_win]
      34             :  *      path = /video
      35             :  *      vfs objects = unityed_media
      36             :  *      ...
      37             :  *
      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 *):
      41             :  *
      42             :  *      veto files = /.DS_Store/._@/.Trash@/.Spotlight@/.hidden/.hotfiles@/.vol/
      43             :  *      delete veto files = yes
      44             :  *
      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
      47             :  * the list.
      48             :  *
      49             :  * Notes:
      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
      53             :  * general use.
      54             :  */
      55             : 
      56             : 
      57             : #include "includes.h"
      58             : #include "system/filesys.h"
      59             : #include "smbd/smbd.h"
      60             : #include "../smbd/globals.h"
      61             : #include "auth.h"
      62             : #include "../lib/tsocket/tsocket.h"
      63             : #include "lib/util/smb_strtox.h"
      64             : #include <libgen.h>
      65             : #include "source3/lib/substitute.h"
      66             : 
      67             : #define UM_PARAM_TYPE_NAME "unityed_media"
      68             : 
      69             : static const char *AVID_MXF_DIRNAME = "Avid MediaFiles/MXF";
      70             : static const size_t AVID_MXF_DIRNAME_LEN = 19;
      71             : static const char *OMFI_MEDIAFILES_DIRNAME = "OMFI MediaFiles";
      72             : static const size_t OMFI_MEDIAFILES_DIRNAME_LEN = 15;
      73             : static const char *APPLE_DOUBLE_PREFIX = "._";
      74             : static const size_t APPLE_DOUBLE_PREFIX_LEN = 2;
      75             : static int vfs_um_debug_level = DBGC_VFS;
      76             : 
      77             : enum um_clientid {UM_CLIENTID_NAME, UM_CLIENTID_IP, UM_CLIENTID_HOSTNAME};
      78             : 
      79             : struct um_config_data {
      80             :         enum um_clientid clientid;
      81             : };
      82             : 
      83             : static const struct enum_list um_clientid[] = {
      84             :         {UM_CLIENTID_NAME, "user"},
      85             :         {UM_CLIENTID_IP, "ip"},
      86             :         {UM_CLIENTID_HOSTNAME, "hostname"},
      87             :         {-1, NULL}
      88             : };
      89             : 
      90             : /* supplements the directory list stream */
      91             : typedef struct um_dirinfo_struct {
      92             :         DIR* dirstream;
      93             :         char *dirpath;
      94             :         char *clientPath;
      95             :         bool isInMediaFiles;
      96             :         char *clientSubDirname;
      97             : } um_dirinfo_struct;
      98             : 
      99             : /**
     100             :  * Returns true and first group of digits in path, false and 0 otherwise
     101             :  **/
     102           0 : static bool get_digit_group(const char *path, uintmax_t *digit)
     103             : {
     104           0 :         const char *p = path;
     105             :         codepoint_t cp;
     106             :         size_t size;
     107           0 :         int error = 0;
     108             : 
     109           0 :         DEBUG(10, ("get_digit_group entering with path '%s'\n",
     110             :                    path));
     111             : 
     112             :         /*
     113             :          * Delibiretly initialize to 0 because callers use this result
     114             :          * even though the string doesn't contain any number and we
     115             :          * returned false
     116             :          */
     117           0 :         *digit = 0;
     118             : 
     119           0 :         while (*p) {
     120           0 :                 cp = next_codepoint(p, &size);
     121           0 :                 if (cp == -1) {
     122           0 :                         return false;
     123             :                 }
     124           0 :                 if ((size == 1) && (isdigit(cp))) {
     125           0 :                         *digit = (uintmax_t)smb_strtoul(p,
     126             :                                                         NULL,
     127             :                                                         10,
     128             :                                                         &error,
     129             :                                                         SMB_STR_STANDARD);
     130           0 :                         if (error != 0) {
     131           0 :                                 return false;
     132             :                         }
     133           0 :                         DEBUG(10, ("num_suffix = '%ju'\n",
     134             :                                    *digit));
     135           0 :                         return true;
     136             :                 }
     137           0 :                 p += size;
     138             :         }
     139             : 
     140           0 :         return false;
     141             : }
     142             : 
     143             : /* Add "_<remote_name>.<number>" suffix to path or filename.
     144             :  *
     145             :  * Success: return 0
     146             :  * Failure: set errno, path NULL, return -1
     147             :  */
     148             : 
     149           0 : static int alloc_append_client_suffix(vfs_handle_struct *handle,
     150             :                                       char **path)
     151             : {
     152           0 :         int status = 0;
     153             :         uintmax_t number;
     154             :         const char *clientid;
     155             :         struct um_config_data *config;
     156             : 
     157           0 :         DEBUG(10, ("Entering with path '%s'\n", *path));
     158             : 
     159           0 :         SMB_VFS_HANDLE_GET_DATA(handle, config,
     160             :                                 struct um_config_data,
     161             :                                 return -1);
     162             : 
     163           0 :         (void)get_digit_group(*path, &number);
     164             : 
     165           0 :         switch (config->clientid) {
     166             : 
     167           0 :         case UM_CLIENTID_IP:
     168           0 :                 clientid = tsocket_address_inet_addr_string(
     169           0 :                         handle->conn->sconn->remote_address, talloc_tos());
     170           0 :                 if (clientid == NULL) {
     171           0 :                         errno = ENOMEM;
     172           0 :                         status = -1;
     173           0 :                         goto err;
     174             :                 }
     175           0 :                 break;
     176             : 
     177           0 :         case UM_CLIENTID_HOSTNAME:
     178           0 :                 clientid = get_remote_machine_name();
     179           0 :                 break;
     180             : 
     181           0 :         case UM_CLIENTID_NAME:
     182             :         default:
     183           0 :                 clientid = get_current_username();
     184           0 :                 break;
     185             :         }
     186             : 
     187           0 :         *path = talloc_asprintf_append(*path, "_%s.%ju",
     188             :                                        clientid, number);
     189           0 :         if (*path == NULL) {
     190           0 :                 DEBUG(1, ("alloc_append_client_suffix "
     191             :                                      "out of memory\n"));
     192           0 :                 errno = ENOMEM;
     193           0 :                 status = -1;
     194           0 :                 goto err;
     195             :         }
     196           0 :         DEBUG(10, ("Leaving with *path '%s'\n", *path));
     197           0 : err:
     198           0 :         return status;
     199             : }
     200             : 
     201             : /* Returns true if the file or directory begins with the appledouble
     202             :  * prefix.
     203             :  */
     204           0 : static bool is_apple_double(const char* fname)
     205             : {
     206           0 :         bool ret = false;
     207             : 
     208           0 :         DEBUG(10, ("Entering with fname '%s'\n", fname));
     209             : 
     210           0 :         if (strnequal(APPLE_DOUBLE_PREFIX, fname, APPLE_DOUBLE_PREFIX_LEN)) {
     211           0 :                 ret = true;
     212             :         }
     213           0 :         DEBUG(10, ("Leaving with ret '%s'\n",
     214             :                               ret == true ? "true" : "false"));
     215           0 :         return ret;
     216             : }
     217             : 
     218           0 : static bool starts_with_media_dir(const char* media_dirname,
     219             :                                   size_t media_dirname_len,
     220             :                                   const char *path)
     221             : {
     222           0 :         bool ret = false;
     223           0 :         const char *path_start = path;
     224             : 
     225           0 :         DEBUG(10, ("Entering with media_dirname '%s' "
     226             :                               "path '%s'\n", media_dirname, path));
     227             : 
     228             :         /* Sometimes Samba gives us "./OMFI MediaFiles". */
     229           0 :         if (strnequal(path, "./", 2)) {
     230           0 :                 path_start += 2;
     231             :         }
     232             : 
     233           0 :         if (strnequal(media_dirname, path_start, media_dirname_len)
     234           0 :             &&
     235           0 :             ((path_start[media_dirname_len] == '\0') ||
     236           0 :              (path_start[media_dirname_len] == '/'))) {
     237           0 :                 ret = true;
     238             :         }
     239             : 
     240           0 :         DEBUG(10, ("Leaving with ret '%s'\n",
     241             :                               ret == true ? "true" : "false"));
     242           0 :         return ret;
     243             : }
     244             : 
     245             : /*
     246             :  * Returns true if the file or directory referenced by the path is ONE
     247             :  * LEVEL below the AVID_MXF_DIRNAME or OMFI_MEDIAFILES_DIRNAME
     248             :  * directory
     249             :  */
     250           0 : static bool is_in_media_dir(const char *path)
     251             : {
     252           0 :         int transition_count = 0;
     253           0 :         const char *path_start = path;
     254             :         const char *p;
     255             :         const char *media_dirname;
     256             :         size_t media_dirname_len;
     257             : 
     258           0 :         DEBUG(10, ("Entering with path'%s' ", path));
     259             : 
     260             :         /* Sometimes Samba gives us "./OMFI MediaFiles". */
     261           0 :         if (strnequal(path, "./", 2)) {
     262           0 :                 path_start += 2;
     263             :         }
     264             : 
     265           0 :         if (strnequal(path_start, AVID_MXF_DIRNAME, AVID_MXF_DIRNAME_LEN)) {
     266           0 :                 media_dirname = AVID_MXF_DIRNAME;
     267           0 :                 media_dirname_len = AVID_MXF_DIRNAME_LEN;
     268           0 :         } else if (strnequal(path_start,
     269             :                              OMFI_MEDIAFILES_DIRNAME,
     270             :                              OMFI_MEDIAFILES_DIRNAME_LEN)) {
     271           0 :                 media_dirname = OMFI_MEDIAFILES_DIRNAME;
     272           0 :                 media_dirname_len = OMFI_MEDIAFILES_DIRNAME_LEN;
     273             :         } else {
     274           0 :                 return false;
     275             :         }
     276             : 
     277           0 :         if (path_start[media_dirname_len] == '\0') {
     278           0 :                 goto out;
     279             :         }
     280             : 
     281           0 :         p = path_start + media_dirname_len + 1;
     282             : 
     283             :         while (true) {
     284           0 :                 if (*p == '\0' || *p == '/') {
     285           0 :                         if (strnequal(p - 3, "/..", 3)) {
     286           0 :                                 transition_count--;
     287           0 :                         } else if ((p[-1] != '/') || !strnequal(p - 2, "/.", 2)) {
     288           0 :                                 transition_count++;
     289             :                         }
     290             :                 }
     291           0 :                 if (*p == '\0') {
     292           0 :                         break;
     293             :                 }
     294           0 :                 p++;
     295             :         }
     296             : 
     297           0 : out:
     298           0 :         DEBUG(10, ("Going out with transition_count '%i'\n",
     299             :                               transition_count));
     300           0 :         if (((transition_count == 1) && (media_dirname == AVID_MXF_DIRNAME))
     301           0 :             ||
     302           0 :             ((transition_count == 0) && (media_dirname == OMFI_MEDIAFILES_DIRNAME))) {
     303           0 :                 return true;
     304             :         }
     305           0 :         else return false;
     306             : }
     307             : 
     308             : /*
     309             :  * Returns true if the file or directory referenced by the path is
     310             :  * below the AVID_MEDIAFILES_DIRNAME or OMFI_MEDIAFILES_DIRNAME
     311             :  * directory The AVID_MEDIAFILES_DIRNAME and OMFI_MEDIAFILES_DIRNAME
     312             :  * are assumed to be in the root directory, which is generally a safe
     313             :  * assumption in the fixed-path world of Avid.
     314             :  */
     315           0 : static bool is_in_media_files(const char *path)
     316             : {
     317           0 :         bool ret = false;
     318             : 
     319           0 :         DEBUG(10, ("Entering with path '%s'\n", path));
     320             : 
     321           0 :         if (starts_with_media_dir(AVID_MXF_DIRNAME,
     322           0 :                                   AVID_MXF_DIRNAME_LEN, path) ||
     323           0 :             starts_with_media_dir(OMFI_MEDIAFILES_DIRNAME,
     324             :                                   OMFI_MEDIAFILES_DIRNAME_LEN, path)) {
     325           0 :                 ret = true;
     326             :         }
     327           0 :         DEBUG(10, ("Leaving with ret '%s'\n",
     328             :                               ret == true ? "true" : "false"));
     329           0 :         return ret;
     330             : }
     331             : 
     332             : 
     333             : /* Add client suffix to "pure-number" path.
     334             :  *
     335             :  * Caller must free newPath.
     336             :  *
     337             :  * Success: return 0
     338             :  * Failure: set errno, newPath NULL, return -1
     339             :  */
     340           0 : static int alloc_get_client_path(vfs_handle_struct *handle,
     341             :                                  TALLOC_CTX *ctx,
     342             :                                  const char *path_in,
     343             :                                  char **path_out)
     344             : {
     345           0 :         int status = 0;
     346             :         char *p;
     347             :         char *digits;
     348             :         size_t digits_len;
     349             :         uintmax_t number;
     350             : 
     351           0 :         *path_out = talloc_strdup(ctx, path_in);
     352           0 :         if (*path_out == NULL) {
     353           0 :                 DEBUG(1, ("alloc_get_client_path ENOMEM\n"));
     354           0 :                 return -1;
     355             :         }
     356             : 
     357           0 :         (void)get_digit_group(*path_out, &number);
     358             : 
     359           0 :         digits = talloc_asprintf(NULL, "%ju", number);
     360           0 :         if (digits == NULL) {
     361           0 :                 DEBUG(1, ("alloc_get_client_path ENOMEM\n"));
     362           0 :                 return -1;
     363             :         }
     364           0 :         digits_len = strlen(digits);
     365             : 
     366           0 :         p = strstr_m(path_in, digits);
     367           0 :         if ((p)
     368           0 :             &&
     369           0 :             ((p[digits_len] == '\0') || (p[digits_len] == '/'))
     370           0 :             &&
     371           0 :             (((p - path_in > 0) && (p[-1] == '/'))
     372           0 :              ||
     373           0 :              (((p - path_in) > APPLE_DOUBLE_PREFIX_LEN)
     374           0 :               &&
     375           0 :               is_apple_double(p - APPLE_DOUBLE_PREFIX_LEN)
     376           0 :               &&
     377           0 :               (p[-(APPLE_DOUBLE_PREFIX_LEN + 1)] == '/'))))
     378             :         {
     379           0 :                 (*path_out)[p - path_in + digits_len] = '\0';
     380             : 
     381           0 :                 status = alloc_append_client_suffix(handle, path_out);
     382           0 :                 if (status != 0) {
     383           0 :                         goto out;
     384             :                 }
     385             : 
     386           0 :                 *path_out = talloc_strdup_append(*path_out, p + digits_len);
     387           0 :                 if (*path_out == NULL) {
     388           0 :                         DEBUG(1, ("alloc_get_client_path ENOMEM\n"));
     389           0 :                         status = -1;
     390           0 :                         goto out;
     391             :                 }
     392             :         }
     393           0 : out:
     394             :         /* path_out must be freed in caller. */
     395           0 :         DEBUG(10, ("Result:'%s'\n", *path_out));
     396           0 :         return status;
     397             : }
     398             : 
     399             : /*
     400             :  * Success: return 0
     401             :  * Failure: set errno, return -1
     402             :  */
     403           0 : static int alloc_get_client_smb_fname(struct vfs_handle_struct *handle,
     404             :                                       TALLOC_CTX *ctx,
     405             :                                       const struct smb_filename *smb_fname,
     406             :                                       struct smb_filename **client_fname)
     407             : {
     408             :         int status ;
     409             : 
     410           0 :         DEBUG(10, ("Entering with smb_fname->base_name '%s'\n",
     411             :                    smb_fname->base_name));
     412             : 
     413           0 :         *client_fname = cp_smb_filename(ctx, smb_fname);
     414           0 :         if (*client_fname == NULL) {
     415           0 :                 DEBUG(1, ("cp_smb_filename returned NULL\n"));
     416           0 :                 return -1;
     417             :         }
     418           0 :         status = alloc_get_client_path(handle, ctx,
     419           0 :                                        smb_fname->base_name,
     420           0 :                                        &(*client_fname)->base_name);
     421           0 :         if (status != 0) {
     422           0 :                 return -1;
     423             :         }
     424             : 
     425           0 :         DEBUG(10, ("Leaving with (*client_fname)->base_name "
     426             :                    "'%s'\n", (*client_fname)->base_name));
     427             : 
     428           0 :         return 0;
     429             : }
     430             : 
     431             : 
     432             : /*
     433             :  * Success: return 0
     434             :  * Failure: set errno, return -1
     435             :  */
     436           0 : static int alloc_set_client_dirinfo_path(struct vfs_handle_struct *handle,
     437             :                                          TALLOC_CTX *ctx,
     438             :                                          char **path,
     439             :                                          const char *suffix_number)
     440             : {
     441             :         int status;
     442             : 
     443           0 :         DEBUG(10, ("Entering with suffix_number '%s'\n",
     444             :                    suffix_number));
     445             : 
     446           0 :         *path = talloc_strdup(ctx, suffix_number);
     447           0 :         if (*path == NULL) {
     448           0 :                 DEBUG(1, ("alloc_set_client_dirinfo_path ENOMEM\n"));
     449           0 :                 return -1;
     450             :         }
     451           0 :         status = alloc_append_client_suffix(handle, path);
     452           0 :         if (status != 0) {
     453           0 :                 return -1;
     454             :         }
     455             : 
     456           0 :         DEBUG(10, ("Leaving with *path '%s'\n", *path));
     457             : 
     458           0 :         return 0;
     459             : }
     460             : 
     461           0 : static int alloc_set_client_dirinfo(vfs_handle_struct *handle,
     462             :                                     const char *fname,
     463             :                                     struct um_dirinfo_struct **di_result)
     464             : {
     465           0 :         int status = 0;
     466             :         char *digits;
     467             :         uintmax_t number;
     468             :         struct um_dirinfo_struct *dip;
     469             : 
     470           0 :         DEBUG(10, ("Entering with fname '%s'\n", fname));
     471             : 
     472           0 :         *di_result = talloc(NULL, struct um_dirinfo_struct);
     473           0 :         if (*di_result == NULL) {
     474           0 :                 goto err;
     475             :         }
     476           0 :         dip = *di_result;
     477             : 
     478           0 :         dip->dirpath = talloc_strdup(dip, fname);
     479           0 :         if (dip->dirpath == NULL) {
     480           0 :                 goto err;
     481             :         }
     482             : 
     483           0 :         if (!is_in_media_files(fname)) {
     484           0 :                 dip->isInMediaFiles = false;
     485           0 :                 dip->clientPath = NULL;
     486           0 :                 dip->clientSubDirname = NULL;
     487           0 :                 goto out;
     488             :         }
     489             : 
     490           0 :         dip->isInMediaFiles = true;
     491             : 
     492           0 :         (void)get_digit_group(fname, &number);
     493           0 :         digits = talloc_asprintf(talloc_tos(), "%ju", number);
     494           0 :         if (digits == NULL) {
     495           0 :                 goto err;
     496             :         }
     497             : 
     498           0 :         status = alloc_set_client_dirinfo_path(handle, dip,
     499             :                                                &dip->clientSubDirname,
     500             :                                                digits);
     501           0 :         if (status != 0) {
     502           0 :                 goto err;
     503             :         }
     504             : 
     505           0 :         status = alloc_get_client_path(handle, dip, fname,
     506             :                                        &dip->clientPath);
     507           0 :         if (status != 0 || dip->clientPath == NULL) {
     508             :                 goto err;
     509             :         }
     510             : 
     511           0 : out:
     512           0 :         DEBUG(10, ("Leaving with (*dirInfo)->dirpath '%s', "
     513             :                               "(*dirInfo)->clientPath '%s'\n",
     514             :                               dip->dirpath, dip->clientPath));
     515           0 :         return status;
     516             : 
     517           0 : err:
     518           0 :         DEBUG(1, ("Failing with fname '%s'\n", fname));
     519           0 :         TALLOC_FREE(*di_result);
     520           0 :         status = -1;
     521           0 :         errno = ENOMEM;
     522           0 :         return status;
     523             : }
     524             : 
     525             : /**********************************************************************
     526             :  * VFS functions
     527             :  **********************************************************************/
     528             : 
     529             : /*
     530             :  * Success: return 0
     531             :  * Failure: set errno, return -1
     532             :  */
     533           0 : static int um_statvfs(struct vfs_handle_struct *handle,
     534             :                       const struct smb_filename *smb_fname,
     535             :                       struct vfs_statvfs_struct *statbuf)
     536             : {
     537             :         int status;
     538           0 :         struct smb_filename *client_fname = NULL;
     539             : 
     540           0 :         DEBUG(10, ("Entering with path '%s'\n", smb_fname->base_name));
     541             : 
     542           0 :         if (!is_in_media_files(smb_fname->base_name)) {
     543           0 :                 return SMB_VFS_NEXT_STATVFS(handle, smb_fname, statbuf);
     544             :         }
     545             : 
     546           0 :         status = alloc_get_client_smb_fname(handle,
     547             :                                 talloc_tos(),
     548             :                                 smb_fname,
     549             :                                 &client_fname);
     550           0 :         if (status != 0) {
     551           0 :                 goto err;
     552             :         }
     553             : 
     554           0 :         status = SMB_VFS_NEXT_STATVFS(handle, client_fname, statbuf);
     555           0 : err:
     556           0 :         TALLOC_FREE(client_fname);
     557           0 :         DEBUG(10, ("Leaving with path '%s'\n", smb_fname->base_name));
     558           0 :         return status;
     559             : }
     560             : 
     561           0 : static DIR *um_fdopendir(vfs_handle_struct *handle,
     562             :                          files_struct *fsp,
     563             :                          const char *mask,
     564             :                          uint32_t attr)
     565             : {
     566           0 :         struct um_dirinfo_struct *dirInfo = NULL;
     567             :         DIR *dirstream;
     568             : 
     569           0 :         DEBUG(10, ("Entering with fsp->fsp_name->base_name '%s'\n",
     570             :                    fsp->fsp_name->base_name));
     571             : 
     572           0 :         dirstream = SMB_VFS_NEXT_FDOPENDIR(handle, fsp, mask, attr);
     573           0 :         if (!dirstream) {
     574           0 :                 goto err;
     575             :         }
     576             : 
     577           0 :         if (alloc_set_client_dirinfo(handle,
     578           0 :                                      fsp->fsp_name->base_name,
     579             :                                      &dirInfo)) {
     580           0 :                 goto err;
     581             :         }
     582             : 
     583           0 :         dirInfo->dirstream = dirstream;
     584             : 
     585           0 :         if (!dirInfo->isInMediaFiles) {
     586             :                 /*
     587             :                  * FIXME: this is the original code, something must be
     588             :                  * missing here, but what? -slow
     589             :                  */
     590           0 :                 goto out;
     591             :         }
     592             : 
     593           0 : out:
     594           0 :         DEBUG(10, ("Leaving with dirInfo->dirpath '%s', "
     595             :                    "dirInfo->clientPath '%s', "
     596             :                    "fsp->fsp_name->st.st_ex_mtime %s",
     597             :                    dirInfo->dirpath,
     598             :                    dirInfo->clientPath,
     599             :                    ctime(&(fsp->fsp_name->st.st_ex_mtime.tv_sec))));
     600           0 :         return (DIR *) dirInfo;
     601             : 
     602           0 : err:
     603           0 :         DEBUG(1, ("Failing with fsp->fsp_name->base_name '%s'\n",
     604             :                   fsp->fsp_name->base_name));
     605           0 :         TALLOC_FREE(dirInfo);
     606           0 :         return NULL;
     607             : }
     608             : 
     609             : /*
     610             :  * skip own suffixed directory
     611             :  * replace own suffixed directory with non suffixed.
     612             :  *
     613             :  * Success: return dirent
     614             :  * End of data: return NULL
     615             :  * Failure: set errno, return NULL
     616             :  */
     617           0 : static struct dirent *um_readdir(vfs_handle_struct *handle,
     618             :                                  struct files_struct *dirfsp,
     619             :                                  DIR *dirp,
     620             :                                  SMB_STRUCT_STAT *sbuf)
     621             : {
     622           0 :         um_dirinfo_struct* dirInfo = (um_dirinfo_struct*)dirp;
     623           0 :         struct dirent *d = NULL;
     624             :         int skip;
     625             : 
     626           0 :         DEBUG(10, ("dirInfo->dirpath '%s', "
     627             :                    "dirInfo->clientPath '%s', "
     628             :                    "dirInfo->isInMediaFiles '%s', "
     629             :                    "dirInfo->clientSubDirname '%s'\n",
     630             :                    dirInfo->dirpath,
     631             :                    dirInfo->clientPath,
     632             :                    dirInfo->isInMediaFiles ? "true" : "false",
     633             :                    dirInfo->clientSubDirname));
     634             : 
     635           0 :         if (!dirInfo->isInMediaFiles) {
     636           0 :                 return SMB_VFS_NEXT_READDIR(handle, dirfsp, dirInfo->dirstream, sbuf);
     637             :         }
     638             : 
     639             :         do {
     640             :                 const char* dname;
     641             :                 bool isAppleDouble;
     642             :                 char *digits;
     643             :                 size_t digits_len;
     644             :                 uintmax_t number;
     645             : 
     646           0 :                 skip = false;
     647           0 :                 d = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirInfo->dirstream, sbuf);
     648             : 
     649           0 :                 if (d == NULL) {
     650           0 :                         break;
     651             :                 }
     652             : 
     653             :                 /* ignore apple double prefix for logic below */
     654           0 :                 if (is_apple_double(d->d_name)) {
     655           0 :                         dname = &d->d_name[APPLE_DOUBLE_PREFIX_LEN];
     656           0 :                         isAppleDouble = true;
     657             :                 } else {
     658           0 :                         dname = d->d_name;
     659           0 :                         isAppleDouble = false;
     660             :                 }
     661             : 
     662           0 :                 DEBUG(10, ("dname = '%s'\n", dname));
     663             : 
     664           0 :                 (void)get_digit_group(dname, &number);
     665           0 :                 digits = talloc_asprintf(talloc_tos(), "%ju", number);
     666           0 :                 if (digits == NULL) {
     667           0 :                         DEBUG(1, ("out of memory"));
     668           0 :                         goto err;
     669             :                 }
     670           0 :                 digits_len = strlen(digits);
     671             : 
     672           0 :                 if (alloc_set_client_dirinfo_path(handle,
     673             :                                                   dirInfo,
     674             :                                                   &((dirInfo)->clientSubDirname),
     675             :                                                   digits)) {
     676           0 :                         goto err;
     677             :                 }
     678             : 
     679             :                 /*
     680             :                  * If set to "true", vfs shows digits-only
     681             :                  * non-suffixed subdirectories.  Normally, such
     682             :                  * subdirectories can exists only in non-media
     683             :                  * directories, so we set it to "false".  Otherwise,
     684             :                  * if we have such subdirectories (probably created
     685             :                  * over not "unityed" connection), it can be little
     686             :                  * bit confusing.
     687             :                  */
     688           0 :                 if (strequal(dname, digits)) {
     689           0 :                         skip = false;
     690           0 :                 } else if (strequal(dname, dirInfo->clientSubDirname)) {
     691             :                         /*
     692             :                          * Remove suffix of this client's suffixed
     693             :                          * subdirectories
     694             :                          */
     695           0 :                         if (isAppleDouble) {
     696           0 :                                 d->d_name[digits_len + APPLE_DOUBLE_PREFIX_LEN] = '\0';
     697             :                         } else {
     698           0 :                                 d->d_name[digits_len] = '\0';
     699             :                         }
     700           0 :                 } else if (strnequal(digits, dname, digits_len)) {
     701             :                         /*
     702             :                          * Set to false to see another clients subdirectories
     703             :                          */
     704           0 :                         skip = false;
     705             :                 }
     706           0 :         } while (skip);
     707             : 
     708           0 :         DEBUG(10, ("Leaving um_readdir\n"));
     709           0 :         return d;
     710           0 : err:
     711           0 :         TALLOC_FREE(dirInfo);
     712           0 :         return NULL;
     713             : }
     714             : 
     715           0 : static void um_seekdir(vfs_handle_struct *handle,
     716             :                        DIR *dirp,
     717             :                        long offset)
     718             : {
     719           0 :         DEBUG(10, ("Entering and leaving um_seekdir\n"));
     720           0 :         SMB_VFS_NEXT_SEEKDIR(handle,
     721             :                              ((um_dirinfo_struct*)dirp)->dirstream, offset);
     722           0 : }
     723             : 
     724           0 : static long um_telldir(vfs_handle_struct *handle,
     725             :                        DIR *dirp)
     726             : {
     727           0 :         DEBUG(10, ("Entering and leaving um_telldir\n"));
     728           0 :         return SMB_VFS_NEXT_TELLDIR(handle,
     729             :                                     ((um_dirinfo_struct*)dirp)->dirstream);
     730             : }
     731             : 
     732           0 : static void um_rewinddir(vfs_handle_struct *handle,
     733             :                          DIR *dirp)
     734             : {
     735           0 :         DEBUG(10, ("Entering and leaving um_rewinddir\n"));
     736           0 :         SMB_VFS_NEXT_REWINDDIR(handle,
     737             :                                ((um_dirinfo_struct*)dirp)->dirstream);
     738           0 : }
     739             : 
     740           0 : static int um_mkdirat(vfs_handle_struct *handle,
     741             :                         struct files_struct *dirfsp,
     742             :                         const struct smb_filename *smb_fname,
     743             :                         mode_t mode)
     744             : {
     745             :         int status;
     746           0 :         const char *path = NULL;
     747           0 :         struct smb_filename *client_fname = NULL;
     748           0 :         struct smb_filename *full_fname = NULL;
     749             : 
     750           0 :         full_fname = full_path_from_dirfsp_atname(talloc_tos(),
     751             :                                                   dirfsp,
     752             :                                                   smb_fname);
     753           0 :         if (full_fname == NULL) {
     754           0 :                 return -1;
     755             :         }
     756             : 
     757           0 :         path = full_fname->base_name;
     758           0 :         DEBUG(10, ("Entering with path '%s'\n", path));
     759             : 
     760           0 :         if (!is_in_media_files(path) || !is_in_media_dir(path)) {
     761           0 :                 TALLOC_FREE(full_fname);
     762           0 :                 return SMB_VFS_NEXT_MKDIRAT(handle,
     763             :                                 dirfsp,
     764             :                                 smb_fname,
     765             :                                 mode);
     766             :         }
     767             : 
     768           0 :         status = alloc_get_client_smb_fname(handle,
     769             :                                 talloc_tos(),
     770             :                                 full_fname,
     771             :                                 &client_fname);
     772           0 :         if (status != 0) {
     773           0 :                 goto err;
     774             :         }
     775             : 
     776           0 :         status = SMB_VFS_NEXT_MKDIRAT(handle,
     777             :                                 handle->conn->cwd_fsp,
     778             :                                 client_fname,
     779             :                                 mode);
     780           0 : err:
     781           0 :         DEBUG(10, ("Leaving with path '%s'\n", path));
     782           0 :         TALLOC_FREE(client_fname);
     783           0 :         TALLOC_FREE(full_fname);
     784           0 :         return status;
     785             : }
     786             : 
     787           0 : static int um_closedir(vfs_handle_struct *handle,
     788             :                        DIR *dirp)
     789             : {
     790           0 :         DIR *realdirp = ((um_dirinfo_struct*)dirp)->dirstream;
     791             : 
     792           0 :         TALLOC_FREE(dirp);
     793             : 
     794           0 :         return SMB_VFS_NEXT_CLOSEDIR(handle, realdirp);
     795             : }
     796             : 
     797           0 : static int um_openat(struct vfs_handle_struct *handle,
     798             :                      const struct files_struct *dirfsp,
     799             :                      const struct smb_filename *smb_fname,
     800             :                      struct files_struct *fsp,
     801             :                      const struct vfs_open_how *how)
     802             : {
     803           0 :         struct smb_filename *client_fname = NULL;
     804             :         int ret;
     805             : 
     806           0 :         DBG_DEBUG("Entering with smb_fname->base_name '%s'\n",
     807             :                   smb_fname->base_name);
     808             : 
     809           0 :         if (!is_in_media_files(smb_fname->base_name)) {
     810           0 :                 return SMB_VFS_NEXT_OPENAT(handle,
     811             :                                            dirfsp,
     812             :                                            smb_fname,
     813             :                                            fsp,
     814             :                                            how);
     815             :         }
     816             : 
     817           0 :         if (alloc_get_client_smb_fname(handle, talloc_tos(),
     818             :                                        smb_fname,
     819             :                                        &client_fname)) {
     820           0 :                 ret = -1;
     821           0 :                 goto err;
     822             :         }
     823             : 
     824             :         /*
     825             :          * FIXME:
     826             :          * What about fsp->fsp_name?  We also have to get correct stat
     827             :          * info into fsp and smb_fname for DB files, don't we?
     828             :          */
     829             : 
     830           0 :         DEBUG(10, ("Leaving with smb_fname->base_name '%s' "
     831             :                    "smb_fname->st.st_ex_mtime %s"
     832             :                    "fsp->fsp_name->st.st_ex_mtime %s",
     833             :                    smb_fname->base_name,
     834             :                    ctime(&(smb_fname->st.st_ex_mtime.tv_sec)),
     835             :                    ctime(&(fsp->fsp_name->st.st_ex_mtime.tv_sec))));
     836             : 
     837           0 :         ret = SMB_VFS_NEXT_OPENAT(handle,
     838             :                                   dirfsp,
     839             :                                   client_fname,
     840             :                                   fsp,
     841             :                                   how);
     842           0 : err:
     843           0 :         TALLOC_FREE(client_fname);
     844           0 :         DEBUG(10, ("Leaving with smb_fname->base_name '%s'\n",
     845             :                               smb_fname->base_name));
     846           0 :         return ret;
     847             : }
     848             : 
     849           0 : static NTSTATUS um_create_file(vfs_handle_struct *handle,
     850             :                                struct smb_request *req,
     851             :                                struct files_struct *dirfsp,
     852             :                                struct smb_filename *smb_fname,
     853             :                                uint32_t access_mask,
     854             :                                uint32_t share_access,
     855             :                                uint32_t create_disposition,
     856             :                                uint32_t create_options,
     857             :                                uint32_t file_attributes,
     858             :                                uint32_t oplock_request,
     859             :                                const struct smb2_lease *lease,
     860             :                                uint64_t allocation_size,
     861             :                                uint32_t private_flags,
     862             :                                struct security_descriptor *sd,
     863             :                                struct ea_list *ea_list,
     864             :                                files_struct **result_fsp,
     865             :                                int *pinfo,
     866             :                                const struct smb2_create_blobs *in_context_blobs,
     867             :                                struct smb2_create_blobs *out_context_blobs)
     868             : {
     869             :         NTSTATUS status;
     870           0 :         struct smb_filename *client_fname = NULL;
     871             : 
     872           0 :         DEBUG(10, ("Entering with smb_fname->base_name '%s'\n",
     873             :                    smb_fname->base_name));
     874             : 
     875           0 :         if (!is_in_media_files(smb_fname->base_name)) {
     876           0 :                 return SMB_VFS_NEXT_CREATE_FILE(
     877             :                         handle,
     878             :                         req,
     879             :                         dirfsp,
     880             :                         smb_fname,
     881             :                         access_mask,
     882             :                         share_access,
     883             :                         create_disposition,
     884             :                         create_options,
     885             :                         file_attributes,
     886             :                         oplock_request,
     887             :                         lease,
     888             :                         allocation_size,
     889             :                         private_flags,
     890             :                         sd,
     891             :                         ea_list,
     892             :                         result_fsp,
     893             :                         pinfo,
     894             :                         in_context_blobs,
     895             :                         out_context_blobs);
     896             :         }
     897             : 
     898           0 :         if (alloc_get_client_smb_fname(handle, talloc_tos(),
     899             :                                        smb_fname,
     900             :                                        &client_fname)) {
     901           0 :                 status = map_nt_error_from_unix(errno);
     902           0 :                 goto err;
     903             :         }
     904             : 
     905             :         /*
     906             :          * FIXME:
     907             :          * This only creates files, so we don't have to worry about
     908             :          * our fake directory stat'ing here.  But we still need to
     909             :          * route stat calls for DB files properly, right?
     910             :          */
     911           0 :         status = SMB_VFS_NEXT_CREATE_FILE(
     912             :                 handle,
     913             :                 req,
     914             :                 dirfsp,
     915             :                 client_fname,
     916             :                 access_mask,
     917             :                 share_access,
     918             :                 create_disposition,
     919             :                 create_options,
     920             :                 file_attributes,
     921             :                 oplock_request,
     922             :                 lease,
     923             :                 allocation_size,
     924             :                 private_flags,
     925             :                 sd,
     926             :                 ea_list,
     927             :                 result_fsp,
     928             :                 pinfo,
     929             :                 in_context_blobs,
     930             :                 out_context_blobs);
     931           0 : err:
     932           0 :         TALLOC_FREE(client_fname);
     933           0 :         DEBUG(10, ("Leaving with smb_fname->base_name '%s'"
     934             :                    "smb_fname->st.st_ex_mtime %s"
     935             :                    " fsp->fsp_name->st.st_ex_mtime %s",
     936             :                    smb_fname->base_name,
     937             :                    ctime(&(smb_fname->st.st_ex_mtime.tv_sec)),
     938             :                    (*result_fsp) && VALID_STAT((*result_fsp)->fsp_name->st) ?
     939             :                    ctime(&((*result_fsp)->fsp_name->st.st_ex_mtime.tv_sec)) :
     940             :                    "No fsp time\n"));
     941           0 :         return status;
     942             : }
     943             : 
     944           0 : static int um_renameat(vfs_handle_struct *handle,
     945             :                 files_struct *srcfsp,
     946             :                 const struct smb_filename *smb_fname_src,
     947             :                 files_struct *dstfsp,
     948             :                 const struct smb_filename *smb_fname_dst)
     949             : {
     950             :         int status;
     951           0 :         struct smb_filename *src_full_fname = NULL;
     952           0 :         struct smb_filename *dst_full_fname = NULL;
     953           0 :         struct smb_filename *src_client_fname = NULL;
     954           0 :         struct smb_filename *dst_client_fname = NULL;
     955             : 
     956           0 :         src_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
     957             :                                                   srcfsp,
     958             :                                                   smb_fname_src);
     959           0 :         if (src_full_fname == NULL) {
     960           0 :                 errno = ENOMEM;
     961           0 :                 return -1;
     962             :         }
     963           0 :         dst_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
     964             :                                                   dstfsp,
     965             :                                                   smb_fname_dst);
     966           0 :         if (dst_full_fname == NULL) {
     967           0 :                 TALLOC_FREE(src_full_fname);
     968           0 :                 errno = ENOMEM;
     969           0 :                 return -1;
     970             :         }
     971             : 
     972           0 :         DBG_DEBUG( "Entering with "
     973             :                    "smb_fname_src->base_name '%s', "
     974             :                    "smb_fname_dst->base_name '%s'\n",
     975             :                    smb_fname_src->base_name,
     976             :                    smb_fname_dst->base_name);
     977             : 
     978           0 :         if (!is_in_media_files(src_full_fname->base_name)
     979           0 :             &&
     980           0 :             !is_in_media_files(dst_full_fname->base_name)) {
     981           0 :                 TALLOC_FREE(src_full_fname);
     982           0 :                 TALLOC_FREE(dst_full_fname);
     983           0 :                 return SMB_VFS_NEXT_RENAMEAT(handle,
     984             :                                         srcfsp,
     985             :                                         smb_fname_src,
     986             :                                         dstfsp,
     987             :                                         smb_fname_dst);
     988             :         }
     989             : 
     990           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
     991             :                                             src_full_fname,
     992             :                                             &src_client_fname);
     993           0 :         if (status != 0) {
     994           0 :                 goto err;
     995             :         }
     996             : 
     997           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
     998             :                                             dst_full_fname,
     999             :                                             &dst_client_fname);
    1000             : 
    1001           0 :         if (status != 0) {
    1002           0 :                 goto err;
    1003             :         }
    1004             : 
    1005           0 :         status = SMB_VFS_NEXT_RENAMEAT(handle,
    1006             :                                 handle->conn->cwd_fsp,
    1007             :                                 src_client_fname,
    1008             :                                 handle->conn->cwd_fsp,
    1009             :                                 dst_client_fname);
    1010             : 
    1011           0 : err:
    1012           0 :         TALLOC_FREE(dst_client_fname);
    1013           0 :         TALLOC_FREE(src_client_fname);
    1014           0 :         TALLOC_FREE(src_full_fname);
    1015           0 :         TALLOC_FREE(dst_full_fname);
    1016           0 :         DBG_DEBUG( "Leaving with smb_fname_src->base_name '%s',"
    1017             :                    " smb_fname_dst->base_name '%s'\n",
    1018             :                    smb_fname_src->base_name,
    1019             :                    smb_fname_dst->base_name);
    1020           0 :         return status;
    1021             : }
    1022             : 
    1023             : 
    1024             : /*
    1025             :  * Success: return 0
    1026             :  * Failure: set errno, return -1
    1027             :  */
    1028           0 : static int um_stat(vfs_handle_struct *handle,
    1029             :                    struct smb_filename *smb_fname)
    1030             : {
    1031           0 :         int status = 0;
    1032           0 :         struct smb_filename *client_fname = NULL;
    1033             : 
    1034           0 :         DEBUG(10, ("Entering with smb_fname->base_name '%s'\n",
    1035             :                    smb_fname->base_name));
    1036             : 
    1037           0 :         if (!is_in_media_files(smb_fname->base_name)) {
    1038           0 :                 return SMB_VFS_NEXT_STAT(handle, smb_fname);
    1039             :         }
    1040             : 
    1041           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1042             :                                             smb_fname,
    1043             :                                             &client_fname);
    1044           0 :         if (status != 0) {
    1045           0 :                 goto err;
    1046             :         }
    1047           0 :         DEBUG(10, ("Stat'ing client_fname->base_name '%s'\n",
    1048             :                    client_fname->base_name));
    1049             : 
    1050           0 :         status = SMB_VFS_NEXT_STAT(handle, client_fname);
    1051           0 :         if (status != 0) {
    1052           0 :                 goto err;
    1053             :         }
    1054             : 
    1055             :         /*
    1056             :          * Unlike functions with const smb_filename, we have to modify
    1057             :          * smb_fname itself to pass our info back up.
    1058             :          */
    1059           0 :         DEBUG(10, ("Setting smb_fname '%s' stat from client_fname '%s'\n",
    1060             :                    smb_fname->base_name, client_fname->base_name));
    1061           0 :         smb_fname->st = client_fname->st;
    1062             : 
    1063           0 : err:
    1064           0 :         TALLOC_FREE(client_fname);
    1065           0 :         DEBUG(10, ("Leaving with smb_fname->st.st_ex_mtime %s",
    1066             :                    ctime(&(smb_fname->st.st_ex_mtime.tv_sec))));
    1067           0 :         return status;
    1068             : }
    1069             : 
    1070           0 : static int um_lstat(vfs_handle_struct *handle,
    1071             :                     struct smb_filename *smb_fname)
    1072             : {
    1073           0 :         int status = 0;
    1074           0 :         struct smb_filename *client_fname = NULL;
    1075             : 
    1076           0 :         DEBUG(10, ("Entering with smb_fname->base_name '%s'\n",
    1077             :                    smb_fname->base_name));
    1078             : 
    1079           0 :         if (!is_in_media_files(smb_fname->base_name)) {
    1080           0 :                 return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
    1081             :         }
    1082             : 
    1083           0 :         client_fname = NULL;
    1084             : 
    1085           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1086             :                                             smb_fname,
    1087             :                                             &client_fname);
    1088           0 :         if (status != 0) {
    1089           0 :                 goto err;
    1090             :         }
    1091           0 :         status = SMB_VFS_NEXT_LSTAT(handle, client_fname);
    1092           0 :         if (status != 0) {
    1093           0 :                 goto err;
    1094             :         }
    1095             : 
    1096           0 :         smb_fname->st = client_fname->st;
    1097             : 
    1098           0 : err:
    1099           0 :         TALLOC_FREE(client_fname);
    1100           0 :         DEBUG(10, ("Leaving with smb_fname->st.st_ex_mtime %s",
    1101             :                    ctime(&(smb_fname->st.st_ex_mtime.tv_sec))));
    1102           0 :         return status;
    1103             : }
    1104             : 
    1105           0 : static int um_fstat(vfs_handle_struct *handle,
    1106             :                     files_struct *fsp, SMB_STRUCT_STAT *sbuf)
    1107             : {
    1108           0 :         int status = 0;
    1109             : 
    1110           0 :         DEBUG(10, ("Entering with fsp->fsp_name->base_name "
    1111             :                    "'%s'\n", fsp_str_dbg(fsp)));
    1112             : 
    1113           0 :         status = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
    1114           0 :         if (status != 0) {
    1115           0 :                 goto out;
    1116             :         }
    1117             : 
    1118           0 :         if ((fsp->fsp_name == NULL) ||
    1119           0 :             !is_in_media_files(fsp->fsp_name->base_name)) {
    1120             :                 goto out;
    1121             :         }
    1122             : 
    1123           0 :         status = um_stat(handle, fsp->fsp_name);
    1124           0 :         if (status != 0) {
    1125           0 :                 goto out;
    1126             :         }
    1127             : 
    1128           0 :         *sbuf = fsp->fsp_name->st;
    1129             : 
    1130           0 : out:
    1131           0 :         DEBUG(10, ("Leaving with fsp->fsp_name->st.st_ex_mtime %s\n",
    1132             :                    fsp->fsp_name != NULL ?
    1133             :                    ctime(&(fsp->fsp_name->st.st_ex_mtime.tv_sec)) : "0"));
    1134           0 :         return status;
    1135             : }
    1136             : 
    1137           0 : static int um_unlinkat(vfs_handle_struct *handle,
    1138             :                         struct files_struct *dirfsp,
    1139             :                         const struct smb_filename *smb_fname,
    1140             :                         int flags)
    1141             : {
    1142             :         int ret;
    1143           0 :         struct smb_filename *full_fname = NULL;
    1144           0 :         struct smb_filename *client_fname = NULL;
    1145             : 
    1146           0 :         DEBUG(10, ("Entering um_unlinkat\n"));
    1147             : 
    1148           0 :         if (!is_in_media_files(smb_fname->base_name)) {
    1149           0 :                 return SMB_VFS_NEXT_UNLINKAT(handle,
    1150             :                                 dirfsp,
    1151             :                                 smb_fname,
    1152             :                                 flags);
    1153             :         }
    1154             : 
    1155           0 :         full_fname = full_path_from_dirfsp_atname(talloc_tos(),
    1156             :                                                   dirfsp,
    1157             :                                                   smb_fname);
    1158           0 :         if (full_fname == NULL) {
    1159           0 :                 return -1;
    1160             :         }
    1161             : 
    1162           0 :         ret = alloc_get_client_smb_fname(handle, talloc_tos(),
    1163             :                                             full_fname,
    1164             :                                             &client_fname);
    1165           0 :         if (ret != 0) {
    1166           0 :                 goto err;
    1167             :         }
    1168             : 
    1169           0 :         ret = SMB_VFS_NEXT_UNLINKAT(handle,
    1170             :                                 dirfsp->conn->cwd_fsp,
    1171             :                                 client_fname,
    1172             :                                 flags);
    1173             : 
    1174           0 : err:
    1175           0 :         TALLOC_FREE(full_fname);
    1176           0 :         TALLOC_FREE(client_fname);
    1177           0 :         return ret;
    1178             : }
    1179             : 
    1180           0 : static int um_lchown(vfs_handle_struct *handle,
    1181             :                         const struct smb_filename *smb_fname,
    1182             :                         uid_t uid,
    1183             :                         gid_t gid)
    1184             : {
    1185             :         int status;
    1186           0 :         struct smb_filename *client_fname = NULL;
    1187             : 
    1188           0 :         DEBUG(10, ("Entering um_lchown\n"));
    1189           0 :         if (!is_in_media_files(smb_fname->base_name)) {
    1190           0 :                 return SMB_VFS_NEXT_LCHOWN(handle, smb_fname, uid, gid);
    1191             :         }
    1192             : 
    1193           0 :         status = alloc_get_client_smb_fname(handle,
    1194             :                                 talloc_tos(),
    1195             :                                 smb_fname,
    1196             :                                 &client_fname);
    1197           0 :         if (status != 0) {
    1198           0 :                 goto err;
    1199             :         }
    1200             : 
    1201           0 :         status = SMB_VFS_NEXT_LCHOWN(handle, client_fname, uid, gid);
    1202             : 
    1203           0 : err:
    1204           0 :         TALLOC_FREE(client_fname);
    1205           0 :         return status;
    1206             : }
    1207             : 
    1208           0 : static int um_chdir(vfs_handle_struct *handle,
    1209             :                         const struct smb_filename *smb_fname)
    1210             : {
    1211             :         int status;
    1212           0 :         struct smb_filename *client_fname = NULL;
    1213             : 
    1214           0 :         DEBUG(10, ("Entering um_chdir\n"));
    1215             : 
    1216           0 :         if (!is_in_media_files(smb_fname->base_name)) {
    1217           0 :                 return SMB_VFS_NEXT_CHDIR(handle, smb_fname);
    1218             :         }
    1219             : 
    1220           0 :         status = alloc_get_client_smb_fname(handle,
    1221             :                                 talloc_tos(),
    1222             :                                 smb_fname,
    1223             :                                 &client_fname);
    1224           0 :         if (status != 0) {
    1225           0 :                 goto err;
    1226             :         }
    1227             : 
    1228           0 :         status = SMB_VFS_NEXT_CHDIR(handle, client_fname);
    1229             : 
    1230           0 : err:
    1231           0 :         TALLOC_FREE(client_fname);
    1232           0 :         return status;
    1233             : }
    1234             : 
    1235           0 : static int um_symlinkat(vfs_handle_struct *handle,
    1236             :                         const struct smb_filename *link_contents,
    1237             :                         struct files_struct *dirfsp,
    1238             :                         const struct smb_filename *new_smb_fname)
    1239             : {
    1240             :         int status;
    1241           0 :         struct smb_filename *new_link_target = NULL;
    1242           0 :         struct smb_filename *new_client_fname = NULL;
    1243           0 :         struct smb_filename *full_fname = NULL;
    1244             : 
    1245           0 :         DEBUG(10, ("Entering um_symlinkat\n"));
    1246             : 
    1247           0 :         full_fname = full_path_from_dirfsp_atname(talloc_tos(),
    1248             :                                                 dirfsp,
    1249             :                                                 new_smb_fname);
    1250           0 :         if (full_fname == NULL) {
    1251           0 :                 return -1;
    1252             :         }
    1253             : 
    1254           0 :         if (!is_in_media_files(link_contents->base_name) &&
    1255           0 :                         !is_in_media_files(full_fname->base_name)) {
    1256           0 :                 TALLOC_FREE(full_fname);
    1257           0 :                 return SMB_VFS_NEXT_SYMLINKAT(handle,
    1258             :                                 link_contents,
    1259             :                                 dirfsp,
    1260             :                                 new_smb_fname);
    1261             :         }
    1262             : 
    1263           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1264             :                                 link_contents, &new_link_target);
    1265           0 :         if (status != 0) {
    1266           0 :                 goto err;
    1267             :         }
    1268           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1269             :                                             full_fname, &new_client_fname);
    1270           0 :         if (status != 0) {
    1271           0 :                 goto err;
    1272             :         }
    1273             : 
    1274           0 :         status = SMB_VFS_NEXT_SYMLINKAT(handle,
    1275             :                                         new_link_target,
    1276             :                                         handle->conn->cwd_fsp,
    1277             :                                         new_client_fname);
    1278             : 
    1279           0 : err:
    1280           0 :         TALLOC_FREE(new_link_target);
    1281           0 :         TALLOC_FREE(new_client_fname);
    1282           0 :         TALLOC_FREE(full_fname);
    1283           0 :         return status;
    1284             : }
    1285             : 
    1286           0 : static int um_readlinkat(vfs_handle_struct *handle,
    1287             :                         const struct files_struct *dirfsp,
    1288             :                         const struct smb_filename *smb_fname,
    1289             :                         char *buf,
    1290             :                         size_t bufsiz)
    1291             : {
    1292             :         int status;
    1293           0 :         struct smb_filename *client_fname = NULL;
    1294           0 :         struct smb_filename *full_fname = NULL;
    1295             : 
    1296           0 :         DEBUG(10, ("Entering um_readlinkat\n"));
    1297             : 
    1298           0 :         full_fname = full_path_from_dirfsp_atname(talloc_tos(),
    1299             :                                                 dirfsp,
    1300             :                                                 smb_fname);
    1301           0 :         if (full_fname == NULL) {
    1302           0 :                 return -1;
    1303             :         }
    1304             : 
    1305           0 :         if (!is_in_media_files(full_fname->base_name)) {
    1306           0 :                 TALLOC_FREE(full_fname);
    1307           0 :                 return SMB_VFS_NEXT_READLINKAT(handle,
    1308             :                                 dirfsp,
    1309             :                                 smb_fname,
    1310             :                                 buf,
    1311             :                                 bufsiz);
    1312             :         }
    1313             : 
    1314           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1315             :                                             full_fname, &client_fname);
    1316           0 :         if (status != 0) {
    1317           0 :                 goto err;
    1318             :         }
    1319             : 
    1320           0 :         status = SMB_VFS_NEXT_READLINKAT(handle,
    1321             :                                 handle->conn->cwd_fsp,
    1322             :                                 client_fname,
    1323             :                                 buf,
    1324             :                                 bufsiz);
    1325             : 
    1326           0 : err:
    1327           0 :         TALLOC_FREE(full_fname);
    1328           0 :         TALLOC_FREE(client_fname);
    1329           0 :         return status;
    1330             : }
    1331             : 
    1332           0 : static int um_linkat(vfs_handle_struct *handle,
    1333             :                         files_struct *srcfsp,
    1334             :                         const struct smb_filename *old_smb_fname,
    1335             :                         files_struct *dstfsp,
    1336             :                         const struct smb_filename *new_smb_fname,
    1337             :                         int flags)
    1338             : {
    1339             :         int status;
    1340           0 :         struct smb_filename *old_full_fname = NULL;
    1341           0 :         struct smb_filename *new_full_fname = NULL;
    1342           0 :         struct smb_filename *old_client_fname = NULL;
    1343           0 :         struct smb_filename *new_client_fname = NULL;
    1344             : 
    1345           0 :         old_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
    1346             :                                                   srcfsp,
    1347             :                                                   old_smb_fname);
    1348           0 :         if (old_full_fname == NULL) {
    1349           0 :                 return -1;
    1350             :         }
    1351           0 :         new_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
    1352             :                                                   dstfsp,
    1353             :                                                   new_smb_fname);
    1354           0 :         if (new_full_fname == NULL) {
    1355           0 :                 TALLOC_FREE(old_full_fname);
    1356           0 :                 return -1;
    1357             :         }
    1358             : 
    1359           0 :         DEBUG(10, ("Entering um_linkat\n"));
    1360           0 :         if (!is_in_media_files(old_full_fname->base_name) &&
    1361           0 :                                 !is_in_media_files(new_full_fname->base_name)) {
    1362           0 :                 TALLOC_FREE(old_full_fname);
    1363           0 :                 TALLOC_FREE(new_full_fname);
    1364           0 :                 return SMB_VFS_NEXT_LINKAT(handle,
    1365             :                                 srcfsp,
    1366             :                                 old_smb_fname,
    1367             :                                 dstfsp,
    1368             :                                 new_smb_fname,
    1369             :                                 flags);
    1370             :         }
    1371             : 
    1372           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1373             :                                             old_full_fname, &old_client_fname);
    1374           0 :         if (status != 0) {
    1375           0 :                 goto err;
    1376             :         }
    1377           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1378             :                                             new_full_fname, &new_client_fname);
    1379           0 :         if (status != 0) {
    1380           0 :                 goto err;
    1381             :         }
    1382             : 
    1383           0 :         status = SMB_VFS_NEXT_LINKAT(handle,
    1384             :                                 handle->conn->cwd_fsp,
    1385             :                                 old_client_fname,
    1386             :                                 handle->conn->cwd_fsp,
    1387             :                                 new_client_fname,
    1388             :                                 flags);
    1389             : 
    1390           0 : err:
    1391           0 :         TALLOC_FREE(old_full_fname);
    1392           0 :         TALLOC_FREE(new_full_fname);
    1393           0 :         TALLOC_FREE(old_client_fname);
    1394           0 :         TALLOC_FREE(new_client_fname);
    1395           0 :         return status;
    1396             : }
    1397             : 
    1398           0 : static int um_mknodat(vfs_handle_struct *handle,
    1399             :                 files_struct *dirfsp,
    1400             :                 const struct smb_filename *smb_fname,
    1401             :                 mode_t mode,
    1402             :                 SMB_DEV_T dev)
    1403             : {
    1404             :         int status;
    1405           0 :         struct smb_filename *client_fname = NULL;
    1406           0 :         struct smb_filename *full_fname = NULL;
    1407             : 
    1408           0 :         full_fname = full_path_from_dirfsp_atname(talloc_tos(),
    1409             :                                                   dirfsp,
    1410             :                                                   smb_fname);
    1411           0 :         if (full_fname == NULL) {
    1412           0 :                 return -1;
    1413             :         }
    1414             : 
    1415           0 :         DEBUG(10, ("Entering um_mknodat\n"));
    1416           0 :         if (!is_in_media_files(full_fname->base_name)) {
    1417           0 :                 TALLOC_FREE(full_fname);
    1418           0 :                 return SMB_VFS_NEXT_MKNODAT(handle,
    1419             :                                 dirfsp,
    1420             :                                 smb_fname,
    1421             :                                 mode,
    1422             :                                 dev);
    1423             :         }
    1424             : 
    1425           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1426             :                                             full_fname, &client_fname);
    1427           0 :         if (status != 0) {
    1428           0 :                 goto err;
    1429             :         }
    1430             : 
    1431           0 :         status = SMB_VFS_NEXT_MKNODAT(handle,
    1432             :                         handle->conn->cwd_fsp,
    1433             :                         client_fname,
    1434             :                         mode,
    1435             :                         dev);
    1436             : 
    1437           0 : err:
    1438           0 :         TALLOC_FREE(client_fname);
    1439           0 :         TALLOC_FREE(full_fname);
    1440           0 :         return status;
    1441             : }
    1442             : 
    1443           0 : static struct smb_filename *um_realpath(vfs_handle_struct *handle,
    1444             :                                 TALLOC_CTX *ctx,
    1445             :                                 const struct smb_filename *smb_fname)
    1446             : {
    1447           0 :         struct smb_filename *client_fname = NULL;
    1448           0 :         struct smb_filename *result_fname = NULL;
    1449             :         int status;
    1450             : 
    1451           0 :         DEBUG(10, ("Entering um_realpath\n"));
    1452             : 
    1453           0 :         if (!is_in_media_files(smb_fname->base_name)) {
    1454           0 :                 return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
    1455             :         }
    1456             : 
    1457           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1458             :                                             smb_fname, &client_fname);
    1459           0 :         if (status != 0) {
    1460           0 :                 goto err;
    1461             :         }
    1462             : 
    1463           0 :         result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, client_fname);
    1464             : 
    1465           0 : err:
    1466           0 :         TALLOC_FREE(client_fname);
    1467           0 :         return result_fname;
    1468             : }
    1469             : 
    1470           0 : static int um_connect(vfs_handle_struct *handle,
    1471             :                          const char *service,
    1472             :                          const char *user)
    1473             : {
    1474             :         int rc;
    1475             :         struct um_config_data *config;
    1476             :         int enumval;
    1477             : 
    1478           0 :         rc = SMB_VFS_NEXT_CONNECT(handle, service, user);
    1479           0 :         if (rc != 0) {
    1480           0 :                 return rc;
    1481             :         }
    1482             : 
    1483           0 :         config = talloc_zero(handle->conn, struct um_config_data);
    1484           0 :         if (!config) {
    1485           0 :                 DEBUG(1, ("talloc_zero() failed\n"));
    1486           0 :                 errno = ENOMEM;
    1487           0 :                 return -1;
    1488             :         }
    1489             : 
    1490           0 :         enumval = lp_parm_enum(SNUM(handle->conn), UM_PARAM_TYPE_NAME,
    1491             :                                "clientid", um_clientid, UM_CLIENTID_NAME);
    1492           0 :         if (enumval == -1) {
    1493           0 :                 DEBUG(1, ("value for %s: type unknown\n",
    1494             :                           UM_PARAM_TYPE_NAME));
    1495           0 :                 return -1;
    1496             :         }
    1497           0 :         config->clientid = (enum um_clientid)enumval;
    1498             : 
    1499           0 :         SMB_VFS_HANDLE_SET_DATA(handle, config,
    1500             :                                 NULL, struct um_config_data,
    1501             :                                 return -1);
    1502             : 
    1503           0 :         return 0;
    1504             : }
    1505             : 
    1506             : /* VFS operations structure */
    1507             : 
    1508             : static struct vfs_fn_pointers vfs_um_fns = {
    1509             :         .connect_fn = um_connect,
    1510             : 
    1511             :         /* Disk operations */
    1512             : 
    1513             :         .statvfs_fn = um_statvfs,
    1514             : 
    1515             :         /* Directory operations */
    1516             : 
    1517             :         .fdopendir_fn = um_fdopendir,
    1518             :         .readdir_fn = um_readdir,
    1519             :         .seekdir_fn = um_seekdir,
    1520             :         .telldir_fn = um_telldir,
    1521             :         .rewind_dir_fn = um_rewinddir,
    1522             :         .mkdirat_fn = um_mkdirat,
    1523             :         .closedir_fn = um_closedir,
    1524             : 
    1525             :         /* File operations */
    1526             : 
    1527             :         .openat_fn = um_openat,
    1528             :         .create_file_fn = um_create_file,
    1529             :         .renameat_fn = um_renameat,
    1530             :         .stat_fn = um_stat,
    1531             :         .lstat_fn = um_lstat,
    1532             :         .fstat_fn = um_fstat,
    1533             :         .unlinkat_fn = um_unlinkat,
    1534             :         .lchown_fn = um_lchown,
    1535             :         .chdir_fn = um_chdir,
    1536             :         .symlinkat_fn = um_symlinkat,
    1537             :         .readlinkat_fn = um_readlinkat,
    1538             :         .linkat_fn = um_linkat,
    1539             :         .mknodat_fn = um_mknodat,
    1540             :         .realpath_fn = um_realpath,
    1541             : 
    1542             :         /* EA operations. */
    1543             :         .getxattrat_send_fn = vfs_not_implemented_getxattrat_send,
    1544             :         .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv,
    1545             : };
    1546             : 
    1547             : static_decl_vfs;
    1548          26 : NTSTATUS vfs_unityed_media_init(TALLOC_CTX *ctx)
    1549             : {
    1550          26 :         NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
    1551             :                                         "unityed_media", &vfs_um_fns);
    1552          26 :         if (!NT_STATUS_IS_OK(ret)) {
    1553           0 :                 return ret;
    1554             :         }
    1555             : 
    1556          26 :         vfs_um_debug_level = debug_add_class("unityed_media");
    1557             : 
    1558          26 :         if (vfs_um_debug_level == -1) {
    1559           0 :                 vfs_um_debug_level = DBGC_VFS;
    1560           0 :                 DEBUG(1, ("unityed_media_init: Couldn't register custom "
    1561             :                           "debugging class.\n"));
    1562             :         }
    1563             : 
    1564          26 :         return ret;
    1565             : }

Generated by: LCOV version 1.13