LCOV - code coverage report
Current view: top level - source3/modules - vfs_unityed_media.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 6 585 1.0 %
Date: 2024-02-28 12:06:22 Functions: 1 32 3.1 %

          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'\n", 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           0 :                 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             : static struct dirent *
     618           0 : um_readdir(vfs_handle_struct *handle, struct files_struct *dirfsp, DIR *dirp)
     619             : {
     620           0 :         um_dirinfo_struct* dirInfo = (um_dirinfo_struct*)dirp;
     621           0 :         struct dirent *d = NULL;
     622             :         int skip;
     623             : 
     624           0 :         DEBUG(10, ("dirInfo->dirpath '%s', "
     625             :                    "dirInfo->clientPath '%s', "
     626             :                    "dirInfo->isInMediaFiles '%s', "
     627             :                    "dirInfo->clientSubDirname '%s'\n",
     628             :                    dirInfo->dirpath,
     629             :                    dirInfo->clientPath,
     630             :                    dirInfo->isInMediaFiles ? "true" : "false",
     631             :                    dirInfo->clientSubDirname));
     632             : 
     633           0 :         if (!dirInfo->isInMediaFiles) {
     634           0 :                 return SMB_VFS_NEXT_READDIR(handle, dirfsp, dirInfo->dirstream);
     635             :         }
     636             : 
     637             :         do {
     638             :                 const char* dname;
     639             :                 bool isAppleDouble;
     640             :                 char *digits;
     641             :                 size_t digits_len;
     642             :                 uintmax_t number;
     643             : 
     644           0 :                 skip = false;
     645           0 :                 d = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirInfo->dirstream);
     646             : 
     647           0 :                 if (d == NULL) {
     648           0 :                         break;
     649             :                 }
     650             : 
     651             :                 /* ignore apple double prefix for logic below */
     652           0 :                 if (is_apple_double(d->d_name)) {
     653           0 :                         dname = &d->d_name[APPLE_DOUBLE_PREFIX_LEN];
     654           0 :                         isAppleDouble = true;
     655             :                 } else {
     656           0 :                         dname = d->d_name;
     657           0 :                         isAppleDouble = false;
     658             :                 }
     659             : 
     660           0 :                 DEBUG(10, ("dname = '%s'\n", dname));
     661             : 
     662           0 :                 (void)get_digit_group(dname, &number);
     663           0 :                 digits = talloc_asprintf(talloc_tos(), "%ju", number);
     664           0 :                 if (digits == NULL) {
     665           0 :                         DEBUG(1, ("out of memory\n"));
     666           0 :                         goto err;
     667             :                 }
     668           0 :                 digits_len = strlen(digits);
     669             : 
     670           0 :                 if (alloc_set_client_dirinfo_path(handle,
     671             :                                                   dirInfo,
     672             :                                                   &((dirInfo)->clientSubDirname),
     673             :                                                   digits)) {
     674           0 :                         goto err;
     675             :                 }
     676             : 
     677             :                 /*
     678             :                  * If set to "true", vfs shows digits-only
     679             :                  * non-suffixed subdirectories.  Normally, such
     680             :                  * subdirectories can exists only in non-media
     681             :                  * directories, so we set it to "false".  Otherwise,
     682             :                  * if we have such subdirectories (probably created
     683             :                  * over not "unityed" connection), it can be little
     684             :                  * bit confusing.
     685             :                  */
     686           0 :                 if (strequal(dname, digits)) {
     687           0 :                         skip = false;
     688           0 :                 } else if (strequal(dname, dirInfo->clientSubDirname)) {
     689             :                         /*
     690             :                          * Remove suffix of this client's suffixed
     691             :                          * subdirectories
     692             :                          */
     693           0 :                         if (isAppleDouble) {
     694           0 :                                 d->d_name[digits_len + APPLE_DOUBLE_PREFIX_LEN] = '\0';
     695             :                         } else {
     696           0 :                                 d->d_name[digits_len] = '\0';
     697             :                         }
     698           0 :                 } else if (strnequal(digits, dname, digits_len)) {
     699             :                         /*
     700             :                          * Set to false to see another clients subdirectories
     701             :                          */
     702           0 :                         skip = false;
     703             :                 }
     704           0 :         } while (skip);
     705             : 
     706           0 :         DEBUG(10, ("Leaving um_readdir\n"));
     707           0 :         return d;
     708           0 : err:
     709           0 :         TALLOC_FREE(dirInfo);
     710           0 :         return NULL;
     711             : }
     712             : 
     713           0 : static void um_rewinddir(vfs_handle_struct *handle,
     714             :                          DIR *dirp)
     715             : {
     716           0 :         DEBUG(10, ("Entering and leaving um_rewinddir\n"));
     717           0 :         SMB_VFS_NEXT_REWINDDIR(handle,
     718             :                                ((um_dirinfo_struct*)dirp)->dirstream);
     719           0 : }
     720             : 
     721           0 : static int um_mkdirat(vfs_handle_struct *handle,
     722             :                         struct files_struct *dirfsp,
     723             :                         const struct smb_filename *smb_fname,
     724             :                         mode_t mode)
     725             : {
     726             :         int status;
     727           0 :         const char *path = NULL;
     728           0 :         struct smb_filename *client_fname = NULL;
     729           0 :         struct smb_filename *full_fname = NULL;
     730             : 
     731           0 :         full_fname = full_path_from_dirfsp_atname(talloc_tos(),
     732             :                                                   dirfsp,
     733             :                                                   smb_fname);
     734           0 :         if (full_fname == NULL) {
     735           0 :                 return -1;
     736             :         }
     737             : 
     738           0 :         path = full_fname->base_name;
     739           0 :         DEBUG(10, ("Entering with path '%s'\n", path));
     740             : 
     741           0 :         if (!is_in_media_files(path) || !is_in_media_dir(path)) {
     742           0 :                 TALLOC_FREE(full_fname);
     743           0 :                 return SMB_VFS_NEXT_MKDIRAT(handle,
     744             :                                 dirfsp,
     745             :                                 smb_fname,
     746             :                                 mode);
     747             :         }
     748             : 
     749           0 :         status = alloc_get_client_smb_fname(handle,
     750             :                                 talloc_tos(),
     751             :                                 full_fname,
     752             :                                 &client_fname);
     753           0 :         if (status != 0) {
     754           0 :                 goto err;
     755             :         }
     756             : 
     757           0 :         status = SMB_VFS_NEXT_MKDIRAT(handle,
     758             :                                 handle->conn->cwd_fsp,
     759             :                                 client_fname,
     760             :                                 mode);
     761           0 : err:
     762           0 :         DEBUG(10, ("Leaving with path '%s'\n", path));
     763           0 :         TALLOC_FREE(client_fname);
     764           0 :         TALLOC_FREE(full_fname);
     765           0 :         return status;
     766             : }
     767             : 
     768           0 : static int um_closedir(vfs_handle_struct *handle,
     769             :                        DIR *dirp)
     770             : {
     771           0 :         DIR *realdirp = ((um_dirinfo_struct*)dirp)->dirstream;
     772             : 
     773           0 :         TALLOC_FREE(dirp);
     774             : 
     775           0 :         return SMB_VFS_NEXT_CLOSEDIR(handle, realdirp);
     776             : }
     777             : 
     778           0 : static int um_openat(struct vfs_handle_struct *handle,
     779             :                      const struct files_struct *dirfsp,
     780             :                      const struct smb_filename *smb_fname,
     781             :                      struct files_struct *fsp,
     782             :                      const struct vfs_open_how *how)
     783             : {
     784           0 :         struct smb_filename *client_fname = NULL;
     785             :         int ret;
     786             : 
     787           0 :         DBG_DEBUG("Entering with smb_fname->base_name '%s'\n",
     788             :                   smb_fname->base_name);
     789             : 
     790           0 :         if (!is_in_media_files(smb_fname->base_name)) {
     791           0 :                 return SMB_VFS_NEXT_OPENAT(handle,
     792             :                                            dirfsp,
     793             :                                            smb_fname,
     794             :                                            fsp,
     795             :                                            how);
     796             :         }
     797             : 
     798           0 :         if (alloc_get_client_smb_fname(handle, talloc_tos(),
     799             :                                        smb_fname,
     800             :                                        &client_fname)) {
     801           0 :                 ret = -1;
     802           0 :                 goto err;
     803             :         }
     804             : 
     805             :         /*
     806             :          * FIXME:
     807             :          * What about fsp->fsp_name?  We also have to get correct stat
     808             :          * info into fsp and smb_fname for DB files, don't we?
     809             :          */
     810             : 
     811           0 :         DEBUG(10, ("Leaving with smb_fname->base_name '%s' "
     812             :                    "smb_fname->st.st_ex_mtime %s"
     813             :                    "fsp->fsp_name->st.st_ex_mtime %s",
     814             :                    smb_fname->base_name,
     815             :                    ctime(&(smb_fname->st.st_ex_mtime.tv_sec)),
     816             :                    ctime(&(fsp->fsp_name->st.st_ex_mtime.tv_sec))));
     817             : 
     818           0 :         ret = SMB_VFS_NEXT_OPENAT(handle,
     819             :                                   dirfsp,
     820             :                                   client_fname,
     821             :                                   fsp,
     822             :                                   how);
     823           0 : err:
     824           0 :         TALLOC_FREE(client_fname);
     825           0 :         DEBUG(10, ("Leaving with smb_fname->base_name '%s'\n",
     826             :                               smb_fname->base_name));
     827           0 :         return ret;
     828             : }
     829             : 
     830           0 : static NTSTATUS um_create_file(vfs_handle_struct *handle,
     831             :                                struct smb_request *req,
     832             :                                struct files_struct *dirfsp,
     833             :                                struct smb_filename *smb_fname,
     834             :                                uint32_t access_mask,
     835             :                                uint32_t share_access,
     836             :                                uint32_t create_disposition,
     837             :                                uint32_t create_options,
     838             :                                uint32_t file_attributes,
     839             :                                uint32_t oplock_request,
     840             :                                const struct smb2_lease *lease,
     841             :                                uint64_t allocation_size,
     842             :                                uint32_t private_flags,
     843             :                                struct security_descriptor *sd,
     844             :                                struct ea_list *ea_list,
     845             :                                files_struct **result_fsp,
     846             :                                int *pinfo,
     847             :                                const struct smb2_create_blobs *in_context_blobs,
     848             :                                struct smb2_create_blobs *out_context_blobs)
     849             : {
     850             :         NTSTATUS status;
     851           0 :         struct smb_filename *client_fname = NULL;
     852             : 
     853           0 :         DEBUG(10, ("Entering with smb_fname->base_name '%s'\n",
     854             :                    smb_fname->base_name));
     855             : 
     856           0 :         if (!is_in_media_files(smb_fname->base_name)) {
     857           0 :                 return SMB_VFS_NEXT_CREATE_FILE(
     858             :                         handle,
     859             :                         req,
     860             :                         dirfsp,
     861             :                         smb_fname,
     862             :                         access_mask,
     863             :                         share_access,
     864             :                         create_disposition,
     865             :                         create_options,
     866             :                         file_attributes,
     867             :                         oplock_request,
     868             :                         lease,
     869             :                         allocation_size,
     870             :                         private_flags,
     871             :                         sd,
     872             :                         ea_list,
     873             :                         result_fsp,
     874             :                         pinfo,
     875             :                         in_context_blobs,
     876             :                         out_context_blobs);
     877             :         }
     878             : 
     879           0 :         if (alloc_get_client_smb_fname(handle, talloc_tos(),
     880             :                                        smb_fname,
     881             :                                        &client_fname)) {
     882           0 :                 status = map_nt_error_from_unix(errno);
     883           0 :                 goto err;
     884             :         }
     885             : 
     886             :         /*
     887             :          * FIXME:
     888             :          * This only creates files, so we don't have to worry about
     889             :          * our fake directory stat'ing here.  But we still need to
     890             :          * route stat calls for DB files properly, right?
     891             :          */
     892           0 :         status = SMB_VFS_NEXT_CREATE_FILE(
     893             :                 handle,
     894             :                 req,
     895             :                 dirfsp,
     896             :                 client_fname,
     897             :                 access_mask,
     898             :                 share_access,
     899             :                 create_disposition,
     900             :                 create_options,
     901             :                 file_attributes,
     902             :                 oplock_request,
     903             :                 lease,
     904             :                 allocation_size,
     905             :                 private_flags,
     906             :                 sd,
     907             :                 ea_list,
     908             :                 result_fsp,
     909             :                 pinfo,
     910             :                 in_context_blobs,
     911             :                 out_context_blobs);
     912           0 : err:
     913           0 :         TALLOC_FREE(client_fname);
     914           0 :         DEBUG(10, ("Leaving with smb_fname->base_name '%s'"
     915             :                    "smb_fname->st.st_ex_mtime %s"
     916             :                    " fsp->fsp_name->st.st_ex_mtime %s",
     917             :                    smb_fname->base_name,
     918             :                    ctime(&(smb_fname->st.st_ex_mtime.tv_sec)),
     919             :                    (*result_fsp) && VALID_STAT((*result_fsp)->fsp_name->st) ?
     920             :                    ctime(&((*result_fsp)->fsp_name->st.st_ex_mtime.tv_sec)) :
     921             :                    "No fsp time\n"));
     922           0 :         return status;
     923             : }
     924             : 
     925           0 : static int um_renameat(vfs_handle_struct *handle,
     926             :                 files_struct *srcfsp,
     927             :                 const struct smb_filename *smb_fname_src,
     928             :                 files_struct *dstfsp,
     929             :                 const struct smb_filename *smb_fname_dst)
     930             : {
     931             :         int status;
     932           0 :         struct smb_filename *src_full_fname = NULL;
     933           0 :         struct smb_filename *dst_full_fname = NULL;
     934           0 :         struct smb_filename *src_client_fname = NULL;
     935           0 :         struct smb_filename *dst_client_fname = NULL;
     936             : 
     937           0 :         src_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
     938             :                                                   srcfsp,
     939             :                                                   smb_fname_src);
     940           0 :         if (src_full_fname == NULL) {
     941           0 :                 errno = ENOMEM;
     942           0 :                 return -1;
     943             :         }
     944           0 :         dst_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
     945             :                                                   dstfsp,
     946             :                                                   smb_fname_dst);
     947           0 :         if (dst_full_fname == NULL) {
     948           0 :                 TALLOC_FREE(src_full_fname);
     949           0 :                 errno = ENOMEM;
     950           0 :                 return -1;
     951             :         }
     952             : 
     953           0 :         DBG_DEBUG( "Entering with "
     954             :                    "smb_fname_src->base_name '%s', "
     955             :                    "smb_fname_dst->base_name '%s'\n",
     956             :                    smb_fname_src->base_name,
     957             :                    smb_fname_dst->base_name);
     958             : 
     959           0 :         if (!is_in_media_files(src_full_fname->base_name)
     960           0 :             &&
     961           0 :             !is_in_media_files(dst_full_fname->base_name)) {
     962           0 :                 TALLOC_FREE(src_full_fname);
     963           0 :                 TALLOC_FREE(dst_full_fname);
     964           0 :                 return SMB_VFS_NEXT_RENAMEAT(handle,
     965             :                                         srcfsp,
     966             :                                         smb_fname_src,
     967             :                                         dstfsp,
     968             :                                         smb_fname_dst);
     969             :         }
     970             : 
     971           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
     972             :                                             src_full_fname,
     973             :                                             &src_client_fname);
     974           0 :         if (status != 0) {
     975           0 :                 goto err;
     976             :         }
     977             : 
     978           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
     979             :                                             dst_full_fname,
     980             :                                             &dst_client_fname);
     981             : 
     982           0 :         if (status != 0) {
     983           0 :                 goto err;
     984             :         }
     985             : 
     986           0 :         status = SMB_VFS_NEXT_RENAMEAT(handle,
     987             :                                 handle->conn->cwd_fsp,
     988             :                                 src_client_fname,
     989             :                                 handle->conn->cwd_fsp,
     990             :                                 dst_client_fname);
     991             : 
     992           0 : err:
     993           0 :         TALLOC_FREE(dst_client_fname);
     994           0 :         TALLOC_FREE(src_client_fname);
     995           0 :         TALLOC_FREE(src_full_fname);
     996           0 :         TALLOC_FREE(dst_full_fname);
     997           0 :         DBG_DEBUG( "Leaving with smb_fname_src->base_name '%s',"
     998             :                    " smb_fname_dst->base_name '%s'\n",
     999             :                    smb_fname_src->base_name,
    1000             :                    smb_fname_dst->base_name);
    1001           0 :         return status;
    1002             : }
    1003             : 
    1004             : 
    1005             : /*
    1006             :  * Success: return 0
    1007             :  * Failure: set errno, return -1
    1008             :  */
    1009           0 : static int um_stat(vfs_handle_struct *handle,
    1010             :                    struct smb_filename *smb_fname)
    1011             : {
    1012           0 :         int status = 0;
    1013           0 :         struct smb_filename *client_fname = NULL;
    1014             : 
    1015           0 :         DEBUG(10, ("Entering with smb_fname->base_name '%s'\n",
    1016             :                    smb_fname->base_name));
    1017             : 
    1018           0 :         if (!is_in_media_files(smb_fname->base_name)) {
    1019           0 :                 return SMB_VFS_NEXT_STAT(handle, smb_fname);
    1020             :         }
    1021             : 
    1022           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1023             :                                             smb_fname,
    1024             :                                             &client_fname);
    1025           0 :         if (status != 0) {
    1026           0 :                 goto err;
    1027             :         }
    1028           0 :         DEBUG(10, ("Stat'ing client_fname->base_name '%s'\n",
    1029             :                    client_fname->base_name));
    1030             : 
    1031           0 :         status = SMB_VFS_NEXT_STAT(handle, client_fname);
    1032           0 :         if (status != 0) {
    1033           0 :                 goto err;
    1034             :         }
    1035             : 
    1036             :         /*
    1037             :          * Unlike functions with const smb_filename, we have to modify
    1038             :          * smb_fname itself to pass our info back up.
    1039             :          */
    1040           0 :         DEBUG(10, ("Setting smb_fname '%s' stat from client_fname '%s'\n",
    1041             :                    smb_fname->base_name, client_fname->base_name));
    1042           0 :         smb_fname->st = client_fname->st;
    1043             : 
    1044           0 : err:
    1045           0 :         TALLOC_FREE(client_fname);
    1046           0 :         DEBUG(10, ("Leaving with smb_fname->st.st_ex_mtime %s",
    1047             :                    ctime(&(smb_fname->st.st_ex_mtime.tv_sec))));
    1048           0 :         return status;
    1049             : }
    1050             : 
    1051           0 : static int um_lstat(vfs_handle_struct *handle,
    1052             :                     struct smb_filename *smb_fname)
    1053             : {
    1054           0 :         int status = 0;
    1055           0 :         struct smb_filename *client_fname = NULL;
    1056             : 
    1057           0 :         DEBUG(10, ("Entering with smb_fname->base_name '%s'\n",
    1058             :                    smb_fname->base_name));
    1059             : 
    1060           0 :         if (!is_in_media_files(smb_fname->base_name)) {
    1061           0 :                 return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
    1062             :         }
    1063             : 
    1064           0 :         client_fname = NULL;
    1065             : 
    1066           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1067             :                                             smb_fname,
    1068             :                                             &client_fname);
    1069           0 :         if (status != 0) {
    1070           0 :                 goto err;
    1071             :         }
    1072           0 :         status = SMB_VFS_NEXT_LSTAT(handle, client_fname);
    1073           0 :         if (status != 0) {
    1074           0 :                 goto err;
    1075             :         }
    1076             : 
    1077           0 :         smb_fname->st = client_fname->st;
    1078             : 
    1079           0 : err:
    1080           0 :         TALLOC_FREE(client_fname);
    1081           0 :         DEBUG(10, ("Leaving with smb_fname->st.st_ex_mtime %s",
    1082             :                    ctime(&(smb_fname->st.st_ex_mtime.tv_sec))));
    1083           0 :         return status;
    1084             : }
    1085             : 
    1086           0 : static int um_fstat(vfs_handle_struct *handle,
    1087             :                     files_struct *fsp, SMB_STRUCT_STAT *sbuf)
    1088             : {
    1089           0 :         int status = 0;
    1090             : 
    1091           0 :         DEBUG(10, ("Entering with fsp->fsp_name->base_name "
    1092             :                    "'%s'\n", fsp_str_dbg(fsp)));
    1093             : 
    1094           0 :         status = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
    1095           0 :         if (status != 0) {
    1096           0 :                 goto out;
    1097             :         }
    1098             : 
    1099           0 :         if ((fsp->fsp_name == NULL) ||
    1100           0 :             !is_in_media_files(fsp->fsp_name->base_name)) {
    1101           0 :                 goto out;
    1102             :         }
    1103             : 
    1104           0 :         status = um_stat(handle, fsp->fsp_name);
    1105           0 :         if (status != 0) {
    1106           0 :                 goto out;
    1107             :         }
    1108             : 
    1109           0 :         *sbuf = fsp->fsp_name->st;
    1110             : 
    1111           0 : out:
    1112           0 :         DEBUG(10, ("Leaving with fsp->fsp_name->st.st_ex_mtime %s",
    1113             :                    fsp->fsp_name != NULL ?
    1114             :                    ctime(&(fsp->fsp_name->st.st_ex_mtime.tv_sec)) : "0\n"));
    1115           0 :         return status;
    1116             : }
    1117             : 
    1118           0 : static int um_unlinkat(vfs_handle_struct *handle,
    1119             :                         struct files_struct *dirfsp,
    1120             :                         const struct smb_filename *smb_fname,
    1121             :                         int flags)
    1122             : {
    1123             :         int ret;
    1124           0 :         struct smb_filename *full_fname = NULL;
    1125           0 :         struct smb_filename *client_fname = NULL;
    1126             : 
    1127           0 :         DEBUG(10, ("Entering um_unlinkat\n"));
    1128             : 
    1129           0 :         if (!is_in_media_files(smb_fname->base_name)) {
    1130           0 :                 return SMB_VFS_NEXT_UNLINKAT(handle,
    1131             :                                 dirfsp,
    1132             :                                 smb_fname,
    1133             :                                 flags);
    1134             :         }
    1135             : 
    1136           0 :         full_fname = full_path_from_dirfsp_atname(talloc_tos(),
    1137             :                                                   dirfsp,
    1138             :                                                   smb_fname);
    1139           0 :         if (full_fname == NULL) {
    1140           0 :                 return -1;
    1141             :         }
    1142             : 
    1143           0 :         ret = alloc_get_client_smb_fname(handle, talloc_tos(),
    1144             :                                             full_fname,
    1145             :                                             &client_fname);
    1146           0 :         if (ret != 0) {
    1147           0 :                 goto err;
    1148             :         }
    1149             : 
    1150           0 :         ret = SMB_VFS_NEXT_UNLINKAT(handle,
    1151             :                                 dirfsp->conn->cwd_fsp,
    1152             :                                 client_fname,
    1153             :                                 flags);
    1154             : 
    1155           0 : err:
    1156           0 :         TALLOC_FREE(full_fname);
    1157           0 :         TALLOC_FREE(client_fname);
    1158           0 :         return ret;
    1159             : }
    1160             : 
    1161           0 : static int um_lchown(vfs_handle_struct *handle,
    1162             :                         const struct smb_filename *smb_fname,
    1163             :                         uid_t uid,
    1164             :                         gid_t gid)
    1165             : {
    1166             :         int status;
    1167           0 :         struct smb_filename *client_fname = NULL;
    1168             : 
    1169           0 :         DEBUG(10, ("Entering um_lchown\n"));
    1170           0 :         if (!is_in_media_files(smb_fname->base_name)) {
    1171           0 :                 return SMB_VFS_NEXT_LCHOWN(handle, smb_fname, uid, gid);
    1172             :         }
    1173             : 
    1174           0 :         status = alloc_get_client_smb_fname(handle,
    1175             :                                 talloc_tos(),
    1176             :                                 smb_fname,
    1177             :                                 &client_fname);
    1178           0 :         if (status != 0) {
    1179           0 :                 goto err;
    1180             :         }
    1181             : 
    1182           0 :         status = SMB_VFS_NEXT_LCHOWN(handle, client_fname, uid, gid);
    1183             : 
    1184           0 : err:
    1185           0 :         TALLOC_FREE(client_fname);
    1186           0 :         return status;
    1187             : }
    1188             : 
    1189           0 : static int um_chdir(vfs_handle_struct *handle,
    1190             :                         const struct smb_filename *smb_fname)
    1191             : {
    1192             :         int status;
    1193           0 :         struct smb_filename *client_fname = NULL;
    1194             : 
    1195           0 :         DEBUG(10, ("Entering um_chdir\n"));
    1196             : 
    1197           0 :         if (!is_in_media_files(smb_fname->base_name)) {
    1198           0 :                 return SMB_VFS_NEXT_CHDIR(handle, smb_fname);
    1199             :         }
    1200             : 
    1201           0 :         status = alloc_get_client_smb_fname(handle,
    1202             :                                 talloc_tos(),
    1203             :                                 smb_fname,
    1204             :                                 &client_fname);
    1205           0 :         if (status != 0) {
    1206           0 :                 goto err;
    1207             :         }
    1208             : 
    1209           0 :         status = SMB_VFS_NEXT_CHDIR(handle, client_fname);
    1210             : 
    1211           0 : err:
    1212           0 :         TALLOC_FREE(client_fname);
    1213           0 :         return status;
    1214             : }
    1215             : 
    1216           0 : static int um_symlinkat(vfs_handle_struct *handle,
    1217             :                         const struct smb_filename *link_contents,
    1218             :                         struct files_struct *dirfsp,
    1219             :                         const struct smb_filename *new_smb_fname)
    1220             : {
    1221             :         int status;
    1222           0 :         struct smb_filename *new_link_target = NULL;
    1223           0 :         struct smb_filename *new_client_fname = NULL;
    1224           0 :         struct smb_filename *full_fname = NULL;
    1225             : 
    1226           0 :         DEBUG(10, ("Entering um_symlinkat\n"));
    1227             : 
    1228           0 :         full_fname = full_path_from_dirfsp_atname(talloc_tos(),
    1229             :                                                 dirfsp,
    1230             :                                                 new_smb_fname);
    1231           0 :         if (full_fname == NULL) {
    1232           0 :                 return -1;
    1233             :         }
    1234             : 
    1235           0 :         if (!is_in_media_files(link_contents->base_name) &&
    1236           0 :                         !is_in_media_files(full_fname->base_name)) {
    1237           0 :                 TALLOC_FREE(full_fname);
    1238           0 :                 return SMB_VFS_NEXT_SYMLINKAT(handle,
    1239             :                                 link_contents,
    1240             :                                 dirfsp,
    1241             :                                 new_smb_fname);
    1242             :         }
    1243             : 
    1244           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1245             :                                 link_contents, &new_link_target);
    1246           0 :         if (status != 0) {
    1247           0 :                 goto err;
    1248             :         }
    1249           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1250             :                                             full_fname, &new_client_fname);
    1251           0 :         if (status != 0) {
    1252           0 :                 goto err;
    1253             :         }
    1254             : 
    1255           0 :         status = SMB_VFS_NEXT_SYMLINKAT(handle,
    1256             :                                         new_link_target,
    1257             :                                         handle->conn->cwd_fsp,
    1258             :                                         new_client_fname);
    1259             : 
    1260           0 : err:
    1261           0 :         TALLOC_FREE(new_link_target);
    1262           0 :         TALLOC_FREE(new_client_fname);
    1263           0 :         TALLOC_FREE(full_fname);
    1264           0 :         return status;
    1265             : }
    1266             : 
    1267           0 : static int um_readlinkat(vfs_handle_struct *handle,
    1268             :                         const struct files_struct *dirfsp,
    1269             :                         const struct smb_filename *smb_fname,
    1270             :                         char *buf,
    1271             :                         size_t bufsiz)
    1272             : {
    1273             :         int status;
    1274           0 :         struct smb_filename *client_fname = NULL;
    1275           0 :         struct smb_filename *full_fname = NULL;
    1276             : 
    1277           0 :         DEBUG(10, ("Entering um_readlinkat\n"));
    1278             : 
    1279           0 :         full_fname = full_path_from_dirfsp_atname(talloc_tos(),
    1280             :                                                 dirfsp,
    1281             :                                                 smb_fname);
    1282           0 :         if (full_fname == NULL) {
    1283           0 :                 return -1;
    1284             :         }
    1285             : 
    1286           0 :         if (!is_in_media_files(full_fname->base_name)) {
    1287           0 :                 TALLOC_FREE(full_fname);
    1288           0 :                 return SMB_VFS_NEXT_READLINKAT(handle,
    1289             :                                 dirfsp,
    1290             :                                 smb_fname,
    1291             :                                 buf,
    1292             :                                 bufsiz);
    1293             :         }
    1294             : 
    1295           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1296             :                                             full_fname, &client_fname);
    1297           0 :         if (status != 0) {
    1298           0 :                 goto err;
    1299             :         }
    1300             : 
    1301           0 :         status = SMB_VFS_NEXT_READLINKAT(handle,
    1302             :                                 handle->conn->cwd_fsp,
    1303             :                                 client_fname,
    1304             :                                 buf,
    1305             :                                 bufsiz);
    1306             : 
    1307           0 : err:
    1308           0 :         TALLOC_FREE(full_fname);
    1309           0 :         TALLOC_FREE(client_fname);
    1310           0 :         return status;
    1311             : }
    1312             : 
    1313           0 : static int um_linkat(vfs_handle_struct *handle,
    1314             :                         files_struct *srcfsp,
    1315             :                         const struct smb_filename *old_smb_fname,
    1316             :                         files_struct *dstfsp,
    1317             :                         const struct smb_filename *new_smb_fname,
    1318             :                         int flags)
    1319             : {
    1320             :         int status;
    1321           0 :         struct smb_filename *old_full_fname = NULL;
    1322           0 :         struct smb_filename *new_full_fname = NULL;
    1323           0 :         struct smb_filename *old_client_fname = NULL;
    1324           0 :         struct smb_filename *new_client_fname = NULL;
    1325             : 
    1326           0 :         old_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
    1327             :                                                   srcfsp,
    1328             :                                                   old_smb_fname);
    1329           0 :         if (old_full_fname == NULL) {
    1330           0 :                 return -1;
    1331             :         }
    1332           0 :         new_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
    1333             :                                                   dstfsp,
    1334             :                                                   new_smb_fname);
    1335           0 :         if (new_full_fname == NULL) {
    1336           0 :                 TALLOC_FREE(old_full_fname);
    1337           0 :                 return -1;
    1338             :         }
    1339             : 
    1340           0 :         DEBUG(10, ("Entering um_linkat\n"));
    1341           0 :         if (!is_in_media_files(old_full_fname->base_name) &&
    1342           0 :                                 !is_in_media_files(new_full_fname->base_name)) {
    1343           0 :                 TALLOC_FREE(old_full_fname);
    1344           0 :                 TALLOC_FREE(new_full_fname);
    1345           0 :                 return SMB_VFS_NEXT_LINKAT(handle,
    1346             :                                 srcfsp,
    1347             :                                 old_smb_fname,
    1348             :                                 dstfsp,
    1349             :                                 new_smb_fname,
    1350             :                                 flags);
    1351             :         }
    1352             : 
    1353           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1354             :                                             old_full_fname, &old_client_fname);
    1355           0 :         if (status != 0) {
    1356           0 :                 goto err;
    1357             :         }
    1358           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1359             :                                             new_full_fname, &new_client_fname);
    1360           0 :         if (status != 0) {
    1361           0 :                 goto err;
    1362             :         }
    1363             : 
    1364           0 :         status = SMB_VFS_NEXT_LINKAT(handle,
    1365             :                                 handle->conn->cwd_fsp,
    1366             :                                 old_client_fname,
    1367             :                                 handle->conn->cwd_fsp,
    1368             :                                 new_client_fname,
    1369             :                                 flags);
    1370             : 
    1371           0 : err:
    1372           0 :         TALLOC_FREE(old_full_fname);
    1373           0 :         TALLOC_FREE(new_full_fname);
    1374           0 :         TALLOC_FREE(old_client_fname);
    1375           0 :         TALLOC_FREE(new_client_fname);
    1376           0 :         return status;
    1377             : }
    1378             : 
    1379           0 : static int um_mknodat(vfs_handle_struct *handle,
    1380             :                 files_struct *dirfsp,
    1381             :                 const struct smb_filename *smb_fname,
    1382             :                 mode_t mode,
    1383             :                 SMB_DEV_T dev)
    1384             : {
    1385             :         int status;
    1386           0 :         struct smb_filename *client_fname = NULL;
    1387           0 :         struct smb_filename *full_fname = NULL;
    1388             : 
    1389           0 :         full_fname = full_path_from_dirfsp_atname(talloc_tos(),
    1390             :                                                   dirfsp,
    1391             :                                                   smb_fname);
    1392           0 :         if (full_fname == NULL) {
    1393           0 :                 return -1;
    1394             :         }
    1395             : 
    1396           0 :         DEBUG(10, ("Entering um_mknodat\n"));
    1397           0 :         if (!is_in_media_files(full_fname->base_name)) {
    1398           0 :                 TALLOC_FREE(full_fname);
    1399           0 :                 return SMB_VFS_NEXT_MKNODAT(handle,
    1400             :                                 dirfsp,
    1401             :                                 smb_fname,
    1402             :                                 mode,
    1403             :                                 dev);
    1404             :         }
    1405             : 
    1406           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1407             :                                             full_fname, &client_fname);
    1408           0 :         if (status != 0) {
    1409           0 :                 goto err;
    1410             :         }
    1411             : 
    1412           0 :         status = SMB_VFS_NEXT_MKNODAT(handle,
    1413             :                         handle->conn->cwd_fsp,
    1414             :                         client_fname,
    1415             :                         mode,
    1416             :                         dev);
    1417             : 
    1418           0 : err:
    1419           0 :         TALLOC_FREE(client_fname);
    1420           0 :         TALLOC_FREE(full_fname);
    1421           0 :         return status;
    1422             : }
    1423             : 
    1424           0 : static struct smb_filename *um_realpath(vfs_handle_struct *handle,
    1425             :                                 TALLOC_CTX *ctx,
    1426             :                                 const struct smb_filename *smb_fname)
    1427             : {
    1428           0 :         struct smb_filename *client_fname = NULL;
    1429           0 :         struct smb_filename *result_fname = NULL;
    1430             :         int status;
    1431             : 
    1432           0 :         DEBUG(10, ("Entering um_realpath\n"));
    1433             : 
    1434           0 :         if (!is_in_media_files(smb_fname->base_name)) {
    1435           0 :                 return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
    1436             :         }
    1437             : 
    1438           0 :         status = alloc_get_client_smb_fname(handle, talloc_tos(),
    1439             :                                             smb_fname, &client_fname);
    1440           0 :         if (status != 0) {
    1441           0 :                 goto err;
    1442             :         }
    1443             : 
    1444           0 :         result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, client_fname);
    1445             : 
    1446           0 : err:
    1447           0 :         TALLOC_FREE(client_fname);
    1448           0 :         return result_fname;
    1449             : }
    1450             : 
    1451           0 : static int um_connect(vfs_handle_struct *handle,
    1452             :                          const char *service,
    1453             :                          const char *user)
    1454             : {
    1455             :         int rc;
    1456             :         struct um_config_data *config;
    1457             :         int enumval;
    1458             : 
    1459           0 :         rc = SMB_VFS_NEXT_CONNECT(handle, service, user);
    1460           0 :         if (rc != 0) {
    1461           0 :                 return rc;
    1462             :         }
    1463             : 
    1464           0 :         config = talloc_zero(handle->conn, struct um_config_data);
    1465           0 :         if (!config) {
    1466           0 :                 DEBUG(1, ("talloc_zero() failed\n"));
    1467           0 :                 errno = ENOMEM;
    1468           0 :                 return -1;
    1469             :         }
    1470             : 
    1471           0 :         enumval = lp_parm_enum(SNUM(handle->conn), UM_PARAM_TYPE_NAME,
    1472             :                                "clientid", um_clientid, UM_CLIENTID_NAME);
    1473           0 :         if (enumval == -1) {
    1474           0 :                 DEBUG(1, ("value for %s: type unknown\n",
    1475             :                           UM_PARAM_TYPE_NAME));
    1476           0 :                 return -1;
    1477             :         }
    1478           0 :         config->clientid = (enum um_clientid)enumval;
    1479             : 
    1480           0 :         SMB_VFS_HANDLE_SET_DATA(handle, config,
    1481             :                                 NULL, struct um_config_data,
    1482             :                                 return -1);
    1483             : 
    1484           0 :         return 0;
    1485             : }
    1486             : 
    1487             : /* VFS operations structure */
    1488             : 
    1489             : static struct vfs_fn_pointers vfs_um_fns = {
    1490             :         .connect_fn = um_connect,
    1491             : 
    1492             :         /* Disk operations */
    1493             : 
    1494             :         .statvfs_fn = um_statvfs,
    1495             : 
    1496             :         /* Directory operations */
    1497             : 
    1498             :         .fdopendir_fn = um_fdopendir,
    1499             :         .readdir_fn = um_readdir,
    1500             :         .rewind_dir_fn = um_rewinddir,
    1501             :         .mkdirat_fn = um_mkdirat,
    1502             :         .closedir_fn = um_closedir,
    1503             : 
    1504             :         /* File operations */
    1505             : 
    1506             :         .openat_fn = um_openat,
    1507             :         .create_file_fn = um_create_file,
    1508             :         .renameat_fn = um_renameat,
    1509             :         .stat_fn = um_stat,
    1510             :         .lstat_fn = um_lstat,
    1511             :         .fstat_fn = um_fstat,
    1512             :         .unlinkat_fn = um_unlinkat,
    1513             :         .lchown_fn = um_lchown,
    1514             :         .chdir_fn = um_chdir,
    1515             :         .symlinkat_fn = um_symlinkat,
    1516             :         .readlinkat_fn = um_readlinkat,
    1517             :         .linkat_fn = um_linkat,
    1518             :         .mknodat_fn = um_mknodat,
    1519             :         .realpath_fn = um_realpath,
    1520             : 
    1521             :         /* EA operations. */
    1522             :         .getxattrat_send_fn = vfs_not_implemented_getxattrat_send,
    1523             :         .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv,
    1524             : };
    1525             : 
    1526             : static_decl_vfs;
    1527          27 : NTSTATUS vfs_unityed_media_init(TALLOC_CTX *ctx)
    1528             : {
    1529          27 :         NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
    1530             :                                         "unityed_media", &vfs_um_fns);
    1531          27 :         if (!NT_STATUS_IS_OK(ret)) {
    1532           0 :                 return ret;
    1533             :         }
    1534             : 
    1535          27 :         vfs_um_debug_level = debug_add_class("unityed_media");
    1536             : 
    1537          27 :         if (vfs_um_debug_level == -1) {
    1538           0 :                 vfs_um_debug_level = DBGC_VFS;
    1539           0 :                 DEBUG(1, ("unityed_media_init: Couldn't register custom "
    1540             :                           "debugging class.\n"));
    1541             :         }
    1542             : 
    1543          27 :         return ret;
    1544             : }

Generated by: LCOV version 1.14