2006-02-04 01:19:41 +03:00
/*
Samba Unix / Linux SMB client library
Distributed SMB / CIFS Server Management Utility
Copyright ( C ) Jeremy Allison ( jra @ samba . org ) 2005
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 . , 675 Mass Ave , Cambridge , MA 0213 9 , USA . */
# include "includes.h"
# include "utils/net.h"
struct {
const char * us_errstr ;
enum usershare_err us_err ;
} us_errs [ ] = {
{ " " , USERSHARE_OK } ,
{ " Malformed usershare file " , USERSHARE_MALFORMED_FILE } ,
{ " Bad version number " , USERSHARE_BAD_VERSION } ,
{ " Malformed path entry " , USERSHARE_MALFORMED_PATH } ,
{ " Malformed comment entryfile " , USERSHARE_MALFORMED_COMMENT_DEF } ,
{ " Malformed acl definition " , USERSHARE_MALFORMED_ACL_DEF } ,
{ " Acl parse error " , USERSHARE_ACL_ERR } ,
{ " Path not absolute " , USERSHARE_PATH_NOT_ABSOLUTE } ,
{ " Path is denied " , USERSHARE_PATH_IS_DENIED } ,
{ " Path not allowed " , USERSHARE_PATH_NOT_ALLOWED } ,
{ " Path is not a directory " , USERSHARE_PATH_NOT_DIRECTORY } ,
{ " System error " , USERSHARE_POSIX_ERR } ,
{ NULL , ( enum usershare_err ) - 1 }
} ;
static const char * get_us_error_code ( enum usershare_err us_err )
{
static pstring out ;
int idx = 0 ;
while ( us_errs [ idx ] . us_errstr ! = NULL ) {
if ( us_errs [ idx ] . us_err = = us_err ) {
return us_errs [ idx ] . us_errstr ;
}
idx + + ;
}
slprintf ( out , sizeof ( out ) , " Usershare error code (0x%x) " , ( unsigned int ) us_err ) ;
return out ;
}
/* The help subsystem for the USERSHARE subcommand */
static int net_usershare_add_usage ( int argc , const char * * argv )
{
char c = * lp_winbind_separator ( ) ;
d_printf (
" net usershare add [-l|--long] <sharename> <path> [<comment>] [<acl>] \n "
" \t Adds the specified share name for this user. \n "
" \t <sharename> is the new share name. \n "
" \t <path> is the path on the filesystem to export. \n "
" \t <comment> is the optional comment for the new share. \n "
" \t <acl> is an optional share acl in the format \" DOMAIN%cname:X,DOMAIN%cname:X,.... \" \n "
" \t \t \" X \" represents a permission and can be any one of the characters f, r or d \n "
" \t \t where \" f \" means full control, \" r \" means read-only, \" d \" means deny access. \n "
" \t \t name may be a domain user or group. For local users use the local server name "
" instead of \" DOMAIN \" \n "
" \t \t The default acl is \" Everyone:r \" which allows everyone read-only access. \n "
" \t Add -l or --long to print the info on the newly added share. \n " ,
c , c ) ;
return - 1 ;
}
static int net_usershare_delete_usage ( int argc , const char * * argv )
{
d_printf (
" net usershare delete <sharename> \n " \
" \t deletes the specified share name for this user. \n " ) ;
return - 1 ;
}
static int net_usershare_info_usage ( int argc , const char * * argv )
{
d_printf (
" net usershare info [-l|--long] [wildcard sharename] \n " \
" \t Prints out the path, comment and acl elements of shares that match the wildcard. \n "
" \t By default only gives info on shares owned by the current user \n "
" \t Add -l or --long to apply this to all shares \n "
" \t Omit the sharename or use a wildcard of '*' to see all shares \n " ) ;
return - 1 ;
}
static int net_usershare_list_usage ( int argc , const char * * argv )
{
d_printf (
" net usershare list [-l|--long] [wildcard sharename] \n " \
" \t Lists the names of all shares that match the wildcard. \n "
" \t By default only lists shares owned by the current user \n "
" \t Add -l or --long to apply this to all shares \n "
" \t Omit the sharename or use a wildcard of '*' to see all shares \n " ) ;
return - 1 ;
}
int net_usershare_usage ( int argc , const char * * argv )
{
d_printf ( " net usershare add <sharename> <path> [<comment>] [<acl>] to add or change a user defined share. \n "
" net usershare delete <sharename> to delete a user defined share. \n "
" net usershare info [-l|--long] [wildcard sharename] to print info about a user defined share. \n "
" net usershare list [-l|--long] [wildcard sharename] to list user defined shares. \n "
" net usershare help \n " \
" \n Type \" net usershare help <option> \" to get more information on that option \n \n " ) ;
net_common_flags_usage ( argc , argv ) ;
return - 1 ;
}
/***************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void get_basepath ( pstring basepath )
{
pstrcpy ( basepath , lp_usershare_path ( ) ) ;
if ( basepath [ strlen ( basepath ) - 1 ] = = ' / ' ) {
basepath [ strlen ( basepath ) - 1 ] = ' \0 ' ;
}
}
/***************************************************************************
Delete a single userlevel share .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int net_usershare_delete ( int argc , const char * * argv )
{
pstring us_path ;
char * sharename ;
if ( argc ! = 1 ) {
return net_usershare_delete_usage ( argc , argv ) ;
}
sharename = strdup_lower ( argv [ 0 ] ) ;
if ( ! validate_net_name ( sharename , INVALID_SHARENAME_CHARS , strlen ( sharename ) ) ) {
d_fprintf ( stderr , " net usershare delete: share name %s contains "
" invalid characters (any of %s) \n " ,
sharename , INVALID_SHARENAME_CHARS ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
pstrcpy ( us_path , lp_usershare_path ( ) ) ;
pstrcat ( us_path , " / " ) ;
pstrcat ( us_path , sharename ) ;
if ( unlink ( us_path ) ! = 0 ) {
d_fprintf ( stderr , " net usershare delete: unable to remove usershare %s. "
" Error was %s \n " ,
us_path , strerror ( errno ) ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
SAFE_FREE ( sharename ) ;
return 0 ;
}
/***************************************************************************
Data structures to handle a list of usershare files .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct file_list {
struct file_list * next , * prev ;
const char * pathname ;
} ;
static struct file_list * flist ;
/***************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int get_share_list ( TALLOC_CTX * ctx , const char * wcard , BOOL only_ours )
{
SMB_STRUCT_DIR * dp ;
SMB_STRUCT_DIRENT * de ;
uid_t myuid = geteuid ( ) ;
struct file_list * fl = NULL ;
pstring basepath ;
get_basepath ( basepath ) ;
dp = sys_opendir ( basepath ) ;
if ( ! dp ) {
d_fprintf ( stderr , " get_share_list: cannot open usershare directory %s. Error %s \n " ,
basepath , strerror ( errno ) ) ;
return - 1 ;
}
while ( ( de = sys_readdir ( dp ) ) ! = 0 ) {
SMB_STRUCT_STAT sbuf ;
pstring path ;
const char * n = de - > d_name ;
/* Ignore . and .. */
if ( * n = = ' . ' ) {
if ( ( n [ 1 ] = = ' \0 ' ) | | ( n [ 1 ] = = ' . ' & & n [ 2 ] = = ' \0 ' ) ) {
continue ;
}
}
if ( ! validate_net_name ( n , INVALID_SHARENAME_CHARS , strlen ( n ) ) ) {
d_fprintf ( stderr , " get_share_list: ignoring bad share name %s \n " , n ) ;
continue ;
}
pstrcpy ( path , basepath ) ;
pstrcat ( path , " / " ) ;
pstrcat ( path , n ) ;
if ( sys_lstat ( path , & sbuf ) ! = 0 ) {
d_fprintf ( stderr , " get_share_list: can't lstat file %s. Error was %s \n " ,
path , strerror ( errno ) ) ;
continue ;
}
if ( ! S_ISREG ( sbuf . st_mode ) ) {
d_fprintf ( stderr , " get_share_list: file %s is not a regular file. Ignoring. \n " ,
path ) ;
continue ;
}
if ( only_ours & & sbuf . st_uid ! = myuid ) {
continue ;
}
if ( ! unix_wild_match ( wcard , n ) ) {
continue ;
}
/* (Finally) - add to list. */
fl = TALLOC_P ( ctx , struct file_list ) ;
if ( ! fl ) {
return - 1 ;
}
fl - > pathname = talloc_strdup ( ctx , n ) ;
if ( ! fl - > pathname ) {
return - 1 ;
}
DLIST_ADD ( flist , fl ) ;
}
sys_closedir ( dp ) ;
return 0 ;
}
enum priv_op { US_LIST_OP , US_INFO_OP } ;
struct priv_info {
TALLOC_CTX * ctx ;
enum priv_op op ;
} ;
/***************************************************************************
Call a function for every share on the list .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-06 21:03:57 +03:00
static int process_share_list ( int ( * fn ) ( struct file_list * , void * ) , void * priv )
2006-02-04 01:19:41 +03:00
{
struct file_list * fl ;
int ret = 0 ;
for ( fl = flist ; fl ; fl = fl - > next ) {
2006-02-06 21:03:57 +03:00
ret = ( * fn ) ( fl , priv ) ;
2006-02-04 01:19:41 +03:00
}
return ret ;
}
/***************************************************************************
Info function .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-06 21:03:57 +03:00
static int info_fn ( struct file_list * fl , void * priv )
2006-02-04 01:19:41 +03:00
{
SMB_STRUCT_STAT sbuf ;
char * * lines = NULL ;
2006-02-06 21:03:57 +03:00
struct priv_info * pi = ( struct priv_info * ) priv ;
2006-02-04 01:19:41 +03:00
TALLOC_CTX * ctx = pi - > ctx ;
int fd = - 1 ;
int numlines = 0 ;
SEC_DESC * psd = NULL ;
pstring basepath ;
pstring sharepath ;
pstring comment ;
pstring acl_str ;
int num_aces ;
char sep_str [ 2 ] ;
enum usershare_err us_err ;
sep_str [ 0 ] = * lp_winbind_separator ( ) ;
sep_str [ 1 ] = ' \0 ' ;
get_basepath ( basepath ) ;
pstrcat ( basepath , " / " ) ;
pstrcat ( basepath , fl - > pathname ) ;
# ifdef O_NOFOLLOW
fd = sys_open ( basepath , O_RDONLY | O_NOFOLLOW , 0 ) ;
# else
fd = sys_open ( basepath , O_RDONLY , 0 ) ;
# endif
if ( fd = = - 1 ) {
d_fprintf ( stderr , " info_fn: unable to open %s. %s \n " ,
basepath , strerror ( errno ) ) ;
return - 1 ;
}
/* Paranoia... */
if ( sys_fstat ( fd , & sbuf ) ! = 0 ) {
d_fprintf ( stderr , " info_fn: can't fstat file %s. Error was %s \n " ,
basepath , strerror ( errno ) ) ;
close ( fd ) ;
return - 1 ;
}
if ( ! S_ISREG ( sbuf . st_mode ) ) {
d_fprintf ( stderr , " info_fn: file %s is not a regular file. Ignoring. \n " ,
basepath ) ;
close ( fd ) ;
return - 1 ;
}
lines = fd_lines_load ( fd , & numlines , 10240 ) ;
close ( fd ) ;
if ( lines = = NULL ) {
return - 1 ;
}
/* Ensure it's well formed. */
us_err = parse_usershare_file ( ctx , & sbuf , fl - > pathname , - 1 , lines , numlines ,
sharepath ,
comment ,
& psd ) ;
if ( us_err ! = USERSHARE_OK ) {
d_fprintf ( stderr , " info_fn: file %s is not a well formed usershare file. \n " ,
basepath ) ;
d_fprintf ( stderr , " info_fn: Error was %s. \n " ,
get_us_error_code ( us_err ) ) ;
return - 1 ;
}
pstrcpy ( acl_str , " usershare_acl= " ) ;
for ( num_aces = 0 ; num_aces < psd - > dacl - > num_aces ; num_aces + + ) {
char access_str [ 2 ] ;
const char * domain ;
const char * name ;
access_str [ 1 ] = ' \0 ' ;
if ( net_lookup_name_from_sid ( ctx , & psd - > dacl - > ace [ num_aces ] . trustee , & domain , & name ) ) {
if ( * domain ) {
pstrcat ( acl_str , domain ) ;
pstrcat ( acl_str , sep_str ) ;
}
pstrcat ( acl_str , name ) ;
} else {
fstring sidstr ;
sid_to_string ( sidstr , & psd - > dacl - > ace [ num_aces ] . trustee ) ;
pstrcat ( acl_str , sidstr ) ;
}
pstrcat ( acl_str , " : " ) ;
if ( psd - > dacl - > ace [ num_aces ] . type = = SEC_ACE_TYPE_ACCESS_DENIED ) {
pstrcat ( acl_str , " D, " ) ;
} else {
if ( psd - > dacl - > ace [ num_aces ] . info . mask & GENERIC_ALL_ACCESS ) {
pstrcat ( acl_str , " F, " ) ;
} else {
pstrcat ( acl_str , " R, " ) ;
}
}
}
acl_str [ strlen ( acl_str ) - 1 ] = ' \0 ' ;
if ( pi - > op = = US_INFO_OP ) {
d_printf ( " [%s] \n " , fl - > pathname ) ;
d_printf ( " path=%s \n " , sharepath ) ;
d_printf ( " comment=%s \n " , comment ) ;
d_printf ( " %s \n \n " , acl_str ) ;
} else if ( pi - > op = = US_LIST_OP ) {
d_printf ( " %s \n " , fl - > pathname ) ;
}
return 0 ;
}
/***************************************************************************
Print out info ( internal detail ) on userlevel shares .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int net_usershare_info ( int argc , const char * * argv )
{
fstring wcard ;
BOOL only_ours = True ;
int ret = - 1 ;
struct priv_info pi ;
TALLOC_CTX * ctx ;
fstrcpy ( wcard , " * " ) ;
if ( opt_long_list_entries ) {
only_ours = False ;
}
switch ( argc ) {
case 0 :
break ;
case 1 :
fstrcpy ( wcard , argv [ 0 ] ) ;
break ;
default :
return net_usershare_info_usage ( argc , argv ) ;
}
strlower_m ( wcard ) ;
ctx = talloc_init ( " share_info " ) ;
ret = get_share_list ( ctx , wcard , only_ours ) ;
if ( ret ) {
return ret ;
}
pi . ctx = ctx ;
pi . op = US_INFO_OP ;
ret = process_share_list ( info_fn , & pi ) ;
talloc_destroy ( ctx ) ;
return ret ;
}
/***************************************************************************
Add a single userlevel share .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int net_usershare_add ( int argc , const char * * argv )
{
TALLOC_CTX * ctx = NULL ;
SMB_STRUCT_STAT sbuf ;
SMB_STRUCT_STAT lsbuf ;
char * sharename ;
pstring full_path ;
pstring full_path_tmp ;
const char * us_path ;
const char * us_comment ;
const char * arg_acl ;
char * us_acl ;
char * file_img ;
int num_aces = 0 ;
int i ;
int tmpfd ;
const char * pacl ;
size_t to_write ;
uid_t myeuid = geteuid ( ) ;
us_comment = " " ;
arg_acl = " S-1-1-0:R " ;
switch ( argc ) {
case 0 :
case 1 :
default :
return net_usershare_add_usage ( argc , argv ) ;
case 2 :
sharename = strdup_lower ( argv [ 0 ] ) ;
us_path = argv [ 1 ] ;
break ;
case 3 :
sharename = strdup_lower ( argv [ 0 ] ) ;
us_path = argv [ 1 ] ;
us_comment = argv [ 2 ] ;
break ;
case 4 :
sharename = strdup_lower ( argv [ 0 ] ) ;
us_path = argv [ 1 ] ;
us_comment = argv [ 2 ] ;
arg_acl = argv [ 3 ] ;
break ;
}
if ( ! validate_net_name ( sharename , INVALID_SHARENAME_CHARS , strlen ( sharename ) ) ) {
d_fprintf ( stderr , " net usershare add: share name %s contains "
" invalid characters (any of %s) \n " ,
sharename , INVALID_SHARENAME_CHARS ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
/* Disallow shares the same as users. */
if ( getpwnam ( sharename ) ) {
d_fprintf ( stderr , " net usershare add: share name %s is already a valid system user name \n " ,
sharename ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
/* Construct the full path for the usershare file. */
get_basepath ( full_path ) ;
pstrcat ( full_path , " / " ) ;
pstrcpy ( full_path_tmp , full_path ) ;
pstrcat ( full_path , sharename ) ;
pstrcat ( full_path_tmp , " :tmpXXXXXX " ) ;
/* The path *must* be absolute. */
if ( us_path [ 0 ] ! = ' / ' ) {
d_fprintf ( stderr , " net usershare add: path %s is not an absolute path. \n " ,
us_path ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
/* Check the directory to be shared exists. */
if ( sys_stat ( us_path , & sbuf ) ! = 0 ) {
d_fprintf ( stderr , " net usershare add: cannot stat path %s to ensure "
" this is a directory. Error was %s \n " ,
us_path , strerror ( errno ) ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
if ( ! S_ISDIR ( sbuf . st_mode ) ) {
d_fprintf ( stderr , " net usershare add: path %s is not a directory. \n " ,
us_path ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
/* If we're not root, check if we're restricted to sharing out directories
that we own only . */
if ( ( myeuid ! = 0 ) & & lp_usershare_owner_only ( ) & & ( myeuid ! = sbuf . st_uid ) ) {
d_fprintf ( stderr , " net usershare add: cannot share path %s as "
" we are restricted to only sharing directories we own. \n " ,
us_path ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
/* No validation needed on comment. Now go through and validate the
acl string . Convert names to SID ' s as needed . Then run it through
parse_usershare_acl to ensure it ' s valid . */
ctx = talloc_init ( " share_info " ) ;
/* Start off the string we'll append to. */
us_acl = talloc_strdup ( ctx , " " ) ;
pacl = arg_acl ;
num_aces = 1 ;
/* Add the number of ',' characters to get the number of aces. */
num_aces + = count_chars ( pacl , ' , ' ) ;
for ( i = 0 ; i < num_aces ; i + + ) {
DOM_SID sid ;
const char * pcolon = strchr_m ( pacl , ' : ' ) ;
const char * name ;
if ( pcolon = = NULL ) {
d_fprintf ( stderr , " net usershare add: malformed acl %s (missing ':'). \n " ,
pacl ) ;
talloc_destroy ( ctx ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
switch ( pcolon [ 1 ] ) {
case ' f ' :
case ' F ' :
case ' d ' :
case ' r ' :
case ' R ' :
break ;
default :
d_fprintf ( stderr , " net usershare add: malformed acl %s "
" (access control must be 'r', 'f', or 'd') \n " ,
pacl ) ;
talloc_destroy ( ctx ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
if ( pcolon [ 2 ] ! = ' , ' & & pcolon [ 2 ] ! = ' \0 ' ) {
d_fprintf ( stderr , " net usershare add: malformed terminating character for acl %s \n " ,
pacl ) ;
talloc_destroy ( ctx ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
/* Get the name */
name = talloc_strndup ( ctx , pacl , pcolon - pacl ) ;
if ( ! string_to_sid ( & sid , name ) ) {
/* Convert to a SID */
if ( ! net_lookup_sid_from_name ( ctx , name , & sid ) ) {
d_fprintf ( stderr , " net usershare add: cannot convert name %s to a SID. \n " ,
name ) ;
talloc_destroy ( ctx ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
}
us_acl = talloc_asprintf_append ( us_acl , " %s:%c, " , sid_string_static ( & sid ) , pcolon [ 1 ] ) ;
/* Move to the next ACL entry. */
if ( pcolon [ 2 ] = = ' , ' ) {
pacl = & pcolon [ 3 ] ;
}
}
/* Remove the last ',' */
us_acl [ strlen ( us_acl ) - 1 ] = ' \0 ' ;
/* Create a temporary filename for this share. */
tmpfd = smb_mkstemp ( full_path_tmp ) ;
if ( tmpfd = = - 1 ) {
d_fprintf ( stderr , " net usershare add: cannot create tmp file %s \n " ,
full_path_tmp ) ;
talloc_destroy ( ctx ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
/* Ensure we opened the file we thought we did. */
if ( sys_lstat ( full_path_tmp , & lsbuf ) ! = 0 ) {
d_fprintf ( stderr , " net usershare add: cannot lstat tmp file %s \n " ,
full_path_tmp ) ;
talloc_destroy ( ctx ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
/* Check this is the same as the file we opened. */
if ( sys_fstat ( tmpfd , & sbuf ) ! = 0 ) {
d_fprintf ( stderr , " net usershare add: cannot fstat tmp file %s \n " ,
full_path_tmp ) ;
talloc_destroy ( ctx ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
if ( ! S_ISREG ( sbuf . st_mode ) | | sbuf . st_dev ! = lsbuf . st_dev | | sbuf . st_ino ! = lsbuf . st_ino ) {
d_fprintf ( stderr , " net usershare add: tmp file %s is not a regular file ? \n " ,
full_path_tmp ) ;
talloc_destroy ( ctx ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
if ( fchmod ( tmpfd , 0644 ) = = - 1 ) {
d_fprintf ( stderr , " net usershare add: failed to fchmod tmp file %s to 0644n " ,
full_path_tmp ) ;
talloc_destroy ( ctx ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
/* Create the in-memory image of the file. */
file_img = talloc_strdup ( ctx , " #VERSION 1 \n path= " ) ;
file_img = talloc_asprintf_append ( file_img , " %s \n comment=%s \n usershare_acl=%s \n " ,
us_path , us_comment , us_acl ) ;
to_write = strlen ( file_img ) ;
if ( write ( tmpfd , file_img , to_write ) ! = to_write ) {
d_fprintf ( stderr , " net usershare add: failed to write %u bytes to file %s. Error was %s \n " ,
( unsigned int ) to_write , full_path_tmp , strerror ( errno ) ) ;
unlink ( full_path_tmp ) ;
talloc_destroy ( ctx ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
/* Attempt to replace any existing share by this name. */
if ( rename ( full_path_tmp , full_path ) ! = 0 ) {
unlink ( full_path_tmp ) ;
d_fprintf ( stderr , " net usershare add: failed to add share %s. Error was %s \n " ,
sharename , strerror ( errno ) ) ;
talloc_destroy ( ctx ) ;
close ( tmpfd ) ;
SAFE_FREE ( sharename ) ;
return - 1 ;
}
close ( tmpfd ) ;
talloc_destroy ( ctx ) ;
if ( opt_long_list_entries ) {
const char * my_argv [ 2 ] ;
my_argv [ 0 ] = sharename ;
my_argv [ 1 ] = NULL ;
net_usershare_info ( 1 , argv ) ;
}
SAFE_FREE ( sharename ) ;
return 0 ;
}
#if 0
/***************************************************************************
List function .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-06 21:03:57 +03:00
static int list_fn ( struct file_list * fl , void * priv )
2006-02-04 01:19:41 +03:00
{
d_printf ( " %s \n " , fl - > pathname ) ;
return 0 ;
}
# endif
/***************************************************************************
List userlevel shares .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int net_usershare_list ( int argc , const char * * argv )
{
fstring wcard ;
BOOL only_ours = True ;
int ret = - 1 ;
struct priv_info pi ;
TALLOC_CTX * ctx ;
fstrcpy ( wcard , " * " ) ;
if ( opt_long_list_entries ) {
only_ours = False ;
}
switch ( argc ) {
case 0 :
break ;
case 1 :
fstrcpy ( wcard , argv [ 0 ] ) ;
break ;
default :
return net_usershare_list_usage ( argc , argv ) ;
}
strlower_m ( wcard ) ;
ctx = talloc_init ( " share_list " ) ;
ret = get_share_list ( ctx , wcard , only_ours ) ;
if ( ret ) {
return ret ;
}
pi . ctx = ctx ;
pi . op = US_LIST_OP ;
ret = process_share_list ( info_fn , & pi ) ;
talloc_destroy ( ctx ) ;
return ret ;
}
/***************************************************************************
Handle " net usershare help * " subcommands .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int net_usershare_help ( int argc , const char * * argv )
{
struct functable func [ ] = {
{ " ADD " , net_usershare_add_usage } ,
{ " DELETE " , net_usershare_delete_usage } ,
{ " INFO " , net_usershare_info_usage } ,
{ " LIST " , net_usershare_list_usage } ,
{ NULL , NULL } } ;
return net_run_function ( argc , argv , func , net_usershare_usage ) ;
}
/***************************************************************************
Entry - point for all the USERSHARE functions .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int net_usershare ( int argc , const char * * argv )
{
SMB_STRUCT_DIR * dp ;
struct functable func [ ] = {
{ " ADD " , net_usershare_add } ,
{ " DELETE " , net_usershare_delete } ,
{ " INFO " , net_usershare_info } ,
{ " LIST " , net_usershare_list } ,
{ " HELP " , net_usershare_help } ,
{ NULL , NULL }
} ;
if ( lp_usershare_max_shares ( ) = = 0 ) {
d_fprintf ( stderr , " net usershare: usershares are currently disabled \n " ) ;
return - 1 ;
}
dp = sys_opendir ( lp_usershare_path ( ) ) ;
if ( ! dp ) {
int err = errno ;
d_fprintf ( stderr , " net usershare: cannot open usershare directory %s. Error %s \n " ,
lp_usershare_path ( ) , strerror ( err ) ) ;
if ( err = = EACCES ) {
d_fprintf ( stderr , " You do not have permission to create a usershare. Ask your "
" administrator to grant you permissions to create a share. \n " ) ;
} else if ( err = = ENOENT ) {
d_fprintf ( stderr , " Please ask your system administrator to "
" enable user sharing. \n " ) ;
}
return - 1 ;
}
sys_closedir ( dp ) ;
return net_run_function ( argc , argv , func , net_usershare_usage ) ;
}