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

Generated by: LCOV version 1.13