1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-24 10:50:22 +03:00

Additional revamped libsmbclient documentation

- Ensured that all public functions have documentation in libsmbclient.h
- Reformatted for "proper" indentation
- Re-added temporarily-disabled alternate authentication function capability

Derrell
(This used to be commit 64b7150d92849a1e1e2416b9dcc12fae8d6bea99)
This commit is contained in:
Derrell Lipman 2008-03-01 20:44:21 -05:00
parent 4ba42cbe0f
commit 223940d9a8
14 changed files with 2617 additions and 2199 deletions

View File

@ -109,22 +109,13 @@ main(int argc, char * argv[])
/* Set mandatory options (is that a contradiction in terms?) */
smbc_setDebug(context, debug);
#if 0
if (context_auth) {
context->callbacks.auth_fn = NULL;
smbc_option_set(context,
"auth_function",
(void *) get_auth_data_with_context_fn);
smbc_option_set(context, "user_data", "hello world");
smbc_setFunctionAuthDataWithContext(context,
get_auth_data_with_context_fn);
smbc_setOptionUserData(context, "hello world");
} else {
context->callbacks.auth_fn =
(no_auth ? no_auth_data_fn : get_auth_data_fn);
smbc_setFunctionAuthData(context, get_auth_data_fn);
}
#else
#warning "temporarily remove setting alternate auth function"
smbc_setFunctionAuthData(context,
(no_auth ? no_auth_data_fn : get_auth_data_fn));
#endif
/* If we've been asked to log to stderr instead of stdout, ... */
if (debug_stderr) {

View File

@ -111,23 +111,23 @@ struct _SMBCFILE {
struct SMBC_internal_data {
/* True when this handle is initialized */
bool initialized;
bool initialized;
#if 0 /* Left in libsmbclient.h for backward compatibility */
/* Netbios name used for making connections */
char * netbios_name;
char * netbios_name;
/* Workgroup used for making connections */
char * workgroup;
char * workgroup;
/* Username used for making connections */
char * user;
char * user;
/* Debug level */
int debug;
int debug;
/* Connection timeout value */
int timeout;
int timeout;
#endif
/* dirent pointer location
@ -141,22 +141,22 @@ struct SMBC_internal_data {
* According to <linux/limits.h>, NAME_MAX is 255. Is it longer
* anyplace else?
*/
char dirent[1024];
char dirent[1024];
/*
* server connection list
*/
SMBCSRV * servers;
SMBCSRV * servers;
/*
* open file/dir list
*/
SMBCFILE * files;
SMBCFILE * files;
/*
* Log to standard error instead of the more typical standard output
*/
bool debug_stderr;
bool debug_stderr;
/*
* Support "Create Time" in get/set with the *xattr() functions, if
@ -165,27 +165,34 @@ struct SMBC_internal_data {
* CREATE_TIME. Default is FALSE, i.e. to use the old-style shorter
* names and to not support CREATE time, for backward compatibility.
*/
bool full_time_names;
bool full_time_names;
/*
* The share mode of a file being opened. To match POSIX semantics
* (and maintain backward compatibility), DENY_NONE is the default.
*/
smbc_share_mode share_mode;
smbc_share_mode share_mode;
/*
* Authentication function which includes the context. This will be
* used if set; otherwise context->callbacks.auth_fn() will be used.
*/
smbc_get_auth_data_with_context_fn auth_fn_with_context;
/*
* An opaque (to this library) user data handle which can be set
* and retrieved with smbc_option_set() and smbc_option_get().
*/
void * user_data;
void * user_data;
/*
* Should we attempt UNIX smb encryption ?
* Set to 0 if we should never attempt, set to 1 if
* encryption requested, set to 2 if encryption required.
*/
int smb_encryption_level;
smbc_smb_encrypt_level smb_encryption_level;
#if 0 /* Left in libsmbclient.h for backward compatibility */
/*
* From how many local master browsers should the list of
* workgroups be retrieved? It can take up to 12 minutes or
@ -203,7 +210,7 @@ struct SMBC_internal_data {
* networks with many workgroups, a suitable value for this
* variable is probably somewhere around 3. (Default: 3).
*/
int browse_max_lmb_count;
int browse_max_lmb_count;
/*
* There is a difference in the desired return strings from
@ -228,7 +235,7 @@ struct SMBC_internal_data {
*
* For backwards compatibility, this option defaults to False.
*/
bool urlencode_readdir_entries;
bool urlencode_readdir_entries;
/*
* Some Windows versions appear to have a limit to the number
@ -240,15 +247,14 @@ struct SMBC_internal_data {
* avoided by using only a single connection to each server,
* and issuing a new TREE CONNECT when the share is accessed.
*/
bool one_share_per_server;
bool one_share_per_server;
#if 0 /* Left in libsmbclient.h (flags) for backward compatibility */
/* Kerberos-related flags */
bool use_kerberos;
bool fallback_after_kerberos;
bool use_kerberos;
bool fallback_after_kerberos;
/* Don't try to do automatic anonymous login */
bool no_auto_anonymous_login;
bool no_auto_anonymous_login;
/* Server-related functions */
struct

View File

@ -155,6 +155,21 @@ typedef enum smbc_share_mode
} smbc_share_mode;
/**
* Values for option SMB Encryption Level, as set and retrieved with
* smbc_setOptionSmbEncryptionLevel() and smbc_getOptionSmbEncryptionLevel()
*/
typedef enum smbc_smb_encrypt_level
{
SMBC_ENCRYPTLEVEL_NONE = 0,
SMBC_ENCRYPTLEVEL_REQUEST = 1,
SMBC_ENCRYPTLEVEL_REQUIRE = 2
} smbc_smb_encrypt_level;
typedef int smbc_bool;
#ifndef ENOATTR
# define ENOATTR ENOENT /* No such attribute */
#endif
@ -214,11 +229,17 @@ typedef struct _SMBCCTX SMBCCTX;
/*
* Flags for SMBCCTX->flags
*
* NEW CODE SHOULD NOT DIRECTLY MANIPULATE THE CONTEXT STRUCTURE.
* For these options, use smbc_option_set() and smbc_option_get().
* Instead, use:
* smbc_setOptionUseKerberos()
* smbc_getOptionUseKerberos()
* smbc_setOptionFallbackAfterKerberos()
* smbc_getOptionFallbackAFterKerberos()
* smbc_setOptionNoAutoAnonymousLogin()
* smbc_getOptionNoAutoAnonymousLogin()
*/
/* Flags for SMBCCTX->flags */
# define SMB_CTX_FLAG_USE_KERBEROS (1 << 0)
# define SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS (1 << 1)
# define SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON (1 << 2)
@ -398,48 +419,286 @@ typedef int (*smbc_remove_cached_srv_fn)(SMBCCTX * c, SMBCSRV *srv);
typedef int (*smbc_purge_cached_srv_fn) (SMBCCTX * c);
/*****************************************
* Getters and setters for CONFIGURATION *
*****************************************/
/** Get the debug level */
int smbc_getDebug(SMBCCTX *c);
int
smbc_getDebug(SMBCCTX *c);
/** Set the debug level */
void smbc_setDebug(SMBCCTX *c, int debug);
void
smbc_setDebug(SMBCCTX *c, int debug);
/** Get the netbios name used for making connections */
char * smbc_getNetbiosName(SMBCCTX *c);
char *
smbc_getNetbiosName(SMBCCTX *c);
/** Set the netbios name used for making connections */
void smbc_setNetbiosName(SMBCCTX *c, char * netbios_name);
void
smbc_setNetbiosName(SMBCCTX *c, char * netbios_name);
/** Get the workgroup used for making connections */
char * smbc_getWorkgroup(SMBCCTX *c);
char *
smbc_getWorkgroup(SMBCCTX *c);
/** Set the workgroup used for making connections */
void smbc_setWorkgroup(SMBCCTX *c, char * workgroup);
/** Get the username used for making connections */
char * smbc_getUser(SMBCCTX *c);
char *
smbc_getUser(SMBCCTX *c);
/** Set the username used for making connections */
void smbc_setUser(SMBCCTX *c, char * user);
void
smbc_setUser(SMBCCTX *c, char * user);
/**
* Get the timeout used for waiting on connections and response data
* (in milliseconds)
*/
int smbc_getTimeout(SMBCCTX *c);
int
smbc_getTimeout(SMBCCTX *c);
/**
* Set the timeout used for waiting on connections and response data
* (in milliseconds)
*/
void smbc_setTimeout(SMBCCTX *c, int timeout);
void
smbc_setTimeout(SMBCCTX *c, int timeout);
/***********************************
* Getters and setters for OPTIONS *
***********************************/
/** Get whether to log to standard error instead of standard output */
smbc_bool
smbc_getOptionDebugToStderr(SMBCCTX *c);
/** Set whether to log to standard error instead of standard output */
void
smbc_setOptionDebugToStderr(SMBCCTX *c, smbc_bool b);
/**
* Get whether to use new-style time attribute names, e.g. WRITE_TIME rather
* than the old-style names such as M_TIME. This allows also setting/getting
* CREATE_TIME which was previously unimplemented. (Note that the old C_TIME
* was supposed to be CHANGE_TIME but was confused and sometimes referred to
* CREATE_TIME.)
*/
smbc_bool
smbc_getOptionFullTimeNames(SMBCCTX *c);
/**
* Set whether to use new-style time attribute names, e.g. WRITE_TIME rather
* than the old-style names such as M_TIME. This allows also setting/getting
* CREATE_TIME which was previously unimplemented. (Note that the old C_TIME
* was supposed to be CHANGE_TIME but was confused and sometimes referred to
* CREATE_TIME.)
*/
void
smbc_setOptionFullTimeNames(SMBCCTX *c, smbc_bool b);
/**
* Get the share mode to use for files opened with SMBC_open_ctx(). The
* default is SMBC_SHAREMODE_DENY_NONE.
*/
smbc_share_mode
smbc_getOptionOpenShareMode(SMBCCTX *c);
/**
* Set the share mode to use for files opened with SMBC_open_ctx(). The
* default is SMBC_SHAREMODE_DENY_NONE.
*/
void
smbc_setOptionOpenShareMode(SMBCCTX *c, smbc_share_mode share_mode);
/** Retrieve a previously saved user data handle */
void *
smbc_getOptionUserData(SMBCCTX *c);
/** Save a user data handle */
void
smbc_setOptionUserData(SMBCCTX *c, void *user_data);
/** Get the encoded value for encryption level. */
smbc_smb_encrypt_level
smbc_getOptionSmbEncryptionLevel(SMBCCTX *c);
/** Set the encoded value for encryption level. */
void
smbc_setOptionSmbEncryptionLevel(SMBCCTX *c, smbc_smb_encrypt_level level);
/**
* Get from how many local master browsers should the list of workgroups be
* retrieved. It can take up to 12 minutes or longer after a server becomes a
* local master browser, for it to have the entire browse list (the list of
* workgroups/domains) from an entire network. Since a client never knows
* which local master browser will be found first, the one which is found
* first and used to retrieve a browse list may have an incomplete or empty
* browse list. By requesting the browse list from multiple local master
* browsers, a more complete list can be generated. For small networks (few
* workgroups), it is recommended that this value be set to 0, causing the
* browse lists from all found local master browsers to be retrieved and
* merged. For networks with many workgroups, a suitable value for this
* variable is probably somewhere around 3. (Default: 3).
*/
int
smbc_getOptionBrowseMaxLmbCount(SMBCCTX *c);
/**
* Set from how many local master browsers should the list of workgroups be
* retrieved. It can take up to 12 minutes or longer after a server becomes a
* local master browser, for it to have the entire browse list (the list of
* workgroups/domains) from an entire network. Since a client never knows
* which local master browser will be found first, the one which is found
* first and used to retrieve a browse list may have an incomplete or empty
* browse list. By requesting the browse list from multiple local master
* browsers, a more complete list can be generated. For small networks (few
* workgroups), it is recommended that this value be set to 0, causing the
* browse lists from all found local master browsers to be retrieved and
* merged. For networks with many workgroups, a suitable value for this
* variable is probably somewhere around 3. (Default: 3).
*/
void
smbc_setOptionBrowseMaxLmbCount(SMBCCTX *c, int count);
/**
* Get whether to url-encode readdir entries.
*
* There is a difference in the desired return strings from
* smbc_readdir() depending upon whether the filenames are to
* be displayed to the user, or whether they are to be
* appended to the path name passed to smbc_opendir() to call
* a further smbc_ function (e.g. open the file with
* smbc_open()). In the former case, the filename should be
* in "human readable" form. In the latter case, the smbc_
* functions expect a URL which must be url-encoded. Those
* functions decode the URL. If, for example, smbc_readdir()
* returned a file name of "abc%20def.txt", passing a path
* with this file name attached to smbc_open() would cause
* smbc_open to attempt to open the file "abc def.txt" since
* the %20 is decoded into a space.
*
* Set this option to True if the names returned by
* smbc_readdir() should be url-encoded such that they can be
* passed back to another smbc_ call. Set it to False if the
* names returned by smbc_readdir() are to be presented to the
* user.
*
* For backwards compatibility, this option defaults to False.
*/
smbc_bool
smbc_getOptionUrlEncodeReaddirEntries(SMBCCTX *c);
/**
* Set whether to url-encode readdir entries.
*
* There is a difference in the desired return strings from
* smbc_readdir() depending upon whether the filenames are to
* be displayed to the user, or whether they are to be
* appended to the path name passed to smbc_opendir() to call
* a further smbc_ function (e.g. open the file with
* smbc_open()). In the former case, the filename should be
* in "human readable" form. In the latter case, the smbc_
* functions expect a URL which must be url-encoded. Those
* functions decode the URL. If, for example, smbc_readdir()
* returned a file name of "abc%20def.txt", passing a path
* with this file name attached to smbc_open() would cause
* smbc_open to attempt to open the file "abc def.txt" since
* the %20 is decoded into a space.
*
* Set this option to True if the names returned by
* smbc_readdir() should be url-encoded such that they can be
* passed back to another smbc_ call. Set it to False if the
* names returned by smbc_readdir() are to be presented to the
* user.
*
* For backwards compatibility, this option defaults to False.
*/
void
smbc_setOptionUrlEncodeReaddirEntries(SMBCCTX *c, smbc_bool b);
/**
* Get whether to use the same connection for all shares on a server.
*
* Some Windows versions appear to have a limit to the number
* of concurrent SESSIONs and/or TREE CONNECTions. In
* one-shot programs (i.e. the program runs and then quickly
* ends, thereby shutting down all connections), it is
* probably reasonable to establish a new connection for each
* share. In long-running applications, the limitation can be
* avoided by using only a single connection to each server,
* and issuing a new TREE CONNECT when the share is accessed.
*/
smbc_bool
smbc_getOptionOneSharePerServer(SMBCCTX *c);
/**
* Set whether to use the same connection for all shares on a server.
*
* Some Windows versions appear to have a limit to the number
* of concurrent SESSIONs and/or TREE CONNECTions. In
* one-shot programs (i.e. the program runs and then quickly
* ends, thereby shutting down all connections), it is
* probably reasonable to establish a new connection for each
* share. In long-running applications, the limitation can be
* avoided by using only a single connection to each server,
* and issuing a new TREE CONNECT when the share is accessed.
*/
void
smbc_setOptionOneSharePerServer(SMBCCTX *c, smbc_bool b);
/** Get whether to enable use of kerberos */
smbc_bool
smbc_getOptionUseKerberos(SMBCCTX *c);
/** Set whether to enable use of kerberos */
void
smbc_setOptionUseKerberos(SMBCCTX *c, smbc_bool b);
/** Get whether to fallback after kerberos */
smbc_bool
smbc_getOptionFallbackAfterKerberos(SMBCCTX *c);
/** Set whether to fallback after kerberos */
void
smbc_setOptionFallbackAfterKerberos(SMBCCTX *c, smbc_bool b);
/** Get whether to automatically select anonymous login */
smbc_bool
smbc_getOptionNoAutoAnonymousLogin(SMBCCTX *c);
/** Set whether to automatically select anonymous login */
void
smbc_setOptionNoAutoAnonymousLogin(SMBCCTX *c, smbc_bool b);
/** Get the function for obtaining authentication data */
smbc_get_auth_data_fn smbc_getFunctionAuthData(SMBCCTX *c);
/*************************************
* Getters and setters for FUNCTIONS *
*************************************/
/** Set the function for obtaining authentication data */
void smbc_setFunctionAuthData(SMBCCTX *c, smbc_get_auth_data_fn f);
/** Get the new-style authentication function which includes the context. */
smbc_get_auth_data_with_context_fn
smbc_getFunctionAuthDataWithContext(SMBCCTX *c);
/** Set the new-style authentication function which includes the context. */
void
smbc_setFunctionAuthDataWithContext(SMBCCTX *c,
smbc_get_auth_data_with_context_fn fn);
/** Get the function for checking if a server is still good */
smbc_check_server_fn smbc_getFunctionCheckServer(SMBCCTX *c);
@ -492,9 +751,12 @@ struct smbc_server_cache * smbc_getServerCacheData(SMBCCTX *c);
void smbc_setServerCacheData(SMBCCTX *c, struct smbc_server_cache * cache);
/**
* Callable functions for files.
*/
/*****************************************************************
* Callable functions for files. *
* Each callable has a function signature typedef, a declaration *
* for the getter, and a declaration for the setter. *
*****************************************************************/
typedef SMBCFILE * (*smbc_open_fn)(SMBCCTX *c,
const char *fname,
@ -566,9 +828,12 @@ smbc_close_fn smbc_getFunctionClose(SMBCCTX *c);
void smbc_setFunctionClose(SMBCCTX *c, smbc_close_fn f);
/**
* Callable functions for directories.
*/
/*****************************************************************
* Callable functions for directories. *
* Each callable has a function signature typedef, a declaration *
* for the getter, and a declaration for the setter. *
*****************************************************************/
typedef SMBCFILE * (*smbc_opendir_fn)(SMBCCTX *c,
const char *fname);
@ -621,9 +886,12 @@ smbc_fstatdir_fn smbc_getFunctionFstatdir(SMBCCTX *c);
void smbc_setFunctionFstatdir(SMBCCTX *c, smbc_fstatdir_fn f);
/**
* Callable functions applicable to both files and directories.
*/
/*****************************************************************
* Callable functions applicable to both files and directories. *
* Each callable has a function signature typedef, a declaration *
* for the getter, and a declaration for the setter. *
*****************************************************************/
typedef int (*smbc_chmod_fn)(SMBCCTX *c,
const char *fname,
@ -668,9 +936,12 @@ smbc_listxattr_fn smbc_getFunctionListxattr(SMBCCTX *c);
void smbc_setFunctionListxattr(SMBCCTX *c, smbc_listxattr_fn f);
/**
* Callable functions related to printing
*/
/*****************************************************************
* Callable functions for printing. *
* Each callable has a function signature typedef, a declaration *
* for the getter, and a declaration for the setter. *
*****************************************************************/
typedef int (*smbc_print_file_fn)(SMBCCTX *c_file,
const char *fname,
@ -2341,6 +2612,7 @@ struct _SMBCCTX {
/**
* debug level
*
* Manually setting/retrieving this value is deprecated.
* Use smbc_getDebug() and smbc_setDebug()
*/
int debug;
@ -2348,6 +2620,7 @@ struct _SMBCCTX {
/**
* netbios name used for making connections
*
* Manually setting/retrieving this value is deprecated.
* Use smbc_getNetbiosName() and smbc_setNetbiosName()
*/
char * netbios_name;
@ -2355,6 +2628,7 @@ struct _SMBCCTX {
/**
* workgroup name used for making connections
*
* Manually setting/retrieving this value is deprecated.
* Use smbc_getWorkgroup() and smbc_setWorkgroup()
*/
char * workgroup;
@ -2362,6 +2636,7 @@ struct _SMBCCTX {
/**
* username used for making connections
*
* Manually setting/retrieving this value is deprecated.
* Use smbc_getUser() and smbc_setUser()
*/
char * user;
@ -2370,6 +2645,7 @@ struct _SMBCCTX {
* timeout used for waiting on connections / response data (in
* milliseconds)
*
* Manually setting/retrieving this value is deprecated.
* Use smbc_getTimeout() and smbc_setTimeout()
*/
int timeout;
@ -2379,6 +2655,8 @@ struct _SMBCCTX {
* callable functions for files:
* For usage and return values see the SMBC_* functions
*
* Manually setting/retrieving these values is deprecated.
*
* Use smbc_getFunction*() and smbc_setFunction*(), e.g.
* smbc_getFunctionOpen(), smbc_setFunctionUnlink(), etc.
*/
@ -2433,6 +2711,7 @@ struct _SMBCCTX {
/**
* authentication function callback: called upon auth requests
*
* Manually setting/retrieving this value is deprecated.
* Use smbc_getFunctionAuthData(), smbc_setFunctionAuthData()
*/
smbc_get_auth_data_fn get_auth_data_fn;
@ -2440,6 +2719,7 @@ struct _SMBCCTX {
/**
* check if a server is still good
*
* Manually setting/retrieving this value is deprecated.
* Use smbc_getFunctionCheckServer(),
* smbc_setFunctionCheckServer()
*/
@ -2448,6 +2728,7 @@ struct _SMBCCTX {
/**
* remove a server if unused
*
* Manually setting/retrieving this value is deprecated.
* Use smbc_getFunctionRemoveUnusedServer(),
* smbc_setFunctionCheckServer()
*/
@ -2467,6 +2748,7 @@ struct _SMBCCTX {
/**
* server cache addition
*
* Manually setting/retrieving this value is deprecated.
* Use smbc_getFunctionAddCachedServer(),
* smbc_setFunctionAddCachedServer()
*/
@ -2475,6 +2757,7 @@ struct _SMBCCTX {
/**
* server cache lookup
*
* Manually setting/retrieving this value is deprecated.
* Use smbc_getFunctionGetCachedServer(),
* smbc_setFunctionGetCachedServer()
*/
@ -2483,6 +2766,7 @@ struct _SMBCCTX {
/**
* server cache removal
*
* Manually setting/retrieving this value is deprecated.
* Use smbc_getFunctionRemoveCachedServer(),
* smbc_setFunctionRemoveCachedServer()
*/
@ -2492,6 +2776,7 @@ struct _SMBCCTX {
* server cache purging, try to remove all cached servers
* (disconnect)
*
* Manually setting/retrieving this value is deprecated.
* Use smbc_getFunctionPurgeCachedServers(),
* smbc_setFunctionPurgeCachedServers()
*/
@ -2500,6 +2785,7 @@ struct _SMBCCTX {
/**
* Space to store private data of the server cache.
*
* Manually setting/retrieving this value is deprecated.
* Use smbc_getServerCacheData(), smbc_setServerCacheData()
*/
struct smbc_server_cache * server_cache_data;
@ -2508,7 +2794,14 @@ struct _SMBCCTX {
/*
* Very old configuration options.
*
* Use smbc_option_set() and smbc_option_get() instead.
* Manually setting/retrieving this value is deprecated.
* Use one of the following functions instead:
* smbc_setOptionUseKerberos()
* smbc_getOptionUseKerberos()
* smbc_setOptionFallbackAfterKerberos()
* smbc_getOptionFallbackAfterKerberos()
* smbc_setOptionNoAutoAnonymousLogin()
* smbc_getOptionNoAutoAnonymousLogin()
*/
struct
{
@ -2521,66 +2814,12 @@ struct _SMBCCTX {
*
* NEW OPTIONS ARE NOT ADDED HERE!
*
* We must maintain ABI backward compatibility. We now use
* smbc_option_set() and smbc_option_get() for all newly added
* options.
* To set and retrieve options, use the smbc_setOption*() and
* smbc_getOption*() functions.
*/
struct _smbc_options {
/*
* From how many local master browsers should the list of
* workgroups be retrieved? It can take up to 12 minutes or
* longer after a server becomes a local master browser, for
* it to have the entire browse list (the list of
* workgroups/domains) from an entire network. Since a client
* never knows which local master browser will be found first,
* the one which is found first and used to retrieve a browse
* list may have an incomplete or empty browse list. By
* requesting the browse list from multiple local master
* browsers, a more complete list can be generated. For small
* networks (few workgroups), it is recommended that this
* value be set to 0, causing the browse lists from all found
* local master browsers to be retrieved and merged. For
* networks with many workgroups, a suitable value for this
* variable is probably somewhere around 3. (Default: 3).
*/
int browse_max_lmb_count;
/*
* There is a difference in the desired return strings from
* smbc_readdir() depending upon whether the filenames are to
* be displayed to the user, or whether they are to be
* appended to the path name passed to smbc_opendir() to call
* a further smbc_ function (e.g. open the file with
* smbc_open()). In the former case, the filename should be
* in "human readable" form. In the latter case, the smbc_
* functions expect a URL which must be url-encoded. Those
* functions decode the URL. If, for example, smbc_readdir()
* returned a file name of "abc%20def.txt", passing a path
* with this file name attached to smbc_open() would cause
* smbc_open to attempt to open the file "abc def.txt" since
* the %20 is decoded into a space.
*
* Set this option to True if the names returned by
* smbc_readdir() should be url-encoded such that they can be
* passed back to another smbc_ call. Set it to False if the
* names returned by smbc_readdir() are to be presented to the
* user.
*
* For backwards compatibility, this option defaults to False.
*/
int urlencode_readdir_entries;
/*
* Some Windows versions appear to have a limit to the number
* of concurrent SESSIONs and/or TREE CONNECTions. In
* one-shot programs (i.e. the program runs and then quickly
* ends, thereby shutting down all connections), it is
* probably reasonable to establish a new connection for each
* share. In long-running applications, the limitation can be
* avoided by using only a single connection to each server,
* and issuing a new TREE CONNECT when the share is accessed.
*/
int one_share_per_server;
} options;

View File

@ -35,10 +35,10 @@ struct smbc_server_cache {
char *workgroup;
char *username;
SMBCSRV *server;
struct smbc_server_cache *next, *prev;
};
/*
@ -54,51 +54,51 @@ SMBC_add_cached_server(SMBCCTX * context,
const char * username)
{
struct smbc_server_cache * srvcache = NULL;
if (!(srvcache = SMB_MALLOC_P(struct smbc_server_cache))) {
errno = ENOMEM;
DEBUG(3, ("Not enough space for server cache allocation\n"));
return 1;
}
ZERO_STRUCTP(srvcache);
srvcache->server = newsrv;
srvcache->server_name = SMB_STRDUP(server);
if (!srvcache->server_name) {
errno = ENOMEM;
goto failed;
}
srvcache->share_name = SMB_STRDUP(share);
if (!srvcache->share_name) {
errno = ENOMEM;
goto failed;
}
srvcache->workgroup = SMB_STRDUP(workgroup);
if (!srvcache->workgroup) {
errno = ENOMEM;
goto failed;
}
srvcache->username = SMB_STRDUP(username);
if (!srvcache->username) {
errno = ENOMEM;
goto failed;
}
DLIST_ADD((context->cache.server_cache_data), srvcache);
return 0;
failed:
failed:
SAFE_FREE(srvcache->server_name);
SAFE_FREE(srvcache->share_name);
SAFE_FREE(srvcache->workgroup);
SAFE_FREE(srvcache->username);
SAFE_FREE(srvcache);
return 1;
}
@ -117,19 +117,19 @@ SMBC_get_cached_server(SMBCCTX * context,
const char * user)
{
struct smbc_server_cache * srv = NULL;
/* Search the cache lines */
for (srv = context->cache.server_cache_data; srv; srv = srv->next) {
if (strcmp(server,srv->server_name) == 0 &&
strcmp(workgroup,srv->workgroup) == 0 &&
strcmp(user, srv->username) == 0) {
/* If the share name matches, we're cool */
if (strcmp(share, srv->share_name) == 0) {
return srv->server;
}
/*
* We only return an empty share name or the attribute
* server on an exact match (which would have been
@ -137,7 +137,7 @@ SMBC_get_cached_server(SMBCCTX * context,
*/
if (*share == '\0' || strcmp(share, "*IPC$") == 0)
continue;
/*
* Never return an empty share name or the attribute
* server if it wasn't what was requested.
@ -145,7 +145,7 @@ SMBC_get_cached_server(SMBCCTX * context,
if (*srv->share_name == '\0' ||
strcmp(srv->share_name, "*IPC$") == 0)
continue;
/*
* If we're only allowing one share per server, then
* a connection to the server (other than the
@ -164,7 +164,7 @@ SMBC_get_cached_server(SMBCCTX * context,
context->cache.remove_cached_server_fn(context, srv->server);
continue;
}
/*
* Save the new share name. We've
* disconnected from the old share, and are
@ -179,13 +179,13 @@ SMBC_get_cached_server(SMBCCTX * context,
context->cache.remove_cached_server_fn(context, srv->server);
continue;
}
return srv->server;
}
}
}
return NULL;
}
@ -200,10 +200,10 @@ SMBC_remove_cached_server(SMBCCTX * context,
SMBCSRV * server)
{
struct smbc_server_cache * srv = NULL;
for (srv = context->cache.server_cache_data; srv; srv = srv->next) {
if (server == srv->server) {
/* remove this sucker */
DLIST_REMOVE(context->cache.server_cache_data, srv);
SAFE_FREE(srv->server_name);
@ -229,13 +229,13 @@ SMBC_purge_cached_servers(SMBCCTX * context)
struct smbc_server_cache * srv;
struct smbc_server_cache * next;
int could_not_purge_all = 0;
for (srv = context->cache.server_cache_data,
next = (srv ? srv->next :NULL);
srv;
srv = next,
next = (srv ? srv->next : NULL)) {
if (SMBC_remove_unused_server(context, srv->server)) {
/* could not be removed */
could_not_purge_all = 1;

View File

@ -55,11 +55,11 @@ static int
add_fd(SMBCFILE * file)
{
struct smbc_compat_fdlist * f = smbc_compat_fd_avail;
if (f) {
/* We found one that's available */
DLIST_REMOVE(smbc_compat_fd_avail, f);
} else {
/*
* None were available, so allocate one. Keep the number of
@ -72,19 +72,19 @@ add_fd(SMBCFILE * file)
errno = EMFILE;
return -1;
}
f = SMB_MALLOC_P(struct smbc_compat_fdlist);
if (!f) {
errno = ENOMEM;
return -1;
}
f->fd = SMBC_BASE_FD + smbc_compat_nextfd++;
}
f->file = file;
DLIST_ADD(smbc_compat_fd_in_use, f);
return f->fd;
}
@ -95,13 +95,13 @@ static int
del_fd(int fd)
{
struct smbc_compat_fdlist * f = smbc_compat_fd_in_use;
while (f) {
if (f->fd == fd)
break;
f = f->next;
}
if (f) {
/* found */
DLIST_REMOVE(smbc_compat_fd_in_use, f);
@ -111,7 +111,7 @@ del_fd(int fd)
}
return 1;
}
int
@ -122,17 +122,17 @@ smbc_init(smbc_get_auth_data_fn fn,
statcont = smbc_new_context();
if (!statcont)
return -1;
smbc_setDebug(statcont, debug);
smbc_setFunctionAuthData(statcont, fn);
if (!smbc_init_context(statcont)) {
smbc_free_context(statcont, False);
return -1;
}
smbc_compat_initialized = 1;
return 0;
}
return 0;
@ -143,11 +143,11 @@ SMBCCTX *
smbc_set_context(SMBCCTX * context)
{
SMBCCTX *old_context = statcont;
if (context) {
/* Save provided context. It must have been initialized! */
statcont = context;
/* You'd better know what you're doing. We won't help you. */
smbc_compat_initialized = 1;
}
@ -163,11 +163,11 @@ smbc_open(const char *furl,
{
SMBCFILE * file;
int fd;
file = smbc_getFunctionOpen(statcont)(statcont, furl, flags, mode);
if (!file)
return -1;
fd = add_fd(file);
if (fd == -1)
smbc_getFunctionClose(statcont)(statcont, file);
@ -181,11 +181,11 @@ smbc_creat(const char *furl,
{
SMBCFILE * file;
int fd;
file = smbc_getFunctionCreat(statcont)(statcont, furl, mode);
if (!file)
return -1;
fd = add_fd(file);
if (fd == -1) {
/* Hmm... should we delete the file too ? I guess we could try */
@ -250,15 +250,15 @@ smbc_opendir(const char *durl)
{
SMBCFILE * file;
int fd;
file = smbc_getFunctionOpendir(statcont)(statcont, durl);
if (!file)
return -1;
fd = add_fd(file);
if (fd == -1)
smbc_getFunctionClosedir(statcont)(statcont, file);
return fd;
}
@ -357,14 +357,14 @@ smbc_utime(const char *fname,
struct utimbuf *utbuf)
{
struct timeval tv[2];
if (utbuf == NULL)
return smbc_getFunctionUtimes(statcont)(statcont, fname, NULL);
tv[0].tv_sec = utbuf->actime;
tv[1].tv_sec = utbuf->modtime;
tv[0].tv_usec = tv[1].tv_usec = 0;
return smbc_getFunctionUtimes(statcont)(statcont, fname, tv);
}
#endif
@ -519,7 +519,7 @@ int
smbc_open_print_job(const char *fname)
{
SMBCFILE * file;
file = smbc_getFunctionOpenPrintJob(statcont)(statcont, fname);
if (!file) return -1;
return file->cli_fd;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,11 @@ SMBC_open_ctx(SMBCCTX *context,
int flags,
mode_t mode)
{
char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *workgroup = NULL;
char *server = NULL;
char *share = NULL;
char *user = NULL;
char *password = NULL;
char *workgroup = NULL;
char *path = NULL;
char *targetpath = NULL;
struct cli_state *targetcli = NULL;
@ -45,38 +49,38 @@ SMBC_open_ctx(SMBCCTX *context,
SMBCFILE *file = NULL;
int fd;
TALLOC_CTX *frame = talloc_stackframe();
if (!context || !context->internal->initialized) {
errno = EINVAL; /* Best I can think of ... */
TALLOC_FREE(frame);
return NULL;
}
if (!fname) {
errno = EINVAL;
TALLOC_FREE(frame);
return NULL;
}
if (SMBC_parse_path(frame,
context,
fname,
&workgroup,
&server,
&share,
&path,
&user,
&password,
NULL)) {
context,
fname,
&workgroup,
&server,
&share,
&path,
&user,
&password,
NULL)) {
errno = EINVAL;
TALLOC_FREE(frame);
return NULL;
}
if (!user || user[0] == (char)0) {
user = talloc_strdup(frame, context->config.user);
if (!user) {
@ -85,62 +89,63 @@ SMBC_open_ctx(SMBCCTX *context,
return NULL;
}
}
srv = SMBC_server(frame, context, True,
server, share, &workgroup, &user, &password);
if (!srv) {
if (errno == EPERM) errno = EACCES;
TALLOC_FREE(frame);
return NULL; /* SMBC_server sets errno */
}
/* Hmmm, the test for a directory is suspect here ... FIXME */
if (strlen(path) > 0 && path[strlen(path) - 1] == '\\') {
fd = -1;
} else {
file = SMB_MALLOC_P(SMBCFILE);
if (!file) {
errno = ENOMEM;
TALLOC_FREE(frame);
return NULL;
}
ZERO_STRUCTP(file);
/*d_printf(">>>open: resolving %s\n", path);*/
if (!cli_resolve_path(frame, "", srv->cli, path, &targetcli, &targetpath)) {
if (!cli_resolve_path(frame, "", srv->cli, path,
&targetcli, &targetpath)) {
d_printf("Could not resolve %s\n", path);
SAFE_FREE(file);
TALLOC_FREE(frame);
return NULL;
}
/*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/
if ((fd = cli_open(targetcli, targetpath, flags,
context->internal->share_mode)) < 0) {
/* Handle the error ... */
SAFE_FREE(file);
errno = SMBC_errno(context, targetcli);
TALLOC_FREE(frame);
return NULL;
}
/* Fill in file struct */
file->cli_fd = fd;
file->fname = SMB_STRDUP(fname);
file->srv = srv;
file->offset = 0;
file->file = True;
DLIST_ADD(context->internal->files, file);
/*
* If the file was opened in O_APPEND mode, all write
* operations should be appended to the file. To do that,
@ -171,51 +176,50 @@ SMBC_open_ctx(SMBCCTX *context,
return NULL;
}
}
TALLOC_FREE(frame);
return file;
}
/* Check if opendir needed ... */
if (fd == -1) {
int eno = 0;
eno = SMBC_errno(context, srv->cli);
file = (context->posix_emu.opendir_fn)(context, fname);
if (!file) errno = eno;
TALLOC_FREE(frame);
return file;
}
errno = EINVAL; /* FIXME, correct errno ? */
TALLOC_FREE(frame);
return NULL;
}
/*
* Routine to create a file
*/
static int creat_bits = O_WRONLY | O_CREAT | O_TRUNC; /* FIXME: Do we need this */
SMBCFILE *
SMBC_creat_ctx(SMBCCTX *context,
const char *path,
mode_t mode)
{
if (!context || !context->internal->initialized) {
errno = EINVAL;
return NULL;
}
return SMBC_open_ctx(context, path, creat_bits, mode);
return SMBC_open_ctx(context, path,
O_WRONLY | O_CREAT | O_TRUNC, mode);
}
/*
@ -234,7 +238,7 @@ SMBC_read_ctx(SMBCCTX *context,
char *targetpath = NULL;
struct cli_state *targetcli = NULL;
TALLOC_CTX *frame = talloc_stackframe();
/*
* offset:
*
@ -245,51 +249,51 @@ SMBC_read_ctx(SMBCCTX *context,
* retrieving data at an offset greater than 4GB.
*/
off_t offset;
if (!context || !context->internal->initialized) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
DEBUG(4, ("smbc_read(%p, %d)\n", file, (int)count));
if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
errno = EBADF;
TALLOC_FREE(frame);
return -1;
}
offset = file->offset;
/* Check that the buffer exists ... */
if (buf == NULL) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
/*d_printf(">>>read: parsing %s\n", file->fname);*/
if (SMBC_parse_path(frame,
context,
file->fname,
NULL,
&server,
&share,
&path,
&user,
&password,
NULL)) {
context,
file->fname,
NULL,
&server,
&share,
&path,
&user,
&password,
NULL)) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
/*d_printf(">>>read: resolving %s\n", path);*/
if (!cli_resolve_path(frame, "", file->srv->cli, path,
&targetcli, &targetpath)) {
@ -298,24 +302,24 @@ SMBC_read_ctx(SMBCCTX *context,
return -1;
}
/*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
ret = cli_read(targetcli, file->cli_fd, (char *)buf, offset, count);
if (ret < 0) {
errno = SMBC_errno(context, targetcli);
TALLOC_FREE(frame);
return -1;
}
file->offset += ret;
DEBUG(4, (" --> %d\n", ret));
TALLOC_FREE(frame);
return ret; /* Success, ret bytes of data ... */
}
/*
@ -335,50 +339,50 @@ SMBC_write_ctx(SMBCCTX *context,
char *targetpath = NULL;
struct cli_state *targetcli = NULL;
TALLOC_CTX *frame = talloc_stackframe();
/* First check all pointers before dereferencing them */
if (!context || !context->internal->initialized) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
errno = EBADF;
TALLOC_FREE(frame);
return -1;
}
/* Check that the buffer exists ... */
if (buf == NULL) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
offset = file->offset; /* See "offset" comment in SMBC_read_ctx() */
/*d_printf(">>>write: parsing %s\n", file->fname);*/
if (SMBC_parse_path(frame,
context,
file->fname,
NULL,
&server,
&share,
&path,
&user,
&password,
NULL)) {
context,
file->fname,
NULL,
&server,
&share,
&path,
&user,
&password,
NULL)) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
/*d_printf(">>>write: resolving %s\n", path);*/
if (!cli_resolve_path(frame, "", file->srv->cli, path,
&targetcli, &targetpath)) {
@ -387,18 +391,19 @@ SMBC_write_ctx(SMBCCTX *context,
return -1;
}
/*d_printf(">>>write: resolved path as %s\n", targetpath);*/
ret = cli_write(targetcli, file->cli_fd, 0, (char *)buf, offset, count);
ret = cli_write(targetcli, file->cli_fd,
0, (char *)buf, offset, count);
if (ret <= 0) {
errno = SMBC_errno(context, targetcli);
TALLOC_FREE(frame);
return -1;
}
file->offset += ret;
TALLOC_FREE(frame);
return ret; /* Success, 0 bytes of data ... */
}
@ -417,42 +422,42 @@ SMBC_close_ctx(SMBCCTX *context,
char *targetpath = NULL;
struct cli_state *targetcli = NULL;
TALLOC_CTX *frame = talloc_stackframe();
if (!context || !context->internal->initialized) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
errno = EBADF;
TALLOC_FREE(frame);
return -1;
}
/* IS a dir ... */
if (!file->file) {
TALLOC_FREE(frame);
return (context->posix_emu.closedir_fn)(context, file);
}
/*d_printf(">>>close: parsing %s\n", file->fname);*/
if (SMBC_parse_path(frame,
context,
file->fname,
NULL,
&server,
&share,
&path,
&user,
&password,
NULL)) {
context,
file->fname,
NULL,
&server,
&share,
&path,
&user,
&password,
NULL)) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
/*d_printf(">>>close: resolving %s\n", path);*/
if (!cli_resolve_path(frame, "", file->srv->cli, path,
&targetcli, &targetpath)) {
@ -461,9 +466,9 @@ SMBC_close_ctx(SMBCCTX *context,
return -1;
}
/*d_printf(">>>close: resolved path as %s\n", targetpath);*/
if (!cli_close(targetcli, file->cli_fd)) {
DEBUG(3, ("cli_close failed on %s. purging server.\n",
file->fname));
/* Deallocate slot and remove the server
@ -476,14 +481,14 @@ SMBC_close_ctx(SMBCCTX *context,
(context->server.remove_unused_server_fn)(context, srv);
TALLOC_FREE(frame);
return -1;
}
DLIST_REMOVE(context->internal->files, file);
SAFE_FREE(file->fname);
SAFE_FREE(file);
TALLOC_FREE(frame);
return 0;
}
@ -508,14 +513,14 @@ SMBC_getatr(SMBCCTX * context,
struct cli_state *targetcli = NULL;
time_t write_time;
TALLOC_CTX *frame = talloc_stackframe();
if (!context || !context->internal->initialized) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
/* path fixup for . and .. */
if (strequal(path, ".") || strequal(path, "..")) {
fixedpath = talloc_strdup(frame, "\\");
@ -535,14 +540,14 @@ SMBC_getatr(SMBCCTX * context,
trim_string(fixedpath, NULL, "\\.");
}
DEBUG(4,("SMBC_getatr: sending qpathinfo\n"));
if (!cli_resolve_path(frame, "", srv->cli, fixedpath,
&targetcli, &targetpath)) {
&targetcli, &targetpath)) {
d_printf("Couldn't resolve %s\n", path);
TALLOC_FREE(frame);
return False;
}
if (!srv->no_pathinfo2 &&
cli_qpathinfo2(targetcli, targetpath,
create_time_ts,
@ -553,45 +558,45 @@ SMBC_getatr(SMBCCTX * context,
TALLOC_FREE(frame);
return True;
}
/* if this is NT then don't bother with the getatr */
if (targetcli->capabilities & CAP_NT_SMBS) {
errno = EPERM;
TALLOC_FREE(frame);
return False;
}
if (cli_getatr(targetcli, targetpath, mode, size, &write_time)) {
struct timespec w_time_ts;
w_time_ts = convert_time_t_to_timespec(write_time);
if (write_time_ts != NULL) {
*write_time_ts = w_time_ts;
}
if (create_time_ts != NULL) {
*create_time_ts = w_time_ts;
}
if (access_time_ts != NULL) {
*access_time_ts = w_time_ts;
}
if (change_time_ts != NULL) {
*change_time_ts = w_time_ts;
}
srv->no_pathinfo2 = True;
TALLOC_FREE(frame);
return True;
}
errno = EPERM;
TALLOC_FREE(frame);
return False;
}
/*
@ -615,7 +620,7 @@ SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
int fd;
int ret;
TALLOC_CTX *frame = talloc_stackframe();
/*
* First, try setpathinfo (if qpathinfo succeeded), for it is the
* modern function for "new code" to be using, and it works given a
@ -629,7 +634,7 @@ SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
write_time,
change_time,
mode)) {
/*
* setpathinfo is not supported; go to plan B.
*
@ -639,27 +644,27 @@ SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
* cli_setattrE() which should work on all OS versions, and
* supports both times.
*/
/* Don't try {q,set}pathinfo() again, with this server */
srv->no_pathinfo = True;
/* Open the file */
if ((fd = cli_open(srv->cli, path, O_RDWR, DENY_NONE)) < 0) {
errno = SMBC_errno(context, srv->cli);
TALLOC_FREE(frame);
return -1;
}
/* Set the new attributes */
ret = cli_setattrE(srv->cli, fd,
change_time,
access_time,
write_time);
/* Close the file */
cli_close(srv->cli, fd);
/*
* Unfortunately, setattrE() doesn't have a provision for
* setting the access mode (attributes). We'll have to try
@ -669,14 +674,14 @@ SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
if (ret && mode != (uint16) -1) {
ret = cli_setatr(srv->cli, path, mode, 0);
}
if (! ret) {
errno = SMBC_errno(context, srv->cli);
TALLOC_FREE(frame);
return False;
}
}
TALLOC_FREE(frame);
return True;
}
@ -697,56 +702,56 @@ SMBC_lseek_ctx(SMBCCTX *context,
char *targetpath = NULL;
struct cli_state *targetcli = NULL;
TALLOC_CTX *frame = talloc_stackframe();
if (!context || !context->internal->initialized) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
errno = EBADF;
TALLOC_FREE(frame);
return -1;
}
if (!file->file) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1; /* Can't lseek a dir ... */
}
switch (whence) {
case SEEK_SET:
file->offset = offset;
break;
case SEEK_CUR:
file->offset += offset;
break;
case SEEK_END:
/*d_printf(">>>lseek: parsing %s\n", file->fname);*/
if (SMBC_parse_path(frame,
context,
file->fname,
NULL,
&server,
&share,
&path,
&user,
&password,
NULL)) {
context,
file->fname,
NULL,
&server,
&share,
&path,
&user,
&password,
NULL)) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
/*d_printf(">>>lseek: resolving %s\n", path);*/
if (!cli_resolve_path(frame, "", file->srv->cli, path,
&targetcli, &targetpath)) {
@ -755,32 +760,32 @@ SMBC_lseek_ctx(SMBCCTX *context,
return -1;
}
/*d_printf(">>>lseek: resolved path as %s\n", targetpath);*/
if (!cli_qfileinfo(targetcli, file->cli_fd, NULL,
&size, NULL, NULL, NULL, NULL, NULL))
{
SMB_OFF_T b_size = size;
SMB_OFF_T b_size = size;
if (!cli_getattrE(targetcli, file->cli_fd,
NULL, &b_size, NULL, NULL, NULL))
{
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
} else
size = b_size;
{
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
} else
size = b_size;
}
file->offset = size + offset;
break;
default:
errno = EINVAL;
break;
}
TALLOC_FREE(frame);
return file->offset;
}
@ -802,26 +807,26 @@ SMBC_ftruncate_ctx(SMBCCTX *context,
char *targetpath = NULL;
struct cli_state *targetcli = NULL;
TALLOC_CTX *frame = talloc_stackframe();
if (!context || !context->internal->initialized) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
errno = EBADF;
TALLOC_FREE(frame);
return -1;
}
if (!file->file) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
/*d_printf(">>>fstat: parsing %s\n", file->fname);*/
if (SMBC_parse_path(frame,
context,
@ -837,7 +842,7 @@ SMBC_ftruncate_ctx(SMBCCTX *context,
TALLOC_FREE(frame);
return -1;
}
/*d_printf(">>>fstat: resolving %s\n", path);*/
if (!cli_resolve_path(frame, "", file->srv->cli, path,
&targetcli, &targetpath)) {
@ -846,14 +851,14 @@ SMBC_ftruncate_ctx(SMBCCTX *context,
return -1;
}
/*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
if (!cli_ftruncate(targetcli, file->cli_fd, size)) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
TALLOC_FREE(frame);
return 0;
}

View File

@ -50,24 +50,24 @@ SMBC_errno(SMBCCTX *context,
struct cli_state *c)
{
int ret = cli_errno(c);
if (cli_is_dos_error(c)) {
uint8 eclass;
uint32 ecode;
cli_dos_error(c, &eclass, &ecode);
DEBUG(3,("smbc_error %d %d (0x%x) -> %d\n",
(int)eclass, (int)ecode, (int)ecode, ret));
} else {
NTSTATUS status;
status = cli_nt_error(c);
DEBUG(3,("smbc errno %s -> %d\n",
nt_errstr(status), ret));
}
return ret;
}

View File

@ -31,13 +31,13 @@
static int
hex2int( unsigned int _char )
{
if ( _char >= 'A' && _char <='F')
return _char - 'A' + 10;
if ( _char >= 'a' && _char <='f')
return _char - 'a' + 10;
if ( _char >= '0' && _char <='9')
return _char - '0';
return -1;
if ( _char >= 'A' && _char <='F')
return _char - 'A' + 10;
if ( _char >= 'a' && _char <='f')
return _char - 'a' + 10;
if ( _char >= '0' && _char <='9')
return _char - '0';
return -1;
}
/*
@ -60,19 +60,19 @@ urldecode_talloc(TALLOC_CTX *ctx, char **pp_dest, const char *src)
int err_count = 0;
size_t newlen = 1;
char *p, *dest;
if (old_length == 0) {
return 0;
}
*pp_dest = NULL;
for (i = 0; i < old_length; ) {
unsigned char character = src[i++];
if (character == '%') {
int a = i+1 < old_length ? hex2int(src[i]) : -1;
int b = i+1 < old_length ? hex2int(src[i+1]) : -1;
/* Replace valid sequence */
if (a != -1 && b != -1) {
/* Replace valid %xx sequence with %dd */
@ -87,20 +87,20 @@ urldecode_talloc(TALLOC_CTX *ctx, char **pp_dest, const char *src)
}
newlen++;
}
dest = TALLOC_ARRAY(ctx, char, newlen);
if (!dest) {
return err_count;
}
err_count = 0;
for (p = dest, i = 0; i < old_length; ) {
unsigned char character = src[i++];
if (character == '%') {
int a = i+1 < old_length ? hex2int(src[i]) : -1;
int b = i+1 < old_length ? hex2int(src[i+1]) : -1;
/* Replace valid sequence */
if (a != -1 && b != -1) {
/* Replace valid %xx sequence with %dd */
@ -115,7 +115,7 @@ urldecode_talloc(TALLOC_CTX *ctx, char **pp_dest, const char *src)
}
*p++ = character;
}
*p = '\0';
*pp_dest = dest;
return err_count;
@ -129,7 +129,7 @@ SMBC_urldecode(char *dest,
TALLOC_CTX *frame = talloc_stackframe();
char *pdest;
int ret = urldecode_talloc(frame, &pdest, src);
if (pdest) {
strlcpy(dest, pdest, max_dest_len);
}
@ -151,9 +151,9 @@ SMBC_urlencode(char *dest,
int max_dest_len)
{
char hex[] = "0123456789ABCDEF";
for (; *src != '\0' && max_dest_len >= 3; src++) {
if ((*src < '0' &&
*src != '-' &&
*src != '.') ||
@ -172,10 +172,10 @@ SMBC_urlencode(char *dest,
max_dest_len--;
}
}
*dest++ = '\0';
max_dest_len--;
return max_dest_len;
}
@ -196,9 +196,9 @@ SMBC_urlencode(char *dest,
*
* The method of locating the list of workgroups varies
* depending upon the setting of the context variable
* context->browse_max_lmb_count. This value determines
* the maximum number of local master browsers to query
* for the list of workgroups. In order to ensure that
* context->options.browse_max_lmb_count. This value
* determines the maximum number of local master browsers to
* query for the list of workgroups. In order to ensure that
* a complete list of workgroups is obtained, all master
* browsers must be queried, but if there are many
* workgroups, the time spent querying can begin to add up.
@ -234,75 +234,75 @@ SMBC_parse_path(TALLOC_CTX *ctx,
const char *p;
char *q, *r;
int len;
/* Ensure these returns are at least valid pointers. */
*pp_server = talloc_strdup(ctx, "");
*pp_share = talloc_strdup(ctx, "");
*pp_path = talloc_strdup(ctx, "");
*pp_user = talloc_strdup(ctx, "");
*pp_password = talloc_strdup(ctx, "");
if (!*pp_server || !*pp_share || !*pp_path ||
!*pp_user || !*pp_password) {
!*pp_user || !*pp_password) {
return -1;
}
/*
* Assume we wont find an authentication domain to parse, so default
* to the workgroup in the provided context.
*/
if (pp_workgroup != NULL) {
*pp_workgroup =
talloc_strdup(ctx, context->config.workgroup);
talloc_strdup(ctx, context->config.workgroup);
}
if (pp_options) {
*pp_options = talloc_strdup(ctx, "");
}
s = talloc_strdup(ctx, fname);
/* see if it has the right prefix */
len = strlen(smbc_prefix);
if (strncmp(s,smbc_prefix,len) || (s[len] != '/' && s[len] != 0)) {
return -1; /* What about no smb: ? */
}
p = s + len;
/* Watch the test below, we are testing to see if we should exit */
if (strncmp(p, "//", 2) && strncmp(p, "\\\\", 2)) {
DEBUG(1, ("Invalid path (does not begin with smb://"));
return -1;
}
p += 2; /* Skip the double slash */
/* See if any options were specified */
if ((q = strrchr(p, '?')) != NULL ) {
/* There are options. Null terminate here and point to them */
*q++ = '\0';
DEBUG(4, ("Found options '%s'", q));
/* Copy the options */
if (*pp_options != NULL) {
TALLOC_FREE(*pp_options);
*pp_options = talloc_strdup(ctx, q);
}
}
if (*p == '\0') {
goto decoding;
}
if (*p == '/') {
int wl = strlen(context->config.workgroup);
if (wl > 16) {
wl = 16;
}
*pp_server = talloc_strdup(ctx, context->config.workgroup);
if (!*pp_server) {
return -1;
@ -310,27 +310,27 @@ SMBC_parse_path(TALLOC_CTX *ctx,
*pp_server[wl] = '\0';
return 0;
}
/*
* ok, its for us. Now parse out the server, share etc.
*
* However, we want to parse out [[domain;]user[:password]@] if it
* exists ...
*/
/* check that '@' occurs before '/', if '/' exists at all */
q = strchr_m(p, '@');
r = strchr_m(p, '/');
if (q && (!r || q < r)) {
char *userinfo = NULL;
const char *u;
next_token_no_ltrim_talloc(ctx, &p, &userinfo, "@");
if (!userinfo) {
return -1;
}
u = userinfo;
if (strchr_m(u, ';')) {
char *workgroup;
next_token_no_ltrim_talloc(ctx, &u, &workgroup, ";");
@ -341,7 +341,7 @@ SMBC_parse_path(TALLOC_CTX *ctx,
*pp_workgroup = workgroup;
}
}
if (strchr_m(u, ':')) {
next_token_no_ltrim_talloc(ctx, &u, pp_user, ":");
if (!*pp_user) {
@ -358,27 +358,27 @@ SMBC_parse_path(TALLOC_CTX *ctx,
}
}
}
if (!next_token_talloc(ctx, &p, pp_server, "/")) {
return -1;
}
if (*p == (char)0) {
goto decoding; /* That's it ... */
}
if (!next_token_talloc(ctx, &p, pp_share, "/")) {
return -1;
}
/*
* Prepend a leading slash if there's a file path, as required by
* NetApp filers.
*/
if (*p != '\0') {
*pp_path = talloc_asprintf(ctx,
"\\%s",
p);
"\\%s",
p);
} else {
*pp_path = talloc_strdup(ctx, "");
}
@ -386,15 +386,15 @@ SMBC_parse_path(TALLOC_CTX *ctx,
return -1;
}
string_replace(*pp_path, '/', '\\');
decoding:
decoding:
(void) urldecode_talloc(ctx, pp_path, *pp_path);
(void) urldecode_talloc(ctx, pp_server, *pp_server);
(void) urldecode_talloc(ctx, pp_share, *pp_share);
(void) urldecode_talloc(ctx, pp_user, *pp_user);
(void) urldecode_talloc(ctx, pp_password, *pp_password);
return 0;
}

View File

@ -41,39 +41,39 @@ SMBC_open_print_job_ctx(SMBCCTX *context,
char *password = NULL;
char *path = NULL;
TALLOC_CTX *frame = talloc_stackframe();
if (!context || !context->internal->initialized) {
errno = EINVAL;
TALLOC_FREE(frame);
return NULL;
}
if (!fname) {
errno = EINVAL;
TALLOC_FREE(frame);
return NULL;
}
DEBUG(4, ("SMBC_open_print_job_ctx(%s)\n", fname));
if (SMBC_parse_path(frame,
context,
fname,
NULL,
&server,
&share,
&path,
&user,
&password,
NULL)) {
context,
fname,
NULL,
&server,
&share,
&path,
&user,
&password,
NULL)) {
errno = EINVAL;
TALLOC_FREE(frame);
return NULL;
}
/* What if the path is empty, or the file exists? */
TALLOC_FREE(frame);
return (context->posix_emu.open_fn)(context, fname, O_WRONLY, 666);
}
@ -98,77 +98,79 @@ SMBC_print_file_ctx(SMBCCTX *c_file,
int tot_bytes = 0;
char buf[4096];
TALLOC_CTX *frame = talloc_stackframe();
if (!c_file || !c_file->internal->initialized ||
!c_print || !c_print->internal->initialized) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
if (!fname && !printq) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
/* Try to open the file for reading ... */
if ((long)(fid1 = smbc_getFunctionOpen(c_file)(c_file, fname, O_RDONLY, 0666)) < 0) {
if ((long)(fid1 = smbc_getFunctionOpen(c_file)(c_file, fname,
O_RDONLY, 0666)) < 0) {
DEBUG(3, ("Error, fname=%s, errno=%i\n", fname, errno));
TALLOC_FREE(frame);
return -1; /* smbc_open sets errno */
}
/* Now, try to open the printer file for writing */
if ((long)(fid2 = smbc_getFunctionOpenPrintJob(c_print)(c_print, printq)) < 0) {
if ((long)(fid2 = smbc_getFunctionOpenPrintJob(c_print)(c_print,
printq)) < 0) {
saverr = errno; /* Save errno */
smbc_getFunctionClose(c_file)(c_file, fid1);
errno = saverr;
TALLOC_FREE(frame);
return -1;
}
while ((bytes = smbc_getFunctionRead(c_file)(c_file, fid1,
buf, sizeof(buf))) > 0) {
tot_bytes += bytes;
if ((smbc_getFunctionWrite(c_print)(c_print, fid2,
buf, bytes)) < 0) {
saverr = errno;
smbc_getFunctionClose(c_file)(c_file, fid1);
smbc_getFunctionClose(c_print)(c_print, fid2);
errno = saverr;
}
}
saverr = errno;
smbc_getFunctionClose(c_file)(c_file, fid1); /* We have to close these anyway */
smbc_getFunctionClose(c_file)(c_file, fid1);
smbc_getFunctionClose(c_print)(c_print, fid2);
if (bytes < 0) {
errno = saverr;
TALLOC_FREE(frame);
return -1;
}
TALLOC_FREE(frame);
return tot_bytes;
}
/*
@ -188,37 +190,37 @@ SMBC_list_print_jobs_ctx(SMBCCTX *context,
char *workgroup = NULL;
char *path = NULL;
TALLOC_CTX *frame = talloc_stackframe();
if (!context || !context->internal->initialized) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
if (!fname) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
DEBUG(4, ("smbc_list_print_jobs(%s)\n", fname));
if (SMBC_parse_path(frame,
context,
fname,
&workgroup,
&server,
&share,
&path,
&user,
&password,
NULL)) {
context,
fname,
&workgroup,
&server,
&share,
&path,
&user,
&password,
NULL)) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
if (!user || user[0] == (char)0) {
user = talloc_strdup(frame, context->config.user);
if (!user) {
@ -227,25 +229,25 @@ SMBC_list_print_jobs_ctx(SMBCCTX *context,
return -1;
}
}
srv = SMBC_server(frame, context, True,
server, share, &workgroup, &user, &password);
if (!srv) {
TALLOC_FREE(frame);
return -1; /* errno set by SMBC_server */
}
if (cli_print_queue(srv->cli,
(void (*)(struct print_job_info *))fn) < 0) {
errno = SMBC_errno(context, srv->cli);
TALLOC_FREE(frame);
return -1;
}
TALLOC_FREE(frame);
return 0;
}
/*
@ -266,37 +268,37 @@ SMBC_unlink_print_job_ctx(SMBCCTX *context,
char *path = NULL;
int err;
TALLOC_CTX *frame = talloc_stackframe();
if (!context || !context->internal->initialized) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
if (!fname) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
DEBUG(4, ("smbc_unlink_print_job(%s)\n", fname));
if (SMBC_parse_path(frame,
context,
fname,
&workgroup,
&server,
&share,
&path,
&user,
&password,
NULL)) {
context,
fname,
&workgroup,
&server,
&share,
&path,
&user,
&password,
NULL)) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
if (!user || user[0] == (char)0) {
user = talloc_strdup(frame, context->config.user);
if (!user) {
@ -305,30 +307,30 @@ SMBC_unlink_print_job_ctx(SMBCCTX *context,
return -1;
}
}
srv = SMBC_server(frame, context, True,
server, share, &workgroup, &user, &password);
if (!srv) {
TALLOC_FREE(frame);
return -1; /* errno set by SMBC_server */
}
if ((err = cli_printjob_del(srv->cli, id)) != 0) {
if (err < 0)
errno = SMBC_errno(context, srv->cli);
else if (err == ERRnosuchprintjob)
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
TALLOC_FREE(frame);
return 0;
}

View File

@ -40,7 +40,7 @@ SMBC_check_server(SMBCCTX * context,
{
socklen_t size;
struct sockaddr addr;
size = sizeof(addr);
return (getpeername(server->cli->fd, &addr, &size) == -1);
}
@ -56,12 +56,12 @@ SMBC_remove_unused_server(SMBCCTX * context,
SMBCSRV * srv)
{
SMBCFILE * file;
/* are we being fooled ? */
if (!context || !context->internal->initialized || !srv) {
return 1;
}
/* Check all open files/directories for a relation with this server */
for (file = context->internal->files; file; file = file->next) {
if (file->srv == srv) {
@ -72,16 +72,16 @@ SMBC_remove_unused_server(SMBCCTX * context,
return 1;
}
}
DLIST_REMOVE(context->internal->servers, srv);
cli_shutdown(srv->cli);
srv->cli = NULL;
DEBUG(3, ("smbc_remove_usused_server: %p removed.\n", srv));
(context->cache.remove_cached_server_fn)(context, srv);
SAFE_FREE(srv);
return 0;
}
@ -101,21 +101,21 @@ SMBC_call_auth_fn(TALLOC_CTX *ctx,
fstring workgroup;
fstring username;
fstring password;
strlcpy(workgroup, *pp_workgroup, sizeof(workgroup));
strlcpy(username, *pp_username, sizeof(username));
strlcpy(password, *pp_password, sizeof(password));
(context->server.get_auth_data_fn)(
server, share,
workgroup, sizeof(workgroup),
username, sizeof(username),
password, sizeof(password));
TALLOC_FREE(*pp_workgroup);
TALLOC_FREE(*pp_username);
TALLOC_FREE(*pp_password);
*pp_workgroup = talloc_strdup(ctx, workgroup);
*pp_username = talloc_strdup(ctx, username);
*pp_password = talloc_strdup(ctx, password);
@ -144,23 +144,23 @@ SMBC_find_server(TALLOC_CTX *ctx,
{
SMBCSRV *srv;
int auth_called = 0;
check_server_cache:
check_server_cache:
srv = (context->cache.get_cached_server_fn)(context,
server, share,
*pp_workgroup,
*pp_username);
if (!auth_called && !srv && (!*pp_username || !(*pp_username)[0] ||
!*pp_password || !(*pp_password)[0])) {
!*pp_password || !(*pp_password)[0])) {
SMBC_call_auth_fn(ctx, context, server, share,
pp_workgroup, pp_username, pp_password);
pp_workgroup, pp_username, pp_password);
if (!pp_workgroup || !pp_username || !pp_password) {
return NULL;
}
/*
* However, smbc_auth_fn may have picked up info relating to
* an existing connection, so try for an existing connection
@ -168,9 +168,9 @@ SMBC_find_server(TALLOC_CTX *ctx,
*/
auth_called = 1;
goto check_server_cache;
}
if (srv) {
if ((context->server.check_server_fn)(context, srv)) {
/*
@ -189,17 +189,17 @@ SMBC_find_server(TALLOC_CTX *ctx,
(context->cache.remove_cached_server_fn)(context,
srv);
}
/*
* Maybe there are more cached connections to this
* server
*/
goto check_server_cache;
}
return srv;
}
return NULL;
}
@ -234,25 +234,25 @@ SMBC_server(TALLOC_CTX *ctx,
int port_try_next;
const char *username_used;
NTSTATUS status;
zero_addr(&ss);
ZERO_STRUCT(c);
if (server[0] == 0) {
errno = EPERM;
return NULL;
}
/* Look for a cached connection */
srv = SMBC_find_server(ctx, context, server, share,
pp_workgroup, pp_username, pp_password);
pp_workgroup, pp_username, pp_password);
/*
* If we found a connection and we're only allowed one share per
* server...
*/
if (srv && *share != '\0' && context->internal->one_share_per_server) {
if (srv && *share != '\0' && context->options.one_share_per_server) {
/*
* ... then if there's no current connection to the share,
* connect to it. SMBC_find_server(), or rather the function
@ -264,8 +264,10 @@ SMBC_server(TALLOC_CTX *ctx,
if (srv->cli->cnum == (uint16) -1) {
/* Ensure we have accurate auth info */
SMBC_call_auth_fn(ctx, context, server, share,
pp_workgroup, pp_username, pp_password);
pp_workgroup,
pp_username,
pp_password);
if (!*pp_workgroup || !*pp_username || !*pp_password) {
errno = ENOMEM;
cli_shutdown(srv->cli);
@ -274,17 +276,17 @@ SMBC_server(TALLOC_CTX *ctx,
srv);
return NULL;
}
/*
* We don't need to renegotiate encryption
* here as the encryption context is not per
* tid.
*/
if (!cli_send_tconX(srv->cli, share, "?????",
*pp_password,
strlen(*pp_password)+1)) {
*pp_password,
strlen(*pp_password)+1)) {
errno = SMBC_errno(context, srv->cli);
cli_shutdown(srv->cli);
srv->cli = NULL;
@ -292,7 +294,7 @@ SMBC_server(TALLOC_CTX *ctx,
srv);
srv = NULL;
}
/*
* Regenerate the dev value since it's based on both
* server and share
@ -303,51 +305,51 @@ SMBC_server(TALLOC_CTX *ctx,
}
}
}
/* If we have a connection... */
if (srv) {
/* ... then we're done here. Give 'em what they came for. */
return srv;
}
/* If we're not asked to connect when a connection doesn't exist... */
if (! connect_if_not_found) {
/* ... then we're done here. */
return NULL;
}
if (!*pp_workgroup || !*pp_username || !*pp_password) {
errno = ENOMEM;
return NULL;
}
make_nmb_name(&calling, context->config.netbios_name, 0x0);
make_nmb_name(&called , server, 0x20);
DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server));
DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));
again:
again:
zero_addr(&ss);
/* have to open a new connection */
if ((c = cli_initialise()) == NULL) {
errno = ENOMEM;
return NULL;
}
if (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS) {
c->use_kerberos = True;
}
if (context->flags.bits & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS) {
c->fallback_after_kerberos = True;
}
c->timeout = context->config.timeout;
/*
* Force use of port 139 for first try if share is $IPC, empty, or
* null, so browse lists can work
@ -359,15 +361,15 @@ SMBC_server(TALLOC_CTX *ctx,
port_try_first = 445;
port_try_next = 139;
}
c->port = port_try_first;
status = cli_connect(c, server_n, &ss);
if (!NT_STATUS_IS_OK(status)) {
/* First connection attempt failed. Try alternate port. */
c->port = port_try_next;
status = cli_connect(c, server_n, &ss);
if (!NT_STATUS_IS_OK(status)) {
cli_shutdown(c);
@ -375,33 +377,36 @@ SMBC_server(TALLOC_CTX *ctx,
return NULL;
}
}
if (!cli_session_request(c, &calling, &called)) {
cli_shutdown(c);
if (strcmp(called.name, "*SMBSERVER")) {
make_nmb_name(&called , "*SMBSERVER", 0x20);
goto again;
} else { /* Try one more time, but ensure we don't loop */
/* Only try this if server is an IP address ... */
if (is_ipaddress(server) && !tried_reverse) {
fstring remote_name;
struct sockaddr_storage rem_ss;
if (!interpret_string_addr(&rem_ss, server,
NI_NUMERICHOST)) {
NI_NUMERICHOST)) {
DEBUG(4, ("Could not convert IP address "
"%s to struct sockaddr_storage\n",
server));
"%s to struct sockaddr_storage\n",
server));
errno = ETIMEDOUT;
return NULL;
}
tried_reverse++; /* Yuck */
if (name_status_find("*", 0, 0, &rem_ss, remote_name)) {
make_nmb_name(&called, remote_name, 0x20);
if (name_status_find("*", 0, 0,
&rem_ss, remote_name)) {
make_nmb_name(&called,
remote_name,
0x20);
goto again;
}
}
@ -409,64 +414,66 @@ SMBC_server(TALLOC_CTX *ctx,
errno = ETIMEDOUT;
return NULL;
}
DEBUG(4,(" session request ok\n"));
if (!cli_negprot(c)) {
cli_shutdown(c);
errno = ETIMEDOUT;
return NULL;
}
username_used = *pp_username;
if (!NT_STATUS_IS_OK(cli_session_setup(c, username_used,
*pp_password, strlen(*pp_password),
*pp_password, strlen(*pp_password),
*pp_password,
strlen(*pp_password),
*pp_password,
strlen(*pp_password),
*pp_workgroup))) {
/* Failed. Try an anonymous login, if allowed by flags. */
username_used = "";
if ((context->flags.bits &
SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON) ||
!NT_STATUS_IS_OK(cli_session_setup(c, username_used,
*pp_password, 1,
*pp_password, 0,
*pp_workgroup))) {
cli_shutdown(c);
errno = EPERM;
return NULL;
}
}
DEBUG(4,(" session setup ok\n"));
if (!cli_send_tconX(c, share, "?????",
*pp_password, strlen(*pp_password)+1)) {
errno = SMBC_errno(context, c);
cli_shutdown(c);
return NULL;
}
DEBUG(4,(" tconx ok\n"));
if (context->internal->smb_encryption_level) {
/* Attempt UNIX smb encryption. */
if (!NT_STATUS_IS_OK(cli_force_encryption(c,
username_used,
*pp_password,
*pp_workgroup))) {
username_used,
*pp_password,
*pp_workgroup))) {
/*
* context->smb_encryption_level == 1
* means don't fail if encryption can't be negotiated,
* == 2 means fail if encryption can't be negotiated.
*/
DEBUG(4,(" SMB encrypt failed\n"));
if (context->internal->smb_encryption_level == 2) {
cli_shutdown(c);
errno = EPERM;
@ -475,25 +482,25 @@ SMBC_server(TALLOC_CTX *ctx,
}
DEBUG(4,(" SMB encrypt ok\n"));
}
/*
* Ok, we have got a nice connection
* Let's allocate a server structure.
*/
srv = SMB_MALLOC_P(SMBCSRV);
if (!srv) {
errno = ENOMEM;
goto failed;
}
ZERO_STRUCTP(srv);
srv->cli = c;
srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
srv->no_pathinfo = False;
srv->no_pathinfo2 = False;
srv->no_nt_session = False;
/* now add it to the cache (internal or external) */
/* Let the cache function set errno if it wants to */
errno = 0;
@ -509,19 +516,19 @@ SMBC_server(TALLOC_CTX *ctx,
}
goto failed;
}
DEBUG(2, ("Server connect ok: //%s/%s: %p\n",
server, share, srv));
DLIST_ADD(context->internal->servers, srv);
return srv;
failed:
failed:
cli_shutdown(c);
if (!srv) {
return NULL;
}
SAFE_FREE(srv);
return NULL;
}
@ -545,32 +552,34 @@ SMBC_attr_server(TALLOC_CTX *ctx,
struct rpc_pipe_client *pipe_hnd;
NTSTATUS nt_status;
SMBCSRV *ipc_srv=NULL;
/*
* See if we've already created this special connection. Reference
* our "special" share name '*IPC$', which is an impossible real share
* name due to the leading asterisk.
*/
ipc_srv = SMBC_find_server(ctx, context, server, "*IPC$",
pp_workgroup, pp_username, pp_password);
pp_workgroup, pp_username, pp_password);
if (!ipc_srv) {
/* We didn't find a cached connection. Get the password */
if (!*pp_password || (*pp_password)[0] == '\0') {
/* ... then retrieve it now. */
SMBC_call_auth_fn(ctx, context, server, share,
pp_workgroup, pp_username, pp_password);
pp_workgroup,
pp_username,
pp_password);
if (!*pp_workgroup || !*pp_username || !*pp_password) {
errno = ENOMEM;
return NULL;
}
}
flags = 0;
if (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS) {
flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
}
zero_addr(&ss);
nt_status = cli_full_connection(&ipc_cli,
global_myname(), server,
@ -586,23 +595,23 @@ SMBC_attr_server(TALLOC_CTX *ctx,
errno = ENOTSUP;
return NULL;
}
if (context->internal->smb_encryption_level) {
/* Attempt UNIX smb encryption. */
if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli,
*pp_username,
*pp_password,
*pp_workgroup))) {
*pp_username,
*pp_password,
*pp_workgroup))) {
/*
* context->smb_encryption_level ==
* 1 means don't fail if encryption can't be
* negotiated, == 2 means fail if encryption
* can't be negotiated.
*/
DEBUG(4,(" SMB encrypt failed on IPC$\n"));
if (context->internal->smb_encryption_level == 2) {
cli_shutdown(ipc_cli);
errno = EPERM;
@ -611,49 +620,49 @@ SMBC_attr_server(TALLOC_CTX *ctx,
}
DEBUG(4,(" SMB encrypt ok on IPC$\n"));
}
ipc_srv = SMB_MALLOC_P(SMBCSRV);
if (!ipc_srv) {
errno = ENOMEM;
cli_shutdown(ipc_cli);
return NULL;
}
ZERO_STRUCTP(ipc_srv);
ipc_srv->cli = ipc_cli;
pipe_hnd = cli_rpc_pipe_open_noauth(ipc_srv->cli,
PI_LSARPC,
&nt_status);
if (!pipe_hnd) {
DEBUG(1, ("cli_nt_session_open fail!\n"));
errno = ENOTSUP;
cli_shutdown(ipc_srv->cli);
free(ipc_srv);
return NULL;
DEBUG(1, ("cli_nt_session_open fail!\n"));
errno = ENOTSUP;
cli_shutdown(ipc_srv->cli);
free(ipc_srv);
return NULL;
}
/*
* Some systems don't support
* SEC_RIGHTS_MAXIMUM_ALLOWED, but NT sends 0x2000000
* so we might as well do it too.
*/
nt_status = rpccli_lsa_open_policy(
pipe_hnd,
talloc_tos(),
True,
GENERIC_EXECUTE_ACCESS,
&ipc_srv->pol);
pipe_hnd,
talloc_tos(),
True,
GENERIC_EXECUTE_ACCESS,
&ipc_srv->pol);
if (!NT_STATUS_IS_OK(nt_status)) {
errno = SMBC_errno(context, ipc_srv->cli);
cli_shutdown(ipc_srv->cli);
return NULL;
errno = SMBC_errno(context, ipc_srv->cli);
cli_shutdown(ipc_srv->cli);
return NULL;
}
/* now add it to the cache (internal or external) */
errno = 0; /* let cache function set errno if it likes */
if ((context->cache.add_cached_server_fn)(context, ipc_srv,
server,
@ -668,9 +677,9 @@ SMBC_attr_server(TALLOC_CTX *ctx,
free(ipc_srv);
return NULL;
}
DLIST_ADD(context->internal->servers, ipc_srv);
}
return ipc_srv;
}

View File

@ -33,18 +33,18 @@
static ino_t
generate_inode(SMBCCTX *context,
const char *name)
const char *name)
{
if (!context || !context->internal->initialized) {
errno = EINVAL;
return -1;
}
if (!*name) return 2; /* FIXME, why 2 ??? */
return (ino_t)str_checksum(name);
}
/*
@ -54,26 +54,26 @@ generate_inode(SMBCCTX *context,
static int
setup_stat(SMBCCTX *context,
struct stat *st,
char *fname,
SMB_OFF_T size,
int mode)
struct stat *st,
char *fname,
SMB_OFF_T size,
int mode)
{
TALLOC_CTX *frame = talloc_stackframe();
st->st_mode = 0;
if (IS_DOS_DIR(mode)) {
st->st_mode = SMBC_DIR_MODE;
} else {
st->st_mode = SMBC_FILE_MODE;
}
if (IS_DOS_ARCHIVE(mode)) st->st_mode |= S_IXUSR;
if (IS_DOS_SYSTEM(mode)) st->st_mode |= S_IXGRP;
if (IS_DOS_HIDDEN(mode)) st->st_mode |= S_IXOTH;
if (!IS_DOS_READONLY(mode)) st->st_mode |= S_IWUSR;
st->st_size = size;
#ifdef HAVE_STAT_ST_BLKSIZE
st->st_blksize = 512;
@ -86,20 +86,20 @@ setup_stat(SMBCCTX *context,
#endif
st->st_uid = getuid();
st->st_gid = getgid();
if (IS_DOS_DIR(mode)) {
st->st_nlink = 2;
} else {
st->st_nlink = 1;
}
if (st->st_ino == 0) {
st->st_ino = generate_inode(context, fname);
}
TALLOC_FREE(frame);
return True; /* FIXME: Is this needed ? */
}
/*
@ -125,37 +125,37 @@ SMBC_stat_ctx(SMBCCTX *context,
uint16 mode = 0;
SMB_INO_T ino = 0;
TALLOC_CTX *frame = talloc_stackframe();
if (!context || !context->internal->initialized) {
errno = EINVAL; /* Best I can think of ... */
TALLOC_FREE(frame);
return -1;
}
if (!fname) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
DEBUG(4, ("smbc_stat(%s)\n", fname));
if (SMBC_parse_path(frame,
context,
fname,
&workgroup,
&server,
&share,
&path,
&user,
&password,
NULL)) {
context,
fname,
&workgroup,
&server,
&share,
&path,
&user,
&password,
NULL)) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
if (!user || user[0] == (char)0) {
user = talloc_strdup(frame,context->config.user);
if (!user) {
@ -164,15 +164,15 @@ SMBC_stat_ctx(SMBCCTX *context,
return -1;
}
}
srv = SMBC_server(frame, context, True,
server, share, &workgroup, &user, &password);
if (!srv) {
TALLOC_FREE(frame);
return -1; /* errno set by SMBC_server */
}
if (!SMBC_getatr(context, srv, path, &mode, &size,
NULL,
&access_time_ts,
@ -183,19 +183,19 @@ SMBC_stat_ctx(SMBCCTX *context,
TALLOC_FREE(frame);
return -1;
}
st->st_ino = ino;
setup_stat(context, st, (char *) fname, size, mode);
set_atimespec(st, access_time_ts);
set_ctimespec(st, change_time_ts);
set_mtimespec(st, write_time_ts);
st->st_dev = srv->dev;
TALLOC_FREE(frame);
return 0;
}
/*
@ -221,41 +221,41 @@ SMBC_fstat_ctx(SMBCCTX *context,
struct cli_state *targetcli = NULL;
SMB_INO_T ino = 0;
TALLOC_CTX *frame = talloc_stackframe();
if (!context || !context->internal->initialized) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
errno = EBADF;
TALLOC_FREE(frame);
return -1;
}
if (!file->file) {
TALLOC_FREE(frame);
return (context->posix_emu.fstatdir_fn)(context, file, st);
}
/*d_printf(">>>fstat: parsing %s\n", file->fname);*/
if (SMBC_parse_path(frame,
context,
file->fname,
NULL,
&server,
&share,
&path,
&user,
&password,
NULL)) {
context,
file->fname,
NULL,
&server,
&share,
&path,
&user,
&password,
NULL)) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
/*d_printf(">>>fstat: resolving %s\n", path);*/
if (!cli_resolve_path(frame, "", file->srv->cli, path,
&targetcli, &targetpath)) {
@ -264,39 +264,39 @@ SMBC_fstat_ctx(SMBCCTX *context,
return -1;
}
/*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
if (!cli_qfileinfo(targetcli, file->cli_fd, &mode, &size,
NULL,
&access_time_ts,
&write_time_ts,
&change_time_ts,
&ino)) {
time_t change_time, access_time, write_time;
if (!cli_getattrE(targetcli, file->cli_fd, &mode, &size,
&change_time, &access_time, &write_time)) {
&change_time, &access_time, &write_time)) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
change_time_ts = convert_time_t_to_timespec(change_time);
access_time_ts = convert_time_t_to_timespec(access_time);
write_time_ts = convert_time_t_to_timespec(write_time);
}
st->st_ino = ino;
setup_stat(context, st, file->fname, size, mode);
set_atimespec(st, access_time_ts);
set_ctimespec(st, change_time_ts);
set_mtimespec(st, write_time_ts);
st->st_dev = file->srv->dev;
TALLOC_FREE(frame);
return 0;
}

File diff suppressed because it is too large Load Diff