/*
* Samba VFS module supporting multiple AVID clients sharing media.
*
* Copyright (C) 2005 Philip de Nier <philipn@users.sourceforge.net>
* Copyright (C) 2012 Andrew Klaassen <clawsoon@yahoo.com>
* Copyright (C) 2013 Milos Lukacek
* Copyright (C) 2013 Ralph Boehme <slow@samba.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/*
* Unityed Media is a Samba VFS module that allows multiple AVID
* clients to share media.
*
* Add this module to the vfs objects option in your Samba share
* configuration.
* eg.
*
* [avid_win]
* path = /video
* vfs objects = unityed_media
* ...
*
* It is recommended that you separate out Samba shares for Mac
* and Windows clients, and add the following options to the shares
* for Windows clients (NOTE: replace @ with *):
*
* veto files = /.DS_Store/._@/.Trash@/.Spotlight@/.hidden/.hotfiles@/.vol/
* delete veto files = yes
*
* This prevents hidden files from Mac clients interfering with Windows
* clients. If you find any more problem hidden files then add them to
* the list.
*
* Notes:
* This module is designed to work with AVID editing applications that
* look in the Avid MediaFiles or OMFI MediaFiles directory for media.
* It is not designed to work as expected in all circumstances for
* general use.
*/
#include "includes.h"
#include "system/filesys.h"
#include "smbd/smbd.h"
#include "../smbd/globals.h"
#include "auth.h"
#include "../lib/tsocket/tsocket.h"
#include "lib/util/smb_strtox.h"
#include <libgen.h>
#include "source3/lib/substitute.h"
#define UM_PARAM_TYPE_NAME "unityed_media"
static const char *AVID_MXF_DIRNAME = "Avid MediaFiles/MXF";
static const size_t AVID_MXF_DIRNAME_LEN = 19;
static const char *OMFI_MEDIAFILES_DIRNAME = "OMFI MediaFiles";
static const size_t OMFI_MEDIAFILES_DIRNAME_LEN = 15;
static const char *APPLE_DOUBLE_PREFIX = "._";
static const size_t APPLE_DOUBLE_PREFIX_LEN = 2;
static int vfs_um_debug_level = DBGC_VFS;
enum um_clientid {UM_CLIENTID_NAME, UM_CLIENTID_IP, UM_CLIENTID_HOSTNAME};
struct um_config_data {
enum um_clientid clientid;
};
static const struct enum_list um_clientid[] = {
{UM_CLIENTID_NAME, "user"},
{UM_CLIENTID_IP, "ip"},
{UM_CLIENTID_HOSTNAME, "hostname"},
{-1, NULL}
};
/* supplements the directory list stream */
typedef struct um_dirinfo_struct {
DIR* dirstream;
char *dirpath;
char *clientPath;
bool isInMediaFiles;
char *clientSubDirname;
} um_dirinfo_struct;
/**
* Returns true and first group of digits in path, false and 0 otherwise
**/
static bool get_digit_group(const char *path, uintmax_t *digit)
{
const char *p = path;
codepoint_t cp;
size_t size;
int error = 0;
DEBUG(10, ("get_digit_group entering with path '%s'\n",
path));
/*
* Delibiretly initialize to 0 because callers use this result
* even though the string doesn't contain any number and we
* returned false
*/
*digit = 0;
while (*p) {
cp = next_codepoint(p, &size);
if (cp == -1) {
return false;
}
if ((size == 1) && (isdigit(cp))) {
*digit = (uintmax_t)smb_strtoul(p,
NULL,
10,
&error,
SMB_STR_STANDARD);
if (error != 0) {
return false;
}
DEBUG(10, ("num_suffix = '%ju'\n",
*digit));
return true;
}
p += size;
}
return false;
}
/* Add "_<remote_name>.<number>" suffix to path or filename.
*
* Success: return 0
* Failure: set errno, path NULL, return -1
*/
static int alloc_append_client_suffix(vfs_handle_struct *handle,
char **path)
{
int status = 0;
uintmax_t number;
const char *clientid;
struct um_config_data *config;
DEBUG(10, ("Entering with path '%s'\n", *path));
SMB_VFS_HANDLE_GET_DATA(handle, config,
struct um_config_data,
return -1);
(void)get_digit_group(*path, &number);
switch (config->clientid) {
case UM_CLIENTID_IP:
clientid = tsocket_address_inet_addr_string(
handle->conn->sconn->remote_address, talloc_tos());
if (clientid == NULL) {
errno = ENOMEM;
status = -1;
goto err;
}
break;
case UM_CLIENTID_HOSTNAME:
clientid = get_remote_machine_name();
break;
case UM_CLIENTID_NAME:
default:
clientid = get_current_username();
break;
}
*path = tall
|