From 84f12a59600bc3f686959d0e17cf972319059e02 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Thu, 10 Jan 2008 08:25:54 -0600 Subject: Set the "stable" vendor string in VERSION. (This used to be commit 22d2ff0bc4d1012cc3ffc7ab0fdbab5a8188a0cb) --- source3/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/VERSION b/source3/VERSION index c97db4b04e..f0883b95bb 100644 --- a/source3/VERSION +++ b/source3/VERSION @@ -95,5 +95,5 @@ SAMBA_VERSION_IS_GIT_SNAPSHOT=yes # e.g. SAMBA_VERSION_VENDOR_SUFFIX=vendor_version() # # -> "CVS 3.0.0rc2-VendorVersion" # ######################################################## -SAMBA_VERSION_VENDOR_SUFFIX="test" +SAMBA_VERSION_VENDOR_SUFFIX="stable" SAMBA_VERSION_VENDOR_PATCH= -- cgit From f0edf72d87ca300058c3ae7f464f26b9a2cce651 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Tue, 15 Jan 2008 07:59:18 -0600 Subject: Add First draf of release notes. (This used to be commit 5adf38606b4c6918412a3da76e6fb3298ac585af) --- WHATSNEW.txt | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 115 insertions(+), 21 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index de8df4b006..53a1c84ab4 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,6 +1,6 @@ ================================= Release Notes for Samba 3.2.0pre2 - Oct XX, 2007 + Jan 16, 2008 ================================= This is the second preview release of Samba 3.2.0. This is *not* @@ -22,6 +22,7 @@ Major enhancements in Samba 3.2.0 include: o Introduction of a registry based configuration system. o Improved CIFS Unix Extensions support. o Experimental support for file serving clusters. + o Support for IPv6 connections. Winbind and Active Directory Integration: @@ -32,6 +33,7 @@ Major enhancements in Samba 3.2.0 include: o Support in pam_winbind for logging on using the userPrincipalName. o Expansion of nested domain groups via NSS calls. o Support for Active Directory LDAP Signing policy. + o New LGPL Winbind client library (libwbclient.so) Users & Groups: @@ -40,7 +42,7 @@ Major enhancements in Samba 3.2.0 include: Documentation: - o Inclusion of an HTLM version of the 3rd edition of "Using Samba" + o Inclusion of an HTML version of the 3rd edition of "Using Samba" from O'Reilly Publishing. @@ -50,12 +52,12 @@ Now Licensed under the GNU GPLv3 The Samba Team has adopted the Version 3 of the GNU General Public License for the 3.2 and later releases. The GPLv3 is the updated version of the GPLv2 license under which Samba is currently -distributed. It has been updated to improvecompatibility with other -licenses and to make it easier to adopt internationally, and is an +distributed. It has been updated to improve compatibility with other +licenses and to make it easier to adopt internationally, and is an improved version of the license to better suit the needs of Free Software in the 21st Century. -The original announcement is available on-line at +The original announcement is available on-line at http://news.samba.org/announcements/samba_gplv3/ @@ -63,12 +65,12 @@ The original announcement is available on-line at New Security Defaults for Authentication ======================================== -Support for LanMan passwords is now disabled in both client and server -applications. Additionally, clear text authentication requests are +Support for LanMan passwords is now disabled in both client and server +applications. Additionally, clear text authentication requests are disabled by default in client utilities such as smbclient and all -libsmbclient based applications. This will affect connection both -to and from hosts running DOS, Windows 9x/ME, and OS/2. Please refer -to the "Changes" section for details on the exact parameters that were +libsmbclient based applications. This will affect connection both +to and from hosts running DOS, Windows 9x/ME, and OS/2. Please refer +to the "Changes" section for details on the exact parameters that were updated. @@ -78,10 +80,10 @@ Registry Configuration Backend Samba is now able to use a registry based configuration backed to supplement smb.conf setting. This feature may be enabled by setting -"include = registry" and "registry shares = yes" in the [global] -section of smb.conf and may be managed using the "net conf" command. +"include = registry" and "registry shares = yes" in the [global] +section of smb.conf and may be managed using the "net conf" command. -More information may be obtained from the smb.conf(5) and net(8) man +More information may be obtained from the smb.conf(5) and net(8) man pages. @@ -110,7 +112,8 @@ smb.conf changes ctdb socket New "" lanman auth Changed Default No mangle map Removed - open files database hashsize Removed + min receive file size New 0 + open files database hash size Removed read bmpx Removed registry shares New No winbind expand groups New 1 @@ -120,6 +123,97 @@ smb.conf changes Changes since 3.2.0pre1: ----------------------- +o Michael Adam + * Add vfs_zfsacl plugin. + * Refactor and consolidate logic for retrieving the machine + trust password information. + * BUG 4801: Correctly implement LSA lookup levels for LookupNames. + + +o Jeremy Allison + * Added support for IPv6 client and server connections. + * Add in the recvfile entry to the VFS layer. + * Removal of pstring data type. + * Remove unused utilities: smbctool and rpctorture. + * Fix service principal detection to match Windows Vista + (based on work from Andreas Schneider). + * Additional work on the session data privacy for clients + implementing the Unix CIFS Extensions. + + +o Gerald (Jerry) Carter + * Add Winbind client library. + * Decouple static linking between smbd and winbindd's client + interface. + + +o Guenther Deschner + * Enhance client and server remote registry access. + * Add client calls for remotely joining a computer to a domain + (including calls from "net dom" command). + * Add libnetapi.so library for joining domains including + sample GTK+ app. + + +o Steve Langasek + * Integrate 2 out of 3 --with-fhs patches from Debian packaging + for better adherence to the FHS standard. + + +o Volker Lendecke + * Add talloc_stackframe() and talloc_pool() features. + * Removal of pstring data type. + * Add generic a in-memory cache. + * Import the Linux red-black tree implementation. + * Remove large amount of global variables. + * Add vfs_ea_tdb module for file systems that do not implement xattrs. + + +o Stefan Metzmacher + * Refactor Winbind internal parent-child interface tables + to achieve better unit testing support. + * Add nss_wrapper API for local Winbind unit tests. + * Networking fixes to the libreplace library. + * Pidl fixes. + * Remove unused Winbind pipe calls. + + +o James Peach + * Add support for DNS Service Discovery. Based on work from + Rishi Srivatsavai . + + +o Andreas Schneider + * Don't restart winbind if a corrupted tdb is found during + initialization. + + +o Karolin Seeger + * Add net rap file user. + + +o David Shaw + * BUG 5073: Allow "delete readonly = yes" to correctly override + deletion of a file. + + +o Rishi Srivatsavai + * Register the smb service with mDNS if mDNS is supported. + * Add smbclient support for basic mDNS browsing. + + +o Andrew Tridgell + * Fix padding between Winbind 32bit/64bit client library in + the request/response structures. + * Added a syncops VFS module for file systems which do not + guarantee meta-data operations are immediately committed to + disk in stable form. + + +o Jelmer Vernooij + * Additional portability support for building shared libraries. + + Original 3.2.0pre1 commits: --------------------------- @@ -134,16 +228,16 @@ o Michael Adam * Merged \winreg server code from the SAMBA_3_2 development branch. * Fixes for libreplace. * Implement new registry configuration backend. - + o Jeremy Allison * Add support for file system objectIDs. * Winbind cache validation support. * Add in the UNIX capability for 24-bit readX. * Improve Delete-on-Close semantics. - * Removal of static file and path name buffers in SMB file serving + * Removal of static file and path name buffers in SMB file serving code. - + o Danilo Almeida * Move the machine account to the OU specified when running "net @@ -151,7 +245,7 @@ o Danilo Almeida o Andrew Bartlett - * Tighten authentication protocol defaults in client tools and + * Tighten authentication protocol defaults in client tools and servers. @@ -165,7 +259,7 @@ o Gerald (Jerry) Carter * Fix lockups in Winbind when running nscd. * UPN logon support in pam_winbind. * Add support for GNU linker scripts when build shared libraries - (based on work by Julien Cristau and James + (based on work by Julien Cristau and James Peach). @@ -182,7 +276,7 @@ o Guenther Deschner o Steve Langasek * Allow SIGTERM to cause nmbd to exit while awaiting a interface - to come up. + to come up. o Volker Lendecke @@ -192,7 +286,7 @@ o Volker Lendecke * Add client support for the SamLogonEx() authentication request. * Implement RPC proxy stubs in the Samba server code to allow replacing implementation functions one by one. - * Remove static incoming and outgoing buffers from core server SMB + * Remove static incoming and outgoing buffers from core server SMB packet processing code. * Add "net sam rights" command. -- cgit From 64e5f2fd8033b14d84d468fde32ac220d82aedb8 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Tue, 15 Jan 2008 10:45:53 -0600 Subject: Add notes from Michael Adam for the commit log in release notes (This used to be commit 04e0460c7e4adfe29a8c788e1912129c4c0c7e62) --- WHATSNEW.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 53a1c84ab4..86f8ad94e2 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -109,6 +109,7 @@ smb.conf changes client plaintext auth Changed Default No clustering New No cluster addresses New "" + debug class New No ctdb socket New "" lanman auth Changed Default No mangle map Removed @@ -124,10 +125,18 @@ Changes since 3.2.0pre1: ----------------------- o Michael Adam - * Add vfs_zfsacl plugin. + * Add library for access to the registry configuration data. + * BUG 5023: Separate NFS4 and POSIX ACL code in file access checks. + * BUG 4308: Fix Excel save operation ACL bug. * Refactor and consolidate logic for retrieving the machine trust password information. + * VFS API cleanup. * BUG 4801: Correctly implement LSA lookup levels for LookupNames. + * Add new option "debug class" to control printing of the debug class. + in debug headers. + * Enable building of the zfsacl and notify_fam vfs modules. + * BUG 5083: Fix memleak in solarisacl module. + * BUG 5063: Fix build on RHEL5. o Jeremy Allison -- cgit From 019c245ae15c7fdc414d41f64dad994337f26cf4 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Tue, 15 Jan 2008 10:48:49 -0600 Subject: Update release notes for vfs_ea_rename to complete the recent merge. (This used to be commit ef2e825e1fe5493115d2b271c2f4198e9e5b1f47) --- WHATSNEW.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 86f8ad94e2..253fe260de 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -175,7 +175,7 @@ o Volker Lendecke * Add generic a in-memory cache. * Import the Linux red-black tree implementation. * Remove large amount of global variables. - * Add vfs_ea_tdb module for file systems that do not implement xattrs. + * Add vfs_xattr_tdb module for file systems that do not implement xattrs. o Stefan Metzmacher -- cgit From f95712432bcebe1e09c087b577556f955b751487 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 29 Feb 2008 11:43:06 +0100 Subject: Fill in WHATSNEW.txt. Guenther (cherry picked from commit 55e85ccd3ec59afc05b955f1458d9fc655cee752) (This used to be commit f85ddd10d644a7212922e1c7e8e2e2793e9703c8) --- WHATSNEW.txt | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 2ac227d141..00b47d8c09 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -25,17 +25,23 @@ Major enhancements in Samba 3.2.0 include: o Support for IPv6 in the server, and client tools and libraries. o Support for storing alternate data streams in xattrs. o Encrypted SMB transport in client tools and libraries, and server. + o Support for Vista clients authenticating via Kerberos. Winbind and Active Directory Integration: o Full support for Windows 2003 cross-forest, transitive trusts and one-way domain trusts. o Support for userPrincipalName logons via pam_winbind and NSS lookups. - o Support in pam_winbind for logging on using the userPrincipalName. o Expansion of nested domain groups via NSS calls. o Support for Active Directory LDAP Signing policy. o New LGPL Winbind client library (libwbclient.so). + Joining: + o New NetApi library for domain join related queries (libnetapi.so) + and example GTK+ Domain join gui. + o New client and server support for remotely joining and unjoining + Domains. + o Support for joining into Windows 2008 domains. Users & Groups: o New ldb backend for local group mapping tables @@ -124,7 +130,7 @@ smb.conf changes mangle map Removed min receive file size New 0 open files database hashsize Removed - read bmpx Removed + read bmpx Removed registry shares New No winbind expand groups New 1 winbind rpc only New No @@ -189,6 +195,40 @@ o Guenther Deschner (including calls from "net dom" command). * Add libnetapi.so library for joining domains including sample GTK+ app. + * Fixes for Vista SP1 Kerberos authdata handling to only pickup + the PAC. + * Various error code and error message fixes. + * Add initial draft of libnetconf to allow programmatic + configuration changes. + * Add libnet_join internal library for programmatically joining + and unjoining Domains. + * Add various fixes and new calls to libnetapi.so library. + * Various fixes for DsGetDcName and conversion to IDL based + structures. + * Fixes for pidl to correctly generate WERROR based client calls. + * Fixes for pidl to generate output that complies to coding + conventions. + * Various IDL fixes. + * Add ads_get_joinable_ous() to libads to get list of joinable ous. + * Add get_logon_hours_from_pdb() to comply with new IDL based + structures. + * Add debugging capabilities to dump AD connections to libads + (using ndr_print). + * Add "dump-domain-list" command for smbcontrol to retrieve better + debugging information out of winbindd. + * Migration of the entire client and server DCE/RPC code to IDL + based structures and autogenerated code for DSSETUP, LSA, SAMR + and NETLOGON. + * Started migration of client and server DCE/RPC code to IDL based + structures and autogenerated code for NTSSVC, SVCCTL and + EVENTLOG. + * Use IDL and autogenerated code for samlogoncache and Kerberos + PAC handling. + * Various fixes and cleanup of Kerberos PAC handling. + * Fix segfault in _srv_net_file_enum. + * Conversion of client join and unjoin code to libnet_join. + * Add remote join/unjoin server-side implementation. + * Removed a lot of code which has become obsolete. o Steve Langasek -- cgit From fbc514eb31cec1b67dced74cbe09457d43b67b12 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 29 Feb 2008 12:38:29 +0100 Subject: Fix linking of smbget when there is no shared library support. smbget needs libwbclient. Michael (cherry picked from commit 78bc496ecf72b5c2474911302e81a90c488e3070) (This used to be commit 901936edd33ae710c6f23bea528132ee5e10e097) --- source3/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/Makefile.in b/source3/Makefile.in index 2f963e295d..35a448016e 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -733,7 +733,7 @@ PDBEDIT_OBJ = utils/pdbedit.o $(PASSWD_UTIL_OBJ) $(PARAM_OBJ) $(PASSDB_OBJ) @LIB $(SECRETS_OBJ) $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) libsmb/asn1.o \ $(RPC_PARSE_OBJ1) $(DOSERR_OBJ) $(LDB_OBJ) $(ERRORMAP_OBJ) -SMBGET_OBJ = utils/smbget.o $(POPT_LIB_OBJ) $(LIBSMBCLIENT_OBJ0) +SMBGET_OBJ = utils/smbget.o $(POPT_LIB_OBJ) $(LIBSMBCLIENT_OBJ0) @LIBWBCLIENT_STATIC@ DISPLAY_SEC_OBJ= lib/display_sec.o -- cgit From f22531b65d88d633e9b217cd4109d9e899c09d1e Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 28 Feb 2008 14:06:11 +0100 Subject: Rename the 'hidden' variable to 'administrative share'. (cherry picked from commit eff3d3bad5a8860b99375cc0be9dc24f3679e416) (This used to be commit 39f712048d7408ba91301b59752f2e87e894a3f0) --- source3/param/loadparm.c | 10 +++++----- source3/rpc_server/srv_srvsvc_nt.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index e23c30789a..5651a435de 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -420,7 +420,7 @@ typedef struct { bool bRead_only; bool bNo_set_dir; bool bGuest_only; - bool bHidden; + bool bAdministrative_share; bool bGuest_ok; bool bPrint_ok; bool bMap_system; @@ -563,7 +563,7 @@ static service sDefault = { True, /* bRead_only */ True, /* bNo_set_dir */ False, /* bGuest_only */ - False, /* bHidden */ + False, /* bAdministrative_share */ False, /* bGuest_ok */ False, /* bPrint_ok */ False, /* bMap_system */ @@ -973,7 +973,7 @@ static struct parm_struct parm_table[] = { {"inherit owner", P_BOOL, P_LOCAL, &sDefault.bInheritOwner, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_HIDE}, - {"hidden", P_BOOL, P_LOCAL, &sDefault.bHidden, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, + {"administrative share", P_BOOL, P_LOCAL, &sDefault.bAdministrative_share, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_HIDE}, @@ -2140,7 +2140,7 @@ FN_LOCAL_BOOL(lp_readonly, bRead_only) FN_LOCAL_BOOL(lp_no_set_dir, bNo_set_dir) FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok) FN_LOCAL_BOOL(lp_guest_only, bGuest_only) -FN_LOCAL_BOOL(lp_hidden, bHidden) +FN_LOCAL_BOOL(lp_administrative_share, bAdministrative_share) FN_LOCAL_BOOL(lp_print_ok, bPrint_ok) FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden) FN_LOCAL_BOOL(lp_map_archive, bMap_archive) @@ -2778,7 +2778,7 @@ static bool lp_add_ipc(const char *ipc_name, bool guest_ok) ServicePtrs[i]->bAvailable = True; ServicePtrs[i]->bRead_only = True; ServicePtrs[i]->bGuest_only = False; - ServicePtrs[i]->bHidden = True; + ServicePtrs[i]->bAdministrative_share = True; ServicePtrs[i]->bGuest_ok = guest_ok; ServicePtrs[i]->bPrint_ok = False; ServicePtrs[i]->bBrowseable = sDefault.bBrowseable; diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index 37bd204f75..8a25b6cfd5 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -232,7 +232,7 @@ static uint32 get_share_type(int snum) type = STYPE_PRINTQ; if (strequal(lp_fstype(snum), "IPC")) type = STYPE_IPC; - if (lp_hidden(snum)) + if (lp_administrative_share(snum)) type |= STYPE_HIDDEN; return type; -- cgit From 1c21e41cd9b4a1121a67b718512381bd8ca14dba Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 29 Feb 2008 06:55:33 -0800 Subject: Patch to fix the "Invalid read of size 4" errors. Bug #3617. Jeremy. (cherry picked from commit fa12667ec284fdda45b79cbf6bf548ab0faae34f) (This used to be commit 5f00c79ac22ecfa846eebd910e7c25d326595f8e) --- source3/nmbd/nmbd_responserecordsdb.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/source3/nmbd/nmbd_responserecordsdb.c b/source3/nmbd/nmbd_responserecordsdb.c index 6498ce04cf..b042fb41ed 100644 --- a/source3/nmbd/nmbd_responserecordsdb.c +++ b/source3/nmbd/nmbd_responserecordsdb.c @@ -46,6 +46,24 @@ static void add_response_record(struct subnet_record *subrec, void remove_response_record(struct subnet_record *subrec, struct response_record *rrec) { + /* It is possible this can be called twice, + with a rrec pointer that has been freed. So + before we inderect into rrec, search for it + on the responselist first. Bug #3617. JRA. */ + + struct response_record *p = NULL; + + for (p = subrec->responselist; p; p = p->next) { + if (p == rrec) { + break; + } + } + + if (p == NULL) { + /* We didn't find rrec on the list. */ + return; + } + DLIST_REMOVE(subrec->responselist, rrec); if(rrec->userdata) { -- cgit From 6d1029607dd372b48ec43c259c8e16f779c89c1f Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Fri, 29 Feb 2008 16:15:39 +0100 Subject: Prepare for release 3.2.0pre2 Karolin (This used to be commit efdf6faba161cae9d4a0a2c693ea0b261dc73ce2) --- source3/VERSION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/VERSION b/source3/VERSION index f0883b95bb..814d171fd9 100644 --- a/source3/VERSION +++ b/source3/VERSION @@ -68,7 +68,7 @@ SAMBA_VERSION_RC_RELEASE= # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=yes +SAMBA_VERSION_IS_GIT_SNAPSHOT= ######################################################## # This can be set by vendors if they want... # @@ -95,5 +95,5 @@ SAMBA_VERSION_IS_GIT_SNAPSHOT=yes # e.g. SAMBA_VERSION_VENDOR_SUFFIX=vendor_version() # # -> "CVS 3.0.0rc2-VendorVersion" # ######################################################## -SAMBA_VERSION_VENDOR_SUFFIX="stable" +SAMBA_VERSION_VENDOR_SUFFIX= SAMBA_VERSION_VENDOR_PATCH= -- cgit From 40ad573190068c8bcad74deff5308cb36871db0a Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Fri, 29 Feb 2008 16:34:07 +0100 Subject: Fix release script. (This used to be commit 400609bce5cd1ce7e3330b9f00bb1f08de9d3a12) --- release-scripts/create-tarball | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/release-scripts/create-tarball b/release-scripts/create-tarball index 459227262d..7dcc6c3b19 100755 --- a/release-scripts/create-tarball +++ b/release-scripts/create-tarball @@ -19,7 +19,7 @@ if [ $? -ne 0 ]; then fi VER_H=source/include/version.h -(cd source && ./autogen.sh) +(cd source && ./script/mkversion.sh) if [ ! -f $VER_H ]; then echo "Failed to find $VER_H! Exiting...." @@ -27,7 +27,10 @@ if [ ! -f $VER_H ]; then fi version=`grep SAMBA_VERSION_OFFICIAL_STRING $VER_H | awk '{print $3}'` -version="$version-`grep SAMBA_VERSION_VENDOR_SUFFIX $VER_H | awk '{print $3}'`" +vendor_version=`grep SAMBA_VERSION_VENDOR_SUFFIX $VER_H | awk '{print $3}'` +if [ -n "$vendor_version" ]; then + version="$version-$vendor_version" +fi version=`echo $version | sed 's/\"//g'` echo "Creating release tarball for Samba $version" @@ -49,7 +52,7 @@ if [ "x$docsdir" != "x" ]; then /bin/rm -rf docs mkdir docs - rsync -a $docsdir/ docs/ + rsync -a --exclude=.svn $docsdir/ docs/ cd docs /bin/rm -rf test.pdf Samba4*pdf htmldocs/Samba4* htmldocs/test @@ -58,6 +61,10 @@ if [ "x$docsdir" != "x" ]; then cd .. fi +cd source +./autogen.sh +cd .. + cd .. tar cf samba-${version}.tar --exclude=.git* --exclude=CVS --exclude=.svn samba-${version} gpg --detach-sign --armor samba-${version}.tar -- cgit From 91609a671e39a177fa30432ceb42ec5b7a5f8fd6 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Fri, 29 Feb 2008 17:51:00 +0100 Subject: Update WHATSNEW. Parameter 'hidden' has been renamed to 'administrative share'. Karolin (This used to be commit f2712698241dc7a0c75378fb8fd747b923d3248f) --- WHATSNEW.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 00b47d8c09..c18ba8b2dc 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -123,7 +123,7 @@ smb.conf changes config backend New file ctdb socket New "" debug class New No - hidden New No + administrative share New No lanman auth Changed Default No ldap debug level New 0 ldap debug threshold New 10 @@ -280,7 +280,7 @@ o Andreas Schneider * Don't restart winbind if a corrupted tdb is found during initialization. * Fix Windows 2008 (Longhorn) join. - * Add share parameter "hidden". + * Add share parameter "administrative share". o Karolin Seeger -- cgit From bc5d7d9387966ae848247776085655a061314b28 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 1 Mar 2008 16:13:25 +0100 Subject: Make sure we are still able to join Windows 2008. Guenther (cherry picked from commit aa9c0f587718f4d647e87b9662acbedba042b9cb) (This used to be commit 851b53895807835fc9e6a4a1b3a2b4739ca7c63f) --- source3/libnet/libnet_join.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 1a8486f5b5..866d1c06e1 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -928,9 +928,8 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, const char *machine_name, const char *dc_name) { - uint32_t neg_flags = NETLOGON_NEG_AUTH2_FLAGS | + uint32_t neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS | NETLOGON_NEG_SCHANNEL; - /* FIXME: NETLOGON_NEG_SELECT_AUTH2_FLAGS */ struct cli_state *cli = NULL; struct rpc_pipe_client *pipe_hnd = NULL; struct rpc_pipe_client *netlogon_pipe = NULL; -- cgit From 80a3e1549c9ff87b54dd1655701138eb77d2384c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Mar 2008 09:26:06 +0100 Subject: Revert "Convert cli_read to use cli_pull" This reverts commit 719527f55e88f0c5fdceda5c807475aba299c79f. (cherry picked from commit ac301fada257e2d3b50148109a3d44fa1421b0b4) (This used to be commit 1bfc4404e7f7314111f979bd09321e39be76bf15) --- source3/libsmb/clireadwrite.c | 178 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 163 insertions(+), 15 deletions(-) diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index c618509f01..5aee8f18bd 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -444,27 +444,175 @@ NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum, return result; } -static NTSTATUS cli_read_sink(char *buf, size_t n, void *priv) +/**************************************************************************** +Issue a single SMBread and don't wait for a reply. +****************************************************************************/ + +static bool cli_issue_read(struct cli_state *cli, int fnum, off_t offset, + size_t size, int i) { - char **pbuf = (char **)priv; - memcpy(*pbuf, buf, n); - *pbuf += n; - return NT_STATUS_OK; + bool bigoffset = False; + + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); + + if ((SMB_BIG_UINT)offset >> 32) + bigoffset = True; + + cli_set_message(cli->outbuf,bigoffset ? 12 : 10,0,True); + + SCVAL(cli->outbuf,smb_com,SMBreadX); + SSVAL(cli->outbuf,smb_tid,cli->cnum); + cli_setup_packet(cli); + + SCVAL(cli->outbuf,smb_vwv0,0xFF); + SSVAL(cli->outbuf,smb_vwv2,fnum); + SIVAL(cli->outbuf,smb_vwv3,offset); + SSVAL(cli->outbuf,smb_vwv5,size); + SSVAL(cli->outbuf,smb_vwv6,size); + SSVAL(cli->outbuf,smb_vwv7,(size >> 16)); + SSVAL(cli->outbuf,smb_mid,cli->mid + i); + + if (bigoffset) { + SIVAL(cli->outbuf,smb_vwv10,(((SMB_BIG_UINT)offset)>>32) & 0xffffffff); + } + + return cli_send_smb(cli); } -ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, - off_t offset, size_t size) +/**************************************************************************** + Read size bytes at offset offset using SMBreadX. +****************************************************************************/ + +ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size) { - NTSTATUS status; - ssize_t ret; + char *p; + size_t size2; + size_t readsize; + ssize_t total = 0; + /* We can only do direct reads if not signing or encrypting. */ + bool direct_reads = !client_is_signing_on(cli) && !cli_encryption_on(cli); - status = cli_pull(cli, fnum, offset, size, size, - cli_read_sink, &buf, &ret); - if (!NT_STATUS_IS_OK(status)) { - cli_set_error(cli, status); - return -1; + if (size == 0) + return 0; + + /* + * Set readsize to the maximum size we can handle in one readX, + * rounded down to a multiple of 1024. + */ + + if (client_is_signing_on(cli) == false && + cli_encryption_on(cli) == false && + (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) { + readsize = CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE; + } else if (cli->capabilities & CAP_LARGE_READX) { + if (cli->is_samba) { + readsize = CLI_SAMBA_MAX_LARGE_READX_SIZE; + } else { + readsize = CLI_WINDOWS_MAX_LARGE_READX_SIZE; + } + } else { + readsize = (cli->max_xmit - (smb_size+32)) & ~1023; + } + + while (total < size) { + readsize = MIN(readsize, size-total); + + /* Issue a read and receive a reply */ + + if (!cli_issue_read(cli, fnum, offset, readsize, 0)) + return -1; + + if (direct_reads) { + if (!cli_receive_smb_readX_header(cli)) + return -1; + } else { + if (!cli_receive_smb(cli)) + return -1; + } + + /* Check for error. Make sure to check for DOS and NT + errors. */ + + if (cli_is_error(cli)) { + bool recoverable_error = False; + NTSTATUS status = NT_STATUS_OK; + uint8 eclass = 0; + uint32 ecode = 0; + + if (cli_is_nt_error(cli)) + status = cli_nt_error(cli); + else + cli_dos_error(cli, &eclass, &ecode); + + /* + * ERRDOS ERRmoredata or STATUS_MORE_ENRTIES is a + * recoverable error, plus we have valid data in the + * packet so don't error out here. + */ + + if ((eclass == ERRDOS && ecode == ERRmoredata) || + NT_STATUS_V(status) == NT_STATUS_V(STATUS_MORE_ENTRIES)) + recoverable_error = True; + + if (!recoverable_error) + return -1; + } + + /* size2 is the number of bytes the server returned. + * Might be zero. */ + size2 = SVAL(cli->inbuf, smb_vwv5); + size2 |= (((unsigned int)(SVAL(cli->inbuf, smb_vwv7))) << 16); + + if (size2 > readsize) { + DEBUG(5,("server returned more than we wanted!\n")); + return -1; + } else if (size2 < 0) { + DEBUG(5,("read return < 0!\n")); + return -1; + } + + if (size2) { + /* smb_vwv6 is the offset in the packet of the returned + * data bytes. Only valid if size2 != 0. */ + + if (!direct_reads) { + /* Copy data into buffer */ + p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6); + memcpy(buf + total, p, size2); + } else { + /* Ensure the remaining data matches the return size. */ + ssize_t toread = smb_len_large(cli->inbuf) - SVAL(cli->inbuf,smb_vwv6); + + /* Ensure the size is correct. */ + if (toread != size2) { + DEBUG(5,("direct read logic fail toread (%d) != size2 (%u)\n", + (int)toread, (unsigned int)size2 )); + return -1; + } + + /* Read data directly into buffer */ + toread = cli_receive_smb_data(cli,buf+total,size2); + if (toread != size2) { + DEBUG(5,("direct read read failure toread (%d) != size2 (%u)\n", + (int)toread, (unsigned int)size2 )); + return -1; + } + } + } + + total += size2; + offset += size2; + + /* + * If the server returned less than we asked for we're at EOF. + */ + + if (size2 < readsize) + break; } - return ret; + + return total; } #if 0 /* relies on client_receive_smb(), now a static in libsmb/clientgen.c */ -- cgit From 54541623e40fcf5ae5a4ef575a4690e388e63a4d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Mar 2008 09:26:18 +0100 Subject: Revert "Add async cli_pull support" This reverts commit 844a163458c7585e4306a21ffdae5d08e03d6e4d. (cherry picked from commit 5ab1cfda500de07ff3c712442ab2fc74eecc8886) (This used to be commit 7821066d4ff4a8503a596ab342a2a84ed9a9f8b9) --- source3/client/client.c | 42 +++-- source3/libsmb/clireadwrite.c | 425 ------------------------------------------ 2 files changed, 27 insertions(+), 440 deletions(-) diff --git a/source3/client/client.c b/source3/client/client.c index 1410fc2f33..f7ed33ad8a 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -964,20 +964,12 @@ static int cmd_echo(void) Get a file from rname to lname ****************************************************************************/ -static NTSTATUS writefile_sink(char *buf, size_t n, void *priv) -{ - int *pfd = (int *)priv; - if (writefile(*pfd, buf, n) == -1) { - return map_nt_error_from_unix(errno); - } - return NT_STATUS_OK; -} - static int do_get(const char *rname, const char *lname_in, bool reget) { TALLOC_CTX *ctx = talloc_tos(); int handle = 0, fnum; bool newhandle = false; + char *data = NULL; struct timeval tp_start; int read_size = io_bufsize; uint16 attr; @@ -988,7 +980,6 @@ static int do_get(const char *rname, const char *lname_in, bool reget) struct cli_state *targetcli = NULL; char *targetname = NULL; char *lname = NULL; - NTSTATUS status; lname = talloc_strdup(ctx, lname_in); if (!lname) { @@ -1047,15 +1038,36 @@ static int do_get(const char *rname, const char *lname_in, bool reget) DEBUG(1,("getting file %s of size %.0f as %s ", rname, (double)size, lname)); - status = cli_pull(targetcli, fnum, start, size, 1024*1024, - writefile_sink, (void *)&handle, &nread); - if (!NT_STATUS_IS_OK(status)) { - d_fprintf(stderr, "parallel_read returned %s\n", - nt_errstr(status)); + if(!(data = (char *)SMB_MALLOC(read_size))) { + d_printf("malloc fail for size %d\n", read_size); cli_close(targetcli, fnum); return 1; } + while (1) { + int n = cli_read(targetcli, fnum, data, nread + start, read_size); + + if (n <= 0) + break; + + if (writefile(handle,data, n) != n) { + d_printf("Error writing local file\n"); + rc = 1; + break; + } + + nread += n; + } + + if (nread + start < size) { + DEBUG (0, ("Short read when getting file %s. Only got %ld bytes.\n", + rname, (long)nread)); + + rc = 1; + } + + SAFE_FREE(data); + if (!cli_close(targetcli, fnum)) { d_printf("Error %s closing remote file\n",cli_errstr(cli)); rc = 1; diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 5aee8f18bd..af13ed8f73 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -19,431 +19,6 @@ #include "includes.h" -/**************************************************************************** - Calculate the recommended read buffer size -****************************************************************************/ -static size_t cli_read_max_bufsize(struct cli_state *cli) -{ - if (!client_is_signing_on(cli) && !cli_encryption_on(cli) == false - && (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) { - return CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE; - } - if (cli->capabilities & CAP_LARGE_READX) { - return cli->is_samba - ? CLI_SAMBA_MAX_LARGE_READX_SIZE - : CLI_WINDOWS_MAX_LARGE_READX_SIZE; - } - return (cli->max_xmit - (smb_size+32)) & ~1023; -} - -/* - * Send a read&x request - */ - -struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, - struct cli_state *cli, int fnum, - off_t offset, size_t size) -{ - struct async_req *result; - struct cli_request *req; - bool bigoffset = False; - char *enc_buf; - - if (size > cli_read_max_bufsize(cli)) { - DEBUG(0, ("cli_read_andx_send got size=%d, can only handle " - "size=%d\n", (int)size, - (int)cli_read_max_bufsize(cli))); - return NULL; - } - - result = cli_request_new(mem_ctx, cli->event_ctx, cli, 12, 0, &req); - if (result == NULL) { - DEBUG(0, ("cli_request_new failed\n")); - return NULL; - } - - req = cli_request_get(result); - - req->data.read.ofs = offset; - req->data.read.size = size; - req->data.read.received = 0; - req->data.read.rcvbuf = NULL; - - if ((SMB_BIG_UINT)offset >> 32) - bigoffset = True; - - cli_set_message(req->outbuf, bigoffset ? 12 : 10, 0, False); - - SCVAL(req->outbuf,smb_com,SMBreadX); - SSVAL(req->outbuf,smb_tid,cli->cnum); - cli_setup_packet_buf(cli, req->outbuf); - - SCVAL(req->outbuf,smb_vwv0,0xFF); - SCVAL(req->outbuf,smb_vwv0+1,0); - SSVAL(req->outbuf,smb_vwv1,0); - SSVAL(req->outbuf,smb_vwv2,fnum); - SIVAL(req->outbuf,smb_vwv3,offset); - SSVAL(req->outbuf,smb_vwv5,size); - SSVAL(req->outbuf,smb_vwv6,size); - SSVAL(req->outbuf,smb_vwv7,(size >> 16)); - SSVAL(req->outbuf,smb_vwv8,0); - SSVAL(req->outbuf,smb_vwv9,0); - SSVAL(req->outbuf,smb_mid,req->mid); - - if (bigoffset) { - SIVAL(req->outbuf, smb_vwv10, - (((SMB_BIG_UINT)offset)>>32) & 0xffffffff); - } - - cli_calculate_sign_mac(cli, req->outbuf); - - event_fd_set_writeable(cli->fd_event); - - if (cli_encryption_on(cli)) { - NTSTATUS status; - status = cli_encrypt_message(cli, req->outbuf, &enc_buf); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Error in encrypting client message. " - "Error %s\n", nt_errstr(status))); - TALLOC_FREE(req); - return NULL; - } - req->outbuf = enc_buf; - req->enc_state = cli->trans_enc_state; - } - - return result; -} - -/* - * Pull the data out of a finished async read_and_x request. rcvbuf is - * talloced from the request, so better make sure that you copy it away before - * you talloc_free(req). "rcvbuf" is NOT a talloc_ctx of its own, so do not - * talloc_move it! - */ - -NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, - uint8_t **rcvbuf) -{ - struct cli_request *cli_req = cli_request_get(req); - NTSTATUS status; - size_t size; - - SMB_ASSERT(req->state >= ASYNC_REQ_DONE); - if (req->state == ASYNC_REQ_ERROR) { - return req->status; - } - - status = cli_pull_error(cli_req->inbuf); - - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /* size is the number of bytes the server returned. - * Might be zero. */ - size = SVAL(cli_req->inbuf, smb_vwv5); - size |= (((unsigned int)(SVAL(cli_req->inbuf, smb_vwv7))) << 16); - - if (size > cli_req->data.read.size) { - DEBUG(5,("server returned more than we wanted!\n")); - return NT_STATUS_UNEXPECTED_IO_ERROR; - } - - if (size < 0) { - DEBUG(5,("read return < 0!\n")); - return NT_STATUS_UNEXPECTED_IO_ERROR; - } - - *rcvbuf = (uint8_t *) - (smb_base(cli_req->inbuf) + SVAL(cli_req->inbuf, smb_vwv6)); - *received = size; - return NT_STATUS_OK; -} - -/* - * Parallel read support. - * - * cli_pull sends as many read&x requests as the server would allow via - * max_mux at a time. When replies flow back in, the data is written into - * the callback function "sink" in the right order. - */ - -struct cli_pull_state { - struct async_req *req; - - struct cli_state *cli; - uint16_t fnum; - off_t start_offset; - size_t size; - - NTSTATUS (*sink)(char *buf, size_t n, void *priv); - void *priv; - - size_t chunk_size; - - /* - * Outstanding requests - */ - int num_reqs; - struct async_req **reqs; - - /* - * For how many bytes did we send requests already? - */ - off_t requested; - - /* - * Next request index to push into "sink". This walks around the "req" - * array, taking care that the requests are pushed to "sink" in the - * right order. If necessary (i.e. replies don't come in in the right - * order), replies are held back in "reqs". - */ - int top_req; - - /* - * How many bytes did we push into "sink"? - */ - - off_t pushed; -}; - -static char *cli_pull_print(TALLOC_CTX *mem_ctx, struct async_req *req) -{ - struct cli_pull_state *state = talloc_get_type_abort( - req->private_data, struct cli_pull_state); - char *result; - - result = async_req_print(mem_ctx, req); - if (result == NULL) { - return NULL; - } - - return talloc_asprintf_append_buffer( - result, "num_reqs=%d, top_req=%d", - state->num_reqs, state->top_req); -} - -static void cli_pull_read_done(struct async_req *read_req); - -/* - * Prepare an async pull request - */ - -struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, - uint16_t fnum, off_t start_offset, - size_t size, size_t window_size, - NTSTATUS (*sink)(char *buf, size_t n, - void *priv), - void *priv) -{ - struct async_req *result; - struct cli_pull_state *state; - int i; - - result = async_req_new(mem_ctx, cli->event_ctx); - if (result == NULL) { - goto failed; - } - state = talloc(result, struct cli_pull_state); - if (state == NULL) { - goto failed; - } - result->private_data = state; - result->print = cli_pull_print; - state->req = result; - - state->cli = cli; - state->fnum = fnum; - state->start_offset = start_offset; - state->size = size; - state->sink = sink; - state->priv = priv; - - state->pushed = 0; - state->top_req = 0; - state->chunk_size = cli_read_max_bufsize(cli); - - state->num_reqs = MAX(window_size/state->chunk_size, 1); - state->num_reqs = MIN(state->num_reqs, cli->max_mux); - - state->reqs = TALLOC_ZERO_ARRAY(state, struct async_req *, - state->num_reqs); - if (state->reqs == NULL) { - goto failed; - } - - state->requested = 0; - - for (i=0; inum_reqs; i++) { - size_t size_left, request_thistime; - - if (state->requested >= size) { - state->num_reqs = i; - break; - } - - size_left = size - state->requested; - request_thistime = MIN(size_left, state->chunk_size); - - state->reqs[i] = cli_read_andx_send( - state->reqs, cli, fnum, - state->start_offset + state->requested, - request_thistime); - - if (state->reqs[i] == NULL) { - goto failed; - } - - state->reqs[i]->async.fn = cli_pull_read_done; - state->reqs[i]->async.priv = result; - - state->requested += request_thistime; - } - return result; - -failed: - TALLOC_FREE(result); - return NULL; -} - -/* - * Handle incoming read replies, push the data into sink and send out new - * requests if necessary. - */ - -static void cli_pull_read_done(struct async_req *read_req) -{ - struct async_req *pull_req = talloc_get_type_abort( - read_req->async.priv, struct async_req); - struct cli_pull_state *state = talloc_get_type_abort( - pull_req->private_data, struct cli_pull_state); - struct cli_request *read_state = cli_request_get(read_req); - NTSTATUS status; - - status = cli_read_andx_recv(read_req, &read_state->data.read.received, - &read_state->data.read.rcvbuf); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(state->req, status); - return; - } - - /* - * This loop is the one to take care of out-of-order replies. All - * pending requests are in state->reqs, state->reqs[top_req] is the - * one that is to be pushed next. If however a request later than - * top_req is replied to, then we can't push yet. If top_req is - * replied to at a later point then, we need to push all the finished - * requests. - */ - - while (state->reqs[state->top_req] != NULL) { - struct cli_request *top_read; - - DEBUG(11, ("cli_pull_read_done: top_req = %d\n", - state->top_req)); - - if (state->reqs[state->top_req]->state < ASYNC_REQ_DONE) { - DEBUG(11, ("cli_pull_read_done: top request not yet " - "done\n")); - return; - } - - top_read = cli_request_get(state->reqs[state->top_req]); - - DEBUG(10, ("cli_pull_read_done: Pushing %d bytes, %d already " - "pushed\n", (int)top_read->data.read.received, - (int)state->pushed)); - - status = state->sink((char *)top_read->data.read.rcvbuf, - top_read->data.read.received, - state->priv); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(state->req, status); - return; - } - state->pushed += top_read->data.read.received; - - TALLOC_FREE(state->reqs[state->top_req]); - - if (state->requested < state->size) { - struct async_req *new_req; - size_t size_left, request_thistime; - - size_left = state->size - state->requested; - request_thistime = MIN(size_left, state->chunk_size); - - DEBUG(10, ("cli_pull_read_done: Requesting %d bytes " - "at %d, position %d\n", - (int)request_thistime, - (int)(state->start_offset - + state->requested), - state->top_req)); - - new_req = cli_read_andx_send( - state->reqs, state->cli, state->fnum, - state->start_offset + state->requested, - request_thistime); - - if (async_req_nomem(new_req, state->req)) { - return; - } - - new_req->async.fn = cli_pull_read_done; - new_req->async.priv = pull_req; - - state->reqs[state->top_req] = new_req; - state->requested += request_thistime; - } - - state->top_req = (state->top_req+1) % state->num_reqs; - } - - async_req_done(pull_req); -} - -NTSTATUS cli_pull_recv(struct async_req *req, ssize_t *received) -{ - struct cli_pull_state *state = talloc_get_type_abort( - req->private_data, struct cli_pull_state); - - SMB_ASSERT(req->state >= ASYNC_REQ_DONE); - if (req->state == ASYNC_REQ_ERROR) { - return req->status; - } - *received = state->pushed; - return NT_STATUS_OK; -} - -NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum, - off_t start_offset, size_t size, size_t window_size, - NTSTATUS (*sink)(char *buf, size_t n, void *priv), - void *priv, ssize_t *received) -{ - TALLOC_CTX *frame = talloc_stackframe(); - struct async_req *req; - NTSTATUS result = NT_STATUS_NO_MEMORY; - - if (cli_tmp_event_ctx(frame, cli) == NULL) { - goto nomem; - } - - req = cli_pull_send(frame, cli, fnum, start_offset, size, window_size, - sink, priv); - if (req == NULL) { - goto nomem; - } - - while (req->state < ASYNC_REQ_DONE) { - event_loop_once(cli->event_ctx); - } - - result = cli_pull_recv(req, received); - nomem: - TALLOC_FREE(frame); - return result; -} - /**************************************************************************** Issue a single SMBread and don't wait for a reply. ****************************************************************************/ -- cgit From a1facdd7cc333183c488d7d090e7bf2915b5c227 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Mar 2008 09:26:27 +0100 Subject: Revert "Add infrastructure to support async SMB requests" This reverts commit f5356825698a02df2d400b51dd95d1f857c83e81. (cherry picked from commit 5f53a62be8a21b8d92ac44b18d202882500356e8) (This used to be commit 8beead9c936038365f28467e527b2c066e3a5440) --- source3/Makefile.in | 2 +- source3/include/async_smb.h | 62 ------ source3/include/client.h | 30 --- source3/include/includes.h | 1 - source3/libsmb/async_smb.c | 483 -------------------------------------------- 5 files changed, 1 insertion(+), 577 deletions(-) delete mode 100644 source3/include/async_smb.h delete mode 100644 source3/libsmb/async_smb.c diff --git a/source3/Makefile.in b/source3/Makefile.in index 35a448016e..bee8cf0738 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -408,7 +408,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \ libsmb/clistr.o libsmb/cliquota.o libsmb/clifsinfo.o libsmb/clidfs.o \ libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \ libsmb/clioplock.o $(ERRORMAP_OBJ) libsmb/clirap2.o \ - libsmb/smb_seal.o $(DOSERR_OBJ) libsmb/async_smb.o \ + libsmb/smb_seal.o $(DOSERR_OBJ) \ $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(LIBNMB_OBJ) RPC_CLIENT_OBJ1 = rpc_client/cli_netlogon.o rpc_client/cli_srvsvc.o diff --git a/source3/include/async_smb.h b/source3/include/async_smb.h deleted file mode 100644 index 19408be74b..0000000000 --- a/source3/include/async_smb.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Infrastructure for async SMB client requests - Copyright (C) Volker Lendecke 2008 - - 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 3 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, see . -*/ - -#include "includes.h" - -/* - * Create a fresh async smb request - */ - -struct async_req *cli_request_new(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - uint8_t num_words, size_t num_bytes, - struct cli_request **preq); - -/* - * Convenience function to get the SMB part out of an async_req - */ - -struct cli_request *cli_request_get(struct async_req *req); - -/* - * Fetch an error out of a NBT packet - */ - -NTSTATUS cli_pull_error(char *buf); - -/* - * Compatibility helper for the sync APIs: Fake NTSTATUS in cli->inbuf - */ - -void cli_set_error(struct cli_state *cli, NTSTATUS status); - -/* - * Create a temporary event context for use in the sync helper functions - */ - -struct cli_tmp_event *cli_tmp_event_ctx(TALLOC_CTX *mem_ctx, - struct cli_state *cli); - -/* - * Attach an event context permanently to a cli_struct - */ - -NTSTATUS cli_add_event_ctx(struct cli_state *cli, - struct event_context *event_ctx); diff --git a/source3/include/client.h b/source3/include/client.h index 52dc513d65..d29a2e7341 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -192,36 +192,6 @@ struct cli_state { bool force_dos_errors; bool case_sensitive; /* False by default. */ - - struct event_context *event_ctx; - struct fd_event *fd_event; - char *evt_inbuf; - - struct cli_request *outstanding_requests; -}; - -struct cli_request { - struct cli_request *prev, *next; - struct async_req *async; - - struct cli_state *cli; - - struct smb_trans_enc_state *enc_state; - - uint16_t mid; - - char *outbuf; - size_t sent; - char *inbuf; - - union { - struct { - off_t ofs; - size_t size; - ssize_t received; - uint8_t *rcvbuf; - } read; - } data; }; typedef struct file_info { diff --git a/source3/include/includes.h b/source3/include/includes.h index 269baa5a9c..8b94d7aed2 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -724,7 +724,6 @@ typedef char fstring[FSTRING_LEN]; #include "talloc_stack.h" #include "memcache.h" #include "async_req.h" -#include "async_smb.h" /* used in net.c */ struct functable { diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c deleted file mode 100644 index 21bcd5b9b1..0000000000 --- a/source3/libsmb/async_smb.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Infrastructure for async SMB client requests - Copyright (C) Volker Lendecke 2008 - - 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 3 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, see . -*/ - -#include "includes.h" - -/* - * Fetch an error out of a NBT packet - */ - -NTSTATUS cli_pull_error(char *buf) -{ - uint32_t flags2 = SVAL(buf, smb_flg2); - - if (flags2 & FLAGS2_32_BIT_ERROR_CODES) { - return NT_STATUS(IVAL(buf, smb_rcls)); - } - - return NT_STATUS_DOS(CVAL(buf, smb_rcls), SVAL(buf,smb_err)); -} - -/* - * Compatibility helper for the sync APIs: Fake NTSTATUS in cli->inbuf - */ - -void cli_set_error(struct cli_state *cli, NTSTATUS status) -{ - uint32_t flags2 = SVAL(cli->inbuf, smb_flg2); - - if (NT_STATUS_IS_DOS(status)) { - SSVAL(cli->inbuf, smb_flg2, - flags2 & ~FLAGS2_32_BIT_ERROR_CODES); - SCVAL(cli->inbuf, smb_rcls, NT_STATUS_DOS_CLASS(status)); - SSVAL(cli->inbuf, smb_err, NT_STATUS_DOS_CODE(status)); - return; - } - - SSVAL(cli->inbuf, smb_flg2, flags2 | FLAGS2_32_BIT_ERROR_CODES); - SIVAL(cli->inbuf, smb_rcls, NT_STATUS_V(status)); - return; -} - -/* - * Allocate a new mid - */ - -static uint16_t cli_new_mid(struct cli_state *cli) -{ - uint16_t result; - struct cli_request *req; - - while (true) { - result = cli->mid++; - if (result == 0) { - continue; - } - - for (req = cli->outstanding_requests; req; req = req->next) { - if (result == req->mid) { - break; - } - } - - if (req == NULL) { - return result; - } - } -} - -static char *cli_request_print(TALLOC_CTX *mem_ctx, struct async_req *req) -{ - char *result = async_req_print(mem_ctx, req); - struct cli_request *cli_req = cli_request_get(req); - - if (result == NULL) { - return NULL; - } - - return talloc_asprintf_append_buffer( - result, "mid=%d\n", cli_req->mid); -} - -static int cli_request_destructor(struct cli_request *req) -{ - if (req->enc_state != NULL) { - common_free_enc_buffer(req->enc_state, req->outbuf); - } - DLIST_REMOVE(req->cli->outstanding_requests, req); - return 0; -} - -/* - * Create a fresh async smb request - */ - -struct async_req *cli_request_new(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - uint8_t num_words, size_t num_bytes, - struct cli_request **preq) -{ - struct async_req *result; - struct cli_request *cli_req; - size_t bufsize = smb_size + num_words * 2 + num_bytes; - - result = async_req_new(mem_ctx, ev); - if (result == NULL) { - return NULL; - } - - cli_req = (struct cli_request *)talloc_size( - result, sizeof(*cli_req) + bufsize); - if (cli_req == NULL) { - TALLOC_FREE(result); - return NULL; - } - talloc_set_name_const(cli_req, "struct cli_request"); - result->private_data = cli_req; - result->print = cli_request_print; - - cli_req->async = result; - cli_req->cli = cli; - cli_req->outbuf = ((char *)cli_req + sizeof(*cli_req)); - cli_req->sent = 0; - cli_req->mid = cli_new_mid(cli); - cli_req->inbuf = NULL; - cli_req->enc_state = NULL; - - SCVAL(cli_req->outbuf, smb_wct, num_words); - SSVAL(cli_req->outbuf, smb_vwv + num_words * 2, num_bytes); - - DLIST_ADD_END(cli->outstanding_requests, cli_req, - struct cli_request *); - talloc_set_destructor(cli_req, cli_request_destructor); - - DEBUG(10, ("cli_request_new: mid=%d\n", cli_req->mid)); - - *preq = cli_req; - return result; -} - -/* - * Convenience function to get the SMB part out of an async_req - */ - -struct cli_request *cli_request_get(struct async_req *req) -{ - if (req == NULL) { - return NULL; - } - return talloc_get_type_abort(req->private_data, struct cli_request); -} - -/* - * A PDU has arrived on cli->evt_inbuf - */ - -static void handle_incoming_pdu(struct cli_state *cli) -{ - struct cli_request *req; - uint16_t mid; - size_t raw_pdu_len, buf_len, pdu_len; - size_t rest_len; - NTSTATUS status; - - /* - * The encrypted PDU len might differ from the unencrypted one - */ - raw_pdu_len = smb_len(cli->evt_inbuf) + 4; - - /* - * TODO: Handle oplock break requests - */ - - if (cli_encryption_on(cli) && CVAL(cli->evt_inbuf, 0) == 0) { - uint16_t enc_ctx_num; - - status = get_enc_ctx_num((uint8_t *)cli->evt_inbuf, - &enc_ctx_num); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("get_enc_ctx_num returned %s\n", - nt_errstr(status))); - goto invalidate_requests; - } - - if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) { - DEBUG(10, ("wrong enc_ctx %d, expected %d\n", - enc_ctx_num, - cli->trans_enc_state->enc_ctx_num)); - status = NT_STATUS_INVALID_HANDLE; - goto invalidate_requests; - } - - status = common_decrypt_buffer(cli->trans_enc_state, - cli->evt_inbuf); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("common_decrypt_buffer returned %s\n", - nt_errstr(status))); - goto invalidate_requests; - } - } - - if (!cli_check_sign_mac(cli, cli->evt_inbuf)) { - DEBUG(10, ("cli_check_sign_mac failed\n")); - status = NT_STATUS_ACCESS_DENIED; - goto invalidate_requests; - } - - mid = SVAL(cli->evt_inbuf, smb_mid); - - DEBUG(10, ("handle_incoming_pdu: got mid %d\n", mid)); - - for (req = cli->outstanding_requests; req; req = req->next) { - if (req->mid == mid) { - break; - } - } - - buf_len = talloc_get_size(cli->evt_inbuf); - pdu_len = smb_len(cli->evt_inbuf) + 4; - rest_len = buf_len - raw_pdu_len; - - if (req == NULL) { - DEBUG(3, ("Request for mid %d not found, dumping PDU\n", mid)); - - memmove(cli->evt_inbuf, cli->evt_inbuf + raw_pdu_len, - buf_len - raw_pdu_len); - - cli->evt_inbuf = TALLOC_REALLOC_ARRAY(NULL, cli->evt_inbuf, - char, rest_len); - return; - } - - if (buf_len == pdu_len) { - /* - * Optimal case: Exactly one PDU was in the socket buffer - */ - req->inbuf = talloc_move(req, &cli->evt_inbuf); - goto done; - } - - DEBUG(11, ("buf_len = %d, pdu_len = %d, splitting buffer\n", - (int)buf_len, (int)pdu_len)); - - if (pdu_len < rest_len) { - /* - * The PDU is shorter, talloc_memdup that one. - */ - req->inbuf = (char *)talloc_memdup( - req, cli->evt_inbuf, pdu_len); - - memmove(cli->evt_inbuf, - cli->evt_inbuf + raw_pdu_len, - buf_len - raw_pdu_len); - - cli->evt_inbuf = TALLOC_REALLOC_ARRAY( - NULL, cli->evt_inbuf, char, rest_len); - } - else { - /* - * The PDU is larger than the rest, - * talloc_memdup the rest - */ - req->inbuf = talloc_move(req, &cli->evt_inbuf); - - cli->evt_inbuf = (char *)talloc_memdup( - cli, req->inbuf + raw_pdu_len, - rest_len); - } - - if ((req->inbuf == NULL) || (cli->evt_inbuf == NULL)) { - status = NT_STATUS_NO_MEMORY; - goto invalidate_requests; - } - - done: - async_req_done(req->async); - return; - - invalidate_requests: - - DEBUG(10, ("handle_incoming_pdu: Aborting with %s\n", - nt_errstr(status))); - - for (req = cli->outstanding_requests; req; req = req->next) { - async_req_error(req->async, status); - } - return; -} - -/* - * fd event callback. This is the basic connection to the socket - */ - -static void cli_state_handler(struct event_context *event_ctx, - struct fd_event *event, uint16 flags, void *p) -{ - struct cli_state *cli = (struct cli_state *)p; - struct cli_request *req; - - DEBUG(11, ("cli_state_handler called with flags %d\n", flags)); - - if (flags & EVENT_FD_READ) { - int res, available; - size_t old_size, new_size; - char *tmp; - - res = ioctl(cli->fd, FIONREAD, &available); - if (res == -1) { - DEBUG(10, ("ioctl(FIONREAD) failed: %s\n", - strerror(errno))); - goto sock_error; - } - - if (available == 0) { - /* EOF */ - goto sock_error; - } - - old_size = talloc_get_size(cli->evt_inbuf); - new_size = old_size + available; - - if (new_size < old_size) { - /* wrap */ - goto sock_error; - } - - tmp = TALLOC_REALLOC_ARRAY(cli, cli->evt_inbuf, char, - new_size); - if (tmp == NULL) { - /* nomem */ - goto sock_error; - } - cli->evt_inbuf = tmp; - - res = recv(cli->fd, cli->evt_inbuf + old_size, available, 0); - if (res == -1) { - DEBUG(10, ("recv failed: %s\n", strerror(errno))); - goto sock_error; - } - - DEBUG(11, ("cli_state_handler: received %d bytes, " - "smb_len(evt_inbuf) = %d\n", (int)res, - smb_len(cli->evt_inbuf))); - - /* recv *might* have returned less than announced */ - new_size = old_size + res; - - /* shrink, so I don't expect errors here */ - cli->evt_inbuf = TALLOC_REALLOC_ARRAY(cli, cli->evt_inbuf, - char, new_size); - - while ((cli->evt_inbuf != NULL) - && ((smb_len(cli->evt_inbuf) + 4) <= new_size)) { - /* - * we've got a complete NBT level PDU in evt_inbuf - */ - handle_incoming_pdu(cli); - new_size = talloc_get_size(cli->evt_inbuf); - } - } - - if (flags & EVENT_FD_WRITE) { - size_t to_send; - ssize_t sent; - - for (req = cli->outstanding_requests; req; req = req->next) { - to_send = smb_len(req->outbuf)+4; - if (to_send > req->sent) { - break; - } - } - - if (req == NULL) { - event_fd_set_not_writeable(event); - return; - } - - sent = send(cli->fd, req->outbuf + req->sent, - to_send - req->sent, 0); - - if (sent < 0) { - goto sock_error; - } - - req->sent += sent; - - if (req->sent == to_send) { - return; - } - } - return; - - sock_error: - for (req = cli->outstanding_requests; req; req = req->next) { - req->async->state = ASYNC_REQ_ERROR; - req->async->status = map_nt_error_from_unix(errno); - } - TALLOC_FREE(cli->fd_event); - close(cli->fd); - cli->fd = -1; -} - -/* - * Holder for a talloc_destructor, we need to zero out the pointers in cli - * when deleting - */ -struct cli_tmp_event { - struct cli_state *cli; -}; - -static int cli_tmp_event_destructor(struct cli_tmp_event *e) -{ - TALLOC_FREE(e->cli->fd_event); - TALLOC_FREE(e->cli->event_ctx); - return 0; -} - -/* - * Create a temporary event context for use in the sync helper functions - */ - -struct cli_tmp_event *cli_tmp_event_ctx(TALLOC_CTX *mem_ctx, - struct cli_state *cli) -{ - struct cli_tmp_event *state; - - if (cli->event_ctx != NULL) { - return NULL; - } - - state = talloc(mem_ctx, struct cli_tmp_event); - if (state == NULL) { - return NULL; - } - state->cli = cli; - talloc_set_destructor(state, cli_tmp_event_destructor); - - cli->event_ctx = event_context_init(state); - if (cli->event_ctx == NULL) { - TALLOC_FREE(state); - return NULL; - } - - cli->fd_event = event_add_fd(cli->event_ctx, state, cli->fd, - EVENT_FD_READ, cli_state_handler, cli); - if (cli->fd_event == NULL) { - TALLOC_FREE(state); - return NULL; - } - return state; -} - -/* - * Attach an event context permanently to a cli_struct - */ - -NTSTATUS cli_add_event_ctx(struct cli_state *cli, - struct event_context *event_ctx) -{ - cli->event_ctx = event_ctx; - cli->fd_event = event_add_fd(event_ctx, cli, cli->fd, EVENT_FD_READ, - cli_state_handler, cli); - if (cli->fd_event == NULL) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} -- cgit From 2e7eb4d023f8b284121ae380091363ba25d0a3e4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Mar 2008 09:26:43 +0100 Subject: Revert "Add basic infrastructure for general async requests" This reverts commit ae254cb61f4b9331755848c47ebc34e90dd80390. (cherry picked from commit 030bef7f22f7a73466204b7860f397dbca9f2ab0) (This used to be commit 575b829b390f7f07138305adc2988918eda95ce1) --- source3/Makefile.in | 2 +- source3/include/async_req.h | 89 --------------------------------------------- source3/include/includes.h | 1 - source3/lib/async_req.c | 68 ---------------------------------- 4 files changed, 1 insertion(+), 159 deletions(-) delete mode 100644 source3/include/async_req.h delete mode 100644 source3/lib/async_req.c diff --git a/source3/Makefile.in b/source3/Makefile.in index bee8cf0738..c91f544369 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -323,7 +323,7 @@ LIB_WITHOUT_PROTO_OBJ = $(LIBSAMBAUTIL_OBJ) \ lib/messages.o librpc/gen_ndr/ndr_messaging.o lib/messages_local.o \ lib/messages_ctdbd.o lib/packet.o lib/ctdbd_conn.o lib/talloc_stack.o \ lib/interfaces.o lib/rbtree.o lib/memcache.o \ - lib/util_transfer_file.o lib/async_req.o + lib/util_transfer_file.o LIB_WITH_PROTO_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \ lib/interface.o lib/md4.o \ diff --git a/source3/include/async_req.h b/source3/include/async_req.h deleted file mode 100644 index 6df53602b2..0000000000 --- a/source3/include/async_req.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Infrastructure for async requests - Copyright (C) Volker Lendecke 2008 - - 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 3 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, see . -*/ - -#ifndef __ASYNC_REQ_H__ -#define __ASYNC_REQ_H__ - -#include "includes.h" - -/* - * An async request moves between the following 4 states. - */ -enum async_req_state { - ASYNC_REQ_INIT, /* we are creating the request */ - ASYNC_REQ_IN_PROGRESS, /* we are waiting the request to complete */ - ASYNC_REQ_DONE, /* the request is finished */ - ASYNC_REQ_ERROR }; /* an error has occured */ - -struct async_req { - /* the external state - will be queried by the caller */ - enum async_req_state state; - - /* a private pointer for use by the async function implementation */ - void *private_data; - - /* print yourself, for debugging purposes */ - char *(*print)(TALLOC_CTX *mem_ctx, struct async_req *); - - /* status code when finished */ - NTSTATUS status; - - /* the event context we are using */ - struct event_context *event_ctx; - - /* information on what to do on completion */ - struct { - void (*fn)(struct async_req *); - void *priv; - } async; -}; - -/* - * Print an async_req structure for debugging purposes - */ -char *async_req_print(TALLOC_CTX *mem_ctx, struct async_req *req); - -/* - * Create an async request - */ -struct async_req *async_req_new(TALLOC_CTX *mem_ctx, struct event_context *ev); - -/* - * An async request has successfully finished, invoke the callback - */ -void async_req_done(struct async_req *req); - -/* - * An async request has seen an error, invoke the callback - */ -void async_req_error(struct async_req *req, NTSTATUS status); - -/* - * Convenience helper to easily check alloc failure within a callback. - * - * Call pattern would be - * p = talloc(mem_ctx, bla); - * if (async_req_nomem(p, req)) { - * return; - * } - * - */ -bool async_req_nomem(const void *p, struct async_req *req); - -#endif diff --git a/source3/include/includes.h b/source3/include/includes.h index 8b94d7aed2..a2c3a0c466 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -723,7 +723,6 @@ typedef char fstring[FSTRING_LEN]; #include "ctdbd_conn.h" #include "talloc_stack.h" #include "memcache.h" -#include "async_req.h" /* used in net.c */ struct functable { diff --git a/source3/lib/async_req.c b/source3/lib/async_req.c deleted file mode 100644 index 01154ca436..0000000000 --- a/source3/lib/async_req.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Infrastructure for async requests - Copyright (C) Volker Lendecke 2008 - - 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 3 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, see . -*/ - -#include "includes.h" - -char *async_req_print(TALLOC_CTX *mem_ctx, struct async_req *req) -{ - return talloc_asprintf(mem_ctx, "async_req: state=%d, status=%s, " - "priv=%s", req->state, nt_errstr(req->status), - talloc_get_name(req->private_data)); -} - -struct async_req *async_req_new(TALLOC_CTX *mem_ctx, struct event_context *ev) -{ - struct async_req *result; - - result = TALLOC_ZERO_P(mem_ctx, struct async_req); - if (result == NULL) { - return NULL; - } - result->state = ASYNC_REQ_IN_PROGRESS; - result->event_ctx = ev; - result->print = async_req_print; - return result; -} - -void async_req_done(struct async_req *req) -{ - req->status = NT_STATUS_OK; - req->state = ASYNC_REQ_DONE; - if (req->async.fn != NULL) { - req->async.fn(req); - } -} - -void async_req_error(struct async_req *req, NTSTATUS status) -{ - req->status = status; - req->state = ASYNC_REQ_ERROR; - if (req->async.fn != NULL) { - req->async.fn(req); - } -} - -bool async_req_nomem(const void *p, struct async_req *req) -{ - if (p != NULL) { - return false; - } - async_req_error(req, NT_STATUS_NO_MEMORY); - return true; -} -- cgit From f247b78eb9db8f85f31d8fd07f2cfbd03c819d14 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 29 Feb 2008 22:38:10 +0100 Subject: Restore 3.0 behaviour with empty /etc/hosts Jeremy, in 3.0 we allowed get_mydnsdomname and get_mydnsfullname to fail without filling in anything useful. Worked fine. Without this patch and a empty /etc/hosts and no DNS configured, session setup would return NT_STATUS_BAD_NETWORK_NAME. This is confusing at best, BAD_NETWORK_NAME afaik is only ever returned from tcon normally. This restores the 3.0 behaviour. Comments? Volker (This used to be commit 4170259e5f83c281966a80916e4ece6937e08988) --- source3/libsmb/ntlmssp.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 35c20ed647..7082ea7e4e 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -566,13 +566,16 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, /* This should be a 'netbios domain -> DNS domain' mapping */ dnsdomname = get_mydnsdomname(ntlmssp_state->mem_ctx); if (!dnsdomname) { - return NT_STATUS_BAD_NETWORK_NAME; + dnsdomname = talloc_strdup(ntlmssp_state->mem_ctx, ""); + } + if (!dnsdomname) { + return NT_STATUS_NO_MEMORY; } strlower_m(dnsdomname); dnsname = get_mydnsfullname(); - if (!dnsdomname) { - return NT_STATUS_INVALID_COMPUTER_NAME; + if (!dnsname) { + dnsname = ""; } /* This creates the 'blob' of names that appears at the end of the packet */ -- cgit From 5491030872b35453d5a13417b0b7f39032b07056 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 3 Mar 2008 18:12:26 +0100 Subject: Zero out the out policy handler in lsa_Close ... after a REALLY long session staring at sniffs we can now join XP to v3-2-test again... Apparently not doing this makes XP keep an internal handle to LSA open which confuses the hell out of it. Karolin, this needs to be in v3-2-stable :-) Volker (cherry picked from commit 2c42fc21d8bede226e411623aecd69038477373b) (This used to be commit a94313e06a030e1a1afff18c797e700eb6b25248) --- source3/rpc_server/srv_lsa_nt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index 1333d656d4..ce3fd1a44f 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -1216,6 +1216,7 @@ NTSTATUS _lsa_Close(pipes_struct *p, struct lsa_Close *r) } close_policy_hnd(p, r->in.handle); + ZERO_STRUCTP(r->out.handle); return NT_STATUS_OK; } -- cgit From c2beacfb3fca5c50fda985862a7a78f12cc6354d Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 28 Feb 2008 11:23:20 -0500 Subject: Initial revamp of the libsmbclient interface. The libsmbclient interface has suffered from difficulty of improvement and feature enrichment without causing ABI breakage. Although there were a number of issues, the primary ones were: (a) the user of the library would manually manipulate the context structure members, meaning that nothing in the context structure could change other than adding stuff at the end; (b) there were three methods of setting options: setting bits in a flags field within the context structure, setting explicit options variables within an options structure in the context structure, and by calling the smbc_option_set() function; (c) the authentication callback did not traditionally provide enough information to the callee which required adding an option for a callback with a different signature, and now there are requests for even more information at the callback, requiring yet a third signature and option to set it (if we implement that feature). This commit provides a reorganization of the code which fixes (a) and (b). The context structure is now entirely opaque, and there are setter and getter functions for manipulating it. This makes maintaining ABI consistency much, much easier. Additionally, the options setting/getting has been unified into a single mechanism using smbc_option_set() and smbc_option_get(). Yet to be completed is a refactoring of the authentication callback (c). The test programs in examples/libsmbclient have been modified (if necessary; some applications require no changes at all) for the new API and a few have been minimally tested. Derrell (cherry picked from commit d4b4bae8ded824d06ad5ab0e219f71187ee5c771) (This used to be commit 59292c0da8880afd7bac82f6a5bba009f3827ea0) --- examples/libsmbclient/smbwrapper/smbw.c | 10 +- examples/libsmbclient/testbrowse.c | 8 +- examples/libsmbclient/testbrowse2.c | 17 +- source3/Makefile.in | 12 +- source3/include/libsmb_internal.h | 538 ++- source3/include/libsmbclient.h | 495 ++- source3/libsmb/libsmb_cache.c | 74 +- source3/libsmb/libsmb_compat.c | 329 +- source3/libsmb/libsmb_context.c | 1283 ++++++ source3/libsmb/libsmb_dir.c | 1928 ++++++++ source3/libsmb/libsmb_file.c | 859 ++++ source3/libsmb/libsmb_misc.c | 73 + source3/libsmb/libsmb_path.c | 399 ++ source3/libsmb/libsmb_printjob.c | 334 ++ source3/libsmb/libsmb_server.c | 675 +++ source3/libsmb/libsmb_stat.c | 302 ++ source3/libsmb/libsmb_xattr.c | 2293 ++++++++++ source3/libsmb/libsmbclient.c | 7233 ------------------------------- 18 files changed, 9227 insertions(+), 7635 deletions(-) create mode 100644 source3/libsmb/libsmb_context.c create mode 100644 source3/libsmb/libsmb_dir.c create mode 100644 source3/libsmb/libsmb_file.c create mode 100644 source3/libsmb/libsmb_misc.c create mode 100644 source3/libsmb/libsmb_path.c create mode 100644 source3/libsmb/libsmb_printjob.c create mode 100644 source3/libsmb/libsmb_server.c create mode 100644 source3/libsmb/libsmb_stat.c create mode 100644 source3/libsmb/libsmb_xattr.c delete mode 100644 source3/libsmb/libsmbclient.c diff --git a/examples/libsmbclient/smbwrapper/smbw.c b/examples/libsmbclient/smbwrapper/smbw.c index b88290ff6d..d3439e436d 100644 --- a/examples/libsmbclient/smbwrapper/smbw.c +++ b/examples/libsmbclient/smbwrapper/smbw.c @@ -174,11 +174,11 @@ static void do_init(StartupType startupType) exit(1); } - smbw_ctx->debug = debug_level; - smbw_ctx->callbacks.auth_fn = get_auth_data_fn; - smbw_ctx->options.browse_max_lmb_count = 0; - smbw_ctx->options.urlencode_readdir_entries = 1; - smbw_ctx->options.one_share_per_server = 1; + smbc_setDebug(smbw_ctx, debug_level); + smbc_setFunctionAuthData(smbw_ctx, get_auth_data_fn); + smbc_option_set(smbw_ctx, "browse_max_lmb_count", 0); + smbc_option_set(smbw_ctx, "urlencode_readdir_entries", 1); + smbc_option_set(smbw_ctx, "one_share_per_server", 1); if (smbc_init_context(smbw_ctx) == NULL) { fprintf(stderr, "Could not initialize context.\n"); diff --git a/examples/libsmbclient/testbrowse.c b/examples/libsmbclient/testbrowse.c index 562d2c2aeb..495cf0fbec 100644 --- a/examples/libsmbclient/testbrowse.c +++ b/examples/libsmbclient/testbrowse.c @@ -108,7 +108,8 @@ main(int argc, char * argv[]) } /* Set mandatory options (is that a contradiction in terms?) */ - context->debug = debug; + smbc_setDebug(context, debug); +#if 0 if (context_auth) { context->callbacks.auth_fn = NULL; smbc_option_set(context, @@ -119,6 +120,11 @@ main(int argc, char * argv[]) context->callbacks.auth_fn = (no_auth ? no_auth_data_fn : 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) { diff --git a/examples/libsmbclient/testbrowse2.c b/examples/libsmbclient/testbrowse2.c index 76d98b9602..0ac1d72bb4 100644 --- a/examples/libsmbclient/testbrowse2.c +++ b/examples/libsmbclient/testbrowse2.c @@ -93,8 +93,8 @@ SMBCCTX* create_smbctx(){ if ((ctx = smbc_new_context()) == NULL) return NULL; - ctx->debug = debuglevel; - ctx->callbacks.auth_fn = smbc_auth_fn; + smbc_setDebug(ctx, debuglevel); + smbc_setFunctionAuthData(ctx, smbc_auth_fn); if (smbc_init_context(ctx) == NULL){ smbc_free_context(ctx, 1); @@ -105,7 +105,7 @@ SMBCCTX* create_smbctx(){ } void delete_smbctx(SMBCCTX* ctx){ - ctx->callbacks.purge_cached_fn(ctx); + smbc_getFunctionPurgeCachedServers(ctx)(ctx); smbc_free_context(ctx, 1); } @@ -114,8 +114,9 @@ smbitem* get_smbitem_list(SMBCCTX *ctx, char *smb_path){ struct smbc_dirent *dirent; smbitem *list = NULL, *item; - if ((fd = ctx->opendir(ctx, smb_path)) == NULL) return NULL; - while((dirent = ctx->readdir(ctx, fd)) != NULL){ + if ((fd = smbc_getFunctionOpendir(ctx)(ctx, smb_path)) == NULL) + return NULL; + while((dirent = smbc_getFunctionReaddir(ctx)(ctx, fd)) != NULL){ if (strcmp(dirent->name, "") == 0) continue; if (strcmp(dirent->name, ".") == 0) continue; if (strcmp(dirent->name, "..") == 0) continue; @@ -128,7 +129,7 @@ smbitem* get_smbitem_list(SMBCCTX *ctx, char *smb_path){ strcpy(item->name, dirent->name); list = item; } - ctx->close_fn(ctx, fd); + smbc_getFunctionClose(ctx)(ctx, fd); return /* smbitem_list_sort */ (list); } @@ -167,7 +168,7 @@ void recurse(SMBCCTX *ctx, char *smb_group, char *smb_path, int maxlen){ delete_smbctx(ctx1); }else{ recurse(ctx, smb_group, smb_path, maxlen); - ctx->callbacks.purge_cached_fn(ctx); + smbc_getFunctionPurgeCachedServers(ctx)(ctx); } break; case SMBC_FILE_SHARE: @@ -181,7 +182,7 @@ void recurse(SMBCCTX *ctx, char *smb_group, char *smb_path, int maxlen){ if (list->type != SMBC_FILE){ recurse(ctx, smb_group, smb_path, maxlen); if (list->type == SMBC_FILE_SHARE) - ctx->callbacks.purge_cached_fn(ctx); + smbc_getFunctionPurgeCachedServers(ctx)(ctx); } break; } diff --git a/source3/Makefile.in b/source3/Makefile.in index c91f544369..ddeac06dc0 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -756,8 +756,18 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \ PAM_WINBIND_OBJ = nsswitch/pam_winbind.o $(WBCOMMON_OBJ) \ $(LIBREPLACE_OBJ) @BUILD_INIPARSER@ -LIBSMBCLIENT_OBJ0 = libsmb/libsmbclient.o libsmb/libsmb_compat.o \ +LIBSMBCLIENT_OBJ0 = \ libsmb/libsmb_cache.o \ + libsmb/libsmb_compat.o \ + libsmb/libsmb_context.o \ + libsmb/libsmb_dir.o \ + libsmb/libsmb_file.o \ + libsmb/libsmb_misc.o \ + libsmb/libsmb_path.o \ + libsmb/libsmb_printjob.o \ + libsmb/libsmb_server.o \ + libsmb/libsmb_stat.o \ + libsmb/libsmb_xattr.o \ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(RPC_PARSE_OBJ) \ diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index 6c7dc80da8..353575dce8 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -1,12 +1,71 @@ +/* + Unix SMB/Netbios implementation. + SMB client library implementation + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000, 2002 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 3 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, see . +*/ + +#include "includes.h" + + #ifndef _LIBSMB_INTERNAL_H_ #define _LIBSMB_INTERNAL_H_ +#include "../include/libsmbclient.h" + #define SMBC_MAX_NAME 1023 #define SMBC_FILE_MODE (S_IFREG | 0444) #define SMBC_DIR_MODE (S_IFDIR | 0555) +/* + * DOS Attribute values (used internally) + */ +typedef struct DOS_ATTR_DESC { + int mode; + SMB_OFF_T size; + time_t create_time; + time_t access_time; + time_t write_time; + time_t change_time; + SMB_INO_T inode; +} DOS_ATTR_DESC; + + +/* + * Internal flags for extended attributes + */ + +/* internal mode values */ +#define SMBC_XATTR_MODE_ADD 1 +#define SMBC_XATTR_MODE_REMOVE 2 +#define SMBC_XATTR_MODE_REMOVE_ALL 3 +#define SMBC_XATTR_MODE_SET 4 +#define SMBC_XATTR_MODE_CHOWN 5 +#define SMBC_XATTR_MODE_CHGRP 6 + +#define CREATE_ACCESS_READ READ_CONTROL_ACCESS -#include "include/libsmbclient.h" +/*We should test for this in configure ... */ +#ifndef ENOTSUP +#define ENOTSUP EOPNOTSUPP +#endif struct _SMBCSRV { @@ -46,12 +105,28 @@ struct _SMBCFILE { }; -struct smbc_internal_data { +/* + * Context structure + */ +struct _SMBCCTX { - /* - * Is this handle initialized ? - */ - bool _initialized; + /* True when this handle is initialized */ + bool initialized; + + /* Netbios name used for making connections */ + char * netbios_name; + + /* Workgroup used for making connections */ + char * workgroup; + + /* Username used for making connections */ + char * user; + + /* Debug level */ + int debug; + + /* Connection timeout value */ + int timeout; /* dirent pointer location * @@ -64,22 +139,22 @@ struct smbc_internal_data { * According to , 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 @@ -88,33 +163,456 @@ 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; - - /* - * 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; + smbc_share_mode share_mode; /* * 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; + int smb_encryption_level; + + /* + * 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. + */ + bool 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. + */ + bool one_share_per_server; + + /* Kerberos-related flags */ + bool use_kerberos; + bool fallback_after_kerberos; + + /* Don't try to do automatic anonymous login */ + bool no_auto_anonymous_login; + + /* Server-related functions */ + struct + { + smbc_get_auth_data_fn get_auth_data_fn; + smbc_check_server_fn check_server_fn; + smbc_remove_unused_server_fn remove_unused_server_fn; + } server; + + /* Cache-related functions */ + struct + { + struct smbc_server_cache * server_cache_data; + smbc_add_cached_srv_fn add_cached_server_fn; + smbc_get_cached_srv_fn get_cached_server_fn; + smbc_remove_cached_srv_fn remove_cached_server_fn; + smbc_purge_cached_srv_fn purge_cached_server_fn; + } cache; + + /* POSIX emulation functions */ + struct + { + smbc_open_fn open_fn; + smbc_creat_fn creat_fn; + smbc_read_fn read_fn; + smbc_write_fn write_fn; + smbc_unlink_fn unlink_fn; + smbc_rename_fn rename_fn; + smbc_lseek_fn lseek_fn; + smbc_ftruncate_fn ftruncate_fn; + smbc_stat_fn stat_fn; + smbc_fstat_fn fstat_fn; + smbc_close_fn close_fn; + smbc_opendir_fn opendir_fn; + smbc_closedir_fn closedir_fn; + smbc_readdir_fn readdir_fn; + smbc_getdents_fn getdents_fn; + smbc_mkdir_fn mkdir_fn; + smbc_rmdir_fn rmdir_fn; + smbc_telldir_fn telldir_fn; + smbc_lseekdir_fn lseekdir_fn; + smbc_fstatdir_fn fstatdir_fn; + smbc_chmod_fn chmod_fn; + smbc_utimes_fn utimes_fn; + smbc_setxattr_fn setxattr_fn; + smbc_getxattr_fn getxattr_fn; + smbc_removexattr_fn removexattr_fn; + smbc_listxattr_fn listxattr_fn; + } posix_emu; + + /* Printing-related functions */ + struct + { + smbc_print_file_fn print_file_fn; + smbc_open_print_job_fn open_print_job_fn; + smbc_list_print_jobs_fn list_print_jobs_fn; + smbc_unlink_print_job_fn unlink_print_job_fn; + } printing; + +#if 0 /* not yet */ + /* SMB high-level functions */ + struct + { + } smb; + +#endif }; +/* Functions in libsmb_cache.c */ +int +SMBC_add_cached_server(SMBCCTX * context, + SMBCSRV * newsrv, + const char * server, + const char * share, + const char * workgroup, + const char * username); + +SMBCSRV * +SMBC_get_cached_server(SMBCCTX * context, + const char * server, + const char * share, + const char * workgroup, + const char * user); + +int +SMBC_remove_cached_server(SMBCCTX * context, + SMBCSRV * server); + +int +SMBC_purge_cached_servers(SMBCCTX * context); + + +/* Functions in libsmb_dir.c */ +int +SMBC_check_options(char *server, + char *share, + char *path, + char *options); + +SMBCFILE * +SMBC_opendir_ctx(SMBCCTX *context, + const char *fname); + +int +SMBC_closedir_ctx(SMBCCTX *context, + SMBCFILE *dir); + +struct smbc_dirent * +SMBC_readdir_ctx(SMBCCTX *context, + SMBCFILE *dir); + +int +SMBC_getdents_ctx(SMBCCTX *context, + SMBCFILE *dir, + struct smbc_dirent *dirp, + int count); + +int +SMBC_mkdir_ctx(SMBCCTX *context, + const char *fname, + mode_t mode); + +int +SMBC_rmdir_ctx(SMBCCTX *context, + const char *fname); + +off_t +SMBC_telldir_ctx(SMBCCTX *context, + SMBCFILE *dir); + +int +SMBC_lseekdir_ctx(SMBCCTX *context, + SMBCFILE *dir, + off_t offset); + +int +SMBC_fstatdir_ctx(SMBCCTX *context, + SMBCFILE *dir, + struct stat *st); + +int +SMBC_chmod_ctx(SMBCCTX *context, + const char *fname, + mode_t newmode); + +int +SMBC_utimes_ctx(SMBCCTX *context, + const char *fname, + struct timeval *tbuf); + +int +SMBC_unlink_ctx(SMBCCTX *context, + const char *fname); + +int +SMBC_rename_ctx(SMBCCTX *ocontext, + const char *oname, + SMBCCTX *ncontext, + const char *nname); + + +/* Functions in libsmb_file.c */ +SMBCFILE * +SMBC_open_ctx(SMBCCTX *context, + const char *fname, + int flags, + mode_t mode); + +SMBCFILE * +SMBC_creat_ctx(SMBCCTX *context, + const char *path, + mode_t mode); + +ssize_t +SMBC_read_ctx(SMBCCTX *context, + SMBCFILE *file, + void *buf, + size_t count); + +ssize_t +SMBC_write_ctx(SMBCCTX *context, + SMBCFILE *file, + void *buf, + size_t count); + +int +SMBC_close_ctx(SMBCCTX *context, + SMBCFILE *file); + +bool +SMBC_getatr(SMBCCTX * context, + SMBCSRV *srv, + char *path, + uint16 *mode, + SMB_OFF_T *size, + struct timespec *create_time_ts, + struct timespec *access_time_ts, + struct timespec *write_time_ts, + struct timespec *change_time_ts, + SMB_INO_T *ino); + +bool +SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, + time_t create_time, + time_t access_time, + time_t write_time, + time_t change_time, + uint16 mode); + +off_t +SMBC_lseek_ctx(SMBCCTX *context, + SMBCFILE *file, + off_t offset, + int whence); + +int +SMBC_ftruncate_ctx(SMBCCTX *context, + SMBCFILE *file, + off_t length); + + +/* Functions in libsmb_misc.c */ +int +SMBC_dlist_contains(SMBCFILE * list, SMBCFILE *p); + +int +SMBC_errno(SMBCCTX *context, + struct cli_state *c); + + +/* Functions in libsmb_path.c */ +int +SMBC_urldecode(char *dest, + char *src, + size_t max_dest_len); + +int +SMBC_urlencode(char *dest, + char *src, + int max_dest_len); + +int +SMBC_parse_path(TALLOC_CTX *ctx, + SMBCCTX *context, + const char *fname, + char **pp_workgroup, + char **pp_server, + char **pp_share, + char **pp_path, + char **pp_user, + char **pp_password, + char **pp_options); + + +/* Functions in libsmb_printjob.c */ +SMBCFILE * +SMBC_open_print_job_ctx(SMBCCTX *context, + const char *fname); + +int +SMBC_print_file_ctx(SMBCCTX *c_file, + const char *fname, + SMBCCTX *c_print, + const char *printq); + +int +SMBC_list_print_jobs_ctx(SMBCCTX *context, + const char *fname, + smbc_list_print_job_fn fn); + +int +SMBC_unlink_print_job_ctx(SMBCCTX *context, + const char *fname, + int id); + + +/* Functions in libsmb_server.c */ +int +SMBC_check_server(SMBCCTX * context, + SMBCSRV * server); + +int +SMBC_remove_unused_server(SMBCCTX * context, + SMBCSRV * srv); + +void +SMBC_call_auth_fn(TALLOC_CTX *ctx, + SMBCCTX *context, + const char *server, + const char *share, + char **pp_workgroup, + char **pp_username, + char **pp_password); + +void +SMBC_get_auth_data(const char *server, const char *share, + char *workgroup_buf, int workgroup_buf_len, + char *username_buf, int username_buf_len, + char *password_buf, int password_buf_len); + +SMBCSRV * +SMBC_find_server(TALLOC_CTX *ctx, + SMBCCTX *context, + const char *server, + const char *share, + char **pp_workgroup, + char **pp_username, + char **pp_password); + +SMBCSRV * +SMBC_server(TALLOC_CTX *ctx, + SMBCCTX *context, + bool connect_if_not_found, + const char *server, + const char *share, + char **pp_workgroup, + char **pp_username, + char **pp_password); + +SMBCSRV * +SMBC_attr_server(TALLOC_CTX *ctx, + SMBCCTX *context, + const char *server, + const char *share, + char **pp_workgroup, + char **pp_username, + char **pp_password); + + +/* Functions in libsmb_stat.c */ +int +SMBC_stat_ctx(SMBCCTX *context, + const char *fname, + struct stat *st); + +int +SMBC_fstat_ctx(SMBCCTX *context, + SMBCFILE *file, + struct stat *st); + + +/* Functions in libsmb_xattr.c */ +int +SMBC_setxattr_ctx(SMBCCTX *context, + const char *fname, + const char *name, + const void *value, + size_t size, + int flags); + +int +SMBC_getxattr_ctx(SMBCCTX *context, + const char *fname, + const char *name, + const void *value, + size_t size); + +int +SMBC_removexattr_ctx(SMBCCTX *context, + const char *fname, + const char *name); + +int +SMBC_listxattr_ctx(SMBCCTX *context, + const char *fname, + char *list, + size_t size); + #endif diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index 64afc09499..a998bcee69 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -386,221 +386,310 @@ typedef int (*smbc_remove_cached_srv_fn)(SMBCCTX * c, SMBCSRV *srv); * @return 0 when found and removed. 1 on failure. * */ -typedef int (*smbc_purge_cached_fn) (SMBCCTX * c); +typedef int (*smbc_purge_cached_srv_fn) (SMBCCTX * c); -/**@ingroup structure - * Structure that contains a client context information - * This structure is know as SMBCCTX +/** Get the debug level */ +int smbc_getDebug(SMBCCTX *c); + +/** Set the debug level */ +void smbc_setDebug(SMBCCTX *c, int debug); + +/** Get the netbios name used for making connections */ +char * smbc_getNetbiosName(SMBCCTX *c); + +/** Set the netbios name used for making connections */ +void smbc_setNetbiosName(SMBCCTX *c, char * netbios_name); + +/** Get the workgroup used for making connections */ +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); + +/** Set the username used for making connections */ +void smbc_setUser(SMBCCTX *c, char * user); + +/** + * Get the timeout used for waiting on connections and response data + * (in milliseconds) */ -struct _SMBCCTX { - /** debug level - */ - int debug; - - /** netbios name used for making connections - */ - char * netbios_name; +int smbc_getTimeout(SMBCCTX *c); - /** workgroup name used for making connections - */ - char * workgroup; +/** + * Set the timeout used for waiting on connections and response data + * (in milliseconds) + */ +void smbc_setTimeout(SMBCCTX *c, int timeout); - /** username used for making connections - */ - char * user; +/** Get the function for obtaining authentication data */ +smbc_get_auth_data_fn smbc_getFunctionAuthData(SMBCCTX *c); - /** timeout used for waiting on connections / response data (in milliseconds) - */ - int timeout; - - /** callable functions for files: - * For usage and return values see the smbc_* functions - */ - SMBCFILE * (*open) (SMBCCTX *c, const char *fname, int flags, mode_t mode); - SMBCFILE * (*creat) (SMBCCTX *c, const char *path, mode_t mode); - ssize_t (*read) (SMBCCTX *c, SMBCFILE *file, void *buf, size_t count); - ssize_t (*write) (SMBCCTX *c, SMBCFILE *file, void *buf, size_t count); - int (*unlink) (SMBCCTX *c, const char *fname); - int (*rename) (SMBCCTX *ocontext, const char *oname, - SMBCCTX *ncontext, const char *nname); - off_t (*lseek) (SMBCCTX *c, SMBCFILE * file, off_t offset, int whence); - int (*stat) (SMBCCTX *c, const char *fname, struct stat *st); - int (*fstat) (SMBCCTX *c, SMBCFILE *file, struct stat *st); - /* ftruncate added near _internal for ABI compatibility */ - - int (*close_fn) (SMBCCTX *c, SMBCFILE *file); - - /** callable functions for dirs - */ - SMBCFILE * (*opendir) (SMBCCTX *c, const char *fname); - int (*closedir)(SMBCCTX *c, SMBCFILE *dir); - struct smbc_dirent * (*readdir)(SMBCCTX *c, SMBCFILE *dir); - int (*getdents)(SMBCCTX *c, SMBCFILE *dir, - struct smbc_dirent *dirp, int count); - int (*mkdir) (SMBCCTX *c, const char *fname, mode_t mode); - int (*rmdir) (SMBCCTX *c, const char *fname); - off_t (*telldir) (SMBCCTX *c, SMBCFILE *dir); - int (*lseekdir)(SMBCCTX *c, SMBCFILE *dir, off_t offset); - int (*fstatdir)(SMBCCTX *c, SMBCFILE *dir, struct stat *st); - int (*chmod)(SMBCCTX *c, const char *fname, mode_t mode); - int (*utimes)(SMBCCTX *c, - const char *fname, struct timeval *tbuf); - int (*setxattr)(SMBCCTX *context, - const char *fname, - const char *name, - const void *value, - size_t size, - int flags); - int (*getxattr)(SMBCCTX *context, - const char *fname, - const char *name, - const void *value, - size_t size); - int (*removexattr)(SMBCCTX *context, - const char *fname, - const char *name); - int (*listxattr)(SMBCCTX *context, +/** Set the function for obtaining authentication data */ +void smbc_setFunctionAuthData(SMBCCTX *c, smbc_get_auth_data_fn f); + +/** Get the function for checking if a server is still good */ +smbc_check_server_fn smbc_getFunctionCheckServer(SMBCCTX *c); + +/** Set the function for checking if a server is still good */ +void smbc_setFunctionCheckServer(SMBCCTX *c, smbc_check_server_fn f); + +/** Get the function for removing a server if unused */ +smbc_remove_unused_server_fn smbc_getFunctionRemoveUnusedServer(SMBCCTX *c); + +/** Set the function for removing a server if unused */ +void smbc_setFunctionRemoveUnusedServer(SMBCCTX *c, + smbc_remove_unused_server_fn f); + +/** Get the function for adding a cached server */ +smbc_add_cached_srv_fn smbc_getFunctionAddCachedServer(SMBCCTX *c); + +/** Set the function for adding a cached server */ +void smbc_setFunctionAddCachedServer(SMBCCTX *c, smbc_add_cached_srv_fn f); + +/** Get the function for server cache lookup */ +smbc_get_cached_srv_fn smbc_getFunctionGetCachedServer(SMBCCTX *c); + +/** Set the function for server cache lookup */ +void smbc_setFunctionGetCachedServer(SMBCCTX *c, smbc_get_cached_srv_fn f); + +/** Get the function for server cache removal */ +smbc_remove_cached_srv_fn smbc_getFunctionRemoveCachedServer(SMBCCTX *c); + +/** Set the function for server cache removal */ +void smbc_setFunctionRemoveCachedServer(SMBCCTX *c, + smbc_remove_cached_srv_fn f); + +/** + * Get the function for server cache purging. This function tries to + * remove all cached servers (e.g. on disconnect) + */ +smbc_purge_cached_srv_fn smbc_getFunctionPurgeCachedServers(SMBCCTX *c); + +/** + * Set the function for server cache purging. This function tries to + * remove all cached servers (e.g. on disconnect) + */ +void smbc_setFunctionPurgeCachedServers(SMBCCTX *c, + smbc_purge_cached_srv_fn f); + +/** Get the function to store private data of the server cache */ +struct smbc_server_cache * smbc_getServerCacheData(SMBCCTX *c); + +/** Set the function to store private data of the server cache */ +void smbc_setServerCacheData(SMBCCTX *c, struct smbc_server_cache * cache); + + +/** + * Callable functions for files. + */ + +typedef SMBCFILE * (*smbc_open_fn)(SMBCCTX *c, + const char *fname, + int flags, + mode_t mode); +smbc_open_fn smbc_getFunctionOpen(SMBCCTX *c); +void smbc_setFunctionOpen(SMBCCTX *c, smbc_open_fn f); + +typedef SMBCFILE * (*smbc_creat_fn)(SMBCCTX *c, + const char *path, + mode_t mode); +smbc_creat_fn smbc_getFunctionCreat(SMBCCTX *c); +void smbc_setFunctionCreat(SMBCCTX *c, smbc_creat_fn); + +typedef ssize_t (*smbc_read_fn)(SMBCCTX *c, + SMBCFILE *file, + void *buf, + size_t count); +smbc_read_fn smbc_getFunctionRead(SMBCCTX *c); +void smbc_setFunctionRead(SMBCCTX *c, smbc_read_fn f); + +typedef ssize_t (*smbc_write_fn)(SMBCCTX *c, + SMBCFILE *file, + void *buf, + size_t count); +smbc_write_fn smbc_getFunctionWrite(SMBCCTX *c); +void smbc_setFunctionWrite(SMBCCTX *c, smbc_write_fn f); + +typedef int (*smbc_unlink_fn)(SMBCCTX *c, + const char *fname); +smbc_unlink_fn smbc_getFunctionUnlink(SMBCCTX *c); +void smbc_setFunctionUnlink(SMBCCTX *c, smbc_unlink_fn f); + +typedef int (*smbc_rename_fn)(SMBCCTX *ocontext, + const char *oname, + SMBCCTX *ncontext, + const char *nname); +smbc_rename_fn smbc_getFunctionRename(SMBCCTX *c); +void smbc_setFunctionRename(SMBCCTX *c, smbc_rename_fn f); + +typedef off_t (*smbc_lseek_fn)(SMBCCTX *c, + SMBCFILE * file, + off_t offset, + int whence); +smbc_lseek_fn smbc_getFunctionLseek(SMBCCTX *c); +void smbc_setFunctionLseek(SMBCCTX *c, smbc_lseek_fn f); + +typedef int (*smbc_stat_fn)(SMBCCTX *c, + const char *fname, + struct stat *st); +smbc_stat_fn smbc_getFunctionStat(SMBCCTX *c); +void smbc_setFunctionStat(SMBCCTX *c, smbc_stat_fn f); + +typedef int (*smbc_fstat_fn)(SMBCCTX *c, + SMBCFILE *file, + struct stat *st); +smbc_fstat_fn smbc_getFunctionFstat(SMBCCTX *c); +void smbc_setFunctionFstat(SMBCCTX *c, smbc_fstat_fn f); + +typedef int (*smbc_ftruncate_fn)(SMBCCTX *c, + SMBCFILE *f, + off_t size); +smbc_ftruncate_fn smbc_getFunctionFtruncate(SMBCCTX *c); +void smbc_setFunctionFtruncate(SMBCCTX *c, smbc_ftruncate_fn f); + +typedef int (*smbc_close_fn)(SMBCCTX *c, + SMBCFILE *file); +smbc_close_fn smbc_getFunctionClose(SMBCCTX *c); +void smbc_setFunctionClose(SMBCCTX *c, smbc_close_fn f); + + +/** + * Callable functions for directories. + */ + +typedef SMBCFILE * (*smbc_opendir_fn)(SMBCCTX *c, + const char *fname); +smbc_opendir_fn smbc_getFunctionOpendir(SMBCCTX *c); +void smbc_setFunctionOpendir(SMBCCTX *c, smbc_opendir_fn f); + +typedef int (*smbc_closedir_fn)(SMBCCTX *c, + SMBCFILE *dir); +smbc_closedir_fn smbc_getFunctionClosedir(SMBCCTX *c); +void smbc_setFunctionClosedir(SMBCCTX *c, smbc_closedir_fn f); + +typedef struct smbc_dirent * (*smbc_readdir_fn)(SMBCCTX *c, + SMBCFILE *dir); +smbc_readdir_fn smbc_getFunctionReaddir(SMBCCTX *c); +void smbc_setFunctionReaddir(SMBCCTX *c, smbc_readdir_fn f); + +typedef int (*smbc_getdents_fn)(SMBCCTX *c, + SMBCFILE *dir, + struct smbc_dirent *dirp, + int count); +smbc_getdents_fn smbc_getFunctionGetdents(SMBCCTX *c); +void smbc_setFunctionGetdents(SMBCCTX *c, smbc_getdents_fn f); + +typedef int (*smbc_mkdir_fn)(SMBCCTX *c, + const char *fname, + mode_t mode); +smbc_mkdir_fn smbc_getFunctionMkdir(SMBCCTX *c); +void smbc_setFunctionMkdir(SMBCCTX *c, smbc_mkdir_fn f); + +typedef int (*smbc_rmdir_fn)(SMBCCTX *c, + const char *fname); +smbc_rmdir_fn smbc_getFunctionRmdir(SMBCCTX *c); +void smbc_setFunctionRmdir(SMBCCTX *c, smbc_rmdir_fn f); + +typedef off_t (*smbc_telldir_fn)(SMBCCTX *c, + SMBCFILE *dir); +smbc_telldir_fn smbc_getFunctionTelldir(SMBCCTX *c); +void smbc_setFunctionTelldir(SMBCCTX *c, smbc_telldir_fn f); + +typedef int (*smbc_lseekdir_fn)(SMBCCTX *c, + SMBCFILE *dir, + off_t offset); +smbc_lseekdir_fn smbc_getFunctionLseekdir(SMBCCTX *c); +void smbc_setFunctionLseekdir(SMBCCTX *c, smbc_lseekdir_fn f); + +typedef int (*smbc_fstatdir_fn)(SMBCCTX *c, + SMBCFILE *dir, + struct stat *st); +smbc_fstatdir_fn smbc_getFunctionFstatdir(SMBCCTX *c); +void smbc_setFunctionFstatdir(SMBCCTX *c, smbc_fstatdir_fn f); + + +/** + * Callable functions applicable to both files and directories. + */ + +typedef int (*smbc_chmod_fn)(SMBCCTX *c, + const char *fname, + mode_t mode); +smbc_chmod_fn smbc_getFunctionChmod(SMBCCTX *c); +void smbc_setFunctionChmod(SMBCCTX *c, smbc_chmod_fn f); + +typedef int (*smbc_utimes_fn)(SMBCCTX *c, + const char *fname, + struct timeval *tbuf); +smbc_utimes_fn smbc_getFunctionUtimes(SMBCCTX *c); +void smbc_setFunctionUtimes(SMBCCTX *c, smbc_utimes_fn f); + +typedef int (*smbc_setxattr_fn)(SMBCCTX *context, + const char *fname, + const char *name, + const void *value, + size_t size, + int flags); +smbc_setxattr_fn smbc_getFunctionSetxattr(SMBCCTX *c); +void smbc_setFunctionSetxattr(SMBCCTX *c, smbc_setxattr_fn f); + +typedef int (*smbc_getxattr_fn)(SMBCCTX *context, const char *fname, - char *list, + const char *name, + const void *value, size_t size); +smbc_getxattr_fn smbc_getFunctionGetxattr(SMBCCTX *c); +void smbc_setFunctionGetxattr(SMBCCTX *c, smbc_getxattr_fn f); - /** callable functions for printing - */ - int (*print_file)(SMBCCTX *c_file, const char *fname, - SMBCCTX *c_print, const char *printq); - SMBCFILE * (*open_print_job)(SMBCCTX *c, const char *fname); - int (*list_print_jobs)(SMBCCTX *c, const char *fname, smbc_list_print_job_fn fn); - int (*unlink_print_job)(SMBCCTX *c, const char *fname, int id); - - - /* - ** Callbacks - * These callbacks _always_ have to be initialized because they will - * not be checked at dereference for increased speed. - */ - struct _smbc_callbacks { - /** authentication function callback: called upon auth requests - */ - smbc_get_auth_data_fn auth_fn; - - /** check if a server is still good - */ - smbc_check_server_fn check_server_fn; - - /** remove a server if unused - */ - smbc_remove_unused_server_fn remove_unused_server_fn; - - /** Cache subsystem - * For an example cache system see samba/source/libsmb/libsmb_cache.c - * Cache subsystem functions follow. - */ - - /** server cache addition - */ - smbc_add_cached_srv_fn add_cached_srv_fn; - - /** server cache lookup - */ - smbc_get_cached_srv_fn get_cached_srv_fn; - - /** server cache removal - */ - smbc_remove_cached_srv_fn remove_cached_srv_fn; - - /** server cache purging, try to remove all cached servers (disconnect) - */ - smbc_purge_cached_fn purge_cached_fn; - } callbacks; +typedef int (*smbc_removexattr_fn)(SMBCCTX *context, + const char *fname, + const char *name); +smbc_removexattr_fn smbc_getFunctionRemovexattr(SMBCCTX *c); +void smbc_setFunctionRemovexattr(SMBCCTX *c, smbc_removexattr_fn f); +typedef int (*smbc_listxattr_fn)(SMBCCTX *context, + const char *fname, + char *list, + size_t size); +smbc_listxattr_fn smbc_getFunctionListxattr(SMBCCTX *c); +void smbc_setFunctionListxattr(SMBCCTX *c, smbc_listxattr_fn f); - /** Space to store private data of the server cache. - */ - struct smbc_server_cache * server_cache; - - int flags; - - /** user options selections that apply to this session - * - * 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. - */ - 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; - - /* Add additional functions here for ABI backward compatibility */ - int (*ftruncate)(SMBCCTX *c, SMBCFILE *f, off_t size); - - /** INTERNAL DATA - * do _NOT_ touch this from your program ! - */ - struct smbc_internal_data * internal; -}; -/* 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) /* don't try to do automatic anon login */ +/** + * Callable functions related to printing + */ + +typedef int (*smbc_print_file_fn)(SMBCCTX *c_file, + const char *fname, + SMBCCTX *c_print, + const char *printq); +smbc_print_file_fn smbc_getFunctionPrintFile(SMBCCTX *c); +void smbc_setFunctionPrintFile(SMBCCTX *c, smbc_print_file_fn f); + +typedef SMBCFILE * (*smbc_open_print_job_fn)(SMBCCTX *c, + const char *fname); +smbc_open_print_job_fn smbc_getFunctionOpenPrintJob(SMBCCTX *c); +void smbc_setFunctionOpenPrintJob(SMBCCTX *c, + smbc_open_print_job_fn f); + +typedef int (*smbc_list_print_jobs_fn)(SMBCCTX *c, + const char *fname, + smbc_list_print_job_fn fn); +smbc_list_print_jobs_fn smbc_getFunctionListPrintJobs(SMBCCTX *c); +void smbc_setFunctionListPrintJobs(SMBCCTX *c, + smbc_list_print_jobs_fn f); + +typedef int (*smbc_unlink_print_job_fn)(SMBCCTX *c, + const char *fname, + int id); +smbc_unlink_print_job_fn smbc_getFunctionUnlinkPrintJob(SMBCCTX *c); +void smbc_setFunctionUnlinkPrintJob(SMBCCTX *c, + smbc_unlink_print_job_fn f); + /**@ingroup misc * Create a new SBMCCTX (a context). diff --git a/source3/libsmb/libsmb_cache.c b/source3/libsmb/libsmb_cache.c index b98df024fa..e0571fa9fe 100644 --- a/source3/libsmb/libsmb_cache.c +++ b/source3/libsmb/libsmb_cache.c @@ -22,11 +22,8 @@ */ #include "includes.h" - -#include "include/libsmbclient.h" -#include "../include/libsmb_internal.h" - -int smbc_default_cache_functions(SMBCCTX * context); +#include "libsmbclient.h" +#include "libsmb_internal.h" /* * Structure we use if internal caching mechanism is used @@ -48,9 +45,13 @@ struct smbc_server_cache { * Add a new connection to the server cache. * This function is only used if the external cache is not enabled */ -static int smbc_add_cached_server(SMBCCTX * context, SMBCSRV * newsrv, - const char * server, const char * share, - const char * workgroup, const char * username) +int +SMBC_add_cached_server(SMBCCTX * context, + SMBCSRV * newsrv, + const char * server, + const char * share, + const char * workgroup, + const char * username) { struct smbc_server_cache * srvcache = NULL; @@ -88,7 +89,7 @@ static int smbc_add_cached_server(SMBCCTX * context, SMBCSRV * newsrv, goto failed; } - DLIST_ADD((context->server_cache), srvcache); + DLIST_ADD((context->cache.server_cache_data), srvcache); return 0; failed: @@ -108,13 +109,17 @@ static int smbc_add_cached_server(SMBCCTX * context, SMBCSRV * newsrv, * returns server handle on success, NULL on error (not found) * This function is only used if the external cache is not enabled */ -static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, const char * server, - const char * share, const char * workgroup, const char * user) +SMBCSRV * +SMBC_get_cached_server(SMBCCTX * context, + const char * server, + const char * share, + const char * workgroup, + const char * user) { struct smbc_server_cache * srv = NULL; /* Search the cache lines */ - for (srv=((struct smbc_server_cache *)context->server_cache);srv;srv=srv->next) { + for (srv = context->cache.server_cache_data; srv; srv = srv->next) { if (strcmp(server,srv->server_name) == 0 && strcmp(workgroup,srv->workgroup) == 0 && @@ -146,7 +151,7 @@ static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, const char * server, * a connection to the server (other than the * attribute server connection) is cool. */ - if (context->options.one_share_per_server) { + if (context->one_share_per_server) { /* * The currently connected share name * doesn't match the requested share, so @@ -156,7 +161,7 @@ static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, const char * server, /* Sigh. Couldn't disconnect. */ cli_shutdown(srv->server->cli); srv->server->cli = NULL; - context->callbacks.remove_cached_srv_fn(context, srv->server); + context->cache.remove_cached_server_fn(context, srv->server); continue; } @@ -171,7 +176,7 @@ static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, const char * server, /* Out of memory. */ cli_shutdown(srv->server->cli); srv->server->cli = NULL; - context->callbacks.remove_cached_srv_fn(context, srv->server); + context->cache.remove_cached_server_fn(context, srv->server); continue; } @@ -190,15 +195,17 @@ static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, const char * server, * returns 0 on success * This function is only used if the external cache is not enabled */ -static int smbc_remove_cached_server(SMBCCTX * context, SMBCSRV * server) +int +SMBC_remove_cached_server(SMBCCTX * context, + SMBCSRV * server) { struct smbc_server_cache * srv = NULL; - for (srv=((struct smbc_server_cache *)context->server_cache);srv;srv=srv->next) { + for (srv = context->cache.server_cache_data; srv; srv = srv->next) { if (server == srv->server) { /* remove this sucker */ - DLIST_REMOVE(context->server_cache, srv); + DLIST_REMOVE(context->cache.server_cache_data, srv); SAFE_FREE(srv->server_name); SAFE_FREE(srv->share_name); SAFE_FREE(srv->workgroup); @@ -216,40 +223,23 @@ static int smbc_remove_cached_server(SMBCCTX * context, SMBCSRV * server) * Try to remove all the servers in cache * returns 1 on failure and 0 if all servers could be removed. */ -static int smbc_purge_cached(SMBCCTX * context) +int +SMBC_purge_cached_servers(SMBCCTX * context) { struct smbc_server_cache * srv; struct smbc_server_cache * next; int could_not_purge_all = 0; - for (srv = ((struct smbc_server_cache *) context->server_cache), - next = (srv ? srv->next :NULL); + for (srv = context->cache.server_cache_data, + next = (srv ? srv->next :NULL); srv; - srv = next, next = (srv ? srv->next : NULL)) { + srv = next, + next = (srv ? srv->next : NULL)) { - if (smbc_remove_unused_server(context, srv->server)) { + if (SMBC_remove_unused_server(context, srv->server)) { /* could not be removed */ could_not_purge_all = 1; } } return could_not_purge_all; } - - - -/* - * This functions initializes all server-cache related functions - * to the default (internal) system. - * - * We use this to make the rest of the cache system static. - */ - -int smbc_default_cache_functions(SMBCCTX * context) -{ - context->callbacks.add_cached_srv_fn = smbc_add_cached_server; - context->callbacks.get_cached_srv_fn = smbc_get_cached_server; - context->callbacks.remove_cached_srv_fn = smbc_remove_cached_server; - context->callbacks.purge_cached_fn = smbc_purge_cached; - - return 0; -} diff --git a/source3/libsmb/libsmb_compat.c b/source3/libsmb/libsmb_compat.c index 6042464fd2..7a0536a92d 100644 --- a/source3/libsmb/libsmb_compat.c +++ b/source3/libsmb/libsmb_compat.c @@ -5,7 +5,7 @@ Copyright (C) Richard Sharpe 2000 Copyright (C) John Terpstra 2000 Copyright (C) Tom Jansen (Ninja ISD) 2002 - Copyright (C) Derrell Lipman 2003 + Copyright (C) Derrell Lipman 2003, 2008 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 @@ -23,8 +23,7 @@ #include "includes.h" - -#include "include/libsmb_internal.h" +#include "libsmb_internal.h" struct smbc_compat_fdlist { SMBCFILE * file; @@ -39,7 +38,8 @@ static struct smbc_compat_fdlist * smbc_compat_fd_in_use = NULL; static struct smbc_compat_fdlist * smbc_compat_fd_avail = NULL; /* Find an fd and return the SMBCFILE * or NULL on failure */ -static SMBCFILE * find_fd(int fd) +static SMBCFILE * +find_fd(int fd) { struct smbc_compat_fdlist * f = smbc_compat_fd_in_use; while (f) { @@ -51,7 +51,8 @@ static SMBCFILE * find_fd(int fd) } /* Add an fd, returns 0 on success, -1 on error with errno set */ -static int add_fd(SMBCFILE * file) +static int +add_fd(SMBCFILE * file) { struct smbc_compat_fdlist * f = smbc_compat_fd_avail; @@ -90,7 +91,8 @@ static int add_fd(SMBCFILE * file) /* Delete an fd, returns 0 on success */ -static int del_fd(int fd) +static int +del_fd(int fd) { struct smbc_compat_fdlist * f = smbc_compat_fd_in_use; @@ -112,15 +114,17 @@ static int del_fd(int fd) -int smbc_init(smbc_get_auth_data_fn fn, int debug) +int +smbc_init(smbc_get_auth_data_fn fn, + int debug) { if (!smbc_compat_initialized) { statcont = smbc_new_context(); if (!statcont) return -1; - statcont->debug = debug; - statcont->callbacks.auth_fn = fn; + smbc_setDebug(statcont, debug); + smbc_setFunctionAuthData(statcont, fn); if (!smbc_init_context(statcont)) { smbc_free_context(statcont, False); @@ -135,7 +139,8 @@ int smbc_init(smbc_get_auth_data_fn fn, int debug) } -SMBCCTX *smbc_set_context(SMBCCTX * context) +SMBCCTX * +smbc_set_context(SMBCCTX * context) { SMBCCTX *old_context = statcont; @@ -151,307 +156,387 @@ SMBCCTX *smbc_set_context(SMBCCTX * context) } -int smbc_open(const char *furl, int flags, mode_t mode) +int +smbc_open(const char *furl, + int flags, + mode_t mode) { SMBCFILE * file; int fd; - file = (statcont->open)(statcont, furl, flags, mode); + file = smbc_getFunctionOpen(statcont)(statcont, furl, flags, mode); if (!file) return -1; fd = add_fd(file); if (fd == -1) - (statcont->close_fn)(statcont, file); + smbc_getFunctionClose(statcont)(statcont, file); return fd; } -int smbc_creat(const char *furl, mode_t mode) +int +smbc_creat(const char *furl, + mode_t mode) { SMBCFILE * file; int fd; - file = (statcont->creat)(statcont, furl, mode); + 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 */ - (statcont->close_fn)(statcont, file); - (statcont->unlink)(statcont, furl); + smbc_getFunctionClose(statcont)(statcont, file); + smbc_getFunctionUnlink(statcont)(statcont, furl); } return fd; } -ssize_t smbc_read(int fd, void *buf, size_t bufsize) +ssize_t +smbc_read(int fd, + void *buf, + size_t bufsize) { SMBCFILE * file = find_fd(fd); - return (statcont->read)(statcont, file, buf, bufsize); + return smbc_getFunctionRead(statcont)(statcont, file, buf, bufsize); } -ssize_t smbc_write(int fd, void *buf, size_t bufsize) +ssize_t +smbc_write(int fd, + void *buf, + size_t bufsize) { SMBCFILE * file = find_fd(fd); - return (statcont->write)(statcont, file, buf, bufsize); + return smbc_getFunctionWrite(statcont)(statcont, file, buf, bufsize); } -off_t smbc_lseek(int fd, off_t offset, int whence) +off_t +smbc_lseek(int fd, + off_t offset, + int whence) { SMBCFILE * file = find_fd(fd); - return (statcont->lseek)(statcont, file, offset, whence); + return smbc_getFunctionLseek(statcont)(statcont, file, offset, whence); } -int smbc_close(int fd) +int +smbc_close(int fd) { SMBCFILE * file = find_fd(fd); del_fd(fd); - return (statcont->close_fn)(statcont, file); + return smbc_getFunctionClose(statcont)(statcont, file); } -int smbc_unlink(const char *fname) +int +smbc_unlink(const char *fname) { - return (statcont->unlink)(statcont, fname); + return smbc_getFunctionUnlink(statcont)(statcont, fname); } -int smbc_rename(const char *ourl, const char *nurl) +int +smbc_rename(const char *ourl, + const char *nurl) { - return (statcont->rename)(statcont, ourl, statcont, nurl); + return smbc_getFunctionRename(statcont)(statcont, ourl, + statcont, nurl); } -int smbc_opendir(const char *durl) +int +smbc_opendir(const char *durl) { SMBCFILE * file; int fd; - file = (statcont->opendir)(statcont, durl); + file = smbc_getFunctionOpendir(statcont)(statcont, durl); if (!file) return -1; fd = add_fd(file); if (fd == -1) - (statcont->closedir)(statcont, file); + smbc_getFunctionClosedir(statcont)(statcont, file); return fd; } -int smbc_closedir(int dh) +int +smbc_closedir(int dh) { SMBCFILE * file = find_fd(dh); del_fd(dh); - return (statcont->closedir)(statcont, file); + return smbc_getFunctionClosedir(statcont)(statcont, file); } -int smbc_getdents(unsigned int dh, struct smbc_dirent *dirp, int count) +int +smbc_getdents(unsigned int dh, + struct smbc_dirent *dirp, + int count) { SMBCFILE * file = find_fd(dh); - return (statcont->getdents)(statcont, file,dirp, count); + return smbc_getFunctionGetdents(statcont)(statcont, file, dirp, count); } -struct smbc_dirent* smbc_readdir(unsigned int dh) +struct smbc_dirent * +smbc_readdir(unsigned int dh) { SMBCFILE * file = find_fd(dh); - return (statcont->readdir)(statcont, file); + return smbc_getFunctionReaddir(statcont)(statcont, file); } -off_t smbc_telldir(int dh) +off_t +smbc_telldir(int dh) { SMBCFILE * file = find_fd(dh); - return (statcont->telldir)(statcont, file); + return smbc_getFunctionTelldir(statcont)(statcont, file); } -int smbc_lseekdir(int fd, off_t offset) +int +smbc_lseekdir(int fd, + off_t offset) { SMBCFILE * file = find_fd(fd); - return (statcont->lseekdir)(statcont, file, offset); + return smbc_getFunctionLseekdir(statcont)(statcont, file, offset); } -int smbc_mkdir(const char *durl, mode_t mode) +int +smbc_mkdir(const char *durl, + mode_t mode) { - return (statcont->mkdir)(statcont, durl, mode); + return smbc_getFunctionMkdir(statcont)(statcont, durl, mode); } -int smbc_rmdir(const char *durl) +int +smbc_rmdir(const char *durl) { - return (statcont->rmdir)(statcont, durl); + return smbc_getFunctionRmdir(statcont)(statcont, durl); } -int smbc_stat(const char *url, struct stat *st) +int +smbc_stat(const char *url, + struct stat *st) { - return (statcont->stat)(statcont, url, st); + return smbc_getFunctionStat(statcont)(statcont, url, st); } -int smbc_fstat(int fd, struct stat *st) +int +smbc_fstat(int fd, + struct stat *st) { SMBCFILE * file = find_fd(fd); - return (statcont->fstat)(statcont, file, st); + return smbc_getFunctionFstat(statcont)(statcont, file, st); } -int smbc_ftruncate(int fd, off_t size) +int +smbc_ftruncate(int fd, + off_t size) { SMBCFILE * file = find_fd(fd); - return (statcont->ftruncate)(statcont, file, size); + return smbc_getFunctionFtruncate(statcont)(statcont, file, size); } -int smbc_chmod(const char *url, mode_t mode) +int +smbc_chmod(const char *url, + mode_t mode) { - return (statcont->chmod)(statcont, url, mode); + return smbc_getFunctionChmod(statcont)(statcont, url, mode); } -int smbc_utimes(const char *fname, struct timeval *tbuf) +int +smbc_utimes(const char *fname, + struct timeval *tbuf) { - return (statcont->utimes)(statcont, fname, tbuf); + return smbc_getFunctionUtimes(statcont)(statcont, fname, tbuf); } #ifdef HAVE_UTIME_H -int smbc_utime(const char *fname, struct utimbuf *utbuf) +int +smbc_utime(const char *fname, + struct utimbuf *utbuf) { struct timeval tv[2]; if (utbuf == NULL) - return (statcont->utimes)(statcont, fname, 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 (statcont->utimes)(statcont, fname, tv); + return smbc_getFunctionUtimes(statcont)(statcont, fname, tv); } #endif -int smbc_setxattr(const char *fname, - const char *name, - const void *value, - size_t size, - int flags) +int +smbc_setxattr(const char *fname, + const char *name, + const void *value, + size_t size, + int flags) { - return (statcont->setxattr)(statcont, fname, name, value, size, flags); + return smbc_getFunctionSetxattr(statcont)(statcont, + fname, name, + value, size, flags); } -int smbc_lsetxattr(const char *fname, - const char *name, - const void *value, - size_t size, - int flags) +int +smbc_lsetxattr(const char *fname, + const char *name, + const void *value, + size_t size, + int flags) { - return (statcont->setxattr)(statcont, fname, name, value, size, flags); + return smbc_getFunctionSetxattr(statcont)(statcont, + fname, name, + value, size, flags); } -int smbc_fsetxattr(int fd, - const char *name, - const void *value, - size_t size, - int flags) +int +smbc_fsetxattr(int fd, + const char *name, + const void *value, + size_t size, + int flags) { SMBCFILE * file = find_fd(fd); if (file == NULL) { errno = EBADF; return -1; } - return (statcont->setxattr)(statcont, file->fname, - name, value, size, flags); + return smbc_getFunctionSetxattr(statcont)(statcont, + file->fname, name, + value, size, flags); } -int smbc_getxattr(const char *fname, - const char *name, - const void *value, - size_t size) +int +smbc_getxattr(const char *fname, + const char *name, + const void *value, + size_t size) { - return (statcont->getxattr)(statcont, fname, name, value, size); + return smbc_getFunctionGetxattr(statcont)(statcont, + fname, name, + value, size); } -int smbc_lgetxattr(const char *fname, - const char *name, - const void *value, - size_t size) +int +smbc_lgetxattr(const char *fname, + const char *name, + const void *value, + size_t size) { - return (statcont->getxattr)(statcont, fname, name, value, size); + return smbc_getFunctionGetxattr(statcont)(statcont, + fname, name, + value, size); } -int smbc_fgetxattr(int fd, - const char *name, - const void *value, - size_t size) +int +smbc_fgetxattr(int fd, + const char *name, + const void *value, + size_t size) { SMBCFILE * file = find_fd(fd); if (file == NULL) { errno = EBADF; return -1; } - return (statcont->getxattr)(statcont, file->fname, name, value, size); + return smbc_getFunctionGetxattr(statcont)(statcont, + file->fname, name, + value, size); } -int smbc_removexattr(const char *fname, - const char *name) +int +smbc_removexattr(const char *fname, + const char *name) { - return (statcont->removexattr)(statcont, fname, name); + return smbc_getFunctionRemovexattr(statcont)(statcont, fname, name); } -int smbc_lremovexattr(const char *fname, - const char *name) +int +smbc_lremovexattr(const char *fname, + const char *name) { - return (statcont->removexattr)(statcont, fname, name); + return smbc_getFunctionRemovexattr(statcont)(statcont, fname, name); } -int smbc_fremovexattr(int fd, - const char *name) +int +smbc_fremovexattr(int fd, + const char *name) { SMBCFILE * file = find_fd(fd); if (file == NULL) { errno = EBADF; return -1; } - return (statcont->removexattr)(statcont, file->fname, name); + return smbc_getFunctionRemovexattr(statcont)(statcont, + file->fname, name); } -int smbc_listxattr(const char *fname, - char *list, - size_t size) +int +smbc_listxattr(const char *fname, + char *list, + size_t size) { - return (statcont->listxattr)(statcont, fname, list, size); + return smbc_getFunctionListxattr(statcont)(statcont, + fname, list, size); } -int smbc_llistxattr(const char *fname, - char *list, - size_t size) +int +smbc_llistxattr(const char *fname, + char *list, + size_t size) { - return (statcont->listxattr)(statcont, fname, list, size); + return smbc_getFunctionListxattr(statcont)(statcont, + fname, list, size); } -int smbc_flistxattr(int fd, - char *list, - size_t size) +int +smbc_flistxattr(int fd, + char *list, + size_t size) { SMBCFILE * file = find_fd(fd); if (file == NULL) { errno = EBADF; return -1; } - return (statcont->listxattr)(statcont, file->fname, list, size); + return smbc_getFunctionListxattr(statcont)(statcont, + file->fname, list, size); } -int smbc_print_file(const char *fname, const char *printq) +int +smbc_print_file(const char *fname, + const char *printq) { - return (statcont->print_file)(statcont, fname, statcont, printq); + return smbc_getFunctionPrintFile(statcont)(statcont, fname, + statcont, printq); } -int smbc_open_print_job(const char *fname) +int +smbc_open_print_job(const char *fname) { - SMBCFILE * file = (statcont->open_print_job)(statcont, fname); + SMBCFILE * file; + + file = smbc_getFunctionOpenPrintJob(statcont)(statcont, fname); if (!file) return -1; return file->cli_fd; } -int smbc_list_print_jobs(const char *purl, smbc_list_print_job_fn fn) +int +smbc_list_print_jobs(const char *purl, + smbc_list_print_job_fn fn) { - return (statcont->list_print_jobs)(statcont, purl, fn); + return smbc_getFunctionListPrintJobs(statcont)(statcont, purl, fn); } -int smbc_unlink_print_job(const char *purl, int id) +int +smbc_unlink_print_job(const char *purl, + int id) { - return (statcont->unlink_print_job)(statcont, purl, id); + return smbc_getFunctionUnlinkPrintJob(statcont)(statcont, purl, id); } diff --git a/source3/libsmb/libsmb_context.c b/source3/libsmb/libsmb_context.c new file mode 100644 index 0000000000..1505d50a43 --- /dev/null +++ b/source3/libsmb/libsmb_context.c @@ -0,0 +1,1283 @@ +/* + Unix SMB/Netbios implementation. + SMB client library implementation + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000, 2002 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 3 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, see . +*/ + +#include "includes.h" +#include "libsmbclient.h" +#include "libsmb_internal.h" + + +/* + * Is the logging working / configfile read ? + */ +static int SMBC_initialized = 0; + + + +/* + * Get a new empty handle to fill in with your own info + */ +SMBCCTX * +smbc_new_context(void) +{ + SMBCCTX *context; + + context = SMB_MALLOC_P(SMBCCTX); + if (!context) { + errno = ENOMEM; + return NULL; + } + + + /* Initialize the context and establish reasonable defaults */ + ZERO_STRUCTP(context); + + context->debug = 0; + context->timeout = 20000; /* 20 seconds */ + + context->full_time_names = False; + context->share_mode = SMBC_SHAREMODE_DENY_NONE; + context->smb_encryption_level = 0; + context->browse_max_lmb_count = 3; /* # LMBs to query */ + context->urlencode_readdir_entries = False; + context->one_share_per_server = False; + context->use_kerberos = False; + context->fallback_after_kerberos = False; + context->no_auto_anonymous_login = False; + + context->server.get_auth_data_fn = SMBC_get_auth_data; + context->server.check_server_fn = SMBC_check_server; + context->server.remove_unused_server_fn = SMBC_remove_unused_server; + + context->cache.server_cache_data = NULL; + context->cache.add_cached_server_fn = SMBC_add_cached_server; + context->cache.get_cached_server_fn = SMBC_get_cached_server; + context->cache.remove_cached_server_fn = SMBC_remove_cached_server; + context->cache.purge_cached_server_fn = SMBC_purge_cached_servers; + + context->posix_emu.open_fn = SMBC_open_ctx; + context->posix_emu.creat_fn = SMBC_creat_ctx; + context->posix_emu.read_fn = SMBC_read_ctx; + context->posix_emu.write_fn = SMBC_write_ctx; + context->posix_emu.close_fn = SMBC_close_ctx; + context->posix_emu.unlink_fn = SMBC_unlink_ctx; + context->posix_emu.rename_fn = SMBC_rename_ctx; + context->posix_emu.lseek_fn = SMBC_lseek_ctx; + context->posix_emu.ftruncate_fn = SMBC_ftruncate_ctx; + context->posix_emu.stat_fn = SMBC_stat_ctx; + context->posix_emu.fstat_fn = SMBC_fstat_ctx; + context->posix_emu.opendir_fn = SMBC_opendir_ctx; + context->posix_emu.closedir_fn = SMBC_closedir_ctx; + context->posix_emu.readdir_fn = SMBC_readdir_ctx; + context->posix_emu.getdents_fn = SMBC_getdents_ctx; + context->posix_emu.mkdir_fn = SMBC_mkdir_ctx; + context->posix_emu.rmdir_fn = SMBC_rmdir_ctx; + context->posix_emu.telldir_fn = SMBC_telldir_ctx; + context->posix_emu.lseekdir_fn = SMBC_lseekdir_ctx; + context->posix_emu.fstatdir_fn = SMBC_fstatdir_ctx; + context->posix_emu.chmod_fn = SMBC_chmod_ctx; + context->posix_emu.utimes_fn = SMBC_utimes_ctx; + context->posix_emu.setxattr_fn = SMBC_setxattr_ctx; + context->posix_emu.getxattr_fn = SMBC_getxattr_ctx; + context->posix_emu.removexattr_fn = SMBC_removexattr_ctx; + context->posix_emu.listxattr_fn = SMBC_listxattr_ctx; + + context->printing.open_print_job_fn = SMBC_open_print_job_ctx; + context->printing.print_file_fn = SMBC_print_file_ctx; + context->printing.list_print_jobs_fn = SMBC_list_print_jobs_ctx; + context->printing.unlink_print_job_fn = SMBC_unlink_print_job_ctx; + + return context; +} + +/* + * Free a context + * + * Returns 0 on success. Otherwise returns 1, the SMBCCTX is _not_ freed + * and thus you'll be leaking memory if not handled properly. + * + */ +int +smbc_free_context(SMBCCTX *context, + int shutdown_ctx) +{ + if (!context) { + errno = EBADF; + return 1; + } + + if (shutdown_ctx) { + SMBCFILE * f; + DEBUG(1,("Performing aggressive shutdown.\n")); + + f = context->files; + while (f) { + (context->posix_emu.close_fn)(context, f); + f = f->next; + } + context->files = NULL; + + /* First try to remove the servers the nice way. */ + if (context->cache.purge_cached_server_fn(context)) { + SMBCSRV * s; + SMBCSRV * next; + DEBUG(1, ("Could not purge all servers, " + "Nice way shutdown failed.\n")); + s = context->servers; + while (s) { + DEBUG(1, ("Forced shutdown: %p (fd=%d)\n", + s, s->cli->fd)); + cli_shutdown(s->cli); + (context->cache.remove_cached_server_fn)(context, + s); + next = s->next; + DLIST_REMOVE(context->servers, s); + SAFE_FREE(s); + s = next; + } + context->servers = NULL; + } + } + else { + /* This is the polite way */ + if ((context->cache.purge_cached_server_fn)(context)) { + DEBUG(1, ("Could not purge all servers, " + "free_context failed.\n")); + errno = EBUSY; + return 1; + } + if (context->servers) { + DEBUG(1, ("Active servers in context, " + "free_context failed.\n")); + errno = EBUSY; + return 1; + } + if (context->files) { + DEBUG(1, ("Active files in context, " + "free_context failed.\n")); + errno = EBUSY; + return 1; + } + } + + /* Things we have to clean up */ + SAFE_FREE(context->workgroup); + SAFE_FREE(context->netbios_name); + SAFE_FREE(context->user); + + DEBUG(3, ("Context %p successfully freed\n", context)); + SAFE_FREE(context); + return 0; +} + + +/* + * Each time the context structure is changed, we have binary backward + * compatibility issues. Instead of modifying the public portions of the + * context structure to add new options, instead, we put them in the internal + * portion of the context structure and provide a set function for these new + * options. + */ +void +smbc_option_set(SMBCCTX *context, + char *option_name, + ... /* option_value */) +{ + va_list ap; + union { + int i; + bool b; + smbc_get_auth_data_with_context_fn auth_fn; + void *v; + const char *s; + } option_value; + + va_start(ap, option_name); + + if (strcmp(option_name, "debug_to_stderr") == 0) { + /* + * Log to standard error instead of standard output. + */ + option_value.b = (bool) va_arg(ap, int); + context->debug_stderr = option_value.b; + + } else if (strcmp(option_name, "full_time_names") == 0) { + /* + * 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.) + */ + option_value.b = (bool) va_arg(ap, int); + context->full_time_names = option_value.b; + + } else if (strcmp(option_name, "open_share_mode") == 0) { + /* + * The share mode to use for files opened with + * SMBC_open_ctx(). The default is SMBC_SHAREMODE_DENY_NONE. + */ + option_value.i = va_arg(ap, int); + context->share_mode = (smbc_share_mode) option_value.i; + + } else if (strcmp(option_name, "user_data") == 0) { + /* + * Save a user data handle which may be retrieved by the user + * with smbc_option_get() + */ + option_value.v = va_arg(ap, void *); + context->user_data = option_value.v; + } else if (strcmp(option_name, "smb_encrypt_level") == 0) { + /* + * Save an encoded value for encryption level. + * 0 = off, 1 = attempt, 2 = required. + */ + option_value.s = va_arg(ap, const char *); + if (strcmp(option_value.s, "none") == 0) { + context->smb_encryption_level = 0; + } else if (strcmp(option_value.s, "request") == 0) { + context->smb_encryption_level = 1; + } else if (strcmp(option_value.s, "require") == 0) { + context->smb_encryption_level = 2; + } + } else if (strcmp(option_name, "browse_max_lmb_count") == 0) { + /* + * 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). + */ + option_value.i = va_arg(ap, int); + context->browse_max_lmb_count = option_value.i; + + } else if (strcmp(option_name, "urlencode_readdir_entries") == 0) { + /* + * 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. + */ + option_value.b = (bool) va_arg(ap, int); + context->urlencode_readdir_entries = option_value.b; + + } else if (strcmp(option_name, "one_share_per_server") == 0) { + /* + * 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. + */ + option_value.b = (bool) va_arg(ap, int); + context->one_share_per_server = option_value.b; + + } else if (strcmp(option_name, "use_kerberos") == 0) { + option_value.b = (bool) va_arg(ap, int); + context->use_kerberos = option_value.b; + + } else if (strcmp(option_name, "fallback_after_kerberos") == 0) { + option_value.b = (bool) va_arg(ap, int); + context->fallback_after_kerberos = option_value.b; + + } else if (strcmp(option_name, "no_auto_anonymous_login") == 0) { + option_value.b = (bool) va_arg(ap, int); + context->no_auto_anonymous_login = option_value.b; + } + + va_end(ap); +} + + +/* + * Retrieve the current value of an option + */ +void * +smbc_option_get(SMBCCTX *context, + char *option_name) +{ + if (strcmp(option_name, "debug_stderr") == 0) { + /* + * Log to standard error instead of standard output. + */ +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) + return (void *) (intptr_t) context->debug_stderr; +#else + return (void *) context->debug_stderr; +#endif + + } else if (strcmp(option_name, "full_time_names") == 0) { + /* + * 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.) + */ +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) + return (void *) (intptr_t) context->full_time_names; +#else + return (void *) context->full_time_names; +#endif + + } else if (strcmp(option_name, "user_data") == 0) { + /* + * Return the user data handle which was saved by the user + * with smbc_option_set() + */ + return context->user_data; + + } else if (strcmp(option_name, "smb_encrypt_level") == 0) { + /* + * Return the current smb encrypt negotiate option as a string. + */ + switch (context->smb_encryption_level) { + case 0: + return (void *) "none"; + case 1: + return (void *) "request"; + case 2: + return (void *) "require"; + } + + } else if (strcmp(option_name, "smb_encrypt_on") == 0) { + /* + * Return the current smb encrypt status option as a bool. + * false = off, true = on. We don't know what server is + * being requested, so we only return true if all servers + * are using an encrypted connection. + */ + SMBCSRV *s; + unsigned int num_servers = 0; + + for (s = context->servers; s; s = s->next) { + num_servers++; + if (s->cli->trans_enc_state == NULL) { + return (void *)false; + } + } +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) + return (void *) (intptr_t) (bool) (num_servers > 0); +#else + return (void *) (bool) (num_servers > 0); +#endif + + } else if (strcmp(option_name, "browse_max_lmb_count") == 0) { + /* + * 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). + */ +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) + return (void *) (intptr_t) context->browse_max_lmb_count; +#else + return (void *) context->browse_max_lmb_count; +#endif + + } else if (strcmp(option_name, "urlencode_readdir_entries") == 0) { + /* + * 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. + */ +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) + return (void *) (intptr_t) context->urlencode_readdir_entries; +#else + return (void *) (bool) context->urlencode_readdir_entries; +#endif + + } else if (strcmp(option_name, "one_share_per_server") == 0) { + /* + * 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. + */ +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) + return (void *) (intptr_t) context->one_share_per_server; +#else + return (void *) (bool) context->one_share_per_server; +#endif + + } else if (strcmp(option_name, "use_kerberos") == 0) { +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) + return (void *) (intptr_t) context->use_kerberos; +#else + return (void *) (bool) context->use_kerberos; +#endif + + } else if (strcmp(option_name, "fallback_after_kerberos") == 0) { +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) + return (void *) (intptr_t) context->fallback_after_kerberos; +#else + return (void *) (bool) context->fallback_after_kerberos; +#endif + + } else if (strcmp(option_name, "no_auto_anonymous_login") == 0) { +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) + return (void *) (intptr_t) context->no_auto_anonymous_login; +#else + return (void *) (bool) context->no_auto_anonymous_login; +#endif + } + + return NULL; +} + + +/* + * Initialize the library, etc. + * + * We accept a struct containing handle information. + * valid values for info->debug from 0 to 100, + * and insist that info->fn must be non-null. + */ +SMBCCTX * +smbc_init_context(SMBCCTX *context) +{ + int pid; + char *user = NULL; + char *home = NULL; + extern bool in_client; + + if (!context) { + errno = EBADF; + return NULL; + } + + /* Do not initialise the same client twice */ + if (context->initialized) { + return 0; + } + + if (!context->server.get_auth_data_fn || + context->debug < 0 || + context->debug > 100) { + + errno = EINVAL; + return NULL; + + } + + if (!SMBC_initialized) { + /* + * Do some library-wide intializations the first time we get + * called + */ + bool conf_loaded = False; + TALLOC_CTX *frame = talloc_stackframe(); + + /* Set this to what the user wants */ + DEBUGLEVEL = context->debug; + + load_case_tables(); + + setup_logging("libsmbclient", True); + if (context->debug_stderr) { + dbf = x_stderr; + x_setbuf(x_stderr, NULL); + } + + /* Here we would open the smb.conf file if needed ... */ + + in_client = True; /* FIXME, make a param */ + + home = getenv("HOME"); + if (home) { + char *conf = NULL; + if (asprintf(&conf, "%s/.smb/smb.conf", home) > 0) { + if (lp_load(conf, True, False, False, True)) { + conf_loaded = True; + } else { + DEBUG(5, ("Could not load config file: %s\n", + conf)); + } + SAFE_FREE(conf); + } + } + + if (!conf_loaded) { + /* + * Well, if that failed, try the get_dyn_CONFIGFILE + * Which points to the standard locn, and if that + * fails, silently ignore it and use the internal + * defaults ... + */ + + if (!lp_load(get_dyn_CONFIGFILE(), True, False, False, False)) { + DEBUG(5, ("Could not load config file: %s\n", + get_dyn_CONFIGFILE())); + } else if (home) { + char *conf; + /* + * We loaded the global config file. Now lets + * load user-specific modifications to the + * global config. + */ + if (asprintf(&conf, + "%s/.smb/smb.conf.append", + home) > 0) { + if (!lp_load(conf, True, False, False, False)) { + DEBUG(10, + ("Could not append config file: " + "%s\n", + conf)); + } + SAFE_FREE(conf); + } + } + } + + load_interfaces(); /* Load the list of interfaces ... */ + + reopen_logs(); /* Get logging working ... */ + + /* + * Block SIGPIPE (from lib/util_sock.c: write()) + * It is not needed and should not stop execution + */ + BlockSignals(True, SIGPIPE); + + /* Done with one-time initialisation */ + SMBC_initialized = 1; + + TALLOC_FREE(frame); + } + + if (!context->user) { + /* + * FIXME: Is this the best way to get the user info? + */ + user = getenv("USER"); + /* walk around as "guest" if no username can be found */ + if (!user) context->user = SMB_STRDUP("guest"); + else context->user = SMB_STRDUP(user); + } + + if (!context->netbios_name) { + /* + * We try to get our netbios name from the config. If that + * fails we fall back on constructing our netbios name from + * our hostname etc + */ + if (global_myname()) { + context->netbios_name = SMB_STRDUP(global_myname()); + } + else { + /* + * Hmmm, I want to get hostname as well, but I am too + * lazy for the moment + */ + pid = sys_getpid(); + context->netbios_name = (char *)SMB_MALLOC(17); + if (!context->netbios_name) { + errno = ENOMEM; + return NULL; + } + slprintf(context->netbios_name, 16, + "smbc%s%d", context->user, pid); + } + } + + DEBUG(1, ("Using netbios name %s.\n", context->netbios_name)); + + if (!context->workgroup) { + if (lp_workgroup()) { + context->workgroup = SMB_STRDUP(lp_workgroup()); + } + else { + /* TODO: Think about a decent default workgroup */ + context->workgroup = SMB_STRDUP("samba"); + } + } + + DEBUG(1, ("Using workgroup %s.\n", context->workgroup)); + + /* shortest timeout is 1 second */ + if (context->timeout > 0 && context->timeout < 1000) + context->timeout = 1000; + + /* + * FIXME: Should we check the function pointers here? + */ + + context->initialized = True; + + return context; +} + + +/* Return the verion of samba, and thus libsmbclient */ +const char * +smbc_version(void) +{ + return samba_version_string(); +} + + +/** Get the netbios name used for making connections */ +char * +smbc_getNetbiosName(SMBCCTX *c) +{ + return c->netbios_name; +} + +/** Set the netbios name used for making connections */ +void +smbc_setNetbiosName(SMBCCTX *c, char * netbios_name) +{ + c->netbios_name = netbios_name; +} + +/** Get the workgroup used for making connections */ +char * +smbc_getWorkgroup(SMBCCTX *c) +{ + return c->workgroup; +} + +/** Set the workgroup used for making connections */ +void +smbc_setWorkgroup(SMBCCTX *c, char * workgroup) +{ + c->workgroup = workgroup; +} + +/** Get the username used for making connections */ +char * +smbc_getUser(SMBCCTX *c) +{ + return c->user; +} + +/** Set the username used for making connections */ +void +smbc_setUser(SMBCCTX *c, char * user) +{ + c->user = user; +} + +/** Get the debug level */ +int +smbc_getDebug(SMBCCTX *c) +{ + return c->debug; +} + +/** Set the debug level */ +void +smbc_setDebug(SMBCCTX *c, int debug) +{ + c->debug = debug; +} + +/** + * Get the timeout used for waiting on connections and response data + * (in milliseconds) + */ +int +smbc_getTimeout(SMBCCTX *c) +{ + return c->timeout; +} + +/** + * Set the timeout used for waiting on connections and response data + * (in milliseconds) + */ +void +smbc_setTimeout(SMBCCTX *c, int timeout) +{ + c->timeout = timeout; +} + +/** Get the function for obtaining authentication data */ + +smbc_get_auth_data_fn +smbc_getFunctionAuthData(SMBCCTX *c) +{ + return c->server.get_auth_data_fn; +} + +/** Set the function for obtaining authentication data */ +void +smbc_setFunctionAuthData(SMBCCTX *c, smbc_get_auth_data_fn fn) +{ + c->server.get_auth_data_fn = fn; +} + +/** Get the function for checking if a server is still good */ +smbc_check_server_fn +smbc_getFunctionCheckServer(SMBCCTX *c) +{ + return c->server.check_server_fn; +} + +/** Set the function for checking if a server is still good */ +void +smbc_setFunctionCheckServer(SMBCCTX *c, smbc_check_server_fn fn) +{ + c->server.check_server_fn = fn; +} + +/** Get the function for removing a server if unused */ +smbc_remove_unused_server_fn +smbc_getFunctionRemoveUnusedServer(SMBCCTX *c) +{ + return c->server.remove_unused_server_fn; +} + +/** Set the function for removing a server if unused */ +void +smbc_setFunctionRemoveUnusedServer(SMBCCTX *c, + smbc_remove_unused_server_fn fn) +{ + c->server.remove_unused_server_fn = fn; +} + +/** Get the function to store private data of the server cache */ +struct +smbc_server_cache * smbc_getServerCacheData(SMBCCTX *c) +{ + return c->cache.server_cache_data; +} + +/** Set the function to store private data of the server cache */ +void +smbc_setServerCacheData(SMBCCTX *c, struct smbc_server_cache * cache) +{ + c->cache.server_cache_data = cache; +} + + +/** Get the function for adding a cached server */ +smbc_add_cached_srv_fn +smbc_getFunctionAddCachedServer(SMBCCTX *c) +{ + return c->cache.add_cached_server_fn; +} + +/** Set the function for adding a cached server */ +void +smbc_setFunctionAddCachedServer(SMBCCTX *c, smbc_add_cached_srv_fn fn) +{ + c->cache.add_cached_server_fn = fn; +} + +/** Get the function for server cache lookup */ +smbc_get_cached_srv_fn +smbc_getFunctionGetCachedServer(SMBCCTX *c) +{ + return c->cache.get_cached_server_fn; +} + +/** Set the function for server cache lookup */ +void +smbc_setFunctionGetCachedServer(SMBCCTX *c, smbc_get_cached_srv_fn fn) +{ + c->cache.get_cached_server_fn = fn; +} + +/** Get the function for server cache removal */ +smbc_remove_cached_srv_fn +smbc_getFunctionRemoveCachedServer(SMBCCTX *c) +{ + return c->cache.remove_cached_server_fn; +} + +/** Set the function for server cache removal */ +void +smbc_setFunctionRemoveCachedServer(SMBCCTX *c, + smbc_remove_cached_srv_fn fn) +{ + c->cache.remove_cached_server_fn = fn; +} + +/** + * Get the function for server cache purging. This function tries to + * remove all cached servers (e.g. on disconnect) + */ +smbc_purge_cached_srv_fn +smbc_getFunctionPurgeCachedServers(SMBCCTX *c) +{ + return c->cache.purge_cached_server_fn; +} + +/** + * Set the function for server cache purging. This function tries to + * remove all cached servers (e.g. on disconnect) + */ +void +smbc_setFunctionPurgeCachedServers(SMBCCTX *c, smbc_purge_cached_srv_fn fn) +{ + c->cache.purge_cached_server_fn = fn; +} + +/** + * Callable functions for files. + */ + +smbc_open_fn +smbc_getFunctionOpen(SMBCCTX *c) +{ + return c->posix_emu.open_fn; +} + +void +smbc_setFunctionOpen(SMBCCTX *c, smbc_open_fn fn) +{ + c->posix_emu.open_fn = fn; +} + +smbc_creat_fn +smbc_getFunctionCreat(SMBCCTX *c) +{ + return c->posix_emu.creat_fn; +} + +void +smbc_setFunctionCreat(SMBCCTX *c, smbc_creat_fn fn) +{ + c->posix_emu.creat_fn = fn; +} + +smbc_read_fn +smbc_getFunctionRead(SMBCCTX *c) +{ + return c->posix_emu.read_fn; +} + +void +smbc_setFunctionRead(SMBCCTX *c, smbc_read_fn fn) +{ + c->posix_emu.read_fn = fn; +} + +smbc_write_fn +smbc_getFunctionWrite(SMBCCTX *c) +{ + return c->posix_emu.write_fn; +} + +void +smbc_setFunctionWrite(SMBCCTX *c, smbc_write_fn fn) +{ + c->posix_emu.write_fn = fn; +} + +smbc_unlink_fn +smbc_getFunctionUnlink(SMBCCTX *c) +{ + return c->posix_emu.unlink_fn; +} + +void +smbc_setFunctionUnlink(SMBCCTX *c, smbc_unlink_fn fn) +{ + c->posix_emu.unlink_fn = fn; +} + +smbc_rename_fn +smbc_getFunctionRename(SMBCCTX *c) +{ + return c->posix_emu.rename_fn; +} + +void +smbc_setFunctionRename(SMBCCTX *c, smbc_rename_fn fn) +{ + c->posix_emu.rename_fn = fn; +} + +smbc_lseek_fn +smbc_getFunctionLseek(SMBCCTX *c) +{ + return c->posix_emu.lseek_fn; +} + +void +smbc_setFunctionLseek(SMBCCTX *c, smbc_lseek_fn fn) +{ + c->posix_emu.lseek_fn = fn; +} + +smbc_stat_fn +smbc_getFunctionStat(SMBCCTX *c) +{ + return c->posix_emu.stat_fn; +} + +void +smbc_setFunctionStat(SMBCCTX *c, smbc_stat_fn fn) +{ + c->posix_emu.stat_fn = fn; +} + +smbc_fstat_fn +smbc_getFunctionFstat(SMBCCTX *c) +{ + return c->posix_emu.fstat_fn; +} + +void +smbc_setFunctionFstat(SMBCCTX *c, smbc_fstat_fn fn) +{ + c->posix_emu.fstat_fn = fn; +} + +smbc_ftruncate_fn +smbc_getFunctionFtruncate(SMBCCTX *c) +{ + return c->posix_emu.ftruncate_fn; +} + +void +smbc_setFunctionFtruncate(SMBCCTX *c, smbc_ftruncate_fn fn) +{ + c->posix_emu.ftruncate_fn = fn; +} + +smbc_close_fn +smbc_getFunctionClose(SMBCCTX *c) +{ + return c->posix_emu.close_fn; +} + +void +smbc_setFunctionClose(SMBCCTX *c, smbc_close_fn fn) +{ + c->posix_emu.close_fn = fn; +} + + +/** + * Callable functions for directories. + */ + +smbc_opendir_fn +smbc_getFunctionOpendir(SMBCCTX *c) +{ + return c->posix_emu.opendir_fn; +} + +void +smbc_setFunctionOpendir(SMBCCTX *c, smbc_opendir_fn fn) +{ + c->posix_emu.opendir_fn = fn; +} + +smbc_closedir_fn +smbc_getFunctionClosedir(SMBCCTX *c) +{ + return c->posix_emu.closedir_fn; +} + +void +smbc_setFunctionClosedir(SMBCCTX *c, smbc_closedir_fn fn) +{ + c->posix_emu.closedir_fn = fn; +} + +smbc_readdir_fn +smbc_getFunctionReaddir(SMBCCTX *c) +{ + return c->posix_emu.readdir_fn; +} + +void +smbc_setFunctionReaddir(SMBCCTX *c, smbc_readdir_fn fn) +{ + c->posix_emu.readdir_fn = fn; +} + +smbc_getdents_fn +smbc_getFunctionGetdents(SMBCCTX *c) +{ + return c->posix_emu.getdents_fn; +} + +void +smbc_setFunctionGetdents(SMBCCTX *c, smbc_getdents_fn fn) +{ + c->posix_emu.getdents_fn = fn; +} + +smbc_mkdir_fn +smbc_getFunctionMkdir(SMBCCTX *c) +{ + return c->posix_emu.mkdir_fn; +} + +void +smbc_setFunctionMkdir(SMBCCTX *c, smbc_mkdir_fn fn) +{ + c->posix_emu.mkdir_fn = fn; +} + +smbc_rmdir_fn +smbc_getFunctionRmdir(SMBCCTX *c) +{ + return c->posix_emu.rmdir_fn; +} + +void +smbc_setFunctionRmdir(SMBCCTX *c, smbc_rmdir_fn fn) +{ + c->posix_emu.rmdir_fn = fn; +} + +smbc_telldir_fn +smbc_getFunctionTelldir(SMBCCTX *c) +{ + return c->posix_emu.telldir_fn; +} + +void +smbc_setFunctionTelldir(SMBCCTX *c, smbc_telldir_fn fn) +{ + c->posix_emu.telldir_fn = fn; +} + +smbc_lseekdir_fn +smbc_getFunctionLseekdir(SMBCCTX *c) +{ + return c->posix_emu.lseekdir_fn; +} + +void +smbc_setFunctionLseekdir(SMBCCTX *c, smbc_lseekdir_fn fn) +{ + c->posix_emu.lseekdir_fn = fn; +} + +smbc_fstatdir_fn +smbc_getFunctionFstatdir(SMBCCTX *c) +{ + return c->posix_emu.fstatdir_fn; +} + +void +smbc_setFunctionFstatdir(SMBCCTX *c, smbc_fstatdir_fn fn) +{ + c->posix_emu.fstatdir_fn = fn; +} + + +/** + * Callable functions applicable to both files and directories. + */ + +smbc_chmod_fn +smbc_getFunctionChmod(SMBCCTX *c) +{ + return c->posix_emu.chmod_fn; +} + +void +smbc_setFunctionChmod(SMBCCTX *c, smbc_chmod_fn fn) +{ + c->posix_emu.chmod_fn = fn; +} + +smbc_utimes_fn +smbc_getFunctionUtimes(SMBCCTX *c) +{ + return c->posix_emu.utimes_fn; +} + +void +smbc_setFunctionUtimes(SMBCCTX *c, smbc_utimes_fn fn) +{ + c->posix_emu.utimes_fn = fn; +} + +smbc_setxattr_fn +smbc_getFunctionSetxattr(SMBCCTX *c) +{ + return c->posix_emu.setxattr_fn; +} + +void +smbc_setFunctionSetxattr(SMBCCTX *c, smbc_setxattr_fn fn) +{ + c->posix_emu.setxattr_fn = fn; +} + +smbc_getxattr_fn +smbc_getFunctionGetxattr(SMBCCTX *c) +{ + return c->posix_emu.getxattr_fn; +} + +void +smbc_setFunctionGetxattr(SMBCCTX *c, smbc_getxattr_fn fn) +{ + c->posix_emu.getxattr_fn = fn; +} + +smbc_removexattr_fn +smbc_getFunctionRemovexattr(SMBCCTX *c) +{ + return c->posix_emu.removexattr_fn; +} + +void +smbc_setFunctionRemovexattr(SMBCCTX *c, smbc_removexattr_fn fn) +{ + c->posix_emu.removexattr_fn = fn; +} + +smbc_listxattr_fn +smbc_getFunctionListxattr(SMBCCTX *c) +{ + return c->posix_emu.listxattr_fn; +} + +void +smbc_setFunctionListxattr(SMBCCTX *c, smbc_listxattr_fn fn) +{ + c->posix_emu.listxattr_fn = fn; +} + + +/** + * Callable functions related to printing + */ + +smbc_print_file_fn +smbc_getFunctionPrintFile(SMBCCTX *c) +{ + return c->printing.print_file_fn; +} + +void +smbc_setFunctionPrintFile(SMBCCTX *c, smbc_print_file_fn fn) +{ + c->printing.print_file_fn = fn; +} + +smbc_open_print_job_fn +smbc_getFunctionOpenPrintJob(SMBCCTX *c) +{ + return c->printing.open_print_job_fn; +} + +void +smbc_setFunctionOpenPrintJob(SMBCCTX *c, + smbc_open_print_job_fn fn) +{ + c->printing.open_print_job_fn = fn; +} + +smbc_list_print_jobs_fn +smbc_getFunctionListPrintJobs(SMBCCTX *c) +{ + return c->printing.list_print_jobs_fn; +} + +void +smbc_setFunctionListPrintJobs(SMBCCTX *c, + smbc_list_print_jobs_fn fn) +{ + c->printing.list_print_jobs_fn = fn; +} + +smbc_unlink_print_job_fn +smbc_getFunctionUnlinkPrintJob(SMBCCTX *c) +{ + return c->printing.unlink_print_job_fn; +} + +void +smbc_setFunctionUnlinkPrintJob(SMBCCTX *c, + smbc_unlink_print_job_fn fn) +{ + c->printing.unlink_print_job_fn = fn; +} + diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c new file mode 100644 index 0000000000..9cb3351433 --- /dev/null +++ b/source3/libsmb/libsmb_dir.c @@ -0,0 +1,1928 @@ +/* + Unix SMB/Netbios implementation. + SMB client library implementation + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000, 2002 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 3 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, see . +*/ + +#include "includes.h" +#include "libsmbclient.h" +#include "libsmb_internal.h" + + +/* + * Routine to open a directory + * We accept the URL syntax explained in SMBC_parse_path(), above. + */ + +static void +remove_dir(SMBCFILE *dir) +{ + struct smbc_dir_list *d,*f; + + d = dir->dir_list; + while (d) { + + f = d; d = d->next; + + SAFE_FREE(f->dirent); + SAFE_FREE(f); + + } + + dir->dir_list = dir->dir_end = dir->dir_next = NULL; + +} + +static int +add_dirent(SMBCFILE *dir, + const char *name, + const char *comment, + uint32 type) +{ + struct smbc_dirent *dirent; + int size; + int name_length = (name == NULL ? 0 : strlen(name)); + int comment_len = (comment == NULL ? 0 : strlen(comment)); + + /* + * Allocate space for the dirent, which must be increased by the + * size of the name and the comment and 1 each for the null terminator. + */ + + size = sizeof(struct smbc_dirent) + name_length + comment_len + 2; + + dirent = (struct smbc_dirent *)SMB_MALLOC(size); + + if (!dirent) { + + dir->dir_error = ENOMEM; + return -1; + + } + + ZERO_STRUCTP(dirent); + + if (dir->dir_list == NULL) { + + dir->dir_list = SMB_MALLOC_P(struct smbc_dir_list); + if (!dir->dir_list) { + + SAFE_FREE(dirent); + dir->dir_error = ENOMEM; + return -1; + + } + ZERO_STRUCTP(dir->dir_list); + + dir->dir_end = dir->dir_next = dir->dir_list; + } + else { + + dir->dir_end->next = SMB_MALLOC_P(struct smbc_dir_list); + + if (!dir->dir_end->next) { + + SAFE_FREE(dirent); + dir->dir_error = ENOMEM; + return -1; + + } + ZERO_STRUCTP(dir->dir_end->next); + + dir->dir_end = dir->dir_end->next; + } + + dir->dir_end->next = NULL; + dir->dir_end->dirent = dirent; + + dirent->smbc_type = type; + dirent->namelen = name_length; + dirent->commentlen = comment_len; + dirent->dirlen = size; + + /* + * dirent->namelen + 1 includes the null (no null termination needed) + * Ditto for dirent->commentlen. + * The space for the two null bytes was allocated. + */ + strncpy(dirent->name, (name?name:""), dirent->namelen + 1); + dirent->comment = (char *)(&dirent->name + dirent->namelen + 1); + strncpy(dirent->comment, (comment?comment:""), dirent->commentlen + 1); + + return 0; + +} + +static void +list_unique_wg_fn(const char *name, + uint32 type, + const char *comment, + void *state) +{ + SMBCFILE *dir = (SMBCFILE *)state; + struct smbc_dir_list *dir_list; + struct smbc_dirent *dirent; + int dirent_type; + int do_remove = 0; + + dirent_type = dir->dir_type; + + if (add_dirent(dir, name, comment, dirent_type) < 0) { + + /* An error occurred, what do we do? */ + /* FIXME: Add some code here */ + } + + /* Point to the one just added */ + dirent = dir->dir_end->dirent; + + /* See if this was a duplicate */ + for (dir_list = dir->dir_list; + dir_list != dir->dir_end; + dir_list = dir_list->next) { + if (! do_remove && + strcmp(dir_list->dirent->name, dirent->name) == 0) { + /* Duplicate. End end of list need to be removed. */ + do_remove = 1; + } + + if (do_remove && dir_list->next == dir->dir_end) { + /* Found the end of the list. Remove it. */ + dir->dir_end = dir_list; + free(dir_list->next); + free(dirent); + dir_list->next = NULL; + break; + } + } +} + +static void +list_fn(const char *name, + uint32 type, + const char *comment, + void *state) +{ + SMBCFILE *dir = (SMBCFILE *)state; + int dirent_type; + + /* + * We need to process the type a little ... + * + * Disk share = 0x00000000 + * Print share = 0x00000001 + * Comms share = 0x00000002 (obsolete?) + * IPC$ share = 0x00000003 + * + * administrative shares: + * ADMIN$, IPC$, C$, D$, E$ ... are type |= 0x80000000 + */ + + if (dir->dir_type == SMBC_FILE_SHARE) { + switch (type) { + case 0 | 0x80000000: + case 0: + dirent_type = SMBC_FILE_SHARE; + break; + + case 1: + dirent_type = SMBC_PRINTER_SHARE; + break; + + case 2: + dirent_type = SMBC_COMMS_SHARE; + break; + + case 3 | 0x80000000: + case 3: + dirent_type = SMBC_IPC_SHARE; + break; + + default: + dirent_type = SMBC_FILE_SHARE; /* FIXME, error? */ + break; + } + } + else { + dirent_type = dir->dir_type; + } + + if (add_dirent(dir, name, comment, dirent_type) < 0) { + + /* An error occurred, what do we do? */ + /* FIXME: Add some code here */ + + } +} + +static void +dir_list_fn(const char *mnt, + file_info *finfo, + const char *mask, + void *state) +{ + + if (add_dirent((SMBCFILE *)state, finfo->name, "", + (finfo->mode&aDIR?SMBC_DIR:SMBC_FILE)) < 0) { + + /* Handle an error ... */ + + /* FIXME: Add some code ... */ + + } + +} + +static int +net_share_enum_rpc(struct cli_state *cli, + void (*fn)(const char *name, + uint32 type, + const char *comment, + void *state), + void *state) +{ + int i; + WERROR result; + ENUM_HND enum_hnd; + uint32 info_level = 1; + uint32 preferred_len = 0xffffffff; + uint32 type; + SRV_SHARE_INFO_CTR ctr; + fstring name = ""; + fstring comment = ""; + struct rpc_pipe_client *pipe_hnd; + NTSTATUS nt_status; + + /* Open the server service pipe */ + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &nt_status); + if (!pipe_hnd) { + DEBUG(1, ("net_share_enum_rpc pipe open fail!\n")); + return -1; + } + + /* Issue the NetShareEnum RPC call and retrieve the response */ + init_enum_hnd(&enum_hnd, 0); + result = rpccli_srvsvc_net_share_enum(pipe_hnd, + talloc_tos(), + info_level, + &ctr, + preferred_len, + &enum_hnd); + + /* Was it successful? */ + if (!W_ERROR_IS_OK(result) || ctr.num_entries == 0) { + /* Nope. Go clean up. */ + goto done; + } + + /* For each returned entry... */ + for (i = 0; i < ctr.num_entries; i++) { + + /* pull out the share name */ + rpcstr_pull_unistr2_fstring( + name, &ctr.share.info1[i].info_1_str.uni_netname); + + /* pull out the share's comment */ + rpcstr_pull_unistr2_fstring( + comment, &ctr.share.info1[i].info_1_str.uni_remark); + + /* Get the type value */ + type = ctr.share.info1[i].info_1.type; + + /* Add this share to the list */ + (*fn)(name, type, comment, state); + } + +done: + /* Close the server service pipe */ + cli_rpc_pipe_close(pipe_hnd); + + /* Tell 'em if it worked */ + return W_ERROR_IS_OK(result) ? 0 : -1; +} + + +/* + * Verify that the options specified in a URL are valid + */ +int +SMBC_check_options(char *server, + char *share, + char *path, + char *options) +{ + DEBUG(4, ("SMBC_check_options(): server='%s' share='%s' " + "path='%s' options='%s'\n", + server, share, path, options)); + + /* No options at all is always ok */ + if (! *options) return 0; + + /* Currently, we don't support any options. */ + return -1; +} + + +SMBCFILE * +SMBC_opendir_ctx(SMBCCTX *context, + const char *fname) +{ + int saved_errno; + char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *options = NULL; + char *workgroup = NULL; + char *path = NULL; + uint16 mode; + char *p = NULL; + SMBCSRV *srv = NULL; + SMBCFILE *dir = NULL; + struct sockaddr_storage rem_ss; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + DEBUG(4, ("no valid context\n")); + errno = EINVAL + 8192; + TALLOC_FREE(frame); + return NULL; + + } + + if (!fname) { + DEBUG(4, ("no valid fname\n")); + errno = EINVAL + 8193; + TALLOC_FREE(frame); + return NULL; + } + + if (SMBC_parse_path(frame, + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + &options)) { + DEBUG(4, ("no valid path\n")); + errno = EINVAL + 8194; + TALLOC_FREE(frame); + return NULL; + } + + DEBUG(4, ("parsed path: fname='%s' server='%s' share='%s' " + "path='%s' options='%s'\n", + fname, server, share, path, options)); + + /* Ensure the options are valid */ + if (SMBC_check_options(server, share, path, options)) { + DEBUG(4, ("unacceptable options (%s)\n", options)); + errno = EINVAL + 8195; + TALLOC_FREE(frame); + return NULL; + } + + if (!user || user[0] == (char)0) { + user = talloc_strdup(frame, context->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + return NULL; + } + } + + dir = SMB_MALLOC_P(SMBCFILE); + + if (!dir) { + errno = ENOMEM; + TALLOC_FREE(frame); + return NULL; + } + + ZERO_STRUCTP(dir); + + dir->cli_fd = 0; + dir->fname = SMB_STRDUP(fname); + dir->srv = NULL; + dir->offset = 0; + dir->file = False; + dir->dir_list = dir->dir_next = dir->dir_end = NULL; + + if (server[0] == (char)0) { + + int i; + int count; + int max_lmb_count; + struct ip_service *ip_list; + struct ip_service server_addr; + struct user_auth_info u_info; + + if (share[0] != (char)0 || path[0] != (char)0) { + + errno = EINVAL + 8196; + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + } + + /* Determine how many local master browsers to query */ + max_lmb_count = (context->browse_max_lmb_count == 0 + ? INT_MAX + : context->browse_max_lmb_count); + + memset(&u_info, '\0', sizeof(u_info)); + u_info.username = talloc_strdup(frame,user); + u_info.password = talloc_strdup(frame,password); + if (!u_info.username || !u_info.password) { + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + } + + /* + * We have server and share and path empty but options + * requesting that we scan all master browsers for their list + * of workgroups/domains. This implies that we must first try + * broadcast queries to find all master browsers, and if that + * doesn't work, then try our other methods which return only + * a single master browser. + */ + + ip_list = NULL; + if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list, + &count))) + { + + SAFE_FREE(ip_list); + + if (!find_master_ip(workgroup, &server_addr.ss)) { + + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + errno = ENOENT; + TALLOC_FREE(frame); + return NULL; + } + + ip_list = (struct ip_service *)memdup( + &server_addr, sizeof(server_addr)); + if (ip_list == NULL) { + errno = ENOMEM; + TALLOC_FREE(frame); + return NULL; + } + count = 1; + } + + for (i = 0; i < count && i < max_lmb_count; i++) { + char addr[INET6_ADDRSTRLEN]; + char *wg_ptr = NULL; + struct cli_state *cli = NULL; + + print_sockaddr(addr, sizeof(addr), &ip_list[i].ss); + DEBUG(99, ("Found master browser %d of %d: %s\n", + i+1, MAX(count, max_lmb_count), + addr)); + + cli = get_ipc_connect_master_ip(talloc_tos(), + &ip_list[i], + &u_info, + &wg_ptr); + /* cli == NULL is the master browser refused to talk or + could not be found */ + if (!cli) { + continue; + } + + workgroup = talloc_strdup(frame, wg_ptr); + server = talloc_strdup(frame, cli->desthost); + + cli_shutdown(cli); + + if (!workgroup || !server) { + errno = ENOMEM; + TALLOC_FREE(frame); + return NULL; + } + + DEBUG(4, ("using workgroup %s %s\n", + workgroup, server)); + + /* + * For each returned master browser IP address, get a + * connection to IPC$ on the server if we do not + * already have one, and determine the + * workgroups/domains that it knows about. + */ + + srv = SMBC_server(frame, context, True, server, "IPC$", + &workgroup, &user, &password); + if (!srv) { + continue; + } + + dir->srv = srv; + dir->dir_type = SMBC_WORKGROUP; + + /* Now, list the stuff ... */ + + if (!cli_NetServerEnum(srv->cli, + workgroup, + SV_TYPE_DOMAIN_ENUM, + list_unique_wg_fn, + (void *)dir)) { + continue; + } + } + + SAFE_FREE(ip_list); + } else { + /* + * Server not an empty string ... Check the rest and see what + * gives + */ + if (*share == '\0') { + if (*path != '\0') { + + /* Should not have empty share with path */ + errno = EINVAL + 8197; + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + + } + + /* + * We don't know if is really a server name + * or is a workgroup/domain name. If we already have + * a server structure for it, we'll use it. + * Otherwise, check to see if <1D>, + * <1B>, or <20> translates. We check + * to see if is an IP address first. + */ + + /* + * See if we have an existing server. Do not + * establish a connection if one does not already + * exist. + */ + srv = SMBC_server(frame, context, False, server, "IPC$", + &workgroup, &user, &password); + + /* + * If no existing server and not an IP addr, look for + * LMB or DMB + */ + if (!srv && + !is_ipaddress(server) && + (resolve_name(server, &rem_ss, 0x1d) || /* LMB */ + resolve_name(server, &rem_ss, 0x1b) )) { /* DMB */ + + fstring buserver; + + dir->dir_type = SMBC_SERVER; + + /* + * Get the backup list ... + */ + if (!name_status_find(server, 0, 0, + &rem_ss, buserver)) { + + DEBUG(0, ("Could not get name of " + "local/domain master browser " + "for server %s\n", server)); + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + errno = EPERM; + TALLOC_FREE(frame); + return NULL; + + } + + /* + * Get a connection to IPC$ on the server if + * we do not already have one + */ + srv = SMBC_server(frame, context, True, + buserver, "IPC$", + &workgroup, &user, &password); + if (!srv) { + DEBUG(0, ("got no contact to IPC$\n")); + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + + } + + dir->srv = srv; + + /* Now, list the servers ... */ + if (!cli_NetServerEnum(srv->cli, server, + 0x0000FFFE, list_fn, + (void *)dir)) { + + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + } + } else if (srv || + (resolve_name(server, &rem_ss, 0x20))) { + + /* If we hadn't found the server, get one now */ + if (!srv) { + srv = SMBC_server(frame, context, True, + server, "IPC$", + &workgroup, + &user, &password); + } + + if (!srv) { + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + + } + + dir->dir_type = SMBC_FILE_SHARE; + dir->srv = srv; + + /* List the shares ... */ + + if (net_share_enum_rpc( + srv->cli, + list_fn, + (void *) dir) < 0 && + cli_RNetShareEnum( + srv->cli, + list_fn, + (void *)dir) < 0) { + + errno = cli_errno(srv->cli); + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + + } + } else { + /* Neither the workgroup nor server exists */ + errno = ECONNREFUSED; + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + } + + } + else { + /* + * The server and share are specified ... work from + * there ... + */ + char *targetpath; + struct cli_state *targetcli; + + /* We connect to the server and list the directory */ + dir->dir_type = SMBC_FILE_SHARE; + + srv = SMBC_server(frame, context, True, server, share, + &workgroup, &user, &password); + + if (!srv) { + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + } + + dir->srv = srv; + + /* Now, list the files ... */ + + p = path + strlen(path); + path = talloc_asprintf_append(path, "\\*"); + if (!path) { + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + } + + if (!cli_resolve_path(frame, "", srv->cli, path, + &targetcli, &targetpath)) { + d_printf("Could not resolve %s\n", path); + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + } + + if (cli_list(targetcli, targetpath, + aDIR | aSYSTEM | aHIDDEN, + dir_list_fn, (void *)dir) < 0) { + + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + saved_errno = SMBC_errno(context, targetcli); + + if (saved_errno == EINVAL) { + /* + * See if they asked to opendir something + * other than a directory. If so, the + * converted error value we got would have + * been EINVAL rather than ENOTDIR. + */ + *p = '\0'; /* restore original path */ + + if (SMBC_getatr(context, srv, path, + &mode, NULL, + NULL, NULL, NULL, NULL, + NULL) && + ! IS_DOS_DIR(mode)) { + + /* It is. Correct the error value */ + saved_errno = ENOTDIR; + } + } + + /* + * If there was an error and the server is no + * good any more... + */ + if (cli_is_error(targetcli) && + (context->server.check_server_fn)(context, srv)) { + + /* ... then remove it. */ + if ((context->server.remove_unused_server_fn)(context, + srv)) { + /* + * We could not remove the + * server completely, remove + * it from the cache so we + * will not get it again. It + * will be removed when the + * last file/dir is closed. + */ + (context->cache.remove_cached_server_fn)(context, srv); + } + } + + errno = saved_errno; + TALLOC_FREE(frame); + return NULL; + } + } + + } + + DLIST_ADD(context->files, dir); + TALLOC_FREE(frame); + return dir; + +} + +/* + * Routine to close a directory + */ + +int +SMBC_closedir_ctx(SMBCCTX *context, + SMBCFILE *dir) +{ + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!dir || !SMBC_dlist_contains(context->files, dir)) { + errno = EBADF; + TALLOC_FREE(frame); + return -1; + } + + remove_dir(dir); /* Clean it up */ + + DLIST_REMOVE(context->files, dir); + + if (dir) { + + SAFE_FREE(dir->fname); + SAFE_FREE(dir); /* Free the space too */ + } + + TALLOC_FREE(frame); + return 0; + +} + +static void +smbc_readdir_internal(SMBCCTX * context, + struct smbc_dirent *dest, + struct smbc_dirent *src, + int max_namebuf_len) +{ + if (context->urlencode_readdir_entries) { + + /* url-encode the name. get back remaining buffer space */ + max_namebuf_len = + SMBC_urlencode(dest->name, src->name, max_namebuf_len); + + /* We now know the name length */ + dest->namelen = strlen(dest->name); + + /* Save the pointer to the beginning of the comment */ + dest->comment = dest->name + dest->namelen + 1; + + /* Copy the comment */ + strncpy(dest->comment, src->comment, max_namebuf_len - 1); + dest->comment[max_namebuf_len - 1] = '\0'; + + /* Save other fields */ + dest->smbc_type = src->smbc_type; + dest->commentlen = strlen(dest->comment); + dest->dirlen = ((dest->comment + dest->commentlen + 1) - + (char *) dest); + } else { + + /* No encoding. Just copy the entry as is. */ + memcpy(dest, src, src->dirlen); + dest->comment = (char *)(&dest->name + src->namelen + 1); + } + +} + +/* + * Routine to get a directory entry + */ + +struct smbc_dirent * +SMBC_readdir_ctx(SMBCCTX *context, + SMBCFILE *dir) +{ + int maxlen; + struct smbc_dirent *dirp, *dirent; + TALLOC_CTX *frame = talloc_stackframe(); + + /* Check that all is ok first ... */ + + if (!context || !context->initialized) { + + errno = EINVAL; + DEBUG(0, ("Invalid context in SMBC_readdir_ctx()\n")); + TALLOC_FREE(frame); + return NULL; + + } + + if (!dir || !SMBC_dlist_contains(context->files, dir)) { + + errno = EBADF; + DEBUG(0, ("Invalid dir in SMBC_readdir_ctx()\n")); + TALLOC_FREE(frame); + return NULL; + + } + + if (dir->file != False) { /* FIXME, should be dir, perhaps */ + + errno = ENOTDIR; + DEBUG(0, ("Found file vs directory in SMBC_readdir_ctx()\n")); + TALLOC_FREE(frame); + return NULL; + + } + + if (!dir->dir_next) { + TALLOC_FREE(frame); + return NULL; + } + + dirent = dir->dir_next->dirent; + if (!dirent) { + + errno = ENOENT; + TALLOC_FREE(frame); + return NULL; + + } + + dirp = (struct smbc_dirent *)context->dirent; + maxlen = (sizeof(context->dirent) - + sizeof(struct smbc_dirent)); + + smbc_readdir_internal(context, dirp, dirent, maxlen); + + dir->dir_next = dir->dir_next->next; + + TALLOC_FREE(frame); + return dirp; +} + +/* + * Routine to get directory entries + */ + +int +SMBC_getdents_ctx(SMBCCTX *context, + SMBCFILE *dir, + struct smbc_dirent *dirp, + int count) +{ + int rem = count; + int reqd; + int maxlen; + char *ndir = (char *)dirp; + struct smbc_dir_list *dirlist; + TALLOC_CTX *frame = talloc_stackframe(); + + /* Check that all is ok first ... */ + + if (!context || !context->initialized) { + + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + + } + + if (!dir || !SMBC_dlist_contains(context->files, dir)) { + + errno = EBADF; + TALLOC_FREE(frame); + return -1; + + } + + if (dir->file != False) { /* FIXME, should be dir, perhaps */ + + errno = ENOTDIR; + TALLOC_FREE(frame); + return -1; + + } + + /* + * Now, retrieve the number of entries that will fit in what was passed + * We have to figure out if the info is in the list, or we need to + * send a request to the server to get the info. + */ + + while ((dirlist = dir->dir_next)) { + struct smbc_dirent *dirent; + + if (!dirlist->dirent) { + + errno = ENOENT; /* Bad error */ + TALLOC_FREE(frame); + return -1; + + } + + /* Do urlencoding of next entry, if so selected */ + dirent = (struct smbc_dirent *)context->dirent; + maxlen = (sizeof(context->dirent) - + sizeof(struct smbc_dirent)); + smbc_readdir_internal(context, dirent, dirlist->dirent, maxlen); + + reqd = dirent->dirlen; + + if (rem < reqd) { + + if (rem < count) { /* We managed to copy something */ + + errno = 0; + TALLOC_FREE(frame); + return count - rem; + + } + else { /* Nothing copied ... */ + + errno = EINVAL; /* Not enough space ... */ + TALLOC_FREE(frame); + return -1; + + } + + } + + memcpy(ndir, dirent, reqd); /* Copy the data in ... */ + + ((struct smbc_dirent *)ndir)->comment = + (char *)(&((struct smbc_dirent *)ndir)->name + + dirent->namelen + + 1); + + ndir += reqd; + + rem -= reqd; + + dir->dir_next = dirlist = dirlist -> next; + } + + TALLOC_FREE(frame); + + if (rem == count) + return 0; + else + return count - rem; + +} + +/* + * Routine to create a directory ... + */ + +int +SMBC_mkdir_ctx(SMBCCTX *context, + const char *fname, + mode_t mode) +{ + SMBCSRV *srv = 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; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!fname) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + DEBUG(4, ("smbc_mkdir(%s)\n", fname)); + + if (SMBC_parse_path(frame, + 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->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + 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 */ + + } + + /*d_printf(">>>mkdir: resolving %s\n", path);*/ + if (!cli_resolve_path(frame, "", srv->cli, path, + &targetcli, &targetpath)) { + d_printf("Could not resolve %s\n", path); + TALLOC_FREE(frame); + return -1; + } + /*d_printf(">>>mkdir: resolved path as %s\n", targetpath);*/ + + if (!cli_mkdir(targetcli, targetpath)) { + + errno = SMBC_errno(context, targetcli); + TALLOC_FREE(frame); + return -1; + + } + + TALLOC_FREE(frame); + return 0; + +} + +/* + * Our list function simply checks to see if a directory is not empty + */ + +static int smbc_rmdir_dirempty = True; + +static void +rmdir_list_fn(const char *mnt, + file_info *finfo, + const char *mask, + void *state) +{ + if (strncmp(finfo->name, ".", 1) != 0 && + strncmp(finfo->name, "..", 2) != 0) { + smbc_rmdir_dirempty = False; + } +} + +/* + * Routine to remove a directory + */ + +int +SMBC_rmdir_ctx(SMBCCTX *context, + const char *fname) +{ + SMBCSRV *srv = 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; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!fname) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + DEBUG(4, ("smbc_rmdir(%s)\n", fname)); + + if (SMBC_parse_path(frame, + 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->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + 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 */ + + } + + /*d_printf(">>>rmdir: resolving %s\n", path);*/ + if (!cli_resolve_path(frame, "", srv->cli, path, + &targetcli, &targetpath)) { + d_printf("Could not resolve %s\n", path); + TALLOC_FREE(frame); + return -1; + } + /*d_printf(">>>rmdir: resolved path as %s\n", targetpath);*/ + + + if (!cli_rmdir(targetcli, targetpath)) { + + errno = SMBC_errno(context, targetcli); + + if (errno == EACCES) { /* Check if the dir empty or not */ + + /* Local storage to avoid buffer overflows */ + char *lpath; + + smbc_rmdir_dirempty = True; /* Make this so ... */ + + lpath = talloc_asprintf(frame, "%s\\*", + targetpath); + if (!lpath) { + errno = ENOMEM; + TALLOC_FREE(frame); + return -1; + } + + if (cli_list(targetcli, lpath, + aDIR | aSYSTEM | aHIDDEN, + rmdir_list_fn, NULL) < 0) { + + /* Fix errno to ignore latest error ... */ + DEBUG(5, ("smbc_rmdir: " + "cli_list returned an error: %d\n", + SMBC_errno(context, targetcli))); + errno = EACCES; + + } + + if (smbc_rmdir_dirempty) + errno = EACCES; + else + errno = ENOTEMPTY; + + } + + TALLOC_FREE(frame); + return -1; + + } + + TALLOC_FREE(frame); + return 0; + +} + +/* + * Routine to return the current directory position + */ + +off_t +SMBC_telldir_ctx(SMBCCTX *context, + SMBCFILE *dir) +{ + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + + } + + if (!dir || !SMBC_dlist_contains(context->files, dir)) { + + errno = EBADF; + TALLOC_FREE(frame); + return -1; + + } + + if (dir->file != False) { /* FIXME, should be dir, perhaps */ + + errno = ENOTDIR; + TALLOC_FREE(frame); + return -1; + + } + + /* See if we're already at the end. */ + if (dir->dir_next == NULL) { + /* We are. */ + TALLOC_FREE(frame); + return -1; + } + + /* + * We return the pointer here as the offset + */ + TALLOC_FREE(frame); + return (off_t)(long)dir->dir_next->dirent; +} + +/* + * A routine to run down the list and see if the entry is OK + */ + +static struct smbc_dir_list * +check_dir_ent(struct smbc_dir_list *list, + struct smbc_dirent *dirent) +{ + + /* Run down the list looking for what we want */ + + if (dirent) { + + struct smbc_dir_list *tmp = list; + + while (tmp) { + + if (tmp->dirent == dirent) + return tmp; + + tmp = tmp->next; + + } + + } + + return NULL; /* Not found, or an error */ + +} + + +/* + * Routine to seek on a directory + */ + +int +SMBC_lseekdir_ctx(SMBCCTX *context, + SMBCFILE *dir, + off_t offset) +{ + long int l_offset = offset; /* Handle problems of size */ + struct smbc_dirent *dirent = (struct smbc_dirent *)l_offset; + struct smbc_dir_list *list_ent = (struct smbc_dir_list *)NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + + } + + if (dir->file != False) { /* FIXME, should be dir, perhaps */ + + errno = ENOTDIR; + TALLOC_FREE(frame); + return -1; + + } + + /* Now, check what we were passed and see if it is OK ... */ + + if (dirent == NULL) { /* Seek to the begining of the list */ + + dir->dir_next = dir->dir_list; + TALLOC_FREE(frame); + return 0; + + } + + if (offset == -1) { /* Seek to the end of the list */ + dir->dir_next = NULL; + TALLOC_FREE(frame); + return 0; + } + + /* Now, run down the list and make sure that the entry is OK */ + /* This may need to be changed if we change the format of the list */ + + if ((list_ent = check_dir_ent(dir->dir_list, dirent)) == NULL) { + errno = EINVAL; /* Bad entry */ + TALLOC_FREE(frame); + return -1; + } + + dir->dir_next = list_ent; + + TALLOC_FREE(frame); + return 0; +} + +/* + * Routine to fstat a dir + */ + +int +SMBC_fstatdir_ctx(SMBCCTX *context, + SMBCFILE *dir, + struct stat *st) +{ + + if (!context || !context->initialized) { + + errno = EINVAL; + return -1; + } + + /* No code yet ... */ + return 0; +} + +int +SMBC_chmod_ctx(SMBCCTX *context, + const char *fname, + mode_t newmode) +{ + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; + uint16 mode; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->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_chmod(%s, 0%3o)\n", fname, newmode)); + + if (SMBC_parse_path(frame, + 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->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + 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 */ + } + + mode = 0; + + if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY; + if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH; + if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM; + if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN; + + if (!cli_setatr(srv->cli, path, mode, 0)) { + errno = SMBC_errno(context, srv->cli); + TALLOC_FREE(frame); + return -1; + } + + TALLOC_FREE(frame); + return 0; +} + +int +SMBC_utimes_ctx(SMBCCTX *context, + const char *fname, + struct timeval *tbuf) +{ + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; + time_t access_time; + time_t write_time; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + + errno = EINVAL; /* Best I can think of ... */ + TALLOC_FREE(frame); + return -1; + } + + if (!fname) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (tbuf == NULL) { + access_time = write_time = time(NULL); + } else { + access_time = tbuf[0].tv_sec; + write_time = tbuf[1].tv_sec; + } + + if (DEBUGLVL(4)) { + char *p; + char atimebuf[32]; + char mtimebuf[32]; + + strncpy(atimebuf, ctime(&access_time), sizeof(atimebuf) - 1); + atimebuf[sizeof(atimebuf) - 1] = '\0'; + if ((p = strchr(atimebuf, '\n')) != NULL) { + *p = '\0'; + } + + strncpy(mtimebuf, ctime(&write_time), sizeof(mtimebuf) - 1); + mtimebuf[sizeof(mtimebuf) - 1] = '\0'; + if ((p = strchr(mtimebuf, '\n')) != NULL) { + *p = '\0'; + } + + dbgtext("smbc_utimes(%s, atime = %s mtime = %s)\n", + fname, atimebuf, mtimebuf); + } + + if (SMBC_parse_path(frame, + 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->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + 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_setatr(context, srv, path, + 0, access_time, write_time, 0, 0)) { + TALLOC_FREE(frame); + return -1; /* errno set by SMBC_setatr */ + } + + TALLOC_FREE(frame); + return 0; +} + +/* + * Routine to unlink() a file + */ + +int +SMBC_unlink_ctx(SMBCCTX *context, + const char *fname) +{ + char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *workgroup = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; + SMBCSRV *srv = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + + errno = EINVAL; /* Best I can think of ... */ + TALLOC_FREE(frame); + return -1; + + } + + if (!fname) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + + } + + if (SMBC_parse_path(frame, + 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->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + return -1; + } + } + + srv = SMBC_server(frame, context, True, + server, share, &workgroup, &user, &password); + + if (!srv) { + TALLOC_FREE(frame); + return -1; /* SMBC_server sets errno */ + + } + + /*d_printf(">>>unlink: resolving %s\n", path);*/ + if (!cli_resolve_path(frame, "", srv->cli, path, + &targetcli, &targetpath)) { + d_printf("Could not resolve %s\n", path); + TALLOC_FREE(frame); + return -1; + } + /*d_printf(">>>unlink: resolved path as %s\n", targetpath);*/ + + if (!cli_unlink(targetcli, targetpath)) { + + errno = SMBC_errno(context, targetcli); + + if (errno == EACCES) { /* Check if the file is a directory */ + + int saverr = errno; + SMB_OFF_T size = 0; + uint16 mode = 0; + struct timespec write_time_ts; + struct timespec access_time_ts; + struct timespec change_time_ts; + SMB_INO_T ino = 0; + + if (!SMBC_getatr(context, srv, path, &mode, &size, + NULL, + &access_time_ts, + &write_time_ts, + &change_time_ts, + &ino)) { + + /* Hmmm, bad error ... What? */ + + errno = SMBC_errno(context, targetcli); + TALLOC_FREE(frame); + return -1; + + } + else { + + if (IS_DOS_DIR(mode)) + errno = EISDIR; + else + errno = saverr; /* Restore this */ + + } + } + + TALLOC_FREE(frame); + return -1; + + } + + TALLOC_FREE(frame); + return 0; /* Success ... */ + +} + +/* + * Routine to rename() a file + */ + +int +SMBC_rename_ctx(SMBCCTX *ocontext, + const char *oname, + SMBCCTX *ncontext, + const char *nname) +{ + char *server1 = NULL; + char *share1 = NULL; + char *server2 = NULL; + char *share2 = NULL; + char *user1 = NULL; + char *user2 = NULL; + char *password1 = NULL; + char *password2 = NULL; + char *workgroup = NULL; + char *path1 = NULL; + char *path2 = NULL; + char *targetpath1 = NULL; + char *targetpath2 = NULL; + struct cli_state *targetcli1 = NULL; + struct cli_state *targetcli2 = NULL; + SMBCSRV *srv = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!ocontext || !ncontext || + !ocontext->initialized || + !ncontext->initialized) { + + errno = EINVAL; /* Best I can think of ... */ + TALLOC_FREE(frame); + return -1; + } + + if (!oname || !nname) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + DEBUG(4, ("smbc_rename(%s,%s)\n", oname, nname)); + + if (SMBC_parse_path(frame, + ocontext, + oname, + &workgroup, + &server1, + &share1, + &path1, + &user1, + &password1, + NULL)) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!user1 || user1[0] == (char)0) { + user1 = talloc_strdup(frame, ocontext->user); + if (!user1) { + errno = ENOMEM; + TALLOC_FREE(frame); + return -1; + } + } + + if (SMBC_parse_path(frame, + ncontext, + nname, + NULL, + &server2, + &share2, + &path2, + &user2, + &password2, + NULL)) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!user2 || user2[0] == (char)0) { + user2 = talloc_strdup(frame, ncontext->user); + if (!user2) { + errno = ENOMEM; + TALLOC_FREE(frame); + return -1; + } + } + + if (strcmp(server1, server2) || strcmp(share1, share2) || + strcmp(user1, user2)) { + /* Can't rename across file systems, or users?? */ + errno = EXDEV; + TALLOC_FREE(frame); + return -1; + } + + srv = SMBC_server(frame, ocontext, True, + server1, share1, &workgroup, &user1, &password1); + if (!srv) { + TALLOC_FREE(frame); + return -1; + + } + + /*d_printf(">>>rename: resolving %s\n", path1);*/ + if (!cli_resolve_path(frame, "", srv->cli, path1, + &targetcli1, &targetpath1)) { + d_printf("Could not resolve %s\n", path1); + TALLOC_FREE(frame); + return -1; + } + /*d_printf(">>>rename: resolved path as %s\n", targetpath1);*/ + /*d_printf(">>>rename: resolving %s\n", path2);*/ + if (!cli_resolve_path(frame, "", srv->cli, path2, + &targetcli2, &targetpath2)) { + d_printf("Could not resolve %s\n", path2); + TALLOC_FREE(frame); + return -1; + } + /*d_printf(">>>rename: resolved path as %s\n", targetpath2);*/ + + if (strcmp(targetcli1->desthost, targetcli2->desthost) || + strcmp(targetcli1->share, targetcli2->share)) + { + /* can't rename across file systems */ + errno = EXDEV; + TALLOC_FREE(frame); + return -1; + } + + if (!cli_rename(targetcli1, targetpath1, targetpath2)) { + int eno = SMBC_errno(ocontext, targetcli1); + + if (eno != EEXIST || + !cli_unlink(targetcli1, targetpath2) || + !cli_rename(targetcli1, targetpath1, targetpath2)) { + + errno = eno; + TALLOC_FREE(frame); + return -1; + + } + } + + TALLOC_FREE(frame); + return 0; /* Success */ +} + diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c new file mode 100644 index 0000000000..619176697b --- /dev/null +++ b/source3/libsmb/libsmb_file.c @@ -0,0 +1,859 @@ +/* + Unix SMB/Netbios implementation. + SMB client library implementation + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000, 2002 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 3 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, see . +*/ + +#include "includes.h" +#include "libsmbclient.h" +#include "libsmb_internal.h" + + +/* + * Routine to open() a file ... + */ + +SMBCFILE * +SMBC_open_ctx(SMBCCTX *context, + const char *fname, + int flags, + mode_t mode) +{ + char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *workgroup = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; + SMBCSRV *srv = NULL; + SMBCFILE *file = NULL; + int fd; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->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)) { + errno = EINVAL; + TALLOC_FREE(frame); + return NULL; + } + + if (!user || user[0] == (char)0) { + user = talloc_strdup(frame, context->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + 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)) { + 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->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->files, file); + + /* + * If the file was opened in O_APPEND mode, all write + * operations should be appended to the file. To do that, + * though, using this protocol, would require a getattrE() + * call for each and every write, to determine where the end + * of the file is. (There does not appear to be an append flag + * in the protocol.) Rather than add all of that overhead of + * retrieving the current end-of-file offset prior to each + * write operation, we'll assume that most append operations + * will continuously write, so we'll just set the offset to + * the end of the file now and hope that's adequate. + * + * Note to self: If this proves inadequate, and O_APPEND + * should, in some cases, be forced for each write, add a + * field in the context options structure, for + * "strict_append_mode" which would select between the current + * behavior (if FALSE) or issuing a getattrE() prior to each + * write and forcing the write to the end of the file (if + * TRUE). Adding that capability will likely require adding + * an "append" flag into the _SMBCFILE structure to track + * whether a file was opened in O_APPEND mode. -- djl + */ + if (flags & O_APPEND) { + if (SMBC_lseek_ctx(context, file, 0, SEEK_END) < 0) { + (void) SMBC_close_ctx(context, file); + errno = ENXIO; + TALLOC_FREE(frame); + 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->initialized) { + + errno = EINVAL; + return NULL; + + } + + return SMBC_open_ctx(context, path, creat_bits, mode); +} + +/* + * Routine to read() a file ... + */ + +ssize_t +SMBC_read_ctx(SMBCCTX *context, + SMBCFILE *file, + void *buf, + size_t count) +{ + int ret; + char *server = NULL, *share = NULL, *user = NULL, *password = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + /* + * offset: + * + * Compiler bug (possibly) -- gcc (GCC) 3.3.5 (Debian 1:3.3.5-2) -- + * appears to pass file->offset (which is type off_t) differently than + * a local variable of type off_t. Using local variable "offset" in + * the call to cli_read() instead of file->offset fixes a problem + * retrieving data at an offset greater than 4GB. + */ + off_t offset; + + if (!context || !context->initialized) { + + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + + } + + DEBUG(4, ("smbc_read(%p, %d)\n", file, (int)count)); + + if (!file || !SMBC_dlist_contains(context->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)) { + 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)) { + d_printf("Could not resolve %s\n", path); + TALLOC_FREE(frame); + 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 ... */ + +} + +/* + * Routine to write() a file ... + */ + +ssize_t +SMBC_write_ctx(SMBCCTX *context, + SMBCFILE *file, + void *buf, + size_t count) +{ + int ret; + off_t offset; + char *server = NULL, *share = NULL, *user = NULL, *password = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + /* First check all pointers before dereferencing them */ + + if (!context || !context->initialized) { + + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + + } + + if (!file || !SMBC_dlist_contains(context->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)) { + 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)) { + d_printf("Could not resolve %s\n", path); + TALLOC_FREE(frame); + return -1; + } + /*d_printf(">>>write: resolved path as %s\n", targetpath);*/ + + 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 ... */ +} + +/* + * Routine to close() a file ... + */ + +int +SMBC_close_ctx(SMBCCTX *context, + SMBCFILE *file) +{ + SMBCSRV *srv; + char *server = NULL, *share = NULL, *user = NULL, *password = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!file || !SMBC_dlist_contains(context->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)) { + 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)) { + d_printf("Could not resolve %s\n", path); + TALLOC_FREE(frame); + 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 + * from the server cache if unused */ + errno = SMBC_errno(context, targetcli); + srv = file->srv; + DLIST_REMOVE(context->files, file); + SAFE_FREE(file->fname); + SAFE_FREE(file); + (context->server.remove_unused_server_fn)(context, srv); + TALLOC_FREE(frame); + return -1; + + } + + DLIST_REMOVE(context->files, file); + SAFE_FREE(file->fname); + SAFE_FREE(file); + TALLOC_FREE(frame); + + return 0; +} + +/* + * Get info from an SMB server on a file. Use a qpathinfo call first + * and if that fails, use getatr, as Win95 sometimes refuses qpathinfo + */ +bool +SMBC_getatr(SMBCCTX * context, + SMBCSRV *srv, + char *path, + uint16 *mode, + SMB_OFF_T *size, + struct timespec *create_time_ts, + struct timespec *access_time_ts, + struct timespec *write_time_ts, + struct timespec *change_time_ts, + SMB_INO_T *ino) +{ + char *fixedpath = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; + time_t write_time; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + /* path fixup for . and .. */ + if (strequal(path, ".") || strequal(path, "..")) { + fixedpath = talloc_strdup(frame, "\\"); + if (!fixedpath) { + errno = ENOMEM; + TALLOC_FREE(frame); + return -1; + } + } else { + fixedpath = talloc_strdup(frame, path); + if (!fixedpath) { + errno = ENOMEM; + TALLOC_FREE(frame); + return -1; + } + trim_string(fixedpath, NULL, "\\.."); + trim_string(fixedpath, NULL, "\\."); + } + DEBUG(4,("SMBC_getatr: sending qpathinfo\n")); + + if (!cli_resolve_path(frame, "", srv->cli, fixedpath, + &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, + access_time_ts, + write_time_ts, + change_time_ts, + size, mode, ino)) { + 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; + +} + +/* + * Set file info on an SMB server. Use setpathinfo call first. If that + * fails, use setattrE.. + * + * Access and modification time parameters are always used and must be + * provided. Create time, if zero, will be determined from the actual create + * time of the file. If non-zero, the create time will be set as well. + * + * "mode" (attributes) parameter may be set to -1 if it is not to be set. + */ +bool +SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, + time_t create_time, + time_t access_time, + time_t write_time, + time_t change_time, + uint16 mode) +{ + 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 + * filename rather than requiring that the file be opened to have its + * attributes manipulated. + */ + if (srv->no_pathinfo || + ! cli_setpathinfo(srv->cli, path, + create_time, + access_time, + write_time, + change_time, + mode)) { + + /* + * setpathinfo is not supported; go to plan B. + * + * cli_setatr() does not work on win98, and it also doesn't + * support setting the access time (only the modification + * time), so in all cases, we open the specified file and use + * 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 + * cli_setatr() for that, and with only this parameter, it + * seems to work on win98. + */ + 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; +} + +/* + * A routine to lseek() a file + */ + +off_t +SMBC_lseek_ctx(SMBCCTX *context, + SMBCFILE *file, + off_t offset, + int whence) +{ + SMB_OFF_T size; + char *server = NULL, *share = NULL, *user = NULL, *password = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!file || !SMBC_dlist_contains(context->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)) { + 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)) { + d_printf("Could not resolve %s\n", path); + TALLOC_FREE(frame); + 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; + if (!cli_getattrE(targetcli, file->cli_fd, + NULL, &b_size, NULL, NULL, NULL)) + { + 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; + +} + + +/* + * Routine to truncate a file given by its file descriptor, to a specified size + */ + +int +SMBC_ftruncate_ctx(SMBCCTX *context, + SMBCFILE *file, + off_t length) +{ + SMB_OFF_T size = length; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!file || !SMBC_dlist_contains(context->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, + 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)) { + d_printf("Could not resolve %s\n", path); + TALLOC_FREE(frame); + 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; + +} diff --git a/source3/libsmb/libsmb_misc.c b/source3/libsmb/libsmb_misc.c new file mode 100644 index 0000000000..f2fd919ef6 --- /dev/null +++ b/source3/libsmb/libsmb_misc.c @@ -0,0 +1,73 @@ +/* + Unix SMB/Netbios implementation. + SMB client library implementation + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000, 2002 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 3 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, see . +*/ + +#include "includes.h" +#include "libsmbclient.h" +#include "libsmb_internal.h" + + +/* + * check if an element is part of the list. + */ +int +SMBC_dlist_contains(SMBCFILE * list, SMBCFILE *p) +{ + if (!p || !list) return False; + do { + if (p == list) return True; + list = list->next; + } while (list); + return False; +} + + +/* + * Convert an SMB error into a UNIX error ... + */ +int +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; +} + diff --git a/source3/libsmb/libsmb_path.c b/source3/libsmb/libsmb_path.c new file mode 100644 index 0000000000..2533f536c3 --- /dev/null +++ b/source3/libsmb/libsmb_path.c @@ -0,0 +1,399 @@ +/* + Unix SMB/Netbios implementation. + SMB client library implementation + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000, 2002 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 3 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, see . +*/ + +#include "includes.h" +#include "libsmbclient.h" +#include "libsmb_internal.h" + + +/* Used by urldecode_talloc() */ +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; +} + +/* + * SMBC_urldecode() + * and urldecode_talloc() (internal fn.) + * + * Convert strings of %xx to their single character equivalent. Each 'x' must + * be a valid hexadecimal digit, or that % sequence is left undecoded. + * + * dest may, but need not be, the same pointer as src. + * + * Returns the number of % sequences which could not be converted due to lack + * of two following hexadecimal digits. + */ +static int +urldecode_talloc(TALLOC_CTX *ctx, char **pp_dest, const char *src) +{ + int old_length = strlen(src); + int i = 0; + 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 */ + character = (a * 16) + b; + if (character == '\0') { + break; /* Stop at %00 */ + } + i += 2; + } else { + err_count++; + } + } + 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 */ + character = (a * 16) + b; + if (character == '\0') { + break; /* Stop at %00 */ + } + i += 2; + } else { + err_count++; + } + } + *p++ = character; + } + + *p = '\0'; + *pp_dest = dest; + return err_count; +} + +int +SMBC_urldecode(char *dest, + char *src, + size_t max_dest_len) +{ + TALLOC_CTX *frame = talloc_stackframe(); + char *pdest; + int ret = urldecode_talloc(frame, &pdest, src); + + if (pdest) { + strlcpy(dest, pdest, max_dest_len); + } + TALLOC_FREE(frame); + return ret; +} + +/* + * SMBC_urlencode() + * + * Convert any characters not specifically allowed in a URL into their %xx + * equivalent. + * + * Returns the remaining buffer length. + */ +int +SMBC_urlencode(char *dest, + char *src, + int max_dest_len) +{ + char hex[] = "0123456789ABCDEF"; + + for (; *src != '\0' && max_dest_len >= 3; src++) { + + if ((*src < '0' && + *src != '-' && + *src != '.') || + (*src > '9' && + *src < 'A') || + (*src > 'Z' && + *src < 'a' && + *src != '_') || + (*src > 'z')) { + *dest++ = '%'; + *dest++ = hex[(*src >> 4) & 0x0f]; + *dest++ = hex[*src & 0x0f]; + max_dest_len -= 3; + } else { + *dest++ = *src; + max_dest_len--; + } + } + + *dest++ = '\0'; + max_dest_len--; + + return max_dest_len; +} + +/* + * Function to parse a path and turn it into components + * + * The general format of an SMB URI is explain in Christopher Hertel's CIFS + * book, at http://ubiqx.org/cifs/Appendix-D.html. We accept a subset of the + * general format ("smb:" only; we do not look for "cifs:"). + * + * + * We accept: + * smb://[[[domain;]user[:password]@]server[/share[/path[/file]]]][?options] + * + * Meaning of URLs: + * + * smb:// Show all workgroups. + * + * 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 + * 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. + * For small networks (not many workgroups), it is suggested + * that this variable be set to 0, indicating query all local + * master browsers. When the network has many workgroups, a + * reasonable setting for this variable might be around 3. + * + * smb://name/ if name<1D> or name<1B> exists, list servers in + * workgroup, else, if name<20> exists, list all shares + * for server ... + * + * If "options" are provided, this function returns the entire option list as a + * string, for later parsing by the caller. Note that currently, no options + * are supported. + */ + +static const char *smbc_prefix = "smb:"; + +int +SMBC_parse_path(TALLOC_CTX *ctx, + SMBCCTX *context, + const char *fname, + char **pp_workgroup, + char **pp_server, + char **pp_share, + char **pp_path, + char **pp_user, + char **pp_password, + char **pp_options) +{ + char *s; + 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) { + 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->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->workgroup); + + if (wl > 16) { + wl = 16; + } + + *pp_server = talloc_strdup(ctx, context->workgroup); + if (!*pp_server) { + return -1; + } + *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, ";"); + if (!workgroup) { + return -1; + } + if (pp_workgroup) { + *pp_workgroup = workgroup; + } + } + + if (strchr_m(u, ':')) { + next_token_no_ltrim_talloc(ctx, &u, pp_user, ":"); + if (!*pp_user) { + return -1; + } + *pp_password = talloc_strdup(ctx, u); + if (!*pp_password) { + return -1; + } + } else { + *pp_user = talloc_strdup(ctx, u); + if (!*pp_user) { + return -1; + } + } + } + + 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); + } else { + *pp_path = talloc_strdup(ctx, ""); + } + if (!*pp_path) { + return -1; + } + string_replace(*pp_path, '/', '\\'); + + 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; +} + diff --git a/source3/libsmb/libsmb_printjob.c b/source3/libsmb/libsmb_printjob.c new file mode 100644 index 0000000000..f106080b6f --- /dev/null +++ b/source3/libsmb/libsmb_printjob.c @@ -0,0 +1,334 @@ +/* + Unix SMB/Netbios implementation. + SMB client library implementation + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000, 2002 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 3 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, see . +*/ + +#include "includes.h" +#include "libsmbclient.h" +#include "libsmb_internal.h" + + +/* + * Open a print file to be written to by other calls + */ + +SMBCFILE * +SMBC_open_print_job_ctx(SMBCCTX *context, + const char *fname) +{ + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *path = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->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)) { + 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); +} + +/* + * Routine to print a file on a remote server ... + * + * We open the file, which we assume to be on a remote server, and then + * copy it to a print file on the share specified by printq. + */ + +int +SMBC_print_file_ctx(SMBCCTX *c_file, + const char *fname, + SMBCCTX *c_print, + const char *printq) +{ + SMBCFILE *fid1; + SMBCFILE *fid2; + int bytes; + int saverr; + int tot_bytes = 0; + char buf[4096]; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!c_file || !c_file->initialized || + !c_print || !c_print->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) { + 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) { + + 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_print)(c_print, fid2); + + if (bytes < 0) { + + errno = saverr; + TALLOC_FREE(frame); + return -1; + + } + + TALLOC_FREE(frame); + return tot_bytes; + +} + +/* + * Routine to list print jobs on a printer share ... + */ + +int +SMBC_list_print_jobs_ctx(SMBCCTX *context, + const char *fname, + smbc_list_print_job_fn fn) +{ + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->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)) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!user || user[0] == (char)0) { + user = talloc_strdup(frame, context->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + 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; + +} + +/* + * Delete a print job from a remote printer share + */ + +int +SMBC_unlink_print_job_ctx(SMBCCTX *context, + const char *fname, + int id) +{ + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; + int err; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->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)) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!user || user[0] == (char)0) { + user = talloc_strdup(frame, context->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + 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; + +} + diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c new file mode 100644 index 0000000000..978a843d30 --- /dev/null +++ b/source3/libsmb/libsmb_server.c @@ -0,0 +1,675 @@ +/* + Unix SMB/Netbios implementation. + SMB client library implementation + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000, 2002 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 3 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, see . +*/ + +#include "includes.h" +#include "libsmbclient.h" +#include "libsmb_internal.h" + + +/* + * Check a server for being alive and well. + * returns 0 if the server is in shape. Returns 1 on error + * + * Also useable outside libsmbclient to enable external cache + * to do some checks too. + */ +int +SMBC_check_server(SMBCCTX * context, + SMBCSRV * server) +{ + socklen_t size; + struct sockaddr addr; + + size = sizeof(addr); + return (getpeername(server->cli->fd, &addr, &size) == -1); +} + +/* + * Remove a server from the cached server list it's unused. + * On success, 0 is returned. 1 is returned if the server could not be removed. + * + * Also useable outside libsmbclient + */ +int +SMBC_remove_unused_server(SMBCCTX * context, + SMBCSRV * srv) +{ + SMBCFILE * file; + + /* are we being fooled ? */ + if (!context || !context->initialized || !srv) { + return 1; + } + + /* Check all open files/directories for a relation with this server */ + for (file = context->files; file; file = file->next) { + if (file->srv == srv) { + /* Still used */ + DEBUG(3, ("smbc_remove_usused_server: " + "%p still used by %p.\n", + srv, file)); + return 1; + } + } + + DLIST_REMOVE(context->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; +} + +/**************************************************************** + * Call the auth_fn with fixed size (fstring) buffers. + ***************************************************************/ +void +SMBC_call_auth_fn(TALLOC_CTX *ctx, + SMBCCTX *context, + const char *server, + const char *share, + char **pp_workgroup, + char **pp_username, + char **pp_password) +{ + 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); +} + + +void +SMBC_get_auth_data(const char *server, const char *share, + char *workgroup_buf, int workgroup_buf_len, + char *username_buf, int username_buf_len, + char *password_buf, int password_buf_len) +{ + /* Default function just uses provided data. Nothing to do. */ +} + + + +SMBCSRV * +SMBC_find_server(TALLOC_CTX *ctx, + SMBCCTX *context, + const char *server, + const char *share, + char **pp_workgroup, + char **pp_username, + char **pp_password) +{ + SMBCSRV *srv; + int auth_called = 0; + + 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])) { + SMBC_call_auth_fn(ctx, context, server, share, + 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 + * again ... + */ + auth_called = 1; + goto check_server_cache; + + } + + if (srv) { + if ((context->server.check_server_fn)(context, srv)) { + /* + * This server is no good anymore + * Try to remove it and check for more possible + * servers in the cache + */ + if ((context->server.remove_unused_server_fn)(context, + srv)) { + /* + * We could not remove the server completely, + * remove it from the cache so we will not get + * it again. It will be removed when the last + * file/dir is closed. + */ + (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; +} + +/* + * Connect to a server, possibly on an existing connection + * + * Here, what we want to do is: If the server and username + * match an existing connection, reuse that, otherwise, establish a + * new connection. + * + * If we have to create a new connection, call the auth_fn to get the + * info we need, unless the username and password were passed in. + */ + +SMBCSRV * +SMBC_server(TALLOC_CTX *ctx, + SMBCCTX *context, + bool connect_if_not_found, + const char *server, + const char *share, + char **pp_workgroup, + char **pp_username, + char **pp_password) +{ + SMBCSRV *srv=NULL; + struct cli_state *c; + struct nmb_name called, calling; + const char *server_n = server; + struct sockaddr_storage ss; + int tried_reverse = 0; + int port_try_first; + 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); + + /* + * If we found a connection and we're only allowed one share per + * server... + */ + if (srv && *share != '\0' && context->one_share_per_server) { + + /* + * ... then if there's no current connection to the share, + * connect to it. SMBC_find_server(), or rather the function + * pointed to by context->cache.get_cached_srv_fn which + * was called by SMBC_find_server(), will have issued a tree + * disconnect if the requested share is not the same as the + * one that was already connected. + */ + 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); + + if (!*pp_workgroup || !*pp_username || !*pp_password) { + errno = ENOMEM; + cli_shutdown(srv->cli); + srv->cli = NULL; + (context->cache.remove_cached_server_fn)(context, + 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)) { + + errno = SMBC_errno(context, srv->cli); + cli_shutdown(srv->cli); + srv->cli = NULL; + (context->cache.remove_cached_server_fn)(context, + srv); + srv = NULL; + } + + /* + * Regenerate the dev value since it's based on both + * server and share + */ + if (srv) { + srv->dev = (dev_t)(str_checksum(server) ^ + str_checksum(share)); + } + } + } + + /* 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->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: + + zero_addr(&ss); + + /* have to open a new connection */ + if ((c = cli_initialise()) == NULL) { + errno = ENOMEM; + return NULL; + } + + if (context->use_kerberos) { + c->use_kerberos = True; + } + if (context->fallback_after_kerberos) { + c->fallback_after_kerberos = True; + } + + c->timeout = context->timeout; + + /* + * Force use of port 139 for first try if share is $IPC, empty, or + * null, so browse lists can work + */ + if (share == NULL || *share == '\0' || strcmp(share, "IPC$") == 0) { + port_try_first = 139; + port_try_next = 445; + } else { + 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); + errno = ETIMEDOUT; + 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)) { + DEBUG(4, ("Could not convert IP address " + "%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); + goto again; + } + } + } + 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_workgroup))) { + + /* Failed. Try an anonymous login, if allowed by flags. */ + username_used = ""; + + if (context->no_auto_anonymous_login || + !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->smb_encryption_level) { + /* Attempt UNIX smb encryption. */ + if (!NT_STATUS_IS_OK(cli_force_encryption(c, + 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->smb_encryption_level == 2) { + cli_shutdown(c); + errno = EPERM; + return NULL; + } + } + 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; + if ((context->cache.add_cached_server_fn)(context, srv, + server, share, + *pp_workgroup, + *pp_username)) { + int saved_errno = errno; + DEBUG(3, (" Failed to add server to cache\n")); + errno = saved_errno; + if (errno == 0) { + errno = ENOMEM; + } + goto failed; + } + + DEBUG(2, ("Server connect ok: //%s/%s: %p\n", + server, share, srv)); + + DLIST_ADD(context->servers, srv); + return srv; + + failed: + cli_shutdown(c); + if (!srv) { + return NULL; + } + + SAFE_FREE(srv); + return NULL; +} + +/* + * Connect to a server for getting/setting attributes, possibly on an existing + * connection. This works similarly to SMBC_server(). + */ +SMBCSRV * +SMBC_attr_server(TALLOC_CTX *ctx, + SMBCCTX *context, + const char *server, + const char *share, + char **pp_workgroup, + char **pp_username, + char **pp_password) +{ + int flags; + struct sockaddr_storage ss; + struct cli_state *ipc_cli; + 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); + 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); + if (!*pp_workgroup || !*pp_username || !*pp_password) { + errno = ENOMEM; + return NULL; + } + } + + flags = 0; + if (context->use_kerberos) { + flags |= CLI_FULL_CONNECTION_USE_KERBEROS; + } + + zero_addr(&ss); + nt_status = cli_full_connection(&ipc_cli, + global_myname(), server, + &ss, 0, "IPC$", "?????", + *pp_username, + *pp_workgroup, + *pp_password, + flags, + Undefined, NULL); + if (! NT_STATUS_IS_OK(nt_status)) { + DEBUG(1,("cli_full_connection failed! (%s)\n", + nt_errstr(nt_status))); + errno = ENOTSUP; + return NULL; + } + + if (context->smb_encryption_level) { + /* Attempt UNIX smb encryption. */ + if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli, + *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->smb_encryption_level == 2) { + cli_shutdown(ipc_cli); + errno = EPERM; + return NULL; + } + } + 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; + } + + /* + * 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); + + if (!NT_STATUS_IS_OK(nt_status)) { + 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, + "*IPC$", + *pp_workgroup, + *pp_username)) { + DEBUG(3, (" Failed to add server to cache\n")); + if (errno == 0) { + errno = ENOMEM; + } + cli_shutdown(ipc_srv->cli); + free(ipc_srv); + return NULL; + } + + DLIST_ADD(context->servers, ipc_srv); + } + + return ipc_srv; +} diff --git a/source3/libsmb/libsmb_stat.c b/source3/libsmb/libsmb_stat.c new file mode 100644 index 0000000000..06238863b7 --- /dev/null +++ b/source3/libsmb/libsmb_stat.c @@ -0,0 +1,302 @@ +/* + Unix SMB/Netbios implementation. + SMB client library implementation + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000, 2002 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 3 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, see . +*/ + +#include "includes.h" +#include "libsmbclient.h" +#include "libsmb_internal.h" + + +/* + * Generate an inode number from file name for those things that need it + */ + +static ino_t +generate_inode(SMBCCTX *context, + const char *name) +{ + if (!context || !context->initialized) { + + errno = EINVAL; + return -1; + + } + + if (!*name) return 2; /* FIXME, why 2 ??? */ + return (ino_t)str_checksum(name); + +} + +/* + * Routine to put basic stat info into a stat structure ... Used by stat and + * fstat below. + */ + +static int +setup_stat(SMBCCTX *context, + 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; +#endif +#ifdef HAVE_STAT_ST_BLOCKS + st->st_blocks = (size+511)/512; +#endif +#ifdef HAVE_STRUCT_STAT_ST_RDEV + st->st_rdev = 0; +#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 ? */ + +} + +/* + * Routine to stat a file given a name + */ + +int +SMBC_stat_ctx(SMBCCTX *context, + const char *fname, + struct stat *st) +{ + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; + struct timespec write_time_ts; + struct timespec access_time_ts; + struct timespec change_time_ts; + SMB_OFF_T size = 0; + uint16 mode = 0; + SMB_INO_T ino = 0; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->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)) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!user || user[0] == (char)0) { + user = talloc_strdup(frame,context->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + 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, + &write_time_ts, + &change_time_ts, + &ino)) { + errno = SMBC_errno(context, srv->cli); + 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; + +} + +/* + * Routine to stat a file given an fd + */ + +int +SMBC_fstat_ctx(SMBCCTX *context, + SMBCFILE *file, + struct stat *st) +{ + struct timespec change_time_ts; + struct timespec access_time_ts; + struct timespec write_time_ts; + SMB_OFF_T size; + uint16 mode; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; + SMB_INO_T ino = 0; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!file || !SMBC_dlist_contains(context->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)) { + 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)) { + d_printf("Could not resolve %s\n", path); + TALLOC_FREE(frame); + 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)) { + + 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; + +} diff --git a/source3/libsmb/libsmb_xattr.c b/source3/libsmb/libsmb_xattr.c new file mode 100644 index 0000000000..93ca0706b2 --- /dev/null +++ b/source3/libsmb/libsmb_xattr.c @@ -0,0 +1,2293 @@ +/* + Unix SMB/Netbios implementation. + SMB client library implementation + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000, 2002 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 3 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, see . +*/ + +#include "includes.h" +#include "libsmbclient.h" +#include "libsmb_internal.h" + + +/* + * Find an lsa pipe handle associated with a cli struct. + */ +static struct rpc_pipe_client * +find_lsa_pipe_hnd(struct cli_state *ipc_cli) +{ + struct rpc_pipe_client *pipe_hnd; + + for (pipe_hnd = ipc_cli->pipe_list; + pipe_hnd; + pipe_hnd = pipe_hnd->next) { + + if (pipe_hnd->pipe_idx == PI_LSARPC) { + return pipe_hnd; + } + } + + return NULL; +} + +/* + * Sort ACEs according to the documentation at + * http://support.microsoft.com/kb/269175, at least as far as it defines the + * order. + */ + +static int +ace_compare(SEC_ACE *ace1, + SEC_ACE *ace2) +{ + bool b1; + bool b2; + + /* If the ACEs are equal, we have nothing more to do. */ + if (sec_ace_equal(ace1, ace2)) { + return 0; + } + + /* Inherited follow non-inherited */ + b1 = ((ace1->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0); + b2 = ((ace2->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0); + if (b1 != b2) { + return (b1 ? 1 : -1); + } + + /* + * What shall we do with AUDITs and ALARMs? It's undefined. We'll + * sort them after DENY and ALLOW. + */ + b1 = (ace1->type != SEC_ACE_TYPE_ACCESS_ALLOWED && + ace1->type != SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT && + ace1->type != SEC_ACE_TYPE_ACCESS_DENIED && + ace1->type != SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); + b2 = (ace2->type != SEC_ACE_TYPE_ACCESS_ALLOWED && + ace2->type != SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT && + ace2->type != SEC_ACE_TYPE_ACCESS_DENIED && + ace2->type != SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); + if (b1 != b2) { + return (b1 ? 1 : -1); + } + + /* Allowed ACEs follow denied ACEs */ + b1 = (ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED || + ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT); + b2 = (ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED || + ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT); + if (b1 != b2) { + return (b1 ? 1 : -1); + } + + /* + * ACEs applying to an entity's object follow those applying to the + * entity itself + */ + b1 = (ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || + ace1->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); + b2 = (ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || + ace2->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); + if (b1 != b2) { + return (b1 ? 1 : -1); + } + + /* + * If we get this far, the ACEs are similar as far as the + * characteristics we typically care about (those defined by the + * referenced MS document). We'll now sort by characteristics that + * just seems reasonable. + */ + + if (ace1->type != ace2->type) { + return ace2->type - ace1->type; + } + + if (sid_compare(&ace1->trustee, &ace2->trustee)) { + return sid_compare(&ace1->trustee, &ace2->trustee); + } + + if (ace1->flags != ace2->flags) { + return ace1->flags - ace2->flags; + } + + if (ace1->access_mask != ace2->access_mask) { + return ace1->access_mask - ace2->access_mask; + } + + if (ace1->size != ace2->size) { + return ace1->size - ace2->size; + } + + return memcmp(ace1, ace2, sizeof(SEC_ACE)); +} + + +static void +sort_acl(SEC_ACL *the_acl) +{ + uint32 i; + if (!the_acl) return; + + qsort(the_acl->aces, the_acl->num_aces, sizeof(the_acl->aces[0]), + QSORT_CAST ace_compare); + + for (i=1;inum_aces;) { + if (sec_ace_equal(&the_acl->aces[i-1], &the_acl->aces[i])) { + int j; + for (j=i; jnum_aces-1; j++) { + the_acl->aces[j] = the_acl->aces[j+1]; + } + the_acl->num_aces--; + } else { + i++; + } + } +} + +/* convert a SID to a string, either numeric or username/group */ +static void +convert_sid_to_string(struct cli_state *ipc_cli, + POLICY_HND *pol, + fstring str, + bool numeric, + DOM_SID *sid) +{ + char **domains = NULL; + char **names = NULL; + enum lsa_SidType *types = NULL; + struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli); + TALLOC_CTX *ctx; + + sid_to_fstring(str, sid); + + if (numeric) { + return; /* no lookup desired */ + } + + if (!pipe_hnd) { + return; + } + + /* Ask LSA to convert the sid to a name */ + + ctx = talloc_stackframe(); + + if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(pipe_hnd, ctx, + pol, 1, sid, &domains, + &names, &types)) || + !domains || !domains[0] || !names || !names[0]) { + TALLOC_FREE(ctx); + return; + } + + TALLOC_FREE(ctx); + /* Converted OK */ + + slprintf(str, sizeof(fstring) - 1, "%s%s%s", + domains[0], lp_winbind_separator(), + names[0]); +} + +/* convert a string to a SID, either numeric or username/group */ +static bool +convert_string_to_sid(struct cli_state *ipc_cli, + POLICY_HND *pol, + bool numeric, + DOM_SID *sid, + const char *str) +{ + enum lsa_SidType *types = NULL; + DOM_SID *sids = NULL; + bool result = True; + TALLOC_CTX *ctx = NULL; + struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli); + + if (!pipe_hnd) { + return False; + } + + if (numeric) { + if (strncmp(str, "S-", 2) == 0) { + return string_to_sid(sid, str); + } + + result = False; + goto done; + } + + ctx = talloc_stackframe(); + if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_names(pipe_hnd, ctx, + pol, 1, &str, NULL, 1, &sids, + &types))) { + result = False; + goto done; + } + + sid_copy(sid, &sids[0]); + done: + + TALLOC_FREE(ctx); + return result; +} + + +/* parse an ACE in the same format as print_ace() */ +static bool +parse_ace(struct cli_state *ipc_cli, + POLICY_HND *pol, + SEC_ACE *ace, + bool numeric, + char *str) +{ + char *p; + const char *cp; + char *tok; + unsigned int atype; + unsigned int aflags; + unsigned int amask; + DOM_SID sid; + SEC_ACCESS mask; + const struct perm_value *v; + struct perm_value { + const char *perm; + uint32 mask; + }; + TALLOC_CTX *frame = talloc_stackframe(); + + /* These values discovered by inspection */ + static const struct perm_value special_values[] = { + { "R", 0x00120089 }, + { "W", 0x00120116 }, + { "X", 0x001200a0 }, + { "D", 0x00010000 }, + { "P", 0x00040000 }, + { "O", 0x00080000 }, + { NULL, 0 }, + }; + + static const struct perm_value standard_values[] = { + { "READ", 0x001200a9 }, + { "CHANGE", 0x001301bf }, + { "FULL", 0x001f01ff }, + { NULL, 0 }, + }; + + + ZERO_STRUCTP(ace); + p = strchr_m(str,':'); + if (!p) { + TALLOC_FREE(frame); + return False; + } + *p = '\0'; + p++; + /* Try to parse numeric form */ + + if (sscanf(p, "%i/%i/%i", &atype, &aflags, &amask) == 3 && + convert_string_to_sid(ipc_cli, pol, numeric, &sid, str)) { + goto done; + } + + /* Try to parse text form */ + + if (!convert_string_to_sid(ipc_cli, pol, numeric, &sid, str)) { + TALLOC_FREE(frame); + return false; + } + + cp = p; + if (!next_token_talloc(frame, &cp, &tok, "/")) { + TALLOC_FREE(frame); + return false; + } + + if (StrnCaseCmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) { + atype = SEC_ACE_TYPE_ACCESS_ALLOWED; + } else if (StrnCaseCmp(tok, "DENIED", strlen("DENIED")) == 0) { + atype = SEC_ACE_TYPE_ACCESS_DENIED; + } else { + TALLOC_FREE(frame); + return false; + } + + /* Only numeric form accepted for flags at present */ + + if (!(next_token_talloc(frame, &cp, &tok, "/") && + sscanf(tok, "%i", &aflags))) { + TALLOC_FREE(frame); + return false; + } + + if (!next_token_talloc(frame, &cp, &tok, "/")) { + TALLOC_FREE(frame); + return false; + } + + if (strncmp(tok, "0x", 2) == 0) { + if (sscanf(tok, "%i", &amask) != 1) { + TALLOC_FREE(frame); + return false; + } + goto done; + } + + for (v = standard_values; v->perm; v++) { + if (strcmp(tok, v->perm) == 0) { + amask = v->mask; + goto done; + } + } + + p = tok; + + while(*p) { + bool found = False; + + for (v = special_values; v->perm; v++) { + if (v->perm[0] == *p) { + amask |= v->mask; + found = True; + } + } + + if (!found) { + TALLOC_FREE(frame); + return false; + } + p++; + } + + if (*p) { + TALLOC_FREE(frame); + return false; + } + + done: + mask = amask; + init_sec_ace(ace, &sid, atype, mask, aflags); + TALLOC_FREE(frame); + return true; +} + +/* add an ACE to a list of ACEs in a SEC_ACL */ +static bool +add_ace(SEC_ACL **the_acl, + SEC_ACE *ace, + TALLOC_CTX *ctx) +{ + SEC_ACL *newacl; + SEC_ACE *aces; + + if (! *the_acl) { + (*the_acl) = make_sec_acl(ctx, 3, 1, ace); + return True; + } + + if ((aces = SMB_CALLOC_ARRAY(SEC_ACE, 1+(*the_acl)->num_aces)) == NULL) { + return False; + } + memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(SEC_ACE)); + memcpy(aces+(*the_acl)->num_aces, ace, sizeof(SEC_ACE)); + newacl = make_sec_acl(ctx, (*the_acl)->revision, + 1+(*the_acl)->num_aces, aces); + SAFE_FREE(aces); + (*the_acl) = newacl; + return True; +} + + +/* parse a ascii version of a security descriptor */ +static SEC_DESC * +sec_desc_parse(TALLOC_CTX *ctx, + struct cli_state *ipc_cli, + POLICY_HND *pol, + bool numeric, + char *str) +{ + const char *p = str; + char *tok; + SEC_DESC *ret = NULL; + size_t sd_size; + DOM_SID *group_sid=NULL; + DOM_SID *owner_sid=NULL; + SEC_ACL *dacl=NULL; + int revision=1; + + while (next_token_talloc(ctx, &p, &tok, "\t,\r\n")) { + + if (StrnCaseCmp(tok,"REVISION:", 9) == 0) { + revision = strtol(tok+9, NULL, 16); + continue; + } + + if (StrnCaseCmp(tok,"OWNER:", 6) == 0) { + if (owner_sid) { + DEBUG(5, ("OWNER specified more than once!\n")); + goto done; + } + owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1); + if (!owner_sid || + !convert_string_to_sid(ipc_cli, pol, + numeric, + owner_sid, tok+6)) { + DEBUG(5, ("Failed to parse owner sid\n")); + goto done; + } + continue; + } + + if (StrnCaseCmp(tok,"OWNER+:", 7) == 0) { + if (owner_sid) { + DEBUG(5, ("OWNER specified more than once!\n")); + goto done; + } + owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1); + if (!owner_sid || + !convert_string_to_sid(ipc_cli, pol, + False, + owner_sid, tok+7)) { + DEBUG(5, ("Failed to parse owner sid\n")); + goto done; + } + continue; + } + + if (StrnCaseCmp(tok,"GROUP:", 6) == 0) { + if (group_sid) { + DEBUG(5, ("GROUP specified more than once!\n")); + goto done; + } + group_sid = SMB_CALLOC_ARRAY(DOM_SID, 1); + if (!group_sid || + !convert_string_to_sid(ipc_cli, pol, + numeric, + group_sid, tok+6)) { + DEBUG(5, ("Failed to parse group sid\n")); + goto done; + } + continue; + } + + if (StrnCaseCmp(tok,"GROUP+:", 7) == 0) { + if (group_sid) { + DEBUG(5, ("GROUP specified more than once!\n")); + goto done; + } + group_sid = SMB_CALLOC_ARRAY(DOM_SID, 1); + if (!group_sid || + !convert_string_to_sid(ipc_cli, pol, + False, + group_sid, tok+6)) { + DEBUG(5, ("Failed to parse group sid\n")); + goto done; + } + continue; + } + + if (StrnCaseCmp(tok,"ACL:", 4) == 0) { + SEC_ACE ace; + if (!parse_ace(ipc_cli, pol, &ace, numeric, tok+4)) { + DEBUG(5, ("Failed to parse ACL %s\n", tok)); + goto done; + } + if(!add_ace(&dacl, &ace, ctx)) { + DEBUG(5, ("Failed to add ACL %s\n", tok)); + goto done; + } + continue; + } + + if (StrnCaseCmp(tok,"ACL+:", 5) == 0) { + SEC_ACE ace; + if (!parse_ace(ipc_cli, pol, &ace, False, tok+5)) { + DEBUG(5, ("Failed to parse ACL %s\n", tok)); + goto done; + } + if(!add_ace(&dacl, &ace, ctx)) { + DEBUG(5, ("Failed to add ACL %s\n", tok)); + goto done; + } + continue; + } + + DEBUG(5, ("Failed to parse security descriptor\n")); + goto done; + } + + ret = make_sec_desc(ctx, revision, SEC_DESC_SELF_RELATIVE, + owner_sid, group_sid, NULL, dacl, &sd_size); + + done: + SAFE_FREE(group_sid); + SAFE_FREE(owner_sid); + + return ret; +} + + +/* Obtain the current dos attributes */ +static DOS_ATTR_DESC * +dos_attr_query(SMBCCTX *context, + TALLOC_CTX *ctx, + const char *filename, + SMBCSRV *srv) +{ + struct timespec create_time_ts; + struct timespec write_time_ts; + struct timespec access_time_ts; + struct timespec change_time_ts; + SMB_OFF_T size = 0; + uint16 mode = 0; + SMB_INO_T inode = 0; + DOS_ATTR_DESC *ret; + + ret = TALLOC_P(ctx, DOS_ATTR_DESC); + if (!ret) { + errno = ENOMEM; + return NULL; + } + + /* Obtain the DOS attributes */ + if (!SMBC_getatr(context, srv, CONST_DISCARD(char *, filename), + &mode, &size, + &create_time_ts, + &access_time_ts, + &write_time_ts, + &change_time_ts, + &inode)) { + errno = SMBC_errno(context, srv->cli); + DEBUG(5, ("dos_attr_query Failed to query old attributes\n")); + return NULL; + } + + ret->mode = mode; + ret->size = size; + ret->create_time = convert_timespec_to_time_t(create_time_ts); + ret->access_time = convert_timespec_to_time_t(access_time_ts); + ret->write_time = convert_timespec_to_time_t(write_time_ts); + ret->change_time = convert_timespec_to_time_t(change_time_ts); + ret->inode = inode; + + return ret; +} + + +/* parse a ascii version of a security descriptor */ +static void +dos_attr_parse(SMBCCTX *context, + DOS_ATTR_DESC *dad, + SMBCSRV *srv, + char *str) +{ + int n; + const char *p = str; + char *tok = NULL; + TALLOC_CTX *frame = NULL; + struct { + const char * create_time_attr; + const char * access_time_attr; + const char * write_time_attr; + const char * change_time_attr; + } attr_strings; + + /* Determine whether to use old-style or new-style attribute names */ + if (context->full_time_names) { + /* new-style names */ + attr_strings.create_time_attr = "CREATE_TIME"; + attr_strings.access_time_attr = "ACCESS_TIME"; + attr_strings.write_time_attr = "WRITE_TIME"; + attr_strings.change_time_attr = "CHANGE_TIME"; + } else { + /* old-style names */ + attr_strings.create_time_attr = NULL; + attr_strings.access_time_attr = "A_TIME"; + attr_strings.write_time_attr = "M_TIME"; + attr_strings.change_time_attr = "C_TIME"; + } + + /* if this is to set the entire ACL... */ + if (*str == '*') { + /* ... then increment past the first colon if there is one */ + if ((p = strchr(str, ':')) != NULL) { + ++p; + } else { + p = str; + } + } + + frame = talloc_stackframe(); + while (next_token_talloc(frame, &p, &tok, "\t,\r\n")) { + if (StrnCaseCmp(tok, "MODE:", 5) == 0) { + long request = strtol(tok+5, NULL, 16); + if (request == 0) { + dad->mode = (request | + (IS_DOS_DIR(dad->mode) + ? FILE_ATTRIBUTE_DIRECTORY + : FILE_ATTRIBUTE_NORMAL)); + } else { + dad->mode = request; + } + continue; + } + + if (StrnCaseCmp(tok, "SIZE:", 5) == 0) { + dad->size = (SMB_OFF_T)atof(tok+5); + continue; + } + + n = strlen(attr_strings.access_time_attr); + if (StrnCaseCmp(tok, attr_strings.access_time_attr, n) == 0) { + dad->access_time = (time_t)strtol(tok+n+1, NULL, 10); + continue; + } + + n = strlen(attr_strings.change_time_attr); + if (StrnCaseCmp(tok, attr_strings.change_time_attr, n) == 0) { + dad->change_time = (time_t)strtol(tok+n+1, NULL, 10); + continue; + } + + n = strlen(attr_strings.write_time_attr); + if (StrnCaseCmp(tok, attr_strings.write_time_attr, n) == 0) { + dad->write_time = (time_t)strtol(tok+n+1, NULL, 10); + continue; + } + + if (attr_strings.create_time_attr != NULL) { + n = strlen(attr_strings.create_time_attr); + if (StrnCaseCmp(tok, attr_strings.create_time_attr, + n) == 0) { + dad->create_time = (time_t)strtol(tok+n+1, + NULL, 10); + continue; + } + } + + if (StrnCaseCmp(tok, "INODE:", 6) == 0) { + dad->inode = (SMB_INO_T)atof(tok+6); + continue; + } + } + TALLOC_FREE(frame); +} + +/***************************************************** + Retrieve the acls for a file. +*******************************************************/ + +static int +cacl_get(SMBCCTX *context, + TALLOC_CTX *ctx, + SMBCSRV *srv, + struct cli_state *ipc_cli, + POLICY_HND *pol, + char *filename, + char *attr_name, + char *buf, + int bufsize) +{ + uint32 i; + int n = 0; + int n_used; + bool all; + bool all_nt; + bool all_nt_acls; + bool all_dos; + bool some_nt; + bool some_dos; + bool exclude_nt_revision = False; + bool exclude_nt_owner = False; + bool exclude_nt_group = False; + bool exclude_nt_acl = False; + bool exclude_dos_mode = False; + bool exclude_dos_size = False; + bool exclude_dos_create_time = False; + bool exclude_dos_access_time = False; + bool exclude_dos_write_time = False; + bool exclude_dos_change_time = False; + bool exclude_dos_inode = False; + bool numeric = True; + bool determine_size = (bufsize == 0); + int fnum = -1; + SEC_DESC *sd; + fstring sidstr; + fstring name_sandbox; + char *name; + char *pExclude; + char *p; + struct timespec create_time_ts; + struct timespec write_time_ts; + struct timespec access_time_ts; + struct timespec change_time_ts; + time_t create_time = (time_t)0; + time_t write_time = (time_t)0; + time_t access_time = (time_t)0; + time_t change_time = (time_t)0; + SMB_OFF_T size = 0; + uint16 mode = 0; + SMB_INO_T ino = 0; + struct cli_state *cli = srv->cli; + struct { + const char * create_time_attr; + const char * access_time_attr; + const char * write_time_attr; + const char * change_time_attr; + } attr_strings; + struct { + const char * create_time_attr; + const char * access_time_attr; + const char * write_time_attr; + const char * change_time_attr; + } excl_attr_strings; + + /* Determine whether to use old-style or new-style attribute names */ + if (context->full_time_names) { + /* new-style names */ + attr_strings.create_time_attr = "CREATE_TIME"; + attr_strings.access_time_attr = "ACCESS_TIME"; + attr_strings.write_time_attr = "WRITE_TIME"; + attr_strings.change_time_attr = "CHANGE_TIME"; + + excl_attr_strings.create_time_attr = "CREATE_TIME"; + excl_attr_strings.access_time_attr = "ACCESS_TIME"; + excl_attr_strings.write_time_attr = "WRITE_TIME"; + excl_attr_strings.change_time_attr = "CHANGE_TIME"; + } else { + /* old-style names */ + attr_strings.create_time_attr = NULL; + attr_strings.access_time_attr = "A_TIME"; + attr_strings.write_time_attr = "M_TIME"; + attr_strings.change_time_attr = "C_TIME"; + + excl_attr_strings.create_time_attr = NULL; + excl_attr_strings.access_time_attr = "dos_attr.A_TIME"; + excl_attr_strings.write_time_attr = "dos_attr.M_TIME"; + excl_attr_strings.change_time_attr = "dos_attr.C_TIME"; + } + + /* Copy name so we can strip off exclusions (if any are specified) */ + strncpy(name_sandbox, attr_name, sizeof(name_sandbox) - 1); + + /* Ensure name is null terminated */ + name_sandbox[sizeof(name_sandbox) - 1] = '\0'; + + /* Play in the sandbox */ + name = name_sandbox; + + /* If there are any exclusions, point to them and mask them from name */ + if ((pExclude = strchr(name, '!')) != NULL) + { + *pExclude++ = '\0'; + } + + all = (StrnCaseCmp(name, "system.*", 8) == 0); + all_nt = (StrnCaseCmp(name, "system.nt_sec_desc.*", 20) == 0); + all_nt_acls = (StrnCaseCmp(name, "system.nt_sec_desc.acl.*", 24) == 0); + all_dos = (StrnCaseCmp(name, "system.dos_attr.*", 17) == 0); + some_nt = (StrnCaseCmp(name, "system.nt_sec_desc.", 19) == 0); + some_dos = (StrnCaseCmp(name, "system.dos_attr.", 16) == 0); + numeric = (* (name + strlen(name) - 1) != '+'); + + /* Look for exclusions from "all" requests */ + if (all || all_nt || all_dos) { + + /* Exclusions are delimited by '!' */ + for (; + pExclude != NULL; + pExclude = (p == NULL ? NULL : p + 1)) { + + /* Find end of this exclusion name */ + if ((p = strchr(pExclude, '!')) != NULL) + { + *p = '\0'; + } + + /* Which exclusion name is this? */ + if (StrCaseCmp(pExclude, "nt_sec_desc.revision") == 0) { + exclude_nt_revision = True; + } + else if (StrCaseCmp(pExclude, "nt_sec_desc.owner") == 0) { + exclude_nt_owner = True; + } + else if (StrCaseCmp(pExclude, "nt_sec_desc.group") == 0) { + exclude_nt_group = True; + } + else if (StrCaseCmp(pExclude, "nt_sec_desc.acl") == 0) { + exclude_nt_acl = True; + } + else if (StrCaseCmp(pExclude, "dos_attr.mode") == 0) { + exclude_dos_mode = True; + } + else if (StrCaseCmp(pExclude, "dos_attr.size") == 0) { + exclude_dos_size = True; + } + else if (excl_attr_strings.create_time_attr != NULL && + StrCaseCmp(pExclude, + excl_attr_strings.change_time_attr) == 0) { + exclude_dos_create_time = True; + } + else if (StrCaseCmp(pExclude, + excl_attr_strings.access_time_attr) == 0) { + exclude_dos_access_time = True; + } + else if (StrCaseCmp(pExclude, + excl_attr_strings.write_time_attr) == 0) { + exclude_dos_write_time = True; + } + else if (StrCaseCmp(pExclude, + excl_attr_strings.change_time_attr) == 0) { + exclude_dos_change_time = True; + } + else if (StrCaseCmp(pExclude, "dos_attr.inode") == 0) { + exclude_dos_inode = True; + } + else { + DEBUG(5, ("cacl_get received unknown exclusion: %s\n", + pExclude)); + errno = ENOATTR; + return -1; + } + } + } + + n_used = 0; + + /* + * If we are (possibly) talking to an NT or new system and some NT + * attributes have been requested... + */ + if (ipc_cli && (all || some_nt || all_nt_acls)) { + /* Point to the portion after "system.nt_sec_desc." */ + name += 19; /* if (all) this will be invalid but unused */ + + /* ... then obtain any NT attributes which were requested */ + fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ); + + if (fnum == -1) { + DEBUG(5, ("cacl_get failed to open %s: %s\n", + filename, cli_errstr(cli))); + errno = 0; + return -1; + } + + sd = cli_query_secdesc(cli, fnum, ctx); + + if (!sd) { + DEBUG(5, + ("cacl_get Failed to query old descriptor\n")); + errno = 0; + return -1; + } + + cli_close(cli, fnum); + + if (! exclude_nt_revision) { + if (all || all_nt) { + if (determine_size) { + p = talloc_asprintf(ctx, + "REVISION:%d", + sd->revision); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "REVISION:%d", + sd->revision); + } + } else if (StrCaseCmp(name, "revision") == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%d", + sd->revision); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, "%d", + sd->revision); + } + } + + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; + n = 0; + } + + if (! exclude_nt_owner) { + /* Get owner and group sid */ + if (sd->owner_sid) { + convert_sid_to_string(ipc_cli, pol, + sidstr, + numeric, + sd->owner_sid); + } else { + fstrcpy(sidstr, ""); + } + + if (all || all_nt) { + if (determine_size) { + p = talloc_asprintf(ctx, ",OWNER:%s", + sidstr); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else if (sidstr[0] != '\0') { + n = snprintf(buf, bufsize, + ",OWNER:%s", sidstr); + } + } else if (StrnCaseCmp(name, "owner", 5) == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%s", sidstr); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, "%s", + sidstr); + } + } + + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; + n = 0; + } + + if (! exclude_nt_group) { + if (sd->group_sid) { + convert_sid_to_string(ipc_cli, pol, + sidstr, numeric, + sd->group_sid); + } else { + fstrcpy(sidstr, ""); + } + + if (all || all_nt) { + if (determine_size) { + p = talloc_asprintf(ctx, ",GROUP:%s", + sidstr); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else if (sidstr[0] != '\0') { + n = snprintf(buf, bufsize, + ",GROUP:%s", sidstr); + } + } else if (StrnCaseCmp(name, "group", 5) == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%s", sidstr); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%s", sidstr); + } + } + + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; + n = 0; + } + + if (! exclude_nt_acl) { + /* Add aces to value buffer */ + for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) { + + SEC_ACE *ace = &sd->dacl->aces[i]; + convert_sid_to_string(ipc_cli, pol, + sidstr, numeric, + &ace->trustee); + + if (all || all_nt) { + if (determine_size) { + p = talloc_asprintf( + ctx, + ",ACL:" + "%s:%d/%d/0x%08x", + sidstr, + ace->type, + ace->flags, + ace->access_mask); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf( + buf, bufsize, + ",ACL:%s:%d/%d/0x%08x", + sidstr, + ace->type, + ace->flags, + ace->access_mask); + } + } else if ((StrnCaseCmp(name, "acl", 3) == 0 && + StrCaseCmp(name+3, sidstr) == 0) || + (StrnCaseCmp(name, "acl+", 4) == 0 && + StrCaseCmp(name+4, sidstr) == 0)) { + if (determine_size) { + p = talloc_asprintf( + ctx, + "%d/%d/0x%08x", + ace->type, + ace->flags, + ace->access_mask); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%d/%d/0x%08x", + ace->type, + ace->flags, + ace->access_mask); + } + } else if (all_nt_acls) { + if (determine_size) { + p = talloc_asprintf( + ctx, + "%s%s:%d/%d/0x%08x", + i ? "," : "", + sidstr, + ace->type, + ace->flags, + ace->access_mask); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%s%s:%d/%d/0x%08x", + i ? "," : "", + sidstr, + ace->type, + ace->flags, + ace->access_mask); + } + } + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; + n = 0; + } + } + + /* Restore name pointer to its original value */ + name -= 19; + } + + if (all || some_dos) { + /* Point to the portion after "system.dos_attr." */ + name += 16; /* if (all) this will be invalid but unused */ + + /* Obtain the DOS attributes */ + if (!SMBC_getatr(context, srv, filename, &mode, &size, + &create_time_ts, + &access_time_ts, + &write_time_ts, + &change_time_ts, + &ino)) { + + errno = SMBC_errno(context, srv->cli); + return -1; + + } + + create_time = convert_timespec_to_time_t(create_time_ts); + access_time = convert_timespec_to_time_t(access_time_ts); + write_time = convert_timespec_to_time_t(write_time_ts); + change_time = convert_timespec_to_time_t(change_time_ts); + + if (! exclude_dos_mode) { + if (all || all_dos) { + if (determine_size) { + p = talloc_asprintf(ctx, + "%sMODE:0x%x", + (ipc_cli && + (all || some_nt) + ? "," + : ""), + mode); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%sMODE:0x%x", + (ipc_cli && + (all || some_nt) + ? "," + : ""), + mode); + } + } else if (StrCaseCmp(name, "mode") == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "0x%x", mode); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "0x%x", mode); + } + } + + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; + n = 0; + } + + if (! exclude_dos_size) { + if (all || all_dos) { + if (determine_size) { + p = talloc_asprintf( + ctx, + ",SIZE:%.0f", + (double)size); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + ",SIZE:%.0f", + (double)size); + } + } else if (StrCaseCmp(name, "size") == 0) { + if (determine_size) { + p = talloc_asprintf( + ctx, + "%.0f", + (double)size); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%.0f", + (double)size); + } + } + + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; + n = 0; + } + + if (! exclude_dos_create_time && + attr_strings.create_time_attr != NULL) { + if (all || all_dos) { + if (determine_size) { + p = talloc_asprintf(ctx, + ",%s:%lu", + attr_strings.create_time_attr, + create_time); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + ",%s:%lu", + attr_strings.create_time_attr, + create_time); + } + } else if (StrCaseCmp(name, attr_strings.create_time_attr) == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%lu", create_time); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%lu", create_time); + } + } + + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; + n = 0; + } + + if (! exclude_dos_access_time) { + if (all || all_dos) { + if (determine_size) { + p = talloc_asprintf(ctx, + ",%s:%lu", + attr_strings.access_time_attr, + access_time); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + ",%s:%lu", + attr_strings.access_time_attr, + access_time); + } + } else if (StrCaseCmp(name, attr_strings.access_time_attr) == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%lu", access_time); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%lu", access_time); + } + } + + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; + n = 0; + } + + if (! exclude_dos_write_time) { + if (all || all_dos) { + if (determine_size) { + p = talloc_asprintf(ctx, + ",%s:%lu", + attr_strings.write_time_attr, + write_time); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + ",%s:%lu", + attr_strings.write_time_attr, + write_time); + } + } else if (StrCaseCmp(name, attr_strings.write_time_attr) == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%lu", write_time); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%lu", write_time); + } + } + + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; + n = 0; + } + + if (! exclude_dos_change_time) { + if (all || all_dos) { + if (determine_size) { + p = talloc_asprintf(ctx, + ",%s:%lu", + attr_strings.change_time_attr, + change_time); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + ",%s:%lu", + attr_strings.change_time_attr, + change_time); + } + } else if (StrCaseCmp(name, attr_strings.change_time_attr) == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%lu", change_time); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%lu", change_time); + } + } + + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; + n = 0; + } + + if (! exclude_dos_inode) { + if (all || all_dos) { + if (determine_size) { + p = talloc_asprintf( + ctx, + ",INODE:%.0f", + (double)ino); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + ",INODE:%.0f", + (double) ino); + } + } else if (StrCaseCmp(name, "inode") == 0) { + if (determine_size) { + p = talloc_asprintf( + ctx, + "%.0f", + (double) ino); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%.0f", + (double) ino); + } + } + + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; + n = 0; + } + + /* Restore name pointer to its original value */ + name -= 16; + } + + if (n_used == 0) { + errno = ENOATTR; + return -1; + } + + return n_used; +} + +/***************************************************** +set the ACLs on a file given an ascii description +*******************************************************/ +static int +cacl_set(TALLOC_CTX *ctx, + struct cli_state *cli, + struct cli_state *ipc_cli, + POLICY_HND *pol, + const char *filename, + const char *the_acl, + int mode, + int flags) +{ + int fnum; + int err = 0; + SEC_DESC *sd = NULL, *old; + SEC_ACL *dacl = NULL; + DOM_SID *owner_sid = NULL; + DOM_SID *group_sid = NULL; + uint32 i, j; + size_t sd_size; + int ret = 0; + char *p; + bool numeric = True; + + /* the_acl will be null for REMOVE_ALL operations */ + if (the_acl) { + numeric = ((p = strchr(the_acl, ':')) != NULL && + p > the_acl && + p[-1] != '+'); + + /* if this is to set the entire ACL... */ + if (*the_acl == '*') { + /* ... then increment past the first colon */ + the_acl = p + 1; + } + + sd = sec_desc_parse(ctx, ipc_cli, pol, numeric, + CONST_DISCARD(char *, the_acl)); + + if (!sd) { + errno = EINVAL; + return -1; + } + } + + /* SMBC_XATTR_MODE_REMOVE_ALL is the only caller + that doesn't deref sd */ + + if (!sd && (mode != SMBC_XATTR_MODE_REMOVE_ALL)) { + errno = EINVAL; + return -1; + } + + /* The desired access below is the only one I could find that works + with NT4, W2KP and Samba */ + + fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ); + + if (fnum == -1) { + DEBUG(5, ("cacl_set failed to open %s: %s\n", + filename, cli_errstr(cli))); + errno = 0; + return -1; + } + + old = cli_query_secdesc(cli, fnum, ctx); + + if (!old) { + DEBUG(5, ("cacl_set Failed to query old descriptor\n")); + errno = 0; + return -1; + } + + cli_close(cli, fnum); + + switch (mode) { + case SMBC_XATTR_MODE_REMOVE_ALL: + old->dacl->num_aces = 0; + dacl = old->dacl; + break; + + case SMBC_XATTR_MODE_REMOVE: + for (i=0;sd->dacl && idacl->num_aces;i++) { + bool found = False; + + for (j=0;old->dacl && jdacl->num_aces;j++) { + if (sec_ace_equal(&sd->dacl->aces[i], + &old->dacl->aces[j])) { + uint32 k; + for (k=j; kdacl->num_aces-1;k++) { + old->dacl->aces[k] = + old->dacl->aces[k+1]; + } + old->dacl->num_aces--; + found = True; + dacl = old->dacl; + break; + } + } + + if (!found) { + err = ENOATTR; + ret = -1; + goto failed; + } + } + break; + + case SMBC_XATTR_MODE_ADD: + for (i=0;sd->dacl && idacl->num_aces;i++) { + bool found = False; + + for (j=0;old->dacl && jdacl->num_aces;j++) { + if (sid_equal(&sd->dacl->aces[i].trustee, + &old->dacl->aces[j].trustee)) { + if (!(flags & SMBC_XATTR_FLAG_CREATE)) { + err = EEXIST; + ret = -1; + goto failed; + } + old->dacl->aces[j] = sd->dacl->aces[i]; + ret = -1; + found = True; + } + } + + if (!found && (flags & SMBC_XATTR_FLAG_REPLACE)) { + err = ENOATTR; + ret = -1; + goto failed; + } + + for (i=0;sd->dacl && idacl->num_aces;i++) { + add_ace(&old->dacl, &sd->dacl->aces[i], ctx); + } + } + dacl = old->dacl; + break; + + case SMBC_XATTR_MODE_SET: + old = sd; + owner_sid = old->owner_sid; + group_sid = old->group_sid; + dacl = old->dacl; + break; + + case SMBC_XATTR_MODE_CHOWN: + owner_sid = sd->owner_sid; + break; + + case SMBC_XATTR_MODE_CHGRP: + group_sid = sd->group_sid; + break; + } + + /* Denied ACE entries must come before allowed ones */ + sort_acl(old->dacl); + + /* Create new security descriptor and set it */ + sd = make_sec_desc(ctx, old->revision, SEC_DESC_SELF_RELATIVE, + owner_sid, group_sid, NULL, dacl, &sd_size); + + fnum = cli_nt_create(cli, filename, + WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS); + + if (fnum == -1) { + DEBUG(5, ("cacl_set failed to open %s: %s\n", + filename, cli_errstr(cli))); + errno = 0; + return -1; + } + + if (!cli_set_secdesc(cli, fnum, sd)) { + DEBUG(5, ("ERROR: secdesc set failed: %s\n", cli_errstr(cli))); + ret = -1; + } + + /* Clean up */ + + failed: + cli_close(cli, fnum); + + if (err != 0) { + errno = err; + } + + return ret; +} + + +int +SMBC_setxattr_ctx(SMBCCTX *context, + const char *fname, + const char *name, + const void *value, + size_t size, + int flags) +{ + int ret; + int ret2; + SMBCSRV *srv = NULL; + SMBCSRV *ipc_srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; + DOS_ATTR_DESC *dad = NULL; + struct { + const char * create_time_attr; + const char * access_time_attr; + const char * write_time_attr; + const char * change_time_attr; + } attr_strings; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->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_setxattr(%s, %s, %.*s)\n", + fname, name, (int) size, (const char*)value)); + + if (SMBC_parse_path(frame, + 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->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + 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 (! srv->no_nt_session) { + ipc_srv = SMBC_attr_server(frame, context, server, share, + &workgroup, &user, &password); + if (! ipc_srv) { + srv->no_nt_session = True; + } + } else { + ipc_srv = NULL; + } + + /* + * Are they asking to set the entire set of known attributes? + */ + if (StrCaseCmp(name, "system.*") == 0 || + StrCaseCmp(name, "system.*+") == 0) { + /* Yup. */ + char *namevalue = + talloc_asprintf(talloc_tos(), "%s:%s", + name+7, (const char *) value); + if (! namevalue) { + errno = ENOMEM; + ret = -1; + TALLOC_FREE(frame); + return -1; + } + + if (ipc_srv) { + ret = cacl_set(talloc_tos(), srv->cli, + ipc_srv->cli, &ipc_srv->pol, path, + namevalue, + (*namevalue == '*' + ? SMBC_XATTR_MODE_SET + : SMBC_XATTR_MODE_ADD), + flags); + } else { + ret = 0; + } + + /* get a DOS Attribute Descriptor with current attributes */ + dad = dos_attr_query(context, talloc_tos(), path, srv); + if (dad) { + /* Overwrite old with new, using what was provided */ + dos_attr_parse(context, dad, srv, namevalue); + + /* Set the new DOS attributes */ + if (! SMBC_setatr(context, srv, path, + dad->create_time, + dad->access_time, + dad->write_time, + dad->change_time, + dad->mode)) { + + /* cause failure if NT failed too */ + dad = NULL; + } + } + + /* we only fail if both NT and DOS sets failed */ + if (ret < 0 && ! dad) { + ret = -1; /* in case dad was null */ + } + else { + ret = 0; + } + + TALLOC_FREE(frame); + return ret; + } + + /* + * Are they asking to set an access control element or to set + * the entire access control list? + */ + if (StrCaseCmp(name, "system.nt_sec_desc.*") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.*+") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.revision") == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) { + + /* Yup. */ + char *namevalue = + talloc_asprintf(talloc_tos(), "%s:%s", + name+19, (const char *) value); + + if (! ipc_srv) { + ret = -1; /* errno set by SMBC_server() */ + } + else if (! namevalue) { + errno = ENOMEM; + ret = -1; + } else { + ret = cacl_set(talloc_tos(), srv->cli, + ipc_srv->cli, &ipc_srv->pol, path, + namevalue, + (*namevalue == '*' + ? SMBC_XATTR_MODE_SET + : SMBC_XATTR_MODE_ADD), + flags); + } + TALLOC_FREE(frame); + return ret; + } + + /* + * Are they asking to set the owner? + */ + if (StrCaseCmp(name, "system.nt_sec_desc.owner") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.owner+") == 0) { + + /* Yup. */ + char *namevalue = + talloc_asprintf(talloc_tos(), "%s:%s", + name+19, (const char *) value); + + if (! ipc_srv) { + ret = -1; /* errno set by SMBC_server() */ + } + else if (! namevalue) { + errno = ENOMEM; + ret = -1; + } else { + ret = cacl_set(talloc_tos(), srv->cli, + ipc_srv->cli, &ipc_srv->pol, path, + namevalue, SMBC_XATTR_MODE_CHOWN, 0); + } + TALLOC_FREE(frame); + return ret; + } + + /* + * Are they asking to set the group? + */ + if (StrCaseCmp(name, "system.nt_sec_desc.group") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.group+") == 0) { + + /* Yup. */ + char *namevalue = + talloc_asprintf(talloc_tos(), "%s:%s", + name+19, (const char *) value); + + if (! ipc_srv) { + /* errno set by SMBC_server() */ + ret = -1; + } + else if (! namevalue) { + errno = ENOMEM; + ret = -1; + } else { + ret = cacl_set(talloc_tos(), srv->cli, + ipc_srv->cli, &ipc_srv->pol, path, + namevalue, SMBC_XATTR_MODE_CHGRP, 0); + } + TALLOC_FREE(frame); + return ret; + } + + /* Determine whether to use old-style or new-style attribute names */ + if (context->full_time_names) { + /* new-style names */ + attr_strings.create_time_attr = "system.dos_attr.CREATE_TIME"; + attr_strings.access_time_attr = "system.dos_attr.ACCESS_TIME"; + attr_strings.write_time_attr = "system.dos_attr.WRITE_TIME"; + attr_strings.change_time_attr = "system.dos_attr.CHANGE_TIME"; + } else { + /* old-style names */ + attr_strings.create_time_attr = NULL; + attr_strings.access_time_attr = "system.dos_attr.A_TIME"; + attr_strings.write_time_attr = "system.dos_attr.M_TIME"; + attr_strings.change_time_attr = "system.dos_attr.C_TIME"; + } + + /* + * Are they asking to set a DOS attribute? + */ + if (StrCaseCmp(name, "system.dos_attr.*") == 0 || + StrCaseCmp(name, "system.dos_attr.mode") == 0 || + (attr_strings.create_time_attr != NULL && + StrCaseCmp(name, attr_strings.create_time_attr) == 0) || + StrCaseCmp(name, attr_strings.access_time_attr) == 0 || + StrCaseCmp(name, attr_strings.write_time_attr) == 0 || + StrCaseCmp(name, attr_strings.change_time_attr) == 0) { + + /* get a DOS Attribute Descriptor with current attributes */ + dad = dos_attr_query(context, talloc_tos(), path, srv); + if (dad) { + char *namevalue = + talloc_asprintf(talloc_tos(), "%s:%s", + name+16, (const char *) value); + if (! namevalue) { + errno = ENOMEM; + ret = -1; + } else { + /* Overwrite old with provided new params */ + dos_attr_parse(context, dad, srv, namevalue); + + /* Set the new DOS attributes */ + ret2 = SMBC_setatr(context, srv, path, + dad->create_time, + dad->access_time, + dad->write_time, + dad->change_time, + dad->mode); + + /* ret2 has True (success) / False (failure) */ + if (ret2) { + ret = 0; + } else { + ret = -1; + } + } + } else { + ret = -1; + } + + TALLOC_FREE(frame); + return ret; + } + + /* Unsupported attribute name */ + errno = EINVAL; + TALLOC_FREE(frame); + return -1; +} + +int +SMBC_getxattr_ctx(SMBCCTX *context, + const char *fname, + const char *name, + const void *value, + size_t size) +{ + int ret; + SMBCSRV *srv = NULL; + SMBCSRV *ipc_srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; + struct { + const char * create_time_attr; + const char * access_time_attr; + const char * write_time_attr; + const char * change_time_attr; + } attr_strings; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->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_getxattr(%s, %s)\n", fname, name)); + + if (SMBC_parse_path(frame, + 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->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + 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 (! srv->no_nt_session) { + ipc_srv = SMBC_attr_server(frame, context, server, share, + &workgroup, &user, &password); + if (! ipc_srv) { + srv->no_nt_session = True; + } + } else { + ipc_srv = NULL; + } + + /* Determine whether to use old-style or new-style attribute names */ + if (context->full_time_names) { + /* new-style names */ + attr_strings.create_time_attr = "system.dos_attr.CREATE_TIME"; + attr_strings.access_time_attr = "system.dos_attr.ACCESS_TIME"; + attr_strings.write_time_attr = "system.dos_attr.WRITE_TIME"; + attr_strings.change_time_attr = "system.dos_attr.CHANGE_TIME"; + } else { + /* old-style names */ + attr_strings.create_time_attr = NULL; + attr_strings.access_time_attr = "system.dos_attr.A_TIME"; + attr_strings.write_time_attr = "system.dos_attr.M_TIME"; + attr_strings.change_time_attr = "system.dos_attr.C_TIME"; + } + + /* Are they requesting a supported attribute? */ + if (StrCaseCmp(name, "system.*") == 0 || + StrnCaseCmp(name, "system.*!", 9) == 0 || + StrCaseCmp(name, "system.*+") == 0 || + StrnCaseCmp(name, "system.*+!", 10) == 0 || + StrCaseCmp(name, "system.nt_sec_desc.*") == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.*!", 21) == 0 || + StrCaseCmp(name, "system.nt_sec_desc.*+") == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.*+!", 22) == 0 || + StrCaseCmp(name, "system.nt_sec_desc.revision") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.owner") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.owner+") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.group") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.group+") == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0 || + StrCaseCmp(name, "system.dos_attr.*") == 0 || + StrnCaseCmp(name, "system.dos_attr.*!", 18) == 0 || + StrCaseCmp(name, "system.dos_attr.mode") == 0 || + StrCaseCmp(name, "system.dos_attr.size") == 0 || + (attr_strings.create_time_attr != NULL && + StrCaseCmp(name, attr_strings.create_time_attr) == 0) || + StrCaseCmp(name, attr_strings.access_time_attr) == 0 || + StrCaseCmp(name, attr_strings.write_time_attr) == 0 || + StrCaseCmp(name, attr_strings.change_time_attr) == 0 || + StrCaseCmp(name, "system.dos_attr.inode") == 0) { + + /* Yup. */ + ret = cacl_get(context, talloc_tos(), srv, + ipc_srv == NULL ? NULL : ipc_srv->cli, + &ipc_srv->pol, path, + CONST_DISCARD(char *, name), + CONST_DISCARD(char *, value), size); + if (ret < 0 && errno == 0) { + errno = SMBC_errno(context, srv->cli); + } + TALLOC_FREE(frame); + return ret; + } + + /* Unsupported attribute name */ + errno = EINVAL; + TALLOC_FREE(frame); + return -1; +} + + +int +SMBC_removexattr_ctx(SMBCCTX *context, + const char *fname, + const char *name) +{ + int ret; + SMBCSRV *srv = NULL; + SMBCSRV *ipc_srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->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_removexattr(%s, %s)\n", fname, name)); + + if (SMBC_parse_path(frame, + 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->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + 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 (! srv->no_nt_session) { + ipc_srv = SMBC_attr_server(frame, context, server, share, + &workgroup, &user, &password); + if (! ipc_srv) { + srv->no_nt_session = True; + } + } else { + ipc_srv = NULL; + } + + if (! ipc_srv) { + TALLOC_FREE(frame); + return -1; /* errno set by SMBC_attr_server */ + } + + /* Are they asking to set the entire ACL? */ + if (StrCaseCmp(name, "system.nt_sec_desc.*") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.*+") == 0) { + + /* Yup. */ + ret = cacl_set(talloc_tos(), srv->cli, + ipc_srv->cli, &ipc_srv->pol, path, + NULL, SMBC_XATTR_MODE_REMOVE_ALL, 0); + TALLOC_FREE(frame); + return ret; + } + + /* + * Are they asking to remove one or more spceific security descriptor + * attributes? + */ + if (StrCaseCmp(name, "system.nt_sec_desc.revision") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.owner") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.owner+") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.group") == 0 || + StrCaseCmp(name, "system.nt_sec_desc.group+") == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) { + + /* Yup. */ + ret = cacl_set(talloc_tos(), srv->cli, + ipc_srv->cli, &ipc_srv->pol, path, + name + 19, SMBC_XATTR_MODE_REMOVE, 0); + TALLOC_FREE(frame); + return ret; + } + + /* Unsupported attribute name */ + errno = EINVAL; + TALLOC_FREE(frame); + return -1; +} + +int +SMBC_listxattr_ctx(SMBCCTX *context, + const char *fname, + char *list, + size_t size) +{ + /* + * This isn't quite what listxattr() is supposed to do. This returns + * the complete set of attribute names, always, rather than only those + * attribute names which actually exist for a file. Hmmm... + */ + size_t retsize; + const char supported_old[] = + "system.*\0" + "system.*+\0" + "system.nt_sec_desc.revision\0" + "system.nt_sec_desc.owner\0" + "system.nt_sec_desc.owner+\0" + "system.nt_sec_desc.group\0" + "system.nt_sec_desc.group+\0" + "system.nt_sec_desc.acl.*\0" + "system.nt_sec_desc.acl\0" + "system.nt_sec_desc.acl+\0" + "system.nt_sec_desc.*\0" + "system.nt_sec_desc.*+\0" + "system.dos_attr.*\0" + "system.dos_attr.mode\0" + "system.dos_attr.c_time\0" + "system.dos_attr.a_time\0" + "system.dos_attr.m_time\0" + ; + const char supported_new[] = + "system.*\0" + "system.*+\0" + "system.nt_sec_desc.revision\0" + "system.nt_sec_desc.owner\0" + "system.nt_sec_desc.owner+\0" + "system.nt_sec_desc.group\0" + "system.nt_sec_desc.group+\0" + "system.nt_sec_desc.acl.*\0" + "system.nt_sec_desc.acl\0" + "system.nt_sec_desc.acl+\0" + "system.nt_sec_desc.*\0" + "system.nt_sec_desc.*+\0" + "system.dos_attr.*\0" + "system.dos_attr.mode\0" + "system.dos_attr.create_time\0" + "system.dos_attr.access_time\0" + "system.dos_attr.write_time\0" + "system.dos_attr.change_time\0" + ; + const char * supported; + + if (context->full_time_names) { + supported = supported_new; + retsize = sizeof(supported_new); + } else { + supported = supported_old; + retsize = sizeof(supported_old); + } + + if (size == 0) { + return retsize; + } + + if (retsize > size) { + errno = ERANGE; + return -1; + } + + /* this can't be strcpy() because there are embedded null characters */ + memcpy(list, supported, retsize); + return retsize; +} diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c deleted file mode 100644 index fe008ed6b6..0000000000 --- a/source3/libsmb/libsmbclient.c +++ /dev/null @@ -1,7233 +0,0 @@ -/* - Unix SMB/Netbios implementation. - SMB client library implementation - Copyright (C) Andrew Tridgell 1998 - Copyright (C) Richard Sharpe 2000, 2002 - Copyright (C) John Terpstra 2000 - Copyright (C) Tom Jansen (Ninja ISD) 2002 - Copyright (C) Derrell Lipman 2003, 2004 - Copyright (C) Jeremy Allison 2007, 2008 - - 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 3 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, see . -*/ - -#include "includes.h" - -#include "include/libsmb_internal.h" - -struct smbc_dirent *smbc_readdir_ctx(SMBCCTX *context, SMBCFILE *dir); -struct smbc_dir_list *smbc_check_dir_ent(struct smbc_dir_list *list, - struct smbc_dirent *dirent); - -/* - * DOS Attribute values (used internally) - */ -typedef struct DOS_ATTR_DESC { - int mode; - SMB_OFF_T size; - time_t create_time; - time_t access_time; - time_t write_time; - time_t change_time; - SMB_INO_T inode; -} DOS_ATTR_DESC; - - -/* - * Internal flags for extended attributes - */ - -/* internal mode values */ -#define SMBC_XATTR_MODE_ADD 1 -#define SMBC_XATTR_MODE_REMOVE 2 -#define SMBC_XATTR_MODE_REMOVE_ALL 3 -#define SMBC_XATTR_MODE_SET 4 -#define SMBC_XATTR_MODE_CHOWN 5 -#define SMBC_XATTR_MODE_CHGRP 6 - -#define CREATE_ACCESS_READ READ_CONTROL_ACCESS - -/*We should test for this in configure ... */ -#ifndef ENOTSUP -#define ENOTSUP EOPNOTSUPP -#endif - -/* - * Functions exported by libsmb_cache.c that we need here - */ -int smbc_default_cache_functions(SMBCCTX *context); - -/* - * check if an element is part of the list. - * FIXME: Does not belong here ! - * Can anyone put this in a macro in dlinklist.h ? - * -- Tom - */ -static int DLIST_CONTAINS(SMBCFILE * list, SMBCFILE *p) { - if (!p || !list) return False; - do { - if (p == list) return True; - list = list->next; - } while (list); - return False; -} - -/* - * Find an lsa pipe handle associated with a cli struct. - */ -static struct rpc_pipe_client * -find_lsa_pipe_hnd(struct cli_state *ipc_cli) -{ - struct rpc_pipe_client *pipe_hnd; - - for (pipe_hnd = ipc_cli->pipe_list; - pipe_hnd; - pipe_hnd = pipe_hnd->next) { - - if (pipe_hnd->pipe_idx == PI_LSARPC) { - return pipe_hnd; - } - } - - return NULL; -} - -static int -smbc_close_ctx(SMBCCTX *context, - SMBCFILE *file); -static off_t -smbc_lseek_ctx(SMBCCTX *context, - SMBCFILE *file, - off_t offset, - int whence); - -extern bool in_client; - -/* - * Is the logging working / configfile read ? - */ -static int smbc_initialized = 0; - -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; -} - -/* - * smbc_urldecode() - * and smbc_urldecode_talloc() (internal fn.) - * - * Convert strings of %xx to their single character equivalent. Each 'x' must - * be a valid hexadecimal digit, or that % sequence is left undecoded. - * - * dest may, but need not be, the same pointer as src. - * - * Returns the number of % sequences which could not be converted due to lack - * of two following hexadecimal digits. - */ -static int -smbc_urldecode_talloc(TALLOC_CTX *ctx, char **pp_dest, const char *src) -{ - int old_length = strlen(src); - int i = 0; - 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 */ - character = (a * 16) + b; - if (character == '\0') { - break; /* Stop at %00 */ - } - i += 2; - } else { - err_count++; - } - } - 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 */ - character = (a * 16) + b; - if (character == '\0') { - break; /* Stop at %00 */ - } - i += 2; - } else { - err_count++; - } - } - *p++ = character; - } - - *p = '\0'; - *pp_dest = dest; - return err_count; -} - -int -smbc_urldecode(char *dest, char *src, size_t max_dest_len) -{ - TALLOC_CTX *frame = talloc_stackframe(); - char *pdest; - int ret = smbc_urldecode_talloc(frame, &pdest, src); - - if (pdest) { - strlcpy(dest, pdest, max_dest_len); - } - TALLOC_FREE(frame); - return ret; -} - -/* - * smbc_urlencode() - * - * Convert any characters not specifically allowed in a URL into their %xx - * equivalent. - * - * Returns the remaining buffer length. - */ -int -smbc_urlencode(char *dest, char *src, int max_dest_len) -{ - char hex[] = "0123456789ABCDEF"; - - for (; *src != '\0' && max_dest_len >= 3; src++) { - - if ((*src < '0' && - *src != '-' && - *src != '.') || - (*src > '9' && - *src < 'A') || - (*src > 'Z' && - *src < 'a' && - *src != '_') || - (*src > 'z')) { - *dest++ = '%'; - *dest++ = hex[(*src >> 4) & 0x0f]; - *dest++ = hex[*src & 0x0f]; - max_dest_len -= 3; - } else { - *dest++ = *src; - max_dest_len--; - } - } - - *dest++ = '\0'; - max_dest_len--; - - return max_dest_len; -} - -/* - * Function to parse a path and turn it into components - * - * The general format of an SMB URI is explain in Christopher Hertel's CIFS - * book, at http://ubiqx.org/cifs/Appendix-D.html. We accept a subset of the - * general format ("smb:" only; we do not look for "cifs:"). - * - * - * We accept: - * smb://[[[domain;]user[:password]@]server[/share[/path[/file]]]][?options] - * - * Meaning of URLs: - * - * smb:// Show all workgroups. - * - * The method of locating the list of workgroups varies - * depending upon the setting of the context variable - * context->options.browse_max_lmb_count. This value - * determine 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. - * For small networks (not many workgroups), it is suggested - * that this variable be set to 0, indicating query all local - * master browsers. When the network has many workgroups, a - * reasonable setting for this variable might be around 3. - * - * smb://name/ if name<1D> or name<1B> exists, list servers in - * workgroup, else, if name<20> exists, list all shares - * for server ... - * - * If "options" are provided, this function returns the entire option list as a - * string, for later parsing by the caller. Note that currently, no options - * are supported. - */ - -static const char *smbc_prefix = "smb:"; - -static int -smbc_parse_path(TALLOC_CTX *ctx, - SMBCCTX *context, - const char *fname, - char **pp_workgroup, - char **pp_server, - char **pp_share, - char **pp_path, - char **pp_user, - char **pp_password, - char **pp_options) -{ - char *s; - 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) { - 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->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->workgroup); - - if (wl > 16) { - wl = 16; - } - - *pp_server = talloc_strdup(ctx, context->workgroup); - if (!*pp_server) { - return -1; - } - *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, ";"); - if (!workgroup) { - return -1; - } - if (pp_workgroup) { - *pp_workgroup = workgroup; - } - } - - if (strchr_m(u, ':')) { - next_token_no_ltrim_talloc(ctx, &u, pp_user, ":"); - if (!*pp_user) { - return -1; - } - *pp_password = talloc_strdup(ctx, u); - if (!*pp_password) { - return -1; - } - } else { - *pp_user = talloc_strdup(ctx, u); - if (!*pp_user) { - return -1; - } - } - } - - 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); - } else { - *pp_path = talloc_strdup(ctx, ""); - } - if (!*pp_path) { - return -1; - } - string_replace(*pp_path, '/', '\\'); - - decoding: - - (void) smbc_urldecode_talloc(ctx, pp_path, *pp_path); - (void) smbc_urldecode_talloc(ctx, pp_server, *pp_server); - (void) smbc_urldecode_talloc(ctx, pp_share, *pp_share); - (void) smbc_urldecode_talloc(ctx, pp_user, *pp_user); - (void) smbc_urldecode_talloc(ctx, pp_password, *pp_password); - - return 0; -} - -/* - * Verify that the options specified in a URL are valid - */ -static int -smbc_check_options(char *server, - char *share, - char *path, - char *options) -{ - DEBUG(4, ("smbc_check_options(): server='%s' share='%s' " - "path='%s' options='%s'\n", - server, share, path, options)); - - /* No options at all is always ok */ - if (! *options) return 0; - - /* Currently, we don't support any options. */ - return -1; -} - -/* - * Convert an SMB error into a UNIX error ... - */ -static int -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; -} - -/* - * Check a server for being alive and well. - * returns 0 if the server is in shape. Returns 1 on error - * - * Also useable outside libsmbclient to enable external cache - * to do some checks too. - */ -static int -smbc_check_server(SMBCCTX * context, - SMBCSRV * server) -{ - socklen_t size; - struct sockaddr addr; - - size = sizeof(addr); - return (getpeername(server->cli->fd, &addr, &size) == -1); -} - -/* - * Remove a server from the cached server list it's unused. - * On success, 0 is returned. 1 is returned if the server could not be removed. - * - * Also useable outside libsmbclient - */ -int -smbc_remove_unused_server(SMBCCTX * context, - SMBCSRV * srv) -{ - SMBCFILE * file; - - /* are we being fooled ? */ - if (!context || !context->internal || - !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) { - /* Still used */ - DEBUG(3, ("smbc_remove_usused_server: " - "%p still used by %p.\n", - srv, file)); - 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->callbacks.remove_cached_srv_fn)(context, srv); - - SAFE_FREE(srv); - return 0; -} - -/**************************************************************** - * Call the auth_fn with fixed size (fstring) buffers. - ***************************************************************/ - -static void call_auth_fn(TALLOC_CTX *ctx, - SMBCCTX *context, - const char *server, - const char *share, - char **pp_workgroup, - char **pp_username, - char **pp_password) -{ - fstring workgroup; - fstring username; - fstring password; - - strlcpy(workgroup, *pp_workgroup, sizeof(workgroup)); - strlcpy(username, *pp_username, sizeof(username)); - strlcpy(password, *pp_password, sizeof(password)); - - if (context->internal->_auth_fn_with_context != NULL) { - (context->internal->_auth_fn_with_context)( - context, - server, share, - workgroup, sizeof(workgroup), - username, sizeof(username), - password, sizeof(password)); - } else { - (context->callbacks.auth_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); -} - -static SMBCSRV * -find_server(TALLOC_CTX *ctx, - SMBCCTX *context, - const char *server, - const char *share, - char **pp_workgroup, - char **pp_username, - char **pp_password) -{ - SMBCSRV *srv; - int auth_called = 0; - - check_server_cache: - - srv = (context->callbacks.get_cached_srv_fn)(context, server, share, - *pp_workgroup, *pp_username); - - if (!auth_called && !srv && (!*pp_username || !(*pp_username)[0] || - !*pp_password || !(*pp_password)[0])) { - call_auth_fn(ctx, context, server, share, - 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 - * again ... - */ - auth_called = 1; - goto check_server_cache; - - } - - if (srv) { - if ((context->callbacks.check_server_fn)(context, srv)) { - /* - * This server is no good anymore - * Try to remove it and check for more possible - * servers in the cache - */ - if ((context->callbacks.remove_unused_server_fn)(context, - srv)) { - /* - * We could not remove the server completely, - * remove it from the cache so we will not get - * it again. It will be removed when the last - * file/dir is closed. - */ - (context->callbacks.remove_cached_srv_fn)(context, - srv); - } - - /* - * Maybe there are more cached connections to this - * server - */ - goto check_server_cache; - } - - return srv; - } - - return NULL; -} - -/* - * Connect to a server, possibly on an existing connection - * - * Here, what we want to do is: If the server and username - * match an existing connection, reuse that, otherwise, establish a - * new connection. - * - * If we have to create a new connection, call the auth_fn to get the - * info we need, unless the username and password were passed in. - */ - -static SMBCSRV * -smbc_server(TALLOC_CTX *ctx, - SMBCCTX *context, - bool connect_if_not_found, - const char *server, - const char *share, - char **pp_workgroup, - char **pp_username, - char **pp_password) -{ - SMBCSRV *srv=NULL; - struct cli_state *c; - struct nmb_name called, calling; - const char *server_n = server; - struct sockaddr_storage ss; - int tried_reverse = 0; - int port_try_first; - 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 = find_server(ctx, context, server, share, - 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->options.one_share_per_server) { - - /* - * ... then if there's no current connection to the share, - * connect to it. find_server(), or rather the function - * pointed to by context->callbacks.get_cached_srv_fn which - * was called by find_server(), will have issued a tree - * disconnect if the requested share is not the same as the - * one that was already connected. - */ - if (srv->cli->cnum == (uint16) -1) { - /* Ensure we have accurate auth info */ - call_auth_fn(ctx, context, server, share, - pp_workgroup, pp_username, pp_password); - - if (!*pp_workgroup || !*pp_username || !*pp_password) { - errno = ENOMEM; - cli_shutdown(srv->cli); - srv->cli = NULL; - (context->callbacks.remove_cached_srv_fn)(context, - 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)) { - - errno = smbc_errno(context, srv->cli); - cli_shutdown(srv->cli); - srv->cli = NULL; - (context->callbacks.remove_cached_srv_fn)(context, - srv); - srv = NULL; - } - - /* - * Regenerate the dev value since it's based on both - * server and share - */ - if (srv) { - srv->dev = (dev_t)(str_checksum(server) ^ - str_checksum(share)); - } - } - } - - /* 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->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: - - zero_addr(&ss); - - /* have to open a new connection */ - if ((c = cli_initialise()) == NULL) { - errno = ENOMEM; - return NULL; - } - - if (context->flags & SMB_CTX_FLAG_USE_KERBEROS) { - c->use_kerberos = True; - } - if (context->flags & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS) { - c->fallback_after_kerberos = True; - } - - c->timeout = context->timeout; - - /* - * Force use of port 139 for first try if share is $IPC, empty, or - * null, so browse lists can work - */ - if (share == NULL || *share == '\0' || strcmp(share, "IPC$") == 0) { - port_try_first = 139; - port_try_next = 445; - } else { - 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); - errno = ETIMEDOUT; - 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)) { - DEBUG(4, ("Could not convert IP address " - "%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); - goto again; - } - } - } - 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_workgroup))) { - - /* Failed. Try an anonymous login, if allowed by flags. */ - username_used = ""; - - if ((context->flags & 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))) { - - /* - * context->internal->_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; - return NULL; - } - } - 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; - if ((context->callbacks.add_cached_srv_fn)(context, srv, - server, share, - *pp_workgroup, - *pp_username)) { - int saved_errno = errno; - DEBUG(3, (" Failed to add server to cache\n")); - errno = saved_errno; - if (errno == 0) { - errno = ENOMEM; - } - goto failed; - } - - DEBUG(2, ("Server connect ok: //%s/%s: %p\n", - server, share, srv)); - - DLIST_ADD(context->internal->_servers, srv); - return srv; - - failed: - cli_shutdown(c); - if (!srv) { - return NULL; - } - - SAFE_FREE(srv); - return NULL; -} - -/* - * Connect to a server for getting/setting attributes, possibly on an existing - * connection. This works similarly to smbc_server(). - */ -static SMBCSRV * -smbc_attr_server(TALLOC_CTX *ctx, - SMBCCTX *context, - const char *server, - const char *share, - char **pp_workgroup, - char **pp_username, - char **pp_password) -{ - int flags; - struct sockaddr_storage ss; - struct cli_state *ipc_cli; - 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 = find_server(ctx, context, server, "*IPC$", - 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. */ - call_auth_fn(ctx, context, server, share, - pp_workgroup, pp_username, pp_password); - if (!*pp_workgroup || !*pp_username || !*pp_password) { - errno = ENOMEM; - return NULL; - } - } - - flags = 0; - if (context->flags & SMB_CTX_FLAG_USE_KERBEROS) { - flags |= CLI_FULL_CONNECTION_USE_KERBEROS; - } - - zero_addr(&ss); - nt_status = cli_full_connection(&ipc_cli, - global_myname(), server, - &ss, 0, "IPC$", "?????", - *pp_username, - *pp_workgroup, - *pp_password, - flags, - Undefined, NULL); - if (! NT_STATUS_IS_OK(nt_status)) { - DEBUG(1,("cli_full_connection failed! (%s)\n", - nt_errstr(nt_status))); - 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))) { - - /* - * context->internal->_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; - return NULL; - } - } - 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; - } - - /* - * 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); - - if (!NT_STATUS_IS_OK(nt_status)) { - 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->callbacks.add_cached_srv_fn)(context, ipc_srv, - server, - "*IPC$", - *pp_workgroup, - *pp_username)) { - DEBUG(3, (" Failed to add server to cache\n")); - if (errno == 0) { - errno = ENOMEM; - } - cli_shutdown(ipc_srv->cli); - free(ipc_srv); - return NULL; - } - - DLIST_ADD(context->internal->_servers, ipc_srv); - } - - return ipc_srv; -} - -/* - * Routine to open() a file ... - */ - -static SMBCFILE * -smbc_open_ctx(SMBCCTX *context, - const char *fname, - int flags, - mode_t mode) -{ - char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *workgroup = NULL; - char *path = NULL; - char *targetpath = NULL; - struct cli_state *targetcli = NULL; - SMBCSRV *srv = NULL; - SMBCFILE *file = NULL; - int fd; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !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)) { - errno = EINVAL; - TALLOC_FREE(frame); - return NULL; - } - - if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); - if (!user) { - errno = ENOMEM; - TALLOC_FREE(frame); - 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)) { - 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, - * though, using this protocol, would require a getattrE() - * call for each and every write, to determine where the end - * of the file is. (There does not appear to be an append flag - * in the protocol.) Rather than add all of that overhead of - * retrieving the current end-of-file offset prior to each - * write operation, we'll assume that most append operations - * will continuously write, so we'll just set the offset to - * the end of the file now and hope that's adequate. - * - * Note to self: If this proves inadequate, and O_APPEND - * should, in some cases, be forced for each write, add a - * field in the context options structure, for - * "strict_append_mode" which would select between the current - * behavior (if FALSE) or issuing a getattrE() prior to each - * write and forcing the write to the end of the file (if - * TRUE). Adding that capability will likely require adding - * an "append" flag into the _SMBCFILE structure to track - * whether a file was opened in O_APPEND mode. -- djl - */ - if (flags & O_APPEND) { - if (smbc_lseek_ctx(context, file, 0, SEEK_END) < 0) { - (void) smbc_close_ctx(context, file); - errno = ENXIO; - TALLOC_FREE(frame); - 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->opendir)(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 */ - -static SMBCFILE * -smbc_creat_ctx(SMBCCTX *context, - const char *path, - mode_t mode) -{ - - if (!context || !context->internal || - !context->internal->_initialized) { - - errno = EINVAL; - return NULL; - - } - - return smbc_open_ctx(context, path, creat_bits, mode); -} - -/* - * Routine to read() a file ... - */ - -static ssize_t -smbc_read_ctx(SMBCCTX *context, - SMBCFILE *file, - void *buf, - size_t count) -{ - int ret; - char *server = NULL, *share = NULL, *user = NULL, *password = NULL; - char *path = NULL; - char *targetpath = NULL; - struct cli_state *targetcli = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - - /* - * offset: - * - * Compiler bug (possibly) -- gcc (GCC) 3.3.5 (Debian 1:3.3.5-2) -- - * appears to pass file->offset (which is type off_t) differently than - * a local variable of type off_t. Using local variable "offset" in - * the call to cli_read() instead of file->offset fixes a problem - * retrieving data at an offset greater than 4GB. - */ - off_t offset; - - if (!context || !context->internal || - !context->internal->_initialized) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - - } - - DEBUG(4, ("smbc_read(%p, %d)\n", file, (int)count)); - - if (!file || !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)) { - 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)) { - d_printf("Could not resolve %s\n", path); - TALLOC_FREE(frame); - 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 ... */ - -} - -/* - * Routine to write() a file ... - */ - -static ssize_t -smbc_write_ctx(SMBCCTX *context, - SMBCFILE *file, - void *buf, - size_t count) -{ - int ret; - off_t offset; - char *server = NULL, *share = NULL, *user = NULL, *password = NULL; - char *path = NULL; - char *targetpath = NULL; - struct cli_state *targetcli = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - - /* First check all pointers before dereferencing them */ - - if (!context || !context->internal || - !context->internal->_initialized) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - - } - - if (!file || !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)) { - 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)) { - d_printf("Could not resolve %s\n", path); - TALLOC_FREE(frame); - return -1; - } - /*d_printf(">>>write: resolved path as %s\n", targetpath);*/ - - 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 ... */ -} - -/* - * Routine to close() a file ... - */ - -static int -smbc_close_ctx(SMBCCTX *context, - SMBCFILE *file) -{ - SMBCSRV *srv; - char *server = NULL, *share = NULL, *user = NULL, *password = NULL; - char *path = NULL; - char *targetpath = NULL; - struct cli_state *targetcli = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !context->internal->_initialized) { - - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - if (!file || !DLIST_CONTAINS(context->internal->_files, file)) { - errno = EBADF; - TALLOC_FREE(frame); - return -1; - } - - /* IS a dir ... */ - if (!file->file) { - TALLOC_FREE(frame); - return (context->closedir)(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)) { - 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)) { - d_printf("Could not resolve %s\n", path); - TALLOC_FREE(frame); - 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 - * from the server cache if unused */ - errno = smbc_errno(context, targetcli); - srv = file->srv; - DLIST_REMOVE(context->internal->_files, file); - SAFE_FREE(file->fname); - SAFE_FREE(file); - (context->callbacks.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; -} - -/* - * Get info from an SMB server on a file. Use a qpathinfo call first - * and if that fails, use getatr, as Win95 sometimes refuses qpathinfo - */ -static bool -smbc_getatr(SMBCCTX * context, - SMBCSRV *srv, - char *path, - uint16 *mode, - SMB_OFF_T *size, - struct timespec *create_time_ts, - struct timespec *access_time_ts, - struct timespec *write_time_ts, - struct timespec *change_time_ts, - SMB_INO_T *ino) -{ - char *fixedpath = NULL; - char *targetpath = NULL; - struct cli_state *targetcli = NULL; - time_t write_time; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !context->internal->_initialized) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - /* path fixup for . and .. */ - if (strequal(path, ".") || strequal(path, "..")) { - fixedpath = talloc_strdup(frame, "\\"); - if (!fixedpath) { - errno = ENOMEM; - TALLOC_FREE(frame); - return -1; - } - } else { - fixedpath = talloc_strdup(frame, path); - if (!fixedpath) { - errno = ENOMEM; - TALLOC_FREE(frame); - return -1; - } - trim_string(fixedpath, NULL, "\\.."); - trim_string(fixedpath, NULL, "\\."); - } - DEBUG(4,("smbc_getatr: sending qpathinfo\n")); - - if (!cli_resolve_path(frame, "", srv->cli, fixedpath, - &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, - access_time_ts, - write_time_ts, - change_time_ts, - size, mode, ino)) { - 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; - -} - -/* - * Set file info on an SMB server. Use setpathinfo call first. If that - * fails, use setattrE.. - * - * Access and modification time parameters are always used and must be - * provided. Create time, if zero, will be determined from the actual create - * time of the file. If non-zero, the create time will be set as well. - * - * "mode" (attributes) parameter may be set to -1 if it is not to be set. - */ -static bool -smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, - time_t create_time, - time_t access_time, - time_t write_time, - time_t change_time, - uint16 mode) -{ - 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 - * filename rather than requiring that the file be opened to have its - * attributes manipulated. - */ - if (srv->no_pathinfo || - ! cli_setpathinfo(srv->cli, path, - create_time, - access_time, - write_time, - change_time, - mode)) { - - /* - * setpathinfo is not supported; go to plan B. - * - * cli_setatr() does not work on win98, and it also doesn't - * support setting the access time (only the modification - * time), so in all cases, we open the specified file and use - * 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 - * cli_setatr() for that, and with only this parameter, it - * seems to work on win98. - */ - 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; -} - - /* - * Routine to unlink() a file - */ - -static int -smbc_unlink_ctx(SMBCCTX *context, - const char *fname) -{ - char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *workgroup = NULL; - char *path = NULL; - char *targetpath = NULL; - struct cli_state *targetcli = NULL; - SMBCSRV *srv = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !context->internal->_initialized) { - errno = EINVAL; /* Best I can think of ... */ - TALLOC_FREE(frame); - return -1; - - } - - if (!fname) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - - } - - if (smbc_parse_path(frame, - 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->user); - if (!user) { - errno = ENOMEM; - TALLOC_FREE(frame); - return -1; - } - } - - srv = smbc_server(frame, context, True, - server, share, &workgroup, &user, &password); - - if (!srv) { - TALLOC_FREE(frame); - return -1; /* smbc_server sets errno */ - - } - - /*d_printf(">>>unlink: resolving %s\n", path);*/ - if (!cli_resolve_path(frame, "", srv->cli, path, - &targetcli, &targetpath)) { - d_printf("Could not resolve %s\n", path); - TALLOC_FREE(frame); - return -1; - } - /*d_printf(">>>unlink: resolved path as %s\n", targetpath);*/ - - if (!cli_unlink(targetcli, targetpath)) { - - errno = smbc_errno(context, targetcli); - - if (errno == EACCES) { /* Check if the file is a directory */ - - int saverr = errno; - SMB_OFF_T size = 0; - uint16 mode = 0; - struct timespec write_time_ts; - struct timespec access_time_ts; - struct timespec change_time_ts; - SMB_INO_T ino = 0; - - if (!smbc_getatr(context, srv, path, &mode, &size, - NULL, - &access_time_ts, - &write_time_ts, - &change_time_ts, - &ino)) { - - /* Hmmm, bad error ... What? */ - - errno = smbc_errno(context, targetcli); - TALLOC_FREE(frame); - return -1; - - } - else { - - if (IS_DOS_DIR(mode)) - errno = EISDIR; - else - errno = saverr; /* Restore this */ - - } - } - - TALLOC_FREE(frame); - return -1; - - } - - TALLOC_FREE(frame); - return 0; /* Success ... */ - -} - -/* - * Routine to rename() a file - */ - -static int -smbc_rename_ctx(SMBCCTX *ocontext, - const char *oname, - SMBCCTX *ncontext, - const char *nname) -{ - char *server1 = NULL; - char *share1 = NULL; - char *server2 = NULL; - char *share2 = NULL; - char *user1 = NULL; - char *user2 = NULL; - char *password1 = NULL; - char *password2 = NULL; - char *workgroup = NULL; - char *path1 = NULL; - char *path2 = NULL; - char *targetpath1 = NULL; - char *targetpath2 = NULL; - struct cli_state *targetcli1 = NULL; - struct cli_state *targetcli2 = NULL; - SMBCSRV *srv = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!ocontext || !ncontext || - !ocontext->internal || !ncontext->internal || - !ocontext->internal->_initialized || - !ncontext->internal->_initialized) { - errno = EINVAL; /* Best I can think of ... */ - TALLOC_FREE(frame); - return -1; - } - - if (!oname || !nname) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - DEBUG(4, ("smbc_rename(%s,%s)\n", oname, nname)); - - if (smbc_parse_path(frame, - ocontext, - oname, - &workgroup, - &server1, - &share1, - &path1, - &user1, - &password1, - NULL)) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - if (!user1 || user1[0] == (char)0) { - user1 = talloc_strdup(frame, ocontext->user); - if (!user1) { - errno = ENOMEM; - TALLOC_FREE(frame); - return -1; - } - } - - if (smbc_parse_path(frame, - ncontext, - nname, - NULL, - &server2, - &share2, - &path2, - &user2, - &password2, - NULL)) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - if (!user2 || user2[0] == (char)0) { - user2 = talloc_strdup(frame, ncontext->user); - if (!user2) { - errno = ENOMEM; - TALLOC_FREE(frame); - return -1; - } - } - - if (strcmp(server1, server2) || strcmp(share1, share2) || - strcmp(user1, user2)) { - /* Can't rename across file systems, or users?? */ - errno = EXDEV; - TALLOC_FREE(frame); - return -1; - } - - srv = smbc_server(frame, ocontext, True, - server1, share1, &workgroup, &user1, &password1); - if (!srv) { - TALLOC_FREE(frame); - return -1; - - } - - /*d_printf(">>>rename: resolving %s\n", path1);*/ - if (!cli_resolve_path(frame, "", srv->cli, path1, - &targetcli1, &targetpath1)) { - d_printf("Could not resolve %s\n", path1); - TALLOC_FREE(frame); - return -1; - } - /*d_printf(">>>rename: resolved path as %s\n", targetpath1);*/ - /*d_printf(">>>rename: resolving %s\n", path2);*/ - if (!cli_resolve_path(frame, "", srv->cli, path2, - &targetcli2, &targetpath2)) { - d_printf("Could not resolve %s\n", path2); - TALLOC_FREE(frame); - return -1; - } - /*d_printf(">>>rename: resolved path as %s\n", targetpath2);*/ - - if (strcmp(targetcli1->desthost, targetcli2->desthost) || - strcmp(targetcli1->share, targetcli2->share)) - { - /* can't rename across file systems */ - errno = EXDEV; - TALLOC_FREE(frame); - return -1; - } - - if (!cli_rename(targetcli1, targetpath1, targetpath2)) { - int eno = smbc_errno(ocontext, targetcli1); - - if (eno != EEXIST || - !cli_unlink(targetcli1, targetpath2) || - !cli_rename(targetcli1, targetpath1, targetpath2)) { - - errno = eno; - TALLOC_FREE(frame); - return -1; - - } - } - - TALLOC_FREE(frame); - return 0; /* Success */ -} - -/* - * A routine to lseek() a file - */ - -static off_t -smbc_lseek_ctx(SMBCCTX *context, - SMBCFILE *file, - off_t offset, - int whence) -{ - SMB_OFF_T size; - char *server = NULL, *share = NULL, *user = NULL, *password = NULL; - char *path = NULL; - char *targetpath = NULL; - struct cli_state *targetcli = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !context->internal->_initialized) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - if (!file || !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)) { - 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)) { - d_printf("Could not resolve %s\n", path); - TALLOC_FREE(frame); - 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; - if (!cli_getattrE(targetcli, file->cli_fd, - NULL, &b_size, NULL, NULL, NULL)) - { - 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; - -} - -/* - * Generate an inode number from file name for those things that need it - */ - -static ino_t -smbc_inode(SMBCCTX *context, - const char *name) -{ - if (!context || !context->internal || - !context->internal->_initialized) { - - errno = EINVAL; - return -1; - - } - - if (!*name) return 2; /* FIXME, why 2 ??? */ - return (ino_t)str_checksum(name); - -} - -/* - * Routine to put basic stat info into a stat structure ... Used by stat and - * fstat below. - */ - -static int -smbc_setup_stat(SMBCCTX *context, - 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; -#endif -#ifdef HAVE_STAT_ST_BLOCKS - st->st_blocks = (size+511)/512; -#endif -#ifdef HAVE_STRUCT_STAT_ST_RDEV - st->st_rdev = 0; -#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 = smbc_inode(context, fname); - } - - TALLOC_FREE(frame); - return True; /* FIXME: Is this needed ? */ - -} - -/* - * Routine to stat a file given a name - */ - -static int -smbc_stat_ctx(SMBCCTX *context, - const char *fname, - struct stat *st) -{ - SMBCSRV *srv = NULL; - char *server = NULL; - char *share = NULL; - char *user = NULL; - char *password = NULL; - char *workgroup = NULL; - char *path = NULL; - struct timespec write_time_ts; - struct timespec access_time_ts; - struct timespec change_time_ts; - SMB_OFF_T size = 0; - uint16 mode = 0; - SMB_INO_T ino = 0; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !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)) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - if (!user || user[0] == (char)0) { - user = talloc_strdup(frame,context->user); - if (!user) { - errno = ENOMEM; - TALLOC_FREE(frame); - 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, - &write_time_ts, - &change_time_ts, - &ino)) { - errno = smbc_errno(context, srv->cli); - TALLOC_FREE(frame); - return -1; - } - - st->st_ino = ino; - - smbc_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; - -} - -/* - * Routine to stat a file given an fd - */ - -static int -smbc_fstat_ctx(SMBCCTX *context, - SMBCFILE *file, - struct stat *st) -{ - struct timespec change_time_ts; - struct timespec access_time_ts; - struct timespec write_time_ts; - SMB_OFF_T size; - uint16 mode; - char *server = NULL; - char *share = NULL; - char *user = NULL; - char *password = NULL; - char *path = NULL; - char *targetpath = NULL; - struct cli_state *targetcli = NULL; - SMB_INO_T ino = 0; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !context->internal->_initialized) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - if (!file || !DLIST_CONTAINS(context->internal->_files, file)) { - errno = EBADF; - TALLOC_FREE(frame); - return -1; - } - - if (!file->file) { - TALLOC_FREE(frame); - return (context->fstatdir)(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)) { - 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)) { - d_printf("Could not resolve %s\n", path); - TALLOC_FREE(frame); - 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)) { - - 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; - - smbc_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; - -} - -/* - * Routine to truncate a file given by its file descriptor, to a specified size - */ - -static int -smbc_ftruncate_ctx(SMBCCTX *context, - SMBCFILE *file, - off_t length) -{ - SMB_OFF_T size = length; - char *server = NULL; - char *share = NULL; - char *user = NULL; - char *password = NULL; - char *path = NULL; - char *targetpath = NULL; - struct cli_state *targetcli = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !context->internal->_initialized) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - if (!file || !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, - 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)) { - d_printf("Could not resolve %s\n", path); - TALLOC_FREE(frame); - 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; - -} - -/* - * Routine to open a directory - * We accept the URL syntax explained in smbc_parse_path(), above. - */ - -static void -smbc_remove_dir(SMBCFILE *dir) -{ - struct smbc_dir_list *d,*f; - - d = dir->dir_list; - while (d) { - - f = d; d = d->next; - - SAFE_FREE(f->dirent); - SAFE_FREE(f); - - } - - dir->dir_list = dir->dir_end = dir->dir_next = NULL; - -} - -static int -add_dirent(SMBCFILE *dir, - const char *name, - const char *comment, - uint32 type) -{ - struct smbc_dirent *dirent; - int size; - int name_length = (name == NULL ? 0 : strlen(name)); - int comment_len = (comment == NULL ? 0 : strlen(comment)); - - /* - * Allocate space for the dirent, which must be increased by the - * size of the name and the comment and 1 each for the null terminator. - */ - - size = sizeof(struct smbc_dirent) + name_length + comment_len + 2; - - dirent = (struct smbc_dirent *)SMB_MALLOC(size); - - if (!dirent) { - - dir->dir_error = ENOMEM; - return -1; - - } - - ZERO_STRUCTP(dirent); - - if (dir->dir_list == NULL) { - - dir->dir_list = SMB_MALLOC_P(struct smbc_dir_list); - if (!dir->dir_list) { - - SAFE_FREE(dirent); - dir->dir_error = ENOMEM; - return -1; - - } - ZERO_STRUCTP(dir->dir_list); - - dir->dir_end = dir->dir_next = dir->dir_list; - } - else { - - dir->dir_end->next = SMB_MALLOC_P(struct smbc_dir_list); - - if (!dir->dir_end->next) { - - SAFE_FREE(dirent); - dir->dir_error = ENOMEM; - return -1; - - } - ZERO_STRUCTP(dir->dir_end->next); - - dir->dir_end = dir->dir_end->next; - } - - dir->dir_end->next = NULL; - dir->dir_end->dirent = dirent; - - dirent->smbc_type = type; - dirent->namelen = name_length; - dirent->commentlen = comment_len; - dirent->dirlen = size; - - /* - * dirent->namelen + 1 includes the null (no null termination needed) - * Ditto for dirent->commentlen. - * The space for the two null bytes was allocated. - */ - strncpy(dirent->name, (name?name:""), dirent->namelen + 1); - dirent->comment = (char *)(&dirent->name + dirent->namelen + 1); - strncpy(dirent->comment, (comment?comment:""), dirent->commentlen + 1); - - return 0; - -} - -static void -list_unique_wg_fn(const char *name, - uint32 type, - const char *comment, - void *state) -{ - SMBCFILE *dir = (SMBCFILE *)state; - struct smbc_dir_list *dir_list; - struct smbc_dirent *dirent; - int dirent_type; - int do_remove = 0; - - dirent_type = dir->dir_type; - - if (add_dirent(dir, name, comment, dirent_type) < 0) { - - /* An error occurred, what do we do? */ - /* FIXME: Add some code here */ - } - - /* Point to the one just added */ - dirent = dir->dir_end->dirent; - - /* See if this was a duplicate */ - for (dir_list = dir->dir_list; - dir_list != dir->dir_end; - dir_list = dir_list->next) { - if (! do_remove && - strcmp(dir_list->dirent->name, dirent->name) == 0) { - /* Duplicate. End end of list need to be removed. */ - do_remove = 1; - } - - if (do_remove && dir_list->next == dir->dir_end) { - /* Found the end of the list. Remove it. */ - dir->dir_end = dir_list; - free(dir_list->next); - free(dirent); - dir_list->next = NULL; - break; - } - } -} - -static void -list_fn(const char *name, - uint32 type, - const char *comment, - void *state) -{ - SMBCFILE *dir = (SMBCFILE *)state; - int dirent_type; - - /* - * We need to process the type a little ... - * - * Disk share = 0x00000000 - * Print share = 0x00000001 - * Comms share = 0x00000002 (obsolete?) - * IPC$ share = 0x00000003 - * - * administrative shares: - * ADMIN$, IPC$, C$, D$, E$ ... are type |= 0x80000000 - */ - - if (dir->dir_type == SMBC_FILE_SHARE) { - switch (type) { - case 0 | 0x80000000: - case 0: - dirent_type = SMBC_FILE_SHARE; - break; - - case 1: - dirent_type = SMBC_PRINTER_SHARE; - break; - - case 2: - dirent_type = SMBC_COMMS_SHARE; - break; - - case 3 | 0x80000000: - case 3: - dirent_type = SMBC_IPC_SHARE; - break; - - default: - dirent_type = SMBC_FILE_SHARE; /* FIXME, error? */ - break; - } - } - else { - dirent_type = dir->dir_type; - } - - if (add_dirent(dir, name, comment, dirent_type) < 0) { - - /* An error occurred, what do we do? */ - /* FIXME: Add some code here */ - - } -} - -static void -dir_list_fn(const char *mnt, - file_info *finfo, - const char *mask, - void *state) -{ - - if (add_dirent((SMBCFILE *)state, finfo->name, "", - (finfo->mode&aDIR?SMBC_DIR:SMBC_FILE)) < 0) { - - /* Handle an error ... */ - - /* FIXME: Add some code ... */ - - } - -} - -static int -net_share_enum_rpc(struct cli_state *cli, - void (*fn)(const char *name, - uint32 type, - const char *comment, - void *state), - void *state) -{ - int i; - WERROR result; - ENUM_HND enum_hnd; - uint32 info_level = 1; - uint32 preferred_len = 0xffffffff; - uint32 type; - SRV_SHARE_INFO_CTR ctr; - fstring name = ""; - fstring comment = ""; - struct rpc_pipe_client *pipe_hnd; - NTSTATUS nt_status; - - /* Open the server service pipe */ - pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &nt_status); - if (!pipe_hnd) { - DEBUG(1, ("net_share_enum_rpc pipe open fail!\n")); - return -1; - } - - /* Issue the NetShareEnum RPC call and retrieve the response */ - init_enum_hnd(&enum_hnd, 0); - result = rpccli_srvsvc_net_share_enum(pipe_hnd, - talloc_tos(), - info_level, - &ctr, - preferred_len, - &enum_hnd); - - /* Was it successful? */ - if (!W_ERROR_IS_OK(result) || ctr.num_entries == 0) { - /* Nope. Go clean up. */ - goto done; - } - - /* For each returned entry... */ - for (i = 0; i < ctr.num_entries; i++) { - - /* pull out the share name */ - rpcstr_pull_unistr2_fstring( - name, &ctr.share.info1[i].info_1_str.uni_netname); - - /* pull out the share's comment */ - rpcstr_pull_unistr2_fstring( - comment, &ctr.share.info1[i].info_1_str.uni_remark); - - /* Get the type value */ - type = ctr.share.info1[i].info_1.type; - - /* Add this share to the list */ - (*fn)(name, type, comment, state); - } - -done: - /* Close the server service pipe */ - cli_rpc_pipe_close(pipe_hnd); - - /* Tell 'em if it worked */ - return W_ERROR_IS_OK(result) ? 0 : -1; -} - - - -static SMBCFILE * -smbc_opendir_ctx(SMBCCTX *context, - const char *fname) -{ - int saved_errno; - char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *options = NULL; - char *workgroup = NULL; - char *path = NULL; - uint16 mode; - char *p = NULL; - SMBCSRV *srv = NULL; - SMBCFILE *dir = NULL; - struct _smbc_callbacks *cb = NULL; - struct sockaddr_storage rem_ss; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !context->internal->_initialized) { - DEBUG(4, ("no valid context\n")); - errno = EINVAL + 8192; - TALLOC_FREE(frame); - return NULL; - - } - - if (!fname) { - DEBUG(4, ("no valid fname\n")); - errno = EINVAL + 8193; - TALLOC_FREE(frame); - return NULL; - } - - if (smbc_parse_path(frame, - context, - fname, - &workgroup, - &server, - &share, - &path, - &user, - &password, - &options)) { - DEBUG(4, ("no valid path\n")); - errno = EINVAL + 8194; - TALLOC_FREE(frame); - return NULL; - } - - DEBUG(4, ("parsed path: fname='%s' server='%s' share='%s' " - "path='%s' options='%s'\n", - fname, server, share, path, options)); - - /* Ensure the options are valid */ - if (smbc_check_options(server, share, path, options)) { - DEBUG(4, ("unacceptable options (%s)\n", options)); - errno = EINVAL + 8195; - TALLOC_FREE(frame); - return NULL; - } - - if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); - if (!user) { - errno = ENOMEM; - TALLOC_FREE(frame); - return NULL; - } - } - - dir = SMB_MALLOC_P(SMBCFILE); - - if (!dir) { - errno = ENOMEM; - TALLOC_FREE(frame); - return NULL; - } - - ZERO_STRUCTP(dir); - - dir->cli_fd = 0; - dir->fname = SMB_STRDUP(fname); - dir->srv = NULL; - dir->offset = 0; - dir->file = False; - dir->dir_list = dir->dir_next = dir->dir_end = NULL; - - if (server[0] == (char)0) { - - int i; - int count; - int max_lmb_count; - struct ip_service *ip_list; - struct ip_service server_addr; - struct user_auth_info u_info; - - if (share[0] != (char)0 || path[0] != (char)0) { - - errno = EINVAL + 8196; - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - TALLOC_FREE(frame); - return NULL; - } - - /* Determine how many local master browsers to query */ - max_lmb_count = (context->options.browse_max_lmb_count == 0 - ? INT_MAX - : context->options.browse_max_lmb_count); - - memset(&u_info, '\0', sizeof(u_info)); - u_info.username = talloc_strdup(frame,user); - u_info.password = talloc_strdup(frame,password); - if (!u_info.username || !u_info.password) { - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - TALLOC_FREE(frame); - return NULL; - } - - /* - * We have server and share and path empty but options - * requesting that we scan all master browsers for their list - * of workgroups/domains. This implies that we must first try - * broadcast queries to find all master browsers, and if that - * doesn't work, then try our other methods which return only - * a single master browser. - */ - - ip_list = NULL; - if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list, - &count))) - { - - SAFE_FREE(ip_list); - - if (!find_master_ip(workgroup, &server_addr.ss)) { - - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - errno = ENOENT; - TALLOC_FREE(frame); - return NULL; - } - - ip_list = (struct ip_service *)memdup( - &server_addr, sizeof(server_addr)); - if (ip_list == NULL) { - errno = ENOMEM; - TALLOC_FREE(frame); - return NULL; - } - count = 1; - } - - for (i = 0; i < count && i < max_lmb_count; i++) { - char addr[INET6_ADDRSTRLEN]; - char *wg_ptr = NULL; - struct cli_state *cli = NULL; - - print_sockaddr(addr, sizeof(addr), &ip_list[i].ss); - DEBUG(99, ("Found master browser %d of %d: %s\n", - i+1, MAX(count, max_lmb_count), - addr)); - - cli = get_ipc_connect_master_ip(talloc_tos(), - &ip_list[i], - &u_info, - &wg_ptr); - /* cli == NULL is the master browser refused to talk or - could not be found */ - if (!cli) { - continue; - } - - workgroup = talloc_strdup(frame, wg_ptr); - server = talloc_strdup(frame, cli->desthost); - - cli_shutdown(cli); - - if (!workgroup || !server) { - errno = ENOMEM; - TALLOC_FREE(frame); - return NULL; - } - - DEBUG(4, ("using workgroup %s %s\n", - workgroup, server)); - - /* - * For each returned master browser IP address, get a - * connection to IPC$ on the server if we do not - * already have one, and determine the - * workgroups/domains that it knows about. - */ - - srv = smbc_server(frame, context, True, server, "IPC$", - &workgroup, &user, &password); - if (!srv) { - continue; - } - - dir->srv = srv; - dir->dir_type = SMBC_WORKGROUP; - - /* Now, list the stuff ... */ - - if (!cli_NetServerEnum(srv->cli, - workgroup, - SV_TYPE_DOMAIN_ENUM, - list_unique_wg_fn, - (void *)dir)) { - continue; - } - } - - SAFE_FREE(ip_list); - } else { - /* - * Server not an empty string ... Check the rest and see what - * gives - */ - if (*share == '\0') { - if (*path != '\0') { - - /* Should not have empty share with path */ - errno = EINVAL + 8197; - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - TALLOC_FREE(frame); - return NULL; - - } - - /* - * We don't know if is really a server name - * or is a workgroup/domain name. If we already have - * a server structure for it, we'll use it. - * Otherwise, check to see if <1D>, - * <1B>, or <20> translates. We check - * to see if is an IP address first. - */ - - /* - * See if we have an existing server. Do not - * establish a connection if one does not already - * exist. - */ - srv = smbc_server(frame, context, False, server, "IPC$", - &workgroup, &user, &password); - - /* - * If no existing server and not an IP addr, look for - * LMB or DMB - */ - if (!srv && - !is_ipaddress(server) && - (resolve_name(server, &rem_ss, 0x1d) || /* LMB */ - resolve_name(server, &rem_ss, 0x1b) )) { /* DMB */ - - fstring buserver; - - dir->dir_type = SMBC_SERVER; - - /* - * Get the backup list ... - */ - if (!name_status_find(server, 0, 0, - &rem_ss, buserver)) { - - DEBUG(0, ("Could not get name of " - "local/domain master browser " - "for server %s\n", server)); - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - errno = EPERM; - TALLOC_FREE(frame); - return NULL; - - } - - /* - * Get a connection to IPC$ on the server if - * we do not already have one - */ - srv = smbc_server(frame, context, True, - buserver, "IPC$", - &workgroup, &user, &password); - if (!srv) { - DEBUG(0, ("got no contact to IPC$\n")); - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - TALLOC_FREE(frame); - return NULL; - - } - - dir->srv = srv; - - /* Now, list the servers ... */ - if (!cli_NetServerEnum(srv->cli, server, - 0x0000FFFE, list_fn, - (void *)dir)) { - - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - TALLOC_FREE(frame); - return NULL; - } - } else if (srv || - (resolve_name(server, &rem_ss, 0x20))) { - - /* If we hadn't found the server, get one now */ - if (!srv) { - srv = smbc_server(frame, context, True, - server, "IPC$", - &workgroup, - &user, &password); - } - - if (!srv) { - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - TALLOC_FREE(frame); - return NULL; - - } - - dir->dir_type = SMBC_FILE_SHARE; - dir->srv = srv; - - /* List the shares ... */ - - if (net_share_enum_rpc( - srv->cli, - list_fn, - (void *) dir) < 0 && - cli_RNetShareEnum( - srv->cli, - list_fn, - (void *)dir) < 0) { - - errno = cli_errno(srv->cli); - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - TALLOC_FREE(frame); - return NULL; - - } - } else { - /* Neither the workgroup nor server exists */ - errno = ECONNREFUSED; - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - TALLOC_FREE(frame); - return NULL; - } - - } - else { - /* - * The server and share are specified ... work from - * there ... - */ - char *targetpath; - struct cli_state *targetcli; - - /* We connect to the server and list the directory */ - dir->dir_type = SMBC_FILE_SHARE; - - srv = smbc_server(frame, context, True, server, share, - &workgroup, &user, &password); - - if (!srv) { - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - TALLOC_FREE(frame); - return NULL; - } - - dir->srv = srv; - - /* Now, list the files ... */ - - p = path + strlen(path); - path = talloc_asprintf_append(path, "\\*"); - if (!path) { - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - TALLOC_FREE(frame); - return NULL; - } - - if (!cli_resolve_path(frame, "", srv->cli, path, - &targetcli, &targetpath)) { - d_printf("Could not resolve %s\n", path); - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - TALLOC_FREE(frame); - return NULL; - } - - if (cli_list(targetcli, targetpath, - aDIR | aSYSTEM | aHIDDEN, - dir_list_fn, (void *)dir) < 0) { - - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - saved_errno = smbc_errno(context, targetcli); - - if (saved_errno == EINVAL) { - /* - * See if they asked to opendir something - * other than a directory. If so, the - * converted error value we got would have - * been EINVAL rather than ENOTDIR. - */ - *p = '\0'; /* restore original path */ - - if (smbc_getatr(context, srv, path, - &mode, NULL, - NULL, NULL, NULL, NULL, - NULL) && - ! IS_DOS_DIR(mode)) { - - /* It is. Correct the error value */ - saved_errno = ENOTDIR; - } - } - - /* - * If there was an error and the server is no - * good any more... - */ - cb = &context->callbacks; - if (cli_is_error(targetcli) && - (cb->check_server_fn)(context, srv)) { - - /* ... then remove it. */ - if ((cb->remove_unused_server_fn)(context, - srv)) { - /* - * We could not remove the - * server completely, remove - * it from the cache so we - * will not get it again. It - * will be removed when the - * last file/dir is closed. - */ - (cb->remove_cached_srv_fn)(context, - srv); - } - } - - errno = saved_errno; - TALLOC_FREE(frame); - return NULL; - } - } - - } - - DLIST_ADD(context->internal->_files, dir); - TALLOC_FREE(frame); - return dir; - -} - -/* - * Routine to close a directory - */ - -static int -smbc_closedir_ctx(SMBCCTX *context, - SMBCFILE *dir) -{ - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !context->internal->_initialized) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - if (!dir || !DLIST_CONTAINS(context->internal->_files, dir)) { - errno = EBADF; - TALLOC_FREE(frame); - return -1; - } - - smbc_remove_dir(dir); /* Clean it up */ - - DLIST_REMOVE(context->internal->_files, dir); - - if (dir) { - - SAFE_FREE(dir->fname); - SAFE_FREE(dir); /* Free the space too */ - } - - TALLOC_FREE(frame); - return 0; - -} - -static void -smbc_readdir_internal(SMBCCTX * context, - struct smbc_dirent *dest, - struct smbc_dirent *src, - int max_namebuf_len) -{ - if (context->options.urlencode_readdir_entries) { - - /* url-encode the name. get back remaining buffer space */ - max_namebuf_len = - smbc_urlencode(dest->name, src->name, max_namebuf_len); - - /* We now know the name length */ - dest->namelen = strlen(dest->name); - - /* Save the pointer to the beginning of the comment */ - dest->comment = dest->name + dest->namelen + 1; - - /* Copy the comment */ - strncpy(dest->comment, src->comment, max_namebuf_len - 1); - dest->comment[max_namebuf_len - 1] = '\0'; - - /* Save other fields */ - dest->smbc_type = src->smbc_type; - dest->commentlen = strlen(dest->comment); - dest->dirlen = ((dest->comment + dest->commentlen + 1) - - (char *) dest); - } else { - - /* No encoding. Just copy the entry as is. */ - memcpy(dest, src, src->dirlen); - dest->comment = (char *)(&dest->name + src->namelen + 1); - } - -} - -/* - * Routine to get a directory entry - */ - -struct smbc_dirent * -smbc_readdir_ctx(SMBCCTX *context, - SMBCFILE *dir) -{ - int maxlen; - struct smbc_dirent *dirp, *dirent; - TALLOC_CTX *frame = talloc_stackframe(); - - /* Check that all is ok first ... */ - - if (!context || !context->internal || - !context->internal->_initialized) { - - errno = EINVAL; - DEBUG(0, ("Invalid context in smbc_readdir_ctx()\n")); - TALLOC_FREE(frame); - return NULL; - - } - - if (!dir || !DLIST_CONTAINS(context->internal->_files, dir)) { - - errno = EBADF; - DEBUG(0, ("Invalid dir in smbc_readdir_ctx()\n")); - TALLOC_FREE(frame); - return NULL; - - } - - if (dir->file != False) { /* FIXME, should be dir, perhaps */ - - errno = ENOTDIR; - DEBUG(0, ("Found file vs directory in smbc_readdir_ctx()\n")); - TALLOC_FREE(frame); - return NULL; - - } - - if (!dir->dir_next) { - TALLOC_FREE(frame); - return NULL; - } - - dirent = dir->dir_next->dirent; - if (!dirent) { - - errno = ENOENT; - TALLOC_FREE(frame); - return NULL; - - } - - dirp = (struct smbc_dirent *)context->internal->_dirent; - maxlen = (sizeof(context->internal->_dirent) - - sizeof(struct smbc_dirent)); - - smbc_readdir_internal(context, dirp, dirent, maxlen); - - dir->dir_next = dir->dir_next->next; - - TALLOC_FREE(frame); - return dirp; -} - -/* - * Routine to get directory entries - */ - -static int -smbc_getdents_ctx(SMBCCTX *context, - SMBCFILE *dir, - struct smbc_dirent *dirp, - int count) -{ - int rem = count; - int reqd; - int maxlen; - char *ndir = (char *)dirp; - struct smbc_dir_list *dirlist; - TALLOC_CTX *frame = talloc_stackframe(); - - /* Check that all is ok first ... */ - - if (!context || !context->internal || - !context->internal->_initialized) { - - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - - } - - if (!dir || !DLIST_CONTAINS(context->internal->_files, dir)) { - - errno = EBADF; - TALLOC_FREE(frame); - return -1; - - } - - if (dir->file != False) { /* FIXME, should be dir, perhaps */ - - errno = ENOTDIR; - TALLOC_FREE(frame); - return -1; - - } - - /* - * Now, retrieve the number of entries that will fit in what was passed - * We have to figure out if the info is in the list, or we need to - * send a request to the server to get the info. - */ - - while ((dirlist = dir->dir_next)) { - struct smbc_dirent *dirent; - - if (!dirlist->dirent) { - - errno = ENOENT; /* Bad error */ - TALLOC_FREE(frame); - return -1; - - } - - /* Do urlencoding of next entry, if so selected */ - dirent = (struct smbc_dirent *)context->internal->_dirent; - maxlen = (sizeof(context->internal->_dirent) - - sizeof(struct smbc_dirent)); - smbc_readdir_internal(context, dirent, dirlist->dirent, maxlen); - - reqd = dirent->dirlen; - - if (rem < reqd) { - - if (rem < count) { /* We managed to copy something */ - - errno = 0; - TALLOC_FREE(frame); - return count - rem; - - } - else { /* Nothing copied ... */ - - errno = EINVAL; /* Not enough space ... */ - TALLOC_FREE(frame); - return -1; - - } - - } - - memcpy(ndir, dirent, reqd); /* Copy the data in ... */ - - ((struct smbc_dirent *)ndir)->comment = - (char *)(&((struct smbc_dirent *)ndir)->name + - dirent->namelen + - 1); - - ndir += reqd; - - rem -= reqd; - - dir->dir_next = dirlist = dirlist -> next; - } - - TALLOC_FREE(frame); - - if (rem == count) - return 0; - else - return count - rem; - -} - -/* - * Routine to create a directory ... - */ - -static int -smbc_mkdir_ctx(SMBCCTX *context, - const char *fname, - mode_t mode) -{ - SMBCSRV *srv = 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; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !context->internal->_initialized) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - if (!fname) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - DEBUG(4, ("smbc_mkdir(%s)\n", fname)); - - if (smbc_parse_path(frame, - 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->user); - if (!user) { - errno = ENOMEM; - TALLOC_FREE(frame); - 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 */ - - } - - /*d_printf(">>>mkdir: resolving %s\n", path);*/ - if (!cli_resolve_path(frame, "", srv->cli, path, - &targetcli, &targetpath)) { - d_printf("Could not resolve %s\n", path); - TALLOC_FREE(frame); - return -1; - } - /*d_printf(">>>mkdir: resolved path as %s\n", targetpath);*/ - - if (!cli_mkdir(targetcli, targetpath)) { - - errno = smbc_errno(context, targetcli); - TALLOC_FREE(frame); - return -1; - - } - - TALLOC_FREE(frame); - return 0; - -} - -/* - * Our list function simply checks to see if a directory is not empty - */ - -static int smbc_rmdir_dirempty = True; - -static void -rmdir_list_fn(const char *mnt, - file_info *finfo, - const char *mask, - void *state) -{ - if (strncmp(finfo->name, ".", 1) != 0 && - strncmp(finfo->name, "..", 2) != 0) { - smbc_rmdir_dirempty = False; - } -} - -/* - * Routine to remove a directory - */ - -static int -smbc_rmdir_ctx(SMBCCTX *context, - const char *fname) -{ - SMBCSRV *srv = 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; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !context->internal->_initialized) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - if (!fname) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - DEBUG(4, ("smbc_rmdir(%s)\n", fname)); - - if (smbc_parse_path(frame, - 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->user); - if (!user) { - errno = ENOMEM; - TALLOC_FREE(frame); - 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 */ - - } - - /*d_printf(">>>rmdir: resolving %s\n", path);*/ - if (!cli_resolve_path(frame, "", srv->cli, path, - &targetcli, &targetpath)) { - d_printf("Could not resolve %s\n", path); - TALLOC_FREE(frame); - return -1; - } - /*d_printf(">>>rmdir: resolved path as %s\n", targetpath);*/ - - - if (!cli_rmdir(targetcli, targetpath)) { - - errno = smbc_errno(context, targetcli); - - if (errno == EACCES) { /* Check if the dir empty or not */ - - /* Local storage to avoid buffer overflows */ - char *lpath; - - smbc_rmdir_dirempty = True; /* Make this so ... */ - - lpath = talloc_asprintf(frame, "%s\\*", - targetpath); - if (!lpath) { - errno = ENOMEM; - TALLOC_FREE(frame); - return -1; - } - - if (cli_list(targetcli, lpath, - aDIR | aSYSTEM | aHIDDEN, - rmdir_list_fn, NULL) < 0) { - - /* Fix errno to ignore latest error ... */ - DEBUG(5, ("smbc_rmdir: " - "cli_list returned an error: %d\n", - smbc_errno(context, targetcli))); - errno = EACCES; - - } - - if (smbc_rmdir_dirempty) - errno = EACCES; - else - errno = ENOTEMPTY; - - } - - TALLOC_FREE(frame); - return -1; - - } - - TALLOC_FREE(frame); - return 0; - -} - -/* - * Routine to return the current directory position - */ - -static off_t -smbc_telldir_ctx(SMBCCTX *context, - SMBCFILE *dir) -{ - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !context->internal->_initialized) { - - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - - } - - if (!dir || !DLIST_CONTAINS(context->internal->_files, dir)) { - - errno = EBADF; - TALLOC_FREE(frame); - return -1; - - } - - if (dir->file != False) { /* FIXME, should be dir, perhaps */ - - errno = ENOTDIR; - TALLOC_FREE(frame); - return -1; - - } - - /* See if we're already at the end. */ - if (dir->dir_next == NULL) { - /* We are. */ - TALLOC_FREE(frame); - return -1; - } - - /* - * We return the pointer here as the offset - */ - TALLOC_FREE(frame); - return (off_t)(long)dir->dir_next->dirent; -} - -/* - * A routine to run down the list and see if the entry is OK - */ - -struct smbc_dir_list * -smbc_check_dir_ent(struct smbc_dir_list *list, - struct smbc_dirent *dirent) -{ - - /* Run down the list looking for what we want */ - - if (dirent) { - - struct smbc_dir_list *tmp = list; - - while (tmp) { - - if (tmp->dirent == dirent) - return tmp; - - tmp = tmp->next; - - } - - } - - return NULL; /* Not found, or an error */ - -} - - -/* - * Routine to seek on a directory - */ - -static int -smbc_lseekdir_ctx(SMBCCTX *context, - SMBCFILE *dir, - off_t offset) -{ - long int l_offset = offset; /* Handle problems of size */ - struct smbc_dirent *dirent = (struct smbc_dirent *)l_offset; - struct smbc_dir_list *list_ent = (struct smbc_dir_list *)NULL; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !context->internal->_initialized) { - - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - - } - - if (dir->file != False) { /* FIXME, should be dir, perhaps */ - - errno = ENOTDIR; - TALLOC_FREE(frame); - return -1; - - } - - /* Now, check what we were passed and see if it is OK ... */ - - if (dirent == NULL) { /* Seek to the begining of the list */ - - dir->dir_next = dir->dir_list; - TALLOC_FREE(frame); - return 0; - - } - - if (offset == -1) { /* Seek to the end of the list */ - dir->dir_next = NULL; - TALLOC_FREE(frame); - return 0; - } - - /* Now, run down the list and make sure that the entry is OK */ - /* This may need to be changed if we change the format of the list */ - - if ((list_ent = smbc_check_dir_ent(dir->dir_list, dirent)) == NULL) { - errno = EINVAL; /* Bad entry */ - TALLOC_FREE(frame); - return -1; - } - - dir->dir_next = list_ent; - - TALLOC_FREE(frame); - return 0; -} - -/* - * Routine to fstat a dir - */ - -static int -smbc_fstatdir_ctx(SMBCCTX *context, - SMBCFILE *dir, - struct stat *st) -{ - - if (!context || !context->internal || - !context->internal->_initialized) { - errno = EINVAL; - return -1; - } - - /* No code yet ... */ - return 0; -} - -static int -smbc_chmod_ctx(SMBCCTX *context, - const char *fname, - mode_t newmode) -{ - SMBCSRV *srv = NULL; - char *server = NULL; - char *share = NULL; - char *user = NULL; - char *password = NULL; - char *workgroup = NULL; - char *path = NULL; - uint16 mode; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !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_chmod(%s, 0%3o)\n", fname, newmode)); - - if (smbc_parse_path(frame, - 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->user); - if (!user) { - errno = ENOMEM; - TALLOC_FREE(frame); - 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 */ - } - - mode = 0; - - if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY; - if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH; - if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM; - if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN; - - if (!cli_setatr(srv->cli, path, mode, 0)) { - errno = smbc_errno(context, srv->cli); - TALLOC_FREE(frame); - return -1; - } - - TALLOC_FREE(frame); - return 0; -} - -static int -smbc_utimes_ctx(SMBCCTX *context, - const char *fname, - struct timeval *tbuf) -{ - SMBCSRV *srv = NULL; - char *server = NULL; - char *share = NULL; - char *user = NULL; - char *password = NULL; - char *workgroup = NULL; - char *path = NULL; - time_t access_time; - time_t write_time; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !context->internal->_initialized) { - errno = EINVAL; /* Best I can think of ... */ - TALLOC_FREE(frame); - return -1; - } - - if (!fname) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - if (tbuf == NULL) { - access_time = write_time = time(NULL); - } else { - access_time = tbuf[0].tv_sec; - write_time = tbuf[1].tv_sec; - } - - if (DEBUGLVL(4)) { - char *p; - char atimebuf[32]; - char mtimebuf[32]; - - strncpy(atimebuf, ctime(&access_time), sizeof(atimebuf) - 1); - atimebuf[sizeof(atimebuf) - 1] = '\0'; - if ((p = strchr(atimebuf, '\n')) != NULL) { - *p = '\0'; - } - - strncpy(mtimebuf, ctime(&write_time), sizeof(mtimebuf) - 1); - mtimebuf[sizeof(mtimebuf) - 1] = '\0'; - if ((p = strchr(mtimebuf, '\n')) != NULL) { - *p = '\0'; - } - - dbgtext("smbc_utimes(%s, atime = %s mtime = %s)\n", - fname, atimebuf, mtimebuf); - } - - if (smbc_parse_path(frame, - 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->user); - if (!user) { - errno = ENOMEM; - TALLOC_FREE(frame); - 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_setatr(context, srv, path, - 0, access_time, write_time, 0, 0)) { - TALLOC_FREE(frame); - return -1; /* errno set by smbc_setatr */ - } - - TALLOC_FREE(frame); - return 0; -} - - -/* - * Sort ACEs according to the documentation at - * http://support.microsoft.com/kb/269175, at least as far as it defines the - * order. - */ - -static int -ace_compare(SEC_ACE *ace1, - SEC_ACE *ace2) -{ - bool b1; - bool b2; - - /* If the ACEs are equal, we have nothing more to do. */ - if (sec_ace_equal(ace1, ace2)) { - return 0; - } - - /* Inherited follow non-inherited */ - b1 = ((ace1->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0); - b2 = ((ace2->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0); - if (b1 != b2) { - return (b1 ? 1 : -1); - } - - /* - * What shall we do with AUDITs and ALARMs? It's undefined. We'll - * sort them after DENY and ALLOW. - */ - b1 = (ace1->type != SEC_ACE_TYPE_ACCESS_ALLOWED && - ace1->type != SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT && - ace1->type != SEC_ACE_TYPE_ACCESS_DENIED && - ace1->type != SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); - b2 = (ace2->type != SEC_ACE_TYPE_ACCESS_ALLOWED && - ace2->type != SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT && - ace2->type != SEC_ACE_TYPE_ACCESS_DENIED && - ace2->type != SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); - if (b1 != b2) { - return (b1 ? 1 : -1); - } - - /* Allowed ACEs follow denied ACEs */ - b1 = (ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED || - ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT); - b2 = (ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED || - ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT); - if (b1 != b2) { - return (b1 ? 1 : -1); - } - - /* - * ACEs applying to an entity's object follow those applying to the - * entity itself - */ - b1 = (ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || - ace1->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); - b2 = (ace2->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || - ace2->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT); - if (b1 != b2) { - return (b1 ? 1 : -1); - } - - /* - * If we get this far, the ACEs are similar as far as the - * characteristics we typically care about (those defined by the - * referenced MS document). We'll now sort by characteristics that - * just seems reasonable. - */ - - if (ace1->type != ace2->type) { - return ace2->type - ace1->type; - } - - if (sid_compare(&ace1->trustee, &ace2->trustee)) { - return sid_compare(&ace1->trustee, &ace2->trustee); - } - - if (ace1->flags != ace2->flags) { - return ace1->flags - ace2->flags; - } - - if (ace1->access_mask != ace2->access_mask) { - return ace1->access_mask - ace2->access_mask; - } - - if (ace1->size != ace2->size) { - return ace1->size - ace2->size; - } - - return memcmp(ace1, ace2, sizeof(SEC_ACE)); -} - - -static void -sort_acl(SEC_ACL *the_acl) -{ - uint32 i; - if (!the_acl) return; - - qsort(the_acl->aces, the_acl->num_aces, sizeof(the_acl->aces[0]), - QSORT_CAST ace_compare); - - for (i=1;inum_aces;) { - if (sec_ace_equal(&the_acl->aces[i-1], &the_acl->aces[i])) { - int j; - for (j=i; jnum_aces-1; j++) { - the_acl->aces[j] = the_acl->aces[j+1]; - } - the_acl->num_aces--; - } else { - i++; - } - } -} - -/* convert a SID to a string, either numeric or username/group */ -static void -convert_sid_to_string(struct cli_state *ipc_cli, - POLICY_HND *pol, - fstring str, - bool numeric, - DOM_SID *sid) -{ - char **domains = NULL; - char **names = NULL; - enum lsa_SidType *types = NULL; - struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli); - TALLOC_CTX *ctx; - - sid_to_fstring(str, sid); - - if (numeric) { - return; /* no lookup desired */ - } - - if (!pipe_hnd) { - return; - } - - /* Ask LSA to convert the sid to a name */ - - ctx = talloc_stackframe(); - - if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(pipe_hnd, ctx, - pol, 1, sid, &domains, - &names, &types)) || - !domains || !domains[0] || !names || !names[0]) { - TALLOC_FREE(ctx); - return; - } - - TALLOC_FREE(ctx); - /* Converted OK */ - - slprintf(str, sizeof(fstring) - 1, "%s%s%s", - domains[0], lp_winbind_separator(), - names[0]); -} - -/* convert a string to a SID, either numeric or username/group */ -static bool -convert_string_to_sid(struct cli_state *ipc_cli, - POLICY_HND *pol, - bool numeric, - DOM_SID *sid, - const char *str) -{ - enum lsa_SidType *types = NULL; - DOM_SID *sids = NULL; - bool result = True; - TALLOC_CTX *ctx = NULL; - struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli); - - if (!pipe_hnd) { - return False; - } - - if (numeric) { - if (strncmp(str, "S-", 2) == 0) { - return string_to_sid(sid, str); - } - - result = False; - goto done; - } - - ctx = talloc_stackframe(); - if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_names(pipe_hnd, ctx, - pol, 1, &str, NULL, 1, &sids, - &types))) { - result = False; - goto done; - } - - sid_copy(sid, &sids[0]); - done: - - TALLOC_FREE(ctx); - return result; -} - - -/* parse an ACE in the same format as print_ace() */ -static bool -parse_ace(struct cli_state *ipc_cli, - POLICY_HND *pol, - SEC_ACE *ace, - bool numeric, - char *str) -{ - char *p; - const char *cp; - char *tok; - unsigned int atype; - unsigned int aflags; - unsigned int amask; - DOM_SID sid; - SEC_ACCESS mask; - const struct perm_value *v; - struct perm_value { - const char *perm; - uint32 mask; - }; - TALLOC_CTX *frame = talloc_stackframe(); - - /* These values discovered by inspection */ - static const struct perm_value special_values[] = { - { "R", 0x00120089 }, - { "W", 0x00120116 }, - { "X", 0x001200a0 }, - { "D", 0x00010000 }, - { "P", 0x00040000 }, - { "O", 0x00080000 }, - { NULL, 0 }, - }; - - static const struct perm_value standard_values[] = { - { "READ", 0x001200a9 }, - { "CHANGE", 0x001301bf }, - { "FULL", 0x001f01ff }, - { NULL, 0 }, - }; - - - ZERO_STRUCTP(ace); - p = strchr_m(str,':'); - if (!p) { - TALLOC_FREE(frame); - return False; - } - *p = '\0'; - p++; - /* Try to parse numeric form */ - - if (sscanf(p, "%i/%i/%i", &atype, &aflags, &amask) == 3 && - convert_string_to_sid(ipc_cli, pol, numeric, &sid, str)) { - goto done; - } - - /* Try to parse text form */ - - if (!convert_string_to_sid(ipc_cli, pol, numeric, &sid, str)) { - TALLOC_FREE(frame); - return false; - } - - cp = p; - if (!next_token_talloc(frame, &cp, &tok, "/")) { - TALLOC_FREE(frame); - return false; - } - - if (StrnCaseCmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) { - atype = SEC_ACE_TYPE_ACCESS_ALLOWED; - } else if (StrnCaseCmp(tok, "DENIED", strlen("DENIED")) == 0) { - atype = SEC_ACE_TYPE_ACCESS_DENIED; - } else { - TALLOC_FREE(frame); - return false; - } - - /* Only numeric form accepted for flags at present */ - - if (!(next_token_talloc(frame, &cp, &tok, "/") && - sscanf(tok, "%i", &aflags))) { - TALLOC_FREE(frame); - return false; - } - - if (!next_token_talloc(frame, &cp, &tok, "/")) { - TALLOC_FREE(frame); - return false; - } - - if (strncmp(tok, "0x", 2) == 0) { - if (sscanf(tok, "%i", &amask) != 1) { - TALLOC_FREE(frame); - return false; - } - goto done; - } - - for (v = standard_values; v->perm; v++) { - if (strcmp(tok, v->perm) == 0) { - amask = v->mask; - goto done; - } - } - - p = tok; - - while(*p) { - bool found = False; - - for (v = special_values; v->perm; v++) { - if (v->perm[0] == *p) { - amask |= v->mask; - found = True; - } - } - - if (!found) { - TALLOC_FREE(frame); - return false; - } - p++; - } - - if (*p) { - TALLOC_FREE(frame); - return false; - } - - done: - mask = amask; - init_sec_ace(ace, &sid, atype, mask, aflags); - TALLOC_FREE(frame); - return true; -} - -/* add an ACE to a list of ACEs in a SEC_ACL */ -static bool -add_ace(SEC_ACL **the_acl, - SEC_ACE *ace, - TALLOC_CTX *ctx) -{ - SEC_ACL *newacl; - SEC_ACE *aces; - - if (! *the_acl) { - (*the_acl) = make_sec_acl(ctx, 3, 1, ace); - return True; - } - - if ((aces = SMB_CALLOC_ARRAY(SEC_ACE, 1+(*the_acl)->num_aces)) == NULL) { - return False; - } - memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(SEC_ACE)); - memcpy(aces+(*the_acl)->num_aces, ace, sizeof(SEC_ACE)); - newacl = make_sec_acl(ctx, (*the_acl)->revision, - 1+(*the_acl)->num_aces, aces); - SAFE_FREE(aces); - (*the_acl) = newacl; - return True; -} - - -/* parse a ascii version of a security descriptor */ -static SEC_DESC * -sec_desc_parse(TALLOC_CTX *ctx, - struct cli_state *ipc_cli, - POLICY_HND *pol, - bool numeric, - char *str) -{ - const char *p = str; - char *tok; - SEC_DESC *ret = NULL; - size_t sd_size; - DOM_SID *group_sid=NULL; - DOM_SID *owner_sid=NULL; - SEC_ACL *dacl=NULL; - int revision=1; - - while (next_token_talloc(ctx, &p, &tok, "\t,\r\n")) { - - if (StrnCaseCmp(tok,"REVISION:", 9) == 0) { - revision = strtol(tok+9, NULL, 16); - continue; - } - - if (StrnCaseCmp(tok,"OWNER:", 6) == 0) { - if (owner_sid) { - DEBUG(5, ("OWNER specified more than once!\n")); - goto done; - } - owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1); - if (!owner_sid || - !convert_string_to_sid(ipc_cli, pol, - numeric, - owner_sid, tok+6)) { - DEBUG(5, ("Failed to parse owner sid\n")); - goto done; - } - continue; - } - - if (StrnCaseCmp(tok,"OWNER+:", 7) == 0) { - if (owner_sid) { - DEBUG(5, ("OWNER specified more than once!\n")); - goto done; - } - owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1); - if (!owner_sid || - !convert_string_to_sid(ipc_cli, pol, - False, - owner_sid, tok+7)) { - DEBUG(5, ("Failed to parse owner sid\n")); - goto done; - } - continue; - } - - if (StrnCaseCmp(tok,"GROUP:", 6) == 0) { - if (group_sid) { - DEBUG(5, ("GROUP specified more than once!\n")); - goto done; - } - group_sid = SMB_CALLOC_ARRAY(DOM_SID, 1); - if (!group_sid || - !convert_string_to_sid(ipc_cli, pol, - numeric, - group_sid, tok+6)) { - DEBUG(5, ("Failed to parse group sid\n")); - goto done; - } - continue; - } - - if (StrnCaseCmp(tok,"GROUP+:", 7) == 0) { - if (group_sid) { - DEBUG(5, ("GROUP specified more than once!\n")); - goto done; - } - group_sid = SMB_CALLOC_ARRAY(DOM_SID, 1); - if (!group_sid || - !convert_string_to_sid(ipc_cli, pol, - False, - group_sid, tok+6)) { - DEBUG(5, ("Failed to parse group sid\n")); - goto done; - } - continue; - } - - if (StrnCaseCmp(tok,"ACL:", 4) == 0) { - SEC_ACE ace; - if (!parse_ace(ipc_cli, pol, &ace, numeric, tok+4)) { - DEBUG(5, ("Failed to parse ACL %s\n", tok)); - goto done; - } - if(!add_ace(&dacl, &ace, ctx)) { - DEBUG(5, ("Failed to add ACL %s\n", tok)); - goto done; - } - continue; - } - - if (StrnCaseCmp(tok,"ACL+:", 5) == 0) { - SEC_ACE ace; - if (!parse_ace(ipc_cli, pol, &ace, False, tok+5)) { - DEBUG(5, ("Failed to parse ACL %s\n", tok)); - goto done; - } - if(!add_ace(&dacl, &ace, ctx)) { - DEBUG(5, ("Failed to add ACL %s\n", tok)); - goto done; - } - continue; - } - - DEBUG(5, ("Failed to parse security descriptor\n")); - goto done; - } - - ret = make_sec_desc(ctx, revision, SEC_DESC_SELF_RELATIVE, - owner_sid, group_sid, NULL, dacl, &sd_size); - - done: - SAFE_FREE(group_sid); - SAFE_FREE(owner_sid); - - return ret; -} - - -/* Obtain the current dos attributes */ -static DOS_ATTR_DESC * -dos_attr_query(SMBCCTX *context, - TALLOC_CTX *ctx, - const char *filename, - SMBCSRV *srv) -{ - struct timespec create_time_ts; - struct timespec write_time_ts; - struct timespec access_time_ts; - struct timespec change_time_ts; - SMB_OFF_T size = 0; - uint16 mode = 0; - SMB_INO_T inode = 0; - DOS_ATTR_DESC *ret; - - ret = TALLOC_P(ctx, DOS_ATTR_DESC); - if (!ret) { - errno = ENOMEM; - return NULL; - } - - /* Obtain the DOS attributes */ - if (!smbc_getatr(context, srv, CONST_DISCARD(char *, filename), - &mode, &size, - &create_time_ts, - &access_time_ts, - &write_time_ts, - &change_time_ts, - &inode)) { - errno = smbc_errno(context, srv->cli); - DEBUG(5, ("dos_attr_query Failed to query old attributes\n")); - return NULL; - } - - ret->mode = mode; - ret->size = size; - ret->create_time = convert_timespec_to_time_t(create_time_ts); - ret->access_time = convert_timespec_to_time_t(access_time_ts); - ret->write_time = convert_timespec_to_time_t(write_time_ts); - ret->change_time = convert_timespec_to_time_t(change_time_ts); - ret->inode = inode; - - return ret; -} - - -/* parse a ascii version of a security descriptor */ -static void -dos_attr_parse(SMBCCTX *context, - DOS_ATTR_DESC *dad, - SMBCSRV *srv, - char *str) -{ - int n; - const char *p = str; - char *tok = NULL; - TALLOC_CTX *frame = NULL; - struct { - const char * create_time_attr; - const char * access_time_attr; - const char * write_time_attr; - const char * change_time_attr; - } attr_strings; - - /* Determine whether to use old-style or new-style attribute names */ - if (context->internal->_full_time_names) { - /* new-style names */ - attr_strings.create_time_attr = "CREATE_TIME"; - attr_strings.access_time_attr = "ACCESS_TIME"; - attr_strings.write_time_attr = "WRITE_TIME"; - attr_strings.change_time_attr = "CHANGE_TIME"; - } else { - /* old-style names */ - attr_strings.create_time_attr = NULL; - attr_strings.access_time_attr = "A_TIME"; - attr_strings.write_time_attr = "M_TIME"; - attr_strings.change_time_attr = "C_TIME"; - } - - /* if this is to set the entire ACL... */ - if (*str == '*') { - /* ... then increment past the first colon if there is one */ - if ((p = strchr(str, ':')) != NULL) { - ++p; - } else { - p = str; - } - } - - frame = talloc_stackframe(); - while (next_token_talloc(frame, &p, &tok, "\t,\r\n")) { - if (StrnCaseCmp(tok, "MODE:", 5) == 0) { - long request = strtol(tok+5, NULL, 16); - if (request == 0) { - dad->mode = (request | - (IS_DOS_DIR(dad->mode) - ? FILE_ATTRIBUTE_DIRECTORY - : FILE_ATTRIBUTE_NORMAL)); - } else { - dad->mode = request; - } - continue; - } - - if (StrnCaseCmp(tok, "SIZE:", 5) == 0) { - dad->size = (SMB_OFF_T)atof(tok+5); - continue; - } - - n = strlen(attr_strings.access_time_attr); - if (StrnCaseCmp(tok, attr_strings.access_time_attr, n) == 0) { - dad->access_time = (time_t)strtol(tok+n+1, NULL, 10); - continue; - } - - n = strlen(attr_strings.change_time_attr); - if (StrnCaseCmp(tok, attr_strings.change_time_attr, n) == 0) { - dad->change_time = (time_t)strtol(tok+n+1, NULL, 10); - continue; - } - - n = strlen(attr_strings.write_time_attr); - if (StrnCaseCmp(tok, attr_strings.write_time_attr, n) == 0) { - dad->write_time = (time_t)strtol(tok+n+1, NULL, 10); - continue; - } - - if (attr_strings.create_time_attr != NULL) { - n = strlen(attr_strings.create_time_attr); - if (StrnCaseCmp(tok, attr_strings.create_time_attr, - n) == 0) { - dad->create_time = (time_t)strtol(tok+n+1, - NULL, 10); - continue; - } - } - - if (StrnCaseCmp(tok, "INODE:", 6) == 0) { - dad->inode = (SMB_INO_T)atof(tok+6); - continue; - } - } - TALLOC_FREE(frame); -} - -/***************************************************** - Retrieve the acls for a file. -*******************************************************/ - -static int -cacl_get(SMBCCTX *context, - TALLOC_CTX *ctx, - SMBCSRV *srv, - struct cli_state *ipc_cli, - POLICY_HND *pol, - char *filename, - char *attr_name, - char *buf, - int bufsize) -{ - uint32 i; - int n = 0; - int n_used; - bool all; - bool all_nt; - bool all_nt_acls; - bool all_dos; - bool some_nt; - bool some_dos; - bool exclude_nt_revision = False; - bool exclude_nt_owner = False; - bool exclude_nt_group = False; - bool exclude_nt_acl = False; - bool exclude_dos_mode = False; - bool exclude_dos_size = False; - bool exclude_dos_create_time = False; - bool exclude_dos_access_time = False; - bool exclude_dos_write_time = False; - bool exclude_dos_change_time = False; - bool exclude_dos_inode = False; - bool numeric = True; - bool determine_size = (bufsize == 0); - int fnum = -1; - SEC_DESC *sd; - fstring sidstr; - fstring name_sandbox; - char *name; - char *pExclude; - char *p; - struct timespec create_time_ts; - struct timespec write_time_ts; - struct timespec access_time_ts; - struct timespec change_time_ts; - time_t create_time = (time_t)0; - time_t write_time = (time_t)0; - time_t access_time = (time_t)0; - time_t change_time = (time_t)0; - SMB_OFF_T size = 0; - uint16 mode = 0; - SMB_INO_T ino = 0; - struct cli_state *cli = srv->cli; - struct { - const char * create_time_attr; - const char * access_time_attr; - const char * write_time_attr; - const char * change_time_attr; - } attr_strings; - struct { - const char * create_time_attr; - const char * access_time_attr; - const char * write_time_attr; - const char * change_time_attr; - } excl_attr_strings; - - /* Determine whether to use old-style or new-style attribute names */ - if (context->internal->_full_time_names) { - /* new-style names */ - attr_strings.create_time_attr = "CREATE_TIME"; - attr_strings.access_time_attr = "ACCESS_TIME"; - attr_strings.write_time_attr = "WRITE_TIME"; - attr_strings.change_time_attr = "CHANGE_TIME"; - - excl_attr_strings.create_time_attr = "CREATE_TIME"; - excl_attr_strings.access_time_attr = "ACCESS_TIME"; - excl_attr_strings.write_time_attr = "WRITE_TIME"; - excl_attr_strings.change_time_attr = "CHANGE_TIME"; - } else { - /* old-style names */ - attr_strings.create_time_attr = NULL; - attr_strings.access_time_attr = "A_TIME"; - attr_strings.write_time_attr = "M_TIME"; - attr_strings.change_time_attr = "C_TIME"; - - excl_attr_strings.create_time_attr = NULL; - excl_attr_strings.access_time_attr = "dos_attr.A_TIME"; - excl_attr_strings.write_time_attr = "dos_attr.M_TIME"; - excl_attr_strings.change_time_attr = "dos_attr.C_TIME"; - } - - /* Copy name so we can strip off exclusions (if any are specified) */ - strncpy(name_sandbox, attr_name, sizeof(name_sandbox) - 1); - - /* Ensure name is null terminated */ - name_sandbox[sizeof(name_sandbox) - 1] = '\0'; - - /* Play in the sandbox */ - name = name_sandbox; - - /* If there are any exclusions, point to them and mask them from name */ - if ((pExclude = strchr(name, '!')) != NULL) - { - *pExclude++ = '\0'; - } - - all = (StrnCaseCmp(name, "system.*", 8) == 0); - all_nt = (StrnCaseCmp(name, "system.nt_sec_desc.*", 20) == 0); - all_nt_acls = (StrnCaseCmp(name, "system.nt_sec_desc.acl.*", 24) == 0); - all_dos = (StrnCaseCmp(name, "system.dos_attr.*", 17) == 0); - some_nt = (StrnCaseCmp(name, "system.nt_sec_desc.", 19) == 0); - some_dos = (StrnCaseCmp(name, "system.dos_attr.", 16) == 0); - numeric = (* (name + strlen(name) - 1) != '+'); - - /* Look for exclusions from "all" requests */ - if (all || all_nt || all_dos) { - - /* Exclusions are delimited by '!' */ - for (; - pExclude != NULL; - pExclude = (p == NULL ? NULL : p + 1)) { - - /* Find end of this exclusion name */ - if ((p = strchr(pExclude, '!')) != NULL) - { - *p = '\0'; - } - - /* Which exclusion name is this? */ - if (StrCaseCmp(pExclude, "nt_sec_desc.revision") == 0) { - exclude_nt_revision = True; - } - else if (StrCaseCmp(pExclude, "nt_sec_desc.owner") == 0) { - exclude_nt_owner = True; - } - else if (StrCaseCmp(pExclude, "nt_sec_desc.group") == 0) { - exclude_nt_group = True; - } - else if (StrCaseCmp(pExclude, "nt_sec_desc.acl") == 0) { - exclude_nt_acl = True; - } - else if (StrCaseCmp(pExclude, "dos_attr.mode") == 0) { - exclude_dos_mode = True; - } - else if (StrCaseCmp(pExclude, "dos_attr.size") == 0) { - exclude_dos_size = True; - } - else if (excl_attr_strings.create_time_attr != NULL && - StrCaseCmp(pExclude, - excl_attr_strings.change_time_attr) == 0) { - exclude_dos_create_time = True; - } - else if (StrCaseCmp(pExclude, - excl_attr_strings.access_time_attr) == 0) { - exclude_dos_access_time = True; - } - else if (StrCaseCmp(pExclude, - excl_attr_strings.write_time_attr) == 0) { - exclude_dos_write_time = True; - } - else if (StrCaseCmp(pExclude, - excl_attr_strings.change_time_attr) == 0) { - exclude_dos_change_time = True; - } - else if (StrCaseCmp(pExclude, "dos_attr.inode") == 0) { - exclude_dos_inode = True; - } - else { - DEBUG(5, ("cacl_get received unknown exclusion: %s\n", - pExclude)); - errno = ENOATTR; - return -1; - } - } - } - - n_used = 0; - - /* - * If we are (possibly) talking to an NT or new system and some NT - * attributes have been requested... - */ - if (ipc_cli && (all || some_nt || all_nt_acls)) { - /* Point to the portion after "system.nt_sec_desc." */ - name += 19; /* if (all) this will be invalid but unused */ - - /* ... then obtain any NT attributes which were requested */ - fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ); - - if (fnum == -1) { - DEBUG(5, ("cacl_get failed to open %s: %s\n", - filename, cli_errstr(cli))); - errno = 0; - return -1; - } - - sd = cli_query_secdesc(cli, fnum, ctx); - - if (!sd) { - DEBUG(5, - ("cacl_get Failed to query old descriptor\n")); - errno = 0; - return -1; - } - - cli_close(cli, fnum); - - if (! exclude_nt_revision) { - if (all || all_nt) { - if (determine_size) { - p = talloc_asprintf(ctx, - "REVISION:%d", - sd->revision); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "REVISION:%d", - sd->revision); - } - } else if (StrCaseCmp(name, "revision") == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "%d", - sd->revision); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, "%d", - sd->revision); - } - } - - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; - } - buf += n; - n_used += n; - bufsize -= n; - n = 0; - } - - if (! exclude_nt_owner) { - /* Get owner and group sid */ - if (sd->owner_sid) { - convert_sid_to_string(ipc_cli, pol, - sidstr, - numeric, - sd->owner_sid); - } else { - fstrcpy(sidstr, ""); - } - - if (all || all_nt) { - if (determine_size) { - p = talloc_asprintf(ctx, ",OWNER:%s", - sidstr); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else if (sidstr[0] != '\0') { - n = snprintf(buf, bufsize, - ",OWNER:%s", sidstr); - } - } else if (StrnCaseCmp(name, "owner", 5) == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "%s", sidstr); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, "%s", - sidstr); - } - } - - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; - } - buf += n; - n_used += n; - bufsize -= n; - n = 0; - } - - if (! exclude_nt_group) { - if (sd->group_sid) { - convert_sid_to_string(ipc_cli, pol, - sidstr, numeric, - sd->group_sid); - } else { - fstrcpy(sidstr, ""); - } - - if (all || all_nt) { - if (determine_size) { - p = talloc_asprintf(ctx, ",GROUP:%s", - sidstr); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else if (sidstr[0] != '\0') { - n = snprintf(buf, bufsize, - ",GROUP:%s", sidstr); - } - } else if (StrnCaseCmp(name, "group", 5) == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "%s", sidstr); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "%s", sidstr); - } - } - - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; - } - buf += n; - n_used += n; - bufsize -= n; - n = 0; - } - - if (! exclude_nt_acl) { - /* Add aces to value buffer */ - for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) { - - SEC_ACE *ace = &sd->dacl->aces[i]; - convert_sid_to_string(ipc_cli, pol, - sidstr, numeric, - &ace->trustee); - - if (all || all_nt) { - if (determine_size) { - p = talloc_asprintf( - ctx, - ",ACL:" - "%s:%d/%d/0x%08x", - sidstr, - ace->type, - ace->flags, - ace->access_mask); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf( - buf, bufsize, - ",ACL:%s:%d/%d/0x%08x", - sidstr, - ace->type, - ace->flags, - ace->access_mask); - } - } else if ((StrnCaseCmp(name, "acl", 3) == 0 && - StrCaseCmp(name+3, sidstr) == 0) || - (StrnCaseCmp(name, "acl+", 4) == 0 && - StrCaseCmp(name+4, sidstr) == 0)) { - if (determine_size) { - p = talloc_asprintf( - ctx, - "%d/%d/0x%08x", - ace->type, - ace->flags, - ace->access_mask); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "%d/%d/0x%08x", - ace->type, - ace->flags, - ace->access_mask); - } - } else if (all_nt_acls) { - if (determine_size) { - p = talloc_asprintf( - ctx, - "%s%s:%d/%d/0x%08x", - i ? "," : "", - sidstr, - ace->type, - ace->flags, - ace->access_mask); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "%s%s:%d/%d/0x%08x", - i ? "," : "", - sidstr, - ace->type, - ace->flags, - ace->access_mask); - } - } - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; - } - buf += n; - n_used += n; - bufsize -= n; - n = 0; - } - } - - /* Restore name pointer to its original value */ - name -= 19; - } - - if (all || some_dos) { - /* Point to the portion after "system.dos_attr." */ - name += 16; /* if (all) this will be invalid but unused */ - - /* Obtain the DOS attributes */ - if (!smbc_getatr(context, srv, filename, &mode, &size, - &create_time_ts, - &access_time_ts, - &write_time_ts, - &change_time_ts, - &ino)) { - - errno = smbc_errno(context, srv->cli); - return -1; - - } - - create_time = convert_timespec_to_time_t(create_time_ts); - access_time = convert_timespec_to_time_t(access_time_ts); - write_time = convert_timespec_to_time_t(write_time_ts); - change_time = convert_timespec_to_time_t(change_time_ts); - - if (! exclude_dos_mode) { - if (all || all_dos) { - if (determine_size) { - p = talloc_asprintf(ctx, - "%sMODE:0x%x", - (ipc_cli && - (all || some_nt) - ? "," - : ""), - mode); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "%sMODE:0x%x", - (ipc_cli && - (all || some_nt) - ? "," - : ""), - mode); - } - } else if (StrCaseCmp(name, "mode") == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "0x%x", mode); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "0x%x", mode); - } - } - - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; - } - buf += n; - n_used += n; - bufsize -= n; - n = 0; - } - - if (! exclude_dos_size) { - if (all || all_dos) { - if (determine_size) { - p = talloc_asprintf( - ctx, - ",SIZE:%.0f", - (double)size); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - ",SIZE:%.0f", - (double)size); - } - } else if (StrCaseCmp(name, "size") == 0) { - if (determine_size) { - p = talloc_asprintf( - ctx, - "%.0f", - (double)size); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "%.0f", - (double)size); - } - } - - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; - } - buf += n; - n_used += n; - bufsize -= n; - n = 0; - } - - if (! exclude_dos_create_time && - attr_strings.create_time_attr != NULL) { - if (all || all_dos) { - if (determine_size) { - p = talloc_asprintf(ctx, - ",%s:%lu", - attr_strings.create_time_attr, - create_time); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - ",%s:%lu", - attr_strings.create_time_attr, - create_time); - } - } else if (StrCaseCmp(name, attr_strings.create_time_attr) == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "%lu", create_time); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "%lu", create_time); - } - } - - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; - } - buf += n; - n_used += n; - bufsize -= n; - n = 0; - } - - if (! exclude_dos_access_time) { - if (all || all_dos) { - if (determine_size) { - p = talloc_asprintf(ctx, - ",%s:%lu", - attr_strings.access_time_attr, - access_time); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - ",%s:%lu", - attr_strings.access_time_attr, - access_time); - } - } else if (StrCaseCmp(name, attr_strings.access_time_attr) == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "%lu", access_time); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "%lu", access_time); - } - } - - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; - } - buf += n; - n_used += n; - bufsize -= n; - n = 0; - } - - if (! exclude_dos_write_time) { - if (all || all_dos) { - if (determine_size) { - p = talloc_asprintf(ctx, - ",%s:%lu", - attr_strings.write_time_attr, - write_time); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - ",%s:%lu", - attr_strings.write_time_attr, - write_time); - } - } else if (StrCaseCmp(name, attr_strings.write_time_attr) == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "%lu", write_time); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "%lu", write_time); - } - } - - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; - } - buf += n; - n_used += n; - bufsize -= n; - n = 0; - } - - if (! exclude_dos_change_time) { - if (all || all_dos) { - if (determine_size) { - p = talloc_asprintf(ctx, - ",%s:%lu", - attr_strings.change_time_attr, - change_time); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - ",%s:%lu", - attr_strings.change_time_attr, - change_time); - } - } else if (StrCaseCmp(name, attr_strings.change_time_attr) == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "%lu", change_time); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "%lu", change_time); - } - } - - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; - } - buf += n; - n_used += n; - bufsize -= n; - n = 0; - } - - if (! exclude_dos_inode) { - if (all || all_dos) { - if (determine_size) { - p = talloc_asprintf( - ctx, - ",INODE:%.0f", - (double)ino); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - ",INODE:%.0f", - (double) ino); - } - } else if (StrCaseCmp(name, "inode") == 0) { - if (determine_size) { - p = talloc_asprintf( - ctx, - "%.0f", - (double) ino); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "%.0f", - (double) ino); - } - } - - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; - } - buf += n; - n_used += n; - bufsize -= n; - n = 0; - } - - /* Restore name pointer to its original value */ - name -= 16; - } - - if (n_used == 0) { - errno = ENOATTR; - return -1; - } - - return n_used; -} - -/***************************************************** -set the ACLs on a file given an ascii description -*******************************************************/ -static int -cacl_set(TALLOC_CTX *ctx, - struct cli_state *cli, - struct cli_state *ipc_cli, - POLICY_HND *pol, - const char *filename, - const char *the_acl, - int mode, - int flags) -{ - int fnum; - int err = 0; - SEC_DESC *sd = NULL, *old; - SEC_ACL *dacl = NULL; - DOM_SID *owner_sid = NULL; - DOM_SID *group_sid = NULL; - uint32 i, j; - size_t sd_size; - int ret = 0; - char *p; - bool numeric = True; - - /* the_acl will be null for REMOVE_ALL operations */ - if (the_acl) { - numeric = ((p = strchr(the_acl, ':')) != NULL && - p > the_acl && - p[-1] != '+'); - - /* if this is to set the entire ACL... */ - if (*the_acl == '*') { - /* ... then increment past the first colon */ - the_acl = p + 1; - } - - sd = sec_desc_parse(ctx, ipc_cli, pol, numeric, - CONST_DISCARD(char *, the_acl)); - - if (!sd) { - errno = EINVAL; - return -1; - } - } - - /* SMBC_XATTR_MODE_REMOVE_ALL is the only caller - that doesn't deref sd */ - - if (!sd && (mode != SMBC_XATTR_MODE_REMOVE_ALL)) { - errno = EINVAL; - return -1; - } - - /* The desired access below is the only one I could find that works - with NT4, W2KP and Samba */ - - fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ); - - if (fnum == -1) { - DEBUG(5, ("cacl_set failed to open %s: %s\n", - filename, cli_errstr(cli))); - errno = 0; - return -1; - } - - old = cli_query_secdesc(cli, fnum, ctx); - - if (!old) { - DEBUG(5, ("cacl_set Failed to query old descriptor\n")); - errno = 0; - return -1; - } - - cli_close(cli, fnum); - - switch (mode) { - case SMBC_XATTR_MODE_REMOVE_ALL: - old->dacl->num_aces = 0; - dacl = old->dacl; - break; - - case SMBC_XATTR_MODE_REMOVE: - for (i=0;sd->dacl && idacl->num_aces;i++) { - bool found = False; - - for (j=0;old->dacl && jdacl->num_aces;j++) { - if (sec_ace_equal(&sd->dacl->aces[i], - &old->dacl->aces[j])) { - uint32 k; - for (k=j; kdacl->num_aces-1;k++) { - old->dacl->aces[k] = - old->dacl->aces[k+1]; - } - old->dacl->num_aces--; - found = True; - dacl = old->dacl; - break; - } - } - - if (!found) { - err = ENOATTR; - ret = -1; - goto failed; - } - } - break; - - case SMBC_XATTR_MODE_ADD: - for (i=0;sd->dacl && idacl->num_aces;i++) { - bool found = False; - - for (j=0;old->dacl && jdacl->num_aces;j++) { - if (sid_equal(&sd->dacl->aces[i].trustee, - &old->dacl->aces[j].trustee)) { - if (!(flags & SMBC_XATTR_FLAG_CREATE)) { - err = EEXIST; - ret = -1; - goto failed; - } - old->dacl->aces[j] = sd->dacl->aces[i]; - ret = -1; - found = True; - } - } - - if (!found && (flags & SMBC_XATTR_FLAG_REPLACE)) { - err = ENOATTR; - ret = -1; - goto failed; - } - - for (i=0;sd->dacl && idacl->num_aces;i++) { - add_ace(&old->dacl, &sd->dacl->aces[i], ctx); - } - } - dacl = old->dacl; - break; - - case SMBC_XATTR_MODE_SET: - old = sd; - owner_sid = old->owner_sid; - group_sid = old->group_sid; - dacl = old->dacl; - break; - - case SMBC_XATTR_MODE_CHOWN: - owner_sid = sd->owner_sid; - break; - - case SMBC_XATTR_MODE_CHGRP: - group_sid = sd->group_sid; - break; - } - - /* Denied ACE entries must come before allowed ones */ - sort_acl(old->dacl); - - /* Create new security descriptor and set it */ - sd = make_sec_desc(ctx, old->revision, SEC_DESC_SELF_RELATIVE, - owner_sid, group_sid, NULL, dacl, &sd_size); - - fnum = cli_nt_create(cli, filename, - WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS); - - if (fnum == -1) { - DEBUG(5, ("cacl_set failed to open %s: %s\n", - filename, cli_errstr(cli))); - errno = 0; - return -1; - } - - if (!cli_set_secdesc(cli, fnum, sd)) { - DEBUG(5, ("ERROR: secdesc set failed: %s\n", cli_errstr(cli))); - ret = -1; - } - - /* Clean up */ - - failed: - cli_close(cli, fnum); - - if (err != 0) { - errno = err; - } - - return ret; -} - - -static int -smbc_setxattr_ctx(SMBCCTX *context, - const char *fname, - const char *name, - const void *value, - size_t size, - int flags) -{ - int ret; - int ret2; - SMBCSRV *srv = NULL; - SMBCSRV *ipc_srv = NULL; - char *server = NULL; - char *share = NULL; - char *user = NULL; - char *password = NULL; - char *workgroup = NULL; - char *path = NULL; - DOS_ATTR_DESC *dad = NULL; - struct { - const char * create_time_attr; - const char * access_time_attr; - const char * write_time_attr; - const char * change_time_attr; - } attr_strings; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !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_setxattr(%s, %s, %.*s)\n", - fname, name, (int) size, (const char*)value)); - - if (smbc_parse_path(frame, - 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->user); - if (!user) { - errno = ENOMEM; - TALLOC_FREE(frame); - 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 (! srv->no_nt_session) { - ipc_srv = smbc_attr_server(frame, context, server, share, - &workgroup, &user, &password); - if (! ipc_srv) { - srv->no_nt_session = True; - } - } else { - ipc_srv = NULL; - } - - /* - * Are they asking to set the entire set of known attributes? - */ - if (StrCaseCmp(name, "system.*") == 0 || - StrCaseCmp(name, "system.*+") == 0) { - /* Yup. */ - char *namevalue = - talloc_asprintf(talloc_tos(), "%s:%s", - name+7, (const char *) value); - if (! namevalue) { - errno = ENOMEM; - ret = -1; - TALLOC_FREE(frame); - return -1; - } - - if (ipc_srv) { - ret = cacl_set(talloc_tos(), srv->cli, - ipc_srv->cli, &ipc_srv->pol, path, - namevalue, - (*namevalue == '*' - ? SMBC_XATTR_MODE_SET - : SMBC_XATTR_MODE_ADD), - flags); - } else { - ret = 0; - } - - /* get a DOS Attribute Descriptor with current attributes */ - dad = dos_attr_query(context, talloc_tos(), path, srv); - if (dad) { - /* Overwrite old with new, using what was provided */ - dos_attr_parse(context, dad, srv, namevalue); - - /* Set the new DOS attributes */ - if (! smbc_setatr(context, srv, path, - dad->create_time, - dad->access_time, - dad->write_time, - dad->change_time, - dad->mode)) { - - /* cause failure if NT failed too */ - dad = NULL; - } - } - - /* we only fail if both NT and DOS sets failed */ - if (ret < 0 && ! dad) { - ret = -1; /* in case dad was null */ - } - else { - ret = 0; - } - - TALLOC_FREE(frame); - return ret; - } - - /* - * Are they asking to set an access control element or to set - * the entire access control list? - */ - if (StrCaseCmp(name, "system.nt_sec_desc.*") == 0 || - StrCaseCmp(name, "system.nt_sec_desc.*+") == 0 || - StrCaseCmp(name, "system.nt_sec_desc.revision") == 0 || - StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 || - StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) { - - /* Yup. */ - char *namevalue = - talloc_asprintf(talloc_tos(), "%s:%s", - name+19, (const char *) value); - - if (! ipc_srv) { - ret = -1; /* errno set by smbc_server() */ - } - else if (! namevalue) { - errno = ENOMEM; - ret = -1; - } else { - ret = cacl_set(talloc_tos(), srv->cli, - ipc_srv->cli, &ipc_srv->pol, path, - namevalue, - (*namevalue == '*' - ? SMBC_XATTR_MODE_SET - : SMBC_XATTR_MODE_ADD), - flags); - } - TALLOC_FREE(frame); - return ret; - } - - /* - * Are they asking to set the owner? - */ - if (StrCaseCmp(name, "system.nt_sec_desc.owner") == 0 || - StrCaseCmp(name, "system.nt_sec_desc.owner+") == 0) { - - /* Yup. */ - char *namevalue = - talloc_asprintf(talloc_tos(), "%s:%s", - name+19, (const char *) value); - - if (! ipc_srv) { - ret = -1; /* errno set by smbc_server() */ - } - else if (! namevalue) { - errno = ENOMEM; - ret = -1; - } else { - ret = cacl_set(talloc_tos(), srv->cli, - ipc_srv->cli, &ipc_srv->pol, path, - namevalue, SMBC_XATTR_MODE_CHOWN, 0); - } - TALLOC_FREE(frame); - return ret; - } - - /* - * Are they asking to set the group? - */ - if (StrCaseCmp(name, "system.nt_sec_desc.group") == 0 || - StrCaseCmp(name, "system.nt_sec_desc.group+") == 0) { - - /* Yup. */ - char *namevalue = - talloc_asprintf(talloc_tos(), "%s:%s", - name+19, (const char *) value); - - if (! ipc_srv) { - /* errno set by smbc_server() */ - ret = -1; - } - else if (! namevalue) { - errno = ENOMEM; - ret = -1; - } else { - ret = cacl_set(talloc_tos(), srv->cli, - ipc_srv->cli, &ipc_srv->pol, path, - namevalue, SMBC_XATTR_MODE_CHGRP, 0); - } - TALLOC_FREE(frame); - return ret; - } - - /* Determine whether to use old-style or new-style attribute names */ - if (context->internal->_full_time_names) { - /* new-style names */ - attr_strings.create_time_attr = "system.dos_attr.CREATE_TIME"; - attr_strings.access_time_attr = "system.dos_attr.ACCESS_TIME"; - attr_strings.write_time_attr = "system.dos_attr.WRITE_TIME"; - attr_strings.change_time_attr = "system.dos_attr.CHANGE_TIME"; - } else { - /* old-style names */ - attr_strings.create_time_attr = NULL; - attr_strings.access_time_attr = "system.dos_attr.A_TIME"; - attr_strings.write_time_attr = "system.dos_attr.M_TIME"; - attr_strings.change_time_attr = "system.dos_attr.C_TIME"; - } - - /* - * Are they asking to set a DOS attribute? - */ - if (StrCaseCmp(name, "system.dos_attr.*") == 0 || - StrCaseCmp(name, "system.dos_attr.mode") == 0 || - (attr_strings.create_time_attr != NULL && - StrCaseCmp(name, attr_strings.create_time_attr) == 0) || - StrCaseCmp(name, attr_strings.access_time_attr) == 0 || - StrCaseCmp(name, attr_strings.write_time_attr) == 0 || - StrCaseCmp(name, attr_strings.change_time_attr) == 0) { - - /* get a DOS Attribute Descriptor with current attributes */ - dad = dos_attr_query(context, talloc_tos(), path, srv); - if (dad) { - char *namevalue = - talloc_asprintf(talloc_tos(), "%s:%s", - name+16, (const char *) value); - if (! namevalue) { - errno = ENOMEM; - ret = -1; - } else { - /* Overwrite old with provided new params */ - dos_attr_parse(context, dad, srv, namevalue); - - /* Set the new DOS attributes */ - ret2 = smbc_setatr(context, srv, path, - dad->create_time, - dad->access_time, - dad->write_time, - dad->change_time, - dad->mode); - - /* ret2 has True (success) / False (failure) */ - if (ret2) { - ret = 0; - } else { - ret = -1; - } - } - } else { - ret = -1; - } - - TALLOC_FREE(frame); - return ret; - } - - /* Unsupported attribute name */ - errno = EINVAL; - TALLOC_FREE(frame); - return -1; -} - -static int -smbc_getxattr_ctx(SMBCCTX *context, - const char *fname, - const char *name, - const void *value, - size_t size) -{ - int ret; - SMBCSRV *srv = NULL; - SMBCSRV *ipc_srv = NULL; - char *server = NULL; - char *share = NULL; - char *user = NULL; - char *password = NULL; - char *workgroup = NULL; - char *path = NULL; - struct { - const char * create_time_attr; - const char * access_time_attr; - const char * write_time_attr; - const char * change_time_attr; - } attr_strings; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !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_getxattr(%s, %s)\n", fname, name)); - - if (smbc_parse_path(frame, - 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->user); - if (!user) { - errno = ENOMEM; - TALLOC_FREE(frame); - 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 (! srv->no_nt_session) { - ipc_srv = smbc_attr_server(frame, context, server, share, - &workgroup, &user, &password); - if (! ipc_srv) { - srv->no_nt_session = True; - } - } else { - ipc_srv = NULL; - } - - /* Determine whether to use old-style or new-style attribute names */ - if (context->internal->_full_time_names) { - /* new-style names */ - attr_strings.create_time_attr = "system.dos_attr.CREATE_TIME"; - attr_strings.access_time_attr = "system.dos_attr.ACCESS_TIME"; - attr_strings.write_time_attr = "system.dos_attr.WRITE_TIME"; - attr_strings.change_time_attr = "system.dos_attr.CHANGE_TIME"; - } else { - /* old-style names */ - attr_strings.create_time_attr = NULL; - attr_strings.access_time_attr = "system.dos_attr.A_TIME"; - attr_strings.write_time_attr = "system.dos_attr.M_TIME"; - attr_strings.change_time_attr = "system.dos_attr.C_TIME"; - } - - /* Are they requesting a supported attribute? */ - if (StrCaseCmp(name, "system.*") == 0 || - StrnCaseCmp(name, "system.*!", 9) == 0 || - StrCaseCmp(name, "system.*+") == 0 || - StrnCaseCmp(name, "system.*+!", 10) == 0 || - StrCaseCmp(name, "system.nt_sec_desc.*") == 0 || - StrnCaseCmp(name, "system.nt_sec_desc.*!", 21) == 0 || - StrCaseCmp(name, "system.nt_sec_desc.*+") == 0 || - StrnCaseCmp(name, "system.nt_sec_desc.*+!", 22) == 0 || - StrCaseCmp(name, "system.nt_sec_desc.revision") == 0 || - StrCaseCmp(name, "system.nt_sec_desc.owner") == 0 || - StrCaseCmp(name, "system.nt_sec_desc.owner+") == 0 || - StrCaseCmp(name, "system.nt_sec_desc.group") == 0 || - StrCaseCmp(name, "system.nt_sec_desc.group+") == 0 || - StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 || - StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0 || - StrCaseCmp(name, "system.dos_attr.*") == 0 || - StrnCaseCmp(name, "system.dos_attr.*!", 18) == 0 || - StrCaseCmp(name, "system.dos_attr.mode") == 0 || - StrCaseCmp(name, "system.dos_attr.size") == 0 || - (attr_strings.create_time_attr != NULL && - StrCaseCmp(name, attr_strings.create_time_attr) == 0) || - StrCaseCmp(name, attr_strings.access_time_attr) == 0 || - StrCaseCmp(name, attr_strings.write_time_attr) == 0 || - StrCaseCmp(name, attr_strings.change_time_attr) == 0 || - StrCaseCmp(name, "system.dos_attr.inode") == 0) { - - /* Yup. */ - ret = cacl_get(context, talloc_tos(), srv, - ipc_srv == NULL ? NULL : ipc_srv->cli, - &ipc_srv->pol, path, - CONST_DISCARD(char *, name), - CONST_DISCARD(char *, value), size); - if (ret < 0 && errno == 0) { - errno = smbc_errno(context, srv->cli); - } - TALLOC_FREE(frame); - return ret; - } - - /* Unsupported attribute name */ - errno = EINVAL; - TALLOC_FREE(frame); - return -1; -} - - -static int -smbc_removexattr_ctx(SMBCCTX *context, - const char *fname, - const char *name) -{ - int ret; - SMBCSRV *srv = NULL; - SMBCSRV *ipc_srv = NULL; - char *server = NULL; - char *share = NULL; - char *user = NULL; - char *password = NULL; - char *workgroup = NULL; - char *path = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !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_removexattr(%s, %s)\n", fname, name)); - - if (smbc_parse_path(frame, - 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->user); - if (!user) { - errno = ENOMEM; - TALLOC_FREE(frame); - 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 (! srv->no_nt_session) { - ipc_srv = smbc_attr_server(frame, context, server, share, - &workgroup, &user, &password); - if (! ipc_srv) { - srv->no_nt_session = True; - } - } else { - ipc_srv = NULL; - } - - if (! ipc_srv) { - TALLOC_FREE(frame); - return -1; /* errno set by smbc_attr_server */ - } - - /* Are they asking to set the entire ACL? */ - if (StrCaseCmp(name, "system.nt_sec_desc.*") == 0 || - StrCaseCmp(name, "system.nt_sec_desc.*+") == 0) { - - /* Yup. */ - ret = cacl_set(talloc_tos(), srv->cli, - ipc_srv->cli, &ipc_srv->pol, path, - NULL, SMBC_XATTR_MODE_REMOVE_ALL, 0); - TALLOC_FREE(frame); - return ret; - } - - /* - * Are they asking to remove one or more spceific security descriptor - * attributes? - */ - if (StrCaseCmp(name, "system.nt_sec_desc.revision") == 0 || - StrCaseCmp(name, "system.nt_sec_desc.owner") == 0 || - StrCaseCmp(name, "system.nt_sec_desc.owner+") == 0 || - StrCaseCmp(name, "system.nt_sec_desc.group") == 0 || - StrCaseCmp(name, "system.nt_sec_desc.group+") == 0 || - StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 || - StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) { - - /* Yup. */ - ret = cacl_set(talloc_tos(), srv->cli, - ipc_srv->cli, &ipc_srv->pol, path, - name + 19, SMBC_XATTR_MODE_REMOVE, 0); - TALLOC_FREE(frame); - return ret; - } - - /* Unsupported attribute name */ - errno = EINVAL; - TALLOC_FREE(frame); - return -1; -} - -static int -smbc_listxattr_ctx(SMBCCTX *context, - const char *fname, - char *list, - size_t size) -{ - /* - * This isn't quite what listxattr() is supposed to do. This returns - * the complete set of attribute names, always, rather than only those - * attribute names which actually exist for a file. Hmmm... - */ - size_t retsize; - const char supported_old[] = - "system.*\0" - "system.*+\0" - "system.nt_sec_desc.revision\0" - "system.nt_sec_desc.owner\0" - "system.nt_sec_desc.owner+\0" - "system.nt_sec_desc.group\0" - "system.nt_sec_desc.group+\0" - "system.nt_sec_desc.acl.*\0" - "system.nt_sec_desc.acl\0" - "system.nt_sec_desc.acl+\0" - "system.nt_sec_desc.*\0" - "system.nt_sec_desc.*+\0" - "system.dos_attr.*\0" - "system.dos_attr.mode\0" - "system.dos_attr.c_time\0" - "system.dos_attr.a_time\0" - "system.dos_attr.m_time\0" - ; - const char supported_new[] = - "system.*\0" - "system.*+\0" - "system.nt_sec_desc.revision\0" - "system.nt_sec_desc.owner\0" - "system.nt_sec_desc.owner+\0" - "system.nt_sec_desc.group\0" - "system.nt_sec_desc.group+\0" - "system.nt_sec_desc.acl.*\0" - "system.nt_sec_desc.acl\0" - "system.nt_sec_desc.acl+\0" - "system.nt_sec_desc.*\0" - "system.nt_sec_desc.*+\0" - "system.dos_attr.*\0" - "system.dos_attr.mode\0" - "system.dos_attr.create_time\0" - "system.dos_attr.access_time\0" - "system.dos_attr.write_time\0" - "system.dos_attr.change_time\0" - ; - const char * supported; - - if (context->internal->_full_time_names) { - supported = supported_new; - retsize = sizeof(supported_new); - } else { - supported = supported_old; - retsize = sizeof(supported_old); - } - - if (size == 0) { - return retsize; - } - - if (retsize > size) { - errno = ERANGE; - return -1; - } - - /* this can't be strcpy() because there are embedded null characters */ - memcpy(list, supported, retsize); - return retsize; -} - - -/* - * Open a print file to be written to by other calls - */ - -static SMBCFILE * -smbc_open_print_job_ctx(SMBCCTX *context, - const char *fname) -{ - char *server = NULL; - char *share = NULL; - char *user = NULL; - char *password = NULL; - char *path = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !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)) { - errno = EINVAL; - TALLOC_FREE(frame); - return NULL; - } - - /* What if the path is empty, or the file exists? */ - - TALLOC_FREE(frame); - return (context->open)(context, fname, O_WRONLY, 666); -} - -/* - * Routine to print a file on a remote server ... - * - * We open the file, which we assume to be on a remote server, and then - * copy it to a print file on the share specified by printq. - */ - -static int -smbc_print_file_ctx(SMBCCTX *c_file, - const char *fname, - SMBCCTX *c_print, - const char *printq) -{ - SMBCFILE *fid1; - SMBCFILE *fid2; - int bytes; - int saverr; - 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 = (c_file->open)(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 = (c_print->open_print_job)(c_print, printq)) < 0) { - - saverr = errno; /* Save errno */ - (c_file->close_fn)(c_file, fid1); - errno = saverr; - TALLOC_FREE(frame); - return -1; - - } - - while ((bytes = (c_file->read)(c_file, fid1, buf, sizeof(buf))) > 0) { - - tot_bytes += bytes; - - if (((c_print->write)(c_print, fid2, buf, bytes)) < 0) { - - saverr = errno; - (c_file->close_fn)(c_file, fid1); - (c_print->close_fn)(c_print, fid2); - errno = saverr; - - } - - } - - saverr = errno; - - (c_file->close_fn)(c_file, fid1); /* We have to close these anyway */ - (c_print->close_fn)(c_print, fid2); - - if (bytes < 0) { - - errno = saverr; - TALLOC_FREE(frame); - return -1; - - } - - TALLOC_FREE(frame); - return tot_bytes; - -} - -/* - * Routine to list print jobs on a printer share ... - */ - -static int -smbc_list_print_jobs_ctx(SMBCCTX *context, - const char *fname, - smbc_list_print_job_fn fn) -{ - SMBCSRV *srv = NULL; - char *server = NULL; - char *share = NULL; - char *user = NULL; - char *password = NULL; - char *workgroup = NULL; - char *path = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !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)) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); - if (!user) { - errno = ENOMEM; - TALLOC_FREE(frame); - 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; - -} - -/* - * Delete a print job from a remote printer share - */ - -static int -smbc_unlink_print_job_ctx(SMBCCTX *context, - const char *fname, - int id) -{ - SMBCSRV *srv = NULL; - char *server = NULL; - char *share = NULL; - char *user = NULL; - char *password = NULL; - char *workgroup = NULL; - char *path = NULL; - int err; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!context || !context->internal || - !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)) { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } - - if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); - if (!user) { - errno = ENOMEM; - TALLOC_FREE(frame); - 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; - -} - -/* - * Get a new empty handle to fill in with your own info - */ -SMBCCTX * -smbc_new_context(void) -{ - SMBCCTX *context; - - context = SMB_MALLOC_P(SMBCCTX); - if (!context) { - errno = ENOMEM; - return NULL; - } - - ZERO_STRUCTP(context); - - context->internal = SMB_MALLOC_P(struct smbc_internal_data); - if (!context->internal) { - SAFE_FREE(context); - errno = ENOMEM; - return NULL; - } - - ZERO_STRUCTP(context->internal); - - /* ADD REASONABLE DEFAULTS */ - context->debug = 0; - context->timeout = 20000; /* 20 seconds */ - - context->options.browse_max_lmb_count = 3; /* # LMBs to query */ - context->options.urlencode_readdir_entries = False;/* backward compat */ - context->options.one_share_per_server = False;/* backward compat */ - context->internal->_share_mode = SMBC_SHAREMODE_DENY_NONE; - /* backward compat */ - - context->open = smbc_open_ctx; - context->creat = smbc_creat_ctx; - context->read = smbc_read_ctx; - context->write = smbc_write_ctx; - context->close_fn = smbc_close_ctx; - context->unlink = smbc_unlink_ctx; - context->rename = smbc_rename_ctx; - context->lseek = smbc_lseek_ctx; - context->stat = smbc_stat_ctx; - context->fstat = smbc_fstat_ctx; - context->opendir = smbc_opendir_ctx; - context->closedir = smbc_closedir_ctx; - context->readdir = smbc_readdir_ctx; - context->getdents = smbc_getdents_ctx; - context->mkdir = smbc_mkdir_ctx; - context->rmdir = smbc_rmdir_ctx; - context->telldir = smbc_telldir_ctx; - context->lseekdir = smbc_lseekdir_ctx; - context->fstatdir = smbc_fstatdir_ctx; - context->ftruncate = smbc_ftruncate_ctx; - context->chmod = smbc_chmod_ctx; - context->utimes = smbc_utimes_ctx; - context->setxattr = smbc_setxattr_ctx; - context->getxattr = smbc_getxattr_ctx; - context->removexattr = smbc_removexattr_ctx; - context->listxattr = smbc_listxattr_ctx; - context->open_print_job = smbc_open_print_job_ctx; - context->print_file = smbc_print_file_ctx; - context->list_print_jobs = smbc_list_print_jobs_ctx; - context->unlink_print_job = smbc_unlink_print_job_ctx; - - context->callbacks.check_server_fn = smbc_check_server; - context->callbacks.remove_unused_server_fn = smbc_remove_unused_server; - - smbc_default_cache_functions(context); - - return context; -} - -/* - * Free a context - * - * Returns 0 on success. Otherwise returns 1, the SMBCCTX is _not_ freed - * and thus you'll be leaking memory if not handled properly. - * - */ -int -smbc_free_context(SMBCCTX *context, - int shutdown_ctx) -{ - if (!context) { - errno = EBADF; - return 1; - } - - if (shutdown_ctx) { - SMBCFILE * f; - DEBUG(1,("Performing aggressive shutdown.\n")); - - f = context->internal->_files; - while (f) { - (context->close_fn)(context, f); - f = f->next; - } - context->internal->_files = NULL; - - /* First try to remove the servers the nice way. */ - if (context->callbacks.purge_cached_fn(context)) { - SMBCSRV * s; - SMBCSRV * next; - DEBUG(1, ("Could not purge all servers, " - "Nice way shutdown failed.\n")); - s = context->internal->_servers; - while (s) { - DEBUG(1, ("Forced shutdown: %p (fd=%d)\n", - s, s->cli->fd)); - cli_shutdown(s->cli); - (context->callbacks.remove_cached_srv_fn)(context, - s); - next = s->next; - DLIST_REMOVE(context->internal->_servers, s); - SAFE_FREE(s); - s = next; - } - context->internal->_servers = NULL; - } - } - else { - /* This is the polite way */ - if ((context->callbacks.purge_cached_fn)(context)) { - DEBUG(1, ("Could not purge all servers, " - "free_context failed.\n")); - errno = EBUSY; - return 1; - } - if (context->internal->_servers) { - DEBUG(1, ("Active servers in context, " - "free_context failed.\n")); - errno = EBUSY; - return 1; - } - if (context->internal->_files) { - DEBUG(1, ("Active files in context, " - "free_context failed.\n")); - errno = EBUSY; - return 1; - } - } - - /* Things we have to clean up */ - SAFE_FREE(context->workgroup); - SAFE_FREE(context->netbios_name); - SAFE_FREE(context->user); - - DEBUG(3, ("Context %p successfully freed\n", context)); - SAFE_FREE(context->internal); - SAFE_FREE(context); - return 0; -} - - -/* - * Each time the context structure is changed, we have binary backward - * compatibility issues. Instead of modifying the public portions of the - * context structure to add new options, instead, we put them in the internal - * portion of the context structure and provide a set function for these new - * options. - */ -void -smbc_option_set(SMBCCTX *context, - char *option_name, - ... /* option_value */) -{ - va_list ap; - union { - int i; - bool b; - smbc_get_auth_data_with_context_fn auth_fn; - void *v; - const char *s; - } option_value; - - va_start(ap, option_name); - - if (strcmp(option_name, "debug_to_stderr") == 0) { - /* - * Log to standard error instead of standard output. - */ - option_value.b = (bool) va_arg(ap, int); - context->internal->_debug_stderr = option_value.b; - - } else if (strcmp(option_name, "full_time_names") == 0) { - /* - * 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.) - */ - option_value.b = (bool) va_arg(ap, int); - context->internal->_full_time_names = option_value.b; - - } else if (strcmp(option_name, "open_share_mode") == 0) { - /* - * The share mode to use for files opened with - * smbc_open_ctx(). The default is SMBC_SHAREMODE_DENY_NONE. - */ - option_value.i = va_arg(ap, int); - context->internal->_share_mode = - (smbc_share_mode) option_value.i; - - } else if (strcmp(option_name, "auth_function") == 0) { - /* - * Use the new-style authentication function which includes - * the context. - */ - option_value.auth_fn = - va_arg(ap, smbc_get_auth_data_with_context_fn); - context->internal->_auth_fn_with_context = - option_value.auth_fn; - } else if (strcmp(option_name, "user_data") == 0) { - /* - * Save a user data handle which may be retrieved by the user - * with smbc_option_get() - */ - option_value.v = va_arg(ap, void *); - context->internal->_user_data = option_value.v; - } else if (strcmp(option_name, "smb_encrypt_level") == 0) { - /* - * Save an encoded value for encryption level. - * 0 = off, 1 = attempt, 2 = required. - */ - option_value.s = va_arg(ap, const char *); - if (strcmp(option_value.s, "none") == 0) { - context->internal->_smb_encryption_level = 0; - } else if (strcmp(option_value.s, "request") == 0) { - context->internal->_smb_encryption_level = 1; - } else if (strcmp(option_value.s, "require") == 0) { - context->internal->_smb_encryption_level = 2; - } - } - - va_end(ap); -} - - -/* - * Retrieve the current value of an option - */ -void * -smbc_option_get(SMBCCTX *context, - char *option_name) -{ - if (strcmp(option_name, "debug_stderr") == 0) { - /* - * Log to standard error instead of standard output. - */ -#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->internal->_debug_stderr; -#else - return (void *) context->internal->_debug_stderr; -#endif - } else if (strcmp(option_name, "full_time_names") == 0) { - /* - * 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.) - */ -#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->internal->_full_time_names; -#else - return (void *) context->internal->_full_time_names; -#endif - - } else if (strcmp(option_name, "auth_function") == 0) { - /* - * Use the new-style authentication function which includes - * the context. - */ - return (void *) context->internal->_auth_fn_with_context; - } else if (strcmp(option_name, "user_data") == 0) { - /* - * Save a user data handle which may be retrieved by the user - * with smbc_option_get() - */ - return context->internal->_user_data; - } else if (strcmp(option_name, "smb_encrypt_level") == 0) { - /* - * Return the current smb encrypt negotiate option as a string. - */ - switch (context->internal->_smb_encryption_level) { - case 0: - return (void *) "none"; - case 1: - return (void *) "request"; - case 2: - return (void *) "require"; - } - } else if (strcmp(option_name, "smb_encrypt_on") == 0) { - /* - * Return the current smb encrypt status option as a bool. - * false = off, true = on. We don't know what server is - * being requested, so we only return true if all servers - * are using an encrypted connection. - */ - SMBCSRV *s; - unsigned int num_servers = 0; - - for (s = context->internal->_servers; s; s = s->next) { - num_servers++; - if (s->cli->trans_enc_state == NULL) { - return (void *)false; - } - } - return (void *) (bool) (num_servers > 0); - } - - return NULL; -} - - -/* - * Initialise the library etc - * - * We accept a struct containing handle information. - * valid values for info->debug from 0 to 100, - * and insist that info->fn must be non-null. - */ -SMBCCTX * -smbc_init_context(SMBCCTX *context) -{ - int pid; - char *user = NULL; - char *home = NULL; - - if (!context || !context->internal) { - errno = EBADF; - return NULL; - } - - /* Do not initialise the same client twice */ - if (context->internal->_initialized) { - return 0; - } - - if ((!context->callbacks.auth_fn && - !context->internal->_auth_fn_with_context) || - context->debug < 0 || - context->debug > 100) { - - errno = EINVAL; - return NULL; - - } - - if (!smbc_initialized) { - /* - * Do some library-wide intializations the first time we get - * called - */ - bool conf_loaded = False; - TALLOC_CTX *frame = talloc_stackframe(); - - /* Set this to what the user wants */ - DEBUGLEVEL = context->debug; - - load_case_tables(); - - setup_logging("libsmbclient", True); - if (context->internal->_debug_stderr) { - dbf = x_stderr; - x_setbuf(x_stderr, NULL); - } - - /* Here we would open the smb.conf file if needed ... */ - - in_client = True; /* FIXME, make a param */ - - home = getenv("HOME"); - if (home) { - char *conf = NULL; - if (asprintf(&conf, "%s/.smb/smb.conf", home) > 0) { - if (lp_load(conf, True, False, False, True)) { - conf_loaded = True; - } else { - DEBUG(5, ("Could not load config file: %s\n", - conf)); - } - SAFE_FREE(conf); - } - } - - if (!conf_loaded) { - /* - * Well, if that failed, try the get_dyn_CONFIGFILE - * Which points to the standard locn, and if that - * fails, silently ignore it and use the internal - * defaults ... - */ - - if (!lp_load(get_dyn_CONFIGFILE(), True, False, False, False)) { - DEBUG(5, ("Could not load config file: %s\n", - get_dyn_CONFIGFILE())); - } else if (home) { - char *conf; - /* - * We loaded the global config file. Now lets - * load user-specific modifications to the - * global config. - */ - if (asprintf(&conf, - "%s/.smb/smb.conf.append", - home) > 0) { - if (!lp_load(conf, True, False, False, False)) { - DEBUG(10, - ("Could not append config file: " - "%s\n", - conf)); - } - SAFE_FREE(conf); - } - } - } - - load_interfaces(); /* Load the list of interfaces ... */ - - reopen_logs(); /* Get logging working ... */ - - /* - * Block SIGPIPE (from lib/util_sock.c: write()) - * It is not needed and should not stop execution - */ - BlockSignals(True, SIGPIPE); - - /* Done with one-time initialisation */ - smbc_initialized = 1; - - TALLOC_FREE(frame); - } - - if (!context->user) { - /* - * FIXME: Is this the best way to get the user info? - */ - user = getenv("USER"); - /* walk around as "guest" if no username can be found */ - if (!user) context->user = SMB_STRDUP("guest"); - else context->user = SMB_STRDUP(user); - } - - if (!context->netbios_name) { - /* - * We try to get our netbios name from the config. If that - * fails we fall back on constructing our netbios name from - * our hostname etc - */ - if (global_myname()) { - context->netbios_name = SMB_STRDUP(global_myname()); - } - else { - /* - * Hmmm, I want to get hostname as well, but I am too - * lazy for the moment - */ - pid = sys_getpid(); - context->netbios_name = (char *)SMB_MALLOC(17); - if (!context->netbios_name) { - errno = ENOMEM; - return NULL; - } - slprintf(context->netbios_name, 16, - "smbc%s%d", context->user, pid); - } - } - - DEBUG(1, ("Using netbios name %s.\n", context->netbios_name)); - - if (!context->workgroup) { - if (lp_workgroup()) { - context->workgroup = SMB_STRDUP(lp_workgroup()); - } - else { - /* TODO: Think about a decent default workgroup */ - context->workgroup = SMB_STRDUP("samba"); - } - } - - DEBUG(1, ("Using workgroup %s.\n", context->workgroup)); - - /* shortest timeout is 1 second */ - if (context->timeout > 0 && context->timeout < 1000) - context->timeout = 1000; - - /* - * FIXME: Should we check the function pointers here? - */ - - context->internal->_initialized = True; - - return context; -} - - -/* Return the verion of samba, and thus libsmbclient */ -const char * -smbc_version(void) -{ - return samba_version_string(); -} -- cgit From 48894994d0f86ca095a1bd617d048e7089a20e7b Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Fri, 29 Feb 2008 13:34:35 -0500 Subject: Modified revamp of the libsmbclient interface. Given the tacit (if that) approval by some people, and clear disapproval by others for my proposed clean-up and reorganization of libsmbclient, I've come up with a slightly different approach. This commit changes back to the original libsmbclient.h SMBCCTX structure which will maintain ABI compatibility. I retain, here, the setter and getter functions which all new code should use. Older programs already compiled should continue to work fine. Older programs being recompiled will encounter compile-time errors (intentionally!) so that the code can be corrected to use the setter/getter interfaces. Although this doesn't clean up the interface in the way I had wanted, the code reorganization and requirement for new programs to use the setters and getters allows future progress to be made on libsmbclient without further muddying up the interface, while retaining the ABI compatibility that was the big issue causing disapproval. I hope that this compromise is adequate. Derrell (cherry picked from commit 56429a3d60b2a48963342f6340b3c01469a892c6) (This used to be commit 7bc53f57dcb1c3bb80cb20796ebfc743c22a76e3) --- source3/include/libsmb_internal.h | 16 +- source3/include/libsmbclient.h | 282 ++++++++++++++++++++++++++++++++++- source3/libsmb/libsmb_cache.c | 2 +- source3/libsmb/libsmb_context.c | 305 ++++++++++++++++++++++---------------- source3/libsmb/libsmb_dir.c | 70 ++++----- source3/libsmb/libsmb_file.c | 36 ++--- source3/libsmb/libsmb_path.c | 7 +- source3/libsmb/libsmb_printjob.c | 14 +- source3/libsmb/libsmb_server.c | 33 +++-- source3/libsmb/libsmb_stat.c | 10 +- source3/libsmb/libsmb_xattr.c | 22 +-- 11 files changed, 566 insertions(+), 231 deletions(-) diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index 353575dce8..555b6ac138 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -108,11 +108,12 @@ struct _SMBCFILE { /* * Context structure */ -struct _SMBCCTX { +struct SMBC_internal_data { /* True when this handle is initialized */ bool initialized; +#if 0 /* Left in libsmbclient.h for backward compatibility */ /* Netbios name used for making connections */ char * netbios_name; @@ -127,6 +128,7 @@ struct _SMBCCTX { /* Connection timeout value */ int timeout; +#endif /* dirent pointer location * @@ -240,6 +242,7 @@ struct _SMBCCTX { */ 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; @@ -264,10 +267,12 @@ struct _SMBCCTX { smbc_remove_cached_srv_fn remove_cached_server_fn; smbc_purge_cached_srv_fn purge_cached_server_fn; } cache; +#endif /* POSIX emulation functions */ struct { +#if 0 /* Left in libsmbclient.h for backward compatibility */ smbc_open_fn open_fn; smbc_creat_fn creat_fn; smbc_read_fn read_fn; @@ -275,9 +280,11 @@ struct _SMBCCTX { smbc_unlink_fn unlink_fn; smbc_rename_fn rename_fn; smbc_lseek_fn lseek_fn; - smbc_ftruncate_fn ftruncate_fn; smbc_stat_fn stat_fn; smbc_fstat_fn fstat_fn; +#endif + smbc_ftruncate_fn ftruncate_fn; +#if 0 /* Left in libsmbclient.h for backward compatibility */ smbc_close_fn close_fn; smbc_opendir_fn opendir_fn; smbc_closedir_fn closedir_fn; @@ -294,8 +301,10 @@ struct _SMBCCTX { smbc_getxattr_fn getxattr_fn; smbc_removexattr_fn removexattr_fn; smbc_listxattr_fn listxattr_fn; +#endif } posix_emu; +#if 0 /* Left in libsmbclient.h for backward compatibility */ /* Printing-related functions */ struct { @@ -304,8 +313,9 @@ struct _SMBCCTX { smbc_list_print_jobs_fn list_print_jobs_fn; smbc_unlink_print_job_fn unlink_print_job_fn; } printing; +#endif -#if 0 /* not yet */ +#if 0 /* None available yet */ /* SMB high-level functions */ struct { diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index a998bcee69..4d78bb2568 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -5,7 +5,7 @@ Copyright (C) Richard Sharpe 2000 Copyright (C) John Terpsra 2000 Copyright (C) Tom Jansen (Ninja ISD) 2002 - Copyright (C) Derrell Lipman 2003 + Copyright (C) Derrell Lipman 2003-2008 This program is free software; you can redistribute it and/or modify @@ -213,6 +213,15 @@ typedef struct _SMBCFILE SMBCFILE; typedef struct _SMBCCTX SMBCCTX; +/* + * NEW CODE SHOULD NOT DIRECTLY MANIPULATE THE CONTEXT STRUCTURE. + * For these options, use smbc_option_set() and smbc_option_get(). + */ + +/* 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) @@ -2311,4 +2320,275 @@ smbc_version(void); #endif +/** + * @ingroup structure + * Structure that contains a client context information + * This structure is known as SMBCCTX + * + * DO NOT DIRECTLY MANIPULATE THE CONTEXT STRUCTURE! The data in the context + * structure should all be considered private to the library. It remains here + * only for backward compatibility. + * + * See the comments herein for use of the setter and getter functions which + * should now be used for manipulating these values. New features, functions, + * etc., are not added here but rather in _internal where they are not + * directly visible to applications. This makes it much easier to maintain + * ABI compatibility. + */ +struct _SMBCCTX { + struct + { + /** + * debug level + * + * Use smbc_getDebug() and smbc_setDebug() + */ + int debug; + + /** + * netbios name used for making connections + * + * Use smbc_getNetbiosName() and smbc_setNetbiosName() + */ + char * netbios_name; + + /** + * workgroup name used for making connections + * + * Use smbc_getWorkgroup() and smbc_setWorkgroup() + */ + char * workgroup; + + /** + * username used for making connections + * + * Use smbc_getUser() and smbc_setUser() + */ + char * user; + + /** + * timeout used for waiting on connections / response data (in + * milliseconds) + * + * Use smbc_getTimeout() and smbc_setTimeout() + */ + int timeout; + } config; + + /** + * callable functions for files: + * For usage and return values see the SMBC_* functions + * + * Use smbc_getFunction*() and smbc_setFunction*(), e.g. + * smbc_getFunctionOpen(), smbc_setFunctionUnlink(), etc. + */ + struct + { + smbc_open_fn open_fn; + smbc_creat_fn creat_fn; + smbc_read_fn read_fn; + smbc_write_fn write_fn; + smbc_unlink_fn unlink_fn; + smbc_rename_fn rename_fn; + smbc_lseek_fn lseek_fn; + smbc_stat_fn stat_fn; + smbc_fstat_fn fstat_fn; +#if 0 /* internal */ + smbc_ftruncate_fn ftruncate_fn; +#endif + smbc_close_fn close_fn; + smbc_opendir_fn opendir_fn; + smbc_closedir_fn closedir_fn; + smbc_readdir_fn readdir_fn; + smbc_getdents_fn getdents_fn; + smbc_mkdir_fn mkdir_fn; + smbc_rmdir_fn rmdir_fn; + smbc_telldir_fn telldir_fn; + smbc_lseekdir_fn lseekdir_fn; + smbc_fstatdir_fn fstatdir_fn; + smbc_chmod_fn chmod_fn; + smbc_utimes_fn utimes_fn; + smbc_setxattr_fn setxattr_fn; + smbc_getxattr_fn getxattr_fn; + smbc_removexattr_fn removexattr_fn; + smbc_listxattr_fn listxattr_fn; + } posix_emu; + + /* Printing-related functions */ + struct + { + smbc_print_file_fn print_file_fn; + smbc_open_print_job_fn open_print_job_fn; + smbc_list_print_jobs_fn list_print_jobs_fn; + smbc_unlink_print_job_fn unlink_print_job_fn; + } printing; + + /* + ** Callbacks + * These callbacks _always_ have to be initialized because they will + * not be checked at dereference for increased speed. + */ + struct + { + /** + * authentication function callback: called upon auth requests + * + * Use smbc_getFunctionAuthData(), smbc_setFunctionAuthData() + */ + smbc_get_auth_data_fn get_auth_data_fn; + + /** + * check if a server is still good + * + * Use smbc_getFunctionCheckServer(), + * smbc_setFunctionCheckServer() + */ + smbc_check_server_fn check_server_fn; + + /** + * remove a server if unused + * + * Use smbc_getFunctionRemoveUnusedServer(), + * smbc_setFunctionCheckServer() + */ + smbc_remove_unused_server_fn remove_unused_server_fn; + } server; + + struct + { + /** Cache subsystem + * + * For an example cache system see + * samba/source/libsmb/libsmb_cache.c + * + * Cache subsystem * functions follow. + */ + + /** + * server cache addition + * + * Use smbc_getFunctionAddCachedServer(), + * smbc_setFunctionAddCachedServer() + */ + smbc_add_cached_srv_fn add_cached_server_fn; + + /** + * server cache lookup + * + * Use smbc_getFunctionGetCachedServer(), + * smbc_setFunctionGetCachedServer() + */ + smbc_get_cached_srv_fn get_cached_server_fn; + + /** + * server cache removal + * + * Use smbc_getFunctionRemoveCachedServer(), + * smbc_setFunctionRemoveCachedServer() + */ + smbc_remove_cached_srv_fn remove_cached_server_fn; + + /** + * server cache purging, try to remove all cached servers + * (disconnect) + * + * Use smbc_getFunctionPurgeCachedServers(), + * smbc_setFunctionPurgeCachedServers() + */ + smbc_purge_cached_srv_fn purge_cached_servers_fn; + + /** + * Space to store private data of the server cache. + * + * Use smbc_getServerCacheData(), smbc_setServerCacheData() + */ + struct smbc_server_cache * server_cache_data; + } cache; + + /* + * Very old configuration options. + * + * Use smbc_option_set() and smbc_option_get() instead. + */ + struct + { + int bits; + } flags; + + /** user options selections that apply to this session + * + * NEW CODE SHOULD NOT DIRECTLY MANIPULATE THE CONTEXT STRUCTURE. + * + * 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. + */ + 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; + + /** INTERNAL DATA + * do _NOT_ touch this from your program ! + */ + struct SMBC_internal_data * internal; +}; + + #endif /* SMBCLIENT_H_INCLUDED */ diff --git a/source3/libsmb/libsmb_cache.c b/source3/libsmb/libsmb_cache.c index e0571fa9fe..7ff92f1b4e 100644 --- a/source3/libsmb/libsmb_cache.c +++ b/source3/libsmb/libsmb_cache.c @@ -151,7 +151,7 @@ SMBC_get_cached_server(SMBCCTX * context, * a connection to the server (other than the * attribute server connection) is cool. */ - if (context->one_share_per_server) { + if (context->options.one_share_per_server) { /* * The currently connected share name * doesn't match the requested share, so diff --git a/source3/libsmb/libsmb_context.c b/source3/libsmb/libsmb_context.c index 1505d50a43..6b7a19e1e4 100644 --- a/source3/libsmb/libsmb_context.c +++ b/source3/libsmb/libsmb_context.c @@ -41,6 +41,15 @@ SMBCCTX * smbc_new_context(void) { SMBCCTX *context; + + /* + * All newly added context fields should be placed in SMBC_internal_data, + * not directly in SMBCCTX. + */ +# undef OLD +# define OLD(field) context->field +# undef NEW +# define NEW(field) context->internal->field context = SMB_MALLOC_P(SMBCCTX); if (!context) { @@ -48,66 +57,73 @@ smbc_new_context(void) return NULL; } - - /* Initialize the context and establish reasonable defaults */ ZERO_STRUCTP(context); + + context->internal = SMB_MALLOC_P(struct SMBC_internal_data); + if (!context->internal) { + SAFE_FREE(context); + errno = ENOMEM; + return NULL; + } + + /* Initialize the context and establish reasonable defaults */ + ZERO_STRUCTP(context->internal); - context->debug = 0; - context->timeout = 20000; /* 20 seconds */ + OLD(config.debug) = 0; + OLD(config.timeout) = 20000; /* 20 seconds */ - context->full_time_names = False; - context->share_mode = SMBC_SHAREMODE_DENY_NONE; - context->smb_encryption_level = 0; - context->browse_max_lmb_count = 3; /* # LMBs to query */ - context->urlencode_readdir_entries = False; - context->one_share_per_server = False; - context->use_kerberos = False; - context->fallback_after_kerberos = False; - context->no_auto_anonymous_login = False; + NEW(full_time_names) = False; + NEW(share_mode) = SMBC_SHAREMODE_DENY_NONE; + NEW(smb_encryption_level) = 0; + NEW(browse_max_lmb_count) = 3; /* # LMBs to query */ + NEW(urlencode_readdir_entries) = False; + NEW(one_share_per_server) = False; - context->server.get_auth_data_fn = SMBC_get_auth_data; - context->server.check_server_fn = SMBC_check_server; - context->server.remove_unused_server_fn = SMBC_remove_unused_server; + OLD(server.get_auth_data_fn) = SMBC_get_auth_data; + OLD(server.check_server_fn) = SMBC_check_server; + OLD(server.remove_unused_server_fn) = SMBC_remove_unused_server; - context->cache.server_cache_data = NULL; - context->cache.add_cached_server_fn = SMBC_add_cached_server; - context->cache.get_cached_server_fn = SMBC_get_cached_server; - context->cache.remove_cached_server_fn = SMBC_remove_cached_server; - context->cache.purge_cached_server_fn = SMBC_purge_cached_servers; + OLD(cache.server_cache_data) = NULL; + OLD(cache.add_cached_server_fn) = SMBC_add_cached_server; + OLD(cache.get_cached_server_fn) = SMBC_get_cached_server; + OLD(cache.remove_cached_server_fn) = SMBC_remove_cached_server; + OLD(cache.purge_cached_servers_fn) = SMBC_purge_cached_servers; - context->posix_emu.open_fn = SMBC_open_ctx; - context->posix_emu.creat_fn = SMBC_creat_ctx; - context->posix_emu.read_fn = SMBC_read_ctx; - context->posix_emu.write_fn = SMBC_write_ctx; - context->posix_emu.close_fn = SMBC_close_ctx; - context->posix_emu.unlink_fn = SMBC_unlink_ctx; - context->posix_emu.rename_fn = SMBC_rename_ctx; - context->posix_emu.lseek_fn = SMBC_lseek_ctx; - context->posix_emu.ftruncate_fn = SMBC_ftruncate_ctx; - context->posix_emu.stat_fn = SMBC_stat_ctx; - context->posix_emu.fstat_fn = SMBC_fstat_ctx; - context->posix_emu.opendir_fn = SMBC_opendir_ctx; - context->posix_emu.closedir_fn = SMBC_closedir_ctx; - context->posix_emu.readdir_fn = SMBC_readdir_ctx; - context->posix_emu.getdents_fn = SMBC_getdents_ctx; - context->posix_emu.mkdir_fn = SMBC_mkdir_ctx; - context->posix_emu.rmdir_fn = SMBC_rmdir_ctx; - context->posix_emu.telldir_fn = SMBC_telldir_ctx; - context->posix_emu.lseekdir_fn = SMBC_lseekdir_ctx; - context->posix_emu.fstatdir_fn = SMBC_fstatdir_ctx; - context->posix_emu.chmod_fn = SMBC_chmod_ctx; - context->posix_emu.utimes_fn = SMBC_utimes_ctx; - context->posix_emu.setxattr_fn = SMBC_setxattr_ctx; - context->posix_emu.getxattr_fn = SMBC_getxattr_ctx; - context->posix_emu.removexattr_fn = SMBC_removexattr_ctx; - context->posix_emu.listxattr_fn = SMBC_listxattr_ctx; + OLD(posix_emu.open_fn) = SMBC_open_ctx; + OLD(posix_emu.creat_fn) = SMBC_creat_ctx; + OLD(posix_emu.read_fn) = SMBC_read_ctx; + OLD(posix_emu.write_fn) = SMBC_write_ctx; + OLD(posix_emu.close_fn) = SMBC_close_ctx; + OLD(posix_emu.unlink_fn) = SMBC_unlink_ctx; + OLD(posix_emu.rename_fn) = SMBC_rename_ctx; + OLD(posix_emu.lseek_fn) = SMBC_lseek_ctx; + NEW(posix_emu.ftruncate_fn) = SMBC_ftruncate_ctx; + OLD(posix_emu.stat_fn) = SMBC_stat_ctx; + OLD(posix_emu.fstat_fn) = SMBC_fstat_ctx; + OLD(posix_emu.opendir_fn) = SMBC_opendir_ctx; + OLD(posix_emu.closedir_fn) = SMBC_closedir_ctx; + OLD(posix_emu.readdir_fn) = SMBC_readdir_ctx; + OLD(posix_emu.getdents_fn) = SMBC_getdents_ctx; + OLD(posix_emu.mkdir_fn) = SMBC_mkdir_ctx; + OLD(posix_emu.rmdir_fn) = SMBC_rmdir_ctx; + OLD(posix_emu.telldir_fn) = SMBC_telldir_ctx; + OLD(posix_emu.lseekdir_fn) = SMBC_lseekdir_ctx; + OLD(posix_emu.fstatdir_fn) = SMBC_fstatdir_ctx; + OLD(posix_emu.chmod_fn) = SMBC_chmod_ctx; + OLD(posix_emu.utimes_fn) = SMBC_utimes_ctx; + OLD(posix_emu.setxattr_fn) = SMBC_setxattr_ctx; + OLD(posix_emu.getxattr_fn) = SMBC_getxattr_ctx; + OLD(posix_emu.removexattr_fn) = SMBC_removexattr_ctx; + OLD(posix_emu.listxattr_fn) = SMBC_listxattr_ctx; - context->printing.open_print_job_fn = SMBC_open_print_job_ctx; - context->printing.print_file_fn = SMBC_print_file_ctx; - context->printing.list_print_jobs_fn = SMBC_list_print_jobs_ctx; - context->printing.unlink_print_job_fn = SMBC_unlink_print_job_ctx; + OLD(printing.open_print_job_fn) = SMBC_open_print_job_ctx; + OLD(printing.print_file_fn) = SMBC_print_file_ctx; + OLD(printing.list_print_jobs_fn) = SMBC_list_print_jobs_ctx; + OLD(printing.unlink_print_job_fn) = SMBC_unlink_print_job_ctx; return context; +#undef OLD +#undef NEW } /* @@ -130,20 +146,20 @@ smbc_free_context(SMBCCTX *context, SMBCFILE * f; DEBUG(1,("Performing aggressive shutdown.\n")); - f = context->files; + f = context->internal->files; while (f) { (context->posix_emu.close_fn)(context, f); f = f->next; } - context->files = NULL; + context->internal->files = NULL; /* First try to remove the servers the nice way. */ - if (context->cache.purge_cached_server_fn(context)) { + if (context->cache.purge_cached_servers_fn(context)) { SMBCSRV * s; SMBCSRV * next; DEBUG(1, ("Could not purge all servers, " "Nice way shutdown failed.\n")); - s = context->servers; + s = context->internal->servers; while (s) { DEBUG(1, ("Forced shutdown: %p (fd=%d)\n", s, s->cli->fd)); @@ -151,28 +167,28 @@ smbc_free_context(SMBCCTX *context, (context->cache.remove_cached_server_fn)(context, s); next = s->next; - DLIST_REMOVE(context->servers, s); + DLIST_REMOVE(context->internal->servers, s); SAFE_FREE(s); s = next; } - context->servers = NULL; + context->internal->servers = NULL; } } else { /* This is the polite way */ - if ((context->cache.purge_cached_server_fn)(context)) { + if ((context->cache.purge_cached_servers_fn)(context)) { DEBUG(1, ("Could not purge all servers, " "free_context failed.\n")); errno = EBUSY; return 1; } - if (context->servers) { + if (context->internal->servers) { DEBUG(1, ("Active servers in context, " "free_context failed.\n")); errno = EBUSY; return 1; } - if (context->files) { + if (context->internal->files) { DEBUG(1, ("Active files in context, " "free_context failed.\n")); errno = EBUSY; @@ -181,9 +197,9 @@ smbc_free_context(SMBCCTX *context, } /* Things we have to clean up */ - SAFE_FREE(context->workgroup); - SAFE_FREE(context->netbios_name); - SAFE_FREE(context->user); + SAFE_FREE(context->config.workgroup); + SAFE_FREE(context->config.netbios_name); + SAFE_FREE(context->config.user); DEBUG(3, ("Context %p successfully freed\n", context)); SAFE_FREE(context); @@ -219,7 +235,7 @@ smbc_option_set(SMBCCTX *context, * Log to standard error instead of standard output. */ option_value.b = (bool) va_arg(ap, int); - context->debug_stderr = option_value.b; + context->internal->debug_stderr = option_value.b; } else if (strcmp(option_name, "full_time_names") == 0) { /* @@ -231,7 +247,7 @@ smbc_option_set(SMBCCTX *context, * CREATE_TIME.) */ option_value.b = (bool) va_arg(ap, int); - context->full_time_names = option_value.b; + context->internal->full_time_names = option_value.b; } else if (strcmp(option_name, "open_share_mode") == 0) { /* @@ -239,7 +255,7 @@ smbc_option_set(SMBCCTX *context, * SMBC_open_ctx(). The default is SMBC_SHAREMODE_DENY_NONE. */ option_value.i = va_arg(ap, int); - context->share_mode = (smbc_share_mode) option_value.i; + context->internal->share_mode = (smbc_share_mode) option_value.i; } else if (strcmp(option_name, "user_data") == 0) { /* @@ -247,7 +263,7 @@ smbc_option_set(SMBCCTX *context, * with smbc_option_get() */ option_value.v = va_arg(ap, void *); - context->user_data = option_value.v; + context->internal->user_data = option_value.v; } else if (strcmp(option_name, "smb_encrypt_level") == 0) { /* * Save an encoded value for encryption level. @@ -255,11 +271,11 @@ smbc_option_set(SMBCCTX *context, */ option_value.s = va_arg(ap, const char *); if (strcmp(option_value.s, "none") == 0) { - context->smb_encryption_level = 0; + context->internal->smb_encryption_level = 0; } else if (strcmp(option_value.s, "request") == 0) { - context->smb_encryption_level = 1; + context->internal->smb_encryption_level = 1; } else if (strcmp(option_value.s, "require") == 0) { - context->smb_encryption_level = 2; + context->internal->smb_encryption_level = 2; } } else if (strcmp(option_name, "browse_max_lmb_count") == 0) { /* @@ -280,7 +296,7 @@ smbc_option_set(SMBCCTX *context, * variable is probably somewhere around 3. (Default: 3). */ option_value.i = va_arg(ap, int); - context->browse_max_lmb_count = option_value.i; + context->internal->browse_max_lmb_count = option_value.i; } else if (strcmp(option_name, "urlencode_readdir_entries") == 0) { /* @@ -307,7 +323,7 @@ smbc_option_set(SMBCCTX *context, * For backwards compatibility, this option defaults to False. */ option_value.b = (bool) va_arg(ap, int); - context->urlencode_readdir_entries = option_value.b; + context->internal->urlencode_readdir_entries = option_value.b; } else if (strcmp(option_name, "one_share_per_server") == 0) { /* @@ -321,19 +337,31 @@ smbc_option_set(SMBCCTX *context, * and issuing a new TREE CONNECT when the share is accessed. */ option_value.b = (bool) va_arg(ap, int); - context->one_share_per_server = option_value.b; + context->options.one_share_per_server = option_value.b; } else if (strcmp(option_name, "use_kerberos") == 0) { option_value.b = (bool) va_arg(ap, int); - context->use_kerberos = option_value.b; + if (option_value.b) { + context->flags.bits |= SMB_CTX_FLAG_USE_KERBEROS; + } else { + context->flags.bits &= ~SMB_CTX_FLAG_USE_KERBEROS; + } } else if (strcmp(option_name, "fallback_after_kerberos") == 0) { option_value.b = (bool) va_arg(ap, int); - context->fallback_after_kerberos = option_value.b; + if (option_value.b) { + context->flags.bits |= SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS; + } else { + context->flags.bits &= ~SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS; + } } else if (strcmp(option_name, "no_auto_anonymous_login") == 0) { option_value.b = (bool) va_arg(ap, int); - context->no_auto_anonymous_login = option_value.b; + if (option_value.b) { + context->flags.bits |= SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON; + } else { + context->flags.bits &= ~SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON; + } } va_end(ap); @@ -347,14 +375,16 @@ void * smbc_option_get(SMBCCTX *context, char *option_name) { + int bits; + if (strcmp(option_name, "debug_stderr") == 0) { /* * Log to standard error instead of standard output. */ #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->debug_stderr; + return (void *) (intptr_t) context->internal->debug_stderr; #else - return (void *) context->debug_stderr; + return (void *) context->internal->debug_stderr; #endif } else if (strcmp(option_name, "full_time_names") == 0) { @@ -367,9 +397,9 @@ smbc_option_get(SMBCCTX *context, * CREATE_TIME.) */ #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->full_time_names; + return (void *) (intptr_t) context->internal->full_time_names; #else - return (void *) context->full_time_names; + return (void *) context->internal->full_time_names; #endif } else if (strcmp(option_name, "user_data") == 0) { @@ -377,13 +407,13 @@ smbc_option_get(SMBCCTX *context, * Return the user data handle which was saved by the user * with smbc_option_set() */ - return context->user_data; + return context->internal->user_data; } else if (strcmp(option_name, "smb_encrypt_level") == 0) { /* * Return the current smb encrypt negotiate option as a string. */ - switch (context->smb_encryption_level) { + switch (context->internal->smb_encryption_level) { case 0: return (void *) "none"; case 1: @@ -402,7 +432,7 @@ smbc_option_get(SMBCCTX *context, SMBCSRV *s; unsigned int num_servers = 0; - for (s = context->servers; s; s = s->next) { + for (s = context->internal->servers; s; s = s->next) { num_servers++; if (s->cli->trans_enc_state == NULL) { return (void *)false; @@ -433,9 +463,9 @@ smbc_option_get(SMBCCTX *context, * variable is probably somewhere around 3. (Default: 3). */ #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->browse_max_lmb_count; + return (void *) (intptr_t) context->internal->browse_max_lmb_count; #else - return (void *) context->browse_max_lmb_count; + return (void *) context->internal->browse_max_lmb_count; #endif } else if (strcmp(option_name, "urlencode_readdir_entries") == 0) { @@ -463,9 +493,9 @@ smbc_option_get(SMBCCTX *context, * For backwards compatibility, this option defaults to False. */ #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->urlencode_readdir_entries; + return (void *)(intptr_t) context->internal->urlencode_readdir_entries; #else - return (void *) (bool) context->urlencode_readdir_entries; + return (void *) (bool) context->internal->urlencode_readdir_entries; #endif } else if (strcmp(option_name, "one_share_per_server") == 0) { @@ -480,30 +510,43 @@ smbc_option_get(SMBCCTX *context, * and issuing a new TREE CONNECT when the share is accessed. */ #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->one_share_per_server; + return (void *) (intptr_t) context->internal->one_share_per_server; #else - return (void *) (bool) context->one_share_per_server; + return (void *) (bool) context->internal->one_share_per_server; #endif } else if (strcmp(option_name, "use_kerberos") == 0) { + bits = context->flags.bits; #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->use_kerberos; + return (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS + ? (void *) (intptr_t) 1 + : (void *) (intptr_t) 0); #else - return (void *) (bool) context->use_kerberos; + return (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS + ? (void *) (bool) 1 + : (void *) (bool) 0); #endif } else if (strcmp(option_name, "fallback_after_kerberos") == 0) { #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->fallback_after_kerberos; + return (context->flags.bits & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS + ? (void *) (intptr_t) 1 + : (void *) (intptr_t) 0); #else - return (void *) (bool) context->fallback_after_kerberos; + return (context->flags.bits & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS + ? (void *) (bool) 1 + : (void *) (bool) 0); #endif } else if (strcmp(option_name, "no_auto_anonymous_login") == 0) { #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->no_auto_anonymous_login; + return (context->flags.bits & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON + ? (void *) (intptr_t) 1 + : (void *) (intptr_t) 0); #else - return (void *) (bool) context->no_auto_anonymous_login; + return (context->flags.bits & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON + ? (void *) (bool) 1 + : (void *) (bool) 0); #endif } @@ -532,13 +575,13 @@ smbc_init_context(SMBCCTX *context) } /* Do not initialise the same client twice */ - if (context->initialized) { + if (context->internal->initialized) { return 0; } if (!context->server.get_auth_data_fn || - context->debug < 0 || - context->debug > 100) { + context->config.debug < 0 || + context->config.debug > 100) { errno = EINVAL; return NULL; @@ -554,12 +597,12 @@ smbc_init_context(SMBCCTX *context) TALLOC_CTX *frame = talloc_stackframe(); /* Set this to what the user wants */ - DEBUGLEVEL = context->debug; + DEBUGLEVEL = context->config.debug; load_case_tables(); setup_logging("libsmbclient", True); - if (context->debug_stderr) { + if (context->internal->debug_stderr) { dbf = x_stderr; x_setbuf(x_stderr, NULL); } @@ -630,24 +673,24 @@ smbc_init_context(SMBCCTX *context) TALLOC_FREE(frame); } - if (!context->user) { + if (!context->config.user) { /* * FIXME: Is this the best way to get the user info? */ user = getenv("USER"); /* walk around as "guest" if no username can be found */ - if (!user) context->user = SMB_STRDUP("guest"); - else context->user = SMB_STRDUP(user); + if (!user) context->config.user = SMB_STRDUP("guest"); + else context->config.user = SMB_STRDUP(user); } - if (!context->netbios_name) { + if (!context->config.netbios_name) { /* * We try to get our netbios name from the config. If that * fails we fall back on constructing our netbios name from * our hostname etc */ if (global_myname()) { - context->netbios_name = SMB_STRDUP(global_myname()); + context->config.netbios_name = SMB_STRDUP(global_myname()); } else { /* @@ -655,39 +698,39 @@ smbc_init_context(SMBCCTX *context) * lazy for the moment */ pid = sys_getpid(); - context->netbios_name = (char *)SMB_MALLOC(17); - if (!context->netbios_name) { + context->config.netbios_name = (char *)SMB_MALLOC(17); + if (!context->config.netbios_name) { errno = ENOMEM; return NULL; } - slprintf(context->netbios_name, 16, - "smbc%s%d", context->user, pid); + slprintf(context->config.netbios_name, 16, + "smbc%s%d", context->config.user, pid); } } - DEBUG(1, ("Using netbios name %s.\n", context->netbios_name)); + DEBUG(1, ("Using netbios name %s.\n", context->config.netbios_name)); - if (!context->workgroup) { + if (!context->config.workgroup) { if (lp_workgroup()) { - context->workgroup = SMB_STRDUP(lp_workgroup()); + context->config.workgroup = SMB_STRDUP(lp_workgroup()); } else { /* TODO: Think about a decent default workgroup */ - context->workgroup = SMB_STRDUP("samba"); + context->config.workgroup = SMB_STRDUP("samba"); } } - DEBUG(1, ("Using workgroup %s.\n", context->workgroup)); + DEBUG(1, ("Using workgroup %s.\n", context->config.workgroup)); /* shortest timeout is 1 second */ - if (context->timeout > 0 && context->timeout < 1000) - context->timeout = 1000; + if (context->config.timeout > 0 && context->config.timeout < 1000) + context->config.timeout = 1000; /* * FIXME: Should we check the function pointers here? */ - context->initialized = True; + context->internal->initialized = True; return context; } @@ -705,56 +748,56 @@ smbc_version(void) char * smbc_getNetbiosName(SMBCCTX *c) { - return c->netbios_name; + return c->config.netbios_name; } /** Set the netbios name used for making connections */ void smbc_setNetbiosName(SMBCCTX *c, char * netbios_name) { - c->netbios_name = netbios_name; + c->config.netbios_name = netbios_name; } /** Get the workgroup used for making connections */ char * smbc_getWorkgroup(SMBCCTX *c) { - return c->workgroup; + return c->config.workgroup; } /** Set the workgroup used for making connections */ void smbc_setWorkgroup(SMBCCTX *c, char * workgroup) { - c->workgroup = workgroup; + c->config.workgroup = workgroup; } /** Get the username used for making connections */ char * smbc_getUser(SMBCCTX *c) { - return c->user; + return c->config.user; } /** Set the username used for making connections */ void smbc_setUser(SMBCCTX *c, char * user) { - c->user = user; + c->config.user = user; } /** Get the debug level */ int smbc_getDebug(SMBCCTX *c) { - return c->debug; + return c->config.debug; } /** Set the debug level */ void smbc_setDebug(SMBCCTX *c, int debug) { - c->debug = debug; + c->config.debug = debug; } /** @@ -764,7 +807,7 @@ smbc_setDebug(SMBCCTX *c, int debug) int smbc_getTimeout(SMBCCTX *c) { - return c->timeout; + return c->config.timeout; } /** @@ -774,7 +817,7 @@ smbc_getTimeout(SMBCCTX *c) void smbc_setTimeout(SMBCCTX *c, int timeout) { - c->timeout = timeout; + c->config.timeout = timeout; } /** Get the function for obtaining authentication data */ @@ -886,7 +929,7 @@ smbc_setFunctionRemoveCachedServer(SMBCCTX *c, smbc_purge_cached_srv_fn smbc_getFunctionPurgeCachedServers(SMBCCTX *c) { - return c->cache.purge_cached_server_fn; + return c->cache.purge_cached_servers_fn; } /** @@ -896,7 +939,7 @@ smbc_getFunctionPurgeCachedServers(SMBCCTX *c) void smbc_setFunctionPurgeCachedServers(SMBCCTX *c, smbc_purge_cached_srv_fn fn) { - c->cache.purge_cached_server_fn = fn; + c->cache.purge_cached_servers_fn = fn; } /** @@ -1014,13 +1057,13 @@ smbc_setFunctionFstat(SMBCCTX *c, smbc_fstat_fn fn) smbc_ftruncate_fn smbc_getFunctionFtruncate(SMBCCTX *c) { - return c->posix_emu.ftruncate_fn; + return c->internal->posix_emu.ftruncate_fn; } void smbc_setFunctionFtruncate(SMBCCTX *c, smbc_ftruncate_fn fn) { - c->posix_emu.ftruncate_fn = fn; + c->internal->posix_emu.ftruncate_fn = fn; } smbc_close_fn diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 9cb3351433..25020762a2 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -356,7 +356,7 @@ SMBC_opendir_ctx(SMBCCTX *context, struct sockaddr_storage rem_ss; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { DEBUG(4, ("no valid context\n")); errno = EINVAL + 8192; TALLOC_FREE(frame); @@ -400,7 +400,7 @@ SMBC_opendir_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -446,9 +446,9 @@ SMBC_opendir_ctx(SMBCCTX *context, } /* Determine how many local master browsers to query */ - max_lmb_count = (context->browse_max_lmb_count == 0 + max_lmb_count = (context->internal->browse_max_lmb_count == 0 ? INT_MAX - : context->browse_max_lmb_count); + : context->internal->browse_max_lmb_count); memset(&u_info, '\0', sizeof(u_info)); u_info.username = talloc_strdup(frame,user); @@ -826,7 +826,7 @@ SMBC_opendir_ctx(SMBCCTX *context, } - DLIST_ADD(context->files, dir); + DLIST_ADD(context->internal->files, dir); TALLOC_FREE(frame); return dir; @@ -842,13 +842,13 @@ SMBC_closedir_ctx(SMBCCTX *context, { TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - if (!dir || !SMBC_dlist_contains(context->files, dir)) { + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; TALLOC_FREE(frame); return -1; @@ -856,7 +856,7 @@ SMBC_closedir_ctx(SMBCCTX *context, remove_dir(dir); /* Clean it up */ - DLIST_REMOVE(context->files, dir); + DLIST_REMOVE(context->internal->files, dir); if (dir) { @@ -875,7 +875,7 @@ smbc_readdir_internal(SMBCCTX * context, struct smbc_dirent *src, int max_namebuf_len) { - if (context->urlencode_readdir_entries) { + if (context->internal->urlencode_readdir_entries) { /* url-encode the name. get back remaining buffer space */ max_namebuf_len = @@ -919,7 +919,7 @@ SMBC_readdir_ctx(SMBCCTX *context, /* Check that all is ok first ... */ - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; DEBUG(0, ("Invalid context in SMBC_readdir_ctx()\n")); @@ -928,7 +928,7 @@ SMBC_readdir_ctx(SMBCCTX *context, } - if (!dir || !SMBC_dlist_contains(context->files, dir)) { + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; DEBUG(0, ("Invalid dir in SMBC_readdir_ctx()\n")); @@ -960,8 +960,8 @@ SMBC_readdir_ctx(SMBCCTX *context, } - dirp = (struct smbc_dirent *)context->dirent; - maxlen = (sizeof(context->dirent) - + dirp = (struct smbc_dirent *)context->internal->dirent; + maxlen = (sizeof(context->internal->dirent) - sizeof(struct smbc_dirent)); smbc_readdir_internal(context, dirp, dirent, maxlen); @@ -991,7 +991,7 @@ SMBC_getdents_ctx(SMBCCTX *context, /* Check that all is ok first ... */ - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); @@ -999,7 +999,7 @@ SMBC_getdents_ctx(SMBCCTX *context, } - if (!dir || !SMBC_dlist_contains(context->files, dir)) { + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; TALLOC_FREE(frame); @@ -1033,8 +1033,8 @@ SMBC_getdents_ctx(SMBCCTX *context, } /* Do urlencoding of next entry, if so selected */ - dirent = (struct smbc_dirent *)context->dirent; - maxlen = (sizeof(context->dirent) - + dirent = (struct smbc_dirent *)context->internal->dirent; + maxlen = (sizeof(context->internal->dirent) - sizeof(struct smbc_dirent)); smbc_readdir_internal(context, dirent, dirlist->dirent, maxlen); @@ -1102,7 +1102,7 @@ SMBC_mkdir_ctx(SMBCCTX *context, struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; @@ -1132,7 +1132,7 @@ SMBC_mkdir_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1209,7 +1209,7 @@ SMBC_rmdir_ctx(SMBCCTX *context, struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; @@ -1239,7 +1239,7 @@ SMBC_rmdir_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1325,7 +1325,7 @@ SMBC_telldir_ctx(SMBCCTX *context, { TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); @@ -1333,7 +1333,7 @@ SMBC_telldir_ctx(SMBCCTX *context, } - if (!dir || !SMBC_dlist_contains(context->files, dir)) { + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; TALLOC_FREE(frame); @@ -1408,7 +1408,7 @@ SMBC_lseekdir_ctx(SMBCCTX *context, struct smbc_dir_list *list_ent = (struct smbc_dir_list *)NULL; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); @@ -1465,7 +1465,7 @@ SMBC_fstatdir_ctx(SMBCCTX *context, struct stat *st) { - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; return -1; @@ -1490,7 +1490,7 @@ SMBC_chmod_ctx(SMBCCTX *context, uint16 mode; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); @@ -1521,7 +1521,7 @@ SMBC_chmod_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1570,7 +1570,7 @@ SMBC_utimes_ctx(SMBCCTX *context, time_t write_time; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); @@ -1627,7 +1627,7 @@ SMBC_utimes_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1668,7 +1668,7 @@ SMBC_unlink_ctx(SMBCCTX *context, SMBCSRV *srv = NULL; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); @@ -1699,7 +1699,7 @@ SMBC_unlink_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1802,8 +1802,8 @@ SMBC_rename_ctx(SMBCCTX *ocontext, TALLOC_CTX *frame = talloc_stackframe(); if (!ocontext || !ncontext || - !ocontext->initialized || - !ncontext->initialized) { + !ocontext->internal->initialized || + !ncontext->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); @@ -1834,7 +1834,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, } if (!user1 || user1[0] == (char)0) { - user1 = talloc_strdup(frame, ocontext->user); + user1 = talloc_strdup(frame, ocontext->config.user); if (!user1) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1858,7 +1858,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, } if (!user2 || user2[0] == (char)0) { - user2 = talloc_strdup(frame, ncontext->user); + user2 = talloc_strdup(frame, ncontext->config.user); if (!user2) { errno = ENOMEM; TALLOC_FREE(frame); diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c index 619176697b..62b990ed00 100644 --- a/source3/libsmb/libsmb_file.c +++ b/source3/libsmb/libsmb_file.c @@ -46,7 +46,7 @@ SMBC_open_ctx(SMBCCTX *context, int fd; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); @@ -78,7 +78,7 @@ SMBC_open_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -120,7 +120,7 @@ SMBC_open_ctx(SMBCCTX *context, /*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/ if ((fd = cli_open(targetcli, targetpath, flags, - context->share_mode)) < 0) { + context->internal->share_mode)) < 0) { /* Handle the error ... */ @@ -139,7 +139,7 @@ SMBC_open_ctx(SMBCCTX *context, file->offset = 0; file->file = True; - DLIST_ADD(context->files, file); + DLIST_ADD(context->internal->files, file); /* * If the file was opened in O_APPEND mode, all write @@ -208,7 +208,7 @@ SMBC_creat_ctx(SMBCCTX *context, mode_t mode) { - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; return NULL; @@ -246,7 +246,7 @@ SMBC_read_ctx(SMBCCTX *context, */ off_t offset; - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); @@ -256,7 +256,7 @@ SMBC_read_ctx(SMBCCTX *context, DEBUG(4, ("smbc_read(%p, %d)\n", file, (int)count)); - if (!file || !SMBC_dlist_contains(context->files, file)) { + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; @@ -338,7 +338,7 @@ SMBC_write_ctx(SMBCCTX *context, /* First check all pointers before dereferencing them */ - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); @@ -346,7 +346,7 @@ SMBC_write_ctx(SMBCCTX *context, } - if (!file || !SMBC_dlist_contains(context->files, file)) { + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; @@ -418,14 +418,14 @@ SMBC_close_ctx(SMBCCTX *context, struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - if (!file || !SMBC_dlist_contains(context->files, file)) { + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; @@ -470,7 +470,7 @@ SMBC_close_ctx(SMBCCTX *context, * from the server cache if unused */ errno = SMBC_errno(context, targetcli); srv = file->srv; - DLIST_REMOVE(context->files, file); + DLIST_REMOVE(context->internal->files, file); SAFE_FREE(file->fname); SAFE_FREE(file); (context->server.remove_unused_server_fn)(context, srv); @@ -479,7 +479,7 @@ SMBC_close_ctx(SMBCCTX *context, } - DLIST_REMOVE(context->files, file); + DLIST_REMOVE(context->internal->files, file); SAFE_FREE(file->fname); SAFE_FREE(file); TALLOC_FREE(frame); @@ -509,7 +509,7 @@ SMBC_getatr(SMBCCTX * context, time_t write_time; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); @@ -698,14 +698,14 @@ SMBC_lseek_ctx(SMBCCTX *context, struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - if (!file || !SMBC_dlist_contains(context->files, file)) { + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); @@ -803,14 +803,14 @@ SMBC_ftruncate_ctx(SMBCCTX *context, struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - if (!file || !SMBC_dlist_contains(context->files, file)) { + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; diff --git a/source3/libsmb/libsmb_path.c b/source3/libsmb/libsmb_path.c index 2533f536c3..6706a59ba8 100644 --- a/source3/libsmb/libsmb_path.c +++ b/source3/libsmb/libsmb_path.c @@ -252,7 +252,8 @@ SMBC_parse_path(TALLOC_CTX *ctx, * to the workgroup in the provided context. */ if (pp_workgroup != NULL) { - *pp_workgroup = talloc_strdup(ctx, context->workgroup); + *pp_workgroup = + talloc_strdup(ctx, context->config.workgroup); } if (pp_options) { @@ -296,13 +297,13 @@ SMBC_parse_path(TALLOC_CTX *ctx, } if (*p == '/') { - int wl = strlen(context->workgroup); + int wl = strlen(context->config.workgroup); if (wl > 16) { wl = 16; } - *pp_server = talloc_strdup(ctx, context->workgroup); + *pp_server = talloc_strdup(ctx, context->config.workgroup); if (!*pp_server) { return -1; } diff --git a/source3/libsmb/libsmb_printjob.c b/source3/libsmb/libsmb_printjob.c index f106080b6f..a03c15e024 100644 --- a/source3/libsmb/libsmb_printjob.c +++ b/source3/libsmb/libsmb_printjob.c @@ -42,7 +42,7 @@ SMBC_open_print_job_ctx(SMBCCTX *context, char *path = NULL; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); @@ -99,8 +99,8 @@ SMBC_print_file_ctx(SMBCCTX *c_file, char buf[4096]; TALLOC_CTX *frame = talloc_stackframe(); - if (!c_file || !c_file->initialized || - !c_print || !c_print->initialized) { + if (!c_file || !c_file->internal->initialized || + !c_print || !c_print->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); @@ -189,7 +189,7 @@ SMBC_list_print_jobs_ctx(SMBCCTX *context, char *path = NULL; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); @@ -220,7 +220,7 @@ SMBC_list_print_jobs_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -267,7 +267,7 @@ SMBC_unlink_print_job_ctx(SMBCCTX *context, int err; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); @@ -298,7 +298,7 @@ SMBC_unlink_print_job_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 978a843d30..70e0d57273 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -58,12 +58,12 @@ SMBC_remove_unused_server(SMBCCTX * context, SMBCFILE * file; /* are we being fooled ? */ - if (!context || !context->initialized || !srv) { + if (!context || !context->internal->initialized || !srv) { return 1; } /* Check all open files/directories for a relation with this server */ - for (file = context->files; file; file = file->next) { + for (file = context->internal->files; file; file = file->next) { if (file->srv == srv) { /* Still used */ DEBUG(3, ("smbc_remove_usused_server: " @@ -73,7 +73,7 @@ SMBC_remove_unused_server(SMBCCTX * context, } } - DLIST_REMOVE(context->servers, srv); + DLIST_REMOVE(context->internal->servers, srv); cli_shutdown(srv->cli); srv->cli = NULL; @@ -251,7 +251,7 @@ SMBC_server(TALLOC_CTX *ctx, * If we found a connection and we're only allowed one share per * server... */ - if (srv && *share != '\0' && context->one_share_per_server) { + if (srv && *share != '\0' && context->internal->one_share_per_server) { /* * ... then if there's no current connection to the share, @@ -322,7 +322,7 @@ SMBC_server(TALLOC_CTX *ctx, return NULL; } - make_nmb_name(&calling, context->netbios_name, 0x0); + 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)); @@ -339,14 +339,14 @@ SMBC_server(TALLOC_CTX *ctx, return NULL; } - if (context->use_kerberos) { + if (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS) { c->use_kerberos = True; } - if (context->fallback_after_kerberos) { + if (context->flags.bits & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS) { c->fallback_after_kerberos = True; } - c->timeout = context->timeout; + c->timeout = context->config.timeout; /* * Force use of port 139 for first try if share is $IPC, empty, or @@ -428,7 +428,8 @@ SMBC_server(TALLOC_CTX *ctx, /* Failed. Try an anonymous login, if allowed by flags. */ username_used = ""; - if (context->no_auto_anonymous_login || + 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, @@ -451,7 +452,7 @@ SMBC_server(TALLOC_CTX *ctx, DEBUG(4,(" tconx ok\n")); - if (context->smb_encryption_level) { + if (context->internal->smb_encryption_level) { /* Attempt UNIX smb encryption. */ if (!NT_STATUS_IS_OK(cli_force_encryption(c, username_used, @@ -466,7 +467,7 @@ SMBC_server(TALLOC_CTX *ctx, DEBUG(4,(" SMB encrypt failed\n")); - if (context->smb_encryption_level == 2) { + if (context->internal->smb_encryption_level == 2) { cli_shutdown(c); errno = EPERM; return NULL; @@ -512,7 +513,7 @@ SMBC_server(TALLOC_CTX *ctx, DEBUG(2, ("Server connect ok: //%s/%s: %p\n", server, share, srv)); - DLIST_ADD(context->servers, srv); + DLIST_ADD(context->internal->servers, srv); return srv; failed: @@ -566,7 +567,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, } flags = 0; - if (context->use_kerberos) { + if (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS) { flags |= CLI_FULL_CONNECTION_USE_KERBEROS; } @@ -586,7 +587,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, return NULL; } - if (context->smb_encryption_level) { + if (context->internal->smb_encryption_level) { /* Attempt UNIX smb encryption. */ if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli, *pp_username, @@ -602,7 +603,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, DEBUG(4,(" SMB encrypt failed on IPC$\n")); - if (context->smb_encryption_level == 2) { + if (context->internal->smb_encryption_level == 2) { cli_shutdown(ipc_cli); errno = EPERM; return NULL; @@ -668,7 +669,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, return NULL; } - DLIST_ADD(context->servers, ipc_srv); + DLIST_ADD(context->internal->servers, ipc_srv); } return ipc_srv; diff --git a/source3/libsmb/libsmb_stat.c b/source3/libsmb/libsmb_stat.c index 06238863b7..6072547e08 100644 --- a/source3/libsmb/libsmb_stat.c +++ b/source3/libsmb/libsmb_stat.c @@ -35,7 +35,7 @@ static ino_t generate_inode(SMBCCTX *context, const char *name) { - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; return -1; @@ -126,7 +126,7 @@ SMBC_stat_ctx(SMBCCTX *context, SMB_INO_T ino = 0; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); @@ -157,7 +157,7 @@ SMBC_stat_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame,context->user); + user = talloc_strdup(frame,context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -222,14 +222,14 @@ SMBC_fstat_ctx(SMBCCTX *context, SMB_INO_T ino = 0; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - if (!file || !SMBC_dlist_contains(context->files, file)) { + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; diff --git a/source3/libsmb/libsmb_xattr.c b/source3/libsmb/libsmb_xattr.c index 93ca0706b2..a420299341 100644 --- a/source3/libsmb/libsmb_xattr.c +++ b/source3/libsmb/libsmb_xattr.c @@ -609,7 +609,7 @@ dos_attr_parse(SMBCCTX *context, } attr_strings; /* Determine whether to use old-style or new-style attribute names */ - if (context->full_time_names) { + if (context->internal->full_time_names) { /* new-style names */ attr_strings.create_time_attr = "CREATE_TIME"; attr_strings.access_time_attr = "ACCESS_TIME"; @@ -759,7 +759,7 @@ cacl_get(SMBCCTX *context, } excl_attr_strings; /* Determine whether to use old-style or new-style attribute names */ - if (context->full_time_names) { + if (context->internal->full_time_names) { /* new-style names */ attr_strings.create_time_attr = "CREATE_TIME"; attr_strings.access_time_attr = "ACCESS_TIME"; @@ -1689,7 +1689,7 @@ SMBC_setxattr_ctx(SMBCCTX *context, } attr_strings; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); @@ -1721,7 +1721,7 @@ SMBC_setxattr_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1893,7 +1893,7 @@ SMBC_setxattr_ctx(SMBCCTX *context, } /* Determine whether to use old-style or new-style attribute names */ - if (context->full_time_names) { + if (context->internal->full_time_names) { /* new-style names */ attr_strings.create_time_attr = "system.dos_attr.CREATE_TIME"; attr_strings.access_time_attr = "system.dos_attr.ACCESS_TIME"; @@ -1984,7 +1984,7 @@ SMBC_getxattr_ctx(SMBCCTX *context, } attr_strings; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); @@ -2015,7 +2015,7 @@ SMBC_getxattr_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -2041,7 +2041,7 @@ SMBC_getxattr_ctx(SMBCCTX *context, } /* Determine whether to use old-style or new-style attribute names */ - if (context->full_time_names) { + if (context->internal->full_time_names) { /* new-style names */ attr_strings.create_time_attr = "system.dos_attr.CREATE_TIME"; attr_strings.access_time_attr = "system.dos_attr.ACCESS_TIME"; @@ -2118,7 +2118,7 @@ SMBC_removexattr_ctx(SMBCCTX *context, char *path = NULL; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); @@ -2149,7 +2149,7 @@ SMBC_removexattr_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -2270,7 +2270,7 @@ SMBC_listxattr_ctx(SMBCCTX *context, ; const char * supported; - if (context->full_time_names) { + if (context->internal->full_time_names) { supported = supported_new; retsize = sizeof(supported_new); } else { -- cgit From 9a96722833d705d8ed462008adbf07b5ff3566fd Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 1 Mar 2008 20:44:21 -0500 Subject: 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 (cherry picked from commit 64b7150d92849a1e1e2416b9dcc12fae8d6bea99) (This used to be commit dca8a612e94095e38df50f0fe567c75ceb8124fe) --- examples/libsmbclient/testbrowse.c | 17 +- source3/include/libsmb_internal.h | 48 +- source3/include/libsmbclient.h | 401 ++++++++-- source3/libsmb/libsmb_cache.c | 54 +- source3/libsmb/libsmb_compat.c | 52 +- source3/libsmb/libsmb_context.c | 1508 ++++++++++++++++++++---------------- source3/libsmb/libsmb_dir.c | 930 +++++++++++----------- source3/libsmb/libsmb_file.c | 393 +++++----- source3/libsmb/libsmb_misc.c | 10 +- source3/libsmb/libsmb_path.c | 114 +-- source3/libsmb/libsmb_printjob.c | 178 ++--- source3/libsmb/libsmb_server.c | 275 +++---- source3/libsmb/libsmb_stat.c | 132 ++-- source3/libsmb/libsmb_xattr.c | 636 +++++++-------- 14 files changed, 2583 insertions(+), 2165 deletions(-) diff --git a/examples/libsmbclient/testbrowse.c b/examples/libsmbclient/testbrowse.c index 495cf0fbec..1b0b54f9f0 100644 --- a/examples/libsmbclient/testbrowse.c +++ b/examples/libsmbclient/testbrowse.c @@ -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) { diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index 555b6ac138..e687e24268 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -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 , 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 diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index 4d78bb2568..28cad351de 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -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; diff --git a/source3/libsmb/libsmb_cache.c b/source3/libsmb/libsmb_cache.c index 7ff92f1b4e..ff13fd7eac 100644 --- a/source3/libsmb/libsmb_cache.c +++ b/source3/libsmb/libsmb_cache.c @@ -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; diff --git a/source3/libsmb/libsmb_compat.c b/source3/libsmb/libsmb_compat.c index 7a0536a92d..9ef5e51fa9 100644 --- a/source3/libsmb/libsmb_compat.c +++ b/source3/libsmb/libsmb_compat.c @@ -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; diff --git a/source3/libsmb/libsmb_context.c b/source3/libsmb/libsmb_context.c index 6b7a19e1e4..8af49d12be 100644 --- a/source3/libsmb/libsmb_context.c +++ b/source3/libsmb/libsmb_context.c @@ -40,88 +40,88 @@ static int SMBC_initialized = 0; SMBCCTX * smbc_new_context(void) { - SMBCCTX *context; - - /* - * All newly added context fields should be placed in SMBC_internal_data, - * not directly in SMBCCTX. - */ -# undef OLD -# define OLD(field) context->field -# undef NEW -# define NEW(field) context->internal->field - - context = SMB_MALLOC_P(SMBCCTX); - if (!context) { - errno = ENOMEM; - return NULL; - } - - ZERO_STRUCTP(context); - - context->internal = SMB_MALLOC_P(struct SMBC_internal_data); - if (!context->internal) { - SAFE_FREE(context); - errno = ENOMEM; - return NULL; - } - - /* Initialize the context and establish reasonable defaults */ - ZERO_STRUCTP(context->internal); - - OLD(config.debug) = 0; - OLD(config.timeout) = 20000; /* 20 seconds */ - - NEW(full_time_names) = False; - NEW(share_mode) = SMBC_SHAREMODE_DENY_NONE; - NEW(smb_encryption_level) = 0; - NEW(browse_max_lmb_count) = 3; /* # LMBs to query */ - NEW(urlencode_readdir_entries) = False; - NEW(one_share_per_server) = False; - - OLD(server.get_auth_data_fn) = SMBC_get_auth_data; - OLD(server.check_server_fn) = SMBC_check_server; - OLD(server.remove_unused_server_fn) = SMBC_remove_unused_server; - - OLD(cache.server_cache_data) = NULL; - OLD(cache.add_cached_server_fn) = SMBC_add_cached_server; - OLD(cache.get_cached_server_fn) = SMBC_get_cached_server; - OLD(cache.remove_cached_server_fn) = SMBC_remove_cached_server; - OLD(cache.purge_cached_servers_fn) = SMBC_purge_cached_servers; - - OLD(posix_emu.open_fn) = SMBC_open_ctx; - OLD(posix_emu.creat_fn) = SMBC_creat_ctx; - OLD(posix_emu.read_fn) = SMBC_read_ctx; - OLD(posix_emu.write_fn) = SMBC_write_ctx; - OLD(posix_emu.close_fn) = SMBC_close_ctx; - OLD(posix_emu.unlink_fn) = SMBC_unlink_ctx; - OLD(posix_emu.rename_fn) = SMBC_rename_ctx; - OLD(posix_emu.lseek_fn) = SMBC_lseek_ctx; - NEW(posix_emu.ftruncate_fn) = SMBC_ftruncate_ctx; - OLD(posix_emu.stat_fn) = SMBC_stat_ctx; - OLD(posix_emu.fstat_fn) = SMBC_fstat_ctx; - OLD(posix_emu.opendir_fn) = SMBC_opendir_ctx; - OLD(posix_emu.closedir_fn) = SMBC_closedir_ctx; - OLD(posix_emu.readdir_fn) = SMBC_readdir_ctx; - OLD(posix_emu.getdents_fn) = SMBC_getdents_ctx; - OLD(posix_emu.mkdir_fn) = SMBC_mkdir_ctx; - OLD(posix_emu.rmdir_fn) = SMBC_rmdir_ctx; - OLD(posix_emu.telldir_fn) = SMBC_telldir_ctx; - OLD(posix_emu.lseekdir_fn) = SMBC_lseekdir_ctx; - OLD(posix_emu.fstatdir_fn) = SMBC_fstatdir_ctx; - OLD(posix_emu.chmod_fn) = SMBC_chmod_ctx; - OLD(posix_emu.utimes_fn) = SMBC_utimes_ctx; - OLD(posix_emu.setxattr_fn) = SMBC_setxattr_ctx; - OLD(posix_emu.getxattr_fn) = SMBC_getxattr_ctx; - OLD(posix_emu.removexattr_fn) = SMBC_removexattr_ctx; - OLD(posix_emu.listxattr_fn) = SMBC_listxattr_ctx; - - OLD(printing.open_print_job_fn) = SMBC_open_print_job_ctx; - OLD(printing.print_file_fn) = SMBC_print_file_ctx; - OLD(printing.list_print_jobs_fn) = SMBC_list_print_jobs_ctx; - OLD(printing.unlink_print_job_fn) = SMBC_unlink_print_job_ctx; - - return context; + SMBCCTX *context; + + /* + * All newly added context fields should be placed in + * SMBC_internal_data, not directly in SMBCCTX. + */ +#undef OLD +#define OLD(field) context->field +#undef NEW +#define NEW(field) context->internal->field + + context = SMB_MALLOC_P(SMBCCTX); + if (!context) { + errno = ENOMEM; + return NULL; + } + + ZERO_STRUCTP(context); + + context->internal = SMB_MALLOC_P(struct SMBC_internal_data); + if (!context->internal) { + SAFE_FREE(context); + errno = ENOMEM; + return NULL; + } + + /* Initialize the context and establish reasonable defaults */ + ZERO_STRUCTP(context->internal); + + OLD(config.debug) = 0; + OLD(config.timeout) = 20000; /* 20 seconds */ + + NEW(full_time_names) = False; + NEW(share_mode) = SMBC_SHAREMODE_DENY_NONE; + NEW(smb_encryption_level) = 0; + OLD(options.browse_max_lmb_count) = 3; /* # LMBs to query */ + OLD(options.urlencode_readdir_entries) = False; + OLD(options.one_share_per_server) = False; + + OLD(server.get_auth_data_fn) = SMBC_get_auth_data; + OLD(server.check_server_fn) = SMBC_check_server; + OLD(server.remove_unused_server_fn) = SMBC_remove_unused_server; + + OLD(cache.server_cache_data) = NULL; + OLD(cache.add_cached_server_fn) = SMBC_add_cached_server; + OLD(cache.get_cached_server_fn) = SMBC_get_cached_server; + OLD(cache.remove_cached_server_fn) = SMBC_remove_cached_server; + OLD(cache.purge_cached_servers_fn) = SMBC_purge_cached_servers; + + OLD(posix_emu.open_fn) = SMBC_open_ctx; + OLD(posix_emu.creat_fn) = SMBC_creat_ctx; + OLD(posix_emu.read_fn) = SMBC_read_ctx; + OLD(posix_emu.write_fn) = SMBC_write_ctx; + OLD(posix_emu.close_fn) = SMBC_close_ctx; + OLD(posix_emu.unlink_fn) = SMBC_unlink_ctx; + OLD(posix_emu.rename_fn) = SMBC_rename_ctx; + OLD(posix_emu.lseek_fn) = SMBC_lseek_ctx; + NEW(posix_emu.ftruncate_fn) = SMBC_ftruncate_ctx; + OLD(posix_emu.stat_fn) = SMBC_stat_ctx; + OLD(posix_emu.fstat_fn) = SMBC_fstat_ctx; + OLD(posix_emu.opendir_fn) = SMBC_opendir_ctx; + OLD(posix_emu.closedir_fn) = SMBC_closedir_ctx; + OLD(posix_emu.readdir_fn) = SMBC_readdir_ctx; + OLD(posix_emu.getdents_fn) = SMBC_getdents_ctx; + OLD(posix_emu.mkdir_fn) = SMBC_mkdir_ctx; + OLD(posix_emu.rmdir_fn) = SMBC_rmdir_ctx; + OLD(posix_emu.telldir_fn) = SMBC_telldir_ctx; + OLD(posix_emu.lseekdir_fn) = SMBC_lseekdir_ctx; + OLD(posix_emu.fstatdir_fn) = SMBC_fstatdir_ctx; + OLD(posix_emu.chmod_fn) = SMBC_chmod_ctx; + OLD(posix_emu.utimes_fn) = SMBC_utimes_ctx; + OLD(posix_emu.setxattr_fn) = SMBC_setxattr_ctx; + OLD(posix_emu.getxattr_fn) = SMBC_getxattr_ctx; + OLD(posix_emu.removexattr_fn) = SMBC_removexattr_ctx; + OLD(posix_emu.listxattr_fn) = SMBC_listxattr_ctx; + + OLD(printing.open_print_job_fn) = SMBC_open_print_job_ctx; + OLD(printing.print_file_fn) = SMBC_print_file_ctx; + OLD(printing.list_print_jobs_fn) = SMBC_list_print_jobs_ctx; + OLD(printing.unlink_print_job_fn) = SMBC_unlink_print_job_ctx; + + return context; #undef OLD #undef NEW } @@ -137,420 +137,268 @@ int smbc_free_context(SMBCCTX *context, int shutdown_ctx) { - if (!context) { - errno = EBADF; - return 1; - } - - if (shutdown_ctx) { - SMBCFILE * f; - DEBUG(1,("Performing aggressive shutdown.\n")); - - f = context->internal->files; - while (f) { - (context->posix_emu.close_fn)(context, f); - f = f->next; + if (!context) { + errno = EBADF; + return 1; } - context->internal->files = NULL; - /* First try to remove the servers the nice way. */ - if (context->cache.purge_cached_servers_fn(context)) { - SMBCSRV * s; - SMBCSRV * next; - DEBUG(1, ("Could not purge all servers, " - "Nice way shutdown failed.\n")); - s = context->internal->servers; - while (s) { - DEBUG(1, ("Forced shutdown: %p (fd=%d)\n", - s, s->cli->fd)); - cli_shutdown(s->cli); - (context->cache.remove_cached_server_fn)(context, - s); - next = s->next; - DLIST_REMOVE(context->internal->servers, s); - SAFE_FREE(s); - s = next; - } - context->internal->servers = NULL; - } - } - else { - /* This is the polite way */ - if ((context->cache.purge_cached_servers_fn)(context)) { - DEBUG(1, ("Could not purge all servers, " - "free_context failed.\n")); - errno = EBUSY; - return 1; - } - if (context->internal->servers) { - DEBUG(1, ("Active servers in context, " - "free_context failed.\n")); - errno = EBUSY; - return 1; + if (shutdown_ctx) { + SMBCFILE * f; + DEBUG(1,("Performing aggressive shutdown.\n")); + + f = context->internal->files; + while (f) { + (context->posix_emu.close_fn)(context, f); + f = f->next; + } + context->internal->files = NULL; + + /* First try to remove the servers the nice way. */ + if (context->cache.purge_cached_servers_fn(context)) { + SMBCSRV * s; + SMBCSRV * next; + DEBUG(1, ("Could not purge all servers, " + "Nice way shutdown failed.\n")); + s = context->internal->servers; + while (s) { + DEBUG(1, ("Forced shutdown: %p (fd=%d)\n", + s, s->cli->fd)); + cli_shutdown(s->cli); + (context->cache.remove_cached_server_fn)(context, + s); + next = s->next; + DLIST_REMOVE(context->internal->servers, s); + SAFE_FREE(s); + s = next; + } + context->internal->servers = NULL; + } } - if (context->internal->files) { - DEBUG(1, ("Active files in context, " - "free_context failed.\n")); - errno = EBUSY; - return 1; + else { + /* This is the polite way */ + if ((context->cache.purge_cached_servers_fn)(context)) { + DEBUG(1, ("Could not purge all servers, " + "free_context failed.\n")); + errno = EBUSY; + return 1; + } + if (context->internal->servers) { + DEBUG(1, ("Active servers in context, " + "free_context failed.\n")); + errno = EBUSY; + return 1; + } + if (context->internal->files) { + DEBUG(1, ("Active files in context, " + "free_context failed.\n")); + errno = EBUSY; + return 1; + } } - } - - /* Things we have to clean up */ - SAFE_FREE(context->config.workgroup); - SAFE_FREE(context->config.netbios_name); - SAFE_FREE(context->config.user); - - DEBUG(3, ("Context %p successfully freed\n", context)); - SAFE_FREE(context); - return 0; + + /* Things we have to clean up */ + SAFE_FREE(context->config.workgroup); + SAFE_FREE(context->config.netbios_name); + SAFE_FREE(context->config.user); + + DEBUG(3, ("Context %p successfully freed\n", context)); + SAFE_FREE(context); + return 0; } -/* - * Each time the context structure is changed, we have binary backward - * compatibility issues. Instead of modifying the public portions of the - * context structure to add new options, instead, we put them in the internal - * portion of the context structure and provide a set function for these new - * options. +/** + * Deprecated interface. Do not use. Instead, use the various + * smbc_setOption*() functions or smbc_setFunctionAuthDataWithContext(). */ void smbc_option_set(SMBCCTX *context, char *option_name, ... /* option_value */) { - va_list ap; - union { - int i; - bool b; - smbc_get_auth_data_with_context_fn auth_fn; - void *v; - const char *s; - } option_value; - - va_start(ap, option_name); - - if (strcmp(option_name, "debug_to_stderr") == 0) { - /* - * Log to standard error instead of standard output. - */ - option_value.b = (bool) va_arg(ap, int); - context->internal->debug_stderr = option_value.b; - - } else if (strcmp(option_name, "full_time_names") == 0) { - /* - * 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.) - */ - option_value.b = (bool) va_arg(ap, int); - context->internal->full_time_names = option_value.b; - - } else if (strcmp(option_name, "open_share_mode") == 0) { - /* - * The share mode to use for files opened with - * SMBC_open_ctx(). The default is SMBC_SHAREMODE_DENY_NONE. - */ - option_value.i = va_arg(ap, int); - context->internal->share_mode = (smbc_share_mode) option_value.i; - - } else if (strcmp(option_name, "user_data") == 0) { - /* - * Save a user data handle which may be retrieved by the user - * with smbc_option_get() - */ - option_value.v = va_arg(ap, void *); - context->internal->user_data = option_value.v; - } else if (strcmp(option_name, "smb_encrypt_level") == 0) { - /* - * Save an encoded value for encryption level. - * 0 = off, 1 = attempt, 2 = required. - */ - option_value.s = va_arg(ap, const char *); - if (strcmp(option_value.s, "none") == 0) { - context->internal->smb_encryption_level = 0; - } else if (strcmp(option_value.s, "request") == 0) { - context->internal->smb_encryption_level = 1; - } else if (strcmp(option_value.s, "require") == 0) { - context->internal->smb_encryption_level = 2; - } - } else if (strcmp(option_name, "browse_max_lmb_count") == 0) { - /* - * 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). - */ - option_value.i = va_arg(ap, int); - context->internal->browse_max_lmb_count = option_value.i; + va_list ap; + union { + int i; + bool b; + smbc_get_auth_data_with_context_fn auth_fn; + void *v; + const char *s; + } option_value; - } else if (strcmp(option_name, "urlencode_readdir_entries") == 0) { - /* - * 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. - */ - option_value.b = (bool) va_arg(ap, int); - context->internal->urlencode_readdir_entries = option_value.b; + va_start(ap, option_name); - } else if (strcmp(option_name, "one_share_per_server") == 0) { - /* - * 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. - */ - option_value.b = (bool) va_arg(ap, int); - context->options.one_share_per_server = option_value.b; - - } else if (strcmp(option_name, "use_kerberos") == 0) { - option_value.b = (bool) va_arg(ap, int); - if (option_value.b) { - context->flags.bits |= SMB_CTX_FLAG_USE_KERBEROS; - } else { - context->flags.bits &= ~SMB_CTX_FLAG_USE_KERBEROS; - } - - } else if (strcmp(option_name, "fallback_after_kerberos") == 0) { - option_value.b = (bool) va_arg(ap, int); - if (option_value.b) { - context->flags.bits |= SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS; - } else { - context->flags.bits &= ~SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS; + if (strcmp(option_name, "debug_to_stderr") == 0) { + option_value.b = (bool) va_arg(ap, int); + smbc_setOptionDebugToStderr(context, option_value.b); + + } else if (strcmp(option_name, "full_time_names") == 0) { + option_value.b = (bool) va_arg(ap, int); + smbc_setOptionFullTimeNames(context, option_value.b); + + } else if (strcmp(option_name, "open_share_mode") == 0) { + option_value.i = va_arg(ap, int); + smbc_setOptionOpenShareMode(context, option_value.i); + + } else if (strcmp(option_name, "auth_function") == 0) { + option_value.auth_fn = + va_arg(ap, smbc_get_auth_data_with_context_fn); + smbc_setFunctionAuthDataWithContext(context, option_value.auth_fn); + + } else if (strcmp(option_name, "user_data") == 0) { + option_value.v = va_arg(ap, void *); + smbc_setOptionUserData(context, option_value.v); + + } else if (strcmp(option_name, "smb_encrypt_level") == 0) { + option_value.s = va_arg(ap, const char *); + if (strcmp(option_value.s, "none") == 0) { + smbc_setOptionSmbEncryptionLevel(context, + SMBC_ENCRYPTLEVEL_NONE); + } else if (strcmp(option_value.s, "request") == 0) { + smbc_setOptionSmbEncryptionLevel(context, + SMBC_ENCRYPTLEVEL_REQUEST); + } else if (strcmp(option_value.s, "require") == 0) { + smbc_setOptionSmbEncryptionLevel(context, + SMBC_ENCRYPTLEVEL_REQUIRE); + } + + } else if (strcmp(option_name, "browse_max_lmb_count") == 0) { + option_value.i = va_arg(ap, int); + smbc_setOptionBrowseMaxLmbCount(context, option_value.i); + + } else if (strcmp(option_name, "urlencode_readdir_entries") == 0) { + option_value.b = (bool) va_arg(ap, int); + smbc_setOptionUrlEncodeReaddirEntries(context, option_value.b); + + } else if (strcmp(option_name, "one_share_per_server") == 0) { + option_value.b = (bool) va_arg(ap, int); + smbc_setOptionOneSharePerServer(context, option_value.b); + + } else if (strcmp(option_name, "use_kerberos") == 0) { + option_value.b = (bool) va_arg(ap, int); + smbc_setOptionUseKerberos(context, option_value.b); + + } else if (strcmp(option_name, "fallback_after_kerberos") == 0) { + option_value.b = (bool) va_arg(ap, int); + smbc_setOptionFallbackAfterKerberos(context, option_value.b); + + } else if (strcmp(option_name, "no_auto_anonymous_login") == 0) { + option_value.b = (bool) va_arg(ap, int); + smbc_setOptionNoAutoAnonymousLogin(context, option_value.b); } - } else if (strcmp(option_name, "no_auto_anonymous_login") == 0) { - option_value.b = (bool) va_arg(ap, int); - if (option_value.b) { - context->flags.bits |= SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON; - } else { - context->flags.bits &= ~SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON; - } - } - - va_end(ap); + va_end(ap); } /* - * Retrieve the current value of an option + * Deprecated interface. Do not use. Instead, use the various + * smbc_getOption*() functions. */ void * smbc_option_get(SMBCCTX *context, char *option_name) { - int bits; - - if (strcmp(option_name, "debug_stderr") == 0) { - /* - * Log to standard error instead of standard output. - */ + int bits; + + if (strcmp(option_name, "debug_stderr") == 0) { #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->internal->debug_stderr; + return (void *) (intptr_t) smbc_getOptionDebugToStderr(context); #else - return (void *) context->internal->debug_stderr; + return (void *) smbc_getOptionDebugToStderr(context); #endif - - } else if (strcmp(option_name, "full_time_names") == 0) { - /* - * 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.) - */ + + } else if (strcmp(option_name, "full_time_names") == 0) { #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->internal->full_time_names; + return (void *) (intptr_t) smbc_getOptionFullTimeNames(context); #else - return (void *) context->internal->full_time_names; + return (void *) smbc_getOptionFullTimeNames(context); #endif - - } else if (strcmp(option_name, "user_data") == 0) { - /* - * Return the user data handle which was saved by the user - * with smbc_option_set() - */ - return context->internal->user_data; - - } else if (strcmp(option_name, "smb_encrypt_level") == 0) { - /* - * Return the current smb encrypt negotiate option as a string. - */ - switch (context->internal->smb_encryption_level) { - case 0: - return (void *) "none"; - case 1: - return (void *) "request"; - case 2: - return (void *) "require"; - } - - } else if (strcmp(option_name, "smb_encrypt_on") == 0) { - /* - * Return the current smb encrypt status option as a bool. - * false = off, true = on. We don't know what server is - * being requested, so we only return true if all servers - * are using an encrypted connection. - */ - SMBCSRV *s; - unsigned int num_servers = 0; - - for (s = context->internal->servers; s; s = s->next) { - num_servers++; - if (s->cli->trans_enc_state == NULL) { - return (void *)false; - } - } + + } else if (strcmp(option_name, "open_share_mode") == 0) { #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) (bool) (num_servers > 0); + return (void *) (intptr_t) smbc_getOptionOpenShareMode(context); #else - return (void *) (bool) (num_servers > 0); + return (void *) smbc_getOptionOpenShareMode(context); #endif - - } else if (strcmp(option_name, "browse_max_lmb_count") == 0) { - /* - * 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). - */ + + } else if (strcmp(option_name, "auth_function") == 0) { + return (void *) smbc_getFunctionAuthDataWithContext(context); + + } else if (strcmp(option_name, "user_data") == 0) { + return smbc_getOptionUserData(context); + + } else if (strcmp(option_name, "smb_encrypt_level") == 0) { + switch(smbc_getOptionSmbEncryptionLevel(context)) + { + case 0: + return (void *) "none"; + case 1: + return (void *) "request"; + case 2: + return (void *) "require"; + } + + } else if (strcmp(option_name, "smb_encrypt_on") == 0) { + SMBCSRV *s; + unsigned int num_servers = 0; + + for (s = context->internal->servers; s; s = s->next) { + num_servers++; + if (s->cli->trans_enc_state == NULL) { + return (void *)false; + } + } #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->internal->browse_max_lmb_count; + return (void *) (intptr_t) (bool) (num_servers > 0); #else - return (void *) context->internal->browse_max_lmb_count; + return (void *) (bool) (num_servers > 0); #endif - - } else if (strcmp(option_name, "urlencode_readdir_entries") == 0) { - /* - * 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. - */ + + } else if (strcmp(option_name, "browse_max_lmb_count") == 0) { #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *)(intptr_t) context->internal->urlencode_readdir_entries; + return (void *) (intptr_t) smbc_getOptionBrowseMaxLmbCount(context); #else - return (void *) (bool) context->internal->urlencode_readdir_entries; + return (void *) smbc_getOptionBrowseMaxLmbCount(context); #endif - - } else if (strcmp(option_name, "one_share_per_server") == 0) { - /* - * 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. - */ + + } else if (strcmp(option_name, "urlencode_readdir_entries") == 0) { #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->internal->one_share_per_server; + return (void *)(intptr_t) smbc_getOptionUrlEncodeReaddirEntries(context); #else - return (void *) (bool) context->internal->one_share_per_server; + return (void *) (bool) smbc_getOptionUrlEncodeReaddirEntries(context); #endif - - } else if (strcmp(option_name, "use_kerberos") == 0) { - bits = context->flags.bits; + + } else if (strcmp(option_name, "one_share_per_server") == 0) { #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS - ? (void *) (intptr_t) 1 - : (void *) (intptr_t) 0); + return (void *) (intptr_t) smbc_getOptionOneSharePerServer(context); #else - return (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS - ? (void *) (bool) 1 - : (void *) (bool) 0); + return (void *) (bool) smbc_getOptionOneSharePerServer(context); #endif - - } else if (strcmp(option_name, "fallback_after_kerberos") == 0) { + + } else if (strcmp(option_name, "use_kerberos") == 0) { + bits = context->flags.bits; #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (context->flags.bits & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS - ? (void *) (intptr_t) 1 - : (void *) (intptr_t) 0); + return (void *) (intptr_t) smbc_getOptionUseKerberos(context); #else - return (context->flags.bits & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS - ? (void *) (bool) 1 - : (void *) (bool) 0); + return (void *) (bool) smbc_getOptionUseKerberos(context); #endif - - } else if (strcmp(option_name, "no_auto_anonymous_login") == 0) { + + } else if (strcmp(option_name, "fallback_after_kerberos") == 0) { #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (context->flags.bits & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON - ? (void *) (intptr_t) 1 - : (void *) (intptr_t) 0); + return (void *)(intptr_t) smbc_getOptionFallbackAfterKerberos(context); #else - return (context->flags.bits & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON - ? (void *) (bool) 1 - : (void *) (bool) 0); + return (void *) (bool) smbc_getOptionFallbackAfterKerberos(context); #endif - } - - return NULL; + + } else if (strcmp(option_name, "no_auto_anonymous_login") == 0) { +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) + return (void *) (intptr_t) smbc_getOptionNoAutoAnonymousLogin(context); +#else + return (void *) (bool) smbc_getOptionNoAutoAnonymousLogin(context); +#endif + } + + return NULL; } @@ -564,175 +412,175 @@ smbc_option_get(SMBCCTX *context, SMBCCTX * smbc_init_context(SMBCCTX *context) { - int pid; - char *user = NULL; - char *home = NULL; - extern bool in_client; - - if (!context) { - errno = EBADF; - return NULL; - } - - /* Do not initialise the same client twice */ - if (context->internal->initialized) { - return 0; - } - - if (!context->server.get_auth_data_fn || - context->config.debug < 0 || - context->config.debug > 100) { + int pid; + char *user = NULL; + char *home = NULL; + extern bool in_client; - errno = EINVAL; - return NULL; - - } - - if (!SMBC_initialized) { - /* - * Do some library-wide intializations the first time we get - * called - */ - bool conf_loaded = False; - TALLOC_CTX *frame = talloc_stackframe(); - - /* Set this to what the user wants */ - DEBUGLEVEL = context->config.debug; - - load_case_tables(); - - setup_logging("libsmbclient", True); - if (context->internal->debug_stderr) { - dbf = x_stderr; - x_setbuf(x_stderr, NULL); + if (!context) { + errno = EBADF; + return NULL; } - /* Here we would open the smb.conf file if needed ... */ + /* Do not initialise the same client twice */ + if (context->internal->initialized) { + return 0; + } - in_client = True; /* FIXME, make a param */ + if (!context->server.get_auth_data_fn || + context->config.debug < 0 || + context->config.debug > 100) { + + errno = EINVAL; + return NULL; + + } - home = getenv("HOME"); - if (home) { - char *conf = NULL; - if (asprintf(&conf, "%s/.smb/smb.conf", home) > 0) { - if (lp_load(conf, True, False, False, True)) { - conf_loaded = True; - } else { - DEBUG(5, ("Could not load config file: %s\n", - conf)); + if (!SMBC_initialized) { + /* + * Do some library-wide intializations the first time we get + * called + */ + bool conf_loaded = False; + TALLOC_CTX *frame = talloc_stackframe(); + + /* Set this to what the user wants */ + DEBUGLEVEL = context->config.debug; + + load_case_tables(); + + setup_logging("libsmbclient", True); + if (context->internal->debug_stderr) { + dbf = x_stderr; + x_setbuf(x_stderr, NULL); } - SAFE_FREE(conf); - } + + /* Here we would open the smb.conf file if needed ... */ + + in_client = True; /* FIXME, make a param */ + + home = getenv("HOME"); + if (home) { + char *conf = NULL; + if (asprintf(&conf, "%s/.smb/smb.conf", home) > 0) { + if (lp_load(conf, True, False, False, True)) { + conf_loaded = True; + } else { + DEBUG(5, ("Could not load config file: %s\n", + conf)); + } + SAFE_FREE(conf); + } + } + + if (!conf_loaded) { + /* + * Well, if that failed, try the get_dyn_CONFIGFILE + * Which points to the standard locn, and if that + * fails, silently ignore it and use the internal + * defaults ... + */ + + if (!lp_load(get_dyn_CONFIGFILE(), True, False, False, False)) { + DEBUG(5, ("Could not load config file: %s\n", + get_dyn_CONFIGFILE())); + } else if (home) { + char *conf; + /* + * We loaded the global config file. Now lets + * load user-specific modifications to the + * global config. + */ + if (asprintf(&conf, + "%s/.smb/smb.conf.append", + home) > 0) { + if (!lp_load(conf, True, False, False, False)) { + DEBUG(10, + ("Could not append config file: " + "%s\n", + conf)); + } + SAFE_FREE(conf); + } + } + } + + load_interfaces(); /* Load the list of interfaces ... */ + + reopen_logs(); /* Get logging working ... */ + + /* + * Block SIGPIPE (from lib/util_sock.c: write()) + * It is not needed and should not stop execution + */ + BlockSignals(True, SIGPIPE); + + /* Done with one-time initialisation */ + SMBC_initialized = 1; + + TALLOC_FREE(frame); } - if (!conf_loaded) { - /* - * Well, if that failed, try the get_dyn_CONFIGFILE - * Which points to the standard locn, and if that - * fails, silently ignore it and use the internal - * defaults ... - */ - - if (!lp_load(get_dyn_CONFIGFILE(), True, False, False, False)) { - DEBUG(5, ("Could not load config file: %s\n", - get_dyn_CONFIGFILE())); - } else if (home) { - char *conf; + if (!context->config.user) { /* - * We loaded the global config file. Now lets - * load user-specific modifications to the - * global config. + * FIXME: Is this the best way to get the user info? */ - if (asprintf(&conf, - "%s/.smb/smb.conf.append", - home) > 0) { - if (!lp_load(conf, True, False, False, False)) { - DEBUG(10, - ("Could not append config file: " - "%s\n", - conf)); - } - SAFE_FREE(conf); + user = getenv("USER"); + /* walk around as "guest" if no username can be found */ + if (!user) context->config.user = SMB_STRDUP("guest"); + else context->config.user = SMB_STRDUP(user); + } + + if (!context->config.netbios_name) { + /* + * We try to get our netbios name from the config. If that + * fails we fall back on constructing our netbios name from + * our hostname etc + */ + if (global_myname()) { + context->config.netbios_name = SMB_STRDUP(global_myname()); + } + else { + /* + * Hmmm, I want to get hostname as well, but I am too + * lazy for the moment + */ + pid = sys_getpid(); + context->config.netbios_name = (char *)SMB_MALLOC(17); + if (!context->config.netbios_name) { + errno = ENOMEM; + return NULL; + } + slprintf(context->config.netbios_name, 16, + "smbc%s%d", context->config.user, pid); + } + } + + DEBUG(1, ("Using netbios name %s.\n", context->config.netbios_name)); + + if (!context->config.workgroup) { + if (lp_workgroup()) { + context->config.workgroup = SMB_STRDUP(lp_workgroup()); + } + else { + /* TODO: Think about a decent default workgroup */ + context->config.workgroup = SMB_STRDUP("samba"); } - } } - load_interfaces(); /* Load the list of interfaces ... */ + DEBUG(1, ("Using workgroup %s.\n", context->config.workgroup)); - reopen_logs(); /* Get logging working ... */ + /* shortest timeout is 1 second */ + if (context->config.timeout > 0 && context->config.timeout < 1000) + context->config.timeout = 1000; /* - * Block SIGPIPE (from lib/util_sock.c: write()) - * It is not needed and should not stop execution + * FIXME: Should we check the function pointers here? */ - BlockSignals(True, SIGPIPE); - /* Done with one-time initialisation */ - SMBC_initialized = 1; + context->internal->initialized = True; - TALLOC_FREE(frame); - } - - if (!context->config.user) { - /* - * FIXME: Is this the best way to get the user info? - */ - user = getenv("USER"); - /* walk around as "guest" if no username can be found */ - if (!user) context->config.user = SMB_STRDUP("guest"); - else context->config.user = SMB_STRDUP(user); - } - - if (!context->config.netbios_name) { - /* - * We try to get our netbios name from the config. If that - * fails we fall back on constructing our netbios name from - * our hostname etc - */ - if (global_myname()) { - context->config.netbios_name = SMB_STRDUP(global_myname()); - } - else { - /* - * Hmmm, I want to get hostname as well, but I am too - * lazy for the moment - */ - pid = sys_getpid(); - context->config.netbios_name = (char *)SMB_MALLOC(17); - if (!context->config.netbios_name) { - errno = ENOMEM; - return NULL; - } - slprintf(context->config.netbios_name, 16, - "smbc%s%d", context->config.user, pid); - } - } - - DEBUG(1, ("Using netbios name %s.\n", context->config.netbios_name)); - - if (!context->config.workgroup) { - if (lp_workgroup()) { - context->config.workgroup = SMB_STRDUP(lp_workgroup()); - } - else { - /* TODO: Think about a decent default workgroup */ - context->config.workgroup = SMB_STRDUP("samba"); - } - } - - DEBUG(1, ("Using workgroup %s.\n", context->config.workgroup)); - - /* shortest timeout is 1 second */ - if (context->config.timeout > 0 && context->config.timeout < 1000) - context->config.timeout = 1000; - - /* - * FIXME: Should we check the function pointers here? - */ - - context->internal->initialized = True; - - return context; + return context; } @@ -740,7 +588,7 @@ smbc_init_context(SMBCCTX *context) const char * smbc_version(void) { - return samba_version_string(); + return samba_version_string(); } @@ -748,56 +596,56 @@ smbc_version(void) char * smbc_getNetbiosName(SMBCCTX *c) { - return c->config.netbios_name; + return c->config.netbios_name; } /** Set the netbios name used for making connections */ void smbc_setNetbiosName(SMBCCTX *c, char * netbios_name) { - c->config.netbios_name = netbios_name; + c->config.netbios_name = netbios_name; } /** Get the workgroup used for making connections */ char * smbc_getWorkgroup(SMBCCTX *c) { - return c->config.workgroup; + return c->config.workgroup; } /** Set the workgroup used for making connections */ void smbc_setWorkgroup(SMBCCTX *c, char * workgroup) { - c->config.workgroup = workgroup; + c->config.workgroup = workgroup; } /** Get the username used for making connections */ char * smbc_getUser(SMBCCTX *c) { - return c->config.user; + return c->config.user; } /** Set the username used for making connections */ void smbc_setUser(SMBCCTX *c, char * user) { - c->config.user = user; + c->config.user = user; } /** Get the debug level */ int smbc_getDebug(SMBCCTX *c) { - return c->config.debug; + return c->config.debug; } /** Set the debug level */ void smbc_setDebug(SMBCCTX *c, int debug) { - c->config.debug = debug; + c->config.debug = debug; } /** @@ -807,7 +655,7 @@ smbc_setDebug(SMBCCTX *c, int debug) int smbc_getTimeout(SMBCCTX *c) { - return c->config.timeout; + return c->config.timeout; } /** @@ -817,43 +665,339 @@ smbc_getTimeout(SMBCCTX *c) void smbc_setTimeout(SMBCCTX *c, int timeout) { - c->config.timeout = timeout; + c->config.timeout = timeout; } -/** Get the function for obtaining authentication data */ +/** Get whether to log to standard error instead of standard output */ +smbc_bool +smbc_getOptionDebugToStderr(SMBCCTX *c) +{ + return c->internal->debug_stderr; +} + +/** Set whether to log to standard error instead of standard output */ +void +smbc_setOptionDebugToStderr(SMBCCTX *c, smbc_bool b) +{ + c->internal->debug_stderr = 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) +{ + return c->internal->full_time_names; +} + +/** + * 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) +{ + c->internal->full_time_names = 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) +{ + return c->internal->share_mode; +} + +/** + * 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) +{ + c->internal->share_mode = share_mode; +} + +/** Retrieve a previously set user data handle */ +void * +smbc_getOptionUserData(SMBCCTX *c) +{ + return c->internal->user_data; +} + +/** Save a user data handle */ +void +smbc_setOptionUserData(SMBCCTX *c, void *user_data) +{ + c->internal->user_data = user_data; +} +/** Get the encoded value for encryption level. */ +smbc_smb_encrypt_level +smbc_getOptionSmbEncryptionLevel(SMBCCTX *c) +{ + return c->internal->smb_encryption_level; +} + +/** Set the encoded value for encryption level. */ +void +smbc_setOptionSmbEncryptionLevel(SMBCCTX *c, smbc_smb_encrypt_level level) +{ + c->internal->smb_encryption_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) +{ + return c->options.browse_max_lmb_count; +} + +/** + * 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) +{ + c->options.browse_max_lmb_count = 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) +{ + return c->options.urlencode_readdir_entries; +} + +/** + * 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) +{ + c->options.urlencode_readdir_entries = 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) +{ + return c->options.one_share_per_server; +} + +/** + * 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) +{ + c->options.one_share_per_server = b; +} + +/** Get whether to enable use of kerberos */ +smbc_bool +smbc_getOptionUseKerberos(SMBCCTX *c) +{ + return c->flags.bits & SMB_CTX_FLAG_USE_KERBEROS ? True : False; +} + +/** Set whether to enable use of kerberos */ +void +smbc_setOptionUseKerberos(SMBCCTX *c, smbc_bool b) +{ + if (b) { + c->flags.bits |= SMB_CTX_FLAG_USE_KERBEROS; + } else { + c->flags.bits &= ~SMB_CTX_FLAG_USE_KERBEROS; + } +} + +/** Get whether to fallback after kerberos */ +smbc_bool +smbc_getOptionFallbackAfterKerberos(SMBCCTX *c) +{ + return c->flags.bits & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS ? True : False; +} + +/** Set whether to fallback after kerberos */ +void +smbc_setOptionFallbackAfterKerberos(SMBCCTX *c, smbc_bool b) +{ + if (b) { + c->flags.bits |= SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS; + } else { + c->flags.bits &= ~SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS; + } +} + +/** Get whether to automatically select anonymous login */ +smbc_bool +smbc_getOptionNoAutoAnonymousLogin(SMBCCTX *c) +{ + return c->flags.bits & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON ? True : False; +} + +/** Set whether to automatically select anonymous login */ +void +smbc_setOptionNoAutoAnonymousLogin(SMBCCTX *c, smbc_bool b) +{ + if (b) { + c->flags.bits |= SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON; + } else { + c->flags.bits &= ~SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON; + } +} + +/** Get the function for obtaining authentication data */ smbc_get_auth_data_fn smbc_getFunctionAuthData(SMBCCTX *c) { - return c->server.get_auth_data_fn; + return c->server.get_auth_data_fn; } /** Set the function for obtaining authentication data */ void smbc_setFunctionAuthData(SMBCCTX *c, smbc_get_auth_data_fn fn) { - c->server.get_auth_data_fn = fn; + c->internal->auth_fn_with_context = NULL; + c->server.get_auth_data_fn = fn; +} + +/** Get the new-style authentication function which includes the context. */ +smbc_get_auth_data_with_context_fn +smbc_getFunctionAuthDataWithContext(SMBCCTX *c) +{ + return c->internal->auth_fn_with_context; +} + +/** Set the new-style authentication function which includes the context. */ +void +smbc_setFunctionAuthDataWithContext(SMBCCTX *c, + smbc_get_auth_data_with_context_fn fn) +{ + c->server.get_auth_data_fn = NULL; + c->internal->auth_fn_with_context = fn; } /** Get the function for checking if a server is still good */ smbc_check_server_fn smbc_getFunctionCheckServer(SMBCCTX *c) { - return c->server.check_server_fn; + return c->server.check_server_fn; } /** Set the function for checking if a server is still good */ void smbc_setFunctionCheckServer(SMBCCTX *c, smbc_check_server_fn fn) { - c->server.check_server_fn = fn; + c->server.check_server_fn = fn; } /** Get the function for removing a server if unused */ smbc_remove_unused_server_fn smbc_getFunctionRemoveUnusedServer(SMBCCTX *c) { - return c->server.remove_unused_server_fn; + return c->server.remove_unused_server_fn; } /** Set the function for removing a server if unused */ @@ -861,21 +1005,21 @@ void smbc_setFunctionRemoveUnusedServer(SMBCCTX *c, smbc_remove_unused_server_fn fn) { - c->server.remove_unused_server_fn = fn; + c->server.remove_unused_server_fn = fn; } /** Get the function to store private data of the server cache */ struct smbc_server_cache * smbc_getServerCacheData(SMBCCTX *c) { - return c->cache.server_cache_data; + return c->cache.server_cache_data; } /** Set the function to store private data of the server cache */ void smbc_setServerCacheData(SMBCCTX *c, struct smbc_server_cache * cache) { - c->cache.server_cache_data = cache; + c->cache.server_cache_data = cache; } @@ -883,35 +1027,35 @@ smbc_setServerCacheData(SMBCCTX *c, struct smbc_server_cache * cache) smbc_add_cached_srv_fn smbc_getFunctionAddCachedServer(SMBCCTX *c) { - return c->cache.add_cached_server_fn; + return c->cache.add_cached_server_fn; } /** Set the function for adding a cached server */ void smbc_setFunctionAddCachedServer(SMBCCTX *c, smbc_add_cached_srv_fn fn) { - c->cache.add_cached_server_fn = fn; + c->cache.add_cached_server_fn = fn; } /** Get the function for server cache lookup */ smbc_get_cached_srv_fn smbc_getFunctionGetCachedServer(SMBCCTX *c) { - return c->cache.get_cached_server_fn; + return c->cache.get_cached_server_fn; } /** Set the function for server cache lookup */ void smbc_setFunctionGetCachedServer(SMBCCTX *c, smbc_get_cached_srv_fn fn) { - c->cache.get_cached_server_fn = fn; + c->cache.get_cached_server_fn = fn; } /** Get the function for server cache removal */ smbc_remove_cached_srv_fn smbc_getFunctionRemoveCachedServer(SMBCCTX *c) { - return c->cache.remove_cached_server_fn; + return c->cache.remove_cached_server_fn; } /** Set the function for server cache removal */ @@ -919,7 +1063,7 @@ void smbc_setFunctionRemoveCachedServer(SMBCCTX *c, smbc_remove_cached_srv_fn fn) { - c->cache.remove_cached_server_fn = fn; + c->cache.remove_cached_server_fn = fn; } /** @@ -929,7 +1073,7 @@ smbc_setFunctionRemoveCachedServer(SMBCCTX *c, smbc_purge_cached_srv_fn smbc_getFunctionPurgeCachedServers(SMBCCTX *c) { - return c->cache.purge_cached_servers_fn; + return c->cache.purge_cached_servers_fn; } /** @@ -939,7 +1083,7 @@ smbc_getFunctionPurgeCachedServers(SMBCCTX *c) void smbc_setFunctionPurgeCachedServers(SMBCCTX *c, smbc_purge_cached_srv_fn fn) { - c->cache.purge_cached_servers_fn = fn; + c->cache.purge_cached_servers_fn = fn; } /** @@ -949,133 +1093,133 @@ smbc_setFunctionPurgeCachedServers(SMBCCTX *c, smbc_purge_cached_srv_fn fn) smbc_open_fn smbc_getFunctionOpen(SMBCCTX *c) { - return c->posix_emu.open_fn; + return c->posix_emu.open_fn; } void smbc_setFunctionOpen(SMBCCTX *c, smbc_open_fn fn) { - c->posix_emu.open_fn = fn; + c->posix_emu.open_fn = fn; } smbc_creat_fn smbc_getFunctionCreat(SMBCCTX *c) { - return c->posix_emu.creat_fn; + return c->posix_emu.creat_fn; } void smbc_setFunctionCreat(SMBCCTX *c, smbc_creat_fn fn) { - c->posix_emu.creat_fn = fn; + c->posix_emu.creat_fn = fn; } smbc_read_fn smbc_getFunctionRead(SMBCCTX *c) { - return c->posix_emu.read_fn; + return c->posix_emu.read_fn; } void smbc_setFunctionRead(SMBCCTX *c, smbc_read_fn fn) { - c->posix_emu.read_fn = fn; + c->posix_emu.read_fn = fn; } smbc_write_fn smbc_getFunctionWrite(SMBCCTX *c) { - return c->posix_emu.write_fn; + return c->posix_emu.write_fn; } void smbc_setFunctionWrite(SMBCCTX *c, smbc_write_fn fn) { - c->posix_emu.write_fn = fn; + c->posix_emu.write_fn = fn; } smbc_unlink_fn smbc_getFunctionUnlink(SMBCCTX *c) { - return c->posix_emu.unlink_fn; + return c->posix_emu.unlink_fn; } void smbc_setFunctionUnlink(SMBCCTX *c, smbc_unlink_fn fn) { - c->posix_emu.unlink_fn = fn; + c->posix_emu.unlink_fn = fn; } smbc_rename_fn smbc_getFunctionRename(SMBCCTX *c) { - return c->posix_emu.rename_fn; + return c->posix_emu.rename_fn; } void smbc_setFunctionRename(SMBCCTX *c, smbc_rename_fn fn) { - c->posix_emu.rename_fn = fn; + c->posix_emu.rename_fn = fn; } smbc_lseek_fn smbc_getFunctionLseek(SMBCCTX *c) { - return c->posix_emu.lseek_fn; + return c->posix_emu.lseek_fn; } void smbc_setFunctionLseek(SMBCCTX *c, smbc_lseek_fn fn) { - c->posix_emu.lseek_fn = fn; + c->posix_emu.lseek_fn = fn; } smbc_stat_fn smbc_getFunctionStat(SMBCCTX *c) { - return c->posix_emu.stat_fn; + return c->posix_emu.stat_fn; } void smbc_setFunctionStat(SMBCCTX *c, smbc_stat_fn fn) { - c->posix_emu.stat_fn = fn; + c->posix_emu.stat_fn = fn; } smbc_fstat_fn smbc_getFunctionFstat(SMBCCTX *c) { - return c->posix_emu.fstat_fn; + return c->posix_emu.fstat_fn; } void smbc_setFunctionFstat(SMBCCTX *c, smbc_fstat_fn fn) { - c->posix_emu.fstat_fn = fn; + c->posix_emu.fstat_fn = fn; } smbc_ftruncate_fn smbc_getFunctionFtruncate(SMBCCTX *c) { - return c->internal->posix_emu.ftruncate_fn; + return c->internal->posix_emu.ftruncate_fn; } void smbc_setFunctionFtruncate(SMBCCTX *c, smbc_ftruncate_fn fn) { - c->internal->posix_emu.ftruncate_fn = fn; + c->internal->posix_emu.ftruncate_fn = fn; } smbc_close_fn smbc_getFunctionClose(SMBCCTX *c) { - return c->posix_emu.close_fn; + return c->posix_emu.close_fn; } void smbc_setFunctionClose(SMBCCTX *c, smbc_close_fn fn) { - c->posix_emu.close_fn = fn; + c->posix_emu.close_fn = fn; } @@ -1086,109 +1230,109 @@ smbc_setFunctionClose(SMBCCTX *c, smbc_close_fn fn) smbc_opendir_fn smbc_getFunctionOpendir(SMBCCTX *c) { - return c->posix_emu.opendir_fn; + return c->posix_emu.opendir_fn; } void smbc_setFunctionOpendir(SMBCCTX *c, smbc_opendir_fn fn) { - c->posix_emu.opendir_fn = fn; + c->posix_emu.opendir_fn = fn; } smbc_closedir_fn smbc_getFunctionClosedir(SMBCCTX *c) { - return c->posix_emu.closedir_fn; + return c->posix_emu.closedir_fn; } void smbc_setFunctionClosedir(SMBCCTX *c, smbc_closedir_fn fn) { - c->posix_emu.closedir_fn = fn; + c->posix_emu.closedir_fn = fn; } smbc_readdir_fn smbc_getFunctionReaddir(SMBCCTX *c) { - return c->posix_emu.readdir_fn; + return c->posix_emu.readdir_fn; } void smbc_setFunctionReaddir(SMBCCTX *c, smbc_readdir_fn fn) { - c->posix_emu.readdir_fn = fn; + c->posix_emu.readdir_fn = fn; } smbc_getdents_fn smbc_getFunctionGetdents(SMBCCTX *c) { - return c->posix_emu.getdents_fn; + return c->posix_emu.getdents_fn; } void smbc_setFunctionGetdents(SMBCCTX *c, smbc_getdents_fn fn) { - c->posix_emu.getdents_fn = fn; + c->posix_emu.getdents_fn = fn; } smbc_mkdir_fn smbc_getFunctionMkdir(SMBCCTX *c) { - return c->posix_emu.mkdir_fn; + return c->posix_emu.mkdir_fn; } void smbc_setFunctionMkdir(SMBCCTX *c, smbc_mkdir_fn fn) { - c->posix_emu.mkdir_fn = fn; + c->posix_emu.mkdir_fn = fn; } smbc_rmdir_fn smbc_getFunctionRmdir(SMBCCTX *c) { - return c->posix_emu.rmdir_fn; + return c->posix_emu.rmdir_fn; } void smbc_setFunctionRmdir(SMBCCTX *c, smbc_rmdir_fn fn) { - c->posix_emu.rmdir_fn = fn; + c->posix_emu.rmdir_fn = fn; } smbc_telldir_fn smbc_getFunctionTelldir(SMBCCTX *c) { - return c->posix_emu.telldir_fn; + return c->posix_emu.telldir_fn; } void smbc_setFunctionTelldir(SMBCCTX *c, smbc_telldir_fn fn) { - c->posix_emu.telldir_fn = fn; + c->posix_emu.telldir_fn = fn; } smbc_lseekdir_fn smbc_getFunctionLseekdir(SMBCCTX *c) { - return c->posix_emu.lseekdir_fn; + return c->posix_emu.lseekdir_fn; } void smbc_setFunctionLseekdir(SMBCCTX *c, smbc_lseekdir_fn fn) { - c->posix_emu.lseekdir_fn = fn; + c->posix_emu.lseekdir_fn = fn; } smbc_fstatdir_fn smbc_getFunctionFstatdir(SMBCCTX *c) { - return c->posix_emu.fstatdir_fn; + return c->posix_emu.fstatdir_fn; } void smbc_setFunctionFstatdir(SMBCCTX *c, smbc_fstatdir_fn fn) { - c->posix_emu.fstatdir_fn = fn; + c->posix_emu.fstatdir_fn = fn; } @@ -1199,73 +1343,73 @@ smbc_setFunctionFstatdir(SMBCCTX *c, smbc_fstatdir_fn fn) smbc_chmod_fn smbc_getFunctionChmod(SMBCCTX *c) { - return c->posix_emu.chmod_fn; + return c->posix_emu.chmod_fn; } void smbc_setFunctionChmod(SMBCCTX *c, smbc_chmod_fn fn) { - c->posix_emu.chmod_fn = fn; + c->posix_emu.chmod_fn = fn; } smbc_utimes_fn smbc_getFunctionUtimes(SMBCCTX *c) { - return c->posix_emu.utimes_fn; + return c->posix_emu.utimes_fn; } void smbc_setFunctionUtimes(SMBCCTX *c, smbc_utimes_fn fn) { - c->posix_emu.utimes_fn = fn; + c->posix_emu.utimes_fn = fn; } smbc_setxattr_fn smbc_getFunctionSetxattr(SMBCCTX *c) { - return c->posix_emu.setxattr_fn; + return c->posix_emu.setxattr_fn; } void smbc_setFunctionSetxattr(SMBCCTX *c, smbc_setxattr_fn fn) { - c->posix_emu.setxattr_fn = fn; + c->posix_emu.setxattr_fn = fn; } smbc_getxattr_fn smbc_getFunctionGetxattr(SMBCCTX *c) { - return c->posix_emu.getxattr_fn; + return c->posix_emu.getxattr_fn; } void smbc_setFunctionGetxattr(SMBCCTX *c, smbc_getxattr_fn fn) { - c->posix_emu.getxattr_fn = fn; + c->posix_emu.getxattr_fn = fn; } smbc_removexattr_fn smbc_getFunctionRemovexattr(SMBCCTX *c) { - return c->posix_emu.removexattr_fn; + return c->posix_emu.removexattr_fn; } void smbc_setFunctionRemovexattr(SMBCCTX *c, smbc_removexattr_fn fn) { - c->posix_emu.removexattr_fn = fn; + c->posix_emu.removexattr_fn = fn; } smbc_listxattr_fn smbc_getFunctionListxattr(SMBCCTX *c) { - return c->posix_emu.listxattr_fn; + return c->posix_emu.listxattr_fn; } void smbc_setFunctionListxattr(SMBCCTX *c, smbc_listxattr_fn fn) { - c->posix_emu.listxattr_fn = fn; + c->posix_emu.listxattr_fn = fn; } @@ -1276,51 +1420,51 @@ smbc_setFunctionListxattr(SMBCCTX *c, smbc_listxattr_fn fn) smbc_print_file_fn smbc_getFunctionPrintFile(SMBCCTX *c) { - return c->printing.print_file_fn; + return c->printing.print_file_fn; } void smbc_setFunctionPrintFile(SMBCCTX *c, smbc_print_file_fn fn) { - c->printing.print_file_fn = fn; + c->printing.print_file_fn = fn; } smbc_open_print_job_fn smbc_getFunctionOpenPrintJob(SMBCCTX *c) { - return c->printing.open_print_job_fn; + return c->printing.open_print_job_fn; } void smbc_setFunctionOpenPrintJob(SMBCCTX *c, smbc_open_print_job_fn fn) { - c->printing.open_print_job_fn = fn; + c->printing.open_print_job_fn = fn; } smbc_list_print_jobs_fn smbc_getFunctionListPrintJobs(SMBCCTX *c) { - return c->printing.list_print_jobs_fn; + return c->printing.list_print_jobs_fn; } void smbc_setFunctionListPrintJobs(SMBCCTX *c, smbc_list_print_jobs_fn fn) { - c->printing.list_print_jobs_fn = fn; + c->printing.list_print_jobs_fn = fn; } smbc_unlink_print_job_fn smbc_getFunctionUnlinkPrintJob(SMBCCTX *c) { - return c->printing.unlink_print_job_fn; + return c->printing.unlink_print_job_fn; } void smbc_setFunctionUnlinkPrintJob(SMBCCTX *c, - smbc_unlink_print_job_fn fn) + smbc_unlink_print_job_fn fn) { - c->printing.unlink_print_job_fn = fn; + c->printing.unlink_print_job_fn = fn; } diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 25020762a2..2ece2ab8ed 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -36,19 +36,19 @@ static void remove_dir(SMBCFILE *dir) { struct smbc_dir_list *d,*f; - + d = dir->dir_list; while (d) { - + f = d; d = d->next; - + SAFE_FREE(f->dirent); SAFE_FREE(f); - + } - + dir->dir_list = dir->dir_end = dir->dir_next = NULL; - + } static int @@ -61,63 +61,63 @@ add_dirent(SMBCFILE *dir, int size; int name_length = (name == NULL ? 0 : strlen(name)); int comment_len = (comment == NULL ? 0 : strlen(comment)); - + /* * Allocate space for the dirent, which must be increased by the * size of the name and the comment and 1 each for the null terminator. */ - + size = sizeof(struct smbc_dirent) + name_length + comment_len + 2; - + dirent = (struct smbc_dirent *)SMB_MALLOC(size); - + if (!dirent) { - + dir->dir_error = ENOMEM; return -1; - + } - + ZERO_STRUCTP(dirent); - + if (dir->dir_list == NULL) { - + dir->dir_list = SMB_MALLOC_P(struct smbc_dir_list); if (!dir->dir_list) { - + SAFE_FREE(dirent); dir->dir_error = ENOMEM; return -1; - + } ZERO_STRUCTP(dir->dir_list); - + dir->dir_end = dir->dir_next = dir->dir_list; } else { - + dir->dir_end->next = SMB_MALLOC_P(struct smbc_dir_list); - + if (!dir->dir_end->next) { - + SAFE_FREE(dirent); dir->dir_error = ENOMEM; return -1; - + } ZERO_STRUCTP(dir->dir_end->next); - + dir->dir_end = dir->dir_end->next; } - + dir->dir_end->next = NULL; dir->dir_end->dirent = dirent; - + dirent->smbc_type = type; dirent->namelen = name_length; dirent->commentlen = comment_len; dirent->dirlen = size; - + /* * dirent->namelen + 1 includes the null (no null termination needed) * Ditto for dirent->commentlen. @@ -126,9 +126,9 @@ add_dirent(SMBCFILE *dir, strncpy(dirent->name, (name?name:""), dirent->namelen + 1); dirent->comment = (char *)(&dirent->name + dirent->namelen + 1); strncpy(dirent->comment, (comment?comment:""), dirent->commentlen + 1); - + return 0; - + } static void @@ -142,18 +142,18 @@ list_unique_wg_fn(const char *name, struct smbc_dirent *dirent; int dirent_type; int do_remove = 0; - + dirent_type = dir->dir_type; - + if (add_dirent(dir, name, comment, dirent_type) < 0) { - + /* An error occurred, what do we do? */ /* FIXME: Add some code here */ } - + /* Point to the one just added */ dirent = dir->dir_end->dirent; - + /* See if this was a duplicate */ for (dir_list = dir->dir_list; dir_list != dir->dir_end; @@ -163,7 +163,7 @@ list_unique_wg_fn(const char *name, /* Duplicate. End end of list need to be removed. */ do_remove = 1; } - + if (do_remove && dir_list->next == dir->dir_end) { /* Found the end of the list. Remove it. */ dir->dir_end = dir_list; @@ -183,7 +183,7 @@ list_fn(const char *name, { SMBCFILE *dir = (SMBCFILE *)state; int dirent_type; - + /* * We need to process the type a little ... * @@ -195,27 +195,27 @@ list_fn(const char *name, * administrative shares: * ADMIN$, IPC$, C$, D$, E$ ... are type |= 0x80000000 */ - + if (dir->dir_type == SMBC_FILE_SHARE) { switch (type) { case 0 | 0x80000000: case 0: dirent_type = SMBC_FILE_SHARE; break; - + case 1: dirent_type = SMBC_PRINTER_SHARE; break; - + case 2: dirent_type = SMBC_COMMS_SHARE; break; - + case 3 | 0x80000000: case 3: dirent_type = SMBC_IPC_SHARE; break; - + default: dirent_type = SMBC_FILE_SHARE; /* FIXME, error? */ break; @@ -224,12 +224,12 @@ list_fn(const char *name, else { dirent_type = dir->dir_type; } - + if (add_dirent(dir, name, comment, dirent_type) < 0) { - + /* An error occurred, what do we do? */ /* FIXME: Add some code here */ - + } } @@ -239,16 +239,16 @@ dir_list_fn(const char *mnt, const char *mask, void *state) { - + if (add_dirent((SMBCFILE *)state, finfo->name, "", (finfo->mode&aDIR?SMBC_DIR:SMBC_FILE)) < 0) { - + /* Handle an error ... */ - + /* FIXME: Add some code ... */ - + } - + } static int @@ -270,14 +270,14 @@ net_share_enum_rpc(struct cli_state *cli, fstring comment = ""; struct rpc_pipe_client *pipe_hnd; NTSTATUS nt_status; - + /* Open the server service pipe */ pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &nt_status); if (!pipe_hnd) { DEBUG(1, ("net_share_enum_rpc pipe open fail!\n")); return -1; } - + /* Issue the NetShareEnum RPC call and retrieve the response */ init_enum_hnd(&enum_hnd, 0); result = rpccli_srvsvc_net_share_enum(pipe_hnd, @@ -286,35 +286,35 @@ net_share_enum_rpc(struct cli_state *cli, &ctr, preferred_len, &enum_hnd); - + /* Was it successful? */ if (!W_ERROR_IS_OK(result) || ctr.num_entries == 0) { /* Nope. Go clean up. */ goto done; } - + /* For each returned entry... */ for (i = 0; i < ctr.num_entries; i++) { - + /* pull out the share name */ rpcstr_pull_unistr2_fstring( name, &ctr.share.info1[i].info_1_str.uni_netname); - + /* pull out the share's comment */ rpcstr_pull_unistr2_fstring( comment, &ctr.share.info1[i].info_1_str.uni_remark); - + /* Get the type value */ type = ctr.share.info1[i].info_1.type; - + /* Add this share to the list */ (*fn)(name, type, comment, state); } - + done: /* Close the server service pipe */ cli_rpc_pipe_close(pipe_hnd); - + /* Tell 'em if it worked */ return W_ERROR_IS_OK(result) ? 0 : -1; } @@ -332,10 +332,10 @@ SMBC_check_options(char *server, DEBUG(4, ("SMBC_check_options(): server='%s' share='%s' " "path='%s' options='%s'\n", server, share, path, options)); - + /* No options at all is always ok */ if (! *options) return 0; - + /* Currently, we don't support any options. */ return -1; } @@ -346,7 +346,11 @@ SMBC_opendir_ctx(SMBCCTX *context, const char *fname) { int saved_errno; - char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *options = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *options = NULL; char *workgroup = NULL; char *path = NULL; uint16 mode; @@ -355,42 +359,42 @@ SMBC_opendir_ctx(SMBCCTX *context, SMBCFILE *dir = NULL; struct sockaddr_storage rem_ss; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { DEBUG(4, ("no valid context\n")); errno = EINVAL + 8192; TALLOC_FREE(frame); return NULL; - + } - + if (!fname) { DEBUG(4, ("no valid fname\n")); errno = EINVAL + 8193; TALLOC_FREE(frame); return NULL; } - + if (SMBC_parse_path(frame, - context, - fname, - &workgroup, - &server, - &share, - &path, - &user, - &password, - &options)) { + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + &options)) { DEBUG(4, ("no valid path\n")); errno = EINVAL + 8194; TALLOC_FREE(frame); return NULL; } - + DEBUG(4, ("parsed path: fname='%s' server='%s' share='%s' " "path='%s' options='%s'\n", fname, server, share, path, options)); - + /* Ensure the options are valid */ if (SMBC_check_options(server, share, path, options)) { DEBUG(4, ("unacceptable options (%s)\n", options)); @@ -398,7 +402,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, context->config.user); if (!user) { @@ -407,35 +411,35 @@ SMBC_opendir_ctx(SMBCCTX *context, return NULL; } } - + dir = SMB_MALLOC_P(SMBCFILE); - + if (!dir) { errno = ENOMEM; TALLOC_FREE(frame); return NULL; } - + ZERO_STRUCTP(dir); - + dir->cli_fd = 0; dir->fname = SMB_STRDUP(fname); dir->srv = NULL; dir->offset = 0; dir->file = False; dir->dir_list = dir->dir_next = dir->dir_end = NULL; - + if (server[0] == (char)0) { - + int i; int count; int max_lmb_count; struct ip_service *ip_list; struct ip_service server_addr; struct user_auth_info u_info; - + if (share[0] != (char)0 || path[0] != (char)0) { - + errno = EINVAL + 8196; if (dir) { SAFE_FREE(dir->fname); @@ -444,12 +448,12 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + /* Determine how many local master browsers to query */ - max_lmb_count = (context->internal->browse_max_lmb_count == 0 + max_lmb_count = (context->options.browse_max_lmb_count == 0 ? INT_MAX - : context->internal->browse_max_lmb_count); - + : context->options.browse_max_lmb_count); + memset(&u_info, '\0', sizeof(u_info)); u_info.username = talloc_strdup(frame,user); u_info.password = talloc_strdup(frame,password); @@ -461,7 +465,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + /* * We have server and share and path empty but options * requesting that we scan all master browsers for their list @@ -470,16 +474,16 @@ SMBC_opendir_ctx(SMBCCTX *context, * doesn't work, then try our other methods which return only * a single master browser. */ - + ip_list = NULL; if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list, - &count))) + &count))) { - + SAFE_FREE(ip_list); - + if (!find_master_ip(workgroup, &server_addr.ss)) { - + if (dir) { SAFE_FREE(dir->fname); SAFE_FREE(dir); @@ -488,7 +492,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + ip_list = (struct ip_service *)memdup( &server_addr, sizeof(server_addr)); if (ip_list == NULL) { @@ -498,17 +502,17 @@ SMBC_opendir_ctx(SMBCCTX *context, } count = 1; } - + for (i = 0; i < count && i < max_lmb_count; i++) { char addr[INET6_ADDRSTRLEN]; char *wg_ptr = NULL; struct cli_state *cli = NULL; - + print_sockaddr(addr, sizeof(addr), &ip_list[i].ss); DEBUG(99, ("Found master browser %d of %d: %s\n", i+1, MAX(count, max_lmb_count), addr)); - + cli = get_ipc_connect_master_ip(talloc_tos(), &ip_list[i], &u_info, @@ -518,39 +522,39 @@ SMBC_opendir_ctx(SMBCCTX *context, if (!cli) { continue; } - + workgroup = talloc_strdup(frame, wg_ptr); server = talloc_strdup(frame, cli->desthost); - + cli_shutdown(cli); - + if (!workgroup || !server) { errno = ENOMEM; TALLOC_FREE(frame); return NULL; } - + DEBUG(4, ("using workgroup %s %s\n", workgroup, server)); - + /* * For each returned master browser IP address, get a * connection to IPC$ on the server if we do not * already have one, and determine the * workgroups/domains that it knows about. */ - + srv = SMBC_server(frame, context, True, server, "IPC$", &workgroup, &user, &password); if (!srv) { continue; } - + dir->srv = srv; dir->dir_type = SMBC_WORKGROUP; - + /* Now, list the stuff ... */ - + if (!cli_NetServerEnum(srv->cli, workgroup, SV_TYPE_DOMAIN_ENUM, @@ -559,7 +563,7 @@ SMBC_opendir_ctx(SMBCCTX *context, continue; } } - + SAFE_FREE(ip_list); } else { /* @@ -568,7 +572,7 @@ SMBC_opendir_ctx(SMBCCTX *context, */ if (*share == '\0') { if (*path != '\0') { - + /* Should not have empty share with path */ errno = EINVAL + 8197; if (dir) { @@ -577,9 +581,9 @@ SMBC_opendir_ctx(SMBCCTX *context, } TALLOC_FREE(frame); return NULL; - + } - + /* * We don't know if is really a server name * or is a workgroup/domain name. If we already have @@ -588,15 +592,16 @@ SMBC_opendir_ctx(SMBCCTX *context, * <1B>, or <20> translates. We check * to see if is an IP address first. */ - + /* * See if we have an existing server. Do not * establish a connection if one does not already * exist. */ - srv = SMBC_server(frame, context, False, server, "IPC$", + srv = SMBC_server(frame, context, False, + server, "IPC$", &workgroup, &user, &password); - + /* * If no existing server and not an IP addr, look for * LMB or DMB @@ -605,20 +610,20 @@ SMBC_opendir_ctx(SMBCCTX *context, !is_ipaddress(server) && (resolve_name(server, &rem_ss, 0x1d) || /* LMB */ resolve_name(server, &rem_ss, 0x1b) )) { /* DMB */ - + fstring buserver; - + dir->dir_type = SMBC_SERVER; - + /* * Get the backup list ... */ if (!name_status_find(server, 0, 0, &rem_ss, buserver)) { - - DEBUG(0, ("Could not get name of " - "local/domain master browser " - "for server %s\n", server)); + + DEBUG(0,("Could not get name of " + "local/domain master browser " + "for server %s\n", server)); if (dir) { SAFE_FREE(dir->fname); SAFE_FREE(dir); @@ -626,16 +631,17 @@ SMBC_opendir_ctx(SMBCCTX *context, errno = EPERM; TALLOC_FREE(frame); return NULL; - + } - + /* * Get a connection to IPC$ on the server if * we do not already have one */ srv = SMBC_server(frame, context, True, buserver, "IPC$", - &workgroup, &user, &password); + &workgroup, + &user, &password); if (!srv) { DEBUG(0, ("got no contact to IPC$\n")); if (dir) { @@ -644,16 +650,16 @@ SMBC_opendir_ctx(SMBCCTX *context, } TALLOC_FREE(frame); return NULL; - + } - + dir->srv = srv; - + /* Now, list the servers ... */ if (!cli_NetServerEnum(srv->cli, server, 0x0000FFFE, list_fn, (void *)dir)) { - + if (dir) { SAFE_FREE(dir->fname); SAFE_FREE(dir); @@ -663,15 +669,17 @@ SMBC_opendir_ctx(SMBCCTX *context, } } else if (srv || (resolve_name(server, &rem_ss, 0x20))) { - - /* If we hadn't found the server, get one now */ + + /* + * If we hadn't found the server, get one now + */ if (!srv) { srv = SMBC_server(frame, context, True, server, "IPC$", &workgroup, &user, &password); } - + if (!srv) { if (dir) { SAFE_FREE(dir->fname); @@ -679,14 +687,14 @@ SMBC_opendir_ctx(SMBCCTX *context, } TALLOC_FREE(frame); return NULL; - + } - + dir->dir_type = SMBC_FILE_SHARE; dir->srv = srv; - + /* List the shares ... */ - + if (net_share_enum_rpc( srv->cli, list_fn, @@ -695,7 +703,7 @@ SMBC_opendir_ctx(SMBCCTX *context, srv->cli, list_fn, (void *)dir) < 0) { - + errno = cli_errno(srv->cli); if (dir) { SAFE_FREE(dir->fname); @@ -703,7 +711,7 @@ SMBC_opendir_ctx(SMBCCTX *context, } TALLOC_FREE(frame); return NULL; - + } } else { /* Neither the workgroup nor server exists */ @@ -715,7 +723,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + } else { /* @@ -724,13 +732,13 @@ SMBC_opendir_ctx(SMBCCTX *context, */ char *targetpath; struct cli_state *targetcli; - + /* We connect to the server and list the directory */ dir->dir_type = SMBC_FILE_SHARE; - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { if (dir) { SAFE_FREE(dir->fname); @@ -739,11 +747,11 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + dir->srv = srv; - + /* Now, list the files ... */ - + p = path + strlen(path); path = talloc_asprintf_append(path, "\\*"); if (!path) { @@ -754,7 +762,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + if (!cli_resolve_path(frame, "", srv->cli, path, &targetcli, &targetpath)) { d_printf("Could not resolve %s\n", path); @@ -765,47 +773,48 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + if (cli_list(targetcli, targetpath, aDIR | aSYSTEM | aHIDDEN, dir_list_fn, (void *)dir) < 0) { - + if (dir) { SAFE_FREE(dir->fname); SAFE_FREE(dir); } saved_errno = SMBC_errno(context, targetcli); - + if (saved_errno == EINVAL) { - /* - * See if they asked to opendir something - * other than a directory. If so, the - * converted error value we got would have - * been EINVAL rather than ENOTDIR. - */ - *p = '\0'; /* restore original path */ - - if (SMBC_getatr(context, srv, path, - &mode, NULL, - NULL, NULL, NULL, NULL, - NULL) && - ! IS_DOS_DIR(mode)) { - - /* It is. Correct the error value */ - saved_errno = ENOTDIR; - } + /* + * See if they asked to opendir + * something other than a directory. + * If so, the converted error value we + * got would have been EINVAL rather + * than ENOTDIR. + */ + *p = '\0'; /* restore original path */ + + if (SMBC_getatr(context, srv, path, + &mode, NULL, + NULL, NULL, NULL, NULL, + NULL) && + ! IS_DOS_DIR(mode)) { + + /* It is. Correct the error value */ + saved_errno = ENOTDIR; + } } - + /* * If there was an error and the server is no * good any more... */ if (cli_is_error(targetcli) && (context->server.check_server_fn)(context, srv)) { - + /* ... then remove it. */ if ((context->server.remove_unused_server_fn)(context, - srv)) { + srv)) { /* * We could not remove the * server completely, remove @@ -817,19 +826,19 @@ SMBC_opendir_ctx(SMBCCTX *context, (context->cache.remove_cached_server_fn)(context, srv); } } - + errno = saved_errno; TALLOC_FREE(frame); return NULL; } } - + } - + DLIST_ADD(context->internal->files, dir); TALLOC_FREE(frame); return dir; - + } /* @@ -841,32 +850,32 @@ SMBC_closedir_ctx(SMBCCTX *context, SMBCFILE *dir) { TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; TALLOC_FREE(frame); return -1; } - + remove_dir(dir); /* Clean it up */ - + DLIST_REMOVE(context->internal->files, dir); - + if (dir) { - + SAFE_FREE(dir->fname); SAFE_FREE(dir); /* Free the space too */ } - + TALLOC_FREE(frame); return 0; - + } static void @@ -875,29 +884,29 @@ smbc_readdir_internal(SMBCCTX * context, struct smbc_dirent *src, int max_namebuf_len) { - if (context->internal->urlencode_readdir_entries) { - + if (context->options.urlencode_readdir_entries) { + /* url-encode the name. get back remaining buffer space */ max_namebuf_len = SMBC_urlencode(dest->name, src->name, max_namebuf_len); - + /* We now know the name length */ dest->namelen = strlen(dest->name); - + /* Save the pointer to the beginning of the comment */ dest->comment = dest->name + dest->namelen + 1; - + /* Copy the comment */ strncpy(dest->comment, src->comment, max_namebuf_len - 1); dest->comment[max_namebuf_len - 1] = '\0'; - + /* Save other fields */ dest->smbc_type = src->smbc_type; dest->commentlen = strlen(dest->comment); dest->dirlen = ((dest->comment + dest->commentlen + 1) - (char *) dest); } else { - + /* No encoding. Just copy the entry as is. */ memcpy(dest, src, src->dirlen); dest->comment = (char *)(&dest->name + src->namelen + 1); @@ -916,58 +925,58 @@ SMBC_readdir_ctx(SMBCCTX *context, int maxlen; struct smbc_dirent *dirp, *dirent; TALLOC_CTX *frame = talloc_stackframe(); - + /* Check that all is ok first ... */ - + if (!context || !context->internal->initialized) { - + errno = EINVAL; DEBUG(0, ("Invalid context in SMBC_readdir_ctx()\n")); TALLOC_FREE(frame); return NULL; - + } - + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { - + errno = EBADF; DEBUG(0, ("Invalid dir in SMBC_readdir_ctx()\n")); TALLOC_FREE(frame); return NULL; - + } - + if (dir->file != False) { /* FIXME, should be dir, perhaps */ - + errno = ENOTDIR; DEBUG(0, ("Found file vs directory in SMBC_readdir_ctx()\n")); TALLOC_FREE(frame); return NULL; - + } - + if (!dir->dir_next) { TALLOC_FREE(frame); return NULL; } - + dirent = dir->dir_next->dirent; if (!dirent) { - + errno = ENOENT; TALLOC_FREE(frame); return NULL; - + } - + dirp = (struct smbc_dirent *)context->internal->dirent; maxlen = (sizeof(context->internal->dirent) - sizeof(struct smbc_dirent)); - + smbc_readdir_internal(context, dirp, dirent, maxlen); - + dir->dir_next = dir->dir_next->next; - + TALLOC_FREE(frame); return dirp; } @@ -988,98 +997,99 @@ SMBC_getdents_ctx(SMBCCTX *context, char *ndir = (char *)dirp; struct smbc_dir_list *dirlist; TALLOC_CTX *frame = talloc_stackframe(); - + /* Check that all is ok first ... */ - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { - + errno = EBADF; TALLOC_FREE(frame); return -1; - + } - + if (dir->file != False) { /* FIXME, should be dir, perhaps */ - + errno = ENOTDIR; TALLOC_FREE(frame); return -1; - + } - + /* * Now, retrieve the number of entries that will fit in what was passed * We have to figure out if the info is in the list, or we need to * send a request to the server to get the info. */ - + while ((dirlist = dir->dir_next)) { struct smbc_dirent *dirent; - + if (!dirlist->dirent) { - + errno = ENOENT; /* Bad error */ TALLOC_FREE(frame); return -1; - + } - + /* Do urlencoding of next entry, if so selected */ dirent = (struct smbc_dirent *)context->internal->dirent; maxlen = (sizeof(context->internal->dirent) - sizeof(struct smbc_dirent)); - smbc_readdir_internal(context, dirent, dirlist->dirent, maxlen); - + smbc_readdir_internal(context, dirent, + dirlist->dirent, maxlen); + reqd = dirent->dirlen; - + if (rem < reqd) { - + if (rem < count) { /* We managed to copy something */ - + errno = 0; TALLOC_FREE(frame); return count - rem; - + } else { /* Nothing copied ... */ - + errno = EINVAL; /* Not enough space ... */ TALLOC_FREE(frame); return -1; - + } - + } - + memcpy(ndir, dirent, reqd); /* Copy the data in ... */ - + ((struct smbc_dirent *)ndir)->comment = (char *)(&((struct smbc_dirent *)ndir)->name + dirent->namelen + 1); - + ndir += reqd; - + rem -= reqd; - + dir->dir_next = dirlist = dirlist -> next; } - + TALLOC_FREE(frame); - + if (rem == count) return 0; else return count - rem; - + } /* @@ -1101,36 +1111,36 @@ SMBC_mkdir_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 (!fname) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + DEBUG(4, ("smbc_mkdir(%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) { @@ -1139,37 +1149,37 @@ SMBC_mkdir_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 */ - + } - + /*d_printf(">>>mkdir: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", srv->cli, path, - &targetcli, &targetpath)) { + &targetcli, &targetpath)) { d_printf("Could not resolve %s\n", path); TALLOC_FREE(frame); return -1; } /*d_printf(">>>mkdir: resolved path as %s\n", targetpath);*/ - + if (!cli_mkdir(targetcli, targetpath)) { - + errno = SMBC_errno(context, targetcli); TALLOC_FREE(frame); return -1; - + } - + TALLOC_FREE(frame); return 0; - + } /* @@ -1208,36 +1218,36 @@ SMBC_rmdir_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 (!fname) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + DEBUG(4, ("smbc_rmdir(%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) { @@ -1246,38 +1256,38 @@ SMBC_rmdir_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 */ - + } - + /*d_printf(">>>rmdir: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", srv->cli, path, - &targetcli, &targetpath)) { + &targetcli, &targetpath)) { d_printf("Could not resolve %s\n", path); TALLOC_FREE(frame); return -1; } /*d_printf(">>>rmdir: resolved path as %s\n", targetpath);*/ - - + + if (!cli_rmdir(targetcli, targetpath)) { - + errno = SMBC_errno(context, targetcli); - + if (errno == EACCES) { /* Check if the dir empty or not */ - + /* Local storage to avoid buffer overflows */ char *lpath; - + smbc_rmdir_dirempty = True; /* Make this so ... */ - + lpath = talloc_asprintf(frame, "%s\\*", targetpath); if (!lpath) { @@ -1285,34 +1295,34 @@ SMBC_rmdir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return -1; } - + if (cli_list(targetcli, lpath, aDIR | aSYSTEM | aHIDDEN, rmdir_list_fn, NULL) < 0) { - + /* Fix errno to ignore latest error ... */ DEBUG(5, ("smbc_rmdir: " "cli_list returned an error: %d\n", SMBC_errno(context, targetcli))); errno = EACCES; - + } - + if (smbc_rmdir_dirempty) errno = EACCES; else errno = ENOTEMPTY; - + } - + TALLOC_FREE(frame); return -1; - + } - + TALLOC_FREE(frame); return 0; - + } /* @@ -1324,38 +1334,38 @@ SMBC_telldir_ctx(SMBCCTX *context, SMBCFILE *dir) { TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { - + errno = EBADF; TALLOC_FREE(frame); return -1; - + } - + if (dir->file != False) { /* FIXME, should be dir, perhaps */ - + errno = ENOTDIR; TALLOC_FREE(frame); return -1; - + } - + /* See if we're already at the end. */ if (dir->dir_next == NULL) { /* We are. */ TALLOC_FREE(frame); return -1; } - + /* * We return the pointer here as the offset */ @@ -1369,28 +1379,28 @@ SMBC_telldir_ctx(SMBCCTX *context, static struct smbc_dir_list * check_dir_ent(struct smbc_dir_list *list, - struct smbc_dirent *dirent) + struct smbc_dirent *dirent) { - + /* Run down the list looking for what we want */ - + if (dirent) { - + struct smbc_dir_list *tmp = list; - + while (tmp) { - + if (tmp->dirent == dirent) return tmp; - + tmp = tmp->next; - + } - + } - + return NULL; /* Not found, or an error */ - + } @@ -1407,50 +1417,50 @@ SMBC_lseekdir_ctx(SMBCCTX *context, struct smbc_dirent *dirent = (struct smbc_dirent *)l_offset; struct smbc_dir_list *list_ent = (struct smbc_dir_list *)NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + if (dir->file != False) { /* FIXME, should be dir, perhaps */ - + errno = ENOTDIR; TALLOC_FREE(frame); return -1; - + } - + /* Now, check what we were passed and see if it is OK ... */ - + if (dirent == NULL) { /* Seek to the begining of the list */ - + dir->dir_next = dir->dir_list; TALLOC_FREE(frame); return 0; - + } - + if (offset == -1) { /* Seek to the end of the list */ dir->dir_next = NULL; TALLOC_FREE(frame); return 0; } - + /* Now, run down the list and make sure that the entry is OK */ /* This may need to be changed if we change the format of the list */ - + if ((list_ent = check_dir_ent(dir->dir_list, dirent)) == NULL) { errno = EINVAL; /* Bad entry */ TALLOC_FREE(frame); return -1; } - + dir->dir_next = list_ent; - + TALLOC_FREE(frame); return 0; } @@ -1464,13 +1474,13 @@ SMBC_fstatdir_ctx(SMBCCTX *context, SMBCFILE *dir, struct stat *st) { - + if (!context || !context->internal->initialized) { - + errno = EINVAL; return -1; } - + /* No code yet ... */ return 0; } @@ -1489,37 +1499,37 @@ SMBC_chmod_ctx(SMBCCTX *context, char *path = NULL; uint16 mode; 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_chmod(%s, 0%3o)\n", fname, newmode)); - + 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) { @@ -1528,28 +1538,28 @@ SMBC_chmod_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 */ } - + mode = 0; - + if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY; if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH; if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM; if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN; - + if (!cli_setatr(srv->cli, path, mode, 0)) { errno = SMBC_errno(context, srv->cli); TALLOC_FREE(frame); return -1; } - + TALLOC_FREE(frame); return 0; } @@ -1569,63 +1579,63 @@ SMBC_utimes_ctx(SMBCCTX *context, time_t access_time; time_t write_time; 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; } - + if (tbuf == NULL) { access_time = write_time = time(NULL); } else { access_time = tbuf[0].tv_sec; write_time = tbuf[1].tv_sec; } - + if (DEBUGLVL(4)) { char *p; char atimebuf[32]; char mtimebuf[32]; - + strncpy(atimebuf, ctime(&access_time), sizeof(atimebuf) - 1); atimebuf[sizeof(atimebuf) - 1] = '\0'; if ((p = strchr(atimebuf, '\n')) != NULL) { *p = '\0'; } - + strncpy(mtimebuf, ctime(&write_time), sizeof(mtimebuf) - 1); mtimebuf[sizeof(mtimebuf) - 1] = '\0'; if ((p = strchr(mtimebuf, '\n')) != NULL) { *p = '\0'; } - + dbgtext("smbc_utimes(%s, atime = %s mtime = %s)\n", fname, atimebuf, mtimebuf); } - + 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) { @@ -1634,21 +1644,21 @@ SMBC_utimes_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_setatr(context, srv, path, 0, access_time, write_time, 0, 0)) { TALLOC_FREE(frame); return -1; /* errno set by SMBC_setatr */ } - + TALLOC_FREE(frame); return 0; } @@ -1661,43 +1671,47 @@ int SMBC_unlink_ctx(SMBCCTX *context, const char *fname) { - 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; SMBCSRV *srv = NULL; 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; - + } - + 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) { @@ -1706,31 +1720,31 @@ SMBC_unlink_ctx(SMBCCTX *context, return -1; } } - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { TALLOC_FREE(frame); return -1; /* SMBC_server sets errno */ - + } - + /*d_printf(">>>unlink: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", srv->cli, path, - &targetcli, &targetpath)) { + &targetcli, &targetpath)) { d_printf("Could not resolve %s\n", path); TALLOC_FREE(frame); return -1; } /*d_printf(">>>unlink: resolved path as %s\n", targetpath);*/ - + if (!cli_unlink(targetcli, targetpath)) { - + errno = SMBC_errno(context, targetcli); - + if (errno == EACCES) { /* Check if the file is a directory */ - + int saverr = errno; SMB_OFF_T size = 0; uint16 mode = 0; @@ -1738,39 +1752,39 @@ SMBC_unlink_ctx(SMBCCTX *context, struct timespec access_time_ts; struct timespec change_time_ts; SMB_INO_T ino = 0; - + if (!SMBC_getatr(context, srv, path, &mode, &size, NULL, &access_time_ts, &write_time_ts, &change_time_ts, &ino)) { - + /* Hmmm, bad error ... What? */ - + errno = SMBC_errno(context, targetcli); TALLOC_FREE(frame); return -1; - + } else { - + if (IS_DOS_DIR(mode)) errno = EISDIR; else errno = saverr; /* Restore this */ - + } } - + TALLOC_FREE(frame); return -1; - + } - + TALLOC_FREE(frame); return 0; /* Success ... */ - + } /* @@ -1800,39 +1814,39 @@ SMBC_rename_ctx(SMBCCTX *ocontext, struct cli_state *targetcli2 = NULL; SMBCSRV *srv = NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!ocontext || !ncontext || !ocontext->internal->initialized || !ncontext->internal->initialized) { - + errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); return -1; } - + if (!oname || !nname) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + DEBUG(4, ("smbc_rename(%s,%s)\n", oname, nname)); - + if (SMBC_parse_path(frame, - ocontext, - oname, - &workgroup, - &server1, - &share1, - &path1, - &user1, - &password1, - NULL)) { + ocontext, + oname, + &workgroup, + &server1, + &share1, + &path1, + &user1, + &password1, + NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!user1 || user1[0] == (char)0) { user1 = talloc_strdup(frame, ocontext->config.user); if (!user1) { @@ -1841,22 +1855,22 @@ SMBC_rename_ctx(SMBCCTX *ocontext, return -1; } } - + if (SMBC_parse_path(frame, - ncontext, - nname, - NULL, - &server2, - &share2, - &path2, - &user2, - &password2, - NULL)) { + ncontext, + nname, + NULL, + &server2, + &share2, + &path2, + &user2, + &password2, + NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!user2 || user2[0] == (char)0) { user2 = talloc_strdup(frame, ncontext->config.user); if (!user2) { @@ -1865,7 +1879,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, return -1; } } - + if (strcmp(server1, server2) || strcmp(share1, share2) || strcmp(user1, user2)) { /* Can't rename across file systems, or users?? */ @@ -1873,18 +1887,18 @@ SMBC_rename_ctx(SMBCCTX *ocontext, TALLOC_FREE(frame); return -1; } - + srv = SMBC_server(frame, ocontext, True, server1, share1, &workgroup, &user1, &password1); if (!srv) { TALLOC_FREE(frame); return -1; - + } - + /*d_printf(">>>rename: resolving %s\n", path1);*/ if (!cli_resolve_path(frame, "", srv->cli, path1, - &targetcli1, &targetpath1)) { + &targetcli1, &targetpath1)) { d_printf("Could not resolve %s\n", path1); TALLOC_FREE(frame); return -1; @@ -1892,13 +1906,13 @@ SMBC_rename_ctx(SMBCCTX *ocontext, /*d_printf(">>>rename: resolved path as %s\n", targetpath1);*/ /*d_printf(">>>rename: resolving %s\n", path2);*/ if (!cli_resolve_path(frame, "", srv->cli, path2, - &targetcli2, &targetpath2)) { + &targetcli2, &targetpath2)) { d_printf("Could not resolve %s\n", path2); TALLOC_FREE(frame); return -1; } /*d_printf(">>>rename: resolved path as %s\n", targetpath2);*/ - + if (strcmp(targetcli1->desthost, targetcli2->desthost) || strcmp(targetcli1->share, targetcli2->share)) { @@ -1907,21 +1921,21 @@ SMBC_rename_ctx(SMBCCTX *ocontext, TALLOC_FREE(frame); return -1; } - + if (!cli_rename(targetcli1, targetpath1, targetpath2)) { int eno = SMBC_errno(ocontext, targetcli1); - + if (eno != EEXIST || !cli_unlink(targetcli1, targetpath2) || !cli_rename(targetcli1, targetpath1, targetpath2)) { - + errno = eno; TALLOC_FREE(frame); return -1; - + } } - + TALLOC_FREE(frame); return 0; /* Success */ } diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c index 62b990ed00..73c9b96978 100644 --- a/source3/libsmb/libsmb_file.c +++ b/source3/libsmb/libsmb_file.c @@ -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; - + } diff --git a/source3/libsmb/libsmb_misc.c b/source3/libsmb/libsmb_misc.c index f2fd919ef6..dd7add5a61 100644 --- a/source3/libsmb/libsmb_misc.c +++ b/source3/libsmb/libsmb_misc.c @@ -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; } diff --git a/source3/libsmb/libsmb_path.c b/source3/libsmb/libsmb_path.c index 6706a59ba8..c962f898e0 100644 --- a/source3/libsmb/libsmb_path.c +++ b/source3/libsmb/libsmb_path.c @@ -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; } diff --git a/source3/libsmb/libsmb_printjob.c b/source3/libsmb/libsmb_printjob.c index a03c15e024..545225cae4 100644 --- a/source3/libsmb/libsmb_printjob.c +++ b/source3/libsmb/libsmb_printjob.c @@ -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; - + } diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 70e0d57273..4f51388870 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -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; } diff --git a/source3/libsmb/libsmb_stat.c b/source3/libsmb/libsmb_stat.c index 6072547e08..b733eab74f 100644 --- a/source3/libsmb/libsmb_stat.c +++ b/source3/libsmb/libsmb_stat.c @@ -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; - + } diff --git a/source3/libsmb/libsmb_xattr.c b/source3/libsmb/libsmb_xattr.c index a420299341..3c08412d59 100644 --- a/source3/libsmb/libsmb_xattr.c +++ b/source3/libsmb/libsmb_xattr.c @@ -34,16 +34,16 @@ static struct rpc_pipe_client * find_lsa_pipe_hnd(struct cli_state *ipc_cli) { struct rpc_pipe_client *pipe_hnd; - + for (pipe_hnd = ipc_cli->pipe_list; pipe_hnd; pipe_hnd = pipe_hnd->next) { - + if (pipe_hnd->pipe_idx == PI_LSARPC) { return pipe_hnd; } } - + return NULL; } @@ -59,19 +59,19 @@ ace_compare(SEC_ACE *ace1, { bool b1; bool b2; - + /* If the ACEs are equal, we have nothing more to do. */ if (sec_ace_equal(ace1, ace2)) { return 0; } - + /* Inherited follow non-inherited */ b1 = ((ace1->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0); b2 = ((ace2->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0); if (b1 != b2) { return (b1 ? 1 : -1); } - + /* * What shall we do with AUDITs and ALARMs? It's undefined. We'll * sort them after DENY and ALLOW. @@ -87,7 +87,7 @@ ace_compare(SEC_ACE *ace1, if (b1 != b2) { return (b1 ? 1 : -1); } - + /* Allowed ACEs follow denied ACEs */ b1 = (ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED || ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT); @@ -96,7 +96,7 @@ ace_compare(SEC_ACE *ace1, if (b1 != b2) { return (b1 ? 1 : -1); } - + /* * ACEs applying to an entity's object follow those applying to the * entity itself @@ -108,34 +108,34 @@ ace_compare(SEC_ACE *ace1, if (b1 != b2) { return (b1 ? 1 : -1); } - + /* * If we get this far, the ACEs are similar as far as the * characteristics we typically care about (those defined by the * referenced MS document). We'll now sort by characteristics that * just seems reasonable. */ - + if (ace1->type != ace2->type) { return ace2->type - ace1->type; } - + if (sid_compare(&ace1->trustee, &ace2->trustee)) { return sid_compare(&ace1->trustee, &ace2->trustee); } - + if (ace1->flags != ace2->flags) { return ace1->flags - ace2->flags; } - + if (ace1->access_mask != ace2->access_mask) { return ace1->access_mask - ace2->access_mask; } - + if (ace1->size != ace2->size) { return ace1->size - ace2->size; } - + return memcmp(ace1, ace2, sizeof(SEC_ACE)); } @@ -145,10 +145,10 @@ sort_acl(SEC_ACL *the_acl) { uint32 i; if (!the_acl) return; - + qsort(the_acl->aces, the_acl->num_aces, sizeof(the_acl->aces[0]), QSORT_CAST ace_compare); - + for (i=1;inum_aces;) { if (sec_ace_equal(&the_acl->aces[i-1], &the_acl->aces[i])) { int j; @@ -175,32 +175,32 @@ convert_sid_to_string(struct cli_state *ipc_cli, enum lsa_SidType *types = NULL; struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli); TALLOC_CTX *ctx; - + sid_to_fstring(str, sid); - + if (numeric) { return; /* no lookup desired */ } - + if (!pipe_hnd) { return; } - + /* Ask LSA to convert the sid to a name */ - + ctx = talloc_stackframe(); - + if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(pipe_hnd, ctx, - pol, 1, sid, &domains, - &names, &types)) || + pol, 1, sid, &domains, + &names, &types)) || !domains || !domains[0] || !names || !names[0]) { TALLOC_FREE(ctx); return; } - + TALLOC_FREE(ctx); /* Converted OK */ - + slprintf(str, sizeof(fstring) - 1, "%s%s%s", domains[0], lp_winbind_separator(), names[0]); @@ -219,31 +219,32 @@ convert_string_to_sid(struct cli_state *ipc_cli, bool result = True; TALLOC_CTX *ctx = NULL; struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli); - + if (!pipe_hnd) { return False; } - + if (numeric) { if (strncmp(str, "S-", 2) == 0) { return string_to_sid(sid, str); } - + result = False; goto done; } - + ctx = talloc_stackframe(); if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_names(pipe_hnd, ctx, - pol, 1, &str, NULL, 1, &sids, - &types))) { + pol, 1, &str, + NULL, 1, &sids, + &types))) { result = False; goto done; } - + sid_copy(sid, &sids[0]); - done: - +done: + TALLOC_FREE(ctx); return result; } @@ -271,7 +272,7 @@ parse_ace(struct cli_state *ipc_cli, uint32 mask; }; TALLOC_CTX *frame = talloc_stackframe(); - + /* These values discovered by inspection */ static const struct perm_value special_values[] = { { "R", 0x00120089 }, @@ -282,15 +283,15 @@ parse_ace(struct cli_state *ipc_cli, { "O", 0x00080000 }, { NULL, 0 }, }; - + static const struct perm_value standard_values[] = { { "READ", 0x001200a9 }, { "CHANGE", 0x001301bf }, { "FULL", 0x001f01ff }, { NULL, 0 }, }; - - + + ZERO_STRUCTP(ace); p = strchr_m(str,':'); if (!p) { @@ -300,25 +301,25 @@ parse_ace(struct cli_state *ipc_cli, *p = '\0'; p++; /* Try to parse numeric form */ - + if (sscanf(p, "%i/%i/%i", &atype, &aflags, &amask) == 3 && convert_string_to_sid(ipc_cli, pol, numeric, &sid, str)) { goto done; } - + /* Try to parse text form */ - + if (!convert_string_to_sid(ipc_cli, pol, numeric, &sid, str)) { TALLOC_FREE(frame); return false; } - + cp = p; if (!next_token_talloc(frame, &cp, &tok, "/")) { TALLOC_FREE(frame); return false; } - + if (StrnCaseCmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) { atype = SEC_ACE_TYPE_ACCESS_ALLOWED; } else if (StrnCaseCmp(tok, "DENIED", strlen("DENIED")) == 0) { @@ -327,20 +328,20 @@ parse_ace(struct cli_state *ipc_cli, TALLOC_FREE(frame); return false; } - + /* Only numeric form accepted for flags at present */ - + if (!(next_token_talloc(frame, &cp, &tok, "/") && sscanf(tok, "%i", &aflags))) { TALLOC_FREE(frame); return false; } - + if (!next_token_talloc(frame, &cp, &tok, "/")) { TALLOC_FREE(frame); return false; } - + if (strncmp(tok, "0x", 2) == 0) { if (sscanf(tok, "%i", &amask) != 1) { TALLOC_FREE(frame); @@ -348,39 +349,39 @@ parse_ace(struct cli_state *ipc_cli, } goto done; } - + for (v = standard_values; v->perm; v++) { if (strcmp(tok, v->perm) == 0) { amask = v->mask; goto done; } } - + p = tok; - + while(*p) { bool found = False; - + for (v = special_values; v->perm; v++) { if (v->perm[0] == *p) { amask |= v->mask; found = True; } } - + if (!found) { TALLOC_FREE(frame); return false; } p++; } - + if (*p) { TALLOC_FREE(frame); return false; } - - done: + +done: mask = amask; init_sec_ace(ace, &sid, atype, mask, aflags); TALLOC_FREE(frame); @@ -395,13 +396,14 @@ add_ace(SEC_ACL **the_acl, { SEC_ACL *newacl; SEC_ACE *aces; - + if (! *the_acl) { (*the_acl) = make_sec_acl(ctx, 3, 1, ace); return True; } - - if ((aces = SMB_CALLOC_ARRAY(SEC_ACE, 1+(*the_acl)->num_aces)) == NULL) { + + if ((aces = SMB_CALLOC_ARRAY(SEC_ACE, + 1+(*the_acl)->num_aces)) == NULL) { return False; } memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(SEC_ACE)); @@ -430,17 +432,17 @@ sec_desc_parse(TALLOC_CTX *ctx, DOM_SID *owner_sid=NULL; SEC_ACL *dacl=NULL; int revision=1; - + while (next_token_talloc(ctx, &p, &tok, "\t,\r\n")) { - + if (StrnCaseCmp(tok,"REVISION:", 9) == 0) { revision = strtol(tok+9, NULL, 16); continue; } - + if (StrnCaseCmp(tok,"OWNER:", 6) == 0) { if (owner_sid) { - DEBUG(5, ("OWNER specified more than once!\n")); + DEBUG(5,("OWNER specified more than once!\n")); goto done; } owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1); @@ -453,10 +455,10 @@ sec_desc_parse(TALLOC_CTX *ctx, } continue; } - + if (StrnCaseCmp(tok,"OWNER+:", 7) == 0) { if (owner_sid) { - DEBUG(5, ("OWNER specified more than once!\n")); + DEBUG(5,("OWNER specified more than once!\n")); goto done; } owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1); @@ -469,10 +471,10 @@ sec_desc_parse(TALLOC_CTX *ctx, } continue; } - + if (StrnCaseCmp(tok,"GROUP:", 6) == 0) { if (group_sid) { - DEBUG(5, ("GROUP specified more than once!\n")); + DEBUG(5,("GROUP specified more than once!\n")); goto done; } group_sid = SMB_CALLOC_ARRAY(DOM_SID, 1); @@ -485,10 +487,10 @@ sec_desc_parse(TALLOC_CTX *ctx, } continue; } - + if (StrnCaseCmp(tok,"GROUP+:", 7) == 0) { if (group_sid) { - DEBUG(5, ("GROUP specified more than once!\n")); + DEBUG(5,("GROUP specified more than once!\n")); goto done; } group_sid = SMB_CALLOC_ARRAY(DOM_SID, 1); @@ -501,7 +503,7 @@ sec_desc_parse(TALLOC_CTX *ctx, } continue; } - + if (StrnCaseCmp(tok,"ACL:", 4) == 0) { SEC_ACE ace; if (!parse_ace(ipc_cli, pol, &ace, numeric, tok+4)) { @@ -514,7 +516,7 @@ sec_desc_parse(TALLOC_CTX *ctx, } continue; } - + if (StrnCaseCmp(tok,"ACL+:", 5) == 0) { SEC_ACE ace; if (!parse_ace(ipc_cli, pol, &ace, False, tok+5)) { @@ -527,18 +529,18 @@ sec_desc_parse(TALLOC_CTX *ctx, } continue; } - + DEBUG(5, ("Failed to parse security descriptor\n")); goto done; } - + ret = make_sec_desc(ctx, revision, SEC_DESC_SELF_RELATIVE, owner_sid, group_sid, NULL, dacl, &sd_size); - - done: + +done: SAFE_FREE(group_sid); SAFE_FREE(owner_sid); - + return ret; } @@ -558,13 +560,13 @@ dos_attr_query(SMBCCTX *context, uint16 mode = 0; SMB_INO_T inode = 0; DOS_ATTR_DESC *ret; - + ret = TALLOC_P(ctx, DOS_ATTR_DESC); if (!ret) { errno = ENOMEM; return NULL; } - + /* Obtain the DOS attributes */ if (!SMBC_getatr(context, srv, CONST_DISCARD(char *, filename), &mode, &size, @@ -577,7 +579,7 @@ dos_attr_query(SMBCCTX *context, DEBUG(5, ("dos_attr_query Failed to query old attributes\n")); return NULL; } - + ret->mode = mode; ret->size = size; ret->create_time = convert_timespec_to_time_t(create_time_ts); @@ -585,7 +587,7 @@ dos_attr_query(SMBCCTX *context, ret->write_time = convert_timespec_to_time_t(write_time_ts); ret->change_time = convert_timespec_to_time_t(change_time_ts); ret->inode = inode; - + return ret; } @@ -607,7 +609,7 @@ dos_attr_parse(SMBCCTX *context, const char * write_time_attr; const char * change_time_attr; } attr_strings; - + /* Determine whether to use old-style or new-style attribute names */ if (context->internal->full_time_names) { /* new-style names */ @@ -622,7 +624,7 @@ dos_attr_parse(SMBCCTX *context, attr_strings.write_time_attr = "M_TIME"; attr_strings.change_time_attr = "C_TIME"; } - + /* if this is to set the entire ACL... */ if (*str == '*') { /* ... then increment past the first colon if there is one */ @@ -632,7 +634,7 @@ dos_attr_parse(SMBCCTX *context, p = str; } } - + frame = talloc_stackframe(); while (next_token_talloc(frame, &p, &tok, "\t,\r\n")) { if (StrnCaseCmp(tok, "MODE:", 5) == 0) { @@ -647,30 +649,30 @@ dos_attr_parse(SMBCCTX *context, } continue; } - + if (StrnCaseCmp(tok, "SIZE:", 5) == 0) { dad->size = (SMB_OFF_T)atof(tok+5); continue; } - + n = strlen(attr_strings.access_time_attr); if (StrnCaseCmp(tok, attr_strings.access_time_attr, n) == 0) { dad->access_time = (time_t)strtol(tok+n+1, NULL, 10); continue; } - + n = strlen(attr_strings.change_time_attr); if (StrnCaseCmp(tok, attr_strings.change_time_attr, n) == 0) { dad->change_time = (time_t)strtol(tok+n+1, NULL, 10); continue; } - + n = strlen(attr_strings.write_time_attr); if (StrnCaseCmp(tok, attr_strings.write_time_attr, n) == 0) { dad->write_time = (time_t)strtol(tok+n+1, NULL, 10); continue; } - + if (attr_strings.create_time_attr != NULL) { n = strlen(attr_strings.create_time_attr); if (StrnCaseCmp(tok, attr_strings.create_time_attr, @@ -680,7 +682,7 @@ dos_attr_parse(SMBCCTX *context, continue; } } - + if (StrnCaseCmp(tok, "INODE:", 6) == 0) { dad->inode = (SMB_INO_T)atof(tok+6); continue; @@ -757,7 +759,7 @@ cacl_get(SMBCCTX *context, const char * write_time_attr; const char * change_time_attr; } excl_attr_strings; - + /* Determine whether to use old-style or new-style attribute names */ if (context->internal->full_time_names) { /* new-style names */ @@ -765,7 +767,7 @@ cacl_get(SMBCCTX *context, attr_strings.access_time_attr = "ACCESS_TIME"; attr_strings.write_time_attr = "WRITE_TIME"; attr_strings.change_time_attr = "CHANGE_TIME"; - + excl_attr_strings.create_time_attr = "CREATE_TIME"; excl_attr_strings.access_time_attr = "ACCESS_TIME"; excl_attr_strings.write_time_attr = "WRITE_TIME"; @@ -776,28 +778,28 @@ cacl_get(SMBCCTX *context, attr_strings.access_time_attr = "A_TIME"; attr_strings.write_time_attr = "M_TIME"; attr_strings.change_time_attr = "C_TIME"; - + excl_attr_strings.create_time_attr = NULL; excl_attr_strings.access_time_attr = "dos_attr.A_TIME"; excl_attr_strings.write_time_attr = "dos_attr.M_TIME"; excl_attr_strings.change_time_attr = "dos_attr.C_TIME"; } - + /* Copy name so we can strip off exclusions (if any are specified) */ strncpy(name_sandbox, attr_name, sizeof(name_sandbox) - 1); - + /* Ensure name is null terminated */ name_sandbox[sizeof(name_sandbox) - 1] = '\0'; - + /* Play in the sandbox */ name = name_sandbox; - + /* If there are any exclusions, point to them and mask them from name */ if ((pExclude = strchr(name, '!')) != NULL) { *pExclude++ = '\0'; } - + all = (StrnCaseCmp(name, "system.*", 8) == 0); all_nt = (StrnCaseCmp(name, "system.nt_sec_desc.*", 20) == 0); all_nt_acls = (StrnCaseCmp(name, "system.nt_sec_desc.acl.*", 24) == 0); @@ -805,71 +807,77 @@ cacl_get(SMBCCTX *context, some_nt = (StrnCaseCmp(name, "system.nt_sec_desc.", 19) == 0); some_dos = (StrnCaseCmp(name, "system.dos_attr.", 16) == 0); numeric = (* (name + strlen(name) - 1) != '+'); - + /* Look for exclusions from "all" requests */ if (all || all_nt || all_dos) { - + /* Exclusions are delimited by '!' */ for (; pExclude != NULL; pExclude = (p == NULL ? NULL : p + 1)) { - - /* Find end of this exclusion name */ - if ((p = strchr(pExclude, '!')) != NULL) - { - *p = '\0'; - } - - /* Which exclusion name is this? */ - if (StrCaseCmp(pExclude, "nt_sec_desc.revision") == 0) { - exclude_nt_revision = True; - } - else if (StrCaseCmp(pExclude, "nt_sec_desc.owner") == 0) { - exclude_nt_owner = True; - } - else if (StrCaseCmp(pExclude, "nt_sec_desc.group") == 0) { - exclude_nt_group = True; - } - else if (StrCaseCmp(pExclude, "nt_sec_desc.acl") == 0) { - exclude_nt_acl = True; - } - else if (StrCaseCmp(pExclude, "dos_attr.mode") == 0) { - exclude_dos_mode = True; - } - else if (StrCaseCmp(pExclude, "dos_attr.size") == 0) { - exclude_dos_size = True; - } - else if (excl_attr_strings.create_time_attr != NULL && - StrCaseCmp(pExclude, - excl_attr_strings.change_time_attr) == 0) { - exclude_dos_create_time = True; - } - else if (StrCaseCmp(pExclude, - excl_attr_strings.access_time_attr) == 0) { - exclude_dos_access_time = True; - } - else if (StrCaseCmp(pExclude, - excl_attr_strings.write_time_attr) == 0) { - exclude_dos_write_time = True; - } - else if (StrCaseCmp(pExclude, - excl_attr_strings.change_time_attr) == 0) { - exclude_dos_change_time = True; - } - else if (StrCaseCmp(pExclude, "dos_attr.inode") == 0) { - exclude_dos_inode = True; - } - else { - DEBUG(5, ("cacl_get received unknown exclusion: %s\n", - pExclude)); - errno = ENOATTR; - return -1; + + /* Find end of this exclusion name */ + if ((p = strchr(pExclude, '!')) != NULL) + { + *p = '\0'; + } + + /* Which exclusion name is this? */ + if (StrCaseCmp(pExclude, + "nt_sec_desc.revision") == 0) { + exclude_nt_revision = True; + } + else if (StrCaseCmp(pExclude, + "nt_sec_desc.owner") == 0) { + exclude_nt_owner = True; + } + else if (StrCaseCmp(pExclude, + "nt_sec_desc.group") == 0) { + exclude_nt_group = True; + } + else if (StrCaseCmp(pExclude, + "nt_sec_desc.acl") == 0) { + exclude_nt_acl = True; + } + else if (StrCaseCmp(pExclude, + "dos_attr.mode") == 0) { + exclude_dos_mode = True; + } + else if (StrCaseCmp(pExclude, + "dos_attr.size") == 0) { + exclude_dos_size = True; + } + else if (excl_attr_strings.create_time_attr != NULL && + StrCaseCmp(pExclude, + excl_attr_strings.change_time_attr) == 0) { + exclude_dos_create_time = True; + } + else if (StrCaseCmp(pExclude, + excl_attr_strings.access_time_attr) == 0) { + exclude_dos_access_time = True; + } + else if (StrCaseCmp(pExclude, + excl_attr_strings.write_time_attr) == 0) { + exclude_dos_write_time = True; + } + else if (StrCaseCmp(pExclude, + excl_attr_strings.change_time_attr) == 0) { + exclude_dos_change_time = True; + } + else if (StrCaseCmp(pExclude, "dos_attr.inode") == 0) { + exclude_dos_inode = True; + } + else { + DEBUG(5, ("cacl_get received unknown exclusion: %s\n", + pExclude)); + errno = ENOATTR; + return -1; + } } - } } - + n_used = 0; - + /* * If we are (possibly) talking to an NT or new system and some NT * attributes have been requested... @@ -877,28 +885,28 @@ cacl_get(SMBCCTX *context, if (ipc_cli && (all || some_nt || all_nt_acls)) { /* Point to the portion after "system.nt_sec_desc." */ name += 19; /* if (all) this will be invalid but unused */ - + /* ... then obtain any NT attributes which were requested */ fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ); - + if (fnum == -1) { DEBUG(5, ("cacl_get failed to open %s: %s\n", filename, cli_errstr(cli))); errno = 0; return -1; } - + sd = cli_query_secdesc(cli, fnum, ctx); - + if (!sd) { DEBUG(5, ("cacl_get Failed to query old descriptor\n")); errno = 0; return -1; } - + cli_close(cli, fnum); - + if (! exclude_nt_revision) { if (all || all_nt) { if (determine_size) { @@ -929,7 +937,7 @@ cacl_get(SMBCCTX *context, sd->revision); } } - + if (!determine_size && n > bufsize) { errno = ERANGE; return -1; @@ -939,7 +947,7 @@ cacl_get(SMBCCTX *context, bufsize -= n; n = 0; } - + if (! exclude_nt_owner) { /* Get owner and group sid */ if (sd->owner_sid) { @@ -950,7 +958,7 @@ cacl_get(SMBCCTX *context, } else { fstrcpy(sidstr, ""); } - + if (all || all_nt) { if (determine_size) { p = talloc_asprintf(ctx, ",OWNER:%s", @@ -977,7 +985,7 @@ cacl_get(SMBCCTX *context, sidstr); } } - + if (!determine_size && n > bufsize) { errno = ERANGE; return -1; @@ -987,7 +995,7 @@ cacl_get(SMBCCTX *context, bufsize -= n; n = 0; } - + if (! exclude_nt_group) { if (sd->group_sid) { convert_sid_to_string(ipc_cli, pol, @@ -996,7 +1004,7 @@ cacl_get(SMBCCTX *context, } else { fstrcpy(sidstr, ""); } - + if (all || all_nt) { if (determine_size) { p = talloc_asprintf(ctx, ",GROUP:%s", @@ -1023,7 +1031,7 @@ cacl_get(SMBCCTX *context, "%s", sidstr); } } - + if (!determine_size && n > bufsize) { errno = ERANGE; return -1; @@ -1033,16 +1041,16 @@ cacl_get(SMBCCTX *context, bufsize -= n; n = 0; } - + if (! exclude_nt_acl) { /* Add aces to value buffer */ for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) { - + SEC_ACE *ace = &sd->dacl->aces[i]; convert_sid_to_string(ipc_cli, pol, sidstr, numeric, &ace->trustee); - + if (all || all_nt) { if (determine_size) { p = talloc_asprintf( @@ -1125,15 +1133,15 @@ cacl_get(SMBCCTX *context, n = 0; } } - + /* Restore name pointer to its original value */ name -= 19; } - + if (all || some_dos) { /* Point to the portion after "system.dos_attr." */ name += 16; /* if (all) this will be invalid but unused */ - + /* Obtain the DOS attributes */ if (!SMBC_getatr(context, srv, filename, &mode, &size, &create_time_ts, @@ -1141,17 +1149,17 @@ cacl_get(SMBCCTX *context, &write_time_ts, &change_time_ts, &ino)) { - + errno = SMBC_errno(context, srv->cli); return -1; - + } - + create_time = convert_timespec_to_time_t(create_time_ts); access_time = convert_timespec_to_time_t(access_time_ts); write_time = convert_timespec_to_time_t(write_time_ts); change_time = convert_timespec_to_time_t(change_time_ts); - + if (! exclude_dos_mode) { if (all || all_dos) { if (determine_size) { @@ -1189,7 +1197,7 @@ cacl_get(SMBCCTX *context, "0x%x", mode); } } - + if (!determine_size && n > bufsize) { errno = ERANGE; return -1; @@ -1199,7 +1207,7 @@ cacl_get(SMBCCTX *context, bufsize -= n; n = 0; } - + if (! exclude_dos_size) { if (all || all_dos) { if (determine_size) { @@ -1234,7 +1242,7 @@ cacl_get(SMBCCTX *context, (double)size); } } - + if (!determine_size && n > bufsize) { errno = ERANGE; return -1; @@ -1244,7 +1252,7 @@ cacl_get(SMBCCTX *context, bufsize -= n; n = 0; } - + if (! exclude_dos_create_time && attr_strings.create_time_attr != NULL) { if (all || all_dos) { @@ -1277,7 +1285,7 @@ cacl_get(SMBCCTX *context, "%lu", create_time); } } - + if (!determine_size && n > bufsize) { errno = ERANGE; return -1; @@ -1287,7 +1295,7 @@ cacl_get(SMBCCTX *context, bufsize -= n; n = 0; } - + if (! exclude_dos_access_time) { if (all || all_dos) { if (determine_size) { @@ -1319,7 +1327,7 @@ cacl_get(SMBCCTX *context, "%lu", access_time); } } - + if (!determine_size && n > bufsize) { errno = ERANGE; return -1; @@ -1329,7 +1337,7 @@ cacl_get(SMBCCTX *context, bufsize -= n; n = 0; } - + if (! exclude_dos_write_time) { if (all || all_dos) { if (determine_size) { @@ -1361,7 +1369,7 @@ cacl_get(SMBCCTX *context, "%lu", write_time); } } - + if (!determine_size && n > bufsize) { errno = ERANGE; return -1; @@ -1371,7 +1379,7 @@ cacl_get(SMBCCTX *context, bufsize -= n; n = 0; } - + if (! exclude_dos_change_time) { if (all || all_dos) { if (determine_size) { @@ -1403,7 +1411,7 @@ cacl_get(SMBCCTX *context, "%lu", change_time); } } - + if (!determine_size && n > bufsize) { errno = ERANGE; return -1; @@ -1413,7 +1421,7 @@ cacl_get(SMBCCTX *context, bufsize -= n; n = 0; } - + if (! exclude_dos_inode) { if (all || all_dos) { if (determine_size) { @@ -1448,7 +1456,7 @@ cacl_get(SMBCCTX *context, (double) ino); } } - + if (!determine_size && n > bufsize) { errno = ERANGE; return -1; @@ -1458,16 +1466,16 @@ cacl_get(SMBCCTX *context, bufsize -= n; n = 0; } - + /* Restore name pointer to its original value */ name -= 16; } - + if (n_used == 0) { errno = ENOATTR; return -1; } - + return n_used; } @@ -1495,68 +1503,68 @@ cacl_set(TALLOC_CTX *ctx, int ret = 0; char *p; bool numeric = True; - + /* the_acl will be null for REMOVE_ALL operations */ if (the_acl) { numeric = ((p = strchr(the_acl, ':')) != NULL && p > the_acl && p[-1] != '+'); - + /* if this is to set the entire ACL... */ if (*the_acl == '*') { /* ... then increment past the first colon */ the_acl = p + 1; } - + sd = sec_desc_parse(ctx, ipc_cli, pol, numeric, CONST_DISCARD(char *, the_acl)); - + if (!sd) { errno = EINVAL; return -1; } } - + /* SMBC_XATTR_MODE_REMOVE_ALL is the only caller that doesn't deref sd */ - + if (!sd && (mode != SMBC_XATTR_MODE_REMOVE_ALL)) { errno = EINVAL; return -1; } - + /* The desired access below is the only one I could find that works with NT4, W2KP and Samba */ - + fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ); - + if (fnum == -1) { DEBUG(5, ("cacl_set failed to open %s: %s\n", filename, cli_errstr(cli))); errno = 0; return -1; } - + old = cli_query_secdesc(cli, fnum, ctx); - + if (!old) { DEBUG(5, ("cacl_set Failed to query old descriptor\n")); errno = 0; return -1; } - + cli_close(cli, fnum); - + switch (mode) { case SMBC_XATTR_MODE_REMOVE_ALL: old->dacl->num_aces = 0; dacl = old->dacl; break; - + case SMBC_XATTR_MODE_REMOVE: for (i=0;sd->dacl && idacl->num_aces;i++) { bool found = False; - + for (j=0;old->dacl && jdacl->num_aces;j++) { if (sec_ace_equal(&sd->dacl->aces[i], &old->dacl->aces[j])) { @@ -1571,7 +1579,7 @@ cacl_set(TALLOC_CTX *ctx, break; } } - + if (!found) { err = ENOATTR; ret = -1; @@ -1579,11 +1587,11 @@ cacl_set(TALLOC_CTX *ctx, } } break; - + case SMBC_XATTR_MODE_ADD: for (i=0;sd->dacl && idacl->num_aces;i++) { bool found = False; - + for (j=0;old->dacl && jdacl->num_aces;j++) { if (sid_equal(&sd->dacl->aces[i].trustee, &old->dacl->aces[j].trustee)) { @@ -1597,67 +1605,67 @@ cacl_set(TALLOC_CTX *ctx, found = True; } } - + if (!found && (flags & SMBC_XATTR_FLAG_REPLACE)) { err = ENOATTR; ret = -1; goto failed; } - + for (i=0;sd->dacl && idacl->num_aces;i++) { add_ace(&old->dacl, &sd->dacl->aces[i], ctx); } } dacl = old->dacl; break; - + case SMBC_XATTR_MODE_SET: old = sd; owner_sid = old->owner_sid; group_sid = old->group_sid; dacl = old->dacl; break; - + case SMBC_XATTR_MODE_CHOWN: owner_sid = sd->owner_sid; break; - + case SMBC_XATTR_MODE_CHGRP: group_sid = sd->group_sid; break; } - + /* Denied ACE entries must come before allowed ones */ sort_acl(old->dacl); - + /* Create new security descriptor and set it */ sd = make_sec_desc(ctx, old->revision, SEC_DESC_SELF_RELATIVE, owner_sid, group_sid, NULL, dacl, &sd_size); - + fnum = cli_nt_create(cli, filename, WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS); - + if (fnum == -1) { DEBUG(5, ("cacl_set failed to open %s: %s\n", filename, cli_errstr(cli))); errno = 0; return -1; } - + if (!cli_set_secdesc(cli, fnum, sd)) { DEBUG(5, ("ERROR: secdesc set failed: %s\n", cli_errstr(cli))); ret = -1; } - + /* Clean up */ - - failed: + +failed: cli_close(cli, fnum); - + if (err != 0) { errno = err; } - + return ret; } @@ -1688,38 +1696,38 @@ SMBC_setxattr_ctx(SMBCCTX *context, const char * change_time_attr; } attr_strings; 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_setxattr(%s, %s, %.*s)\n", fname, name, (int) size, (const char*)value)); - + 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) { @@ -1728,14 +1736,14 @@ SMBC_setxattr_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 (! srv->no_nt_session) { ipc_srv = SMBC_attr_server(frame, context, server, share, &workgroup, &user, &password); @@ -1745,7 +1753,7 @@ SMBC_setxattr_ctx(SMBCCTX *context, } else { ipc_srv = NULL; } - + /* * Are they asking to set the entire set of known attributes? */ @@ -1761,7 +1769,7 @@ SMBC_setxattr_ctx(SMBCCTX *context, TALLOC_FREE(frame); return -1; } - + if (ipc_srv) { ret = cacl_set(talloc_tos(), srv->cli, ipc_srv->cli, &ipc_srv->pol, path, @@ -1773,13 +1781,13 @@ SMBC_setxattr_ctx(SMBCCTX *context, } else { ret = 0; } - + /* get a DOS Attribute Descriptor with current attributes */ dad = dos_attr_query(context, talloc_tos(), path, srv); if (dad) { /* Overwrite old with new, using what was provided */ dos_attr_parse(context, dad, srv, namevalue); - + /* Set the new DOS attributes */ if (! SMBC_setatr(context, srv, path, dad->create_time, @@ -1787,12 +1795,12 @@ SMBC_setxattr_ctx(SMBCCTX *context, dad->write_time, dad->change_time, dad->mode)) { - + /* cause failure if NT failed too */ dad = NULL; } } - + /* we only fail if both NT and DOS sets failed */ if (ret < 0 && ! dad) { ret = -1; /* in case dad was null */ @@ -1800,11 +1808,11 @@ SMBC_setxattr_ctx(SMBCCTX *context, else { ret = 0; } - + TALLOC_FREE(frame); return ret; } - + /* * Are they asking to set an access control element or to set * the entire access control list? @@ -1814,12 +1822,12 @@ SMBC_setxattr_ctx(SMBCCTX *context, StrCaseCmp(name, "system.nt_sec_desc.revision") == 0 || StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 || StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) { - + /* Yup. */ char *namevalue = talloc_asprintf(talloc_tos(), "%s:%s", name+19, (const char *) value); - + if (! ipc_srv) { ret = -1; /* errno set by SMBC_server() */ } @@ -1838,18 +1846,18 @@ SMBC_setxattr_ctx(SMBCCTX *context, TALLOC_FREE(frame); return ret; } - + /* * Are they asking to set the owner? */ if (StrCaseCmp(name, "system.nt_sec_desc.owner") == 0 || StrCaseCmp(name, "system.nt_sec_desc.owner+") == 0) { - + /* Yup. */ char *namevalue = talloc_asprintf(talloc_tos(), "%s:%s", name+19, (const char *) value); - + if (! ipc_srv) { ret = -1; /* errno set by SMBC_server() */ } @@ -1864,18 +1872,18 @@ SMBC_setxattr_ctx(SMBCCTX *context, TALLOC_FREE(frame); return ret; } - + /* * Are they asking to set the group? */ if (StrCaseCmp(name, "system.nt_sec_desc.group") == 0 || StrCaseCmp(name, "system.nt_sec_desc.group+") == 0) { - + /* Yup. */ char *namevalue = talloc_asprintf(talloc_tos(), "%s:%s", name+19, (const char *) value); - + if (! ipc_srv) { /* errno set by SMBC_server() */ ret = -1; @@ -1891,7 +1899,7 @@ SMBC_setxattr_ctx(SMBCCTX *context, TALLOC_FREE(frame); return ret; } - + /* Determine whether to use old-style or new-style attribute names */ if (context->internal->full_time_names) { /* new-style names */ @@ -1906,7 +1914,7 @@ SMBC_setxattr_ctx(SMBCCTX *context, attr_strings.write_time_attr = "system.dos_attr.M_TIME"; attr_strings.change_time_attr = "system.dos_attr.C_TIME"; } - + /* * Are they asking to set a DOS attribute? */ @@ -1917,7 +1925,7 @@ SMBC_setxattr_ctx(SMBCCTX *context, StrCaseCmp(name, attr_strings.access_time_attr) == 0 || StrCaseCmp(name, attr_strings.write_time_attr) == 0 || StrCaseCmp(name, attr_strings.change_time_attr) == 0) { - + /* get a DOS Attribute Descriptor with current attributes */ dad = dos_attr_query(context, talloc_tos(), path, srv); if (dad) { @@ -1930,7 +1938,7 @@ SMBC_setxattr_ctx(SMBCCTX *context, } else { /* Overwrite old with provided new params */ dos_attr_parse(context, dad, srv, namevalue); - + /* Set the new DOS attributes */ ret2 = SMBC_setatr(context, srv, path, dad->create_time, @@ -1938,7 +1946,7 @@ SMBC_setxattr_ctx(SMBCCTX *context, dad->write_time, dad->change_time, dad->mode); - + /* ret2 has True (success) / False (failure) */ if (ret2) { ret = 0; @@ -1949,11 +1957,11 @@ SMBC_setxattr_ctx(SMBCCTX *context, } else { ret = -1; } - + TALLOC_FREE(frame); return ret; } - + /* Unsupported attribute name */ errno = EINVAL; TALLOC_FREE(frame); @@ -1983,37 +1991,37 @@ SMBC_getxattr_ctx(SMBCCTX *context, const char * change_time_attr; } attr_strings; 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_getxattr(%s, %s)\n", fname, name)); - + 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) { @@ -2022,14 +2030,14 @@ SMBC_getxattr_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 (! srv->no_nt_session) { ipc_srv = SMBC_attr_server(frame, context, server, share, &workgroup, &user, &password); @@ -2039,7 +2047,7 @@ SMBC_getxattr_ctx(SMBCCTX *context, } else { ipc_srv = NULL; } - + /* Determine whether to use old-style or new-style attribute names */ if (context->internal->full_time_names) { /* new-style names */ @@ -2054,7 +2062,7 @@ SMBC_getxattr_ctx(SMBCCTX *context, attr_strings.write_time_attr = "system.dos_attr.M_TIME"; attr_strings.change_time_attr = "system.dos_attr.C_TIME"; } - + /* Are they requesting a supported attribute? */ if (StrCaseCmp(name, "system.*") == 0 || StrnCaseCmp(name, "system.*!", 9) == 0 || @@ -2081,7 +2089,7 @@ SMBC_getxattr_ctx(SMBCCTX *context, StrCaseCmp(name, attr_strings.write_time_attr) == 0 || StrCaseCmp(name, attr_strings.change_time_attr) == 0 || StrCaseCmp(name, "system.dos_attr.inode") == 0) { - + /* Yup. */ ret = cacl_get(context, talloc_tos(), srv, ipc_srv == NULL ? NULL : ipc_srv->cli, @@ -2094,7 +2102,7 @@ SMBC_getxattr_ctx(SMBCCTX *context, TALLOC_FREE(frame); return ret; } - + /* Unsupported attribute name */ errno = EINVAL; TALLOC_FREE(frame); @@ -2117,37 +2125,37 @@ SMBC_removexattr_ctx(SMBCCTX *context, char *workgroup = NULL; char *path = NULL; 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_removexattr(%s, %s)\n", fname, name)); - + 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) { @@ -2156,14 +2164,14 @@ SMBC_removexattr_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 (! srv->no_nt_session) { ipc_srv = SMBC_attr_server(frame, context, server, share, &workgroup, &user, &password); @@ -2173,16 +2181,16 @@ SMBC_removexattr_ctx(SMBCCTX *context, } else { ipc_srv = NULL; } - + if (! ipc_srv) { TALLOC_FREE(frame); return -1; /* errno set by SMBC_attr_server */ } - + /* Are they asking to set the entire ACL? */ if (StrCaseCmp(name, "system.nt_sec_desc.*") == 0 || StrCaseCmp(name, "system.nt_sec_desc.*+") == 0) { - + /* Yup. */ ret = cacl_set(talloc_tos(), srv->cli, ipc_srv->cli, &ipc_srv->pol, path, @@ -2190,7 +2198,7 @@ SMBC_removexattr_ctx(SMBCCTX *context, TALLOC_FREE(frame); return ret; } - + /* * Are they asking to remove one or more spceific security descriptor * attributes? @@ -2202,7 +2210,7 @@ SMBC_removexattr_ctx(SMBCCTX *context, StrCaseCmp(name, "system.nt_sec_desc.group+") == 0 || StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 || StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) { - + /* Yup. */ ret = cacl_set(talloc_tos(), srv->cli, ipc_srv->cli, &ipc_srv->pol, path, @@ -2210,7 +2218,7 @@ SMBC_removexattr_ctx(SMBCCTX *context, TALLOC_FREE(frame); return ret; } - + /* Unsupported attribute name */ errno = EINVAL; TALLOC_FREE(frame); @@ -2269,7 +2277,7 @@ SMBC_listxattr_ctx(SMBCCTX *context, "system.dos_attr.change_time\0" ; const char * supported; - + if (context->internal->full_time_names) { supported = supported_new; retsize = sizeof(supported_new); @@ -2277,16 +2285,16 @@ SMBC_listxattr_ctx(SMBCCTX *context, supported = supported_old; retsize = sizeof(supported_old); } - + if (size == 0) { return retsize; } - + if (retsize > size) { errno = ERANGE; return -1; } - + /* this can't be strcpy() because there are embedded null characters */ memcpy(list, supported, retsize); return retsize; -- cgit From 4a1f55ba0d6e736e8175efb0c5e4906a5bb43ee3 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 1 Mar 2008 20:55:21 -0500 Subject: Mark smbc_option_{get,set} as deprecated (cherry picked from commit a8b4b773d4647f28e7b92c5968469721d34eb550) (This used to be commit 7b05e264d58c65af37af457947548611fc77edce) --- source3/include/libsmbclient.h | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index 28cad351de..058ac64210 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -142,7 +142,7 @@ struct smbc_dirent /* * Valid values for the option "open_share_mode", when calling - * smbc_option_set() + * smbc_setOptionOpenShareMode() */ typedef enum smbc_share_mode { @@ -1010,35 +1010,15 @@ int smbc_free_context(SMBCCTX * context, int shutdown_ctx); /**@ingroup misc - * Each time the context structure is changed, we have binary backward - * compatibility issues. Instead of modifying the public portions of the - * context structure to add new options, instead, we put them in the internal - * portion of the context structure and provide a set function for these new - * options. - * - * @param context A pointer to a SMBCCTX obtained from smbc_new_context() - * - * @param option_name - * The name of the option for which the value is to be set - * - * @param option_value - * The new value of the option being set * + * @DEPRECATED. Use smbc_setOption*() functions instead. */ void smbc_option_set(SMBCCTX *context, char *option_name, ... /* option_value */); /* - * Retrieve the current value of an option - * - * @param context A pointer to a SMBCCTX obtained from smbc_new_context() - * - * @param option_name - * The name of the option for which the value is to be - * retrieved - * - * @return The value of the specified option. + * @DEPRECATED. Use smbc_getOption*() functions instead. */ void * smbc_option_get(SMBCCTX *context, -- cgit From 99eab28ce164356bb446e0732a990af5eba14cb9 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 1 Mar 2008 20:56:54 -0500 Subject: Comment was in wrong place (cherry picked from commit dec70fa3c0424c148016cc667a3c159e16d8a944) (This used to be commit eb4d6dda1091199af7e62fb584525deb382978e2) --- source3/include/libsmbclient.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index 058ac64210..95ee64d0fe 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -677,16 +677,15 @@ smbc_getOptionNoAutoAnonymousLogin(SMBCCTX *c); 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 * *************************************/ +/** Get the function for obtaining authentication data */ +smbc_get_auth_data_fn smbc_getFunctionAuthData(SMBCCTX *c); + /** Set the function for obtaining authentication data */ void smbc_setFunctionAuthData(SMBCCTX *c, smbc_get_auth_data_fn f); -- cgit From 298fb5128610505a9b15b804a92dd00c86b6f178 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 1 Mar 2008 21:19:15 -0500 Subject: change variable name from f to fn for function pointers (cherry picked from commit 1fd65359f6cd07539cfe43146ac367a48708a678) (This used to be commit b7f10bd31dec8047ea996c4738a6db5535c9261a) --- source3/include/libsmbclient.h | 74 +++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index 95ee64d0fe..78f5931221 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -687,7 +687,7 @@ smbc_setOptionNoAutoAnonymousLogin(SMBCCTX *c, smbc_bool b); smbc_get_auth_data_fn smbc_getFunctionAuthData(SMBCCTX *c); /** Set the function for obtaining authentication data */ -void smbc_setFunctionAuthData(SMBCCTX *c, smbc_get_auth_data_fn f); +void smbc_setFunctionAuthData(SMBCCTX *c, smbc_get_auth_data_fn fn); /** Get the new-style authentication function which includes the context. */ smbc_get_auth_data_with_context_fn @@ -696,39 +696,39 @@ 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); + 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); /** Set the function for checking if a server is still good */ -void smbc_setFunctionCheckServer(SMBCCTX *c, smbc_check_server_fn f); +void smbc_setFunctionCheckServer(SMBCCTX *c, smbc_check_server_fn fn); /** Get the function for removing a server if unused */ smbc_remove_unused_server_fn smbc_getFunctionRemoveUnusedServer(SMBCCTX *c); /** Set the function for removing a server if unused */ void smbc_setFunctionRemoveUnusedServer(SMBCCTX *c, - smbc_remove_unused_server_fn f); + smbc_remove_unused_server_fn fn); /** Get the function for adding a cached server */ smbc_add_cached_srv_fn smbc_getFunctionAddCachedServer(SMBCCTX *c); /** Set the function for adding a cached server */ -void smbc_setFunctionAddCachedServer(SMBCCTX *c, smbc_add_cached_srv_fn f); +void smbc_setFunctionAddCachedServer(SMBCCTX *c, smbc_add_cached_srv_fn fn); /** Get the function for server cache lookup */ smbc_get_cached_srv_fn smbc_getFunctionGetCachedServer(SMBCCTX *c); /** Set the function for server cache lookup */ -void smbc_setFunctionGetCachedServer(SMBCCTX *c, smbc_get_cached_srv_fn f); +void smbc_setFunctionGetCachedServer(SMBCCTX *c, smbc_get_cached_srv_fn fn); /** Get the function for server cache removal */ smbc_remove_cached_srv_fn smbc_getFunctionRemoveCachedServer(SMBCCTX *c); /** Set the function for server cache removal */ void smbc_setFunctionRemoveCachedServer(SMBCCTX *c, - smbc_remove_cached_srv_fn f); + smbc_remove_cached_srv_fn fn); /** * Get the function for server cache purging. This function tries to @@ -741,7 +741,7 @@ smbc_purge_cached_srv_fn smbc_getFunctionPurgeCachedServers(SMBCCTX *c); * remove all cached servers (e.g. on disconnect) */ void smbc_setFunctionPurgeCachedServers(SMBCCTX *c, - smbc_purge_cached_srv_fn f); + smbc_purge_cached_srv_fn fn); /** Get the function to store private data of the server cache */ struct smbc_server_cache * smbc_getServerCacheData(SMBCCTX *c); @@ -762,7 +762,7 @@ typedef SMBCFILE * (*smbc_open_fn)(SMBCCTX *c, int flags, mode_t mode); smbc_open_fn smbc_getFunctionOpen(SMBCCTX *c); -void smbc_setFunctionOpen(SMBCCTX *c, smbc_open_fn f); +void smbc_setFunctionOpen(SMBCCTX *c, smbc_open_fn fn); typedef SMBCFILE * (*smbc_creat_fn)(SMBCCTX *c, const char *path, @@ -775,56 +775,56 @@ typedef ssize_t (*smbc_read_fn)(SMBCCTX *c, void *buf, size_t count); smbc_read_fn smbc_getFunctionRead(SMBCCTX *c); -void smbc_setFunctionRead(SMBCCTX *c, smbc_read_fn f); +void smbc_setFunctionRead(SMBCCTX *c, smbc_read_fn fn); typedef ssize_t (*smbc_write_fn)(SMBCCTX *c, SMBCFILE *file, void *buf, size_t count); smbc_write_fn smbc_getFunctionWrite(SMBCCTX *c); -void smbc_setFunctionWrite(SMBCCTX *c, smbc_write_fn f); +void smbc_setFunctionWrite(SMBCCTX *c, smbc_write_fn fn); typedef int (*smbc_unlink_fn)(SMBCCTX *c, const char *fname); smbc_unlink_fn smbc_getFunctionUnlink(SMBCCTX *c); -void smbc_setFunctionUnlink(SMBCCTX *c, smbc_unlink_fn f); +void smbc_setFunctionUnlink(SMBCCTX *c, smbc_unlink_fn fn); typedef int (*smbc_rename_fn)(SMBCCTX *ocontext, const char *oname, SMBCCTX *ncontext, const char *nname); smbc_rename_fn smbc_getFunctionRename(SMBCCTX *c); -void smbc_setFunctionRename(SMBCCTX *c, smbc_rename_fn f); +void smbc_setFunctionRename(SMBCCTX *c, smbc_rename_fn fn); typedef off_t (*smbc_lseek_fn)(SMBCCTX *c, SMBCFILE * file, off_t offset, int whence); smbc_lseek_fn smbc_getFunctionLseek(SMBCCTX *c); -void smbc_setFunctionLseek(SMBCCTX *c, smbc_lseek_fn f); +void smbc_setFunctionLseek(SMBCCTX *c, smbc_lseek_fn fn); typedef int (*smbc_stat_fn)(SMBCCTX *c, const char *fname, struct stat *st); smbc_stat_fn smbc_getFunctionStat(SMBCCTX *c); -void smbc_setFunctionStat(SMBCCTX *c, smbc_stat_fn f); +void smbc_setFunctionStat(SMBCCTX *c, smbc_stat_fn fn); typedef int (*smbc_fstat_fn)(SMBCCTX *c, SMBCFILE *file, struct stat *st); smbc_fstat_fn smbc_getFunctionFstat(SMBCCTX *c); -void smbc_setFunctionFstat(SMBCCTX *c, smbc_fstat_fn f); +void smbc_setFunctionFstat(SMBCCTX *c, smbc_fstat_fn fn); typedef int (*smbc_ftruncate_fn)(SMBCCTX *c, SMBCFILE *f, off_t size); smbc_ftruncate_fn smbc_getFunctionFtruncate(SMBCCTX *c); -void smbc_setFunctionFtruncate(SMBCCTX *c, smbc_ftruncate_fn f); +void smbc_setFunctionFtruncate(SMBCCTX *c, smbc_ftruncate_fn fn); typedef int (*smbc_close_fn)(SMBCCTX *c, SMBCFILE *file); smbc_close_fn smbc_getFunctionClose(SMBCCTX *c); -void smbc_setFunctionClose(SMBCCTX *c, smbc_close_fn f); +void smbc_setFunctionClose(SMBCCTX *c, smbc_close_fn fn); @@ -837,52 +837,52 @@ void smbc_setFunctionClose(SMBCCTX *c, smbc_close_fn f); typedef SMBCFILE * (*smbc_opendir_fn)(SMBCCTX *c, const char *fname); smbc_opendir_fn smbc_getFunctionOpendir(SMBCCTX *c); -void smbc_setFunctionOpendir(SMBCCTX *c, smbc_opendir_fn f); +void smbc_setFunctionOpendir(SMBCCTX *c, smbc_opendir_fn fn); typedef int (*smbc_closedir_fn)(SMBCCTX *c, SMBCFILE *dir); smbc_closedir_fn smbc_getFunctionClosedir(SMBCCTX *c); -void smbc_setFunctionClosedir(SMBCCTX *c, smbc_closedir_fn f); +void smbc_setFunctionClosedir(SMBCCTX *c, smbc_closedir_fn fn); typedef struct smbc_dirent * (*smbc_readdir_fn)(SMBCCTX *c, SMBCFILE *dir); smbc_readdir_fn smbc_getFunctionReaddir(SMBCCTX *c); -void smbc_setFunctionReaddir(SMBCCTX *c, smbc_readdir_fn f); +void smbc_setFunctionReaddir(SMBCCTX *c, smbc_readdir_fn fn); typedef int (*smbc_getdents_fn)(SMBCCTX *c, SMBCFILE *dir, struct smbc_dirent *dirp, int count); smbc_getdents_fn smbc_getFunctionGetdents(SMBCCTX *c); -void smbc_setFunctionGetdents(SMBCCTX *c, smbc_getdents_fn f); +void smbc_setFunctionGetdents(SMBCCTX *c, smbc_getdents_fn fn); typedef int (*smbc_mkdir_fn)(SMBCCTX *c, const char *fname, mode_t mode); smbc_mkdir_fn smbc_getFunctionMkdir(SMBCCTX *c); -void smbc_setFunctionMkdir(SMBCCTX *c, smbc_mkdir_fn f); +void smbc_setFunctionMkdir(SMBCCTX *c, smbc_mkdir_fn fn); typedef int (*smbc_rmdir_fn)(SMBCCTX *c, const char *fname); smbc_rmdir_fn smbc_getFunctionRmdir(SMBCCTX *c); -void smbc_setFunctionRmdir(SMBCCTX *c, smbc_rmdir_fn f); +void smbc_setFunctionRmdir(SMBCCTX *c, smbc_rmdir_fn fn); typedef off_t (*smbc_telldir_fn)(SMBCCTX *c, SMBCFILE *dir); smbc_telldir_fn smbc_getFunctionTelldir(SMBCCTX *c); -void smbc_setFunctionTelldir(SMBCCTX *c, smbc_telldir_fn f); +void smbc_setFunctionTelldir(SMBCCTX *c, smbc_telldir_fn fn); typedef int (*smbc_lseekdir_fn)(SMBCCTX *c, SMBCFILE *dir, off_t offset); smbc_lseekdir_fn smbc_getFunctionLseekdir(SMBCCTX *c); -void smbc_setFunctionLseekdir(SMBCCTX *c, smbc_lseekdir_fn f); +void smbc_setFunctionLseekdir(SMBCCTX *c, smbc_lseekdir_fn fn); typedef int (*smbc_fstatdir_fn)(SMBCCTX *c, SMBCFILE *dir, struct stat *st); smbc_fstatdir_fn smbc_getFunctionFstatdir(SMBCCTX *c); -void smbc_setFunctionFstatdir(SMBCCTX *c, smbc_fstatdir_fn f); +void smbc_setFunctionFstatdir(SMBCCTX *c, smbc_fstatdir_fn fn); @@ -896,13 +896,13 @@ typedef int (*smbc_chmod_fn)(SMBCCTX *c, const char *fname, mode_t mode); smbc_chmod_fn smbc_getFunctionChmod(SMBCCTX *c); -void smbc_setFunctionChmod(SMBCCTX *c, smbc_chmod_fn f); +void smbc_setFunctionChmod(SMBCCTX *c, smbc_chmod_fn fn); typedef int (*smbc_utimes_fn)(SMBCCTX *c, const char *fname, struct timeval *tbuf); smbc_utimes_fn smbc_getFunctionUtimes(SMBCCTX *c); -void smbc_setFunctionUtimes(SMBCCTX *c, smbc_utimes_fn f); +void smbc_setFunctionUtimes(SMBCCTX *c, smbc_utimes_fn fn); typedef int (*smbc_setxattr_fn)(SMBCCTX *context, const char *fname, @@ -911,7 +911,7 @@ typedef int (*smbc_setxattr_fn)(SMBCCTX *context, size_t size, int flags); smbc_setxattr_fn smbc_getFunctionSetxattr(SMBCCTX *c); -void smbc_setFunctionSetxattr(SMBCCTX *c, smbc_setxattr_fn f); +void smbc_setFunctionSetxattr(SMBCCTX *c, smbc_setxattr_fn fn); typedef int (*smbc_getxattr_fn)(SMBCCTX *context, const char *fname, @@ -919,20 +919,20 @@ typedef int (*smbc_getxattr_fn)(SMBCCTX *context, const void *value, size_t size); smbc_getxattr_fn smbc_getFunctionGetxattr(SMBCCTX *c); -void smbc_setFunctionGetxattr(SMBCCTX *c, smbc_getxattr_fn f); +void smbc_setFunctionGetxattr(SMBCCTX *c, smbc_getxattr_fn fn); typedef int (*smbc_removexattr_fn)(SMBCCTX *context, const char *fname, const char *name); smbc_removexattr_fn smbc_getFunctionRemovexattr(SMBCCTX *c); -void smbc_setFunctionRemovexattr(SMBCCTX *c, smbc_removexattr_fn f); +void smbc_setFunctionRemovexattr(SMBCCTX *c, smbc_removexattr_fn fn); typedef int (*smbc_listxattr_fn)(SMBCCTX *context, const char *fname, char *list, size_t size); smbc_listxattr_fn smbc_getFunctionListxattr(SMBCCTX *c); -void smbc_setFunctionListxattr(SMBCCTX *c, smbc_listxattr_fn f); +void smbc_setFunctionListxattr(SMBCCTX *c, smbc_listxattr_fn fn); @@ -947,27 +947,27 @@ typedef int (*smbc_print_file_fn)(SMBCCTX *c_file, SMBCCTX *c_print, const char *printq); smbc_print_file_fn smbc_getFunctionPrintFile(SMBCCTX *c); -void smbc_setFunctionPrintFile(SMBCCTX *c, smbc_print_file_fn f); +void smbc_setFunctionPrintFile(SMBCCTX *c, smbc_print_file_fn fn); typedef SMBCFILE * (*smbc_open_print_job_fn)(SMBCCTX *c, const char *fname); smbc_open_print_job_fn smbc_getFunctionOpenPrintJob(SMBCCTX *c); void smbc_setFunctionOpenPrintJob(SMBCCTX *c, - smbc_open_print_job_fn f); + smbc_open_print_job_fn fn); typedef int (*smbc_list_print_jobs_fn)(SMBCCTX *c, const char *fname, smbc_list_print_job_fn fn); smbc_list_print_jobs_fn smbc_getFunctionListPrintJobs(SMBCCTX *c); void smbc_setFunctionListPrintJobs(SMBCCTX *c, - smbc_list_print_jobs_fn f); + smbc_list_print_jobs_fn fn); typedef int (*smbc_unlink_print_job_fn)(SMBCCTX *c, const char *fname, int id); smbc_unlink_print_job_fn smbc_getFunctionUnlinkPrintJob(SMBCCTX *c); void smbc_setFunctionUnlinkPrintJob(SMBCCTX *c, - smbc_unlink_print_job_fn f); + smbc_unlink_print_job_fn fn); /**@ingroup misc -- cgit From ddf19f91e5e4b003f7af994ddb958630f340ce93 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 1 Mar 2008 21:19:52 -0500 Subject: Return NULL, not 0, from a function which returns a pointer. (cherry picked from commit 23cb9c49e3724cecaa66655ef64c3111bf14c552) (This used to be commit 9b4bd6473ed3f93c1bbfae3f82d0a100e832df48) --- source3/libsmb/libsmb_cache.c | 1 - source3/libsmb/libsmb_context.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/source3/libsmb/libsmb_cache.c b/source3/libsmb/libsmb_cache.c index ff13fd7eac..c45aba4544 100644 --- a/source3/libsmb/libsmb_cache.c +++ b/source3/libsmb/libsmb_cache.c @@ -1,4 +1,3 @@ - /* Unix SMB/CIFS implementation. SMB client library implementation (server cache) diff --git a/source3/libsmb/libsmb_context.c b/source3/libsmb/libsmb_context.c index 8af49d12be..c107ab2220 100644 --- a/source3/libsmb/libsmb_context.c +++ b/source3/libsmb/libsmb_context.c @@ -424,7 +424,7 @@ smbc_init_context(SMBCCTX *context) /* Do not initialise the same client twice */ if (context->internal->initialized) { - return 0; + return NULL; } if (!context->server.get_auth_data_fn || @@ -446,7 +446,7 @@ smbc_init_context(SMBCCTX *context) /* Set this to what the user wants */ DEBUGLEVEL = context->config.debug; - + load_case_tables(); setup_logging("libsmbclient", True); -- cgit From 2492e96a8e4be4ebfc389a16427f809240350804 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 1 Mar 2008 23:08:19 -0500 Subject: Update WHATSNEW for libsmbclient changes (cherry picked from commit f07407a32e178a47c8f9b3e3703aa5a20f0a4f06) (This used to be commit 938c6aef24c696be9bd247e43c7c5ec1f792dbd6) --- WHATSNEW.txt | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index c18ba8b2dc..62a0baf9fc 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -105,6 +105,68 @@ See examples/scripts/mount/mount.smbfs as an example for a wrapper which calls mount.cifs instead of smbmount/mount.smbfs. +Modified API for libsmbclient +============================================================================== + +Maintaining ABI compatibility for libsmbclient has become increasingly +difficult to accomplish, while also keeping the code organization such that it +is easily readable. Towards the goal of maintaining ABI compatibility and +also keeping the code easy to maintain and enhance, the API has changed +somewhat. In particular, the fields in the SMBCCTX context structure are no +longer intended to be read/write by the user. The names of the fields have +changed to encourage any recompilations to use the new interface, but for +continued ABI compatibility, the fields are in the same locations in the +context structure as they were previously so any previously-compiled +applications should continue to work with this new version. + +An application that previously accessed the members of the SMBCCTX context +structure will encounter errors if recompiled. This is intentional to +encourage implementation of the small changes required for the new interface. +The number of changes is expected to be quite small for the vast majority of +applications, and no changes need be made for many applications. The changes +required for KDE (konqueror) to conform to the new interface, for example, are +only four lines in only one file. + +Instead of the application manually changing or reading values in the context +structure, there are now setter and getter functions for each configurable +member in that structure. Similarly, the smbc_option_get() and +smbc_option_set() functions are deprecated in favor of the setter/getter +interface. The setters and getters are all documented in libsmbclient.h +under these comment blocks: + + Getters and setters for CONFIGURATION + Getters and setters for OPTIONS + Getters and setters for FUNCTIONS + Callable functions for files + Callable functions for directories + Callable functions applicable to both files and directories + +Example changes that may be required: + + /* Set the debug level */ + context->debug = 99; +changes to: + smbc_setDebug(context, 99); + + /* Specify the authentication callback function */ + context->callbacks.auth_fn = auth_smbc_get_data; +changes to: + smbc_setFunctionAuthData(context, auth_smbc_get_data); + + /* Specify the new-style authentication callback with context parameter */ + smbc_option_set("auth_function", auth_smbc_get_data_with_ctx); +changes to: + smbc_setFunctionAuthDataWithContext(context, auth_smbc_get_data_with_ctx); + + /* Set kerberos flags */ + context->flags = (SMB_CTX_FLAG_USE_KERBEROS | + SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS); +changes to: + smbc_setOptionUseKerberos(context, 1); + smbc_setOptionFallbackAfterKerberos(context, 1); + + + ###################################################################### Changes @@ -249,6 +311,9 @@ o Volker Lendecke * Speed up the smbclient "get" command * Add the aio_fork module +o Derrell Lipman + * Modified libsmbclient API for more easily maintaining ABI compatibility + while adding new features to libsmbclient. o Stefan Metzmacher * Refactor Winbind internal parent-child interface tables -- cgit From 2edf9c595ec16c169653ee6620d6fe0190f908cd Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sun, 2 Mar 2008 16:13:25 -0500 Subject: fixed missing white space (cherry picked from commit 71e86f13b0ace3841c6712084728c79db74ff803) (This used to be commit 8bf707c13794539029be2229f0c587b713b4fd20) --- source3/include/libsmbclient.h | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index 78f5931221..bfed71de1c 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -1016,6 +1016,7 @@ void smbc_option_set(SMBCCTX *context, char *option_name, ... /* option_value */); + /* * @DEPRECATED. Use smbc_getOption*() functions instead. */ -- cgit From 8cd0cf153e409dd49e66bd500fad8501371a83a5 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sun, 2 Mar 2008 16:21:48 -0500 Subject: Remove use of deprecated function (cherry picked from commit 93580bce833453ba512ee436d6dfdbdcd2c53777) (This used to be commit 0621dfe10f1fd3d8ce04a039d2d44d6c67407746) --- examples/libsmbclient/smbwrapper/smbw.c | 6 +++--- examples/libsmbclient/testacl.c | 2 +- examples/libsmbclient/testacl2.c | 2 +- examples/libsmbclient/testacl3.c | 2 +- examples/libsmbclient/testbrowse.c | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/libsmbclient/smbwrapper/smbw.c b/examples/libsmbclient/smbwrapper/smbw.c index d3439e436d..e2e44c1f0f 100644 --- a/examples/libsmbclient/smbwrapper/smbw.c +++ b/examples/libsmbclient/smbwrapper/smbw.c @@ -176,9 +176,9 @@ static void do_init(StartupType startupType) smbc_setDebug(smbw_ctx, debug_level); smbc_setFunctionAuthData(smbw_ctx, get_auth_data_fn); - smbc_option_set(smbw_ctx, "browse_max_lmb_count", 0); - smbc_option_set(smbw_ctx, "urlencode_readdir_entries", 1); - smbc_option_set(smbw_ctx, "one_share_per_server", 1); + smbc_setOptionBrowseMaxLmbCount(smbw_ctx, 0); + smbc_setOptionUrlEncodeReaddirEntries(smbw_ctx, 1); + smbc_setOptionOneSharePerServer(smbw_ctx, 1); if (smbc_init_context(smbw_ctx) == NULL) { fprintf(stderr, "Could not initialize context.\n"); diff --git a/examples/libsmbclient/testacl.c b/examples/libsmbclient/testacl.c index 51cc90f101..00e1c2c9da 100644 --- a/examples/libsmbclient/testacl.c +++ b/examples/libsmbclient/testacl.c @@ -143,7 +143,7 @@ int main(int argc, const char *argv[]) if (full_time_names) { SMBCCTX *context = smbc_set_context(NULL); - smbc_option_set(context, "full_time_names", 1); + smbc_setOptionFullTimeNames(context, 1); } /* Perform requested action */ diff --git a/examples/libsmbclient/testacl2.c b/examples/libsmbclient/testacl2.c index df38fe208e..d2a97cf2d2 100644 --- a/examples/libsmbclient/testacl2.c +++ b/examples/libsmbclient/testacl2.c @@ -39,7 +39,7 @@ int main(int argc, const char *argv[]) } SMBCCTX *context = smbc_set_context(NULL); - smbc_option_set(context, "full_time_names", 1); + smbc_setOptionFullTimeNames(context, 1); the_acl = strdup("system.nt_sec_desc.*"); ret = smbc_getxattr(argv[1], the_acl, value, sizeof(value)); diff --git a/examples/libsmbclient/testacl3.c b/examples/libsmbclient/testacl3.c index 9102405659..4ef6e80a7b 100644 --- a/examples/libsmbclient/testacl3.c +++ b/examples/libsmbclient/testacl3.c @@ -28,7 +28,7 @@ int main(int argc, char * argv[]) smbc_init(get_auth_data_fn, debug); context = smbc_set_context(NULL); - smbc_option_set(context, "full_time_names", 1); + smbc_setOptionFullTimeNames(context, 1); for (;;) { diff --git a/examples/libsmbclient/testbrowse.c b/examples/libsmbclient/testbrowse.c index 1b0b54f9f0..c4ca6667e0 100644 --- a/examples/libsmbclient/testbrowse.c +++ b/examples/libsmbclient/testbrowse.c @@ -120,7 +120,7 @@ main(int argc, char * argv[]) /* If we've been asked to log to stderr instead of stdout, ... */ if (debug_stderr) { /* ... then set the option to do so */ - smbc_option_set(context, "debug_to_stderr", 1); + smbc_setOptionDebugToStderr(context, 1); } /* Initialize the context using the previously specified options */ @@ -196,7 +196,7 @@ get_auth_data_with_context_fn(SMBCCTX * context, { printf("Authenticating with context 0x%lx", context); if (context != NULL) { - char *user_data = smbc_option_get(context, "user_data"); + char *user_data = smbc_getOptionUserData(context); printf(" with user data %s", user_data); } printf("\n"); -- cgit From 2f0a61564ae080b027d43d77428d290fd8ca017b Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Mon, 3 Mar 2008 18:13:33 -0500 Subject: Continued revamping of libsmbclient. - James suggested using gcc's "deprecated" attribute to mark the context structure fields to generate warnings. This creates a scenario with the best of all worlds. I'm able to move to an organization that more easily allows future enhancements, while avoiding any mandatory changes by applications. Thanks, James! - Updated WHATSNEW.txt so that it accurately reflects the current state of affairs. Derrell (cherry picked from commit a67f96fbe9683b46c2149f7cb439d13f7f0e6ecd) (This used to be commit 046653403fadfa2d42decce7048eca6321b321c6) --- WHATSNEW.txt | 17 +- examples/libsmbclient/Makefile | 4 +- examples/libsmbclient/testsmbc.c | 2 +- source3/Makefile.in | 1 + source3/include/libsmb_internal.h | 100 +--- source3/include/libsmbclient.h | 247 +++++---- source3/libsmb/libsmb_cache.c | 16 +- source3/libsmb/libsmb_context.c | 1078 ++++--------------------------------- source3/libsmb/libsmb_dir.c | 30 +- source3/libsmb/libsmb_file.c | 8 +- source3/libsmb/libsmb_path.c | 6 +- source3/libsmb/libsmb_printjob.c | 6 +- source3/libsmb/libsmb_server.c | 75 +-- source3/libsmb/libsmb_setget.c | 905 +++++++++++++++++++++++++++++++ source3/libsmb/libsmb_stat.c | 4 +- source3/libsmb/libsmb_xattr.c | 6 +- 16 files changed, 1223 insertions(+), 1282 deletions(-) create mode 100644 source3/libsmb/libsmb_setget.c diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 62a0baf9fc..0b355547d9 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -111,16 +111,11 @@ Modified API for libsmbclient Maintaining ABI compatibility for libsmbclient has become increasingly difficult to accomplish, while also keeping the code organization such that it is easily readable. Towards the goal of maintaining ABI compatibility and -also keeping the code easy to maintain and enhance, the API has changed -somewhat. In particular, the fields in the SMBCCTX context structure are no -longer intended to be read/write by the user. The names of the fields have -changed to encourage any recompilations to use the new interface, but for -continued ABI compatibility, the fields are in the same locations in the -context structure as they were previously so any previously-compiled -applications should continue to work with this new version. - -An application that previously accessed the members of the SMBCCTX context -structure will encounter errors if recompiled. This is intentional to +also keeping the code easy to maintain and enhance, the API has been enhanced. +In particular, the fields in the SMBCCTX context structure are no longer +intended to be read/write by the user, and are marked as deprecated. An +application that previously accessed the members of the SMBCCTX context +structure will now encounter warnings if recompiled. This is intentional, to encourage implementation of the small changes required for the new interface. The number of changes is expected to be quite small for the vast majority of applications, and no changes need be made for many applications. The changes @@ -141,7 +136,7 @@ under these comment blocks: Callable functions for directories Callable functions applicable to both files and directories -Example changes that may be required: +Example changes that may be required to eliminate "deprecated" warnings: /* Set the debug level */ context->debug = 99; diff --git a/examples/libsmbclient/Makefile b/examples/libsmbclient/Makefile index e2d8b6895f..a50e80a918 100644 --- a/examples/libsmbclient/Makefile +++ b/examples/libsmbclient/Makefile @@ -1,14 +1,14 @@ # CC = gcc -SAMBA_INCL = ../../source/include +SAMBA_INCL = -I/usr/local/samba/include EXTLIB_INCL = -I/usr/include/gtk-1.2 \ -I/usr/include/glib-1.2 \ -I/usr/lib/glib/include EXTLIB_INCL = `gtk-config --cflags` DEFS = -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -CFLAGS = -O0 -g -I$(SAMBA_INCL) $(EXTLIB_INCL) $(DEFS) +CFLAGS = -O0 -g $(SAMBA_INCL) $(EXTLIB_INCL) $(DEFS) LDFLAGS = -L/usr/local/samba/lib \ -lldap -lkrb5 -lgssapi_krb5 diff --git a/examples/libsmbclient/testsmbc.c b/examples/libsmbclient/testsmbc.c index c506f5fd64..1f06437293 100644 --- a/examples/libsmbclient/testsmbc.c +++ b/examples/libsmbclient/testsmbc.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include "libsmbclient.h" #include "get_auth_data_fn.h" int global_id = 0; diff --git a/source3/Makefile.in b/source3/Makefile.in index ddeac06dc0..44ac6622de 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -768,6 +768,7 @@ LIBSMBCLIENT_OBJ0 = \ libsmb/libsmb_server.o \ libsmb/libsmb_stat.o \ libsmb/libsmb_xattr.o \ + libsmb/libsmb_setget.o \ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(RPC_PARSE_OBJ) \ diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index e687e24268..6930812b29 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -113,23 +113,6 @@ struct SMBC_internal_data { /* True when this handle is initialized */ bool initialized; -#if 0 /* Left in libsmbclient.h for backward compatibility */ - /* Netbios name used for making connections */ - char * netbios_name; - - /* Workgroup used for making connections */ - char * workgroup; - - /* Username used for making connections */ - char * user; - - /* Debug level */ - int debug; - - /* Connection timeout value */ - int timeout; -#endif - /* dirent pointer location * * Leave room for any urlencoded filename and the comment field. @@ -192,88 +175,7 @@ struct SMBC_internal_data { */ 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 - * 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. - */ - bool 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. - */ - bool one_share_per_server; - - /* Kerberos-related flags */ - bool use_kerberos; - bool fallback_after_kerberos; - - /* Don't try to do automatic anonymous login */ - bool no_auto_anonymous_login; - - /* Server-related functions */ - struct - { - smbc_get_auth_data_fn get_auth_data_fn; - smbc_check_server_fn check_server_fn; - smbc_remove_unused_server_fn remove_unused_server_fn; - } server; - - /* Cache-related functions */ - struct - { - struct smbc_server_cache * server_cache_data; - smbc_add_cached_srv_fn add_cached_server_fn; - smbc_get_cached_srv_fn get_cached_server_fn; - smbc_remove_cached_srv_fn remove_cached_server_fn; - smbc_purge_cached_srv_fn purge_cached_server_fn; - } cache; -#endif + struct smbc_server_cache * server_cache; /* POSIX emulation functions */ struct diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index bfed71de1c..a60c05fa7f 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -25,6 +25,13 @@ #ifndef SMBCLIENT_H_INCLUDED #define SMBCLIENT_H_INCLUDED +#undef _DEPRECATED_ +#if ! defined(__LIBSMBCLIENT_INTERNAL__) && defined(__GNUC__) +# define _DEPRECATED_ __attribute__ ((deprecated)) +#else +# define _DEPRECATED_ +#endif + #ifdef __cplusplus extern "C" { #endif @@ -416,7 +423,7 @@ typedef int (*smbc_remove_cached_srv_fn)(SMBCCTX * c, SMBCSRV *srv); * @return 0 when found and removed. 1 on failure. * */ -typedef int (*smbc_purge_cached_srv_fn) (SMBCCTX * c); +typedef int (*smbc_purge_cached_fn) (SMBCCTX * c); @@ -734,14 +741,14 @@ void smbc_setFunctionRemoveCachedServer(SMBCCTX *c, * Get the function for server cache purging. This function tries to * remove all cached servers (e.g. on disconnect) */ -smbc_purge_cached_srv_fn smbc_getFunctionPurgeCachedServers(SMBCCTX *c); +smbc_purge_cached_fn smbc_getFunctionPurgeCachedServers(SMBCCTX *c); /** * Set the function for server cache purging. This function tries to * remove all cached servers (e.g. on disconnect) */ void smbc_setFunctionPurgeCachedServers(SMBCCTX *c, - smbc_purge_cached_srv_fn fn); + smbc_purge_cached_fn fn); /** Get the function to store private data of the server cache */ struct smbc_server_cache * smbc_getServerCacheData(SMBCCTX *c); @@ -1010,7 +1017,7 @@ int smbc_free_context(SMBCCTX * context, int shutdown_ctx); /**@ingroup misc * - * @DEPRECATED. Use smbc_setOption*() functions instead. + * @deprecated. Use smbc_setOption*() functions instead. */ void smbc_option_set(SMBCCTX *context, @@ -1018,7 +1025,7 @@ smbc_option_set(SMBCCTX *context, ... /* option_value */); /* - * @DEPRECATED. Use smbc_getOption*() functions instead. + * @deprecated. Use smbc_getOption*() functions instead. */ void * smbc_option_get(SMBCCTX *context, @@ -2570,7 +2577,6 @@ smbc_version(void); } #endif - /** * @ingroup structure * Structure that contains a client context information @@ -2586,137 +2592,129 @@ smbc_version(void); * directly visible to applications. This makes it much easier to maintain * ABI compatibility. */ -struct _SMBCCTX { - struct - { - /** - * debug level - * - * Manually setting/retrieving this value is deprecated. - * Use smbc_getDebug() and smbc_setDebug() - */ - int debug; +struct _SMBCCTX +{ + /** + * debug level + * + * DEPRECATED: + * Use smbc_getDebug() and smbc_setDebug() + */ + int debug _DEPRECATED_; - /** - * netbios name used for making connections - * - * Manually setting/retrieving this value is deprecated. - * Use smbc_getNetbiosName() and smbc_setNetbiosName() - */ - char * netbios_name; + /** + * netbios name used for making connections + * + * DEPRECATED: + * Use smbc_getNetbiosName() and smbc_setNetbiosName() + */ + char * netbios_name _DEPRECATED_; - /** - * workgroup name used for making connections - * - * Manually setting/retrieving this value is deprecated. - * Use smbc_getWorkgroup() and smbc_setWorkgroup() - */ - char * workgroup; + /** + * workgroup name used for making connections + * + * DEPRECATED: + * Use smbc_getWorkgroup() and smbc_setWorkgroup() + */ + char * workgroup _DEPRECATED_; - /** - * username used for making connections - * - * Manually setting/retrieving this value is deprecated. - * Use smbc_getUser() and smbc_setUser() - */ - char * user; - - /** - * 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; - } config; + /** + * username used for making connections + * + * DEPRECATED: + * Use smbc_getUser() and smbc_setUser() + */ + char * user _DEPRECATED_; + + /** + * timeout used for waiting on connections / response data (in + * milliseconds) + * + * DEPRECATED: + * Use smbc_getTimeout() and smbc_setTimeout() + */ + int timeout _DEPRECATED_; /** * callable functions for files: * For usage and return values see the SMBC_* functions * - * Manually setting/retrieving these values is deprecated. + * DEPRECATED: * * Use smbc_getFunction*() and smbc_setFunction*(), e.g. * smbc_getFunctionOpen(), smbc_setFunctionUnlink(), etc. */ - struct - { - smbc_open_fn open_fn; - smbc_creat_fn creat_fn; - smbc_read_fn read_fn; - smbc_write_fn write_fn; - smbc_unlink_fn unlink_fn; - smbc_rename_fn rename_fn; - smbc_lseek_fn lseek_fn; - smbc_stat_fn stat_fn; - smbc_fstat_fn fstat_fn; + smbc_open_fn open _DEPRECATED_; + smbc_creat_fn creat _DEPRECATED_; + smbc_read_fn read _DEPRECATED_; + smbc_write_fn write _DEPRECATED_; + smbc_unlink_fn unlink _DEPRECATED_; + smbc_rename_fn rename _DEPRECATED_; + smbc_lseek_fn lseek _DEPRECATED_; + smbc_stat_fn stat _DEPRECATED_; + smbc_fstat_fn fstat _DEPRECATED_; #if 0 /* internal */ - smbc_ftruncate_fn ftruncate_fn; + smbc_ftruncate_fn ftruncate_fn; #endif - smbc_close_fn close_fn; - smbc_opendir_fn opendir_fn; - smbc_closedir_fn closedir_fn; - smbc_readdir_fn readdir_fn; - smbc_getdents_fn getdents_fn; - smbc_mkdir_fn mkdir_fn; - smbc_rmdir_fn rmdir_fn; - smbc_telldir_fn telldir_fn; - smbc_lseekdir_fn lseekdir_fn; - smbc_fstatdir_fn fstatdir_fn; - smbc_chmod_fn chmod_fn; - smbc_utimes_fn utimes_fn; - smbc_setxattr_fn setxattr_fn; - smbc_getxattr_fn getxattr_fn; - smbc_removexattr_fn removexattr_fn; - smbc_listxattr_fn listxattr_fn; - } posix_emu; + smbc_close_fn close_fn _DEPRECATED_; + smbc_opendir_fn opendir _DEPRECATED_; + smbc_closedir_fn closedir _DEPRECATED_; + smbc_readdir_fn readdir _DEPRECATED_; + smbc_getdents_fn getdents _DEPRECATED_; + smbc_mkdir_fn mkdir _DEPRECATED_; + smbc_rmdir_fn rmdir _DEPRECATED_; + smbc_telldir_fn telldir _DEPRECATED_; + smbc_lseekdir_fn lseekdir _DEPRECATED_; + smbc_fstatdir_fn fstatdir _DEPRECATED_; + smbc_chmod_fn chmod _DEPRECATED_; + smbc_utimes_fn utimes _DEPRECATED_; + smbc_setxattr_fn setxattr _DEPRECATED_; + smbc_getxattr_fn getxattr _DEPRECATED_; + smbc_removexattr_fn removexattr _DEPRECATED_; + smbc_listxattr_fn listxattr _DEPRECATED_; /* Printing-related functions */ - struct - { - smbc_print_file_fn print_file_fn; - smbc_open_print_job_fn open_print_job_fn; - smbc_list_print_jobs_fn list_print_jobs_fn; - smbc_unlink_print_job_fn unlink_print_job_fn; - } printing; + smbc_print_file_fn print_file _DEPRECATED_; + smbc_open_print_job_fn open_print_job _DEPRECATED_; + smbc_list_print_jobs_fn list_print_jobs _DEPRECATED_; + smbc_unlink_print_job_fn unlink_print_job _DEPRECATED_; /* ** Callbacks - * These callbacks _always_ have to be initialized because they will - * not be checked at dereference for increased speed. + * + * DEPRECATED: + * + * See the comment above each field, for the getter and setter + * functions that should now be used. */ - struct + struct _smbc_callbacks { /** * authentication function callback: called upon auth requests * - * Manually setting/retrieving this value is deprecated. + * DEPRECATED: * Use smbc_getFunctionAuthData(), smbc_setFunctionAuthData() */ - smbc_get_auth_data_fn get_auth_data_fn; + smbc_get_auth_data_fn auth_fn _DEPRECATED_; /** * check if a server is still good * - * Manually setting/retrieving this value is deprecated. + * DEPRECATED: * Use smbc_getFunctionCheckServer(), * smbc_setFunctionCheckServer() */ - smbc_check_server_fn check_server_fn; + smbc_check_server_fn check_server_fn _DEPRECATED_; /** * remove a server if unused * - * Manually setting/retrieving this value is deprecated. + * DEPRECATED: * Use smbc_getFunctionRemoveUnusedServer(), * smbc_setFunctionCheckServer() */ - smbc_remove_unused_server_fn remove_unused_server_fn; - } server; + smbc_remove_unused_server_fn remove_unused_server_fn _DEPRECATED_; - struct - { /** Cache subsystem * * For an example cache system see @@ -2728,53 +2726,53 @@ struct _SMBCCTX { /** * server cache addition * - * Manually setting/retrieving this value is deprecated. + * DEPRECATED: * Use smbc_getFunctionAddCachedServer(), * smbc_setFunctionAddCachedServer() */ - smbc_add_cached_srv_fn add_cached_server_fn; + smbc_add_cached_srv_fn add_cached_srv_fn _DEPRECATED_; /** * server cache lookup * - * Manually setting/retrieving this value is deprecated. + * DEPRECATED: * Use smbc_getFunctionGetCachedServer(), * smbc_setFunctionGetCachedServer() */ - smbc_get_cached_srv_fn get_cached_server_fn; + smbc_get_cached_srv_fn get_cached_srv_fn _DEPRECATED_; /** * server cache removal * - * Manually setting/retrieving this value is deprecated. + * DEPRECATED: * Use smbc_getFunctionRemoveCachedServer(), * smbc_setFunctionRemoveCachedServer() */ - smbc_remove_cached_srv_fn remove_cached_server_fn; + smbc_remove_cached_srv_fn remove_cached_srv_fn _DEPRECATED_; /** * server cache purging, try to remove all cached servers * (disconnect) * - * Manually setting/retrieving this value is deprecated. + * DEPRECATED: * Use smbc_getFunctionPurgeCachedServers(), * smbc_setFunctionPurgeCachedServers() */ - smbc_purge_cached_srv_fn purge_cached_servers_fn; + smbc_purge_cached_fn purge_cached_fn _DEPRECATED_; + } callbacks; - /** - * 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; - } cache; + /** + * Space where the private data of the server cache used to be + * + * DEPRECATED: + * Use smbc_getServerCacheData(), smbc_setServerCacheData() + */ + void * reserved; /* space where server_cache_data used to be */ /* * Very old configuration options. * - * Manually setting/retrieving this value is deprecated. + * DEPRECATED: * Use one of the following functions instead: * smbc_setOptionUseKerberos() * smbc_getOptionUseKerberos() @@ -2783,24 +2781,21 @@ struct _SMBCCTX { * smbc_setOptionNoAutoAnonymousLogin() * smbc_getOptionNoAutoAnonymousLogin() */ - struct - { - int bits; - } flags; + int flags _DEPRECATED_; - /** user options selections that apply to this session - * - * NEW CODE SHOULD NOT DIRECTLY MANIPULATE THE CONTEXT STRUCTURE. + /** + * user options selections that apply to this session * - * NEW OPTIONS ARE NOT ADDED HERE! + * NEW OPTIONS ARE NOT ADDED HERE! * - * To set and retrieve options, use the smbc_setOption*() and - * smbc_getOption*() functions. + * DEPRECATED: + * To set and retrieve options, use the smbc_setOption*() and + * smbc_getOption*() functions. */ struct _smbc_options { - int browse_max_lmb_count; - int urlencode_readdir_entries; - int one_share_per_server; + int browse_max_lmb_count _DEPRECATED_; + int urlencode_readdir_entries _DEPRECATED_; + int one_share_per_server _DEPRECATED_; } options; /** INTERNAL DATA diff --git a/source3/libsmb/libsmb_cache.c b/source3/libsmb/libsmb_cache.c index c45aba4544..bfacea368d 100644 --- a/source3/libsmb/libsmb_cache.c +++ b/source3/libsmb/libsmb_cache.c @@ -88,7 +88,7 @@ SMBC_add_cached_server(SMBCCTX * context, goto failed; } - DLIST_ADD((context->cache.server_cache_data), srvcache); + DLIST_ADD(context->internal->server_cache, srvcache); return 0; failed: @@ -118,7 +118,7 @@ SMBC_get_cached_server(SMBCCTX * context, struct smbc_server_cache * srv = NULL; /* Search the cache lines */ - for (srv = context->cache.server_cache_data; srv; srv = srv->next) { + for (srv = context->internal->server_cache; srv; srv = srv->next) { if (strcmp(server,srv->server_name) == 0 && strcmp(workgroup,srv->workgroup) == 0 && @@ -150,7 +150,7 @@ SMBC_get_cached_server(SMBCCTX * context, * a connection to the server (other than the * attribute server connection) is cool. */ - if (context->options.one_share_per_server) { + if (smbc_getOptionOneSharePerServer(context)) { /* * The currently connected share name * doesn't match the requested share, so @@ -160,7 +160,7 @@ SMBC_get_cached_server(SMBCCTX * context, /* Sigh. Couldn't disconnect. */ cli_shutdown(srv->server->cli); srv->server->cli = NULL; - context->cache.remove_cached_server_fn(context, srv->server); + smbc_getFunctionRemoveCachedServer(context)(context, srv->server); continue; } @@ -175,7 +175,7 @@ SMBC_get_cached_server(SMBCCTX * context, /* Out of memory. */ cli_shutdown(srv->server->cli); srv->server->cli = NULL; - context->cache.remove_cached_server_fn(context, srv->server); + smbc_getFunctionRemoveCachedServer(context)(context, srv->server); continue; } @@ -200,11 +200,11 @@ SMBC_remove_cached_server(SMBCCTX * context, { struct smbc_server_cache * srv = NULL; - for (srv = context->cache.server_cache_data; srv; srv = srv->next) { + for (srv = context->internal->server_cache; srv; srv = srv->next) { if (server == srv->server) { /* remove this sucker */ - DLIST_REMOVE(context->cache.server_cache_data, srv); + DLIST_REMOVE(context->internal->server_cache, srv); SAFE_FREE(srv->server_name); SAFE_FREE(srv->share_name); SAFE_FREE(srv->workgroup); @@ -229,7 +229,7 @@ SMBC_purge_cached_servers(SMBCCTX * context) struct smbc_server_cache * next; int could_not_purge_all = 0; - for (srv = context->cache.server_cache_data, + for (srv = context->internal->server_cache, next = (srv ? srv->next :NULL); srv; srv = next, diff --git a/source3/libsmb/libsmb_context.c b/source3/libsmb/libsmb_context.c index c107ab2220..c04f751696 100644 --- a/source3/libsmb/libsmb_context.c +++ b/source3/libsmb/libsmb_context.c @@ -46,11 +46,6 @@ smbc_new_context(void) * All newly added context fields should be placed in * SMBC_internal_data, not directly in SMBCCTX. */ -#undef OLD -#define OLD(field) context->field -#undef NEW -#define NEW(field) context->internal->field - context = SMB_MALLOC_P(SMBCCTX); if (!context) { errno = ENOMEM; @@ -69,61 +64,59 @@ smbc_new_context(void) /* Initialize the context and establish reasonable defaults */ ZERO_STRUCTP(context->internal); - OLD(config.debug) = 0; - OLD(config.timeout) = 20000; /* 20 seconds */ - - NEW(full_time_names) = False; - NEW(share_mode) = SMBC_SHAREMODE_DENY_NONE; - NEW(smb_encryption_level) = 0; - OLD(options.browse_max_lmb_count) = 3; /* # LMBs to query */ - OLD(options.urlencode_readdir_entries) = False; - OLD(options.one_share_per_server) = False; - - OLD(server.get_auth_data_fn) = SMBC_get_auth_data; - OLD(server.check_server_fn) = SMBC_check_server; - OLD(server.remove_unused_server_fn) = SMBC_remove_unused_server; - - OLD(cache.server_cache_data) = NULL; - OLD(cache.add_cached_server_fn) = SMBC_add_cached_server; - OLD(cache.get_cached_server_fn) = SMBC_get_cached_server; - OLD(cache.remove_cached_server_fn) = SMBC_remove_cached_server; - OLD(cache.purge_cached_servers_fn) = SMBC_purge_cached_servers; - - OLD(posix_emu.open_fn) = SMBC_open_ctx; - OLD(posix_emu.creat_fn) = SMBC_creat_ctx; - OLD(posix_emu.read_fn) = SMBC_read_ctx; - OLD(posix_emu.write_fn) = SMBC_write_ctx; - OLD(posix_emu.close_fn) = SMBC_close_ctx; - OLD(posix_emu.unlink_fn) = SMBC_unlink_ctx; - OLD(posix_emu.rename_fn) = SMBC_rename_ctx; - OLD(posix_emu.lseek_fn) = SMBC_lseek_ctx; - NEW(posix_emu.ftruncate_fn) = SMBC_ftruncate_ctx; - OLD(posix_emu.stat_fn) = SMBC_stat_ctx; - OLD(posix_emu.fstat_fn) = SMBC_fstat_ctx; - OLD(posix_emu.opendir_fn) = SMBC_opendir_ctx; - OLD(posix_emu.closedir_fn) = SMBC_closedir_ctx; - OLD(posix_emu.readdir_fn) = SMBC_readdir_ctx; - OLD(posix_emu.getdents_fn) = SMBC_getdents_ctx; - OLD(posix_emu.mkdir_fn) = SMBC_mkdir_ctx; - OLD(posix_emu.rmdir_fn) = SMBC_rmdir_ctx; - OLD(posix_emu.telldir_fn) = SMBC_telldir_ctx; - OLD(posix_emu.lseekdir_fn) = SMBC_lseekdir_ctx; - OLD(posix_emu.fstatdir_fn) = SMBC_fstatdir_ctx; - OLD(posix_emu.chmod_fn) = SMBC_chmod_ctx; - OLD(posix_emu.utimes_fn) = SMBC_utimes_ctx; - OLD(posix_emu.setxattr_fn) = SMBC_setxattr_ctx; - OLD(posix_emu.getxattr_fn) = SMBC_getxattr_ctx; - OLD(posix_emu.removexattr_fn) = SMBC_removexattr_ctx; - OLD(posix_emu.listxattr_fn) = SMBC_listxattr_ctx; - - OLD(printing.open_print_job_fn) = SMBC_open_print_job_ctx; - OLD(printing.print_file_fn) = SMBC_print_file_ctx; - OLD(printing.list_print_jobs_fn) = SMBC_list_print_jobs_ctx; - OLD(printing.unlink_print_job_fn) = SMBC_unlink_print_job_ctx; + smbc_setDebug(context, 0); + smbc_setTimeout(context, 20000); + + smbc_setOptionFullTimeNames(context, False); + smbc_setOptionOpenShareMode(context, SMBC_SHAREMODE_DENY_NONE); + smbc_setOptionSmbEncryptionLevel(context, SMBC_ENCRYPTLEVEL_NONE); + smbc_setOptionBrowseMaxLmbCount(context, 3); /* # LMBs to query */ + smbc_setOptionUrlEncodeReaddirEntries(context, False); + smbc_setOptionOneSharePerServer(context, False); + + smbc_setFunctionAuthData(context, SMBC_get_auth_data); + smbc_setFunctionCheckServer(context, SMBC_check_server); + smbc_setFunctionRemoveUnusedServer(context, SMBC_remove_unused_server); + + smbc_setOptionUserData(context, NULL); + smbc_setFunctionAddCachedServer(context, SMBC_add_cached_server); + smbc_setFunctionGetCachedServer(context, SMBC_get_cached_server); + smbc_setFunctionRemoveCachedServer(context, SMBC_remove_cached_server); + smbc_setFunctionPurgeCachedServers(context, SMBC_purge_cached_servers); + + smbc_setFunctionOpen(context, SMBC_open_ctx); + smbc_setFunctionCreat(context, SMBC_creat_ctx); + smbc_setFunctionRead(context, SMBC_read_ctx); + smbc_setFunctionWrite(context, SMBC_write_ctx); + smbc_setFunctionClose(context, SMBC_close_ctx); + smbc_setFunctionUnlink(context, SMBC_unlink_ctx); + smbc_setFunctionRename(context, SMBC_rename_ctx); + smbc_setFunctionLseek(context, SMBC_lseek_ctx); + smbc_setFunctionFtruncate(context, SMBC_ftruncate_ctx); + smbc_setFunctionStat(context, SMBC_stat_ctx); + smbc_setFunctionFstat(context, SMBC_fstat_ctx); + smbc_setFunctionOpendir(context, SMBC_opendir_ctx); + smbc_setFunctionClosedir(context, SMBC_closedir_ctx); + smbc_setFunctionReaddir(context, SMBC_readdir_ctx); + smbc_setFunctionGetdents(context, SMBC_getdents_ctx); + smbc_setFunctionMkdir(context, SMBC_mkdir_ctx); + smbc_setFunctionRmdir(context, SMBC_rmdir_ctx); + smbc_setFunctionTelldir(context, SMBC_telldir_ctx); + smbc_setFunctionLseekdir(context, SMBC_lseekdir_ctx); + smbc_setFunctionFstatdir(context, SMBC_fstatdir_ctx); + smbc_setFunctionChmod(context, SMBC_chmod_ctx); + smbc_setFunctionUtimes(context, SMBC_utimes_ctx); + smbc_setFunctionSetxattr(context, SMBC_setxattr_ctx); + smbc_setFunctionGetxattr(context, SMBC_getxattr_ctx); + smbc_setFunctionRemovexattr(context, SMBC_removexattr_ctx); + smbc_setFunctionListxattr(context, SMBC_listxattr_ctx); + + smbc_setFunctionOpenPrintJob(context, SMBC_open_print_job_ctx); + smbc_setFunctionPrintFile(context, SMBC_print_file_ctx); + smbc_setFunctionListPrintJobs(context, SMBC_list_print_jobs_ctx); + smbc_setFunctionUnlinkPrintJob(context, SMBC_unlink_print_job_ctx); return context; -#undef OLD -#undef NEW } /* @@ -148,13 +141,13 @@ smbc_free_context(SMBCCTX *context, f = context->internal->files; while (f) { - (context->posix_emu.close_fn)(context, f); + smbc_getFunctionClose(context)(context, f); f = f->next; } context->internal->files = NULL; /* First try to remove the servers the nice way. */ - if (context->cache.purge_cached_servers_fn(context)) { + if (smbc_getFunctionPurgeCachedServers(context)(context)) { SMBCSRV * s; SMBCSRV * next; DEBUG(1, ("Could not purge all servers, " @@ -164,7 +157,7 @@ smbc_free_context(SMBCCTX *context, DEBUG(1, ("Forced shutdown: %p (fd=%d)\n", s, s->cli->fd)); cli_shutdown(s->cli); - (context->cache.remove_cached_server_fn)(context, + smbc_getFunctionRemoveCachedServer(context)(context, s); next = s->next; DLIST_REMOVE(context->internal->servers, s); @@ -176,7 +169,7 @@ smbc_free_context(SMBCCTX *context, } else { /* This is the polite way */ - if ((context->cache.purge_cached_servers_fn)(context)) { + if (smbc_getFunctionPurgeCachedServers(context)(context)) { DEBUG(1, ("Could not purge all servers, " "free_context failed.\n")); errno = EBUSY; @@ -197,9 +190,14 @@ smbc_free_context(SMBCCTX *context, } /* Things we have to clean up */ - SAFE_FREE(context->config.workgroup); - SAFE_FREE(context->config.netbios_name); - SAFE_FREE(context->config.user); + free(smbc_getWorkgroup(context)); + smbc_setWorkgroup(context, NULL); + + free(smbc_getNetbiosName(context)); + smbc_setNetbiosName(context, NULL); + + free(smbc_getUser(context)); + smbc_setUser(context, NULL); DEBUG(3, ("Context %p successfully freed\n", context)); SAFE_FREE(context); @@ -298,8 +296,6 @@ void * smbc_option_get(SMBCCTX *context, char *option_name) { - int bits; - if (strcmp(option_name, "debug_stderr") == 0) { #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) return (void *) (intptr_t) smbc_getOptionDebugToStderr(context); @@ -376,7 +372,6 @@ smbc_option_get(SMBCCTX *context, #endif } else if (strcmp(option_name, "use_kerberos") == 0) { - bits = context->flags.bits; #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) return (void *) (intptr_t) smbc_getOptionUseKerberos(context); #else @@ -427,9 +422,9 @@ smbc_init_context(SMBCCTX *context) return NULL; } - if (!context->server.get_auth_data_fn || - context->config.debug < 0 || - context->config.debug > 100) { + if (!smbc_getFunctionAuthData(context) || + smbc_getDebug(context) < 0 || + smbc_getDebug(context) > 100) { errno = EINVAL; return NULL; @@ -444,9 +439,6 @@ smbc_init_context(SMBCCTX *context) bool conf_loaded = False; TALLOC_CTX *frame = talloc_stackframe(); - /* Set this to what the user wants */ - DEBUGLEVEL = context->config.debug; - load_case_tables(); setup_logging("libsmbclient", True); @@ -521,58 +513,84 @@ smbc_init_context(SMBCCTX *context) TALLOC_FREE(frame); } - if (!context->config.user) { + if (!smbc_getUser(context)) { /* * FIXME: Is this the best way to get the user info? */ user = getenv("USER"); /* walk around as "guest" if no username can be found */ - if (!user) context->config.user = SMB_STRDUP("guest"); - else context->config.user = SMB_STRDUP(user); + if (!user) { + user = SMB_STRDUP("guest"); + } else { + user = SMB_STRDUP(user); + } + + if (!user) { + errno = ENOMEM; + return NULL; + } + + smbc_setUser(context, user); } - if (!context->config.netbios_name) { + if (!smbc_getNetbiosName(context)) { /* * We try to get our netbios name from the config. If that * fails we fall back on constructing our netbios name from * our hostname etc */ + char *netbios_name; if (global_myname()) { - context->config.netbios_name = SMB_STRDUP(global_myname()); - } - else { + netbios_name = SMB_STRDUP(global_myname()); + } else { /* * Hmmm, I want to get hostname as well, but I am too * lazy for the moment */ pid = sys_getpid(); - context->config.netbios_name = (char *)SMB_MALLOC(17); - if (!context->config.netbios_name) { + netbios_name = (char *)SMB_MALLOC(17); + if (!netbios_name) { errno = ENOMEM; return NULL; } - slprintf(context->config.netbios_name, 16, - "smbc%s%d", context->config.user, pid); + slprintf(netbios_name, 16, + "smbc%s%d", smbc_getUser(context), pid); } + + if (!netbios_name) { + errno = ENOMEM; + return NULL; + } + + smbc_setNetbiosName(context, netbios_name); } - DEBUG(1, ("Using netbios name %s.\n", context->config.netbios_name)); + DEBUG(1, ("Using netbios name %s.\n", smbc_getNetbiosName(context))); - if (!context->config.workgroup) { + if (!smbc_getWorkgroup(context)) { + char *workgroup; + if (lp_workgroup()) { - context->config.workgroup = SMB_STRDUP(lp_workgroup()); + workgroup = SMB_STRDUP(lp_workgroup()); } else { /* TODO: Think about a decent default workgroup */ - context->config.workgroup = SMB_STRDUP("samba"); + workgroup = SMB_STRDUP("samba"); } + + if (!workgroup) { + errno = ENOMEM; + return NULL; + } + + smbc_setWorkgroup(context, workgroup); } - DEBUG(1, ("Using workgroup %s.\n", context->config.workgroup)); + DEBUG(1, ("Using workgroup %s.\n", smbc_getWorkgroup(context))); /* shortest timeout is 1 second */ - if (context->config.timeout > 0 && context->config.timeout < 1000) - context->config.timeout = 1000; + if (smbc_getTimeout(context) > 0 && smbc_getTimeout(context) < 1000) + smbc_setTimeout(context, 1000); /* * FIXME: Should we check the function pointers here? @@ -592,879 +610,3 @@ smbc_version(void) } -/** Get the netbios name used for making connections */ -char * -smbc_getNetbiosName(SMBCCTX *c) -{ - return c->config.netbios_name; -} - -/** Set the netbios name used for making connections */ -void -smbc_setNetbiosName(SMBCCTX *c, char * netbios_name) -{ - c->config.netbios_name = netbios_name; -} - -/** Get the workgroup used for making connections */ -char * -smbc_getWorkgroup(SMBCCTX *c) -{ - return c->config.workgroup; -} - -/** Set the workgroup used for making connections */ -void -smbc_setWorkgroup(SMBCCTX *c, char * workgroup) -{ - c->config.workgroup = workgroup; -} - -/** Get the username used for making connections */ -char * -smbc_getUser(SMBCCTX *c) -{ - return c->config.user; -} - -/** Set the username used for making connections */ -void -smbc_setUser(SMBCCTX *c, char * user) -{ - c->config.user = user; -} - -/** Get the debug level */ -int -smbc_getDebug(SMBCCTX *c) -{ - return c->config.debug; -} - -/** Set the debug level */ -void -smbc_setDebug(SMBCCTX *c, int debug) -{ - c->config.debug = debug; -} - -/** - * Get the timeout used for waiting on connections and response data - * (in milliseconds) - */ -int -smbc_getTimeout(SMBCCTX *c) -{ - return c->config.timeout; -} - -/** - * Set the timeout used for waiting on connections and response data - * (in milliseconds) - */ -void -smbc_setTimeout(SMBCCTX *c, int timeout) -{ - c->config.timeout = timeout; -} - -/** Get whether to log to standard error instead of standard output */ -smbc_bool -smbc_getOptionDebugToStderr(SMBCCTX *c) -{ - return c->internal->debug_stderr; -} - -/** Set whether to log to standard error instead of standard output */ -void -smbc_setOptionDebugToStderr(SMBCCTX *c, smbc_bool b) -{ - c->internal->debug_stderr = 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) -{ - return c->internal->full_time_names; -} - -/** - * 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) -{ - c->internal->full_time_names = 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) -{ - return c->internal->share_mode; -} - -/** - * 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) -{ - c->internal->share_mode = share_mode; -} - -/** Retrieve a previously set user data handle */ -void * -smbc_getOptionUserData(SMBCCTX *c) -{ - return c->internal->user_data; -} - -/** Save a user data handle */ -void -smbc_setOptionUserData(SMBCCTX *c, void *user_data) -{ - c->internal->user_data = user_data; -} - -/** Get the encoded value for encryption level. */ -smbc_smb_encrypt_level -smbc_getOptionSmbEncryptionLevel(SMBCCTX *c) -{ - return c->internal->smb_encryption_level; -} - -/** Set the encoded value for encryption level. */ -void -smbc_setOptionSmbEncryptionLevel(SMBCCTX *c, smbc_smb_encrypt_level level) -{ - c->internal->smb_encryption_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) -{ - return c->options.browse_max_lmb_count; -} - -/** - * 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) -{ - c->options.browse_max_lmb_count = 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) -{ - return c->options.urlencode_readdir_entries; -} - -/** - * 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) -{ - c->options.urlencode_readdir_entries = 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) -{ - return c->options.one_share_per_server; -} - -/** - * 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) -{ - c->options.one_share_per_server = b; -} - -/** Get whether to enable use of kerberos */ -smbc_bool -smbc_getOptionUseKerberos(SMBCCTX *c) -{ - return c->flags.bits & SMB_CTX_FLAG_USE_KERBEROS ? True : False; -} - -/** Set whether to enable use of kerberos */ -void -smbc_setOptionUseKerberos(SMBCCTX *c, smbc_bool b) -{ - if (b) { - c->flags.bits |= SMB_CTX_FLAG_USE_KERBEROS; - } else { - c->flags.bits &= ~SMB_CTX_FLAG_USE_KERBEROS; - } -} - -/** Get whether to fallback after kerberos */ -smbc_bool -smbc_getOptionFallbackAfterKerberos(SMBCCTX *c) -{ - return c->flags.bits & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS ? True : False; -} - -/** Set whether to fallback after kerberos */ -void -smbc_setOptionFallbackAfterKerberos(SMBCCTX *c, smbc_bool b) -{ - if (b) { - c->flags.bits |= SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS; - } else { - c->flags.bits &= ~SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS; - } -} - -/** Get whether to automatically select anonymous login */ -smbc_bool -smbc_getOptionNoAutoAnonymousLogin(SMBCCTX *c) -{ - return c->flags.bits & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON ? True : False; -} - -/** Set whether to automatically select anonymous login */ -void -smbc_setOptionNoAutoAnonymousLogin(SMBCCTX *c, smbc_bool b) -{ - if (b) { - c->flags.bits |= SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON; - } else { - c->flags.bits &= ~SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON; - } -} - -/** Get the function for obtaining authentication data */ -smbc_get_auth_data_fn -smbc_getFunctionAuthData(SMBCCTX *c) -{ - return c->server.get_auth_data_fn; -} - -/** Set the function for obtaining authentication data */ -void -smbc_setFunctionAuthData(SMBCCTX *c, smbc_get_auth_data_fn fn) -{ - c->internal->auth_fn_with_context = NULL; - c->server.get_auth_data_fn = fn; -} - -/** Get the new-style authentication function which includes the context. */ -smbc_get_auth_data_with_context_fn -smbc_getFunctionAuthDataWithContext(SMBCCTX *c) -{ - return c->internal->auth_fn_with_context; -} - -/** Set the new-style authentication function which includes the context. */ -void -smbc_setFunctionAuthDataWithContext(SMBCCTX *c, - smbc_get_auth_data_with_context_fn fn) -{ - c->server.get_auth_data_fn = NULL; - c->internal->auth_fn_with_context = fn; -} - -/** Get the function for checking if a server is still good */ -smbc_check_server_fn -smbc_getFunctionCheckServer(SMBCCTX *c) -{ - return c->server.check_server_fn; -} - -/** Set the function for checking if a server is still good */ -void -smbc_setFunctionCheckServer(SMBCCTX *c, smbc_check_server_fn fn) -{ - c->server.check_server_fn = fn; -} - -/** Get the function for removing a server if unused */ -smbc_remove_unused_server_fn -smbc_getFunctionRemoveUnusedServer(SMBCCTX *c) -{ - return c->server.remove_unused_server_fn; -} - -/** Set the function for removing a server if unused */ -void -smbc_setFunctionRemoveUnusedServer(SMBCCTX *c, - smbc_remove_unused_server_fn fn) -{ - c->server.remove_unused_server_fn = fn; -} - -/** Get the function to store private data of the server cache */ -struct -smbc_server_cache * smbc_getServerCacheData(SMBCCTX *c) -{ - return c->cache.server_cache_data; -} - -/** Set the function to store private data of the server cache */ -void -smbc_setServerCacheData(SMBCCTX *c, struct smbc_server_cache * cache) -{ - c->cache.server_cache_data = cache; -} - - -/** Get the function for adding a cached server */ -smbc_add_cached_srv_fn -smbc_getFunctionAddCachedServer(SMBCCTX *c) -{ - return c->cache.add_cached_server_fn; -} - -/** Set the function for adding a cached server */ -void -smbc_setFunctionAddCachedServer(SMBCCTX *c, smbc_add_cached_srv_fn fn) -{ - c->cache.add_cached_server_fn = fn; -} - -/** Get the function for server cache lookup */ -smbc_get_cached_srv_fn -smbc_getFunctionGetCachedServer(SMBCCTX *c) -{ - return c->cache.get_cached_server_fn; -} - -/** Set the function for server cache lookup */ -void -smbc_setFunctionGetCachedServer(SMBCCTX *c, smbc_get_cached_srv_fn fn) -{ - c->cache.get_cached_server_fn = fn; -} - -/** Get the function for server cache removal */ -smbc_remove_cached_srv_fn -smbc_getFunctionRemoveCachedServer(SMBCCTX *c) -{ - return c->cache.remove_cached_server_fn; -} - -/** Set the function for server cache removal */ -void -smbc_setFunctionRemoveCachedServer(SMBCCTX *c, - smbc_remove_cached_srv_fn fn) -{ - c->cache.remove_cached_server_fn = fn; -} - -/** - * Get the function for server cache purging. This function tries to - * remove all cached servers (e.g. on disconnect) - */ -smbc_purge_cached_srv_fn -smbc_getFunctionPurgeCachedServers(SMBCCTX *c) -{ - return c->cache.purge_cached_servers_fn; -} - -/** - * Set the function for server cache purging. This function tries to - * remove all cached servers (e.g. on disconnect) - */ -void -smbc_setFunctionPurgeCachedServers(SMBCCTX *c, smbc_purge_cached_srv_fn fn) -{ - c->cache.purge_cached_servers_fn = fn; -} - -/** - * Callable functions for files. - */ - -smbc_open_fn -smbc_getFunctionOpen(SMBCCTX *c) -{ - return c->posix_emu.open_fn; -} - -void -smbc_setFunctionOpen(SMBCCTX *c, smbc_open_fn fn) -{ - c->posix_emu.open_fn = fn; -} - -smbc_creat_fn -smbc_getFunctionCreat(SMBCCTX *c) -{ - return c->posix_emu.creat_fn; -} - -void -smbc_setFunctionCreat(SMBCCTX *c, smbc_creat_fn fn) -{ - c->posix_emu.creat_fn = fn; -} - -smbc_read_fn -smbc_getFunctionRead(SMBCCTX *c) -{ - return c->posix_emu.read_fn; -} - -void -smbc_setFunctionRead(SMBCCTX *c, smbc_read_fn fn) -{ - c->posix_emu.read_fn = fn; -} - -smbc_write_fn -smbc_getFunctionWrite(SMBCCTX *c) -{ - return c->posix_emu.write_fn; -} - -void -smbc_setFunctionWrite(SMBCCTX *c, smbc_write_fn fn) -{ - c->posix_emu.write_fn = fn; -} - -smbc_unlink_fn -smbc_getFunctionUnlink(SMBCCTX *c) -{ - return c->posix_emu.unlink_fn; -} - -void -smbc_setFunctionUnlink(SMBCCTX *c, smbc_unlink_fn fn) -{ - c->posix_emu.unlink_fn = fn; -} - -smbc_rename_fn -smbc_getFunctionRename(SMBCCTX *c) -{ - return c->posix_emu.rename_fn; -} - -void -smbc_setFunctionRename(SMBCCTX *c, smbc_rename_fn fn) -{ - c->posix_emu.rename_fn = fn; -} - -smbc_lseek_fn -smbc_getFunctionLseek(SMBCCTX *c) -{ - return c->posix_emu.lseek_fn; -} - -void -smbc_setFunctionLseek(SMBCCTX *c, smbc_lseek_fn fn) -{ - c->posix_emu.lseek_fn = fn; -} - -smbc_stat_fn -smbc_getFunctionStat(SMBCCTX *c) -{ - return c->posix_emu.stat_fn; -} - -void -smbc_setFunctionStat(SMBCCTX *c, smbc_stat_fn fn) -{ - c->posix_emu.stat_fn = fn; -} - -smbc_fstat_fn -smbc_getFunctionFstat(SMBCCTX *c) -{ - return c->posix_emu.fstat_fn; -} - -void -smbc_setFunctionFstat(SMBCCTX *c, smbc_fstat_fn fn) -{ - c->posix_emu.fstat_fn = fn; -} - -smbc_ftruncate_fn -smbc_getFunctionFtruncate(SMBCCTX *c) -{ - return c->internal->posix_emu.ftruncate_fn; -} - -void -smbc_setFunctionFtruncate(SMBCCTX *c, smbc_ftruncate_fn fn) -{ - c->internal->posix_emu.ftruncate_fn = fn; -} - -smbc_close_fn -smbc_getFunctionClose(SMBCCTX *c) -{ - return c->posix_emu.close_fn; -} - -void -smbc_setFunctionClose(SMBCCTX *c, smbc_close_fn fn) -{ - c->posix_emu.close_fn = fn; -} - - -/** - * Callable functions for directories. - */ - -smbc_opendir_fn -smbc_getFunctionOpendir(SMBCCTX *c) -{ - return c->posix_emu.opendir_fn; -} - -void -smbc_setFunctionOpendir(SMBCCTX *c, smbc_opendir_fn fn) -{ - c->posix_emu.opendir_fn = fn; -} - -smbc_closedir_fn -smbc_getFunctionClosedir(SMBCCTX *c) -{ - return c->posix_emu.closedir_fn; -} - -void -smbc_setFunctionClosedir(SMBCCTX *c, smbc_closedir_fn fn) -{ - c->posix_emu.closedir_fn = fn; -} - -smbc_readdir_fn -smbc_getFunctionReaddir(SMBCCTX *c) -{ - return c->posix_emu.readdir_fn; -} - -void -smbc_setFunctionReaddir(SMBCCTX *c, smbc_readdir_fn fn) -{ - c->posix_emu.readdir_fn = fn; -} - -smbc_getdents_fn -smbc_getFunctionGetdents(SMBCCTX *c) -{ - return c->posix_emu.getdents_fn; -} - -void -smbc_setFunctionGetdents(SMBCCTX *c, smbc_getdents_fn fn) -{ - c->posix_emu.getdents_fn = fn; -} - -smbc_mkdir_fn -smbc_getFunctionMkdir(SMBCCTX *c) -{ - return c->posix_emu.mkdir_fn; -} - -void -smbc_setFunctionMkdir(SMBCCTX *c, smbc_mkdir_fn fn) -{ - c->posix_emu.mkdir_fn = fn; -} - -smbc_rmdir_fn -smbc_getFunctionRmdir(SMBCCTX *c) -{ - return c->posix_emu.rmdir_fn; -} - -void -smbc_setFunctionRmdir(SMBCCTX *c, smbc_rmdir_fn fn) -{ - c->posix_emu.rmdir_fn = fn; -} - -smbc_telldir_fn -smbc_getFunctionTelldir(SMBCCTX *c) -{ - return c->posix_emu.telldir_fn; -} - -void -smbc_setFunctionTelldir(SMBCCTX *c, smbc_telldir_fn fn) -{ - c->posix_emu.telldir_fn = fn; -} - -smbc_lseekdir_fn -smbc_getFunctionLseekdir(SMBCCTX *c) -{ - return c->posix_emu.lseekdir_fn; -} - -void -smbc_setFunctionLseekdir(SMBCCTX *c, smbc_lseekdir_fn fn) -{ - c->posix_emu.lseekdir_fn = fn; -} - -smbc_fstatdir_fn -smbc_getFunctionFstatdir(SMBCCTX *c) -{ - return c->posix_emu.fstatdir_fn; -} - -void -smbc_setFunctionFstatdir(SMBCCTX *c, smbc_fstatdir_fn fn) -{ - c->posix_emu.fstatdir_fn = fn; -} - - -/** - * Callable functions applicable to both files and directories. - */ - -smbc_chmod_fn -smbc_getFunctionChmod(SMBCCTX *c) -{ - return c->posix_emu.chmod_fn; -} - -void -smbc_setFunctionChmod(SMBCCTX *c, smbc_chmod_fn fn) -{ - c->posix_emu.chmod_fn = fn; -} - -smbc_utimes_fn -smbc_getFunctionUtimes(SMBCCTX *c) -{ - return c->posix_emu.utimes_fn; -} - -void -smbc_setFunctionUtimes(SMBCCTX *c, smbc_utimes_fn fn) -{ - c->posix_emu.utimes_fn = fn; -} - -smbc_setxattr_fn -smbc_getFunctionSetxattr(SMBCCTX *c) -{ - return c->posix_emu.setxattr_fn; -} - -void -smbc_setFunctionSetxattr(SMBCCTX *c, smbc_setxattr_fn fn) -{ - c->posix_emu.setxattr_fn = fn; -} - -smbc_getxattr_fn -smbc_getFunctionGetxattr(SMBCCTX *c) -{ - return c->posix_emu.getxattr_fn; -} - -void -smbc_setFunctionGetxattr(SMBCCTX *c, smbc_getxattr_fn fn) -{ - c->posix_emu.getxattr_fn = fn; -} - -smbc_removexattr_fn -smbc_getFunctionRemovexattr(SMBCCTX *c) -{ - return c->posix_emu.removexattr_fn; -} - -void -smbc_setFunctionRemovexattr(SMBCCTX *c, smbc_removexattr_fn fn) -{ - c->posix_emu.removexattr_fn = fn; -} - -smbc_listxattr_fn -smbc_getFunctionListxattr(SMBCCTX *c) -{ - return c->posix_emu.listxattr_fn; -} - -void -smbc_setFunctionListxattr(SMBCCTX *c, smbc_listxattr_fn fn) -{ - c->posix_emu.listxattr_fn = fn; -} - - -/** - * Callable functions related to printing - */ - -smbc_print_file_fn -smbc_getFunctionPrintFile(SMBCCTX *c) -{ - return c->printing.print_file_fn; -} - -void -smbc_setFunctionPrintFile(SMBCCTX *c, smbc_print_file_fn fn) -{ - c->printing.print_file_fn = fn; -} - -smbc_open_print_job_fn -smbc_getFunctionOpenPrintJob(SMBCCTX *c) -{ - return c->printing.open_print_job_fn; -} - -void -smbc_setFunctionOpenPrintJob(SMBCCTX *c, - smbc_open_print_job_fn fn) -{ - c->printing.open_print_job_fn = fn; -} - -smbc_list_print_jobs_fn -smbc_getFunctionListPrintJobs(SMBCCTX *c) -{ - return c->printing.list_print_jobs_fn; -} - -void -smbc_setFunctionListPrintJobs(SMBCCTX *c, - smbc_list_print_jobs_fn fn) -{ - c->printing.list_print_jobs_fn = fn; -} - -smbc_unlink_print_job_fn -smbc_getFunctionUnlinkPrintJob(SMBCCTX *c) -{ - return c->printing.unlink_print_job_fn; -} - -void -smbc_setFunctionUnlinkPrintJob(SMBCCTX *c, - smbc_unlink_print_job_fn fn) -{ - c->printing.unlink_print_job_fn = fn; -} - diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 2ece2ab8ed..1486097d51 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -404,7 +404,7 @@ SMBC_opendir_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -450,9 +450,9 @@ SMBC_opendir_ctx(SMBCCTX *context, } /* Determine how many local master browsers to query */ - max_lmb_count = (context->options.browse_max_lmb_count == 0 + max_lmb_count = (smbc_getOptionBrowseMaxLmbCount(context) == 0 ? INT_MAX - : context->options.browse_max_lmb_count); + : smbc_getOptionBrowseMaxLmbCount(context)); memset(&u_info, '\0', sizeof(u_info)); u_info.username = talloc_strdup(frame,user); @@ -810,11 +810,11 @@ SMBC_opendir_ctx(SMBCCTX *context, * good any more... */ if (cli_is_error(targetcli) && - (context->server.check_server_fn)(context, srv)) { + smbc_getFunctionCheckServer(context)(context, srv)) { /* ... then remove it. */ - if ((context->server.remove_unused_server_fn)(context, - srv)) { + if (smbc_getFunctionRemoveUnusedServer(context)(context, + srv)) { /* * We could not remove the * server completely, remove @@ -823,7 +823,7 @@ SMBC_opendir_ctx(SMBCCTX *context, * will be removed when the * last file/dir is closed. */ - (context->cache.remove_cached_server_fn)(context, srv); + smbc_getFunctionRemoveCachedServer(context)(context, srv); } } @@ -884,7 +884,7 @@ smbc_readdir_internal(SMBCCTX * context, struct smbc_dirent *src, int max_namebuf_len) { - if (context->options.urlencode_readdir_entries) { + if (smbc_getOptionUrlEncodeReaddirEntries(context)) { /* url-encode the name. get back remaining buffer space */ max_namebuf_len = @@ -1142,7 +1142,7 @@ SMBC_mkdir_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1249,7 +1249,7 @@ SMBC_rmdir_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1531,7 +1531,7 @@ SMBC_chmod_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1637,7 +1637,7 @@ SMBC_utimes_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1713,7 +1713,7 @@ SMBC_unlink_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1848,7 +1848,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, } if (!user1 || user1[0] == (char)0) { - user1 = talloc_strdup(frame, ocontext->config.user); + user1 = talloc_strdup(frame, smbc_getUser(ocontext)); if (!user1) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1872,7 +1872,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, } if (!user2 || user2[0] == (char)0) { - user2 = talloc_strdup(frame, ncontext->config.user); + user2 = talloc_strdup(frame, smbc_getUser(ncontext)); if (!user2) { errno = ENOMEM; TALLOC_FREE(frame); diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c index 73c9b96978..423450b23e 100644 --- a/source3/libsmb/libsmb_file.c +++ b/source3/libsmb/libsmb_file.c @@ -82,7 +82,7 @@ SMBC_open_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -188,7 +188,7 @@ SMBC_open_ctx(SMBCCTX *context, int eno = 0; eno = SMBC_errno(context, srv->cli); - file = (context->posix_emu.opendir_fn)(context, fname); + file = smbc_getFunctionOpendir(context)(context, fname); if (!file) errno = eno; TALLOC_FREE(frame); return file; @@ -439,7 +439,7 @@ SMBC_close_ctx(SMBCCTX *context, /* IS a dir ... */ if (!file->file) { TALLOC_FREE(frame); - return (context->posix_emu.closedir_fn)(context, file); + return smbc_getFunctionClosedir(context)(context, file); } /*d_printf(">>>close: parsing %s\n", file->fname);*/ @@ -478,7 +478,7 @@ SMBC_close_ctx(SMBCCTX *context, DLIST_REMOVE(context->internal->files, file); SAFE_FREE(file->fname); SAFE_FREE(file); - (context->server.remove_unused_server_fn)(context, srv); + smbc_getFunctionRemoveUnusedServer(context)(context, srv); TALLOC_FREE(frame); return -1; diff --git a/source3/libsmb/libsmb_path.c b/source3/libsmb/libsmb_path.c index c962f898e0..2c3a5f8866 100644 --- a/source3/libsmb/libsmb_path.c +++ b/source3/libsmb/libsmb_path.c @@ -253,7 +253,7 @@ SMBC_parse_path(TALLOC_CTX *ctx, */ if (pp_workgroup != NULL) { *pp_workgroup = - talloc_strdup(ctx, context->config.workgroup); + talloc_strdup(ctx, smbc_getWorkgroup(context)); } if (pp_options) { @@ -297,13 +297,13 @@ SMBC_parse_path(TALLOC_CTX *ctx, } if (*p == '/') { - int wl = strlen(context->config.workgroup); + int wl = strlen(smbc_getWorkgroup(context)); if (wl > 16) { wl = 16; } - *pp_server = talloc_strdup(ctx, context->config.workgroup); + *pp_server = talloc_strdup(ctx, smbc_getWorkgroup(context)); if (!*pp_server) { return -1; } diff --git a/source3/libsmb/libsmb_printjob.c b/source3/libsmb/libsmb_printjob.c index 545225cae4..c8d7ad039d 100644 --- a/source3/libsmb/libsmb_printjob.c +++ b/source3/libsmb/libsmb_printjob.c @@ -75,7 +75,7 @@ SMBC_open_print_job_ctx(SMBCCTX *context, /* What if the path is empty, or the file exists? */ TALLOC_FREE(frame); - return (context->posix_emu.open_fn)(context, fname, O_WRONLY, 666); + return smbc_getFunctionOpen(context)(context, fname, O_WRONLY, 666); } /* @@ -222,7 +222,7 @@ SMBC_list_print_jobs_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -300,7 +300,7 @@ SMBC_unlink_print_job_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 4f51388870..64eb1ea584 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -80,7 +80,7 @@ SMBC_remove_unused_server(SMBCCTX * context, DEBUG(3, ("smbc_remove_usused_server: %p removed.\n", srv)); - (context->cache.remove_cached_server_fn)(context, srv); + smbc_getFunctionRemoveCachedServer(context)(context, srv); SAFE_FREE(srv); return 0; @@ -106,11 +106,10 @@ SMBC_call_auth_fn(TALLOC_CTX *ctx, 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)); + smbc_getFunctionAuthData(context)(server, share, + workgroup, sizeof(workgroup), + username, sizeof(username), + password, sizeof(password)); TALLOC_FREE(*pp_workgroup); TALLOC_FREE(*pp_username); @@ -147,10 +146,10 @@ SMBC_find_server(TALLOC_CTX *ctx, check_server_cache: - srv = (context->cache.get_cached_server_fn)(context, - server, share, - *pp_workgroup, - *pp_username); + srv = smbc_getFunctionGetCachedServer(context)(context, + server, share, + *pp_workgroup, + *pp_username); if (!auth_called && !srv && (!*pp_username || !(*pp_username)[0] || !*pp_password || !(*pp_password)[0])) { @@ -172,22 +171,22 @@ check_server_cache: } if (srv) { - if ((context->server.check_server_fn)(context, srv)) { + if (smbc_getFunctionCheckServer(context)(context, srv)) { /* * This server is no good anymore * Try to remove it and check for more possible * servers in the cache */ - if ((context->server.remove_unused_server_fn)(context, - srv)) { + if (smbc_getFunctionRemoveUnusedServer(context)(context, + srv)) { /* * We could not remove the server completely, * remove it from the cache so we will not get * it again. It will be removed when the last * file/dir is closed. */ - (context->cache.remove_cached_server_fn)(context, - srv); + smbc_getFunctionRemoveCachedServer(context)(context, + srv); } /* @@ -251,12 +250,14 @@ SMBC_server(TALLOC_CTX *ctx, * If we found a connection and we're only allowed one share per * server... */ - if (srv && *share != '\0' && context->options.one_share_per_server) { + if (srv && + *share != '\0' && + smbc_getOptionOneSharePerServer(context)) { /* * ... then if there's no current connection to the share, * connect to it. SMBC_find_server(), or rather the function - * pointed to by context->cache.get_cached_srv_fn which + * pointed to by context->get_cached_srv_fn which * was called by SMBC_find_server(), will have issued a tree * disconnect if the requested share is not the same as the * one that was already connected. @@ -272,8 +273,8 @@ SMBC_server(TALLOC_CTX *ctx, errno = ENOMEM; cli_shutdown(srv->cli); srv->cli = NULL; - (context->cache.remove_cached_server_fn)(context, - srv); + smbc_getFunctionRemoveCachedServer(context)(context, + srv); return NULL; } @@ -290,8 +291,8 @@ SMBC_server(TALLOC_CTX *ctx, errno = SMBC_errno(context, srv->cli); cli_shutdown(srv->cli); srv->cli = NULL; - (context->cache.remove_cached_server_fn)(context, - srv); + smbc_getFunctionRemoveCachedServer(context)(context, + srv); srv = NULL; } @@ -324,7 +325,7 @@ SMBC_server(TALLOC_CTX *ctx, return NULL; } - make_nmb_name(&calling, context->config.netbios_name, 0x0); + make_nmb_name(&calling, smbc_getNetbiosName(context), 0x0); make_nmb_name(&called , server, 0x20); DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server)); @@ -341,14 +342,15 @@ again: return NULL; } - if (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS) { + if (smbc_getOptionUseKerberos(context)) { c->use_kerberos = True; } - if (context->flags.bits & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS) { + + if (smbc_getOptionFallbackAfterKerberos(context)) { c->fallback_after_kerberos = True; } - c->timeout = context->config.timeout; + c->timeout = smbc_getTimeout(context); /* * Force use of port 139 for first try if share is $IPC, empty, or @@ -435,8 +437,7 @@ again: /* Failed. Try an anonymous login, if allowed by flags. */ username_used = ""; - if ((context->flags.bits & - SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON) || + if (smbc_getOptionNoAutoAnonymousLogin(context) || !NT_STATUS_IS_OK(cli_session_setup(c, username_used, *pp_password, 1, *pp_password, 0, @@ -504,10 +505,10 @@ again: /* now add it to the cache (internal or external) */ /* Let the cache function set errno if it wants to */ errno = 0; - if ((context->cache.add_cached_server_fn)(context, srv, - server, share, - *pp_workgroup, - *pp_username)) { + if (smbc_getFunctionAddCachedServer(context)(context, srv, + server, share, + *pp_workgroup, + *pp_username)) { int saved_errno = errno; DEBUG(3, (" Failed to add server to cache\n")); errno = saved_errno; @@ -576,7 +577,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, } flags = 0; - if (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS) { + if (smbc_getOptionUseKerberos(context)) { flags |= CLI_FULL_CONNECTION_USE_KERBEROS; } @@ -664,11 +665,11 @@ SMBC_attr_server(TALLOC_CTX *ctx, /* 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, - "*IPC$", - *pp_workgroup, - *pp_username)) { + if (smbc_getFunctionAddCachedServer(context)(context, ipc_srv, + server, + "*IPC$", + *pp_workgroup, + *pp_username)) { DEBUG(3, (" Failed to add server to cache\n")); if (errno == 0) { errno = ENOMEM; diff --git a/source3/libsmb/libsmb_setget.c b/source3/libsmb/libsmb_setget.c new file mode 100644 index 0000000000..d0823bd77e --- /dev/null +++ b/source3/libsmb/libsmb_setget.c @@ -0,0 +1,905 @@ +/* + Unix SMB/Netbios implementation. + SMB client library implementation + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000, 2002 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 3 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, see . +*/ + +#include "includes.h" +#define __LIBSMBCLIENT_INTERNAL__ +#include "libsmbclient.h" +#include "libsmb_internal.h" + + +/** Get the netbios name used for making connections */ +char * +smbc_getNetbiosName(SMBCCTX *c) +{ + return c->netbios_name; +} + +/** Set the netbios name used for making connections */ +void +smbc_setNetbiosName(SMBCCTX *c, char * netbios_name) +{ + c->netbios_name = netbios_name; +} + +/** Get the workgroup used for making connections */ +char * +smbc_getWorkgroup(SMBCCTX *c) +{ + return c->workgroup; +} + +/** Set the workgroup used for making connections */ +void +smbc_setWorkgroup(SMBCCTX *c, char * workgroup) +{ + c->workgroup = workgroup; +} + +/** Get the username used for making connections */ +char * +smbc_getUser(SMBCCTX *c) +{ + return c->user; +} + +/** Set the username used for making connections */ +void +smbc_setUser(SMBCCTX *c, char * user) +{ + c->user = user; +} + +/** Get the debug level */ +int +smbc_getDebug(SMBCCTX *c) +{ + return c->debug; +} + +/** Set the debug level */ +void +smbc_setDebug(SMBCCTX *c, int debug) +{ + c->debug = debug; + DEBUGLEVEL = debug; +} + +/** + * Get the timeout used for waiting on connections and response data + * (in milliseconds) + */ +int +smbc_getTimeout(SMBCCTX *c) +{ + return c->timeout; +} + +/** + * Set the timeout used for waiting on connections and response data + * (in milliseconds) + */ +void +smbc_setTimeout(SMBCCTX *c, int timeout) +{ + c->timeout = timeout; +} + +/** Get whether to log to standard error instead of standard output */ +smbc_bool +smbc_getOptionDebugToStderr(SMBCCTX *c) +{ + return c->internal->debug_stderr; +} + +/** Set whether to log to standard error instead of standard output */ +void +smbc_setOptionDebugToStderr(SMBCCTX *c, smbc_bool b) +{ + c->internal->debug_stderr = 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) +{ + return c->internal->full_time_names; +} + +/** + * 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) +{ + c->internal->full_time_names = 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) +{ + return c->internal->share_mode; +} + +/** + * 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) +{ + c->internal->share_mode = share_mode; +} + +/** Retrieve a previously set user data handle */ +void * +smbc_getOptionUserData(SMBCCTX *c) +{ + return c->internal->user_data; +} + +/** Save a user data handle */ +void +smbc_setOptionUserData(SMBCCTX *c, void *user_data) +{ + c->internal->user_data = user_data; +} + +/** Get the encoded value for encryption level. */ +smbc_smb_encrypt_level +smbc_getOptionSmbEncryptionLevel(SMBCCTX *c) +{ + return c->internal->smb_encryption_level; +} + +/** Set the encoded value for encryption level. */ +void +smbc_setOptionSmbEncryptionLevel(SMBCCTX *c, smbc_smb_encrypt_level level) +{ + c->internal->smb_encryption_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) +{ + return c->options.browse_max_lmb_count; +} + +/** + * 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) +{ + c->options.browse_max_lmb_count = 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) +{ + return c->options.urlencode_readdir_entries; +} + +/** + * 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) +{ + c->options.urlencode_readdir_entries = 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) +{ + return c->options.one_share_per_server; +} + +/** + * 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) +{ + c->options.one_share_per_server = b; +} + +/** Get whether to enable use of kerberos */ +smbc_bool +smbc_getOptionUseKerberos(SMBCCTX *c) +{ + return c->flags & SMB_CTX_FLAG_USE_KERBEROS ? True : False; +} + +/** Set whether to enable use of kerberos */ +void +smbc_setOptionUseKerberos(SMBCCTX *c, smbc_bool b) +{ + if (b) { + c->flags |= SMB_CTX_FLAG_USE_KERBEROS; + } else { + c->flags &= ~SMB_CTX_FLAG_USE_KERBEROS; + } +} + +/** Get whether to fallback after kerberos */ +smbc_bool +smbc_getOptionFallbackAfterKerberos(SMBCCTX *c) +{ + return c->flags & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS ? True : False; +} + +/** Set whether to fallback after kerberos */ +void +smbc_setOptionFallbackAfterKerberos(SMBCCTX *c, smbc_bool b) +{ + if (b) { + c->flags |= SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS; + } else { + c->flags &= ~SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS; + } +} + +/** Get whether to automatically select anonymous login */ +smbc_bool +smbc_getOptionNoAutoAnonymousLogin(SMBCCTX *c) +{ + return c->flags & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON ? True : False; +} + +/** Set whether to automatically select anonymous login */ +void +smbc_setOptionNoAutoAnonymousLogin(SMBCCTX *c, smbc_bool b) +{ + if (b) { + c->flags |= SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON; + } else { + c->flags &= ~SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON; + } +} + +/** Get the function for obtaining authentication data */ +smbc_get_auth_data_fn +smbc_getFunctionAuthData(SMBCCTX *c) +{ + return c->callbacks.auth_fn; +} + +/** Set the function for obtaining authentication data */ +void +smbc_setFunctionAuthData(SMBCCTX *c, smbc_get_auth_data_fn fn) +{ + c->internal->auth_fn_with_context = NULL; + c->callbacks.auth_fn = fn; +} + +/** Get the new-style authentication function which includes the context. */ +smbc_get_auth_data_with_context_fn +smbc_getFunctionAuthDataWithContext(SMBCCTX *c) +{ + return c->internal->auth_fn_with_context; +} + +/** Set the new-style authentication function which includes the context. */ +void +smbc_setFunctionAuthDataWithContext(SMBCCTX *c, + smbc_get_auth_data_with_context_fn fn) +{ + c->callbacks.auth_fn = NULL; + c->internal->auth_fn_with_context = fn; +} + +/** Get the function for checking if a server is still good */ +smbc_check_server_fn +smbc_getFunctionCheckServer(SMBCCTX *c) +{ + return c->callbacks.check_server_fn; +} + +/** Set the function for checking if a server is still good */ +void +smbc_setFunctionCheckServer(SMBCCTX *c, smbc_check_server_fn fn) +{ + c->callbacks.check_server_fn = fn; +} + +/** Get the function for removing a server if unused */ +smbc_remove_unused_server_fn +smbc_getFunctionRemoveUnusedServer(SMBCCTX *c) +{ + return c->callbacks.remove_unused_server_fn; +} + +/** Set the function for removing a server if unused */ +void +smbc_setFunctionRemoveUnusedServer(SMBCCTX *c, + smbc_remove_unused_server_fn fn) +{ + c->callbacks.remove_unused_server_fn = fn; +} + +/** Get the function for adding a cached server */ +smbc_add_cached_srv_fn +smbc_getFunctionAddCachedServer(SMBCCTX *c) +{ + return c->callbacks.add_cached_srv_fn; +} + +/** Set the function for adding a cached server */ +void +smbc_setFunctionAddCachedServer(SMBCCTX *c, smbc_add_cached_srv_fn fn) +{ + c->callbacks.add_cached_srv_fn = fn; +} + +/** Get the function for server cache lookup */ +smbc_get_cached_srv_fn +smbc_getFunctionGetCachedServer(SMBCCTX *c) +{ + return c->callbacks.get_cached_srv_fn; +} + +/** Set the function for server cache lookup */ +void +smbc_setFunctionGetCachedServer(SMBCCTX *c, smbc_get_cached_srv_fn fn) +{ + c->callbacks.get_cached_srv_fn = fn; +} + +/** Get the function for server cache removal */ +smbc_remove_cached_srv_fn +smbc_getFunctionRemoveCachedServer(SMBCCTX *c) +{ + return c->callbacks.remove_cached_srv_fn; +} + +/** Set the function for server cache removal */ +void +smbc_setFunctionRemoveCachedServer(SMBCCTX *c, + smbc_remove_cached_srv_fn fn) +{ + c->callbacks.remove_cached_srv_fn = fn; +} + +/** + * Get the function for server cache purging. This function tries to + * remove all cached servers (e.g. on disconnect) + */ +smbc_purge_cached_fn +smbc_getFunctionPurgeCachedServers(SMBCCTX *c) +{ + return c->callbacks.purge_cached_fn; +} + +/** Set the function to store private data of the server cache */ +void smbc_setServerCacheData(SMBCCTX *c, struct smbc_server_cache * cache) +{ + c->internal->server_cache = cache; +} + +/** Get the function to store private data of the server cache */ +struct smbc_server_cache * smbc_getServerCacheData(SMBCCTX *c) +{ + return c->internal->server_cache; +} + + +/** + * Set the function for server cache purging. This function tries to + * remove all cached servers (e.g. on disconnect) + */ +void +smbc_setFunctionPurgeCachedServers(SMBCCTX *c, smbc_purge_cached_fn fn) +{ + c->callbacks.purge_cached_fn = fn; +} + +/** + * Callable functions for files. + */ + +smbc_open_fn +smbc_getFunctionOpen(SMBCCTX *c) +{ + return c->open; +} + +void +smbc_setFunctionOpen(SMBCCTX *c, smbc_open_fn fn) +{ + c->open = fn; +} + +smbc_creat_fn +smbc_getFunctionCreat(SMBCCTX *c) +{ + return c->creat; +} + +void +smbc_setFunctionCreat(SMBCCTX *c, smbc_creat_fn fn) +{ + c->creat = fn; +} + +smbc_read_fn +smbc_getFunctionRead(SMBCCTX *c) +{ + return c->read; +} + +void +smbc_setFunctionRead(SMBCCTX *c, smbc_read_fn fn) +{ + c->read = fn; +} + +smbc_write_fn +smbc_getFunctionWrite(SMBCCTX *c) +{ + return c->write; +} + +void +smbc_setFunctionWrite(SMBCCTX *c, smbc_write_fn fn) +{ + c->write = fn; +} + +smbc_unlink_fn +smbc_getFunctionUnlink(SMBCCTX *c) +{ + return c->unlink; +} + +void +smbc_setFunctionUnlink(SMBCCTX *c, smbc_unlink_fn fn) +{ + c->unlink = fn; +} + +smbc_rename_fn +smbc_getFunctionRename(SMBCCTX *c) +{ + return c->rename; +} + +void +smbc_setFunctionRename(SMBCCTX *c, smbc_rename_fn fn) +{ + c->rename = fn; +} + +smbc_lseek_fn +smbc_getFunctionLseek(SMBCCTX *c) +{ + return c->lseek; +} + +void +smbc_setFunctionLseek(SMBCCTX *c, smbc_lseek_fn fn) +{ + c->lseek = fn; +} + +smbc_stat_fn +smbc_getFunctionStat(SMBCCTX *c) +{ + return c->stat; +} + +void +smbc_setFunctionStat(SMBCCTX *c, smbc_stat_fn fn) +{ + c->stat = fn; +} + +smbc_fstat_fn +smbc_getFunctionFstat(SMBCCTX *c) +{ + return c->fstat; +} + +void +smbc_setFunctionFstat(SMBCCTX *c, smbc_fstat_fn fn) +{ + c->fstat = fn; +} + +smbc_ftruncate_fn +smbc_getFunctionFtruncate(SMBCCTX *c) +{ + return c->internal->posix_emu.ftruncate_fn; +} + +void +smbc_setFunctionFtruncate(SMBCCTX *c, smbc_ftruncate_fn fn) +{ + c->internal->posix_emu.ftruncate_fn = fn; +} + +smbc_close_fn +smbc_getFunctionClose(SMBCCTX *c) +{ + return c->close_fn; +} + +void +smbc_setFunctionClose(SMBCCTX *c, smbc_close_fn fn) +{ + c->close_fn = fn; +} + + +/** + * Callable functions for directories. + */ + +smbc_opendir_fn +smbc_getFunctionOpendir(SMBCCTX *c) +{ + return c->opendir; +} + +void +smbc_setFunctionOpendir(SMBCCTX *c, smbc_opendir_fn fn) +{ + c->opendir = fn; +} + +smbc_closedir_fn +smbc_getFunctionClosedir(SMBCCTX *c) +{ + return c->closedir; +} + +void +smbc_setFunctionClosedir(SMBCCTX *c, smbc_closedir_fn fn) +{ + c->closedir = fn; +} + +smbc_readdir_fn +smbc_getFunctionReaddir(SMBCCTX *c) +{ + return c->readdir; +} + +void +smbc_setFunctionReaddir(SMBCCTX *c, smbc_readdir_fn fn) +{ + c->readdir = fn; +} + +smbc_getdents_fn +smbc_getFunctionGetdents(SMBCCTX *c) +{ + return c->getdents; +} + +void +smbc_setFunctionGetdents(SMBCCTX *c, smbc_getdents_fn fn) +{ + c->getdents = fn; +} + +smbc_mkdir_fn +smbc_getFunctionMkdir(SMBCCTX *c) +{ + return c->mkdir; +} + +void +smbc_setFunctionMkdir(SMBCCTX *c, smbc_mkdir_fn fn) +{ + c->mkdir = fn; +} + +smbc_rmdir_fn +smbc_getFunctionRmdir(SMBCCTX *c) +{ + return c->rmdir; +} + +void +smbc_setFunctionRmdir(SMBCCTX *c, smbc_rmdir_fn fn) +{ + c->rmdir = fn; +} + +smbc_telldir_fn +smbc_getFunctionTelldir(SMBCCTX *c) +{ + return c->telldir; +} + +void +smbc_setFunctionTelldir(SMBCCTX *c, smbc_telldir_fn fn) +{ + c->telldir = fn; +} + +smbc_lseekdir_fn +smbc_getFunctionLseekdir(SMBCCTX *c) +{ + return c->lseekdir; +} + +void +smbc_setFunctionLseekdir(SMBCCTX *c, smbc_lseekdir_fn fn) +{ + c->lseekdir = fn; +} + +smbc_fstatdir_fn +smbc_getFunctionFstatdir(SMBCCTX *c) +{ + return c->fstatdir; +} + +void +smbc_setFunctionFstatdir(SMBCCTX *c, smbc_fstatdir_fn fn) +{ + c->fstatdir = fn; +} + + +/** + * Callable functions applicable to both files and directories. + */ + +smbc_chmod_fn +smbc_getFunctionChmod(SMBCCTX *c) +{ + return c->chmod; +} + +void +smbc_setFunctionChmod(SMBCCTX *c, smbc_chmod_fn fn) +{ + c->chmod = fn; +} + +smbc_utimes_fn +smbc_getFunctionUtimes(SMBCCTX *c) +{ + return c->utimes; +} + +void +smbc_setFunctionUtimes(SMBCCTX *c, smbc_utimes_fn fn) +{ + c->utimes = fn; +} + +smbc_setxattr_fn +smbc_getFunctionSetxattr(SMBCCTX *c) +{ + return c->setxattr; +} + +void +smbc_setFunctionSetxattr(SMBCCTX *c, smbc_setxattr_fn fn) +{ + c->setxattr = fn; +} + +smbc_getxattr_fn +smbc_getFunctionGetxattr(SMBCCTX *c) +{ + return c->getxattr; +} + +void +smbc_setFunctionGetxattr(SMBCCTX *c, smbc_getxattr_fn fn) +{ + c->getxattr = fn; +} + +smbc_removexattr_fn +smbc_getFunctionRemovexattr(SMBCCTX *c) +{ + return c->removexattr; +} + +void +smbc_setFunctionRemovexattr(SMBCCTX *c, smbc_removexattr_fn fn) +{ + c->removexattr = fn; +} + +smbc_listxattr_fn +smbc_getFunctionListxattr(SMBCCTX *c) +{ + return c->listxattr; +} + +void +smbc_setFunctionListxattr(SMBCCTX *c, smbc_listxattr_fn fn) +{ + c->listxattr = fn; +} + + +/** + * Callable functions related to printing + */ + +smbc_print_file_fn +smbc_getFunctionPrintFile(SMBCCTX *c) +{ + return c->print_file; +} + +void +smbc_setFunctionPrintFile(SMBCCTX *c, smbc_print_file_fn fn) +{ + c->print_file = fn; +} + +smbc_open_print_job_fn +smbc_getFunctionOpenPrintJob(SMBCCTX *c) +{ + return c->open_print_job; +} + +void +smbc_setFunctionOpenPrintJob(SMBCCTX *c, + smbc_open_print_job_fn fn) +{ + c->open_print_job = fn; +} + +smbc_list_print_jobs_fn +smbc_getFunctionListPrintJobs(SMBCCTX *c) +{ + return c->list_print_jobs; +} + +void +smbc_setFunctionListPrintJobs(SMBCCTX *c, + smbc_list_print_jobs_fn fn) +{ + c->list_print_jobs = fn; +} + +smbc_unlink_print_job_fn +smbc_getFunctionUnlinkPrintJob(SMBCCTX *c) +{ + return c->unlink_print_job; +} + +void +smbc_setFunctionUnlinkPrintJob(SMBCCTX *c, + smbc_unlink_print_job_fn fn) +{ + c->unlink_print_job = fn; +} + diff --git a/source3/libsmb/libsmb_stat.c b/source3/libsmb/libsmb_stat.c index b733eab74f..27546f687e 100644 --- a/source3/libsmb/libsmb_stat.c +++ b/source3/libsmb/libsmb_stat.c @@ -157,7 +157,7 @@ SMBC_stat_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame,context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -237,7 +237,7 @@ SMBC_fstat_ctx(SMBCCTX *context, if (!file->file) { TALLOC_FREE(frame); - return (context->posix_emu.fstatdir_fn)(context, file, st); + return smbc_getFunctionFstatdir(context)(context, file, st); } /*d_printf(">>>fstat: parsing %s\n", file->fname);*/ diff --git a/source3/libsmb/libsmb_xattr.c b/source3/libsmb/libsmb_xattr.c index 3c08412d59..e17146e611 100644 --- a/source3/libsmb/libsmb_xattr.c +++ b/source3/libsmb/libsmb_xattr.c @@ -1729,7 +1729,7 @@ SMBC_setxattr_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -2023,7 +2023,7 @@ SMBC_getxattr_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -2157,7 +2157,7 @@ SMBC_removexattr_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); -- cgit From ed26f09a91d0bc13ca17d14da6545c8b2a606f97 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Mon, 3 Mar 2008 18:25:49 -0500 Subject: Missed a few 'deprecated' markers (cherry picked from commit 76ba37ac46b4a77fe228ca90635fa19140541ccd) (This used to be commit 7c2a0be9cb2916c07074d8d56d698721b02bcfc3) --- examples/libsmbclient/testbrowse.c | 2 +- source3/include/libsmbclient.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/libsmbclient/testbrowse.c b/examples/libsmbclient/testbrowse.c index c4ca6667e0..a7eda365af 100644 --- a/examples/libsmbclient/testbrowse.c +++ b/examples/libsmbclient/testbrowse.c @@ -122,7 +122,7 @@ main(int argc, char * argv[]) /* ... then set the option to do so */ smbc_setOptionDebugToStderr(context, 1); } - + /* Initialize the context using the previously specified options */ if (!smbc_init_context(context)) { smbc_free_context(context, 0); diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index a60c05fa7f..e1a4b74567 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -2767,7 +2767,7 @@ struct _SMBCCTX * DEPRECATED: * Use smbc_getServerCacheData(), smbc_setServerCacheData() */ - void * reserved; /* space where server_cache_data used to be */ + void * reserved _DEPRECATED_; /* * Very old configuration options. @@ -2796,7 +2796,7 @@ struct _SMBCCTX int browse_max_lmb_count _DEPRECATED_; int urlencode_readdir_entries _DEPRECATED_; int one_share_per_server _DEPRECATED_; - } options; + } options _DEPRECATED_; /** INTERNAL DATA * do _NOT_ touch this from your program ! -- cgit From 9ad8af0d067ae7598b693b21efa0b2d243ecda03 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Mon, 3 Mar 2008 22:56:32 -0500 Subject: use constant name less likely to cause conflict (cherry picked from commit fd18b01016d1dc4b08983975353e62084fdc323c) (This used to be commit 4279cc49ff73d4503df2fd0c6176c3f90f67066c) --- source3/include/libsmbclient.h | 100 ++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index e1a4b74567..2e38944d65 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -25,11 +25,11 @@ #ifndef SMBCLIENT_H_INCLUDED #define SMBCLIENT_H_INCLUDED -#undef _DEPRECATED_ +#undef DEPRECATED_SMBC_INTERFACE #if ! defined(__LIBSMBCLIENT_INTERNAL__) && defined(__GNUC__) -# define _DEPRECATED_ __attribute__ ((deprecated)) +# define DEPRECATED_SMBC_INTERFACE __attribute__ ((deprecated)) #else -# define _DEPRECATED_ +# define DEPRECATED_SMBC_INTERFACE #endif #ifdef __cplusplus @@ -2600,7 +2600,7 @@ struct _SMBCCTX * DEPRECATED: * Use smbc_getDebug() and smbc_setDebug() */ - int debug _DEPRECATED_; + int debug DEPRECATED_SMBC_INTERFACE; /** * netbios name used for making connections @@ -2608,7 +2608,7 @@ struct _SMBCCTX * DEPRECATED: * Use smbc_getNetbiosName() and smbc_setNetbiosName() */ - char * netbios_name _DEPRECATED_; + char * netbios_name DEPRECATED_SMBC_INTERFACE; /** * workgroup name used for making connections @@ -2616,7 +2616,7 @@ struct _SMBCCTX * DEPRECATED: * Use smbc_getWorkgroup() and smbc_setWorkgroup() */ - char * workgroup _DEPRECATED_; + char * workgroup DEPRECATED_SMBC_INTERFACE; /** * username used for making connections @@ -2624,7 +2624,7 @@ struct _SMBCCTX * DEPRECATED: * Use smbc_getUser() and smbc_setUser() */ - char * user _DEPRECATED_; + char * user DEPRECATED_SMBC_INTERFACE; /** * timeout used for waiting on connections / response data (in @@ -2633,7 +2633,7 @@ struct _SMBCCTX * DEPRECATED: * Use smbc_getTimeout() and smbc_setTimeout() */ - int timeout _DEPRECATED_; + int timeout DEPRECATED_SMBC_INTERFACE; /** * callable functions for files: @@ -2644,40 +2644,40 @@ struct _SMBCCTX * Use smbc_getFunction*() and smbc_setFunction*(), e.g. * smbc_getFunctionOpen(), smbc_setFunctionUnlink(), etc. */ - smbc_open_fn open _DEPRECATED_; - smbc_creat_fn creat _DEPRECATED_; - smbc_read_fn read _DEPRECATED_; - smbc_write_fn write _DEPRECATED_; - smbc_unlink_fn unlink _DEPRECATED_; - smbc_rename_fn rename _DEPRECATED_; - smbc_lseek_fn lseek _DEPRECATED_; - smbc_stat_fn stat _DEPRECATED_; - smbc_fstat_fn fstat _DEPRECATED_; + smbc_open_fn open DEPRECATED_SMBC_INTERFACE; + smbc_creat_fn creat DEPRECATED_SMBC_INTERFACE; + smbc_read_fn read DEPRECATED_SMBC_INTERFACE; + smbc_write_fn write DEPRECATED_SMBC_INTERFACE; + smbc_unlink_fn unlink DEPRECATED_SMBC_INTERFACE; + smbc_rename_fn rename DEPRECATED_SMBC_INTERFACE; + smbc_lseek_fn lseek DEPRECATED_SMBC_INTERFACE; + smbc_stat_fn stat DEPRECATED_SMBC_INTERFACE; + smbc_fstat_fn fstat DEPRECATED_SMBC_INTERFACE; #if 0 /* internal */ smbc_ftruncate_fn ftruncate_fn; #endif - smbc_close_fn close_fn _DEPRECATED_; - smbc_opendir_fn opendir _DEPRECATED_; - smbc_closedir_fn closedir _DEPRECATED_; - smbc_readdir_fn readdir _DEPRECATED_; - smbc_getdents_fn getdents _DEPRECATED_; - smbc_mkdir_fn mkdir _DEPRECATED_; - smbc_rmdir_fn rmdir _DEPRECATED_; - smbc_telldir_fn telldir _DEPRECATED_; - smbc_lseekdir_fn lseekdir _DEPRECATED_; - smbc_fstatdir_fn fstatdir _DEPRECATED_; - smbc_chmod_fn chmod _DEPRECATED_; - smbc_utimes_fn utimes _DEPRECATED_; - smbc_setxattr_fn setxattr _DEPRECATED_; - smbc_getxattr_fn getxattr _DEPRECATED_; - smbc_removexattr_fn removexattr _DEPRECATED_; - smbc_listxattr_fn listxattr _DEPRECATED_; + smbc_close_fn close_fn DEPRECATED_SMBC_INTERFACE; + smbc_opendir_fn opendir DEPRECATED_SMBC_INTERFACE; + smbc_closedir_fn closedir DEPRECATED_SMBC_INTERFACE; + smbc_readdir_fn readdir DEPRECATED_SMBC_INTERFACE; + smbc_getdents_fn getdents DEPRECATED_SMBC_INTERFACE; + smbc_mkdir_fn mkdir DEPRECATED_SMBC_INTERFACE; + smbc_rmdir_fn rmdir DEPRECATED_SMBC_INTERFACE; + smbc_telldir_fn telldir DEPRECATED_SMBC_INTERFACE; + smbc_lseekdir_fn lseekdir DEPRECATED_SMBC_INTERFACE; + smbc_fstatdir_fn fstatdir DEPRECATED_SMBC_INTERFACE; + smbc_chmod_fn chmod DEPRECATED_SMBC_INTERFACE; + smbc_utimes_fn utimes DEPRECATED_SMBC_INTERFACE; + smbc_setxattr_fn setxattr DEPRECATED_SMBC_INTERFACE; + smbc_getxattr_fn getxattr DEPRECATED_SMBC_INTERFACE; + smbc_removexattr_fn removexattr DEPRECATED_SMBC_INTERFACE; + smbc_listxattr_fn listxattr DEPRECATED_SMBC_INTERFACE; /* Printing-related functions */ - smbc_print_file_fn print_file _DEPRECATED_; - smbc_open_print_job_fn open_print_job _DEPRECATED_; - smbc_list_print_jobs_fn list_print_jobs _DEPRECATED_; - smbc_unlink_print_job_fn unlink_print_job _DEPRECATED_; + smbc_print_file_fn print_file DEPRECATED_SMBC_INTERFACE; + smbc_open_print_job_fn open_print_job DEPRECATED_SMBC_INTERFACE; + smbc_list_print_jobs_fn list_print_jobs DEPRECATED_SMBC_INTERFACE; + smbc_unlink_print_job_fn unlink_print_job DEPRECATED_SMBC_INTERFACE; /* ** Callbacks @@ -2695,7 +2695,7 @@ struct _SMBCCTX * DEPRECATED: * Use smbc_getFunctionAuthData(), smbc_setFunctionAuthData() */ - smbc_get_auth_data_fn auth_fn _DEPRECATED_; + smbc_get_auth_data_fn auth_fn DEPRECATED_SMBC_INTERFACE; /** * check if a server is still good @@ -2704,7 +2704,7 @@ struct _SMBCCTX * Use smbc_getFunctionCheckServer(), * smbc_setFunctionCheckServer() */ - smbc_check_server_fn check_server_fn _DEPRECATED_; + smbc_check_server_fn check_server_fn DEPRECATED_SMBC_INTERFACE; /** * remove a server if unused @@ -2713,7 +2713,7 @@ struct _SMBCCTX * Use smbc_getFunctionRemoveUnusedServer(), * smbc_setFunctionCheckServer() */ - smbc_remove_unused_server_fn remove_unused_server_fn _DEPRECATED_; + smbc_remove_unused_server_fn remove_unused_server_fn DEPRECATED_SMBC_INTERFACE; /** Cache subsystem * @@ -2730,7 +2730,7 @@ struct _SMBCCTX * Use smbc_getFunctionAddCachedServer(), * smbc_setFunctionAddCachedServer() */ - smbc_add_cached_srv_fn add_cached_srv_fn _DEPRECATED_; + smbc_add_cached_srv_fn add_cached_srv_fn DEPRECATED_SMBC_INTERFACE; /** * server cache lookup @@ -2739,7 +2739,7 @@ struct _SMBCCTX * Use smbc_getFunctionGetCachedServer(), * smbc_setFunctionGetCachedServer() */ - smbc_get_cached_srv_fn get_cached_srv_fn _DEPRECATED_; + smbc_get_cached_srv_fn get_cached_srv_fn DEPRECATED_SMBC_INTERFACE; /** * server cache removal @@ -2748,7 +2748,7 @@ struct _SMBCCTX * Use smbc_getFunctionRemoveCachedServer(), * smbc_setFunctionRemoveCachedServer() */ - smbc_remove_cached_srv_fn remove_cached_srv_fn _DEPRECATED_; + smbc_remove_cached_srv_fn remove_cached_srv_fn DEPRECATED_SMBC_INTERFACE; /** * server cache purging, try to remove all cached servers @@ -2758,7 +2758,7 @@ struct _SMBCCTX * Use smbc_getFunctionPurgeCachedServers(), * smbc_setFunctionPurgeCachedServers() */ - smbc_purge_cached_fn purge_cached_fn _DEPRECATED_; + smbc_purge_cached_fn purge_cached_fn DEPRECATED_SMBC_INTERFACE; } callbacks; /** @@ -2767,7 +2767,7 @@ struct _SMBCCTX * DEPRECATED: * Use smbc_getServerCacheData(), smbc_setServerCacheData() */ - void * reserved _DEPRECATED_; + void * reserved DEPRECATED_SMBC_INTERFACE; /* * Very old configuration options. @@ -2781,7 +2781,7 @@ struct _SMBCCTX * smbc_setOptionNoAutoAnonymousLogin() * smbc_getOptionNoAutoAnonymousLogin() */ - int flags _DEPRECATED_; + int flags DEPRECATED_SMBC_INTERFACE; /** * user options selections that apply to this session @@ -2793,10 +2793,10 @@ struct _SMBCCTX * smbc_getOption*() functions. */ struct _smbc_options { - int browse_max_lmb_count _DEPRECATED_; - int urlencode_readdir_entries _DEPRECATED_; - int one_share_per_server _DEPRECATED_; - } options _DEPRECATED_; + int browse_max_lmb_count DEPRECATED_SMBC_INTERFACE; + int urlencode_readdir_entries DEPRECATED_SMBC_INTERFACE; + int one_share_per_server DEPRECATED_SMBC_INTERFACE; + } options DEPRECATED_SMBC_INTERFACE; /** INTERNAL DATA * do _NOT_ touch this from your program ! -- cgit From 143e709c8c0e689b5ad288f4d7eeb8ac9429a199 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 1 Mar 2008 00:32:36 +0100 Subject: Fix init_registry_data for subkeyless top-level keys. On a fresh install with no existing registry.tdb, make sure we are able to create our initial top-level entries. Michael, Volker, please check. Guenther (cherry picked from commit 956bc602062825493e1c357e2388fee1e5514b50) (This used to be commit bf03cba57d3cfe07b8d848aa3b5a165bb198b7aa) --- source3/registry/reg_backend_db.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c index 52e0fd4289..518078a062 100644 --- a/source3/registry/reg_backend_db.c +++ b/source3/registry/reg_backend_db.c @@ -454,7 +454,8 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr) regdb_fetch_keys(key, old_subkeys); - if (ctr->num_subkeys == old_subkeys->num_subkeys) { + if ((ctr->num_subkeys && old_subkeys->num_subkeys) && + (ctr->num_subkeys == old_subkeys->num_subkeys)) { for (i = 0; inum_subkeys; i++) { if (strcmp(ctr->subkeys[i], @@ -550,6 +551,22 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr) /* now create records for any subkeys that don't already exist */ num_subkeys = regsubkey_ctr_numkeys(ctr); + + if (num_subkeys == 0) { + if (!(subkeys = TALLOC_ZERO_P(ctr, REGSUBKEY_CTR)) ) { + DEBUG(0,("regdb_store_keys: talloc() failure!\n")); + goto fail; + } + + if (!regdb_store_keys_internal(key, subkeys)) { + DEBUG(0,("regdb_store_keys: Failed to store " + "new record for key [%s]\n", key)); + goto fail; + } + TALLOC_FREE(subkeys); + + } + for (i=0; i Date: Tue, 4 Mar 2008 09:53:37 +0100 Subject: Update release date. Karolin (This used to be commit 491535d0911c64869055b85a210c2ef076086b83) --- WHATSNEW.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 0b355547d9..003752d18c 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,6 +1,6 @@ ================================= Release Notes for Samba 3.2.0pre2 - Feb 29, 2008 + Mar 04, 2008 ================================= This is the second preview release of Samba 3.2.0. This is *not* -- cgit From 0a27ef8be7df518770ae8b5a44f72efc86f280bf Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 4 Mar 2008 11:02:26 +0100 Subject: Fix crash bug in pdb_init_ldapsam(). Karolin, this needs to be in 3-2-stable. Guenther (cherry picked from commit 0d73bde6de4391e7aec862424762473441fa0905) (This used to be commit 4c2d6ce18daf07de7233e3e90bd24fa2a5f9e945) --- source3/passdb/pdb_ldap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index ce79dce668..87a648a5b4 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -6264,7 +6264,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location) entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), - NULL); + talloc_tos()); if (domain_sid_string) { bool found_sid; @@ -6300,7 +6300,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location) entry, get_attr_key2string( dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE ), - NULL); + talloc_tos()); if (alg_rid_base_string) { alg_rid_base = (uint32)atol(alg_rid_base_string); if (alg_rid_base != algorithmic_rid_base()) { -- cgit From 59e745ea67c8dfe1168ca08eec59cb29c333c403 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 4 Mar 2008 11:06:02 +0100 Subject: Zero more structs initially in LSA rpc server. Guenther (cherry picked from commit d7ce643285276790a65faff76666498595a508d7) (This used to be commit 7867f40567503db32dbb13b4fca19792cf198505) --- source3/rpc_server/srv_lsa_nt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index ce3fd1a44f..c2502141e5 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -82,6 +82,8 @@ static int init_lsa_ref_domain_list(TALLOC_CTX *mem_ctx, return -1; } + ZERO_STRUCT(ref->domains[num]); + init_lsa_StringLarge(&ref->domains[num].name, dom_name); ref->domains[num].sid = sid_dup_talloc(mem_ctx, dom_sid); if (!ref->domains[num].sid) { @@ -228,6 +230,8 @@ static NTSTATUS lookup_lsa_sids(TALLOC_CTX *mem_ctx, const char *domain; enum lsa_SidType type = SID_NAME_UNKNOWN; + ZERO_STRUCT(sid); + /* Split name into domain and user component */ full_name = name[i].string; -- cgit From 295734191fc0165a2ea17561a0fd39bffb9625d6 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 4 Mar 2008 12:46:15 +0100 Subject: Fix lsa_QueryInfoPolicy: make proper talloc copies of the sids. Guenther (cherry picked from commit b9441232d66d78e66464be6c9748a023681ce6ca) (This used to be commit 1081da4d83dbfb6d87c3267c5e00e668b2151294) --- source3/rpc_server/srv_lsa_nt.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index c2502141e5..c03630d6f9 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -603,15 +603,22 @@ NTSTATUS _lsa_QueryInfoPolicy(pipes_struct *p, case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: name = get_global_sam_name(); - sid = get_global_sam_sid(); + sid = sid_dup_talloc(p->mem_ctx, get_global_sam_sid()); + if (!sid) { + return NT_STATUS_NO_MEMORY; + } break; case ROLE_DOMAIN_MEMBER: name = lp_workgroup(); /* We need to return the Domain SID here. */ - if (secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) - sid = &domain_sid; - else + if (secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) { + sid = sid_dup_talloc(p->mem_ctx, &domain_sid); + if (!sid) { + return NT_STATUS_NO_MEMORY; + } + } else { return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } break; case ROLE_STANDALONE: name = lp_workgroup(); -- cgit From 659d21a2cb5c84abdf2e4e8440039e73e60c5a50 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 4 Mar 2008 13:16:02 +0100 Subject: Fix counter mismatch in lsa_LookupNames server. Guenther (cherry picked from commit 80fd085c34befd38d33cf6e59080a2a36016a92d) (This used to be commit af7aded25d9007a8c2037940ab90fb30d0a3eef2) --- source3/rpc_server/srv_lsa_nt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index c03630d6f9..b3275f27a3 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -1036,10 +1036,10 @@ done: } } - *r->out.count = num_entries; + *r->out.count = mapped_count; *r->out.domains = domains; r->out.sids->sids = rids; - r->out.sids->count = mapped_count; + r->out.sids->count = num_entries; return status; } -- cgit From 91414a5f9fef2c3b71760ee1a578c2e651642a0d Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 4 Mar 2008 13:19:38 +0100 Subject: Fix counter mismatch in lsa_LookupNames3 server. Guenther (cherry picked from commit e052d6f2c82a644986e5d99f640310d71cd5c396) (This used to be commit 59d5e15ee50fbae858358aedf0e458b7e4a4af20) --- source3/rpc_server/srv_lsa_nt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index b3275f27a3..20c910e46d 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -1176,10 +1176,10 @@ done: } } - *r->out.count = num_entries; + *r->out.count = mapped_count; *r->out.domains = domains; r->out.sids->sids = trans_sids; - r->out.sids->count = mapped_count; + r->out.sids->count = num_entries; return status; } -- cgit From b4f9990948ca457e03622eacb46cc473932b7e04 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 4 Mar 2008 12:26:05 +0100 Subject: Add new Windows 2008 Kerberos PAC Type 12 (apparently again undocumented). We need at least to parse this in order to correctly support kerberized session setup from w2k8 as well as local pam_winbind logons using kerberos. Guenther (cherry picked from commit 4ba62d49d740c43cf17ceef1534cf1c8a7e4a130) (This used to be commit a3b623bfbbfb1abe0c1f0adcf83afbf808df60a4) --- source3/librpc/idl/krb5pac.idl | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/source3/librpc/idl/krb5pac.idl b/source3/librpc/idl/krb5pac.idl index 601e3e1a27..11f08e11aa 100644 --- a/source3/librpc/idl/krb5pac.idl +++ b/source3/librpc/idl/krb5pac.idl @@ -31,6 +31,19 @@ interface krb5pac samr_RidWithAttributeArray res_groups; } PAC_LOGON_INFO; + typedef struct { + [value(2*strlen_m(upn_name))] uint16 upn_size; + uint16 unknown1; /* 0x10 */ + [value(2*strlen_m(domain_name))] uint16 domain_size; + uint16 unknown2; /* 0x50 */ + uint16 unknown3; /* 0x01 */ + uint16 unknown4; + uint32 unknown5; + [charset(UTF16)] uint8 upn_name[upn_size+2]; + [charset(UTF16)] uint8 domain_name[domain_size+2]; + uint32 unknown6; + } PAC_UNKNOWN_12; + typedef [public] struct { [value(0x00081001)] uint32 unknown1; [value(0xCCCCCCCC)] uint32 unknown2; @@ -44,7 +57,8 @@ interface krb5pac PAC_TYPE_SRV_CHECKSUM = 6, PAC_TYPE_KDC_CHECKSUM = 7, PAC_TYPE_LOGON_NAME = 10, - PAC_TYPE_CONSTRAINED_DELEGATION = 11 + PAC_TYPE_CONSTRAINED_DELEGATION = 11, + PAC_TYPE_UNKNOWN_12 = 12 } PAC_TYPE; typedef [public,nodiscriminant,gensize] union { @@ -52,6 +66,7 @@ interface krb5pac [case(PAC_TYPE_SRV_CHECKSUM)] PAC_SIGNATURE_DATA srv_cksum; [case(PAC_TYPE_KDC_CHECKSUM)] PAC_SIGNATURE_DATA kdc_cksum; [case(PAC_TYPE_LOGON_NAME)] PAC_LOGON_NAME logon_name; + [case(PAC_TYPE_UNKNOWN_12)] PAC_UNKNOWN_12 unknown; } PAC_INFO; typedef [public,nopush,nopull,noprint] struct { -- cgit From 0c08a2e8c0612eea0da2e0715566adcb99f47bc1 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 4 Mar 2008 12:28:36 +0100 Subject: Re-run make idl. Guenther (cherry picked from commit 8e601e2365f50e582de442daa1559f828bda3e89) (This used to be commit 3c26f1899e4b1d47f0463f05a81ac70d6d484e7a) --- source3/librpc/gen_ndr/krb5pac.h | 18 ++++++++- source3/librpc/gen_ndr/ndr_krb5pac.c | 76 ++++++++++++++++++++++++++++++++++++ source3/librpc/gen_ndr/ndr_krb5pac.h | 1 + 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/source3/librpc/gen_ndr/krb5pac.h b/source3/librpc/gen_ndr/krb5pac.h index b8b9054bb6..8a148253ae 100644 --- a/source3/librpc/gen_ndr/krb5pac.h +++ b/source3/librpc/gen_ndr/krb5pac.h @@ -25,6 +25,19 @@ struct PAC_LOGON_INFO { struct samr_RidWithAttributeArray res_groups; }/* [gensize] */; +struct PAC_UNKNOWN_12 { + uint16_t upn_size;/* [value(2*strlen_m(upn_name))] */ + uint16_t unknown1; + uint16_t domain_size;/* [value(2*strlen_m(domain_name))] */ + uint16_t unknown2; + uint16_t unknown3; + uint16_t unknown4; + uint32_t unknown5; + const char *upn_name;/* [charset(UTF16)] */ + const char *domain_name;/* [charset(UTF16)] */ + uint32_t unknown6; +}; + struct PAC_LOGON_INFO_CTR { uint32_t unknown1;/* [value(0x00081001)] */ uint32_t unknown2;/* [value(0xCCCCCCCC)] */ @@ -40,7 +53,8 @@ enum PAC_TYPE PAC_TYPE_SRV_CHECKSUM=6, PAC_TYPE_KDC_CHECKSUM=7, PAC_TYPE_LOGON_NAME=10, - PAC_TYPE_CONSTRAINED_DELEGATION=11 + PAC_TYPE_CONSTRAINED_DELEGATION=11, + PAC_TYPE_UNKNOWN_12=12 } #else { __donnot_use_enum_PAC_TYPE=0x7FFFFFFF} @@ -49,6 +63,7 @@ enum PAC_TYPE #define PAC_TYPE_KDC_CHECKSUM ( 7 ) #define PAC_TYPE_LOGON_NAME ( 10 ) #define PAC_TYPE_CONSTRAINED_DELEGATION ( 11 ) +#define PAC_TYPE_UNKNOWN_12 ( 12 ) #endif ; @@ -57,6 +72,7 @@ union PAC_INFO { struct PAC_SIGNATURE_DATA srv_cksum;/* [case(PAC_TYPE_SRV_CHECKSUM)] */ struct PAC_SIGNATURE_DATA kdc_cksum;/* [case(PAC_TYPE_KDC_CHECKSUM)] */ struct PAC_LOGON_NAME logon_name;/* [case(PAC_TYPE_LOGON_NAME)] */ + struct PAC_UNKNOWN_12 unknown;/* [case(PAC_TYPE_UNKNOWN_12)] */ }/* [gensize,nodiscriminant,public] */; struct PAC_BUFFER { diff --git a/source3/librpc/gen_ndr/ndr_krb5pac.c b/source3/librpc/gen_ndr/ndr_krb5pac.c index 7c4dba0b0a..be9e2e1e4e 100644 --- a/source3/librpc/gen_ndr/ndr_krb5pac.c +++ b/source3/librpc/gen_ndr/ndr_krb5pac.c @@ -166,6 +166,63 @@ static size_t ndr_size_PAC_LOGON_INFO(const struct PAC_LOGON_INFO *r, int flags) return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_PAC_LOGON_INFO); } +static enum ndr_err_code ndr_push_PAC_UNKNOWN_12(struct ndr_push *ndr, int ndr_flags, const struct PAC_UNKNOWN_12 *r) +{ + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 2 * strlen_m(r->upn_name))); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->unknown1)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 2 * strlen_m(r->domain_name))); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->unknown2)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->unknown3)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->unknown4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->unknown5)); + NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->upn_name, 2 * strlen_m(r->upn_name) + 2, sizeof(uint8_t), CH_UTF16)); + NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->domain_name, 2 * strlen_m(r->domain_name) + 2, sizeof(uint8_t), CH_UTF16)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->unknown6)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +static enum ndr_err_code ndr_pull_PAC_UNKNOWN_12(struct ndr_pull *ndr, int ndr_flags, struct PAC_UNKNOWN_12 *r) +{ + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->upn_size)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->unknown1)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->domain_size)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->unknown2)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->unknown3)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->unknown4)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->unknown5)); + NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->upn_name, r->upn_size + 2, sizeof(uint8_t), CH_UTF16)); + NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->domain_name, r->domain_size + 2, sizeof(uint8_t), CH_UTF16)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->unknown6)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_PAC_UNKNOWN_12(struct ndr_print *ndr, const char *name, const struct PAC_UNKNOWN_12 *r) +{ + ndr_print_struct(ndr, name, "PAC_UNKNOWN_12"); + ndr->depth++; + ndr_print_uint16(ndr, "upn_size", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?2 * strlen_m(r->upn_name):r->upn_size); + ndr_print_uint16(ndr, "unknown1", r->unknown1); + ndr_print_uint16(ndr, "domain_size", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?2 * strlen_m(r->domain_name):r->domain_size); + ndr_print_uint16(ndr, "unknown2", r->unknown2); + ndr_print_uint16(ndr, "unknown3", r->unknown3); + ndr_print_uint16(ndr, "unknown4", r->unknown4); + ndr_print_uint32(ndr, "unknown5", r->unknown5); + ndr_print_string(ndr, "upn_name", r->upn_name); + ndr_print_string(ndr, "domain_name", r->domain_name); + ndr_print_uint32(ndr, "unknown6", r->unknown6); + ndr->depth--; +} + _PUBLIC_ enum ndr_err_code ndr_push_PAC_LOGON_INFO_CTR(struct ndr_push *ndr, int ndr_flags, const struct PAC_LOGON_INFO_CTR *r) { if (ndr_flags & NDR_SCALARS) { @@ -253,6 +310,7 @@ _PUBLIC_ void ndr_print_PAC_TYPE(struct ndr_print *ndr, const char *name, enum P case PAC_TYPE_KDC_CHECKSUM: val = "PAC_TYPE_KDC_CHECKSUM"; break; case PAC_TYPE_LOGON_NAME: val = "PAC_TYPE_LOGON_NAME"; break; case PAC_TYPE_CONSTRAINED_DELEGATION: val = "PAC_TYPE_CONSTRAINED_DELEGATION"; break; + case PAC_TYPE_UNKNOWN_12: val = "PAC_TYPE_UNKNOWN_12"; break; } ndr_print_enum(ndr, name, "ENUM", val, r); } @@ -278,6 +336,10 @@ _PUBLIC_ enum ndr_err_code ndr_push_PAC_INFO(struct ndr_push *ndr, int ndr_flags NDR_CHECK(ndr_push_PAC_LOGON_NAME(ndr, NDR_SCALARS, &r->logon_name)); break; } + case PAC_TYPE_UNKNOWN_12: { + NDR_CHECK(ndr_push_PAC_UNKNOWN_12(ndr, NDR_SCALARS, &r->unknown)); + break; } + default: return ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level); } @@ -298,6 +360,9 @@ _PUBLIC_ enum ndr_err_code ndr_push_PAC_INFO(struct ndr_push *ndr, int ndr_flags case PAC_TYPE_LOGON_NAME: break; + case PAC_TYPE_UNKNOWN_12: + break; + default: return ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level); } @@ -327,6 +392,10 @@ _PUBLIC_ enum ndr_err_code ndr_pull_PAC_INFO(struct ndr_pull *ndr, int ndr_flags NDR_CHECK(ndr_pull_PAC_LOGON_NAME(ndr, NDR_SCALARS, &r->logon_name)); break; } + case PAC_TYPE_UNKNOWN_12: { + NDR_CHECK(ndr_pull_PAC_UNKNOWN_12(ndr, NDR_SCALARS, &r->unknown)); + break; } + default: return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level); } @@ -346,6 +415,9 @@ _PUBLIC_ enum ndr_err_code ndr_pull_PAC_INFO(struct ndr_pull *ndr, int ndr_flags case PAC_TYPE_LOGON_NAME: break; + case PAC_TYPE_UNKNOWN_12: + break; + default: return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level); } @@ -375,6 +447,10 @@ _PUBLIC_ void ndr_print_PAC_INFO(struct ndr_print *ndr, const char *name, const ndr_print_PAC_LOGON_NAME(ndr, "logon_name", &r->logon_name); break; + case PAC_TYPE_UNKNOWN_12: + ndr_print_PAC_UNKNOWN_12(ndr, "unknown", &r->unknown); + break; + default: ndr_print_bad_level(ndr, name, level); } diff --git a/source3/librpc/gen_ndr/ndr_krb5pac.h b/source3/librpc/gen_ndr/ndr_krb5pac.h index f23505d4f0..1d60382dc3 100644 --- a/source3/librpc/gen_ndr/ndr_krb5pac.h +++ b/source3/librpc/gen_ndr/ndr_krb5pac.h @@ -23,6 +23,7 @@ enum ndr_err_code ndr_push_PAC_SIGNATURE_DATA(struct ndr_push *ndr, int ndr_flag enum ndr_err_code ndr_pull_PAC_SIGNATURE_DATA(struct ndr_pull *ndr, int ndr_flags, struct PAC_SIGNATURE_DATA *r); void ndr_print_PAC_SIGNATURE_DATA(struct ndr_print *ndr, const char *name, const struct PAC_SIGNATURE_DATA *r); void ndr_print_PAC_LOGON_INFO(struct ndr_print *ndr, const char *name, const struct PAC_LOGON_INFO *r); +void ndr_print_PAC_UNKNOWN_12(struct ndr_print *ndr, const char *name, const struct PAC_UNKNOWN_12 *r); enum ndr_err_code ndr_push_PAC_LOGON_INFO_CTR(struct ndr_push *ndr, int ndr_flags, const struct PAC_LOGON_INFO_CTR *r); enum ndr_err_code ndr_pull_PAC_LOGON_INFO_CTR(struct ndr_pull *ndr, int ndr_flags, struct PAC_LOGON_INFO_CTR *r); void ndr_print_PAC_LOGON_INFO_CTR(struct ndr_print *ndr, const char *name, const struct PAC_LOGON_INFO_CTR *r); -- cgit From 0289067c6b414f6357ff9b544e197f9eb03d0c9d Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 4 Mar 2008 17:27:08 +0100 Subject: ask for the keyid in the release script. (This used to be commit bccae9487485a6c9468bc6afb9ada8c8d9f6e135) --- release-scripts/create-tarball | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/release-scripts/create-tarball b/release-scripts/create-tarball index 7dcc6c3b19..a689e693af 100755 --- a/release-scripts/create-tarball +++ b/release-scripts/create-tarball @@ -85,7 +85,13 @@ if [ "x$tagname" != "x" ]; then fi fi - git-tag -s ${tagname} + echo -n "Enter the keyid:" + read keyid + if [ x"$keyid" = x"" ];then + echo "no keyid" + exit 1 + fi + git-tag -u $keyid ${tagname} fi echo "Done!" -- cgit From 863ac14108c7bfffd22f7500f0b62443aa5989ea Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 5 Mar 2008 11:31:26 +0100 Subject: Fix build of pam_smbpass. Guenther (cherry picked from commit cd582b7705dca40b3c688c9e23d8375dab43b4d0) (This used to be commit ecdbc96b4dd56629bb8f99c41ecf76506df91d71) --- source3/Makefile.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source3/Makefile.in b/source3/Makefile.in index 44ac6622de..a8c3fe48b6 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1891,7 +1891,8 @@ bin/ntlm_auth@EXEEXT@: $(BINARY_PREREQS) $(NTLM_AUTH_OBJ) $(PARAM_OBJ) \ bin/pam_smbpass.@SHLIBEXT@: $(BINARY_PREREQS) $(PAM_SMBPASS_OBJ) @echo "Linking shared library $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_OBJ) -lpam $(DYNEXP) $(LIBS) $(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS) + @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_OBJ) -lpam $(DYNEXP) $(LIBS) $(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS) \ + @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/tdbbackup@EXEEXT@: $(BINARY_PREREQS) $(TDBBACKUP_OBJ) @LIBTDB_SHARED@ @echo Linking $@ -- cgit From 12d60bf9daedf5095fb9310904f9759d319155fa Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 5 Mar 2008 11:39:47 +0100 Subject: Makefile: Add explicit dependecies to libtalloc.so. So as to fix building of isolated targets. Michael (cherry picked from commit 7dbc251e1cd28abf28342529607fa4b5f579a9c4) (This used to be commit ad711da7972b9ccc8b82c506db830b192a833918) --- source3/Makefile.in | 118 ++++++++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/source3/Makefile.in b/source3/Makefile.in index a8c3fe48b6..d568bc4fd5 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1254,48 +1254,48 @@ bin/.dummy: dir=bin $(MAKEDIR); fi @: >> $@ || : > $@ # what a fancy emoticon! -bin/smbd@EXEEXT@: $(BINARY_PREREQS) $(SMBD_OBJ) @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @BUILD_POPT@ +bin/smbd@EXEEXT@: $(BINARY_PREREQS) $(SMBD_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @BUILD_POPT@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \ $(KRB5LIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \ $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) $(DNSSD_LIBS) \ @POPTLIBS@ @SMBD_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/nmbd@EXEEXT@: $(BINARY_PREREQS) $(NMBD_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/nmbd@EXEEXT@: $(BINARY_PREREQS) $(NMBD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ @LIBTDB_LIBS@ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) -bin/swat@EXEEXT@: $(BINARY_PREREQS) $(SWAT_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/swat@EXEEXT@: $(BINARY_PREREQS) $(SWAT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINT_LIBS) \ $(AUTH_LIBS) $(LIBS) $(PASSDB_LIBS) @POPTLIBS@ $(KRB5LIBS) \ $(LDAP_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/rpcclient@EXEEXT@: $(BINARY_PREREQS) $(RPCCLIENT_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/rpcclient@EXEEXT@: $(BINARY_PREREQS) $(RPCCLIENT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(PASSDB_LIBS) $(RPCCLIENT_OBJ) \ $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ \ $(KRB5LIBS) $(LDAP_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/smbclient@EXEEXT@: $(BINARY_PREREQS) $(CLIENT_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/smbclient@EXEEXT@: $(BINARY_PREREQS) $(CLIENT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(DYNEXP) \ $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ \ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) $(DNSSD_LIBS) \ @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/net@EXEEXT@: $(BINARY_PREREQS) $(NET_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/net@EXEEXT@: $(BINARY_PREREQS) $(NET_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) \ $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @INIPARSERLIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ @LIBNETAPI_LIBS@ -bin/profiles@EXEEXT@: $(BINARY_PREREQS) $(PROFILES_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/profiles@EXEEXT@: $(BINARY_PREREQS) $(PROFILES_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(PROFILES_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ -bin/smbspool@EXEEXT@: $(BINARY_PREREQS) $(CUPS_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/smbspool@EXEEXT@: $(BINARY_PREREQS) $(CUPS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ @@ -1307,160 +1307,160 @@ bin/umount.cifs@EXEEXT@: $(BINARY_PREREQS) $(CIFS_UMOUNT_OBJ) @BUILD_POPT@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(CIFS_UMOUNT_OBJ) $(DYNEXP) $(LDFLAGS) @POPTLIBS@ -bin/cifs.spnego@EXEEXT@: $(BINARY_PREREQS) $(CIFS_SPNEGO_OBJ) $(LIBSMBCLIENT_OBJ0) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/cifs.spnego@EXEEXT@: $(BINARY_PREREQS) $(CIFS_SPNEGO_OBJ) $(LIBSMBCLIENT_OBJ0) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(CIFS_SPNEGO_OBJ) $(DYNEXP) $(LDFLAGS) -lkeyutils $(LIBS) \ $(LIBSMBCLIENT_OBJ0) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBWBCLIENT_SHARED@ @LIBTDB_LIBS@ -bin/testparm@EXEEXT@: $(BINARY_PREREQS) $(TESTPARM_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/testparm@EXEEXT@: $(BINARY_PREREQS) $(TESTPARM_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(TESTPARM_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ -bin/smbstatus@EXEEXT@: $(BINARY_PREREQS) $(STATUS_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/smbstatus@EXEEXT@: $(BINARY_PREREQS) $(STATUS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(STATUS_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) \ @POPTLIBS@ @LIBTDB_LIBS@ -bin/smbcontrol@EXEEXT@: $(BINARY_PREREQS) $(SMBCONTROL_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/smbcontrol@EXEEXT@: $(BINARY_PREREQS) $(SMBCONTROL_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) -DUSING_SMBCONTROL $(FLAGS) -o $@ \ $(SMBCONTROL_OBJ) $(DYNEXP) $(LDFLAGS) \ $(LIBS) $(LDAP_LIBS) @LIBUNWIND_PTRACE@ @POPTLIBS@ @LIBTDB_LIBS@ -bin/smbtree@EXEEXT@: $(BINARY_PREREQS) $(SMBTREE_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/smbtree@EXEEXT@: $(BINARY_PREREQS) $(SMBTREE_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBTREE_OBJ) $(LDFLAGS) $(DYNEXP) \ $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/smbpasswd@EXEEXT@: $(BINARY_PREREQS) $(SMBPASSWD_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/smbpasswd@EXEEXT@: $(BINARY_PREREQS) $(SMBPASSWD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBPASSWD_OBJ) $(LDFLAGS) $(PASSDB_LIBS) \ $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) \ @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/pdbedit@EXEEXT@: $(BINARY_PREREQS) $(PDBEDIT_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/pdbedit@EXEEXT@: $(BINARY_PREREQS) $(PDBEDIT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ @POPTLIBS@ $(PASSDB_LIBS) $(LDAP_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/smbget@EXEEXT@: $(BINARY_PREREQS) $(SMBGET_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/smbget@EXEEXT@: $(BINARY_PREREQS) $(SMBGET_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBGET_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/nmblookup@EXEEXT@: $(BINARY_PREREQS) $(NMBLOOKUP_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/nmblookup@EXEEXT@: $(BINARY_PREREQS) $(NMBLOOKUP_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(NMBLOOKUP_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ @POPTLIBS@ $(LDAP_LIBS) @LIBTDB_LIBS@ -bin/smbtorture@EXEEXT@: $(BINARY_PREREQS) $(SMBTORTURE_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/smbtorture@EXEEXT@: $(BINARY_PREREQS) $(SMBTORTURE_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ -bin/talloctort@EXEEXT@: $(BINARY_PREREQS) $(TALLOCTORT_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/talloctort@EXEEXT@: $(BINARY_PREREQS) $(TALLOCTORT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(TALLOCTORT_OBJ) $(LDFLAGS) \ $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ -bin/replacetort@EXEEXT@: $(REPLACETORT_OBJ) @BUILD_POPT@ +bin/replacetort@EXEEXT@: $(REPLACETORT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(REPLACETORT_OBJ) $(LDFLAGS) \ $(DYNEXP) $(LIBS) @POPTLIBS@ -bin/masktest@EXEEXT@: $(BINARY_PREREQS) $(MASKTEST_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/masktest@EXEEXT@: $(BINARY_PREREQS) $(MASKTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ -bin/msgtest@EXEEXT@: $(BINARY_PREREQS) $(MSGTEST_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/msgtest@EXEEXT@: $(BINARY_PREREQS) $(MSGTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ -bin/smbcacls@EXEEXT@: $(BINARY_PREREQS) $(SMBCACLS_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/smbcacls@EXEEXT@: $(BINARY_PREREQS) $(SMBCACLS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBCACLS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ \ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/smbcquotas@EXEEXT@: $(BINARY_PREREQS) $(SMBCQUOTAS_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/smbcquotas@EXEEXT@: $(BINARY_PREREQS) $(SMBCQUOTAS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBCQUOTAS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ \ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/eventlogadm@EXEEXT@: $(BINARY_PREREQS) $(EVTLOGADM_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/eventlogadm@EXEEXT@: $(BINARY_PREREQS) $(EVTLOGADM_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ -bin/sharesec@EXEEXT@: $(BINARY_PREREQS) $(SHARESEC_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/sharesec@EXEEXT@: $(BINARY_PREREQS) $(SHARESEC_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SHARESEC_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ -bin/locktest@EXEEXT@: $(BINARY_PREREQS) $(LOCKTEST_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/locktest@EXEEXT@: $(BINARY_PREREQS) $(LOCKTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ -bin/nsstest@EXEEXT@: $(BINARY_PREREQS) $(NSSTEST_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/nsstest@EXEEXT@: $(BINARY_PREREQS) $(NSSTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ -bin/pdbtest@EXEEXT@: $(BINARY_PREREQS) $(PDBTEST_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/pdbtest@EXEEXT@: $(BINARY_PREREQS) $(PDBTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(PDBTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@ @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ -bin/vfstest@EXEEXT@: $(BINARY_PREREQS) $(VFSTEST_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/vfstest@EXEEXT@: $(BINARY_PREREQS) $(VFSTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(ACL_LIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) @SMBD_LIBS@ $(NSCD_LIBS) @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ -bin/smbiconv@EXEEXT@: $(BINARY_PREREQS) $(SMBICONV_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/smbiconv@EXEEXT@: $(BINARY_PREREQS) $(SMBICONV_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBICONV_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ -bin/log2pcap@EXEEXT@: $(BINARY_PREREQS) $(LOG2PCAP_OBJ) @BUILD_POPT@ +bin/log2pcap@EXEEXT@: $(BINARY_PREREQS) $(LOG2PCAP_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LOG2PCAP_OBJ) $(LDFLAGS) $(DYNEXP) @POPTLIBS@ $(LIBS) -bin/locktest2@EXEEXT@: $(BINARY_PREREQS) $(LOCKTEST2_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/locktest2@EXEEXT@: $(BINARY_PREREQS) $(LOCKTEST2_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ -bin/ndrdump@EXEEXT@: $(BINARY_PREREQS) $(NDRDUMP_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/ndrdump@EXEEXT@: $(BINARY_PREREQS) $(NDRDUMP_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(NDRDUMP_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ @LDAP_LIBS@ @LIBTDB_LIBS@ -bin/debug2html@EXEEXT@: $(BINARY_PREREQS) $(DEBUG2HTML_OBJ) @BUILD_POPT@ +bin/debug2html@EXEEXT@: $(BINARY_PREREQS) $(DEBUG2HTML_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) -bin/smbfilter@EXEEXT@: $(BINARY_PREREQS) $(SMBFILTER_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ +bin/smbfilter@EXEEXT@: $(BINARY_PREREQS) $(SMBFILTER_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ -bin/ldbedit: $(BINARY_PREREQS) $(LDBEDIT_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/ldbedit: $(BINARY_PREREQS) $(LDBEDIT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDBEDIT_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/ldbsearch: $(BINARY_PREREQS) $(LDBSEARCH_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/ldbsearch: $(BINARY_PREREQS) $(LDBSEARCH_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDBSEARCH_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/ldbadd: $(BINARY_PREREQS) $(LDBADD_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/ldbadd: $(BINARY_PREREQS) $(LDBADD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDBADD_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/ldbmodify: $(BINARY_PREREQS) $(LDBMODIFY_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/ldbmodify: $(BINARY_PREREQS) $(LDBMODIFY_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDBMODIFY_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/ldbdel: $(BINARY_PREREQS) $(LDBDEL_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/ldbdel: $(BINARY_PREREQS) $(LDBDEL_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDBDEL_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ @@ -1501,7 +1501,7 @@ bin/libwbclient.a: $(BINARY_PREREQS) $(LIBWBCLIENT_OBJ0) $(WBCOMMON_OBJ) @echo Linking non-shared library $@ @-$(AR) -rc $@ $(LIBWBCLIENT_OBJ0) $(WBCOMMON_OBJ) -bin/libaddns.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBADDNS_OBJ) +bin/libaddns.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBADDNS_OBJ) @LIBTALLOC_SHARED@ @echo Linking shared library $@ @$(SHLD_DSO) $(LIBADDNS_OBJ) $(LIBS) \ $(KRB5LIBS) $(UUID_LIBS)\ @@ -1511,7 +1511,7 @@ bin/libaddns.a: $(BINARY_PREREQS) $(LIBADDNS_OBJ) @echo Linking non-shared library $@ @-$(AR) -rc $@ $(LIBADDNS_OBJ) -$(LIBNETAPI_SHARED_TARGET): $(BINARY_PREREQS) $(LIBNETAPI_OBJ) @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +$(LIBNETAPI_SHARED_TARGET): $(BINARY_PREREQS) $(LIBNETAPI_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking shared library $@ @$(SHLD_DSO) $(LIBNETAPI_OBJ) @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ $(LIBS) \ $(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS) \ @@ -1522,7 +1522,7 @@ $(LIBNETAPI_STATIC_TARGET): $(BINARY_PREREQS) $(LIBNETAPI_OBJ1) @echo Linking non-shared library $@ @-$(AR) -rc $@ $(LIBNETAPI_OBJ1) -bin/libsmbclient.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBSMBCLIENT_OBJ) @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/libsmbclient.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBSMBCLIENT_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking shared library $@ @$(SHLD_DSO) $(LIBSMBCLIENT_OBJ) @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ $(LIBS) \ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ @@ -1532,7 +1532,7 @@ bin/libsmbclient.a: $(BINARY_PREREQS) $(LIBSMBCLIENT_OBJ0) @echo Linking non-shared library $@ @-$(AR) -rc $@ $(LIBSMBCLIENT_OBJ0) -bin/libsmbsharemodes.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBSMBSHAREMODES_OBJ) @LIBTDB_SHARED@ +bin/libsmbsharemodes.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBSMBSHAREMODES_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking shared library $@ @$(SHLD_DSO) $(LIBSMBSHAREMODES_OBJ) $(LIBS) @LIBTDB_LIBS@ \ $(KRB5LIBS) $(LDAP_LIBS) \ @@ -1543,7 +1543,7 @@ bin/libsmbsharemodes.a: $(BINARY_PREREQS) $(LIBSMBSHAREMODES_OBJ) @-$(AR) -rc $@ $(LIBSMBSHAREMODES_OBJ) # This is probably wrong for anything other than the GNU linker. -bin/libbigballofmud.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBBIGBALLOFMUD_OBJ) +bin/libbigballofmud.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBBIGBALLOFMUD_OBJ) @LIBTALLOC_SHARED@ @echo Linking shared library $@ @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBBIGBALLOFMUD_OBJ) $(LIBS) \ $(PASSDB_LIBS) $(IDMAP_LIBS) $(KRB5LIBS) $(LDAP_LIBS) \ @@ -1623,13 +1623,13 @@ bin/librpc_echo.@SHLIBEXT@: $(BINARY_PREREQS) $(RPC_ECHO_OBJ) @echo "Linking $@" @$(SHLD_MODULE) $(RPC_ECHO_OBJ) -bin/winbindd@EXEEXT@: $(BINARY_PREREQS) $(WINBINDD_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/winbindd@EXEEXT@: $(BINARY_PREREQS) $(WINBINDD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo "Linking $@" @$(CC) $(FLAGS) -o $@ $(WINBINDD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) \ $(PASSDB_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/vlp@EXEEXT@: $(BINARY_PREREQS) $(VLP_OBJ) @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/vlp@EXEEXT@: $(BINARY_PREREQS) $(VLP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo "Linking $@" @$(CC) $(FLAGS) -o $@ $(VLP_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ \ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ @@ -1639,7 +1639,7 @@ bin/vlp@EXEEXT@: $(BINARY_PREREQS) $(VLP_OBJ) @LIBTDB_SHARED@ @LIBWBCLIENT_SHARE @$(SHLD) $(WINBIND_NSS_LDSHFLAGS) -o $@ $(WINBIND_NSS_OBJ) \ @WINBIND_NSS_EXTRA_LIBS@ @WINBIND_NSS_PTHREAD@ @SONAMEFLAG@`basename $@`@NSSSONAMEVERSIONSUFFIX@ -@WINBIND_WINS_NSS@: $(BINARY_PREREQS) $(WINBIND_WINS_NSS_OBJ) @LIBTDB_SHARED@ +@WINBIND_WINS_NSS@: $(BINARY_PREREQS) $(WINBIND_WINS_NSS_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo "Linking $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(WINBIND_WINS_NSS_OBJ) \ $(LDAP_LIBS) $(KRB5LIBS) $(LIBS) @LIBTDB_LIBS@ \ @@ -1876,47 +1876,47 @@ bin/aio_fork.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_AIO_FORK_OBJ) ## None here right now ######################################################### -bin/wbinfo@EXEEXT@: $(BINARY_PREREQS) $(WBINFO_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/wbinfo@EXEEXT@: $(BINARY_PREREQS) $(WBINFO_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(WBINFO_OBJ) $(DYNEXP) $(LIBS) \ $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/ntlm_auth@EXEEXT@: $(BINARY_PREREQS) $(NTLM_AUTH_OBJ) $(PARAM_OBJ) \ - $(LIB_NONSMBD_OBJ) @BUILD_POPT@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ + $(LIB_NONSMBD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(DYNEXP) $(NTLM_AUTH_OBJ) \ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/pam_smbpass.@SHLIBEXT@: $(BINARY_PREREQS) $(PAM_SMBPASS_OBJ) +bin/pam_smbpass.@SHLIBEXT@: $(BINARY_PREREQS) $(PAM_SMBPASS_OBJ) @LIBTALLOC_SHARED@ @echo "Linking shared library $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_OBJ) -lpam $(DYNEXP) $(LIBS) $(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS) \ @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/tdbbackup@EXEEXT@: $(BINARY_PREREQS) $(TDBBACKUP_OBJ) @LIBTDB_SHARED@ +bin/tdbbackup@EXEEXT@: $(BINARY_PREREQS) $(TDBBACKUP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBBACKUP_OBJ) $(DYNEXP) $(LIBS) @LIBTDB_LIBS@ -bin/tdbtool@EXEEXT@: $(BINARY_PREREQS) $(TDBTOOL_OBJ) @LIBTDB_SHARED@ +bin/tdbtool@EXEEXT@: $(BINARY_PREREQS) $(TDBTOOL_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBTOOL_OBJ) $(DYNEXP) $(LIBS) @LIBTDB_LIBS@ -bin/tdbdump@EXEEXT@: $(BINARY_PREREQS) $(TDBDUMP_OBJ) @LIBTDB_SHARED@ +bin/tdbdump@EXEEXT@: $(BINARY_PREREQS) $(TDBDUMP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBDUMP_OBJ) $(DYNEXP) $(LIBS) @LIBTDB_LIBS@ -bin/tdbtorture@EXEEXT@: $(BINARY_PREREQS) $(TDBTORTURE_OBJ) @LIBTDB_SHARED@ +bin/tdbtorture@EXEEXT@: $(BINARY_PREREQS) $(TDBTORTURE_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBTORTURE_OBJ) $(DYNEXP) $(LIBS) @LIBTDB_LIBS@ -bin/t_strcmp@EXEEXT@: $(BINARY_PREREQS) bin/libbigballofmud.@SHLIBEXT@ torture/t_strcmp.o +bin/t_strcmp@EXEEXT@: $(BINARY_PREREQS) @LIBTALLOC_SHARED@ bin/libbigballofmud.@SHLIBEXT@ torture/t_strcmp.o $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_strcmp.o -L ./bin -lbigballofmud -bin/t_strstr@EXEEXT@: $(BINARY_PREREQS) bin/libbigballofmud.@SHLIBEXT@ torture/t_strstr.o +bin/t_strstr@EXEEXT@: $(BINARY_PREREQS) @LIBTALLOC_SHARED@ bin/libbigballofmud.@SHLIBEXT@ torture/t_strstr.o $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_strstr.o -L ./bin -lbigballofmud -bin/t_strappend@EXEEXT@: $(BINARY_PREREQS) bin/libbigballofmud.@SHLIBEXT@ torture/t_strappend.o +bin/t_strappend@EXEEXT@: $(BINARY_PREREQS) @LIBTALLOC_SHARED@ bin/libbigballofmud.@SHLIBEXT@ torture/t_strappend.o $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_strappend.o -L ./bin -lbigballofmud bin/t_stringoverflow@EXEEXT@: $(BINARY_PREREQS) bin/libbigballofmud.@SHLIBEXT@ torture/t_stringoverflow.o -- cgit From 5fad32a4cecd2dfd9aabe08ab767d782e19d4337 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 5 Mar 2008 16:20:34 +0100 Subject: Fix coverity ID 525, 526, 527, 528, 529 and 530 Upon failure to allocate one of the arrays, further down the TALLOC_FREE would have looked at the variables given to it without initizalizing. (cherry picked from commit 6cac3127312acaac65fcd54280605605765787ad) (This used to be commit f990498818e28cbf12fe387746b182c6893d2639) --- source3/rpc_client/cli_lsarpc.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c index 2759881dd3..0b89488a21 100644 --- a/source3/rpc_client/cli_lsarpc.c +++ b/source3/rpc_client/cli_lsarpc.c @@ -243,46 +243,45 @@ NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli, POLICY_HND *pol, int num_sids, const DOM_SID *sids, - char ***domains, - char ***names, - enum lsa_SidType **types) + char ***pdomains, + char ***pnames, + enum lsa_SidType **ptypes) { NTSTATUS result = NT_STATUS_OK; int sids_left = 0; int sids_processed = 0; const DOM_SID *hunk_sids = sids; - char **hunk_domains = NULL; - char **hunk_names = NULL; - enum lsa_SidType *hunk_types = NULL; + char **hunk_domains; + char **hunk_names; + enum lsa_SidType *hunk_types; + char **domains = NULL; + char **names = NULL; + enum lsa_SidType *types = NULL; if (num_sids) { - if (!((*domains) = TALLOC_ARRAY(mem_ctx, char *, num_sids))) { + if (!(domains = TALLOC_ARRAY(mem_ctx, char *, num_sids))) { DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n")); result = NT_STATUS_NO_MEMORY; goto fail; } - if (!((*names) = TALLOC_ARRAY(mem_ctx, char *, num_sids))) { + if (!(names = TALLOC_ARRAY(mem_ctx, char *, num_sids))) { DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n")); result = NT_STATUS_NO_MEMORY; goto fail; } - if (!((*types) = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_sids))) { + if (!(types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_sids))) { DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n")); result = NT_STATUS_NO_MEMORY; goto fail; } - } else { - (*domains) = NULL; - (*names) = NULL; - (*types) = NULL; } sids_left = num_sids; - hunk_domains = *domains; - hunk_names = *names; - hunk_types = *types; + hunk_domains = domains; + hunk_names = names; + hunk_types = types; while (sids_left > 0) { int hunk_num_sids; @@ -334,12 +333,15 @@ NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli, hunk_types += hunk_num_sids; } + *pdomains = domains; + *pnames = names; + *ptypes = types; return result; fail: - TALLOC_FREE(*domains); - TALLOC_FREE(*names); - TALLOC_FREE(*types); + TALLOC_FREE(domains); + TALLOC_FREE(names); + TALLOC_FREE(types); return result; } -- cgit From f9e85e579cac2546fe201a5e015a8d60bd6ace28 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 5 Mar 2008 13:20:32 +0100 Subject: Add PICFLAG to libnetapi Makefile. Guenther (cherry picked from commit 29fca3c0353f2be4577613d7e38fbc51d2a370fa) (This used to be commit 1e7ee35c0cb937405689f58e8846016b2ab44582) --- source3/lib/netapi/examples/Makefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/lib/netapi/examples/Makefile.in b/source3/lib/netapi/examples/Makefile.in index 6de3e65546..000eef118b 100644 --- a/source3/lib/netapi/examples/Makefile.in +++ b/source3/lib/netapi/examples/Makefile.in @@ -7,6 +7,7 @@ LIBS=@LIBS@ -lnetapi -ltdb -ltalloc DEVELOPER_CFLAGS=@DEVELOPER_CFLAGS@ FLAGS=-I../ -L../../../bin @CFLAGS@ $(GTK_FLAGS) CC=@CC@ +PICFLAG=@PICFLAG@ LDFLAGS=@PIE_LDFLAGS@ @LDFLAGS@ DYNEXP=@DYNEXP@ -- cgit From 7f80099e52f4c795bd4c23fd073bde975d2802a0 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 5 Mar 2008 15:21:43 +0100 Subject: Give a better error message why NetServerSetInfo() may fail in the gui. Guenther (cherry picked from commit 1bbbebb7767b8a25532e8be3dbd274c211e34bbd) (This used to be commit 370d030b227486ba87a98f4f6e8920f52f743a94) --- source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c | 2 +- source3/lib/netapi/serverinfo.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c b/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c index 73b14d4d87..a3719c7442 100644 --- a/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c +++ b/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c @@ -154,7 +154,7 @@ static void callback_apply_description_change(GtkWidget *widget, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Failed to change computer description: %s.", - libnetapi_errstr(status)); + libnetapi_get_error_string(state->ctx, status)); g_signal_connect_swapped(dialog, "response", G_CALLBACK(gtk_widget_destroy), dialog); diff --git a/source3/lib/netapi/serverinfo.c b/source3/lib/netapi/serverinfo.c index 7fa166e411..09f275bac9 100644 --- a/source3/lib/netapi/serverinfo.c +++ b/source3/lib/netapi/serverinfo.c @@ -185,6 +185,9 @@ static WERROR NetServerSetInfoLocal_1005(struct libnetapi_ctx *ctx, } if (!lp_config_backend_is_registry()) { + libnetapi_set_error_string(ctx, + "Configuration manipulation requested but not " + "supported by backend"); return WERR_NOT_SUPPORTED; } -- cgit From eb0e549b670b22a524ab0dbcbc2b41450cedd520 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 6 Mar 2008 00:51:20 +0100 Subject: Fix lp_load with an empty registry and "config backend = registry". Michael, please check. Guenther (cherry picked from commit d9f4060c660da0ad671e061b123df71d109d51b9) (This used to be commit 11b151f3552cbcddcfe671dcda4fe0110c4f2b48) --- source3/param/loadparm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 5651a435de..25aa48b61b 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -3404,6 +3404,13 @@ static bool process_registry_globals(bool (*pfunc)(const char *, const char *)) } } + if (!libnet_conf_share_exists(conf_ctx, GLOBAL_NAME)) { + /* nothing to read from the registry yet but make sure lp_load + * doesn't return false */ + ret = true; + goto done; + } + werr = libnet_conf_get_share(mem_ctx, conf_ctx, GLOBAL_NAME, &num_params, ¶m_names, ¶m_values); if (!W_ERROR_IS_OK(werr)) { -- cgit From 6412d72ca1f9727d2f84f9e2f5d08b6dd10fa393 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 6 Mar 2008 00:45:20 +0100 Subject: In libnetapi, point out that lp_load has failed. Guenther (cherry picked from commit be673bfc61559f661040c6fb1ba7d2e4552967f2) (This used to be commit 0fba3713e1c3379edcd99fb28ddac21616f34777) --- source3/lib/netapi/netapi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/lib/netapi/netapi.c b/source3/lib/netapi/netapi.c index fb091f6e0b..82a8a8d3cd 100644 --- a/source3/lib/netapi/netapi.c +++ b/source3/lib/netapi/netapi.c @@ -63,6 +63,7 @@ NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context) if (!lp_load(get_dyn_CONFIGFILE(), true, false, false, false)) { TALLOC_FREE(frame); + fprintf(stderr, "lp_load failed\n"); return W_ERROR_V(WERR_GENERAL_FAILURE); } -- cgit From 001ef704e55473d7af7f9fe1954ed6d3df392bff Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 5 Mar 2008 14:16:46 +0100 Subject: Makefile: untangle -ltalloc from LIBS, making use of libtalloc explicit. Michael (cherry picked from commit 237ea62a49fbf47634b55795c1065250d5148600) (This used to be commit 393fc8df2898208dff14aedd7b0924624cc4f164) --- source3/Makefile.in | 120 ++++++++++++++++++++++++++-------------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/source3/Makefile.in b/source3/Makefile.in index d568bc4fd5..2e1078cdee 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -18,7 +18,7 @@ datarootdir=@datarootdir@ selftest_prefix=@selftest_prefix@ smbtorture4_path=@smbtorture4_path@ -LIBS=@LIBS@ @LIBTALLOC_LIBS@ +LIBS=@LIBS@ CC=@CC@ SHLD=@SHLD@ LIB_PATH_VAR=@LIB_PATH_VAR@ @@ -1259,45 +1259,45 @@ bin/smbd@EXEEXT@: $(BINARY_PREREQS) $(SMBD_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARE @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \ $(KRB5LIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \ $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) $(DNSSD_LIBS) \ - @POPTLIBS@ @SMBD_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ + @POPTLIBS@ @SMBD_LIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/nmbd@EXEEXT@: $(BINARY_PREREQS) $(NMBD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ - @LIBTDB_LIBS@ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) bin/swat@EXEEXT@: $(BINARY_PREREQS) $(SWAT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINT_LIBS) \ $(AUTH_LIBS) $(LIBS) $(PASSDB_LIBS) @POPTLIBS@ $(KRB5LIBS) \ - $(LDAP_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ + $(LDAP_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/rpcclient@EXEEXT@: $(BINARY_PREREQS) $(RPCCLIENT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(PASSDB_LIBS) $(RPCCLIENT_OBJ) \ $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ \ - $(KRB5LIBS) $(LDAP_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ + $(KRB5LIBS) $(LDAP_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/smbclient@EXEEXT@: $(BINARY_PREREQS) $(CLIENT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(DYNEXP) \ $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ \ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) $(DNSSD_LIBS) \ - @LIBTDB_LIBS@ @WINBIND_LIBS@ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/net@EXEEXT@: $(BINARY_PREREQS) $(NET_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) \ - $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @INIPARSERLIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ @LIBNETAPI_LIBS@ + $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @INIPARSERLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ @LIBNETAPI_LIBS@ bin/profiles@EXEEXT@: $(BINARY_PREREQS) $(PROFILES_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(PROFILES_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(PROFILES_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/smbspool@EXEEXT@: $(BINARY_PREREQS) $(CUPS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/mount.cifs@EXEEXT@: $(BINARY_PREREQS) $(CIFS_MOUNT_OBJ) @BUILD_POPT@ @echo Linking $@ @@ -1310,161 +1310,161 @@ bin/umount.cifs@EXEEXT@: $(BINARY_PREREQS) $(CIFS_UMOUNT_OBJ) @BUILD_POPT@ bin/cifs.spnego@EXEEXT@: $(BINARY_PREREQS) $(CIFS_SPNEGO_OBJ) $(LIBSMBCLIENT_OBJ0) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(CIFS_SPNEGO_OBJ) $(DYNEXP) $(LDFLAGS) -lkeyutils $(LIBS) \ - $(LIBSMBCLIENT_OBJ0) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBWBCLIENT_SHARED@ @LIBTDB_LIBS@ + $(LIBSMBCLIENT_OBJ0) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBWBCLIENT_SHARED@ @LIBTDB_LIBS@ bin/testparm@EXEEXT@: $(BINARY_PREREQS) $(TESTPARM_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(TESTPARM_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(TESTPARM_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/smbstatus@EXEEXT@: $(BINARY_PREREQS) $(STATUS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(STATUS_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) \ - @POPTLIBS@ @LIBTDB_LIBS@ + @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/smbcontrol@EXEEXT@: $(BINARY_PREREQS) $(SMBCONTROL_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) -DUSING_SMBCONTROL $(FLAGS) -o $@ \ $(SMBCONTROL_OBJ) $(DYNEXP) $(LDFLAGS) \ - $(LIBS) $(LDAP_LIBS) @LIBUNWIND_PTRACE@ @POPTLIBS@ @LIBTDB_LIBS@ + $(LIBS) $(LDAP_LIBS) @LIBUNWIND_PTRACE@ @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/smbtree@EXEEXT@: $(BINARY_PREREQS) $(SMBTREE_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBTREE_OBJ) $(LDFLAGS) $(DYNEXP) \ $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ - @LIBTDB_LIBS@ @WINBIND_LIBS@ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/smbpasswd@EXEEXT@: $(BINARY_PREREQS) $(SMBPASSWD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBPASSWD_OBJ) $(LDFLAGS) $(PASSDB_LIBS) \ $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) \ - @LIBTDB_LIBS@ @WINBIND_LIBS@ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/pdbedit@EXEEXT@: $(BINARY_PREREQS) $(PDBEDIT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ - @POPTLIBS@ $(PASSDB_LIBS) $(LDAP_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ + @POPTLIBS@ $(PASSDB_LIBS) $(LDAP_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/smbget@EXEEXT@: $(BINARY_PREREQS) $(SMBGET_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBGET_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ - @LIBTDB_LIBS@ @WINBIND_LIBS@ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/nmblookup@EXEEXT@: $(BINARY_PREREQS) $(NMBLOOKUP_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(NMBLOOKUP_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ - @POPTLIBS@ $(LDAP_LIBS) @LIBTDB_LIBS@ + @POPTLIBS@ $(LDAP_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/smbtorture@EXEEXT@: $(BINARY_PREREQS) $(SMBTORTURE_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/talloctort@EXEEXT@: $(BINARY_PREREQS) $(TALLOCTORT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(TALLOCTORT_OBJ) $(LDFLAGS) \ - $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ + $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/replacetort@EXEEXT@: $(REPLACETORT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(REPLACETORT_OBJ) $(LDFLAGS) \ - $(DYNEXP) $(LIBS) @POPTLIBS@ + $(DYNEXP) $(LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ bin/masktest@EXEEXT@: $(BINARY_PREREQS) $(MASKTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/msgtest@EXEEXT@: $(BINARY_PREREQS) $(MSGTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/smbcacls@EXEEXT@: $(BINARY_PREREQS) $(SMBCACLS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBCACLS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ \ - $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ + $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/smbcquotas@EXEEXT@: $(BINARY_PREREQS) $(SMBCQUOTAS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBCQUOTAS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ \ - $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ + $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/eventlogadm@EXEEXT@: $(BINARY_PREREQS) $(EVTLOGADM_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/sharesec@EXEEXT@: $(BINARY_PREREQS) $(SHARESEC_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SHARESEC_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(SHARESEC_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/locktest@EXEEXT@: $(BINARY_PREREQS) $(LOCKTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/nsstest@EXEEXT@: $(BINARY_PREREQS) $(NSSTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/pdbtest@EXEEXT@: $(BINARY_PREREQS) $(PDBTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(PDBTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@ @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ + @$(CC) $(FLAGS) -o $@ $(PDBTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ bin/vfstest@EXEEXT@: $(BINARY_PREREQS) $(VFSTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(ACL_LIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) @SMBD_LIBS@ $(NSCD_LIBS) @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ + @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(ACL_LIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) @SMBD_LIBS@ $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ bin/smbiconv@EXEEXT@: $(BINARY_PREREQS) $(SMBICONV_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBICONV_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(SMBICONV_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/log2pcap@EXEEXT@: $(BINARY_PREREQS) $(LOG2PCAP_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LOG2PCAP_OBJ) $(LDFLAGS) $(DYNEXP) @POPTLIBS@ $(LIBS) + @$(CC) $(FLAGS) -o $@ $(LOG2PCAP_OBJ) $(LDFLAGS) $(DYNEXP) @POPTLIBS@ $(LIBS) @LIBTALLOC_LIBS@ bin/locktest2@EXEEXT@: $(BINARY_PREREQS) $(LOCKTEST2_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/ndrdump@EXEEXT@: $(BINARY_PREREQS) $(NDRDUMP_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(NDRDUMP_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ - @POPTLIBS@ @LDAP_LIBS@ @LIBTDB_LIBS@ + @POPTLIBS@ @LDAP_LIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/debug2html@EXEEXT@: $(BINARY_PREREQS) $(DEBUG2HTML_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) + @$(CC) $(FLAGS) -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ bin/smbfilter@EXEEXT@: $(BINARY_PREREQS) $(SMBFILTER_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/ldbedit: $(BINARY_PREREQS) $(LDBEDIT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDBEDIT_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ - $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ + $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/ldbsearch: $(BINARY_PREREQS) $(LDBSEARCH_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDBSEARCH_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ - $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ + $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/ldbadd: $(BINARY_PREREQS) $(LDBADD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDBADD_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ - $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ + $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/ldbmodify: $(BINARY_PREREQS) $(LDBMODIFY_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDBMODIFY_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ - $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ + $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/ldbdel: $(BINARY_PREREQS) $(LDBDEL_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDBDEL_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ - $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ + $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ $(LIBTALLOC_SHARED_TARGET): $(BINARY_PREREQS) $(LIBTALLOC_OBJ) @echo Linking shared library $@ @@ -1504,7 +1504,7 @@ bin/libwbclient.a: $(BINARY_PREREQS) $(LIBWBCLIENT_OBJ0) $(WBCOMMON_OBJ) bin/libaddns.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBADDNS_OBJ) @LIBTALLOC_SHARED@ @echo Linking shared library $@ @$(SHLD_DSO) $(LIBADDNS_OBJ) $(LIBS) \ - $(KRB5LIBS) $(UUID_LIBS)\ + $(KRB5LIBS) $(UUID_LIBS) @LIBTALLOC_LIBS@ \ @SONAMEFLAG@`basename $@`.$(SONAME_VER) bin/libaddns.a: $(BINARY_PREREQS) $(LIBADDNS_OBJ) @@ -1513,7 +1513,7 @@ bin/libaddns.a: $(BINARY_PREREQS) $(LIBADDNS_OBJ) $(LIBNETAPI_SHARED_TARGET): $(BINARY_PREREQS) $(LIBNETAPI_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking shared library $@ - @$(SHLD_DSO) $(LIBNETAPI_OBJ) @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ $(LIBS) \ + @$(SHLD_DSO) $(LIBNETAPI_OBJ) @LIBTALLOC_LIBS@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ $(LIBS) \ $(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS) \ @SONAMEFLAG@`basename $@`.$(SONAME_VER) @ln -s -f `basename $@` $@.$(SONAME_VER) @@ -1524,7 +1524,7 @@ $(LIBNETAPI_STATIC_TARGET): $(BINARY_PREREQS) $(LIBNETAPI_OBJ1) bin/libsmbclient.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBSMBCLIENT_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking shared library $@ - @$(SHLD_DSO) $(LIBSMBCLIENT_OBJ) @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ $(LIBS) \ + @$(SHLD_DSO) $(LIBSMBCLIENT_OBJ) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ $(LIBS) \ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ @SONAMEFLAG@`basename $@`.$(SONAME_VER) @@ -1534,7 +1534,7 @@ bin/libsmbclient.a: $(BINARY_PREREQS) $(LIBSMBCLIENT_OBJ0) bin/libsmbsharemodes.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBSMBSHAREMODES_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking shared library $@ - @$(SHLD_DSO) $(LIBSMBSHAREMODES_OBJ) $(LIBS) @LIBTDB_LIBS@ \ + @$(SHLD_DSO) $(LIBSMBSHAREMODES_OBJ) $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ \ $(KRB5LIBS) $(LDAP_LIBS) \ @SONAMEFLAG@`basename $@`.$(SONAME_VER) @@ -1545,7 +1545,7 @@ bin/libsmbsharemodes.a: $(BINARY_PREREQS) $(LIBSMBSHAREMODES_OBJ) # This is probably wrong for anything other than the GNU linker. bin/libbigballofmud.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBBIGBALLOFMUD_OBJ) @LIBTALLOC_SHARED@ @echo Linking shared library $@ - @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBBIGBALLOFMUD_OBJ) $(LIBS) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBBIGBALLOFMUD_OBJ) $(LIBS) @LIBTALLOC_LIBS@ \ $(PASSDB_LIBS) $(IDMAP_LIBS) $(KRB5LIBS) $(LDAP_LIBS) \ @SONAMEFLAG@`basename $@`.$(LIBBIGBALLOFMUD_MAJOR) ln -snf libbigballofmud.so bin/libbigballofmud.so.0 @@ -1627,12 +1627,12 @@ bin/winbindd@EXEEXT@: $(BINARY_PREREQS) $(WINBINDD_OBJ) @BUILD_POPT@ @LIBTALLOC_ @echo "Linking $@" @$(CC) $(FLAGS) -o $@ $(WINBINDD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) \ - $(PASSDB_LIBS) @LIBTDB_LIBS@ @WINBIND_LIBS@ + $(PASSDB_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/vlp@EXEEXT@: $(BINARY_PREREQS) $(VLP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo "Linking $@" @$(CC) $(FLAGS) -o $@ $(VLP_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ \ - $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ + $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ @WINBIND_NSS@: $(BINARY_PREREQS) $(WINBIND_NSS_OBJ) @echo "Linking $@" @@ -1642,7 +1642,7 @@ bin/vlp@EXEEXT@: $(BINARY_PREREQS) $(VLP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @WINBIND_WINS_NSS@: $(BINARY_PREREQS) $(WINBIND_WINS_NSS_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo "Linking $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(WINBIND_WINS_NSS_OBJ) \ - $(LDAP_LIBS) $(KRB5LIBS) $(LIBS) @LIBTDB_LIBS@ \ + $(LDAP_LIBS) $(KRB5LIBS) $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ \ @SONAMEFLAG@`basename $@`@NSSSONAMEVERSIONSUFFIX@ bin/winbind_krb5_locator.@SHLIBEXT@: $(BINARY_PREREQS) $(WINBIND_KRB5_LOCATOR_OBJ) @@ -1879,7 +1879,7 @@ bin/aio_fork.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_AIO_FORK_OBJ) bin/wbinfo@EXEEXT@: $(BINARY_PREREQS) $(WBINFO_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(WBINFO_OBJ) $(DYNEXP) $(LIBS) \ - $(LDAP_LIBS) @POPTLIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ + $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/ntlm_auth@EXEEXT@: $(BINARY_PREREQS) $(NTLM_AUTH_OBJ) $(PARAM_OBJ) \ $(LIB_NONSMBD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @@ -1887,37 +1887,37 @@ bin/ntlm_auth@EXEEXT@: $(BINARY_PREREQS) $(NTLM_AUTH_OBJ) $(PARAM_OBJ) \ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(DYNEXP) $(NTLM_AUTH_OBJ) \ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ - @LIBTDB_LIBS@ @WINBIND_LIBS@ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/pam_smbpass.@SHLIBEXT@: $(BINARY_PREREQS) $(PAM_SMBPASS_OBJ) @LIBTALLOC_SHARED@ @echo "Linking shared library $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_OBJ) -lpam $(DYNEXP) $(LIBS) $(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS) \ - @LIBTDB_LIBS@ @WINBIND_LIBS@ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/tdbbackup@EXEEXT@: $(BINARY_PREREQS) $(TDBBACKUP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBBACKUP_OBJ) $(DYNEXP) $(LIBS) @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBBACKUP_OBJ) $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/tdbtool@EXEEXT@: $(BINARY_PREREQS) $(TDBTOOL_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBTOOL_OBJ) $(DYNEXP) $(LIBS) @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBTOOL_OBJ) $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/tdbdump@EXEEXT@: $(BINARY_PREREQS) $(TDBDUMP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBDUMP_OBJ) $(DYNEXP) $(LIBS) @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBDUMP_OBJ) $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/tdbtorture@EXEEXT@: $(BINARY_PREREQS) $(TDBTORTURE_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBTORTURE_OBJ) $(DYNEXP) $(LIBS) @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBTORTURE_OBJ) $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/t_strcmp@EXEEXT@: $(BINARY_PREREQS) @LIBTALLOC_SHARED@ bin/libbigballofmud.@SHLIBEXT@ torture/t_strcmp.o - $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_strcmp.o -L ./bin -lbigballofmud + $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ torture/t_strcmp.o -L ./bin -lbigballofmud bin/t_strstr@EXEEXT@: $(BINARY_PREREQS) @LIBTALLOC_SHARED@ bin/libbigballofmud.@SHLIBEXT@ torture/t_strstr.o - $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_strstr.o -L ./bin -lbigballofmud + $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ torture/t_strstr.o -L ./bin -lbigballofmud bin/t_strappend@EXEEXT@: $(BINARY_PREREQS) @LIBTALLOC_SHARED@ bin/libbigballofmud.@SHLIBEXT@ torture/t_strappend.o - $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_strappend.o -L ./bin -lbigballofmud + $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ torture/t_strappend.o -L ./bin -lbigballofmud bin/t_stringoverflow@EXEEXT@: $(BINARY_PREREQS) bin/libbigballofmud.@SHLIBEXT@ torture/t_stringoverflow.o $(CC) $(FLAGS) -o $@ $(DYNEXP) torture/t_stringoverflow.o -L./bin -lbigballofmud -- cgit From 039c4f9261d1d898ae5d97ee1be974d9aaf26fd9 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 5 Mar 2008 15:04:28 +0100 Subject: Makefile: reformat - break long target lines. Michael (cherry picked from commit e26133808469cb7e9acc41cb15219d7b736d228a) (This used to be commit f3c06fccd6011d4e3c2e3f0dc1e37a0eb7e0f645) --- source3/Makefile.in | 193 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 129 insertions(+), 64 deletions(-) diff --git a/source3/Makefile.in b/source3/Makefile.in index 2e1078cdee..3180c185e7 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -374,7 +374,9 @@ LIBWBCLIENT_OBJ0 = nsswitch/libwbclient/wbclient.o \ nsswitch/libwbclient/wbc_idmap.o \ nsswitch/libwbclient/wbc_sid.o \ nsswitch/libwbclient/wbc_pam.o -LIBWBCLIENT_OBJ = $(LIBWBCLIENT_OBJ0) $(WBCOMMON_OBJ) @LIBTALLOC_STATIC@ $(LIBREPLACE_OBJ) +LIBWBCLIENT_OBJ = $(LIBWBCLIENT_OBJ0) \ + $(WBCOMMON_OBJ) \ + @LIBTALLOC_STATIC@ $(LIBREPLACE_OBJ) LIBGPO_OBJ0 = libgpo/gpo_ldap.o libgpo/gpo_ini.o libgpo/gpo_util.o \ libgpo/gpo_fetch.o libgpo/gpo_filesync.o libgpo/gpo_sec.o @@ -1259,12 +1261,14 @@ bin/smbd@EXEEXT@: $(BINARY_PREREQS) $(SMBD_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARE @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \ $(KRB5LIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \ $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) $(DNSSD_LIBS) \ - @POPTLIBS@ @SMBD_LIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ + @POPTLIBS@ @SMBD_LIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ \ + @WINBIND_LIBS@ bin/nmbd@EXEEXT@: $(BINARY_PREREQS) $(NMBD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ - @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @POPTLIBS@ \ + $(KRB5LIBS) $(LDAP_LIBS) bin/swat@EXEEXT@: $(BINARY_PREREQS) $(SWAT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @@ -1276,7 +1280,8 @@ bin/rpcclient@EXEEXT@: $(BINARY_PREREQS) $(RPCCLIENT_OBJ) @BUILD_POPT@ @LIBTALLO @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(PASSDB_LIBS) $(RPCCLIENT_OBJ) \ $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ \ - $(KRB5LIBS) $(LDAP_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ + $(KRB5LIBS) $(LDAP_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ \ + @WINBIND_LIBS@ bin/smbclient@EXEEXT@: $(BINARY_PREREQS) $(CLIENT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @@ -1289,15 +1294,19 @@ bin/net@EXEEXT@: $(BINARY_PREREQS) $(NET_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @L @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) \ - $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @INIPARSERLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ @LIBNETAPI_LIBS@ + $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) \ + @INIPARSERLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ \ + @LIBNETAPI_LIBS@ bin/profiles@EXEEXT@: $(BINARY_PREREQS) $(PROFILES_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(PROFILES_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(PROFILES_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ + $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/smbspool@EXEEXT@: $(BINARY_PREREQS) $(CUPS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ + $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/mount.cifs@EXEEXT@: $(BINARY_PREREQS) $(CIFS_MOUNT_OBJ) @BUILD_POPT@ @echo Linking $@ @@ -1309,23 +1318,27 @@ bin/umount.cifs@EXEEXT@: $(BINARY_PREREQS) $(CIFS_UMOUNT_OBJ) @BUILD_POPT@ bin/cifs.spnego@EXEEXT@: $(BINARY_PREREQS) $(CIFS_SPNEGO_OBJ) $(LIBSMBCLIENT_OBJ0) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(CIFS_SPNEGO_OBJ) $(DYNEXP) $(LDFLAGS) -lkeyutils $(LIBS) \ - $(LIBSMBCLIENT_OBJ0) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBWBCLIENT_SHARED@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(CIFS_SPNEGO_OBJ) $(DYNEXP) $(LDFLAGS) \ + -lkeyutils $(LIBS) $(LIBSMBCLIENT_OBJ0) $(KRB5LIBS) \ + $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBWBCLIENT_SHARED@ \ + @LIBTDB_LIBS@ bin/testparm@EXEEXT@: $(BINARY_PREREQS) $(TESTPARM_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(TESTPARM_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(TESTPARM_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ + $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/smbstatus@EXEEXT@: $(BINARY_PREREQS) $(STATUS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(STATUS_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) \ - @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(STATUS_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ + $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/smbcontrol@EXEEXT@: $(BINARY_PREREQS) $(SMBCONTROL_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) -DUSING_SMBCONTROL $(FLAGS) -o $@ \ - $(SMBCONTROL_OBJ) $(DYNEXP) $(LDFLAGS) \ - $(LIBS) $(LDAP_LIBS) @LIBUNWIND_PTRACE@ @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + $(SMBCONTROL_OBJ) $(DYNEXP) $(LDFLAGS) \ + $(LIBS) $(LDAP_LIBS) @LIBUNWIND_PTRACE@ @POPTLIBS@ \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/smbtree@EXEEXT@: $(BINARY_PREREQS) $(SMBTREE_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @@ -1342,7 +1355,8 @@ bin/smbpasswd@EXEEXT@: $(BINARY_PREREQS) $(SMBPASSWD_OBJ) @BUILD_POPT@ @LIBTALLO bin/pdbedit@EXEEXT@: $(BINARY_PREREQS) $(PDBEDIT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ - @POPTLIBS@ $(PASSDB_LIBS) $(LDAP_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ + @POPTLIBS@ $(PASSDB_LIBS) $(LDAP_LIBS) @LIBTALLOC_LIBS@ \ + @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/smbget@EXEEXT@: $(BINARY_PREREQS) $(SMBGET_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @@ -1357,12 +1371,15 @@ bin/nmblookup@EXEEXT@: $(BINARY_PREREQS) $(NMBLOOKUP_OBJ) @BUILD_POPT@ @LIBTALLO bin/smbtorture@EXEEXT@: $(BINARY_PREREQS) $(SMBTORTURE_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) \ + $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ \ + @LIBTDB_LIBS@ bin/talloctort@EXEEXT@: $(BINARY_PREREQS) $(TALLOCTORT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(TALLOCTORT_OBJ) $(LDFLAGS) \ - $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/replacetort@EXEEXT@: $(REPLACETORT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @echo Linking $@ @@ -1371,57 +1388,80 @@ bin/replacetort@EXEEXT@: $(REPLACETORT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ bin/masktest@EXEEXT@: $(BINARY_PREREQS) $(MASKTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ + $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/msgtest@EXEEXT@: $(BINARY_PREREQS) $(MSGTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ + $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/smbcacls@EXEEXT@: $(BINARY_PREREQS) $(SMBCACLS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBCACLS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ \ - $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ + @$(CC) $(FLAGS) -o $@ $(SMBCACLS_OBJ) $(DYNEXP) $(LDFLAGS) \ + $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/smbcquotas@EXEEXT@: $(BINARY_PREREQS) $(SMBCQUOTAS_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBCQUOTAS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ \ - $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ + @$(CC) $(FLAGS) -o $@ $(SMBCQUOTAS_OBJ) $(DYNEXP) $(LDFLAGS) \ + $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/eventlogadm@EXEEXT@: $(BINARY_PREREQS) $(EVTLOGADM_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) \ + $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/sharesec@EXEEXT@: $(BINARY_PREREQS) $(SHARESEC_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SHARESEC_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(SHARESEC_OBJ) $(DYNEXP) $(LDFLAGS) \ + $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/locktest@EXEEXT@: $(BINARY_PREREQS) $(LOCKTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ + $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/nsstest@EXEEXT@: $(BINARY_PREREQS) $(NSSTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ + $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/pdbtest@EXEEXT@: $(BINARY_PREREQS) $(PDBTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(PDBTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ + @$(CC) $(FLAGS) -o $@ $(PDBTEST_OBJ) $(LDFLAGS) $(DYNEXP) \ + $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ + @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ bin/vfstest@EXEEXT@: $(BINARY_PREREQS) $(VFSTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(ACL_LIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) @SMBD_LIBS@ $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ + @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) \ + $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \ + $(ACL_LIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) \ + @SMBD_LIBS@ $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ \ + @LIBWBCLIENT_SHARED@ bin/smbiconv@EXEEXT@: $(BINARY_PREREQS) $(SMBICONV_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBICONV_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(SMBICONV_OBJ) $(LDFLAGS) $(TERMLDFLAGS) \ + $(TERMLIBS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/log2pcap@EXEEXT@: $(BINARY_PREREQS) $(LOG2PCAP_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LOG2PCAP_OBJ) $(LDFLAGS) $(DYNEXP) @POPTLIBS@ $(LIBS) @LIBTALLOC_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LOG2PCAP_OBJ) $(LDFLAGS) $(DYNEXP) \ + @POPTLIBS@ $(LIBS) @LIBTALLOC_LIBS@ bin/locktest2@EXEEXT@: $(BINARY_PREREQS) $(LOCKTEST2_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(DYNEXP) \ + $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/ndrdump@EXEEXT@: $(BINARY_PREREQS) $(NDRDUMP_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ @@ -1430,41 +1470,49 @@ bin/ndrdump@EXEEXT@: $(BINARY_PREREQS) $(NDRDUMP_OBJ) @BUILD_POPT@ @LIBTALLOC_SH bin/debug2html@EXEEXT@: $(BINARY_PREREQS) $(DEBUG2HTML_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ + @$(CC) $(FLAGS) -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(DYNEXP) \ + $(LIBS) @LIBTALLOC_LIBS@ bin/smbfilter@EXEEXT@: $(BINARY_PREREQS) $(SMBFILTER_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) \ + $(KRB5LIBS) $(LDAP_LIBS) @POPTLIBS@ \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/ldbedit: $(BINARY_PREREQS) $(LDBEDIT_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDBEDIT_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ - @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ - $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LDBEDIT_OBJ) $(DYNEXP) $(LDFLAGS) \ + $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) \ + $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/ldbsearch: $(BINARY_PREREQS) $(LDBSEARCH_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDBSEARCH_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ - @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ - $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LDBSEARCH_OBJ) $(DYNEXP) $(LDFLAGS) \ + $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) \ + $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/ldbadd: $(BINARY_PREREQS) $(LDBADD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDBADD_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ - @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ - $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ + @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) \ + $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/ldbmodify: $(BINARY_PREREQS) $(LDBMODIFY_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDBMODIFY_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ - @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ - $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ + @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) \ + $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/ldbdel: $(BINARY_PREREQS) $(LDBDEL_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDBDEL_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ - @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \ - $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ + @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) \ + $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ $(LIBTALLOC_SHARED_TARGET): $(BINARY_PREREQS) $(LIBTALLOC_OBJ) @echo Linking shared library $@ @@ -1513,7 +1561,8 @@ bin/libaddns.a: $(BINARY_PREREQS) $(LIBADDNS_OBJ) $(LIBNETAPI_SHARED_TARGET): $(BINARY_PREREQS) $(LIBNETAPI_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking shared library $@ - @$(SHLD_DSO) $(LIBNETAPI_OBJ) @LIBTALLOC_LIBS@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ $(LIBS) \ + @$(SHLD_DSO) $(LIBNETAPI_OBJ) \ + @LIBTALLOC_LIBS@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ $(LIBS) \ $(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS) \ @SONAMEFLAG@`basename $@`.$(SONAME_VER) @ln -s -f `basename $@` $@.$(SONAME_VER) @@ -1524,7 +1573,8 @@ $(LIBNETAPI_STATIC_TARGET): $(BINARY_PREREQS) $(LIBNETAPI_OBJ1) bin/libsmbclient.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBSMBCLIENT_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking shared library $@ - @$(SHLD_DSO) $(LIBSMBCLIENT_OBJ) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ $(LIBS) \ + @$(SHLD_DSO) $(LIBSMBCLIENT_OBJ) \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ $(LIBS) \ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ @SONAMEFLAG@`basename $@`.$(SONAME_VER) @@ -1534,7 +1584,8 @@ bin/libsmbclient.a: $(BINARY_PREREQS) $(LIBSMBCLIENT_OBJ0) bin/libsmbsharemodes.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBSMBSHAREMODES_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking shared library $@ - @$(SHLD_DSO) $(LIBSMBSHAREMODES_OBJ) $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ \ + @$(SHLD_DSO) $(LIBSMBSHAREMODES_OBJ) \ + $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ \ $(KRB5LIBS) $(LDAP_LIBS) \ @SONAMEFLAG@`basename $@`.$(SONAME_VER) @@ -1545,7 +1596,8 @@ bin/libsmbsharemodes.a: $(BINARY_PREREQS) $(LIBSMBSHAREMODES_OBJ) # This is probably wrong for anything other than the GNU linker. bin/libbigballofmud.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBBIGBALLOFMUD_OBJ) @LIBTALLOC_SHARED@ @echo Linking shared library $@ - @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBBIGBALLOFMUD_OBJ) $(LIBS) @LIBTALLOC_LIBS@ \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBBIGBALLOFMUD_OBJ) \ + $(LIBS) @LIBTALLOC_LIBS@ \ $(PASSDB_LIBS) $(IDMAP_LIBS) $(KRB5LIBS) $(LDAP_LIBS) \ @SONAMEFLAG@`basename $@`.$(LIBBIGBALLOFMUD_MAJOR) ln -snf libbigballofmud.so bin/libbigballofmud.so.0 @@ -1631,13 +1683,16 @@ bin/winbindd@EXEEXT@: $(BINARY_PREREQS) $(WINBINDD_OBJ) @BUILD_POPT@ @LIBTALLOC_ bin/vlp@EXEEXT@: $(BINARY_PREREQS) $(VLP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo "Linking $@" - @$(CC) $(FLAGS) -o $@ $(VLP_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ \ - $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ + @$(CC) $(FLAGS) -o $@ $(VLP_OBJ) $(LDFLAGS) $(DYNEXP) \ + $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ \ + $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ @WINBIND_NSS@: $(BINARY_PREREQS) $(WINBIND_NSS_OBJ) @echo "Linking $@" @$(SHLD) $(WINBIND_NSS_LDSHFLAGS) -o $@ $(WINBIND_NSS_OBJ) \ - @WINBIND_NSS_EXTRA_LIBS@ @WINBIND_NSS_PTHREAD@ @SONAMEFLAG@`basename $@`@NSSSONAMEVERSIONSUFFIX@ + @WINBIND_NSS_EXTRA_LIBS@ @WINBIND_NSS_PTHREAD@ \ + @SONAMEFLAG@`basename $@`@NSSSONAMEVERSIONSUFFIX@ @WINBIND_WINS_NSS@: $(BINARY_PREREQS) $(WINBIND_WINS_NSS_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo "Linking $@" @@ -1879,7 +1934,8 @@ bin/aio_fork.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_AIO_FORK_OBJ) bin/wbinfo@EXEEXT@: $(BINARY_PREREQS) $(WBINFO_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(WBINFO_OBJ) $(DYNEXP) $(LIBS) \ - $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ + $(LDAP_LIBS) @POPTLIBS@ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ \ + @WINBIND_LIBS@ bin/ntlm_auth@EXEEXT@: $(BINARY_PREREQS) $(NTLM_AUTH_OBJ) $(PARAM_OBJ) \ $(LIB_NONSMBD_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @@ -1891,36 +1947,45 @@ bin/ntlm_auth@EXEEXT@: $(BINARY_PREREQS) $(NTLM_AUTH_OBJ) $(PARAM_OBJ) \ bin/pam_smbpass.@SHLIBEXT@: $(BINARY_PREREQS) $(PAM_SMBPASS_OBJ) @LIBTALLOC_SHARED@ @echo "Linking shared library $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_OBJ) -lpam $(DYNEXP) $(LIBS) $(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS) \ - @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ + @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_OBJ) -lpam $(DYNEXP) \ + $(LIBS) $(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS) \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ bin/tdbbackup@EXEEXT@: $(BINARY_PREREQS) $(TDBBACKUP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBBACKUP_OBJ) $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBBACKUP_OBJ) $(DYNEXP) \ + $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/tdbtool@EXEEXT@: $(BINARY_PREREQS) $(TDBTOOL_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBTOOL_OBJ) $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBTOOL_OBJ) $(DYNEXP) \ + $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/tdbdump@EXEEXT@: $(BINARY_PREREQS) $(TDBDUMP_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBDUMP_OBJ) $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBDUMP_OBJ) $(DYNEXP) \ + $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/tdbtorture@EXEEXT@: $(BINARY_PREREQS) $(TDBTORTURE_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBTORTURE_OBJ) $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ + @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(TDBTORTURE_OBJ) $(DYNEXP) \ + $(LIBS) @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ bin/t_strcmp@EXEEXT@: $(BINARY_PREREQS) @LIBTALLOC_SHARED@ bin/libbigballofmud.@SHLIBEXT@ torture/t_strcmp.o - $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ torture/t_strcmp.o -L ./bin -lbigballofmud + $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ \ + torture/t_strcmp.o -L ./bin -lbigballofmud bin/t_strstr@EXEEXT@: $(BINARY_PREREQS) @LIBTALLOC_SHARED@ bin/libbigballofmud.@SHLIBEXT@ torture/t_strstr.o - $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ torture/t_strstr.o -L ./bin -lbigballofmud + $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ \ + torture/t_strstr.o -L ./bin -lbigballofmud bin/t_strappend@EXEEXT@: $(BINARY_PREREQS) @LIBTALLOC_SHARED@ bin/libbigballofmud.@SHLIBEXT@ torture/t_strappend.o - $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ torture/t_strappend.o -L ./bin -lbigballofmud + $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) @LIBTALLOC_LIBS@ \ + torture/t_strappend.o -L ./bin -lbigballofmud bin/t_stringoverflow@EXEEXT@: $(BINARY_PREREQS) bin/libbigballofmud.@SHLIBEXT@ torture/t_stringoverflow.o - $(CC) $(FLAGS) -o $@ $(DYNEXP) torture/t_stringoverflow.o -L./bin -lbigballofmud + $(CC) $(FLAGS) -o $@ $(DYNEXP) torture/t_stringoverflow.o \ + -L./bin -lbigballofmud bin/timelimit@EXEEXT@: script/tests/timelimit.o @echo Linking $@ -- cgit From 681af65dd781c99d8ae3b6a85f7bf79b7a2e1ca0 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 5 Mar 2008 23:47:59 +0100 Subject: Build: fix bin/net on Solaris - use -ltdb instead of bin/libtdb.so Reported by Christian McHugh on the samba ML. Michael (cherry picked from commit 3398403c22c0f39b0d91621d81e31004fc8d28bc) (This used to be commit 350edda357a527822468bc055f6b866e11a99de7) --- source3/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/Makefile.in b/source3/Makefile.in index 3180c185e7..522ae65136 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1562,7 +1562,7 @@ bin/libaddns.a: $(BINARY_PREREQS) $(LIBADDNS_OBJ) $(LIBNETAPI_SHARED_TARGET): $(BINARY_PREREQS) $(LIBNETAPI_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @echo Linking shared library $@ @$(SHLD_DSO) $(LIBNETAPI_OBJ) \ - @LIBTALLOC_LIBS@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ $(LIBS) \ + @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @LIBWBCLIENT_SHARED@ $(LIBS) \ $(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS) \ @SONAMEFLAG@`basename $@`.$(SONAME_VER) @ln -s -f `basename $@` $@.$(SONAME_VER) -- cgit From 966074242c99d2bab02bb2fbbcc2c00a38d3af82 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 6 Mar 2008 07:19:46 +0100 Subject: Respect FAMChanged -- attempt to fix bug 5307 Thanks to Ricardo Santos (cherry picked from commit 8ef57a34ebf24e577ba7bca57a5456c1f78a3659) (This used to be commit a00275fde179ab8228fa9d678ec114b677bdecc0) --- source3/modules/vfs_notify_fam.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source3/modules/vfs_notify_fam.c b/source3/modules/vfs_notify_fam.c index 30cb0aa17c..aacc52e68c 100644 --- a/source3/modules/vfs_notify_fam.c +++ b/source3/modules/vfs_notify_fam.c @@ -155,6 +155,9 @@ static void fam_handler(struct event_context *event_ctx, fam_event.filename)); switch (fam_event.code) { + case FAMChanged: + ne.action = NOTIFY_ACTION_MODIFIED; + break; case FAMCreated: ne.action = NOTIFY_ACTION_ADDED; break; -- cgit From aa6277162edcefbb8148281dae19e795883d4dbd Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 5 Mar 2008 19:54:34 +0100 Subject: Another build fix for pam_smbpass: make sure libwbclient is there. Guenther (cherry picked from commit f6762f9cd0b2ace46e16d246adf2e386749650f9) (This used to be commit 4c2a6ef16090df2bca0811806c982e0e8f3f1eb8) --- source3/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/Makefile.in b/source3/Makefile.in index 522ae65136..5ebda854f8 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1945,7 +1945,7 @@ bin/ntlm_auth@EXEEXT@: $(BINARY_PREREQS) $(NTLM_AUTH_OBJ) $(PARAM_OBJ) \ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/pam_smbpass.@SHLIBEXT@: $(BINARY_PREREQS) $(PAM_SMBPASS_OBJ) @LIBTALLOC_SHARED@ +bin/pam_smbpass.@SHLIBEXT@: $(BINARY_PREREQS) $(PAM_SMBPASS_OBJ) @LIBTALLOC_SHARED@ @LIBWBCLIENT_SHARED@ @echo "Linking shared library $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_OBJ) -lpam $(DYNEXP) \ $(LIBS) $(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS) \ -- cgit From baed6131d57c645d8c8e2649a371341fcf787afa Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 5 Mar 2008 22:21:10 +0100 Subject: Fix build targets for bin/net. Guenther (cherry picked from commit 5159e3dafa9f9bb85cde6681052d8f54b8bf8a2e) (This used to be commit 1718c1b5448d0e73cbd50da5ffba29a487d68b3d) --- source3/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/Makefile.in b/source3/Makefile.in index 5ebda854f8..3e47b1f03f 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1290,7 +1290,7 @@ bin/smbclient@EXEEXT@: $(BINARY_PREREQS) $(CLIENT_OBJ) @BUILD_POPT@ @LIBTALLOC_S $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) $(DNSSD_LIBS) \ @LIBTALLOC_LIBS@ @LIBTDB_LIBS@ @WINBIND_LIBS@ -bin/net@EXEEXT@: $(BINARY_PREREQS) $(NET_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ +bin/net@EXEEXT@: $(BINARY_PREREQS) $(NET_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@ @LIBNETAPI_SHARED@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) \ -- cgit From 3785b898178bda8e2aff763d462f21d105aa350d Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 6 Mar 2008 10:26:29 +0100 Subject: Make test: set LD_LIBRARY_PATH for make test_shlibs and friends. Michael (cherry picked from commit 21a527569bccff8e8cb6e751c9f3fce6ff598204) (This used to be commit 25a63d044e82ae3cbd9b8e350fcf4cf548236caa) --- source3/Makefile.in | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source3/Makefile.in b/source3/Makefile.in index 3e47b1f03f..3df7958b1a 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -2344,7 +2344,8 @@ Makefile: $(srcdir)/Makefile.in config.status # Check shared libs for unresolved symbols test_shlibs: $(SHLIBS) @echo "Testing $(SHLIBS) " - @for module in $(SHLIBS); do \ + @export $(LIB_PATH_VAR)=./bin && \ + for module in $(SHLIBS); do \ ./script/tests/dlopen.sh bin/$${module}.@SHLIBEXT@ \ || exit 1; \ done @@ -2352,7 +2353,8 @@ test_shlibs: $(SHLIBS) # Check for NSS module problems. test_nss_modules: nss_modules @echo "Testing $(NSS_MODULES) " - @for module in $(NSS_MODULES); do \ + @export $(LIB_PATH_VAR)=./bin && \ + for module in $(NSS_MODULES); do \ ./script/tests/dlopen.sh $${module} \ || exit 1; \ done @@ -2361,7 +2363,8 @@ test_nss_modules: nss_modules # built can actually be loaded by a minimal PAM-aware application. test_pam_modules: pam_modules @echo "Testing $(PAM_MODULES) " - @for module in $(PAM_MODULES); do \ + @export $(LIB_PATH_VAR)=./bin && \ + for module in $(PAM_MODULES); do \ ./script/tests/dlopen.sh -lpam -ldl bin/$${module}.@SHLIBEXT@ \ || exit 1; \ done -- cgit