diff options
118 files changed, 13000 insertions, 4703 deletions
diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 179a31c7fda..22e5b56accc 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,6 +1,5651 @@ - WHATS NEW IN Samba 3 SVN - ======================== + =============================== + Release Notes for Samba 3.0.21a + Dec 30, 2005 + =============================== -This file is NOT maintained but will be created during releases. -See the SAMBA_3_0_RELEASE branch for the current WHATSNEW. +This is the latest stable release of Samba. This is the version +that production Samba servers should be running for all current +bug-fixes. Please read the following important changes in this +release. + +###################################################################### +Changes +####### + +Changes since 3.0.21 +-------------------- + +commits +------- +o Gerald (Jerry) Carter <jerry@samba.org> + * RedHat 9 packaging Fixes. + + +o Guenther Deschner <gd@samba.org> + * eDirectory schema syntax fixes. + + +o Volker Lendecke <vl@samba.org> + * BUG 3349: Deadlock caused logic error in oplock code. + + +Release Notes for older release follow: + + -------------------------------------------------- + ============================== + Release Notes for Samba 3.0.21 + Dec 20, 2005 + ============================== + +Common bugs fixed in 3.0.21 include: + + o Missing groups in a user's token when logging in via kerberos + o Incompatibilities with newer MS Windows hotfixes and + embedded OS platforms + o Portability and crash bugs. + o Performance issues in winbindd. + +New features introduced in Samba 3.0.21 include: + + o Complete NTLMv2 support by consolidating authentication + mechanism used at the CIFS and RPC layers. + o The capability to manage Unix services using the Win32 + Service Control API. + o The capability to view external Unix log files via the + Microsoft Event Viewer. + o New libmsrpc share library for application developers. + o Rewrite of CIFS oplock implementation. + o Performance Counter external daemon. + o Winbindd auto-detection query methods when communicating with + a domain controller. + o The ability to enumerate long share names in libsmbclient + applications. + + +###################################################################### +Changes +####### + +smb.conf changes +---------------- + + Parameter Name Action + -------------- ------ + dfree cache time New + dfree command Per share + eventlog list New + iprint server New + map read only New + passdb expand explicit New + rename user script New + reset on zero vc New + svcctl list Renamed from 'enable svcctl' + + + +Changes since 3.0.20b +--------------------- + +o Jeremy Allison <jra@samba.org> + * BUG 1828: Fixed SPNEGO issues with PocketPC clients. + * Added 'map readonly' parameter. + * BUG 3166: Fix crash in libsmbclient if the $HOME environment is + not defined. + * Maintain schannel client session keys in volatile + $(privatedir)/schannel_store.tdb. + * BUG 2769: Ensure we mangle filenames ending in a space + * Catch corner case of renaming a symlinked directory into + itself + * Ensure that smb.conf requests for hidden files are honored, + even when DOS attributes are stored in EA's + * Add new auth method "auth_script" for calling an external + program + * BUG 2152: Fix for mangled filenames when the client does + support long filenames + * Rewritten implementation of client and server DCE/RPC infrastructure + * BUG 3192: Adds a "dfree cache time" parameter. + * Fix acl evaluation bug found by Marc Cousin. Only evaluate + the S_IWGRP mask in the absence of a POSIX ACL. + * Remove use of 'long long' in libsmbclient code. + * Ensure the new canonicalize_servicename() in name/snum hash + is multi-byte safe. + * BUG 2922: Integration of FreeBSD AIO patches from Timur + Bakeyev. + * BUG 3216: Put directory opens into the share mode db so we + can treat them similarly to file opens (delete on close, + share mode violations etc.). + * Fix bug in name mangling code when case sensitivity is enabled. + * Remove external dependencies from the sharemodes library. + * BUG 3212: Ignore bogus OS/2 set EA values on trans2 calls. + * Don't misinterpret wild card characters in file names on disk + as they are actually valid characters. + * BUG 3223: Fix bug in account policy management when + account_pol.tdb settings have been migrating to an LDAP + backend. + * Allow the hash size of the tdb open (locking) database to be + set in local.h. + * Fix error code returns on client spoolss code. + * Remove unneeded strncpy use. + * Fix uninitialized variables warnings. + * Cleanup smbcacls security descriptor parsing and error codes. + * BUG 3224: Correctly use machine_account_name and client_name + when doing netlogon credential setup. Fixes winbindd running + on a Samba PDC. + * Backport Samba 4 time zone handling. + * Fix core dump if setmntent() returns NULL. + * Replace old crc32 code with one from the FreeBSD tree. + * Filter stored DOS attributes by SAMBA_ATTRIBUTES_MASK. + * Remove #define of close -> close_fn macro in libsmbclient. + * Return early if -1 returned from *BSD EA call (reported by + Timur). + * Name space cleanup by marking local functions static. + * Move samr enumeration cache from per handle basis to a shared + cache. + * BUG 3274: Fix invalid smbclient qpath_basic() queries against + OS/2 servers (based on patch from Guenter Kukkukk). + * Ensure default applies to new files (reported by Thomas + Neumann). + * BUG 3293: Use SMBecho to testing the server in client rather + than SMBchkpath. + * Merge talloc fixes from Samba 4 branch. + * Add support DCE/RPC cancel operation. + * Don't reset attrs to zero in EA get. Fixes 'hide dot files' + when using EA for DOS attributes. + * Fix bug in returning remote time (reported by Thomas Bork). + * No users or groups to return in BUILTIN domain. + * Removed separate "builtin" search enumeration. + * Added count_sam_aliases to return the correct alias count. + * Correctly handle the LDAP_UNWILLING_TO_PERFORM error from + eDirectory when accessing the universal password. + * Fix deadlock condition in share mode locking code. + * Fix logic bug in unix_mask_match(). + * Fix memory leak in SMB client code found by Mikhail Kshevetskiy. + + +o Rashid N. Achilov <shelton@granch.ru> + * Add better service description names to the svcctl code. + + +o Timur Bakeyev <timur@com.bat.ru> + * BUG 3262: Improve FreeBSD DOS attribute error reporting. + + +o Andrew Bartlett <abartlet@samba.org> + * Remove another ancient NTLMSSP implementation. + * Allow machine account logons work if the client gives the + appropriate flags. + + +o Alexander Bokovoy <ab@samba.org> + * Add POSIX statvfs() to VFS api. + + +o Gerald (Jerry) Carter <jerry@samba.org> + * Eventlog and ServiceControl support. + * BUG 1051: store the directory path so we can send the full + name in the unlink call from smbclient. + * Use reference count strategy for keeping the registry tdb + open. + * Convert internal registry objects to new hierarchical talloc + * Allow the root user a free pass for access checks in the + registry and service control checks. + * Sanity checks in the privilege code to prevent empty SID + entries + * Add basic infrastructure for 'make test' when the socket + wrapper library is configured at compile time + * Convert profiles utility to use the current regfio interface + for reading and writing user profiles + * Remove netsamlogon_cache interface + * Ensure that print jobs are removed even when the cancel + command is received before the print cache has been updated + * Fix linking problem on Solaris when including ACL support. + * Give root a free pass to open the eventlog tdb files. + * Fix segfault in addprinter due to mixing talloc() and + malloc()'d memory. + * fix invalid read reported by valgrind in the spoolss + backchannel connection. + * Remove use of 'long long' in perfcounter registry code. + * BUG 3201: make sure request structure is cleared prior to + sending the request to winbindd. + * Don't count open pipes in the num_files_open on a connection + (regression from Samba 2.2). + * Ensure servername hashing code normalizes the name. + * Fix checks for connect() in -lnsl[_s]. + * Convert eventlog API to use NTSTATUS return codes rather + than WERROR. + * Fix segv in winbindd caused by an uninitialized variable + in winbindd_dual_getsidaliases(). + * Allow winbindd to select the appropriate backend methods + based on the DC attributes and not the security parameter. + * Re-add the netsamlogon_cache tdb and ensure that user entries + are updated from the PAC data during kerberos ticket + validation. + * Fix lockup when running 'wbinfo -t' on a Samba PDC caused + by mangling machine names in sub_set_smb_name(). + * Add smbget to the list of tools built by default. + * Fix clearing of eventlog tdb files. + * Fix sequential reads in eventlog support. + * BUG 2718: Don't use qpathinfo_basic() call when remote server + is Win9x. + * Fix build issues with the Sun compiler. + * BUG 3156: Don't use find_service() when explicitly looking + for a printer. + * Fix nss_winbind_solaris.c build breakage on HP-UX. + * Initialize the local group description. + * Disable WINS and NetLogon services in the MMC services + plugin when the associated smb.conf features are not enabled. + * Add checks for invalid characters in new share names on the + srvsvc pipe. + * Fix SWAT installation issues with 'make install'. + + +o Alex Deiter <tiamat@komi.mts.ru> + * BUG 3196: Patch to compile against the Sun LDAP client libs. + (not for AD support; just ldap support). + + +o Guenther Deschner <gd@samba.org> + * Fixed compile problems and warnings with newer OpenLDAP + and OpenSSL libs + * Fix bug when enumerating trusted domains via 'wbinfo -m' + * Parse the MS Kerberos PAC to obtain the user group + membership during logon. + * Add support for SeRestorePrivilege to allow a process to + change the ownership of a file to any arbitrary account + * Fix password history storage when using Novell eDirectory for + ldapsam storage + * Backport Kerberos PAC parsing from Samba 4 branch in order to + correctly create the NT User Token when logging into a Samba + member server + * Add small helper function to return a PAC_LOGON_INFO. + * Use LDAP bitwise matching rule when searching for groups + in ADS. + * Avoid an infinite loop when retrying to connect in smbspool. + * Memory leak fixes in the kerberos PAC parsing code. + * Improve NT_STATUS error messages returned from pam_winbind. + * Rename unknown samr group fields in samr structures with + the correct name.removed separate "builtin" search enumeration. + * Cleanup redundant StartTLS code. + * Allow StartTLS support when connecting to Windows 2003 by + setting 'ldap ssl = start_tls'. + * Support raw NTLMSSP session setups in smbspool. + * Add rpccli_samr_chgpasswd3(). + * Add 'wbinfo --separator'. + * Uninitialized warnings fixes. + * Fix return value in client spooler code. + * Require forced migration of account policies. + + +o Steve French <sfrench@us.ibm.com> + * Fix cifs to handle non-numeric uid and gid parameters. + * Merge trunk and SAMBA_3_0 mount.cifs code. + * Cleanup cifs cfs help message. + + +o Paul Green <paulg@samba.org> + * Update to the latest config.guess and config.sub files. + + +o Deryck Hodge <deryck@samba.org> + * Allow control of syslog facility and level in audit vfs modules. + + +o S Murthy Kambhampaty <smk_va@yahoo.com> + * Patches for Fedora RPM specfile and init script + + +o Krishna Ganugapati <krishnag@centeris.com> + * Use the subtree delete ldap control when running 'net ads + leave'. + + +o Volker Lendecke <vl@samba.org> + * New oplock implementation. + * Add assert() call if winbindd cannot locate the domain SID in + secrets.tdb on startup + * Fix an annoying timeout in winbindd when nmbd is not running. + * Speed up loading smb.conf for large numbers of share + definitions by adding an internal hashing of names to snums. + Thanks to Michael Adam. + * Fix potential segv in rpcclient's lsarpc calls. + * Fix bugs in winbindd's use of rpccli_netlogon_getdcname(). + * Fix alignment in getdc response. + * Allow pdbedit to set the domain for a user account. + * Fix fallback logic in rpc binds. + * Fix memleak in message handling code. + * Fix connection bug to port 445 and 139 after a successful + getdcname response. + * Add additional calls to initialize_krb5_error_table() for + kerberos client code. + * Implement the possibility to have AFS users as SIDs in pts. + * Removed unused alternative_name code from winbindd. + * Protect against NULL alternative_name strings in winbindd. + * Define a default panic action with -DEVELOPER is defined. + * Add the capability to reset smbd connections on a zero VC id. + * Allow smb.conf variable expansion to be disabled in passdb + backends. + * Add lookupname to rpcclient query_user as a fallback. + * BUG 3292: Prevent smbclient from spinning when the server + disconnects. + * BUG 2191: Fix valgrind error in cli_session_setup_guest(). + * Add samr_lookup_rids for the builtin domain. + * Memory allocation cleanups in passdb. + * Restrict samr_open_domain() to our domain only. + * Change local_lookup_sid() to local_lookup_rid() since it + is responsible for our domain only. + * Fix some uninitialized variable warnings. + * Fix winbind_lookup_name for the local domain, + + +o Derrell Lipman <derrell@samba.org> + * Cleanup libmsrpc version numbers. + * Libsmbclient memory & file descriptor leak fixes. + * Fix crash bug in libsmbclient. + * Add long share name support to libsmbclient when enumerating shares. + + +o Jason Mader <jason@ncac.gwu.edu> + * Removed compiler various warnings. + + +o Alex Masterov <alex@infobit.ru> + * BUG 3218: Fix XATTR calls on *BSD systems. + + +o Jim McDonough <jmcd@us.ibm.com> + * Speed up string_to_sid by removing next_token calls and + unneeded strncmp() calls. + * Implement user rename for smbpasswd and LDAP backends. + * BUG 2961 (partial): Add rename support for user accounts to tdbsam + * BUG 3187: Fix time zone offset in logon hours restrictions. + + +o Stefan Metzmacher <metze@samba.org> + * Fix setting of quotas on linux kernel with the struct + if_dqblk interface + * Enable sysquota interfact on Linux by default + * Use lp_socket_address() when binding to port 138/udp in nmbd. + + +o Brian Moran <bmoran@centeris.com> + * Eventlog and ServiceControl support. + * Added eventlogadm tool for writing Eventlog records. + * Fix typo when creating Eventlog source DLL registry paths. + * Add simple script to tail syslog and write records to + eventlog tdb. + * Fix segv in eventlogadm when not event logs are listed in + smb.conf. + + +o Lars Müller <lmuelle@samba.org> + * Only install smbsh manpage if smbwrapper has been successfully + built. + * Ensure setmntent() returns with != NULL in the disk_quotas() + Linux version. + * Add configure switch to disable libmsrpc build. + * Add a soname to libmsrpc. + + +o Ricky Nance <ricky.nance@gmail.com> + * Updates for the mklogon perl scripts. + + +o Chris Nicholls <skel@samba.org> + * New libmsrpc library (Google SoC Project). + * Fix libmsrpc build of on the Sun compiler by removing empty + structure declarations. + + +o James Peach <jpeach@sgi.com> + * Fix parsing error for smb ports parameter. + + +o Tim Potter <tpot@samba.org> + * BUG 3260: Fix DYNEXP flags on HPUX. + + +o Marcin Porwit <mporwit@centeris.com> + * Eventlog and ServiceControl support. + * Added basic Performance Counter daemon which can feed data + for the Windows perfmon.exe tool. + * Fix directory permissions in the perfcounter daemon. + * Add the 'File' registry value for the eventlog keys. + + +o Aruna Prabakar <aruna.prabakar@hp.com. + * Add checks to verify that the spooler is running on HP-UX when + reloading the printer name cache. + + +o Joel Smith <joel.j.smith@novell.com> + * Add iPrint printing backend support. + + +o Toomas Soome <Toomas.Soome@mls.ee> + * Implement host lookups in nss_winbind.so.1 on Solaris + + +o Simo Sorce <idra@samba.org> + * Update Debian packaging. + + +o John Terpstra <jht@samba.org> + * Add 'net idmap' usage help text. + + +o Andrew Tridgell <tridge@samba.org> + * Change license notice of standalone talloc library to LGPL. + + +o Darren Tucker <dtucker@zip.com.au> + o Crash fix for snprintf() code. + + +o Rainer Weikusat <rainer.weikusat@sncag.com> + * Fix function name typo in skeleton VFS code. + + + +Release Notes for older release follow: + + -------------------------------------------------- + =============================== + Release Notes for Samba 3.0.20b + Oct 12, 2005 + =============================== + +Common bugs fixed in 3.0.20b include: + + o A crash bug in winbindd + o Reporting files as read-only instead of returning the + correct error code of "access denied" + o File system quota support defects + + +###################################################################### +Changes +####### + + +Changes since 3.0.20a +--------------------- + +commits +------- + +o Jeremy Allison <jra@samba.org> + * BUG 3088: Fix error condition for files on a read-write share + which cannot be read due to permissions. + + +o Gerald (Jerry) Carter <jerry@samba.org> + * BUG 3070: Fix crash bug in qfsinfo when retrieving fs quota + details. + * BUG 1473, 3090: Quota detection and compilation problems on + Solaris. + + +o Marc Balmer <marc@msys.ch> + * Build fixes when builddir != srcdir + + +o Alex Deiter <tiamat@komi.mts.ru> + * BUG 3145: Fix build issue regarding quota support on Solaris. + + +o Volker Lendecke <vl@samba.org> + * BUG 3068: Fix for winbindd crashed by empty DC alternative + name. + + + -------------------------------------------------- + =============================== + Release Notes for Samba 3.0.20a + Sept 30, 2005 + =============================== + +Common bugs fixed in 3.0.20a include: + + o Stability problems with winbindd. + o Crash bugs caused by incompatibilities on 64-bit systems. + o Missing files from directory listings on AIX servers + o User Manager interoperability problems. + o Minor build difficulties on various platforms such as + Solaris and OpenBSD, + + +Winbind, security = domain, and Active Directory +================================================ + +Recent security updates for Windows 2000 and Windows 2003 have +changed the fashion in which user and group lists can be obtained +from domain controllers. In short, the RPC mechanisms used by +"security = domain" to retrieve users and groups is not compatible +with these changes. The "security = ads" configuration is not +affected by the Windows protocol changes. + +Samba developers are actively working to correct this problem in +the 3.0.21 release. In the meantime, Administrators who are unable +to migrate to "security = ads" and must continue using "security = +domain", can define credentials to be used by winbindd for account +enumeration by executing the following command as root. + + wbinfo --set-auth-user='DOMAIN\username%password' + + + +###################################################################### +Changes +####### + + +Changes since 3.0.20 +-------------------- + +commits +------- + +o Jeremy Allison <jra@samba.org> + * BUG 3065: Fix for legacy clients retrieving a listing of + an empty directory. + * Added external library for accessing Samba's share mode + database. + * Fix winbindd credentials chain which caused logon failures + after attempting to authenticate an unknown user. + * Fix recursive looping bug in winbindd. + * Fix build errors on 64-bit systems. + * Posix ACL memory leak and crash bug fixes. + * BUG 3044: Ensure OPEN-EXEC is honored as read-only. + * BUG 3060: Ensure SMBcreate truncates the file if it exists. + * Hide dot files and directory logic fixes. + * Correct display of open file modes by smbstatus. + * BUG 3010: Fix missing files bug on AIX systems. + + +o Gerald (Jerry) Carter <jerry@samba.org> + * Allow the root user to automatically pass se_access_checks() + in the registry and service control server code. + * Ensure that winbindd uses the correct name in the net_auth2() + request when running on a Samba PDC. + * Fix linking problem with tdb utilities. + * BUG 3080: Fix regression in 'net rpc shutdown' command. + * Fix segv in 'net rpc' when the pipe open fails. + * Fix upload bug when installing 64-bit Windows printer drivers. + * Fix regression in the smburi syntax used by smbspool. + * Fix sorting of subkey hash records in registry files. + * Correct REG_CREATE_KEY_EX parsing error. + * Interoperability issues with usrmgr.exe and Samba groups. + * Use the display names and not the Unix names when enumerating + groups in the ldapsam passdb backend. + * Ensure that Windows domain user names are converted to lower case. + + +o Guenther Deschner <gd@samba.org> + * Prevent BUILTIN sids returned in the user's token from + a Windows DC from being applied to any local group mappings + on the Samba host. + * Plug memory leaks in the kerberos keytab code. + * Ensure BUILTIN groups are returned from winbindd's idmap_rid + backend when 'winbind nested groups' is enabled. + * Fix crash bug in winbindd caused by 64-bit build issues. + * Improve debug messages in smbspool. + * Give better error-message when "NDS Universal Password" change fails. + * Fix password history error in the eDirectory schema file. + * Ensure that Windows domain group names are converted to lower case. + + +o Steve French <sfrench@us.ibm.com> + * Allow disabling mandatory byte range lock mount flag, and fix + corresponding entry in mtab. + + +o Volker Lendecke <vl@samba.org> + * Fix race condition in the NTcreate&X open code when the + disposition is NTCREATEX_DISP_CREATE. + * Correct logic error when checking the pid for pending print + change notify messages. + * Ensure that winbindd child process complete startup even when + the parent is receiving authentication requests. + * Return the full NTSTATUS code to ntlm_auth and pam_winbindd + when authentication fails. + + +o Jason Mader <jason@ncac.gwu.edu> + * Compile warning fixes. + + +o Uli Meis <a.sporto@gmail.com> + * Patches for pdb_*sql.c + + +o Luke Mewburn <lukem@NetBSD.org> + * Autoconf syntax fixes. + + +o James Peach <jpeach@sgi.com> + * Correct problem with creating a core file in Linux. + + +o Stefan Metzmacher <metze@samba.org> + * Quota fixes in smbd. + + +o Peter Rindfuss <rindfuss@wz-berlin.de> + * Patches for pdb_*sql.c + + +o Jiri Sasek <Jiri.Sasek@Sun.COM> + * Solaris toolchain patches for autoconf scripts. + + +o Andrew Tridgell <tridge@samba.org> + * Fix for tdb clear-if-first race condition. + + +o Leo Weppelman <leo@wau.mis.ah.nl> + * BUG 3104: Don't allow time updates to files on read-only shares. + + +o Steve Williams <steve@celineandsteve.com> + * BUG 3052: Fix compile issues on OpenBSD. + + + -------------------------------------------------- + ============================== + Release Notes for Samba 3.0.20 + Aug 19, 2005 + ============================== + +Additional features introduced in Samba 3.0.20 include: + + o Support for several new Win32 rpc pipes. + o Improved support for OS/2 clients. + o New 'net rpc service' tool for managing Win32 services. + o Capability to set the owner on new files and directory + based on the parent's ownership. + o Experimental, asynchronous IO file serving support. + o Completed Support for Microsoft Print Migrator. + o New Winbind IDmap plugin (ad) for retrieving uid and gid + from AD servers which maintain the SFU user and group + attributes. + o Rewritten support for POSIX pathnames when utilizing + the Linux CIFS fs client. + o New asynchronous winbindd. + o Support for Microsoft Print Migrator. + o New Windows NT registry file I/O library. + o New user right (SeTakeOwnershipPrivilege) added. + o New "net share migrate" options. + + +What happened to 3.0.15 - 3.0.19? +================================== + +After some discussion it was deemed that the amount of changes +going into the next Samba 3.0 release needed something to catch +people's attention. Skipping several releases was chosen as +the best solution with the least overhead. There will be no +3.0.15 - 3.0.19 ever released. The next production release +following 3.0.20 should be 3.0.21. + +The original announcement about the version number change can +be found in the samba mailing list archives: + +http://marc.theaimsgroup.com/?l=samba&m=111721010206997&w=2 + + +Asynchronous Winbind Implementation +=================================== + +Winbindd has been completely rewritten in this release to support +an almost completely non-blocking, asynchronous request/reply +model. This means that winbindd will scale much better in +large domain environments and on high latency networks. Neither +the client interface nor the command line tools (i.e. wbinfo) have +changed in their calling conventions or syntax. However, due to +internal structure changes, it is required (more so than normal) +that you install the nss_winbind.so library included in this release. + + +Support for Microsoft Print Migrator +==================================== + +Samba 3.0.20 includes full support for migrating printers from +Windows servers or other Samba servers via the Microsoft Print +Migrator tool. Restoring printers requires a working "add printer +command" defined in smb.conf. Current support also allows +administrators to create a master list of printer drivers which +can be restored in bulk on new (or existing) Samba installations. + + +Asynchronous IO Support +======================= + +Experimental support for async IO has been added to smbd for +certain platforms. To enable this new feature, Samba must be +compiled to include the --with-aio-support configure option. +In addition, the "aio read size" and "aio write size" to non-zero +values. See the smb.conf(5) man page for more details on these +settings. + + +###################################################################### +Changes +####### + +smb.conf changes +---------------- + + Parameter Name Action + -------------- ------ + acl check permissions New + acl group control New + acl map full control New + aio read size New + aio write size New + enable asu support New + inherit owner New + ldap filter Removed + map to guest Modified (new value added) + max stat cache size New + min password length Removed + printer admin Deprecated + username map script New + winbind enable local accounts Removed + winbindd nss info New + + +Changes since 3.0.14a +--------------------- + + +commits +------- + +o Jeremy Allison <jra@samba.org> + * BUG 2533: Fix incorrect directory listings for OS/2 clients. + * Ensure the old SMB search calls always ask mask_match() to + translate patterns like ????????.???. + * Split out the check_path_syntax() into a findfirst, findnext, + & wildcard versions. + * Fix checks for matching groups in an file ACL against the + user's primary and supplementary group list. + * BUG 2541: Ensure we recognize LANMAN2.1 as OS/2 and select + LANMAN2 protocol, ensure the EA size is always correctly + set on a query for a file with no EA's. + * BUG 2551: Look at the incoming flags2 flag + FLAGS2_LONG_PATH_COMPONENTS determines if a reply is + uppercased on a SMBsearch request, not the protocol level. + * Added "volume" command to smbclient that prints out the + volume name and serial number. + * Added "fix for broken SMB_INFO_VOLUME level used by OS/2. + * Add support for OS/2 Extended Attributes. + * Correctly check OpenX open modes. + * Ensure allocation size is correctly returned for OpenX. + * Only set allocation on create/truncate for nttrans. + * Fix oplock bug in trans2open() code. + * Remove unix_ERR_XXX global nastiness. + * Only do the strange DOS error for openX, not trans2open. + * Ensure SMBopen replies includes the share modes as well as + open modes. + * BUG 2581: Add size limit (in kb) to stat cache. + * Fix bug in the trans2 secondary processing. + * BUG 2601: Enforce DOS_OPEN_EXEC to mean read-only. + * Add an SMB counter per connection struct for gathering + profiling data. + * BUG 2605: Ensure smbclient doesn't perform commands if + the "chdir" fails in a scripted set. + * Ensure a 'forced group' is added to the list of effective + gids when processing ACLs. + * Refactor rpc_bind structures for better future work. + * BUG 2942: Add missing value in debug message. + * BUG 2946: Fix regressions in str[n]cmp_w) functions found + by 'mangling method = hash'. + * Fix memory leaks in the msdfs trans2 server code. + * Convert msdfs server to be talloc'd based. + * Fix up stackable vfs interface. + * Fix rpc fault when encountering an unknown rpc_bind auth + type. + * BUG 2954: More AIX 5.1 AIO compile fixes. + * Fix valgrind bug in interaction with new aio buffer (found + by Volker). + * BUG 2878: Fix Norton commander not running on OS/2 clients. + * Cleanup SAMR user info structure naming. + * BUG 2889: Fix directly listings from OS/2 clients. + * Added "acl group control" parameter. + * Add debug warning if AddPrinterEx() is called without having + an 'add printer command' defined. + * Add better log messages when modifying ldap entries. + * BUG 2829: Fix strXX_w() functions on non-x86 platforms when + when string is unaligned. + * BUG 2918: Fix SMB chaining by ensuring that deferred open + message buffer is nor reused. + * Add support for client setting capabilities to select posix + pathnames on the wire. + * Stop using C++ reserved words so that Samba can be compiled + using g++. Also allows VFS modules in C++. + * More fixes to allow better large directory scaling. + * BUG 2827: Ensure we call the vfs connection hook before + doing a vfs stat. Allows database vfs backends to initialize + with a working connection. + * BUG 2826: Ensure the correct return value for symlink and + readlink in the VFS. + * Merge handling of ASN.1 objects bigger than 64k from Samba 4. + * Added AIO support to smbd. + * Add "acl map full control", true by default, to allow people + to change mapping of rwx to full control or not. + * Transition smbd to use NTcreate&X for internal file opens. + * Add checks against the current effective group id (e.g. force + user) when testing write permissions one ACLs. + * Fix FindFirst/FindNext server code when parsing directories + on old IRIX XFS file systems (thanks to Cale Fairchild + for the debugging help). + * BUG 2644: Test for special files to be ignored was reversed. + * Ensure yield_connection() is called on all appropriate error + conditions. + * Fix EDEADLCK problem with deferred open calls. + * BUG 2622: Remove DPTR_MASK as it makes no sense. + * Fix the write cache based on some VERY good detective work + from Ingo Kilian. + * BUG 2346: Fix read-only excel file bugs. + * Don't wrap the setfsinfo call in HAVE_QUOTA as they'll just + return ENOSYS if not implemented. + * Add new CAP for POSIX pathnames. + * BUG 2703: Add NULL guard for disp_fields[0]. + * BUG 2681: With "strict allocate = yes" we now zero fill when + a file is extended. Should catch disk full errors on write + from MS-Office. + * Add "acl check permissions" to turn on/off the new + behavior of checking for write access in a directory + before delete. + * Refactor printing interface to take offset into job. + * Allow mapping of POSIX ACLs to NT perms to differentiate + between directories and files. + * Added encrypt/decrypt function for LSA secrets and trusted + domain passwords on the wire. + * BUG 2729: Resume keys are *mandatory* for a search when + listing a W2K and above server from a FATxx filesystem only. + * BUG 2735: Ensure that smbd mangles control characters in file + and directory names. + * Refactor small pieces of socket handling code (in conjunction + with Derrell). + * BUG 2698: Fix infinite listing loop in smbclient caused by + an invalid character set conversion. + * Add client code that will abort a directory listing if we + see the same name twice between packets. + * Performance improvements in trans2 qfilepathinfo code by + removing unnecessary memset() calls. + * Rewrite the RPC bind parsing functions to follow the + spec; fixes bug with 64-bit Windows XP and OS X 10.4. + * BUG 2774: Set sparse flag if needed when returning + file attributes. + * Fix errors listing directories from Windows NT clients + which caused "." and ".." to show up in explorer.exe. + * Merge of error code fixes from SAMBA_4_0 branch. + * BUG 2801: Fix regression in the "delete veto files" option. + * Fix based on work from Shlomi Yaakobovich to catch loops + in corrupted tdb files. + * Allow someone with SeTakeOwnershipPrivilege to chown the + user of a file to herself. + * Fix minor compiler warnings in printing/printing.c. + * Merge new DOS error code from SAMBA_4. + * Fix issue when non-English characters in filenames and + directories. + * Fix bogus error message in smbstatus about unknown share modes. + + +o Andrew Bartlett <abartlet@samba.org> + * Support raw NTLMSSP authentication for Windows Vista + clients. + * Fix parallel NTLMSSP processing by removing global state. + * BUG 2684: Add per service hosts allow/deny checks for + printers when connecting via MS-RPC. + * BUG 2391: Fix segv caused by free a static pointer returned + from getpwnam(). + * Support kerberos authentication in smbd when using a keytab + and participating in a non-Microsoft Kerberos realm. + + +o Timur Bakeyev <timur@com.bat.ru> + * BUG 2546: Add support for FreeBSD EA API + * Fix detection of FreeBSD 7.x platforms in autoconf checks. + * BUG 2908: Fix string length logic error in msdfs code. + * BUG 2909: Fix typo that caused smbd to call the wrong + aio_fsync function. + + +o Ed Boraas <ed.boraas@concordia.ab.ca>. + * Added Linux per-socket TCP settings. + + +o Gerald (Jerry) Carter <jerry@samba.org> + * Added support for \svcctl pipe rpcs. + * Added 'net rpc service' subcommand for managing Win32 + services. + * Refactoring work on the rpc [un]marshalling layer and + structures. + * Verify privilege name in 'net rpc rights privileges' in + order to provide better error messages. + * Cleanup rpc structures in rpc_spoolss.h. + * Cleanups and fixes for the \winreg server code. + * Cleanup of rpc structures used by LsaEnumerateTrustedDomains. + * Fix bugs in client spoolss code after refactoring work. + * Fix Valgrind warnings of invalid reads in the spoolss + server code. + * Fixed a segv when enumerating services on a Samba host. + * Fix segv in the service control server code. + * Fix crashes in client spoolss calls caused by not checking + for a valid pointer from the caller. + * Fix regression in DeleteDriver() server routines. + * Fix dup_a_regval() when size is 0. + * Fix usrmgr.exe crash when viewing user properties at + debuglevel 10. + * Do not enumerate any privileges when 'enable privileges = no' + and log a message if a client tries. + * BUG 2872: Fix cut-n-paste error when checking pointer value + in ntlmssp_set_workstation(). + * Fix upgrade path from earlier nt*tdb files. + * Removed print handle object cache. + * BUG 2853: Don't strip out characters like '$' from printer + names when substituting for the lpq command. + * BUG 2557: Gracefully fail on unsupported SetPrinter() levels. + * Fix build issues on x86_64-linux systems caused by valgrind + headers. Thanks to Bent Vangli to the suggestions. + * Refactor spoolss client calls. + * Adding 'username map script'. + * Disable schannel on the LSA and SAMR pipes in winbindd client + code to deal with Windows 2003 SP1 and Windows 2000 SP4 SR1. + * Cleanup of winreg API functions. + * Add server stubs for RegSetKeySec() and RegGetKeySec(). + * Map generic bits to specific bits in reg_open_entry() + requests. + * Add write support to registry tdb and printing backends. + * Use tdb lookups rather than hard-coding certain registry + value names and data. + * BUG 2808: don't try to install man pages if they are not + present. + * Fix initialized variables reported by valgrind. + * Normalize key lookups in ntprinters.tdb. + * Mark "enumports command" as deprecated. + * Add missing class file for python share command example. + * Fix smbclient build issue on Solaris. + * BUG 2626: ensure that the calling_name is set to something + after parsing smb.conf (if not set via -n). + * Use "add machine script" when creating a user (ACB_NORMAL) + who has a name ending in '$' (e.g. usrmgr.exe creating + domain trust accounts). + * Add 'rid' synonym for idmap_rid IDMap module. + * Ensure that we set full access on the handle returned + from _samr_create_dom_{alias,group}() so that future + set_{alias,group}() commands succeed. + * Fix bug when looking for internal domains in winbindd + (caused winbindd_getgrgid() for local groups to fail). + * Fix query and set alias info calls (level 1 from the MMC + manage computer plug-in. + * Remove bogus log messages about unknown specversions. + * BUG 2680: copy files from an MS-DFS win2k root share + * BUG 2688: re-implement support for the -P (--port) option + * Support connecting to an 'msdfs proxy' share on a Samba + server. + * Strip the directory path from cups command line printing + defaults. + * Fix bug that prevented smbclient from creating directories + on non-dfs paths. + * Deprecate the "printer admin" parameter in favor of the + SePrintOperatorPrivilege. + * Add the capability to read and write WinNT regf registry + files. + * Implement access checks for RegOpenXXX() server calls. + * Extend registry client rpc calls. + * Add "net rpc registry" set of commands. + * Remove testprns tool. + * Ensure that printer ACLs use the specific bits as well as + the generic bits. Upgrade existing ntprinters.tdb SECDESC + records. + * Add server support for RegSaveKey() for dumping registry + trees to a regf file. + * Add "enable asu support" smb.conf parameter. + * Merge various small file changes from trunk. + * Remove "winbind enable local accounts" support. + * Remove "ldap filter" smb.conf option. + * Remove editreg utility (needs to be rewritten using regfio.c). + * Fix build failure when running 'make torture' without first + running 'make all' first. + * BUG 1261: Remove unusable libbiconv from iconv detection + in configure. + * Add new option for "map to guest". "Bad Uid" re-enables the + Samba 2.2 behavior of mapping authenticated users to the + guest account if there does not exist a valid Unix account + for the Windows domain user (based on patch from + aruna.prabakar@hp.com). + * Fix a couple of regressions after introduction of new winbindd. + * Fix smbpasswd user password change (still worked by bad error + messages) due to trying to strdup a NULL pointer. + * Implement default security descriptors for the + OpenService[Manager]() calls and check requested access mask + at connect time. + * Include access checks on handle mask for \svcctl operations + such as ControlService() and StartService(). + * Implement simulated start and stop service control for + the spooler service as a per smbd service state value. + * Add interface structure for controlling service via rc.init + scripts (incomplete). + * Convert move_driver_to_download_area() to use copy_file() + rather than moving the files. + * Add version number to registry.tdb file since it can be + modified now. + * Remove over-paranoid assert() call when checking spoolss + buffer pointers + * Fix error in EnumPrinterData() reported by valgrind. + * Fix broken help links in SWAT editor caused by new doc layout. + * Ensure that a domain structure in winbind is initialized prior + to assigning the methods for communicating to a DC. + * BUG 3000: Remove background updates of winbind cache and allow + child processes to immediately update and expired cache entry. + + +o David.Collier-Brown <David.Collier-Brown@sun.com> + * Added panic action script for Solaris. + + +o Jeremy Cooper <jeremy@ncircle.com> + * Added support for several new \winreg client rpcs. + + +o <core@road-star.jp> + * BUG 2792: Ensure the shadow copy module hooks seekdir, + telldir, rewinddir to match updated large directory code. + + +o Guenther Deschner <gd@samba.org> + * Close handles on group creation in rpcclient to better + support mass group account creation. + * Fix account policy key lookup for minimum and maximum + password lengths. + * Fix some compiler warnings and add missing exclude-block + in 'net rpc share migrate'. + * Allow use of a non-default smb.conf by rpcclient. + * Fix querydispinfo search semantics in rpcclient test code. + * Fix querydispinfo server semantics to allow to list more + then 511 users. + * Fix server crash bug in ancient OpenPrinter() call. + * Fix a crash bug when enumerating privileges via the LSA + calls. + * Fix crash in EnumPrinterKey() client calls caused by previous + refactoring work. + * Various compiler warning fixes. + * Fix segfault in the client AddPrinterEx-call of 'net + rpc printer'. + * Fix build issues when --with-aio-support is enabled. + * BUG 2502: Removed the deprecated 'min passwd length parameter'. + * Honour the CC environment variable in python build. + * Fix searches in pdb_ldap for inter-domain trust accounts. + * Don't expand the %L in %LOGONSERVER% from user attributes. + * Fix bug in 'net rpc vampire' that caused accounts to be created + with no assigned ACB flags. + * Fix enumeration of builtin-aliases. + * Avoid unset rids for builtin-aliases. + * Add 'recycle:touch_mtime = true' vfs option for the recycle bin. + * More "net rpc share migrate" fixes. + * Merge PADL's idmap_ad plugin (taken from the latest + xad_oss_plugins-tarball). + * Add support for "idmap backend = ad" when "security = ads". + * Add home directory and shell support from AD via "winbindd nss + support = sfu" and "security = ads". + * Provide better feedback when we fail share-manipulation + due to missing scripts. + * Correctly substitute "\" as default winbind separator in + generate_parm_table.py example share command script. + * Document pam_winbind.c to clarify the working status of + require-membership-of option. + * Added client-support for various lsa_query_trust_dom_info() + calls and a rpcclient-tester for some info-levels. + * Add "net rpc trustdom vampire" tool (in conjunction with + Lars Mueller). + * Add missing cli_srvsvc_net_share_set_info-function and + rpcclient-testers (in preparation for net share acl migration). + * Print trusted domain passwords returned via rpcclient in + display charset. + * Error code fixes when attempting to manipulating + non-existent shares. + * Cleanup "net share migrate" code. + * Allow to touch mtime in vfs-recycle with "recycle:touch_mtime + = true". + * Allow admins to uncheck the "User must change Password at + next Logon" checkbox in User manager (merge from trunk). + + +o Renaud Duhaut <rd@duhaut.com> + * BUG 1040: Add directory_mode parameter when creating recycle + directories. + + +o Steven Edwards <steven_ed4153@yahoo.com>. + * Use chsize() if we don't have ftruncate(). + + +o Rodrigo Fernandez-Vizarra <Rodrigo.Fernandez-Vizarra@Sun.COM> + * BUG 1780: Add kerberos (file based ticket cache) support + to smbspool. + + +o Steve French <sfrench@us.ibm.com> + * Update list of mount options for mount.cifs. + * Add more defines for POSIX extensions to match the newly + added client implementation. + * Add initial support for cifs umount utility. + * Fix cifs mounts to handle commas embedded in prompted + password, and password and credential files. + * Fix cifs mounts to handle domain name and user name in + username field (in form domain\user). + * Add missing error code mappings when a client unsuccessfully + tries to create a hard-link. + * Add support so umount.cifs can update mtab. + * Add two newer mount options to syntax help for mount.cifs. + * Add missing remount flag handling. + * Allow domain= to be specified in credentials file. + * Fix umount.cifs help, allow root to unmount someone else's + mount. + * Lock mtab when updating it during umount.cifs, also delete + only one matching entry at a time. + * Fix minor compiler warnings in the mount.cifs helper. + + +o Deryck Hodge <deryck@samba.org> + * BUG 2137: Encode quotes for display in HTML (original patch + from Jay Fenlason). + + +o Olaf Imig <Olaf.Imig@bifab.de> + * BUG 1998: Correct byte ordering bug when storing 16-bit RAP + print job ids. + * BUG 2653: Fix segv in rpcclient OpenPrinterEx() call. + + +o Björn Jacke <bj@sernet.de> + * Added ioctl constants reported by msbackup.exe and filemon.exe. + + +o Kevin Jamieson <bugzilla@kevinjamieson.com> + * BUG 2819: Fix typo when checking for ".." in smbd's statcache. + + +o John Janosik <jpjanosi@us.ibm.com> + * BUG 2077: Correctly fill in the correct server name when + processing trusted domain logins. + * BUG 2976: Mark logons for unknown domains with a + non-authoritative response. + + +o William Jojo <jojowil@hvcc.edu> + * AIX AIO fixes. + + +o Guenter Kukkukk <guenter.kukkukk@kukkukk.com> + * BUG 2541: Fix copying of file(s) from samba share to an OS/2 + local drive. + + +o Tom Lackemann <cessnatomny@yahoo.com> + * BUG 2242: Patch to ensure that we only set the security + descriptor on an NTtransact create if we created the file. + + +o Volker Lendecke <vl@samba.org> + * Port some of the non-critical changes from HEAD to 3_0. + The main one is the change in pdb_enum_alias_memberships + to match samr.idl a bit closer. + * Close handles on user creation in rpcclient to better + support mass user account creation. + * Implement client RAP calls for enumusers/enumgroups level 0. + * Implement a new caching API for enumerating the pdb elements. + * Convert the RAP user and group enumeration functions to the + utilized the pdb_search API. + * BUG 2438: Partial fix for 'net rpc trustdom establish' in + RestrictAnonymous environments. + * Internal passdb API changes for better search capabilities + (based on original work by Guenther Deschner). + * Fix various compiler warnings. + * Add chain length statistics to tdbtool. + * Fix set afs ACL calls on files and directories in the root of + a share. + * Refactoring work on internal open code + * Correctly initialize the version in a new set of nt*tdb files. + * Remove smb_run_idle_events() from main process loop in smbd + and instead rely upon the timeout processing to handle + dropping idle LDAP connections. + * Fix the bug where users show up as trusting domains. + * Fix an assertion failure in winbindd. + * Fix a memleak in vfs_afsacl. + * Various compiler warning fixes. + * Fix compile when --enable-socket-wrapper is defined. + * Fixes for top level acls in vfs_acl.c. + * Refactor passdb interface functions. + * Compile fixes when '#define PARANOID_MALLOC_CHECKER 1'. + * Correct 2 segv's in "net rpc printer migrate". + * Return correct group type from smbd for BUILTIN groups. + * Backport the talloc() layer from Samba 4. + * BUG 2701: Fix segv in ldap reconnection code. + * BUG 2705: Fix segv when connecting from usrmgr.exe. + * Use the SID in the user token for the %s expansion in 'afs + username map'. + * Memory leak fixes in passdb code. + * BUG 2720: Fixes for "net usersidlist". + * BUG 2725: Fix segv in "net ads user". + * Only allow schannel connections if a successful Auth2 + has been previously performed. + * Don't look at gencache.tdb for the trusted domains if + winbind is present. + * Rewrite winbindd using an asynchronous process model. + + +o Herb Lewis <herb@samba.org> + * Compiler warning cleanups. + * smbwrapper Makefile and compile time check cleanups. + * Adding robustness checks for tdbdump and tdbtool. + * Extend tdb command line parsing to arbitrary hex characters. + * Add LOCKING debug class. + * Fix more compiler warnings. + + +o Derrell Lipman <derrell@samba.org> + * add support for opening a file for write with O_APPEND + in libsmbclient. + * Added smbsh/smbwrapper for Linux to example/libsmbclient + tree. + * Fix smbc_stat() from returning incorrect timestamps IFF + it used cli_qpathinfo2() to retrieve the timestamps (Win2k) + and not if it used cli-getatr() to retrieve the timestamps + (Win98). + * Fix handful of compiler warnings. + * BUG 2498, 2484: smbc_getxattr() fixes. + * BUG 1133: Added provision for overloading some global + configuration options via the new, per-user file + ~/.smb/smb.conf.append. + * BUG 2543: Properly cache anonymous username when reverting + to anonymous login, in libsmbclient. + * BUG 2505: Fix large file support in libsmbclient. + * BUG 2564: Ensure correct errno when smbc_opendir() was called + with a file rather than a directory. + * Correct deprecated lvalue casts in testsuite/libsmbclient. + * BUG 2663. cli_getattrE() and cli_setattrE() were not + formatting or parsing the timestamp values correctly. + * Correctly detect AF_LOCAL support in configure. + * Fix problem updating file times on Windows 98 hosts using + libsmbclient. + * Fix compile breakage on Solaris by eliminating the use of + ctime_r() in libsmbclient DEBUG statement. + + +o Jason Mader <jason@ncac.gwu.edu> + * BUG 2483, 2468. 2469, 2478, 2093: Compiler warning fixes. + * Various compiler warning fixes about mistyped variables. + * BUG 2882, 2885, 2890, 2891, 2900: Various compiler warning fixes + and code cleanups. + * BUG 2527, 2538: Removed unused variables. + + +o Marcel <samba.10.maazl@spamgourmet.com> + * Fix regression in OS/2 trans2 open code. + + +o Jim McDonough <jmcd@us.ibm.com> + * Fixes for samr_lookup_rids() when using ldapsam:trusted=yes + (in conjunction with Volker). + * BUG 2953: Prevent the credentials chain on DC gets out + of sync with client when NT_STATUS_NO_USER is returned. + * Added subcommands to "net rpc vampire" (mostly done by Don + Watson <dwatson@us.ibm.com>) to allow data to be put into an + ldif file instead of actually writing to the passdb. + * BUG 2736: Add retries to workaround winbind race condition + with detecting idle clients. + * BUG 2953: Additional fixes for domain trusts. Also clears + up the "bad stub" error when attempting to logon to a Samba + domain with a bad username. + + +o Luke Mewburn <lukem@NetBSD.org> + * Compiler warning fixes. + + +o Kalim Moghul <kalim@samba.org> + * Removed unused printmode command from smbclient. + + +o Lars Müller <lmuelle@samba.org> + * Re-enable the VERSION_REVISION option in case of another + letter release. + * Fix spoolss python bindings after C++ compiler changes and + other python fixes. + * BUG 2659: Don't trump on memory in smbtorture. + * BUG 2060: Add -fPIC which is the case for all other Samba + shared libs. + * Fix argv parsing in "net rpc". + * Add support to create position independent executable (PIE) + code if the compiler supports it. + * BUG 2767: Add new options to testparm (--show-all-parameters, + --parameter-name, and --section-name). + * Fix net share migrate files to also migrate the ACLs of + the top level dir of a share. + + +o Marcel Muller <mueller@maazl.de> + * Patch to fix the OS/2 EA_FROM_LIST info level call. + * Mangled names fix for OS/2 clients. + * Ensure we correctly set the return packet size to include the + pad bytes in reply_readbmpx(). + * Fix for bug in SMBwriteBraw that incorrectly returned the + number of bytes written. + + +o Ricky Nance <ricky.nance@gmail.com> + * Implemented mklogon script generator for domain logon scripts. + + +o James Peach <jpeach@sgi.com> + * BUG 1843: Fix quotas (with no soft limits) on IRIX. + * BUG 2285: Patch for hires timestamps and efficient notify code. + * MS-DFS tidyup patches. + * Build fixes on IRIX. + * IRIX compiler warning fixes. + * BUG 2596: Fix become_root link issues and one IRIX stack + backtrace bug. + * Fix for null pointer ACL free. + * BUG 2314: Fix const compiler warnings in the quota code. + + +o Ed Plese <ed@edplese.com> + * Fix faulty logic which caused winbindd to return failure + when a user possessed no supplementary groups. + + +o Marcin Porwit <mporwit@centeris.com> + * Initial support for the \eventlog pipe. + * Fix a memleak in the eventlog code. + * Miscellaneous fixes for Samba's experimental event log support. + * Add ServiceQueryConfig2() and ServiceQueryStatusEx() server + calls. + + +o Tim Potter <tpot@samba.org> + * BUG 2940, 2943: Fixed various compiler warnings regarding + mismatched types and unused variables. + * BUG 1888, 1894: Fix warnings when time_t is an unsigned type. + * BUG 2733: Fix incorrect SHLIBEXT is set when running + configure script on HPUX IA. + * Remove unused autoconf #define's. + * BUG 2893: Fix inverted assignment in 'net rpc printer' code. + * Removed unused function declarations in tdb.h. + * BUG 2895: Don't wrap non-existent functions in the python + tdb bindings. + * BUG 2623, 2630: $< and $* are not valid in explicit rules + according to POSIX. + * BUG 2560: Fix compile error lurking where PATH_MAX is not + defined. + * BUG 2625: Remove configure check for FTRUNCATE_NEEDS_ROOT. + * BUG 2611: Add fflush(stdout) after displaying username prompt + in smbsh if username not specified on command line. + * BUG 2699: Fix for segfault in samba.winbind.auth_crap module + * BUG 2808: Update install swat message to reflect the fact + that swat/README no longer exists. + + +o Denis Sbragion <d.sbragion@infotecna.it> + * BUG 2196: Allow absolute path (system wide) recycle bin. + + +o Fernando Schapachnik <fernando@mecon.gov.ar> + * Add logon hours support for the Postgres backend. + + +o Richard Sharpe <rsharpe@samba.org> + * Fix bug in profiles tool caused by use of MAP_PRIVATE. + +o Joerg Sonnenberger <joerg@leaf.dragonflybsd.org> + * BUG 2362: Quota support fix for DragonFly. + * Fix dragonfly detection in configure. + + +o Simo Sorce <idra@samba.org> + * Allow Domain Admins to force user sessions to close via the + Windows Server Manager. + * Add support to 'net rpc right privileges <name>' to enumerate + accounts which possess a specific privilege. + * Fix memory issues issues in vfstest (reported by Rainer Link). + * Randomize reloading as to not overload cupsd. + + +o Smitty <smitty@plainjoe.org> + * Compile fixes for smbget when using --enable-developer. + * Include LUID values to match Windows privileges since + apparently this matters to printmig.exe + + +o John Terpstra <jht@samba.org> + * Solaris packaging fixes. + * Clean up usage help text in "net rpc user" + + +o Andrew Tridgell <tridge@samba.org> + * Merge socket wrapper library fixes from Samba 4. + + +o Brett Trotter <blt@iastate.edu> + * Fix definition of global_sid_* in vfs_acl.c. + + +o Mark Weaver <mark-clist@npsl.co.uk> + * Patch to fix sys_select so it can't drop signals if another + fd is ready to read. + + +o Jelmer Vernooij <jelmer@samba.org> + * Remove --with-manpage-languages configure option. + * Merge socket wrapper fixes for IRIX systems from the + Samba 4 branch. + * Add socket_wrapper library to 3.0. Can be enabled by passing + --enable-socket-wrapper to configure. + * Fix build of the various sql pdb backends after new talloc. + + +o Qiao Yang <qyang@stbernard.com> + * Use our own DC when getting the SID for a domain. + + + +Release Notes for older release follow: + + -------------------------------------------------- + =============================== + Release Notes for Samba 3.0.14a + Apr 14, 2005 + =============================== + +Common bugs fixed in 3.0.14a include: + + o Compatibility issues between Winbind and Windows 2003 SP1 + domain controllers (*2k3sp1*). + o MS-DFS errors with Windows XP SP2 clients. + o High CPU loads caused by infinite loops in the FindNext() + server code. + o Invalid SMB_ASSERT() which caused smbd to panic on ACL'd + files. + + +###################################################################### +Changes +####### + +Changes since 3.0.14 +-------------------- + +commits +------- +o Jeremy Allison <jra@samba.org> + * Fixed invalid SMB_ASSERT() triggered by checking access on + ACL'd files. + + +Changes since 3.0.13 +-------------------- + +smb.conf changes +---------------- + + Parameter Name Action + -------------- ------ + dos filetimes Enabled by default + + +commits +------- +o Jeremy Allison <jra@samba.org> + * Prevent nt_status code support when negotiating protocols + earlier than NT1. + * BUG 2533: Remove the UNICODE flags2 bit from SMBsearch calls + as this SMB is DOS codepage only. + * BUG 2585: Fix printf() issues in smbpasswd which caused + seg faults. + * BUG 2563: Fix infinite loop on non-existent file with + FindNext(). + * BUG 2581 (partial): Ensure if realloc fails on an internal + tdb we fail gracefully. + * Ensure that 'dos filetimes' works with ACLs. + * Set 'dos filetimes = yes' as the default for smb.conf. + + +o Gerald (Jerry) Carter <jerry@samba.org> + * Workaround autoconf issue to prevent debug symbols from + being included in the default build. + * Disable schannel on the \lsarpc pipe in order to successfully + enumerate users and groups (*2k3sp1*) + * Fix parsing error in rpc binds which broke NTLMSSP + authentication. And as a result broke CTL+ALT+DEL password + changes from a Windows 2003 SP1 member of a Samba domain + (*2k3sp1*). + * Revert change to FindFirst() server code that broke WinXP + SP2 clients from launching *.exe files from a dfs target + share. + * BUG 2588: Force smbclient to send netbios messages to port + 139 unless otherwise instructed (based on patch from Thomas + Bork). + + +o Volker Lendecke <vl@samba.org> + * Fix build on FreeBSD 4 where Winbind is not supported. + * Fix 'wbinfo --user-sids' when using domain local groups. + * Restrict domain local groups reported by 'wbinfo -r' to + the Samba server domain and not the users domain. + + +o Lin Li <linl@xandros.com> + * Ensure that winbind initializes internal trusted domain + structures when enumerating users and groups. + + +o Tim Potter <tpot@samba.org> + * BUG 2565: Fix crash bug and compiler warnings in strchr_m() + test. + * Fix compiler warnings. + + +o <psz@maths.usyd.edu.au> + * Fix for possible root squash NFS bugs. + + +o Simo Sorce <irda@samba.org> + * Debian packaging fixes. + + + -------------------------------------------------- + ============================== + Release Notes for Samba 3.0.13 + Mar 24, 2005 + ============================== + +Common bugs fixed in 3.0.13 include: + + o Infinite FindNext() loop from Windows 9x client when + copying or deleting files on a Samba file share using + explorer.exe. + o Numerous smbclient bugs when listing directories. + o Failures in smbclient when connecting to a Windows 9x + file server. + + +###################################################################### +Changes +####### + +Changes since 3.0.12 +-------------------- + +o Jeremy Allison <jra@samba.org> + * Fix typo bug in smbclient where flags overwrote info level + in the cli_list_new(). + * Fix old smbclient bug where ff_searchcount was being compared + to -1 resulting in processing a filename twice. + * Fix segv in smbclient caused by overwriting the last 2 bytes + in cli_list_new(). + * BUG 2530: Fix potential segv in smbclient when talking to a + Windows 9x file server. + * Fix last entry offset in cli_list_new() when using a + FindFirst/FindNext info level of 0x104. + * BUG 2501: Stop Win98 from looping doing FindNext on a + singleton directory. + * BUG 2521: Fix error in access checks when user group ACLs. + + +o Gerald (Jerry) Carter <jerry@samba.org> + * BUG 2497: Fix bug in rpcclient's deletedriverex when asking + to delete all versions of a driver. + * BUG 2517: use the realm from smb.conf for 'net ads info' when + 'disable netbios = yes'. + * BUG 2530: Ensure that smbclient correctly detects MS-DFS root + shares. + * Update RedHat packaging files to require cups support. Also + remove requirement for 'idmap {uid,gid}' settings in smb.conf + from winbindd init script. + * BUG 2516: fix compile issue on True64. + + + +o Guenther Deschner <gd@samba.org> + * Check for the correct cli-struct when copying files in 'net + rpc printer' routines. + + +o Herb Lewis <herb@samba.org> + * Fix incorrect test in 'net rpc user' when the user is not + a member of any groups. + + +o Jim McDonough <jmcd@us.ibm.com> + * Make sure that enum_group_members() searches the correct suffix. + + + -------------------------------------------------- + ============================== + Release Notes for Samba 3.0.12 + Mar 18, 2005 + ============================== + +Common bugs fixed in 3.0.12 include: + + o Winbind failures when using 'disable netbios = yes' + o Failure to establish a trust relationship via 'net rpc trust + establish' + o Various portability & compiler issues. + o Read only file deletion failure caused by new delete semantics + in Windows XP SP2 and the MS 04-044 security hotfix. + o Error messages from shared Excel workbooks residing on Samba + file shares. + o Missing files in the output of smbclient -c 'dir' when run + against Windows file servers. + o Inability for Print Administrators to pause/resume/purge print + queues. + +Additional features introduced in Samba 3.0.12: + + o Performance enhancements when serving directories containing + large number of files. + o MS-DFS support added to smbclient. + o More performance improvements when using Samba/OpenLDAP based + DC's via the 'ldapsam:trusted=yes' option. + o Support for the Novell NDS universal password when using the + ldapsam passdb backend. + o New 'net rpc trustdom {add,del}' functionality to eventually + replace 'smbpasswd {-a,-x} -i'. + o New libsmbclient functionality. + + + +======================= +Large Directory Support +======================= + +Samba 3.0.12pre1 introduces a specific mechanism for dealing +with file services that frequently contain a large number of files +per directory. Historically Samba's performance has suffered +in such environments due to the translation from case +insensitive lookups by Windows client to the case sensitive +storage mechanisms used by UNIX filesystems. + +Configuration details along with a short HOWTO can be found at: + +http://www.samba.org/samba/ftp/HOWTO/Samba-LargeDirectory-HOWTO + + +================================== +libsmbclient Binary Compatibility +================================== + +Please note that a change has been made to the _SMBCCTX structure +in source/include/libsmbclient.h. This change is not backwards +compatible with applications linked against the libsmbclient.so +library from Samba 3.0.11. However, it is compatible with all +other Samba 3.0.x releases. This means that it will be most likely +be necessary to recompile any applications linked against the +3.0.11 version of the library. + + +###################################################################### +Changes +####### + +smb.conf changes +---------------- + + Parameter Name Action + -------------- ------ + allocation roundup size New + log nt token command New + write cache Deprecated + + + +Changes since 3.0.11 +-------------------- + +commits +------- +o Jeremy Allison <jra@samba.org> + * BUG 2146: Return correct allocation sizes so as not to crash + the VC++ compiler. + * BUG 962: Ensure that parsing of service names in smb.conf is + multibyte safe. + * BUG 2201, 2227: Support new delete semantics used by MS04-044 + and XP SP2. + * BUG 1525: Correctly timestamps interpreted on 64-bit time_t + values (patch submitted by Jay Fenlason <fenlason@redhat.com>). + * Add special hooks when serving directories containing large + numbers of files. + * Ensure that WINS negative name query responses and WACK + packets use the correct RR type of 0xA instead of reflecting + back what the query RR type was (0x20). + * BUG 2310: Only do 16-bit normalization on small dfree request. + * BUG 2323: Correct authentication failure when using plaintext + passwords from Windows XP clients. + * BUG 2146: Add new smb.conf option 'allocation roundup size' to + work around issues building MS Visual Studio 6.0 project + on a Samba file share while restoring the pre-3.0.21pre1 + behavior by default. + * BUG 2399 (partial): Ensure we use SMB_VFS_STAT instead of + stat when checking for existence of a pathname. + * Check the sticky bit on the parent directory for supporting + the new WinXP SP2 file deletion semantics. + * Various oplock, share mode, and byte range locking fixes + found by Connectathon tests. + * BUG 2271: Fix resume key issues in trans2FindFirst() client + code (inspired by patch from Satwik Hebbar). + * BUG 2382, 2045: More pending modtime and delayed write fixes + for MS Excel (incorporates partial patches from + ke_miyata@itg.hitachi.co.jp). + * Debug log message cleanups. + * Add case insensitive search for a principal match on logon + verification in the system keytab (based on patch by + Michael Brown <mbrown@fensystems.co.uk>). + * Revert the previous SMB signing change from Nalin Dahyabhai + when using DES keys. + * Add missing RESOLVE_DFSPATH() calls for older SMB commands. + * Fix FindFirst() server code to deal with resume names of ".." + and "." (found by Jim McDonough). + * BUG 2451: Fix missing functions in full audit VFS module. + * Ensure that smbd logs failures reported by DISK_FREE() + (reported by Ying Li <ying.li2@hp.com>). + * Ensure that smbclient obeys the max protocol argument again. + * BUG 2335: Return correct error code for OS/2 clients (based on + negotiated protocol level). + * BUG 2460, 2464: remove dead code and unused variables + (reported by Jason Mader). + + +o Andrew Bartlett <abartlet@samba.org> + * Avoid length-limited intermediate copy of NT and LM responses + in NETLOGON client. + * Debug message cleanups in the NTLMSSP implementation. + + +o Manuel Baena <mbaena@lcc.uma.es> + * Print actual error message in smbmnt.c:fullpath(). + + +o Vince Brimhall <vbrimhall@novell.com> + * Add support for Novell NDS universal password. + * BUG 2424: Ensure that uidNumber and gidNumber use match + the RFC2307 schema. + * BUG 2453: Change the way pdb_nds.c handles users with no + Universal or Simple Password. + * NDS schema file corrections. + + +o Gerald (Jerry) Carter <jerry@samba.org> + * Add trans2 client call for checking dfs referrals + * Convert smbclient to use TRANS_QPATHINFO(SMB_QUERY_FILE_BASIC_INFO) + when checking directories on modern CIFS servers. + * Add MS-DFS support to smbclient. + * Code cleanup of adt_tree.[ch]. + * Add missing checks to allow root to manage user rights. + * Allow domain admins to manage rights assignments on domain members + servers. + * BUG 2333: Use the lpq command to pass in the correct printer name + for cups_queue_get(). CUPS backend now sets 'lpq command= %p' as + the default. + * BUG 1439: make sure to initialize pointer to prevent invalid + free()'s on exit. + * BUG 2329: fix to re-enable winbindd to locate DC's when 'disable + netbios = yes'. + * Add cups-devel to BuidlRequires directive in Fedora spec file. + * BUG 858: Fix order of popt args evaluation so we don't crash + when given no command line args. + * Remove dependency on bash for source/autogen.sh. + * Fix clitar.c compile issues caused by broken MIT 1.4 headers. + * Implement MS-DFS for recursive directory listings in smbclient. + * BUG 2394: Fix nmbd linking issue on IRIX. + * Only display the publish check box in the client's printer + properties dialog if we are a member of an AD domain. + * BUG 2363: allow 'in use' driver to be removed as long as + one 'Windows NT x86' driver remains. + * BUG 1881: Allow PRINT_SPOOL_PREFIX to be set in local.h for + porting purposes. + * Enforce better printer.tdb cache consistency when removing + jobs from a print queue via SMB. + * Ensure that pause/resume/purge print queue commands are run + with the appropriate level of privilege necessary to actually + work. + * BUG 2355: Use bsd style commands (lpq, lpr, etc...) for default + for 'printing = cups' installations that do not actually have + libcups. + * BUG 2425: Remove incorrect checks for Win98 DFS clients. + * BUG 2215: Rewrite questionable code that was causing gcc to + choke. + * Add server support for LsaLookupPrivValue(). + * Various small compile fixes and cleanup warnings. + * BUG 2456: Fix compile failure on non-gcc platforms due to + non-standard pragma. + + +o Kevin Dalley <kevin@kelphead.org> + * BUG 2398: Don't force smbclient to assume a dry run if the + target tarfile is /dev/null. + + +o Guenther Deschner <gd@samba.org> + * Fix crash bug in the client-spoolss enumdataex-call. + * Expand the valid-workstation-scheme by expanding names + beginning with a plus (+) as a unix group. + * Allow own netbios name to be set in smbclient's session setup. + * Better handling of LDAP over IPC connections that have expired + on the LDAP-Server. + * Fix pipe-mismatch for NETDFS in cli_dfs.c. + * Add examples/misc/adssearch.pl. + * BUG 2343: Build fixes. + * Support get_user_info_7 in SAMR server RPC. + * Fix server_role in the samr_query_dom_info calls. + * Add example perl script to check for multiple LDAP entries + after running 'net rpc vampire'. + * Add more output when listing printer forms via rpcclient. + * Debug log message cleanup. + + +o Steve French <sfrench@us.ibm.com> + * On failed mount (ENXIO) retry share name in uppercase (fix + mount to FastConnect AIX SMB server). + * Add missing FILE_ATTRIBUTE_XXX defines to smb.h. + * Ignore user_xattr mount parm (mount.cifs) so as not to confuse + it with a user name. + * Update for new CIFS POSIX info levels. + * Ignore users mount parm in mount.cifs. + +o SATOH Fumiyasu <fumiya@samba.gr.jp> + * BUG 1549: Don't truncate service names in smbstatus. + + +o William Jojo <jojowil@hvcc.edu> + * BUG 2445: Patch to avoid default ACLs on AIX. + + +o S Murthy Kambhampaty <smk_va@yahoo.com> + * Add idmap_rid module to Fedora and RedHat spec files. + + +o Volker Lendecke <vl@samba.org> + * BUG 2401: Flush internal getpwnam() cache after deleting a + user. + * BUG 1604: Make winbind work with more than 10 trusted domains. + * Cleanup various compiler warnings. + * Fix a memory leaks in privileges code and passdb backends. + * Fixes for samr_lookup_sids() client call. + * Optimize _samr_query_groupmem with LDAP backend for large + domains. + * Support SIDs as %s replacements in the afs username map + parameter. + * Add 'log nt token command' parameter. If set, %s is replaced + with the user sid, and %t takes all the group sids. + * Do not use the "Local Unix Group"-default description for + all kinds of group-mappings. + * Fix uninitialized variable in Linux nss_winbind library. + * Move 'net afskey' into a subcommand of its own, 'net afs key'. + * Implement 'net afs impersonate'. + + +o Herb Lewis <herb@samba.org> + * Fix build problem when HAVE_POSIX_ACL is not defined. + * BUG 2417: Add help lines for net rpc group addmem and + delmem commands. + + +o Derrell Lipman <derrell.lipman@unwireduniverse.com> + * Add support to libsmbclient for getting and setting DOS + attributes using EA functions. + * Fix libsmbclient's URL encoding/decoding. + * Replace browse listing URI queries with an internal options + structure (previous method violated the SMB URI syntax). + * Allow tree connects to be multiplexed over a single CIFS server + connection context. + * Ensure that cli_tdis() sets the cnum field to -1 so that callers + can determine a dead tree connection. + * Implement better solution for backwards binary compatibility + in libsmbclient while adding new fields to struct _SMBCCTX. + + +o Mark Loeser <halcy0n@gentoo.org> + * BUG 2443: Compile fix for gcc4. + + +o Jim McDonough <jmcd@us.ibm.com> + * BUG 2338: Fix coredump when OS/2 checks for long file name + support (with .+,;=[].) (thanks to Guenter Kukkukk). + + +o Jason Mader <jason@ncac.gwu.edu> + * Compiler warning fixes (BUGS BUG 2132, 2134, 2289, 2327, 2340, + 2341, 2342) + + +o Jim McDonough <jmcd@us.ibm.com> + * Fixes for server schannel implementation when 'restrict + anonymous = 1' is set in smb.conf. + * Fix bug in server side lookupsids reply that crashed lsass.exe + on Windows clients. + * Fix 'net rpc trustdom establish'. + * BUG 2062: Turn off broadcast for all 390 NICs. + * Fix 'net rpc trustdom add' to correctly add new domain trust + accounts. This will eventually replace 'smbpasswd -a -i'. + * Implement 'net rpc trustdom del', including client side of + samr_remove_sid_from_foreign_domain. + * Bring IBM Directory Server schema up to date with openldap + schema. + * Allow for better protection of sensitive attributes in IBM + Directory Server. + + +o Stefan Metzmacher <metze@samba.org> + * Fix memleaks in the nttrans code. + + +o Mike Nix <mnix@wanm.com.au> + * Add SMBsplopen and SMBsplclose client calls. + + +o Justin Ossevoort <justin@snt.utwente.nl> + * BUG 2316: Fix crashes in pdb_pgsql. + + +o James Peach <jpeach@sgi.com> + * Fixes in string handling code. + * Fix oplock2 test in client smbtorture. + + +o Tim Potter <tpot@samba.org> + * Fix up example pdb modules after prototype change for + setsampwent. + * BUG 2058: Fix for shared object creation in examples. + * BUG 2315: Fix segv in LSA privileges server code. + * Build fixes for python wrapper libraries. + + +o Richard Sharpe <rsharpe@samba.org> + * BUG 2044: Fix segv in profiles tool. + * Fix bogus error messages when enumerating user group + membership via 'net rpc'. + + +o Simo Sorce <idra@samba.org> + * Debian packaging fixes. + + +o John Terpstra <jht@samba.org> + * Add the capability to set account description using pdbedit. + + +o Doug VanLeuven <roamdad@sonic.net> + * Add more case/realm/name permutations to the kerberos keytab. + * AIX compile fixes. + + +o Jelmer Vernooij <jelmer@samba.org> + * BUG 892: Default unknown_6 field to 1260 in mySQL pdb module. + * BUG 1957: Implement minimal update of fields in mySQL pdb + module. + + +o Torsten Werner <torsten.werner@assyst-intl.com> + * BUG 2405: Define 'lpstat' printcap output on HPUX. + + +o Shlomi Yaakobovich" <Shlomi@exanet.com> + * Detect infinite loops when traversing tdbs. + + + -------------------------------------------------- + ============================== + Release Notes for Samba 3.0.11 + Feb 5, 2005 + ============================== + +Common bugs fixed in 3.0.11 include: + + o Crash in smbd when using CUPS printing. + o Parsing error of other SIDs included in the user_info_3 + structure returned from domain controllers. + o Inefficiencies when searching non-AD LDAP directories. + o Failure to expand variables in user domain attributes + in tdbsam and ldapsam. + o Memory leaks. + o Failure to retrieve certain attribute when migrating from + a Windows DC to a Samba DC via 'net rpc vampire'. + o Numerous printing bugs bugs including memory + bloating on large/busy print servers. + o Compatibility issues with Exchange 5.5 SP4. + o sendfile fixes. + +Additional features introduced in Samba 3.0.11: + + o Winbindd performance improvements. + o More 'net rpc vampire' functionality. + o Support for the Windows privilege model to assign rights + to specific SIDs. + o New administrative options to the 'net rpc' command. + + +============ +LDAP Changes +============ + +If "ldap user suffix" or "ldap machine suffix" are defined in +smb.conf, all user-accounts must reside below the user suffix, +and all machine and inter-domain trust-accounts must be located +below the machine suffix. Previous Samba releases would fall +back to searching the 'ldap suffix' in some cases. + + +=============== +Privilege Model +=============== + +Samba 3.0.11 supports the following assignable rights + +SeMachineAccountPrivilege Add machines to domain +SePrintOperatorPrivilege Manage printers +SeAddUsersPrivilege Add users and groups to the domain +SeRemoteShutdownPrivilege Force shutdown from a remote system +SeDiskOperatorPrivilege Manage disk shares + +These rights can be assigned to arbitrary users or groups +via the 'net rpc rights grant/revoke' command. More details +of Samba's privilege implementation can be found in the +Samba-HOWTO-Collection. + + +###################################################################### +Changes +####### + +Changes since 3.0.10 +-------------------- + +smb.conf changes +---------------- + + Parameter Name Action + -------------- ------ + afs token lifetime New + enable privileges New + ldap password sync Alias + min password length Deprecated + winbind enable local accounts Deprecated + + +commits +------- +o Jeremy Allison <jra@samba.org> + * Extend vfs to add seekdir/telldir/rewinddir. + * Fix dirent return. + * Fix bugs when handling secondary trans2 requests. + * Implementation of get posix acls in UNIX extensions. + * Added set posix acl functionality into the UNIX extensions code. + * Updated config.guess/config.sub . + * Fix error reply when 'follow symlinks = no'. + * BUG 1061, 2045: Only set mtime from pending_modtime if it's + not already zero. + * Fixes for LARGE_READX support. + * Fix the problem we get on Linux where sendfile fails, but we've + already sent the header using send(). + * BUG 2081: Ensure SE_DESC_DACL_PROTECTED is set if 'map acl + inherit = no'. + * BUG 2088: Ensure inherit permissions is only applied on a new + file, not an existing one. + * Don't go fishing for the krb5 authorization data unless we know + it's there. + * Fixes for libsmbclient to ensure that interrupted system calls + are restarted minus the already expired portion of the timeout + (based on work by Derrell Lipman). + * More Unicode string parsing fixes. + * Convert the winreg pipe to use WERROR returns. + * Make all LDAP timeouts consistent (input from Joe Meadows + <jameadows@webopolis.com>). + * BUG 2231: Remove double "\\" from client findfirst. + * BUG 2238: Fix memory leak in shadow copy vfs. + * Return correct DOS/NT error code on transact named pipe on + closed pipe handle. + * BUG 2211: Fix security descriptor parsing bug (based on work by + Mrinal Kalakrishnan <mail@mrinal.net>). + * BUG 2270: Fix memory leaks in cups printing backend support + (based on work by Lars Mueller). + * BUG 2255: Fix debug level in kerberos error messages. + * BUG 2110: Ensure we convert to ucs2 correctly after the + CAN-2004-0930 patch. + * Make strict locking an enum. Auto means use oplock optimization. + * Fix client & server to allow 127k READX calls. + * More *alloc fixes (includes additional fixes by Albert Chin. + * Catch sendfile errors correctly and return the correct values + we want the caller to return. + * BUG 2092: Prevent auto-anonymous logins via libsmbclient + for better use by desktop environments such as GNOME. + * Ensure we can't remove a level II oplock without having the + shared memory area locked. + + +o Timur Bakeyev <timur@com.bat.ru> + * BUG 2100: change the way we check for errors after a dlopen(). + * BUG 2263: Guard base64_encode_data_blob() against empty blobs. + + +o Andrew Bartlett <abartlet@samba.org> + * Clarify error message when 'lanman auth = no'. + * Remove the unnecessary UTF-8 conversion calls in the calls to + auth_winbind from smbd. + * Don't store the auth-user credentials with the cli_state* as + this can cause the schannel setup to fail when the auth-user + domain is not our primary domain. + + +o Grigory Batalov <bga@altlinux.org> + * Fix encoding while receiving of a message which was actually + sent using STR_ASCII. + + +o Daniel Beschorner <db@unit-netz.de> + * BUG 603: Correct access mask check for _samr_lookup_domain() + to work with Windows RAS server + + +o Jerome Borsboom <j.borsboom@erasmusmc.nl> + * Fix missing printer_tdb reference decrement. + + +o Gerald (Jerry) Carter <jerry@samba.org> + * BUG 2073: fall back to smb_name if current_user_info is not + available in lp_file_list_changed(). + * Fixes the spurious 'register_message_flags: tdb fetch failed' + errors. + * Don't run the background LPQ daemon when we are running in + interactive mode. + * prevent the background LPQ daemon from updating the print queue + cache just because multiple smbd processes sent a message that + it was out of date. + * consolidate printer searches to use find_service rather than + for(...) loops. + * BUG 2091: don't remove statically defined printers in + remove_stale_printers(). + * Fix logic error in add_a_form() that only compared N characters + instead of the entire form name. + * BUG 2107: fix memory bloating caused by large numbers of + print_queue_updates() requests sent via messages.tdb. + * Check the setprinter(3) based on the access permissions on + the handle and avoid the call to print_access_check(). + * Re-instantiate previous semantics for calling init_unistr2() + with a NULL source buffer. + * Support Windows privilege model for assigning rights + to specific SIDs. Based on work by Simo Sorce in the trunk + svn branch. This feature is controlled by the 'enable + privileges = [yes|no]' smb.conf(5) option. + * Add some smb.conf scripts for add/delete/change shares and + deleting cups printers. + * Expand variables in the profile path, logon home and logon script + values when using either tdbsam or ldapsam. + * Add Domain Admins (Full Control) to the default printer security + descriptor if we are a DC. + * RedHat and Fedora Packaging fixes for perl dependencies. + * Remove unused schema items from OpenLDAP schema file. + * Remove duplicate enumeration of "Windows x86" architecture + when listing printer drivers via rpcclient. + * Fail set_privileges() if 'enable privileges = no' to prevent + confused admins. + * Fix segfault in cups_queue_get(). + * Tighten restrictions on changing user passwords when + the connected user possesses the SeMachineAccountPrivilege. + * Ensure we set NETBIOSNAME.domainname for the long machine name + when publishing printers in AD (based on input from Rob Foehl). + * Mark 'winbind enable local accounts' as deprecated. + * Mark testprns tool as deprecated. + * Allow root to grant/revoke privilege assignments. + * Correct interaction between user rights and se_access_check() on + SAMR objects. + * BUG 2286: Fix typo OpenLDAP schema file for sambaConfig object + class. + * BUG 2262: Add support in configure.in for *freebsd6*. + * BUG 2266: Portability fixes for quota code on FreeBSD4. + * BUG 2264: Remove shutdown and abortshutdown commands from + rpcclient in favor of using the same functions in 'net'. + * BUG 2295: Prevent smbd from returning an empty server name + in certain lanman api calls. + * BUG 2290: Fix autogen.sh script in examples (based on original + patch from Lars Mueller). + * Fix bug enumerating domain trusts in security = ads. + * Fix segv in rpcclient's dsenumdomtrusts. + * Fix bug in expansion of %U and %G in included filenames. + * BUG 2291: Restrict creation of server trust and domain trust + accounts to members of the "Domain Admins" group. + +o Nadav Danieli <nadavd@exanet.com> + * Short circuit some is_locked() tests if we are oplocked. + + +o Guenther Deschner <gd@samba.org> + * Allow 'localhost' as a valid server name in the smbd for the + spoolss calls. + * Fix KRB5_SETPW-defines, no change in behavior (Thanks to Luke + Mewburn for the input). + * BUG 2059: Add additional checks needed after logic change to the + HAVE_WRFILE_KEYTAB detection test. + * BUG 1076: Fix interaction with Exchange 5.5. SP4 and a + Samba DC. Allow us to lookup at least our own SID. + * More fixes to have proper German in swat (Thanks to Reiner + Klaproth and Björn Jacke. + * BUG 404, 2076: Allow to set OWNER- and GROUP-entries while + setting security descriptors with smbcacls and using with + the -S or -M switch. + * Include the munged_dial, bad_password_count, logon_count, and + logon_hours attributes when running 'net rpc vampire'. + * Fix segfault in idmap_rid. + * When winbindd is operating in the multi-mapping mode of + idmap_rid, allow BUILTIN domain-mapping. + * Display infolevel 12 in query_dom_info in rpcclient. + * Fix bug in winbindd's lowercasing of usernames. + * Allow -v or -l for displaying verbose groupmap-listing + as well as "verbose". + * Backport Samba4 SAM_DELTA_DOMAIN_INFO for use in 'net rpc + vampire'. + * Close LDAP-Connection before retrying to open a new connection + in the retry-loop. + * Marking "min password length" as depreciated. + * Implement SAMR query_dom_info-call info-level 8 server- and + client-side, based on samba4-idl. + * Allow rpcclient to define a port to use when connecting + to a remote server. + * Allow Account Lockout with Lockout Duration "forever" (until + admin unlocks) to be set and displayed in User Manager. + * Allow to set acb_mask in rpcclient's enumdomusers. + * Add more generic rootDSE inspection function to check + for given controls or extensions and remember these on a + per server basis. + * Improve LDAP search efficiency by passing the acb_mask to + pdb_setsampwent(). + * Fixes for ldapsam_enum_group_memberships(). + * Add createdomgroup to rpcclient. + * Add "net rpc user RENAME"-command. + * Display sam_user_info_7 in rpcclient. + * Make multi-domain-mode in idmap_rid accessible from outside + (can be compiled with -DIDMAP_RID_SUPPORT_TRUSTED_DOMAINS). + * When vampiring account policy AP_LOCK_ACCOUNT_DURATION honor + "Lockout Duration: Forever". + * Fix configure.in tests using KRB5_CONFIG variable and krb5- + config utility. + * Require assignment of Administrator SID in the passdb + backend. Fall back to the default name of 'Administrator' if + the lookup fails rather than using the first name in the + default 'admin users' list. + * Enhance LDAP failure debug messages. + * BUG 2291: Call the 'add machine script' for server trust and + domain trust accounts as well as workstation accounts. + + +o Levente Farkas <lfarkas@lfarkas.org> + * BUG 2299: Better logrotate scripts for RedHat and Fedora + packages. + + +o Jay Fenlason <fenlason@redhat.com> + * Fix crash in 'net join' due to calling free on + static buffers. + * Several patches from RedHat's Fedora Core RPMS. + + +o Rob Foehl <rwf@loonybin.net>. + * Compiler warnings. + * Try modifying printer published attributes before adding it a + new entry in AD. + * Solaris packaging fixes. + * Don't force the cups printer-make-and-model tag as the comment + for autoloaded printers. + * Implement caching of names from printcap to support a true + 'printcap cache time'. + + +o Johann Hanne <jhml@gmx.net> + * BUG 2038: Only fail winbindd_getgroups() if all lookups fail. + + +o Jeff Hardy <hardyjm@potsdam.edu> + * Example script for 'add print command' when using CUPS. + + +o Deryck Hodge <deryck@samba.org> + * Add -P (--password-only-menu) to SWAT for displaying only the + password change page to non-root users. + + +o David Hu <david.hu@hp.com> + * Copy structure from print_queue_update() message rather than + referencing it. Fixes seg fault on HP-UX. + + +o Buck Huppmann <buckh@pobox.com> + * BUG 2186: Don't free uninitialized credentials. + * BUG 2189: Add the HOST/fqdn servicePrincipalName even when + dnsDomainName != realm. + + +o Björn Jacke <bjoern@j3e.de> + * BUG 2040: Ensure the locale is reset to C to get ASCII- + compatible toupper/lower functions. + + +o William Jojo <jojowil@hvcc.edu> + * Fix HPUX sendfile and add configure.in tests and code for + sendfile on AIX. + * AIX 5.3 compile fixes. + + +o Volker Lendecke <vl@samba.org> + * Optimize anonymous session setups by workstations in a + Samba domain. + * Reimplment the QueryUserAliases() server RPC reply. + * Re-add the getpwnam-cache for performance. + * Cache the result of a pdb_getsampwnam for later SID lookup + queries. + * Unify the means of localtaing a user's global groups on a + Samba DC. + * Fix bug when serving the 'Start Menu' in a roaming user profile.. + * Map more pre-defined NT security descriptors to AFS acls. + * Add timeout to AD search requests. + * If a connection to a DC is requested (in winbindd), open + connections simultaneously to all DCs found. + * Memleak fixes. + * Fix logic error in handling of 'printcap name' parameter. + * Prevent winbindd from SPAM'ing the log files with 'user root + does not exist'. + * Backport samr_DomInfo2 IDL specification from Samba 4. + * Implement smbstatus -n, don't lookup users and groups. + * Implement simple mapping that maps the space to another character + defined by afsacl:space. + * Add support for 'net idmap delete <idmap-file> <SID>'. + * Add new parameter 'afs token lifetime' tells the AFS client + when to throw away a token (patch from kllin@it.su.se). + * Initial work to allow support for multiple pipe opens on a + single cli_state*. + * Ensure that we still retrieve the netbios name of any DC + listed as a 'password server' to work around cases where the + DC was defined using an IP address or fqdn. + * Fix memleak in winbindd connection code. + * Fix cli_samr_queryuseraliases. + * Allow wbinfo --user-sids to expand expand domain local groups. + * Allow 'rpcclient -c enumtrust' to enumerate more than 10 trusts. + * Fix parsing of other_sids in net_user_info3. + * Correct bad failure logic when user was not a member of any + domain local groups. + + +o Jason Mader <jason@ncac.gwu.edu> + * BUG 2113, 2289: Remove dead code. + + +o Jim McDonough <jmcd@us.ibm.com> + * BUG 1952: Try INITSHUTDOWN pipe first, used by newer + clients. If it fails, fall back to WINREG. + * BUG 1770: Remove READ_ATTRIBUTES from GENERIC_EXECUTE. + * BUG 2198: Set password last change time when running 'net rpc + vampire'. + * Add "refuse machine password change" policy field. + + +o Luke Mewburn <lukem@NetBSD.org> + * BUG 2150: shmget() - Use POSIX definitions instead of non- + standard SHM_. + + +o Stefan Metzmacher <metze@samba.org> + * autogen.sh fixes. + + +o Buchan Milne <bgmilne@mandrake.org> + * Mandrake packaging fixes. + + +o Lars Mueller <lmuelle@samba.org> + * Fix build of libsmbclient on x86_64. + * BUG 2013: Fix testsuite build issues when libsmbclient.so + is installed in a non-default location. + * BUG 2050: Calculate max_fd for select correctly. + * Fix inverted logic heck for HAVE_WRFILE_KEYTAB in autoconf + script. + + +o Jason Mader <jason@ncac.gwu.edu> + * BUG 2069: Remove unused variables. + * BUG 2075: Remove dead code paths. + * BUG 2083: Fix compiler warnings caused by bad type casts. + + +o James Peach <jpeach@sgi.com> + * Fix rewinddir -> rewind_dir when using VFS macros. + + +o Gavrie Philipson <gavrie@disksites.com> + * BUG 1838: Remove stale printers imeeddiately when + processing a SIGHUP and during smb.conf reload. + + +o Tim Potter <tpot@samba.org> + * BUG 2080: Fix duplicate call to pdb_get_acct_desc(). + * BUG 2168: Fix cast in SMB_XMALLOC_ARRAY. + * Change the license for the winbindd external interface + more liberal. + * HP-UX compile fixes. + * Compile fixes after new setsampwent() API. + + +o Richard Renard <rrenard@idealx.com> + * Update Netscape DS 5.2 LDAP schema. + + +o Simo Sorce <idra@samba.org> + * Backport pdbedit changes from trunk. + * Allows the add/change share command to create the shared + directory directory on disk. + * Log a warning in testparm if a print command is defined for + a print service using 'printing = cups'. + +o Jelmer Vernooij <jelmer@samba.org> + * Bug fixes for pdb_{xml,pqsql,xml} + * Fixes for pdb_mysql. + + +o Andrew Tridgell <tridge@samba.org> + * Bring Samba3 into line with the Samba4 password change code. + + +o Shiro Yamada <shiro@miraclelinux.com> + * BUG 2190: Force SWAT to display parameters in unix charset and + not UTF-8. + + + -------------------------------------------------- + ============================== + Release Notes for Samba 3.0.10 + Dec 16, 2004 + ============================== + +Common bugs fixed in 3.0.10 include: + + o Fix for security issues described in CAN-2004-1154. + + +Changes since 3.0.9 +------------------- + +commits +------- + +o Jeremy Allison <jra@samba.org> + * Added checks surrounding all *alloc() calls to fix + CAN-2004-1154. + * Fix long standing memory size bug in bitmap_allocate(). + * Remove bogus error check in deferred open file serving + code. + + +o Thomas Bork <tombork@web.de> + * Fix autoconf script on platforms using a version of GNU ld + that does not include a date stamp in the output of --version. + + +o Luke Mewburn <lukem@NetBSD.org> + * Fix the swat install script to deal with the new image + destination directory used by the docs. + + + + -------------------------------------------------- + + ============================= + Release Notes for Samba 3.0.9 + Nov 15, 2004 + ============================= + +Common bugs fixed in 3.0.9 include: + + o Problem updating roaming user profiles. + o Crash in smbd when printing from a Windows 9x client. + o Unresolved symbols in libsmbclient which caused + applications such as KDE's konqueror to fail when + accessing smb:// URLs. + + +Changes since 3.0.8 +------------------- + + +commits +------- + +o Jeremy Allison <jra@samba.org> + * Correctly detect errno for no acl/ea support. + * BUG 2036: Fix seg fault in 'net ads join'. + + +o Gerald (Jerry) Carter <jerry@samba.org> + * Solaris packaging fixes. + * Fix seg fault in lanman printing code. + * BUG 2017: fix testparm reporting for the passwd program + string. + * Fix output of smbstatus to match the man page. + * BUG 2027: fix conflict with declaration MD5_CTX in system + headers. + * 2028: Avoid false error messages when copying a long + printer name to the device mode. + + +o Guenther Deschner <gd@samba.org> + * Allow deldriverex in rpcclient to delete drivers for a + specific architecture and a specific version. + * Fix a couple of rpcclient spoolss commands (setprinter, + setprintername, getdriver) w.r.t to printer-naming scheme. + Allow 'localhost' in the server string for certain server-side + spoolss functions. + * BUG 2015: Do not fail on setting file attributes with + acl support enabled. + + +o Michel Gravey <michel.gravey@optogone.com> + * Fix build when using gcc 3.0. + + +o Volker Lendecke <vl@samba.org> + * Fix tdb open logic when checking our local_pid after + the fork(). + + +o Jim McDonough <jmcd@us.ibm.com> + * BUG 1932: Fix crash in 'net getlocalsid' when run as + non-root user. + + +o Luke Mewburn <lukem@NetBSD.org> + BUG 1661: Fix KRB5_SETPW-defines + + +o Buchan Milne <bgmilne@mandrake.org> + * BUG 2023: Mandrake packaging fixes for building 3.0.9. + + +o Lars Mueller <lmuelle@samba.org> + * BUG 2013: Fix unresolved symbols in libsmbclient.so. + + +o Martin Zielinski <mz@seh.de> + * Add DeletePrinterDriverEx() functionality to rpcclient. + + + -------------------------------------------------- + + ============================= + Release Notes for Samba 3.0.8 + Nov 7, 2004 + ============================= + +Common bugs fixed in 3.0.8 include: + + o Compile fixes for HP-UX + o Fixes for the printer publishing code used when joined to + an AD domain. + o Incompatibilities with file system quotas. + o Several bugs in the spoolss printing code and print system + backends. + o Inconsistencies in the username map functionality when + configured on domain member servers. + o Various compile warnings and errors on various platforms. + o Fixes for kerberos interoperability with Windows 200x + domains when using DES keys. + o Fix for CAN-2004-0930 -- smbd remote DoS vulnerability. + o Fix for CAN-2004-0882 -- possible buffer overrun in smbd. + + +New features included in the 3.0.8 release are: + + o New migration functionality added the the net tool + for files/directories, printers, and shares. + o New experimental idmap backend for assigning uids/gids + directly based on the user/group RID when acting as a + member of single domain without any trusts. + o Additional printer migration support for XP/2003 platforms. + + +=========================== +Change in Winbindd Behavior +=========================== + +All usernames returned by winbindd are now converted to lower +case for better consistency. This means any winbind installation +relying on the winbind username will need to rename existing +directories and/or files based on the username (%u and %U) to lower +case (e.g. mv $name `echo $name | tr '[A-Z]' '[a-z]'`). This may +include mail spool files, home directories, valid user lines in +smb.conf, etc.... + + +====================== +Change in Username Map +====================== + +Previous Samba releases would only support reading the fully qualified +username (e.g. DOMAIN\user) from the username map when performing a +kerberos login from a client. However, when looking up a map +entry for a user authenticated by NTLM[SSP], only the login name would be +used for matches. This resulted in inconsistent behavior sometimes +even on the same server. + +Samba 3.0.8 obeys the following rules when applying the username +map functionality: + + * When performing local authentication, the username map is + applied to the login name before attempting to authenticate + the connection. + * When relying upon a external domain controller for validating + authentication requests, smbd will apply the username map + to the fully qualified username (i.e. DOMAIN\user) only + after the user has been successfully authenticated. + + +###################################################################### +Changes +####### + +Changes since 3.0.7 +------------------- + +smb.conf changes +---------------- + Parameter Name Action + -------------- ------ + force printername New + sendfile disabled by default + + +commits +------- + +o Jeremy Allison <jra@samba.org> + * Ensure extended security bit is on only if we negotiated + extended security. + * Simplify statcache to use an in-memory tdb. + * If you're selecting a hash algorithm for tdb, you need + to do it at open time. + * Removed old dir caching code - not being used now we + have the statcache anyway. + * Simplify the mangle hash code to use an in-memory tdb. + * Merge iconv changes from Samba 4 branch. + * Fix parsing of names ending in dot and a few other error + returns. + * BUG 1667: Smbpasswd file could be left locked on some + error exits. + * Fixes for smbclient tar functionality. + * BUG 1743: Fix logic bug the deferred open code. + * Don't try to set security descriptors on shares where + this has been turned off. + * Return correct error codes on old SEARCH call. + * Ensure we set errno = E2BIG when we overflow in the + fast-path character conversion code. + * Fix the roundup problem (returning 1mb roundup) for + non-Windows clients. + * Added 'stat' command to smbclient to exercise the + UNIX_FILE_BASIC info level. + * Fix bug where we could incorrectly set sparse attribute. + * Fix incorrect locks/unlocks in tdb_lockkeys()/tdb_unlockkeys() + (reported by Taj Khattra <taj.khattra@gmail.com>). + * Remove locked keys tdb code. + * BUG 1886: Prevent delete on close being set for readonly files + (and return the correct error code). + * Ensure we pass most of the new lock tests except for the cancel + lock which is yet to be added (merged from Samba 4 branch). + * BUG 1947: Fix incorrect use of getpwnam() etc. interface. + * BUG 1956: Ensure errno is saved and restored consistently on a + normal_close. + * BUG 1651: Adapted patch from Nalin Dahyabhai for ensuring + that all of the appropriate service principal names are set + upon joining an AD domain. + * Fix the correct use of resume name in the trans2 code. + * BUG 1717: Adapted patch from Nalin Dahyabhai to detect the + correct salt used when generated the DES key after joining an + AD domain. + * Enhanced krb5 detection routines in the autoconf scripts. + + +o Andrew Bartlett <abartlet@samba.org> + * Avoid changing the machine account password in the passdb + backend, when it has 'already been changed'. This occurs + in situations where the secure channel between the workstation + and the DC breaks down, such as occurred in the MS04-11 + security patch. + * Fix utility name in error message in ntlm_auth. + * Fix NTLMv2 for use with pam_winbind. + * Remove conversion to and from UTF8 on the winbind pipe. + * Allow 'require_membership_of' and 'require-membership-of'. + * Fix the error code for 'you didn't specify a domain' in + ntlm_auth. + * Use sys_getgroups() rather than scanning all groups + when generating SAMR replies. + + +o Igor Belyi <sambauser@katehok.ac93.org> + * Ensure pdb user is deleted first before deleting UNIX + user (LDAP backend needs this ordering). + + +o Cornelio Bondad Jr <Corny.Bondad@hp.com> + * Fix core dump in 'net rpc vampire'. + + +o Vince Brimhall <vbrimhall@novell.com> + * Make ldapsam_compat robust against NULL attributes. + + +o Gerald Carter <jerry@samba.org> + * Don't limit the number of groups returned by winbindd_getgroups() + by NGROUPS_MAX. + * BUG 1519: Match Windows 2000 behavior when opening a + printer using a servername in the form of an IP address or + DNS name. + * BUG 1907: remove extra slashes from the printer name in + getprinterdriverdir_1(). + * Fix standard_sub_snum() to use the current user's gid. + * Fix background queue update bug (based on Volker's initial work + in 3.1.0). + * Add 'force printername' service parameter for people that want + to enforce printername == sharename for spoolss printing. + * Ensure consistent usage of the username map. Use the fully + qualified DOMAIN\user format for 'security = domain|ads' and + apply after authentication has succeeded. + * Cosmetic fix for getent output -- lowercase the username only + and not the complete domain\username string. + * Packaging fixes for Solaris, Redhat, & Fedora. + + +o Sean Chandler <sean.chandler@verizon.net> + * Fix memlieak in cliconnect.c. + + +o Darren Chew <darrenc@vicscouts.asn.au> + * Solaris packaging fixes. + + +o Nalin Dahyabhai <nalin@redhat.com> + * SMB signing fix for 56-bit DES session keys. + + +o Guenther Deschner <gd@samba.org> + * add IA64 to the architecture table of printer-drivers. + * Add file/share/printer migration functionality to + the net command. + * Show correct help for net groupmap commands. + * Fix deadlock loop in winbind's required_membership_sid + verification. + * Bring the same level of "required_membership"-functionality + that ntlm_auth uses, to pam_winbindd as well. + * Prevent "net lookup kdc" from seg-faulting when + using our own implementation of krb5_lookup_kdc with + heimdal. + * Adding getprinter level 7 to rpcclient. + * Support migrating printers|shares|files from Server A + to Server B while running the net-command on client C. + * Fixed krb5_krbhost_get_addrinfo()-parameters and make + failure of this call non-critical (Thanks to Love @ Heimdal + for the explanation and patch). + * Fix typos in net's usage-output. + * Fix the paranoia-check to ensure the ldap-attribute and the + smb.conf-parameter for samba's "algorithmic rid base" in ldapsam + are identical. + * Fix several bugs in the _samr_query_useraliases() rpc reply. + * Check correct string length when verifying password-policies + and using extended characters (Thanks to Uwe Morgenroth from CC + Compunet and Volker). + * Make 'password history'-behavior in ldapsam more consistent. + * Adding "Windows x64" as architecture string and driverdir "x64" + for the 64bit AMD platform. + * BUG 1343: Readd WKGUID-binding to match the correct default- + locations of new User-, Group- and Machine-Accounts in Active + Directory (this got lost during the last trunk-merge). + * Fix printer-migration w.r.t. to new naming-convention for + policy-handles. + * Allow to migrate win2k3/xp-drivers as well. + * Add client-side support of triggering ads printer publishing + over msrpc setprinter calls inside the net-tool. + * Add the idmap_rid module (written in conjunction with + Sumit Bose <sbose@suse.de>). + * BUG 1661: Fix build with recent heimdal releases. + * Prevent idmap_rid from making unnecessary calls to domain + controllers for trusted domains. + + +o Arthur van Dongen <avdongen@xs4all.nl> + * Fix typos in pam_winbind log messages and SuSE + packaging files. + + +o Rob Foehl <rwf@loonybin.net> + * Typo fixes for log messages in printer publishing code. + * Fix memory leak in printer publishing code. + * Ensure print_backend_init() only gets called once. + * Have smbd check the published status of all printers + at startup. + * Cleanup up the XXX_a_printer() API for consistency. + * Refactored the printer publishing code and include better + error handling. + + +o Steve French <sfrench@us.ibm.com> + * Fix IP address override in mount.cifs mount helper and clean + up warning messages from the sparse tool and expand syntax help. + * Strip guest mount option off before sending to kernel mount + routine to avoid logging spurious message. + + +o Satoh Fumiyasu <fumiya@samba.gr.jp> + * BUG 1732: Limit share names returned by RAP based on windows + character width, not unix character width. + * BUG 1498: Ensure that acl entries are stored in the correct + order. + + +o Brett Funderburg <brett@deepfile.com> + * Pass create options parameter to nt_create_andx() function + from the python bindings. + * BUG 1864: Add sd->type field to security descriptor Python + representation. + * Return an error if a Netapp filer returns NT_STATUS_ACCESS_DENIED + when trying to return the security descriptor for a file. + * BUG 1884: Fixes for the Python bindings to use the value + of the desired_access filed passed into the lsa_open_policy() + routines. + + +o Michael Gravey <michel.gravey@optogone.com> + * BUG 1776: Fix warnings when building modules caused by + certain versions of GNU ld not using the the default + --allow-shlib-undefined flag. + + +o Chris Hertel <crh@samba.org> + * Fix logic bug in splay tree data structure when finding + a leaf node. + * Fix bug where an invalid MAC address would be printed by + a node status lookup from nmblookup. + + +o Uli Iske <iske@elkb.de> + * Update the DNS/eDirectory LDAP schema file. + + +o Björn Jacke <bjacke@sernet.de> + * BUG 1766: Unify charset-handling in Content-Type:-headers to + UTF-8. Reformat msgstr in msg-files to UTF-8. + * Do not use display charset for swat output. + * Convert the share names correctly from unix encoding to web + encoding and vice versa. + * Convert files from status page from unix charset to UTF-8. + + +o Guenter Kukkukk <guenter.kukkukk@kukkukk.com> + * BUG 1590: Fix for talking to OS/2 clients (max_mux ignored). + + +o Tom Lackemann <cessnatomny@yahoo.com> + * BUG 1954: Fix memory leak in posix acl code. + + +o Volker Lendecke <vl@samba.org> + * Robustnss fix for winbindd when sending multiple requests + at a high rate for a slow operation. + * Solve the problem of user sids ending up with gid's + and vice versa. + * Use sys_fork instead of fork for the dual daemon so that + we get the correct debug pid in the logfiles. + * Based on patch from jmcd, implement special lists for the LDAP + user attributes to delete. + * Fix creation of aliases via usrmgr. Winbind was too strict + checking the type of sids. + * Lowercase all usernames returned by winbind. + * BUG 1545, 1823: Only issue the ldap extended password change + operation if the ldap server supports it. Also ignore object + class violation errors from the extended operation. + * Optimization for 'idmap backend = ldap': When asking sid2id + for the wrong type, don't ask ldap when we have the opposite mapping + in the local tdb. + * Fix ldapsam_compat homeDrive. + * Add usersidlist and allowedusers subcommands to the net tool + in order to support scanning a file server's share and list + all users who have permission to connect there. + * Allow for multiple DC's to be named as #1c names in lmhosts. + * Memory leak fixes. + * Fix checks for the local pid of an smbd process after + reopening tdbs. + + +o Herb Lewis <herb@samba.org> + * Added tdbtool to be built by default. + + +o Love <lha@stacken.kth.se> + * BUG 1955: Inconsistent error return. + + +o Sorin Manolache <sorinm@gmail.com> + * Memory leak fix. + + +o Jim McDonough <jmcd@us.ibm.com> + * Allow 'net ads lookup' to rely on command line arguments + if contacting an ADS server fails; utilize cldap for lookups. + * Fixup formatting errors in TDB_LOG calls; add printf attribute + support to tdb log functions. + + +o Bill McGonigle <bill+samba@bfccomputing.com> + * BUG 1926: Type in debug message. + + +o Sean McGrath + * BUG 1822: Add -D_REENTRANT to CPPFLAGS and -lthread to LDFLAGS + for libsmbclient. + + +o Luke Mewburn <lukem@NetBSD.org> + * BUG 1782: Prevent testparm from displaying parameter synonyms. + + +o Stefan Metzmacher <metze@samba.org> + * Fix crash in smbcquotas and smbcacls caused by setup_logging(). + * Fix client quota support. + * Fix opening of system quota file. + + +o Lars Mueller <lmuelle@samba.org> + * Small fixes for autogen.sh to deal with version detection + of autoconf and autoheader; fixes for examples using + libtool to adhere to stricter syntax of newer version. + + +o Henrik Nordstrom <hno@squid-cache.org> + * Allow winbindd to return the correct number of groups + when the groups array must be enlarged. + + +o Narayana Pattipati <narayana.pattipati@wipro.com> + * Solaris autoconf detection fixes. + + +o Tim Potter <tpot@samba.org> + * BUG 1360: (correct fix) Use -Wl when passing flags to + the linker. + * HP-UX compile fixes (from JBravo on #samba-technical). + * BUG 1731: More HP-UX compiles fixes. + * BUG 1778: Include yp_prot.h before ypclnt.h as AIX 5.2 + spits the dummy otherwise. + * Fix bug in Python printerdata wrapper. + * BUG 1762: nss_winbind fixes on AIX 5.x (patch from + <bugzilla-samba@thewrittenword.com>). + * Fix parameter confusion in priming of name-to-sid cache + (Found by Qiao Yang). + * BUG 1888: Remove '..' from all pre-processor commands. + * BUG 1903: Change some #if DEBUG_PASSWORD's to #ifdef + DEBUG_PASSWORD. + + +o Matt Selsky <selsky@columbia.edu> + * BUG 350: use autoconf 2.57 feature for checking header file + preprocessing (fixes configure warnings on Solaris). + + +o Richard Renard <rrenard@idealx.com> + * Fix usermgr.exe and trust relationships. + + +o Paul Szabo <psz@maths.usyd.edu.au> + * Fix to make find_workgroup use the same + truncation as create_workgroup. + + +o Richard Sharpe <rsharpe@samba.org> + * Ensure cli_write() can support writes >= 65536 bytes. + + +o Simo Sorce <idra@samba.org> + * Added check password script code in examples/auth/crackcheck/ + * Fix memory corruption bug caused in freeing static memory. + + +o Andrew Tridgell <tridge@samba.org> + * Remove lp_use_mmap() from map_file() since the latter + is for read only and does not require coherence. + * Ensure that the uuid pack/unpack routines do not go past + the end of the structure. + * Converted Samba 3 tree to use the new utf-16 aware iconv + code. + * Changed iconv to recognise UCS-2LE and UTF-16LE as synonyms. + * Ensure configure only uses '=' instead of the bashism '=='. + * Reduces the number of tdb locking calls made on file IO. + + +o Jelmer Vernooij <jelmer@samba.org> + * Convert internal data to UTF-8 before calling libxml2. + * Complain if 'password chat' doesn't contain the %u variable + (based on a patch by Ronan Waide). + + +o Josef Zlomek + * BUG 1541: Fix recursive ls in smbclient. + + +o Igor Zhbanov <bsg@uniyar.ac.ru> + * BUG 1797: Prevent winbind and nmbd from ignoring the "-l" + option. + + -------------------------------------------------- + + ============================= + Release Notes for Samba 3.0.7 + Sept 13, 2004 + ============================= + +Common bugs fixed in 3.0.7 include: + + o Fixes for two Denial of Service vulnerabilities + (CVE ID# CAN-2004-0807 & CAN-2004-0808). + o Winbind failure to return user entries under certain + conditions. + o Syntax errors in the OpenLDAP schema file (samba.schema). + o Printing errors caused by not setting default values + for the various printing commands. + + +Changes since 3.0.6 +------------------- + +smb.conf changes +---------------- + + Parameter Name Action + -------------- ------ + winbind enable local accounts disabled by default + + +commits +------- +o Jeremy Allison <jra@samba.org> + * Fix parsing of names ending in dot and a few other error + returns. + * BUG 1674: Move the symlinks checks into reduce_name(). + * Fix memleak when checking the valid names smb.conf option. + * Fix memleak on error return path in the file open code. + * More paranoia checks in the hash2 mangling code. + * Fix syntax error in configure.in. + * Match Win2k3's behavior for pathname parsing error returns. + * Make nmbd more robust against bad netbios packets + (CAN-2004-0808). + * Add more checks for invalid ASN.1 packets for SPNEGO packets + (CAN-2004-0807). + + +o Andrew Bartlett <abartlet@samba.org> + * Janitor work in loadparm.c -- remove unused parameters. + + +o Gerald Carter <jerry@samba.org> + * BUG 1464: Ensure that printing commands are initialized even + if the 'printing' parameter is not explicitly set. + * Resolve name conflict on DEC OSF-5.1 (inspired by patch from + Adharsh Praveen <rprav@india.hp.com>) + * Work around parsing error in the print change notify code. + * remove duplicate declaration of getprintprocdir from + rpcclient. + * Only use sAMAccountName and not userPrincipalName when looking + up a username in AD since the breaks winbindd (lookup_name() + only works with the sAMAccountName). + * Fix bug with winbindd_getpwnam() caused by Microsoft DC's not + filling in the username in the user_info3. + * Fix logic bug in the check for creating a user's home directory + in register_vuid(); caused home directory to be mismatched to + the first share in smb.conf under certain conditions. + * BUG 1656: rename auto.a to auto.smb. + * Ensure that we assign our pid to print jobs (and not our + parent's pid); ensures that spooling jobs from dead smbds + are removed from the tdb. + * Disable 'winbind enable local accounts' by default. + * Adding some initial checks for DragonFly (same as + FreeBSD 4.1). + + +o Guenther Deschner <gd@samba.org> + * Use SMB_ASSERT() to track down NULL printer names in + the tdb open code. + * Revert fix for BUG 1474 to avoid unnecessary packaging + dependencies. + + +o Olaf Flebbe <o.flebbe@science-computing.de>. + * BUG 1627: fix for NIS compiles on HPUX 11.00, AIX 4.3 + and 5.1. + * BUG 1626: More compile fixes. + + +o Rob Foehl <rwf@loonybin.net> + * Don't clear the PRINT_ATTRIBUTE_PUBLISHED was getting reset + by attempts to sanitize the defined attributes. + + +o SATOH Fumiyasu <fumiya@miraclelinux.com> + * BUG 1546: Preserve errno in MB strupper_m/strlower_m. + + +o Helmut Heinreichsberger <helmut.heinreichsberger@chello.at>. + * BUG 1657: Remove used initialized variable, + * BUG 1658: Add a little bit of const. + + +o Volker Lendecke <vl@samba.org> + * If there's garbage in the pidfile, we should not panic + but assume that no one else is around. We can't find the + other guy anyway. + + +o Jim McDonough <jmcd@us.ibm.com> + * Fixup format string in the tdb error messages. + + +o Jonas Olsson <lexicon@lysator.liu.se> + * BUG 1416: Don't reuncture a users list to NGROUPS_MAX when + reporting the list in usrmgr.exe. + + +o Tim Potter <tpot@samba.org> + * Fix out-of-tree builds (problem with the script to generate + the svn version number). + * BUG 1360: Need to use -Wl when passing flags to the linker. + * BUG 1741: Define a struct nss_groupsbymem for HPUX 11 which + doesn't have one of its own. + +o Simo Sorce <idra@samba.org> + * Fixup compile issues on AIX caused by broken strlen() and + strdup(). + * Update debian packaging files. + + +o Dimitri van der Spek <dwspek@aboveit.nl> + * Use the correct counter when copying group rids from the + user_info3 struct in pam_winbind. + + +o Qiao Yang <qyang@stbernard.com> + * BUG 1622: Only cache the user + + + -------------------------------------------------- + + ============================= + Release Notes for Samba 3.0.6 + Aug 19, 2004 + ============================= + +Common bugs fixed in 3.0.6 include: + + o Schannel failure in winbindd. + o Numerous memory leaks. + o Incompatibilities between the 'write list' and 'force user' + smb.conf options. + o Premature optimization of the open_directory() internal + function that broke tools such as the ArcServe backup + agent, Macromedia HomeSite, and Robocopy. + o Corrupt workgroup names in nmbd's browse.dat. + o Sharing violation errors commonly seen when opening + when serving Microsoft Office documents from a Samba + file share. + o Browsing problems caused by an apostrophe (') in the + computer's description field. + o Problems creating special file types from UNIX CIFS + clients and enabling 'unix extensions'. + o Fix stalls in smbd caused by inaccessible LDAP servers. + o Remove various memory leaks. + o Fix issues in the password lockout feature. + +New features introduced in this release include: + + O Support symlinks created by CIFS clients which + can be followed on the server. + o Using a cups server other than localhost. + o Maintaining the service principal entry in the system + keytab for integration with other kerberized services. + Please refer to the 'use kerberos keytab' entry in + smb.conf(5). When using the heimdal kerberos libraries, + you must also specify the following in /etc/krb5.conf: + [libdefaults] + default_keytab_name = FILE:/etc/krb5.keytab + o Support for maintaining individual printer names + stored separately from the printer's sharename. + o Support for maintaining user password history. + o Support for honoring the logon times for user in a + Samba domain. + + +============================================ +unix extensions = yes (default) and symlinks +============================================ + +Beginning with Samba 3.0.6pre1 (formerly known as 3.0.5pre1), +clients supporting the UNIX extensions to the CIFS protocol +can create symlinks to absolute paths which will be **followed** +by the server. This functionality has been requested in order +to correctly support certain applications when the user's home +directory is mounted using some type of CIFS client (e.g. the +cifsvfs in the Linux 2.6 kernel). + +If this behavior is not acceptable for your production environment +you can set 'wide links = no' in the specific share declaration in +the server's smb.conf. Be aware that disabling wide link support +out of a share in Samba may impact the server's performance due +to the fact that smbd will now have to check each path additional +times before traversing it. + + +======================== +Password History Support +======================== + +The new password history feature allows smbd to check the new +password in password change requests against a list of the user's +previous passwords. The number of previous passwords to save can +be set using pdbedit (4 in this example): + + root# pdbedit -P "password history" -C 4 + +When using the ldapsam passdb backend, it is vital to secure the +following attributes from access by non-administrative users: + + * sambaNTPassword + * sambaLMPassword + * sambaPasswordHistory + +You should refer to your directory server's documentation on how +to implement this restriction. + + +Changes since 3.0.5 +------------------- + +smb.conf changes +---------------- + + Parameter Name Action + -------------- ------ + cups server New + defer sharing violations New + force unknown acl user New + ldap timeout New + printcap cache time New + use kerberos keytab New + +commits +------- +o Jeremy Allison <jra@samba.org> + * Correct path parsing bug that broke DeletePrinterDriverEx(). + * Fix bugs in check_path_syntax() caught by asserts. + * Internal change - rearrange internal global case setting + variables to a per connection basis. + * BUG 1345: Fix premature optimization in unix_convert(). + * Allow clients to truncate a locked file. + * BUG 1319: Always check to see if a user as write access + to a share, even when 'force user' is set. + * Fix specific case of open that doesn't cause oplock break, + or share mode check. + * Correct sid type is WKN_GROUP, not alias. Added some + more known types (inspired by patch from Jianliang Lu). + * Allow creation of absolute symlink paths via CIFS clients. + * Fix charset bug in when invoking send_mailslot(). + * When using widelinks = no, use realpath to canonicalize + the connection path on connection create for the user. + * Enhance stat open code. + * Fix unix extensions mknod code path. + * Allow unix domain socket creation via unix extensions. + * Auto disable the 'store dos attribute' parameter if the + underlying filesystem doesn't support EAs. + * Implement deferred open code to fix a bug with Excel files + on Samba shares. + * BUG 1427: Catch bad path errors at the right point. Ensure + all our pathname parsing is consistent. + * Fix SMB signing error introduced by the new deferred open + code. + * Change default setting for case sensitivity to "auto". (see + commit message -- r1154 -- for details). + * Add new remote client arch -- CIFSFS. + * Allow smbd to maintain the service principal entry in the + system keytab file (based on patch Dan Perry <dperry@pppl.gov>, + Guenther Deschner, et. al.). + * Fix longstanding memleak bug with logfile name. + * Fix incorrect type in printer publishing (struct uuid, + not UUID_FLAT). + * Heimdal compile fixes after introduction of the new ketyab + feature. + * Ensure we check attributes correctly on rename request. + * Ensure we defer a sharing violation on rename correctly. + * BUG 607: Ensure we remove DNS and DNSFAIL records immediately + on timeout. + * Fix bogus error message when using "mangling method = hash" + rather than hash2. + * Turn on sendfile by default for non-Win9x clients. + * Handle non-io opens that cause oplock breaks correctly. + * Ensure ldap replication sleep time is not more than 5 seconds. + * Add support for storing a user's password history. + LDAP portion of the code was based on a patch from + Jianliang Lu <j.lu@tiesse.com>. + * Correct memory leaks found in the password change code. + * Fix support for the mknod command with the Linux CIFS client. + * Remove support for passing the new password to smbpasswd + on the command line without using the -s option. + * Ensure home directory service number is correctly reused + (inspired by patches from Michael Collin Nielsen + <michael@hum.aau.dk>). + * Fix to stop printing accounts from resetting the bas + password and account lockout flags. + * If a account was locked out by an admin (and has a bad + password count of zero) leave it locked out until an admin + unlocks it (but log a message). + * Ensure we return the same ACL revision on the wire that + W2K3 does. + * BUG 1578: Hardcode replacement for invalid characters as '_' + (based on fix from Alexander E. Patrakov <patrakov@ums.usu.ru>). + * Fix hashed password history for LDAP backends. + * Enforce logon hours restrictions if confiogured (based on code + from Richard Renard <rrenard@idealx.com>). + * BUG 1606: Force smbd to disable sendfile with DOS clients + and ensure that the chained header is filled in for ...&X + commands. + * BUG 1602: Fix access to shares when all symlink support + has been disabled. + + + +o Tom Alsberg <alsbergt@cs.huji.ac.il> + * Allow pdbedit to export a single user from a passdb backend. + + +o Andrew Bartlett <abartlet@samba.org> + * Fix parsing bug in GetDomPwInfo(). + * Fix segfault in 'ntlm_auth --diagnostics'. + * Re-enable code to allow sid_to_gid() to perform a group + mapping lookup before checking with winbindd. + * Fix memory leak in the trans2 signing code. + * Allow more flexible GSS-SPENGO client and server operation + in ntlm_auth. + * Improve smbd's internal random number generation. + * Fix a few outstanding long password changes in smbd. + * Fix LANMAN2 session setup code. + + +o Eric Boehm <boehm@nortelnetworks.com> + BUG 703: Final touches on netgroup case lookups. + + +o Jerome Borsboom <j.borsboom@erasmusmc.nl> + * Ensure error status codes don't get overwritten in + lsa_lookup_sids() server code. + * Correct bug that caused smbd to overwrite certain error + codes when returning up the call stack. + * Ensure the correct sid type returned for builtin sids. + + +o Gerald Carter <jerry@samba.org> + * Fix a few bugs in the Fedora Packaging files. + * Fix for setting the called name to by our IP if the + called name was *SMBSERVER and *SMBSERV. Fixes issue + with connecting to printers via \\ip.ad.dr.ess\printer + UNC path. + * BUG 1315: fix for schannel client connections to servers + when we haven't specifically negotiated AUTH_PIPE_SEAL. + * Allow PrinterDriverData valuenames with embedded backslashes + (Fixes bug with one of the Konica Fiery drivers). + * Fixed string length miscalculation in netbios names that + resulted in corrupt workgroup names in browse.dat. + * When running smbd as a daemon, launch child smbd to update + the lpq cache listing in the background. + * Allow printers "Printers..." folder to be renamed to a string + other than the share name. + * Allow winbindd to use domain trust account passwords when + running on a Samba DC to establish an schannel to remote + domains. + * Fix bad merge and ensure that we always use tdb_open_log() + instead of tdb_open_ex() (the former call enforce the 'use + mmap' parameter). + * BUG 1221: revert old change that used single and double + quotes as delimeters in next_token(), and change + print_parameter() to print out parm values surrounded by + double quotes (instead of single quotes). + * Prevent home directories added during the SMBsesssetup&X from + being removed as unused services. + * Invalidate the print object cache for open printer handles when + smbd receives a message that an attribute on a given printer + has been changed. + * Cause the configure script to exit if --enable-cups[=yes] is + defined and the system does not have the cups devel files + installed. + * BUG 1297: Prevent map_username() from being called twice + during logon. + * Ensure that we use the userPrincipalName AD attribute + value for LDAP SASL binds. + * Ensure we remove the tdb entry when deleting a job that + is being spooled. + * BUG 1520: Work around bug in Windows XP SP2 RC2 where the + client sends a FindNextPrintChangeNotify() request without + previously sending a FindFirstPrintChangeNotify(). Return + the same error code as Windows 2000 SP4. + * BUG 1516: Manually declare ldap_open_with_timeout() to + workaround compiler errors on IRIX (or other systems without + LDAP headers). + * Merge security fixes for CAN-2004-0600, CAN-2004-0686 from + 3.0.5. + * Corrected syntax error in the OID for sambaUnixIdPool, + sambaSidEntry, & sambaIdmapEntry object classes. + * Tighten the cache consistency with the ntprinters.tdb entry + an the in memory cache associated with open printer handles. + * Make sure that register_messages_flags() doesn't overwrite + the originally registered flags. + + +o Fabien Chevalier <fabien.chevalier@supelec.fr> + * Debian BUG 252591: Ensure that the return value from the + number of available interfaces is initialized in case no + interfaces are actually available. + + +o Guenther Deschner <gd@sernet.de> + * Implement 'rpcclient setprintername'. + * Add local groups to the user's NT_TOKEN since they are + actually supported now. + * Heimdal compile fixes after introduction of the new keytab + feature. + * Correctly honor the info level parameter in 'rpcclient + enumprinters'. + * Reintroduce 'force unknown acl user' parameter. When getting a + security descriptor for a file, if the owner sid is not known, + the owner uid is set to the current uid. Same for group sid. + * Ensure that REG_SZ values in the SetPrinterData actually + get written in UNICODE strings rather than ASCII. + * Ensure that the last kerberos error return is not invalid. + * Display share ACL entries from rpcclient. + * Correct infinite loop in pam_winbind's verification of + group membership in the 'other sids' field in the user_info3 + struct. + + +o Fabian Franz <FabianFranz@gmx.de> + * Support specifying a port in the device URL passed to smbspool. + + +o Steve French <sfrench@us.ibm.com> + * Handle -S and user mount parms in mount.cifs. + * Fix user unmount of shares mount with suid mount.cifs. + * prevent infinite recusion in reopen_logs() when expanding + the smb.conf variable %I. + + +o Bjoern Jacke <bj@sernet.de> + * Install libsmbclient into $(LIBDIR), not into hard coded + ${prefix}/lib. This helps amd64 systems with /lib and /lib64 + and an explicit configure --libdir setting. + + +o <kawasa_r@itg.hitachi.co.jp> + * Correct more memory leaks and initialization bugs. + * Fix bug that prevented core dumps from being generated + even if you tried. + * Connect to the winbind pipe in non-blocking mode to + prevent processes from hanging. + * Memory leak fixes. + + +o Stephan Kulow <coolo@suse.de> + * Fix crash bug in libsmbclient. + + +o Volker Lendecke <vl@samba.org> + * Added vfs_full_audit module. + * Add vfs_afsacl.c which can display & set AFS acls via + the NT security editor. + * Fix crash bug caused by trying to Base64 encode a NULL string. + * Fix DOS error code bug in reply_chkpath(). + * Correct misunderstanding of the max_size field in + cli_samr_enum_als_groups; it is more like an account_control + field with individual bits what to retrieve. + * Implement 'net rpc group rename' -- rename domain groups. + * Implement the 'cups server' option. This makes it possible + to have virtual smbd's connect to different cups daemons. + * Paranoia fixes when adding local aliases to a user's NT_TOKEN. + * Fix sid_to_gid() calls in winbindd to prevent loops. + * Ensure that local_sid_to_gid() sets the type of the group on + return. + * Make sure that the clients are given back the IP address to + which they connected in the case of a multi-homed host. Only + affects strings the spoolss printing replies. + * Fix the bad password lockout. This has not worked as pdb_ldap.c + did not ask for the modifyTimestamp attribute, so it could + not find it. Try not to regress by not putting that attrib + in the main list but append it manually for the relevant searches. + * Fix two memleaks in login_cache.c. + * fixes memory bloat when unmarshalling strings. + * Fix compile errors using gcc 3.2 on SuSE 8.2. + * Fix the build for systems without kerberos headers. + * Allow winbindd to handle authentication requests only when + started without either an 'idmap uid' or 'idmap gid' range. + * Fix the build for systems without ldap headers. + * Fix interaction between share security descriptor and the + 'read only' smb.conf option. + * Fix bug that caused _samr_lookupsids() with more than 32 ( + MAX_REF_DOMAINS) SIDs to fail. + * Allow the 'idmap backend' parameter to accept a list of + LDAP servers for failover purposes. + * Revert code in smbd to remove a tdb when it has become + corrupted. + * Add paranoid checks when mapping SIDs to a uid/gid to + ensure that the type is correct. + * Initial work on getting client support for sending mailslot + datagrams. + * Add 'ldap timeout' parameter. + * Dont always uppercase 'afs username map'. + * Expand aliases for getusersids as well. + * Improved NT->AFS ACL mapping VFS module. + + +o Herb Lewis <herb@samba.org> + * Add the acls debug class. + * Fix logic bug in netbios name truncate routine. + * Fix smbd crash caused by smbtorture IOCTL test. + * Fix errno tromping before calling iconv to reset the + conversion state. + * need to leave empty dacl so we can remove last ACE. + + +o Jianliang Lu <Jianliang.Lu@getronics.com> + * Fix to stop smbd hanging on missing group member in + get_memberuids(). + * Make sure Samba returns the correct group types. + * Reset the bad password count password counts upon a successful login. + + +o Jason Mader <jason@ncac.gwu.edu> + * BUG 1385: Don't use non-consts in a structure initialization. + + +o Jim McDonough <jmcd@us.ibm.com> + * BUG 1279: SMBjobid fix for Samba print servers running on + Big-Endian platforms. + + +o Joe Meadows <jameadows@webopolis.com> + * Add optional timeout parameter to ldap open calls. + * Allow get_dc_list() to check the negative cache. + + +o Stefan Metzmacher <metze@samba.org> + * fix a configure logic bug for linux/XFS quotas when + using --with-sys-quotas. + * Use quota debug class in quota code. + * print out the SVN revision by configure, + + +o Buchan Milne <bgmilne@mandrake.org> + * Mandrake packaging fixes. + + +o Lars Mueller <lmuelle@samba.org> + * BUG 1279: Added 'printcap cache time' parameter. + * Fix afs related build issues on SuSE. + * Fix compiler warnings in the kerberos client code. + + +o James Peach <jpeach@sgi.com> + * More iconv detection fixes for IRIX. + * Compile fixed for systems that do not have C99/UNIX98 compliant + vsnprintf by default. + * Prevent smbd from attempting to use sendfile at all if it is + not supported by the server's OS. + * Allow SWAT to search for index.html when serving html files + in a directory. + + +o Dan Peterson + * Implement NFS quota support on FreeBSD. + + +o Tim Potter <tpot@samba.org> + * BUG 1360: Use -Bsymbolic when creating shared libraries to + avoid conflicts with identical symbols in the global namespace + when loading libnss_wins.so. + + +o Richard Renard <rrenard@idealx.com> + * Save the current password as it is being changed into the + password history list. + + +o Richard Sharpe <rsharpe@samba.org> + * Fix error return codes on some lock messages. + * BUG 1178: Make the libsmbclient routines callable + by C++ programs. + * BUG 1333: Make sure we return an error code when + things go wrong. + * BUG 1301: Return NT_STATUS_SHARING_VIOLATION when + share mode locking requests fail. + + +o Simo Sorce <idra@samba.org> + * Update Debian stable & unstable packaging. + * Tidy up parametric options in testparm output. + + +o Richard Sharpe <rsharpe@samba.org> + * Add sigchild handling to winbindd to restart the child + daemon if necessary. + + +o Tom Shaw <tomisfaraway@gmail.com> + * Use winbindd_fill_pwent() consistently. + + +o Nick Thompson <nickthompson@agere.com> + * Protect smbd against broken filesystems which return zero + blocksize. + + +o Andrew Tridgell <tridge@samba.org> + * Fixed bug in handling of timeout in socket connections. + + +o Nick Wellnhofer <wellnhofer@aevum.de> + * Prevent lp_interfaces() list from being corrupted. Fixes + bug where nmbd would lose the list of network interfaces + on the system and consequently shutdown. + + +o James Wilkinson <jwilk@alumni.cse.ucsc.edu> + * Fix ntlm_auth memory leaks. + + +o Jelmer Vernooij <jelmer@samba.org> + * Additional NT status to unix error mappings. + * BUG 478: Rename vsnprintf to smb_vsnprintf so we don't + get duplicate symbol errors. + * Return an error when the last command read from stdin + fails in smbclient. + * Prepare for better error checking in tar. + * BUG 1474: Fix build of --with-expsam stuff on Solaris. + + + -------------------------------------------------- + + ============================= + Release Notes for Samba 3.0.5 + July 20, 2004 + ============================= + +Please note that Samba 3.0.5 is identical to Samba 3.0.4 with +the exception of correcting the two security issues outlined +below. + +######################## SECURITY RELEASE ######################## + +Summary: Multiple Potential Buffer Overruns in Samba 3.0.x +CVE ID: CAN-2004-0600, CAN-2004-0686 + (http://cve.mitre.org/) + + +This is the latest stable release of Samba. This is the version +that production Samba servers should be running for all current +bug-fixes. + +It has been confirmed that versions of Samba 3 prior to v3.0.4 +are vulnerable to two potential buffer overruns. The individual +details are given below. + +============= +CAN-2004-0600 +============= + +Affected Versions: Samba 3.0.2 and later + +The internal routine used by the Samba Web Administration +Tool (SWAT v3.0.2 and later) to decode the base64 data +during HTTP basic authentication is subject to a buffer +overrun caused by an invalid base64 character. It is +recommended that all Samba v3.0.2 or later installations +running SWAT either (a) upgrade to v3.0.5, or (b) disable +the swat administration service as a temporary workaround. + +This same code is used internally to decode the +sambaMungedDial attribute value when using the ldapsam +passdb backend. While we do not believe that the base64 +decoding routines used by the ldapsam passdb backend can +be exploited, sites using an LDAP directory service with +Samba are strongly encouraged to verify that the DIT only +allows write access to sambaSamAccount attributes by a +sufficiently authorized user. + +The Samba Team would like to heartily thank Evgeny Demidov +for analyzing and reporting this bug. + +------------- +CAN-2004-0686 +------------- + +Affected Versions: Samba 3.0.0 and later + +A buffer overrun has been located in the code used to support +the 'mangling method = hash' smb.conf option. Please be aware +that the default setting for this parameter is 'mangling method += hash2' and therefore not vulnerable. + +Affected Samba 3 installations can avoid this possible security +bug by using the default hash2 mangling method. Server +installations requiring the hash mangling method are encouraged +to upgrade to Samba 3.0.5. + + +################################################################## + + -------------------------------------------------- + + ============================= + Release Notes for Samba 3.0.4 + May 8, 2004 + ============================= + +Common bugs fixed in Samba 3.0.4 include: + + o Password changing after applying the patch described in + the Microsoft KB828741 article to Windows clients. + o Crashes in smbd. + o Managing print jobs via Windows on Big-Endian servers. + o Several memory leaks in winbindd and smbd. + o Compile issues on AIX and *BSD. + +Changes since 3.0.3 +-------------------- + +commits +------- + +o Jeremy Allison <jra@samba.org> + * Fix path processing for DeletePrinterDriverEx(). + * BUG 1303: Fix for Microsoft hotfix MS04-011 password change + breakage. + + +o Andrew Bartlett <abartlet@samba.org> + * Fix alignment bug in GetDomPwInfo(). + + +o Alexander Bokovoy <ab@samba.org> + * Fix utime[s]() issues in smbwrapper on systems + that can boot both the 2.4 and 2.6 Linux kernels. + + +o Gerald Carter <jerry@samba.org> + * Fedora packaging fixes. + * BUG 1302: Fix seg fault by not trying to optimize a list of + invalid gids using the wrong array size. + * BUG 1309: fix seg fault caused by trying to strdup(NULL) + seen when 'security = share'. + * Fix problems when using IBM's compiler on AIX. + * Link Developer's Guide, Example Guide, and multi-page HOWTO + into SWAT's welcome page. + * BUG 1293: fix double free in printer publishing code. + + +o Wim Delvaux <wim.delvaux@adaptiveplanet.com> + * Fix for handling timeouts in socket connections. + + +o Michel Gravey <michel.gravey@optogone.com> + * BUG 483: patch from to fix password hash creation in SWAT. + + +o Volker Lendecke <vl@samba.org> + * Close the open NT pipes before the tdis. + * Fix AFS related build issues. + * Handle error conditions when base64 encoding a blob of 0 bytes. + + +o Herb Lewis <herb@samba.org> + * Added 'acls' debug class. + +o kawasa_r@itg.hitachi.co.jp + * Multiple variable initialization and memory leak fixes. + + +o Stephan Kulow <coolo@suse.de> + * Fix string length bug in libsmbclient that caused KDE's + Konqueror to crash. + * BUG 429: More libsmbclient fixes. + + +o Jim McDonough <jmcd@us.ibm.com> + * BUG 1007, 1279: Store the print job using a little-endian key. + + +o Eric Mertens + o Compile fix for OpenBSD (ENOTSUP not supported). + + +o Stefan Metzmacher <metze@samba.org> + * Correct bug in disks quota views from explorer. + + +o Tim Potter <tpot@samba.org> + BUG 1305: Correct debug output. + + +o Richard Sharpe <rsharpe@samba.org> + * Fix incorrect error code mapping. + + +o Jelmer Vernooij <jelmer@samba.org> + * Add additional NT_STATUS errorm mappings. + + + -------------------------------------------------- + + ============================= + Release Notes for Samba 3.0.3 + April 29, 2004 + ============================= + + +Common bugs fixed in Samba 3.0.3 include: + + o Crash bugs and change notify issues in Samba's printing code. + o Honoring secondary group membership on domain member servers. + o TDB scalability issue surrounding the TDB_CLEAR_IF_FIRST flag. + o Substitution errors for %[UuGg] in smb.conf. + o winbindd crashes when using ADS security mode. + o SMB signing errors. + o Delays in winbindd startup caused by unnecessary + connections to trusted domain controllers. + o Various small memory leaks. + o Winbindd failing due to expired Kerberos tickets. + +New features introduced in Samba 3.0.3 include: + + o Improved support for i18n character sets. + o Support for account lockout policy based on + bad password attempts. + o Improved support for long password changes (>14 + characters) and strong password enforcement. + o Support for Windows aliases (i.e. nested groups). + o Experimental support for storing DOS attribute on files + and folders in Extended Attributes. + o Support for local nested groups via winbindd. + o Specifying options to be passed directly to the CUPS libraries. + +Please be aware that the Samba source code repository was +migrated from CVS to Subversion on April 4, 2004. Details on +accessing the Samba source tree via anonymous svn can be found +at http://svn.samba.org/samba/subversion.html. + + +Changes since 3.0.2a +-------------------- +smb.conf changes +---------------- + + Parameter Name Action + -------------- ------ + cups options New + ea support New + only user Deprecated + store dos attributes New + unicode Removed + winbind nested groups New + + +commits +------- + +o Jeremy Allison <jra@samba.org> + * Ensure that Kerberos mutex is always properly unlocked. + * Removed Heimdal "in-memory keytab" support. + * Fixup the 'multiple-vuids' bugs in our server code. + * Correct return code from lsa_lookup_sids() on unmapped + sids (based on work by vl@samba.org). + * Fix the "too many fcntl locks" scalability problem + raised by tridge. + * Fixup correct (as per W2K3) returns for lookupsids + as well as lookupnames. + * Fixups for delete-on-close semantics as per Win2k3 behavior. + * Make SMB_FILE_ACCESS_INFORMATION call work correctly. + * Fix "unable to initialize" bug when smbd hasn't been run with + new system and a user is being added via pdbedit/smbpasswd. + * Added NTrename SMB (0xA5). + * Fixup correct timeout values for blocking lock timeouts. + * Fix various bugs reported by 'gentest'. + * More locking fixes in the case where we own the lock. + * Fix up regression in IS_NAME_VALID and renames. + * Don't set allocation size on directories. + * Return correct error code on fail if file exists and target + is a directory. + * Added client "hardlink" comment to test doing NT rename with + hard links. Added hardlink_internals() code - UNIX extensions + now use this as well. + * Use a common function to parse all pathnames from the wire for + much closer emulation of Win2k3 error return codes. + * Implement check_path_syntax() and rewrite string sub + functions for better multibyte support. + * Ensure msdfs referrals are multibyte safe. + * Allow msdfs symlink syntax to be more forgiving. + eg. sym_link -> msdfs://server/share/path/in/share + or sym_link -> msdfs:\\server\share\path\in\share. + * Cleanup multibyte netbios name support in nmbd ( based on patch + by MORIYAMA Masayuki <moriyama@miraclelinux.com>). + * Fix check_path_syntax() for multibyte encodings which have + no '\' as second byte (based on work by ab@samba.org. + * Fix the "dfs self-referrals as anonymous user" problem + (based on patch from vl@samba.org). + * BUG 1064: Ensure truncate attribute checking is done correctly + on "hidden" dot files. + * Fix bug in anonymous dfs self-referrals again. + * Fix get/set of EA's in client library + * Added support for OS/2 EA's in smbd server. + * Added 'ea support' parameter to smb.conf. + * Added 'store dos attributes' parameter to smb.conf. + * Fix wildcard identical rename. + * Fix reply_ctemp - make compatible with w2k3. + * Fix wildcard unlink. + * Fix wildcard src with wildcard dest renames. + * BUG 1139: Fix based on suggestion by jdev@panix.com. + swap lookups for user and group - group will do an + algorithmic lookup if it fails, user won't. + * Make EA's lookups case independent. + * Fix SETPATHINFO in 'unix extensions' support. + * Make 3.x pass the Samba 4.x RAW-SEARCH tests - except for + the UNIX info levels, and the short case preserve names. + + +o Timur Bakeyev <timur@com.bat.ru> + * BUG 1144: only set --with-fhs when the argument is 'yes' + * BUG 1152: Allow python modules to build despite libraries added + to LDFLAGS instead of LDPATH. + * BUG 1141: Fix nss*.so names on FreeBSD 5.x. + + +o Craig Barratt <cbarratt@users.sourceforge.net> + * BUG 389: Allow multiple exclude arguments with smbclient + tar -Xr options (better support for Amanda backup client). + + +o Andrew Bartlett <abartlet@samba.org> + * Include support for linking with cracklib for enforcing strong + password changes. + * Add support for >14 character password changes from Windows + clients. + * Add 'admin set password' capability to 'net rpc'. + * Allow 'net rpc samdump' to work with any joined domain + regardless of smb.conf settings. + * Use an allocated buffer for count_chars. + * Add sanity checks for changes in the domain SID in an + LDAP DIT. + * Implement python unit tests for Samba's multibyte string + support. + * Remove 'unicode' smb.conf option. + * BUG 1138: Fix support for 'optional' SMB signing and other + signing bugs. + * BUG 169: Fix NTLMv2-only behavior. + * Ensure 'net' honors the 'netbios name' in the smb.conf by + default. + * Support SMB signing on connections using only the LANMAN + password and generate the correct the 'session key' for these + connections. + * Implement --required-membership-of=, an ntlm_auth option + that restricts all authentication to members of this particular + group. + * Improve our fall back code for password changes. + * Only send the ntlm_auth 'ntlm-server-1' helper client a '.' + after the server had said something (such as an error). + * Add 'ntlm-server-1' helper protocol to ntlm_auth. + + +o Alexander Bokovoy <ab@samba.org> + * Fix incorrect size calculation of the directory name + in recycle.so. + * Fix problems with very long filenames in both smbd and smbclient + caused by truncating paths during character conversions. + * Fix smbfs problem with Tree Disconnect issued before smbfs + starts its work. + + +o Gerald Carter <jerry@samba.org> + * BUG 850: Fix 'make installmodules' bug on True64. + * BUG 66: mark 'only user' deprecated. + * Remove corrupt tdb and shutdown (only for printing tdbs, + connections, sessionid & locking). + * decrement smbd counter in connections.tdb in smb_panic(). + * RedHat specfile updates. + * Fix xattr.h build issue on Debian testing and SuSE 8.2. + * BUG 1147; bad pointer case in get_stored_queue_info() + causing seg fault. + * BUG 761: read the config file before initialized default + values for printing options; don't default to bsd printing + Linux. + * Allow the 'printing' parameter to be set on a per share basis. + * BUG 503: RedHat/Fedora packaging fixes regarding logrotate. + * BUG 848: don't create winbind local users/groups that already + exist in the tdb. + * BUG 1080: fix declaration of SMB_BIG_UINT (broke compile on + LynxOS/ppc). + * BUG 488: fix the 'show client in col 1' button and correctly + enumerate active connections. + * BUG 1007 (partial): Fix abort in smbd caused by byte ordering + problem when storing the updating pid for the lpq cache. + * BUG 1007 (partial): Fix print change notify bugs. + * BUG 1165, 1126: Fix bug with secondary groups (security = ads) + and winbind use default domain = yes. Also ensures that + * BUG 1151: Ensure that winbindd users are passed through + the username map. + * Fix client rpc binds for ASU derived servers (pc netlink, + etc...). + * BUG 417, 1128: Ensure that the current_user_info is set + consistently so that %[UuGg] is expanded correctly. + * BUG 1195: Fix crash in winbindd when the ADS server is + unavailable. + * BUG 1185: Set reconnect time to be the same as the + 'winbind cache time'. + * Ensure that we return the sec_desc in smb_io_printer_info_2. + * Change Samba printers Win32 attribute to PRINTER_ATTRIBUTE_LOCAL. + * BUG 1095: Honor the '-l' option in smbclient. + * BUG 1023: surround get_group_from_gid() with become_unbecome_root() + block. + * Ensure server schannel uses the auth level requested by the + client. + * Removed --with-cracklib option due to potential crash issue. + * Fix -lcrypto linking problem with wbinfo. + * BUG 761: allow printing parameter to set defaults on a per + share basis. + * Add 'cups options' parameter to allow raw printing without + changing /etc/cups/cupsd.conf. + * BUG 1081, 1183: Added remove_duplicate_gids() to smbd and + winbindd. + * BUG 1246: Fix typo in Fedora /etc/init.d/winbind. + * BUG 1288: resolve any machine netbios name (0x00) and not just + servers (0x20). + * BUG 1199: Fix potential symlink issue in + examples/printing/smbprint. + + +o Robert Dahlem <Robert.Dahlem@gmx.net> + * BUG 1048: Don't return short names when when 'mangled names = no' + + +o Guenther Deschner <gd@suse.com> + * Remove hard coded attribute name in the ads ranged retrieval + code. + * Add --with-libdir and --with-mandir to autoconf script. + + +o Bostjan Golob <golob@gimb.org> + * BUG 1046: Fix getpwent_list() so that the username is not + overwritten by other fields. + + +o Landon Fuller <landonf@opendarwin.org> + * BUG 1232: patch from landonf@opendarwin.org (Landon Fuller) + to fix user/group enumeration on systems whose libc does not + call setgrent() before trying to enumerate users (i.e. + FreeBSD 5.2). + + +o Steve French <sfrench@us.ibm.com> + * Update mount.cifs to version 1.1. + * Disable dev (MS_NODEV) on user mounts from cifs vfs. + * Fixes to minor security bug in the mount helper. + * Fix credential file mounting for cifs vfs. + * Fix free of incremented pointer in cifsvfs mount helper. + * Fix path canonicalization of the mount target path and help + text display in the cifs mount helper. + * Add missing guest mount option for mount.cifs. + + +o SATOH Fumiyasu <fumiya@miraclelinux.com> + * BUG 1055; formatting fixes for 'net share'. + * BUG 692: correct truncation of share names and workgroup + names in smbclient. + * BUG 1088: use strchr_m() for query_host (smbclient -L). + * Patch from to internally count characters correctly. + + +o Paul Green <paulg@samba.org> + * Update VOS _POSIX_C_SOURCE macro to 200112L. + * Fix bug in configure.ion by moving the first use of + AC_CHECK_HEADERS so it is always executed. + * Fix configure.in to only use $BLDSHARED to select whether to + build static or shared libraries. + + +o Pat Haywarrd <Pat.Hayward@propero.net> + * Make the session_users list dynamic (max of 128K). + + +o Cal Heldenbrand <calzplace@yahoo.com> + * Fix for for 'pam_smbpass migrate' functionality. + + +o Chris Hertel <crh@samba.org> + * fix enumeration of shares 12 characters in length via + smbclient. + + +o Ulrich Holeschak <ulrich@holeschak.de> + * BUG 932: fix local password change using pam_smbpass + + +o Krischan Jodies <kj@sernet.de> + * Implement 'net rpc group delete' + + +o John Klinger <john.klinger@lmco.com> + * Return NSS_SUCCESS once the max number of gids possible + has been found in initgroups() on Solaris. + * BUG 1182: Re-enable the -n 'no cache' option for winbindd. + + +o Volker Lendecke <vl@samba.org> + * Fix success message for net groupmap modify. + * Fix errors when enumerating members of groups in 'net rpc'. + * Match Windows behavior in samr_lookup_names() by returning + ALIAS(4) when you search in BUILTIN. + * Fix server SAMR code to be able to set alias info for + builtin as well. + * Fix duplication of logic when creating groups via smbd. + * Ensure that the HWM values are set correctly after running + 'net idmap'. + * Add 'net rpc group add'. + * Implement 'net groupmap set' and 'net groupmap cleanup'. + * Add 'net rpc group [add|del]mem' for domain groups and aliases. + * Fix wb_delgrpmem (wbinfo -o). + * As a DC we should not reply to lsalookupnames on DCNAME\\user. + * Fix sambaUserWorkstations on a Samba DC. + * Implement wbinfo -k: Have winbind generate an AFS token after + authenticating the user. + * Add expand_msdfs VFS module for providing referrals based on the + the client's IP address. + * Implement client side NETLOGON GetDCName function. + * Fix caching of name->sid lookups. + * Add support in winbindd for expanding nested local groups. + * Fix memleak in winbindd. + * Fix msdfs proxy. + * Don't list domain groups from BUILTIN. + * Fix memleak in policy handle utility functions. + * Decrease winbindd startup time by only contacting trusted + domains as necessary. + * Allow winbindd to ask the DC for its domain for a trusted + DC. + * Fix Netscape DS schema based on comments from + <thomas.mueller@christ-wasser.de>. + * Correct case where adding a domain user to a XP local group + did a lsalookupname on the user without domain prefix, and + failed. + * Fix segfault in winbindd caused by 'wbinfo -a'. + + +o Herb Lewis <herb@samba.org> + * Fix typo for tag in proto file. + * Add missing #ifdef HAVE_BICONV stuff. + * Truncate Samba's netbios name at the first '.' (not + right to left). + + +o Derrell Lipman <Derrell.Lipman@UnwiredUniverse.com> + * Bug fixes and enhancements to libsmbclient library. + + +o Jianliang Lu <j.lu@tiesse.com> + * Enforce the 'user must change password at next login' flag. + * Decode meaning of 'fields present' flags (improves support + for usrmgr.exe). + * NTLMv2 fixes. + * Don't force an upper case domain name in the ntlmssp code. + + +o L. Lucius <ib@digicron.com>. + * type fixes. + + +o Jim McDonough <jmcd@us.ibm.com> + * Add versioning support to tdbsam. + * Update the IBM Directory Server schema with the OpenLDAP + file. + * Various decoding fixes to improve usrmgr.exe support. + * Fix statfs redeclaration of statfs struct on ppc + * Implement support for password lockout of Samba domain + controllers and standalone servers. + * Get MungedDial attribute actually working with full TS + strings in it for pdb_ldap. + * BUG 1208 (partial): Improvements for working with expired krb5 + tickets in winbindd. + * Use timegm, or our already existing replacement instead of + timezone (spotted by Andrzej Tobola <san@iem.pw.edu.pl>). + * Remove modifyTimestamp from list of our attributes. + * Fix lsalookupnames to check for domain users as well as local + users. + * Merge struct uuid replacement for GUID from trunk. + * BUG 1208: Finish support for handling expired tickets in + winbindd (in conjunction with Guenther Deschner <gd@suse.de>). + + +o Stefan Metzmacher <metze@samba.org> + * Implement new VERSION schema based on subversion revision + numbers. + * Add shadow_copy vfs module. + * Fix segault in login_cache support. + + +o Heinrich Mislik <Heinrich.Mislik@univie.ac.at> + o BUG 979 -- Fix quota display on AIX. + + +o James Peach <jpeach@sgi.com> + * Correct check for printf() format when using the SGI MIPSPro + compiler. + * BUG 1038: support backtrace for 'panic action' on IRIX. + * BUG 768: Accept profileing arg to IRIX init script. + * BUG 748: Relax arg parsing to sambalp script (IRIX). + * BUG 758: Fix pdma build. + * Search IRIX ABI paths for libiconv. Based on initial fix from + Jason Mader. + + +o Kurt Pfeifle <kpfeifle@danka.de> + * Add example shell script for migrating drivers and printers + from a Windows print server to a Samba print server using + smbclient/rpcclient (examples/printing/VamireDriversFunctions). + + +o Tim Potter <tpot@samba.org> + * Fix logic bug in tdb non-blocking lock routines when + errno == EAGAIN. + * BUG 1025: Include sys/acl.h in check for broken nisplus + include files. + * BUG 1066: s/printf/d_printf/g in SWAT. + * BUG 1098: rename internal msleep() function to fix build + problems on AIX. + * BUG 1112: Fix for writable printerdata problem in python bindings. + * BUG 1154: Remove reference to <sys/mman.h> in tdbdump.c. + * BUG 1155: enclose use of fchown() with guards. + * Relicense tdb python module as LGPL. + + +o Richard Sharpe <rsharpe@samba.org> + * Add support to smbclient for multiple logins on the same + session (based on work by abartlet@samba.org). + * Correct blocking condition in smbd's use of accept() on IRIX. + * Add support for printing out the MAC address on nmblookup. + + +o Simo Sorce <idra@samba.org> + * Replace unknown_3 with fields_present in SAMR code. + * More length checks in strlcat(). + + +o Andrew Tridgell <tridge@samba.org> + * Rewrote the AIX UESS backend for winbindd. + * Fixed compilation with --enable-dmalloc. + * Change tdb license to LGPL (see source/tdb/tdb.c). + * Force winbindd to use schannel in clients connections to + DC's if possible. + + +o Jelmer Vernooij <jelmer@samba.org> + * Fix ETA Calculation when resuming downloads in smbget. + * Add -O (for writing downloaded files to standard out) + based on patch by Bas van Sisseren <bas@dnd.utwente.nl>. + * Fix syntax error in example mysql table + + +o TAKEDA yasuma <yasuma@miraclelinux.com> + * BUG 900: fix token processing in cmd_symlink, cmd_link, + cmd_chown, cmd_chmod smbclient functions. + + +o Shiro Yamada <shiro@miraclelinux.com> + * BUG 1129: install image files for SWAT. + + + -------------------------------------------------- + + ============================== + Release Notes for Samba 3.0.2a + February 13, 2004 + ============================== + +Samba 3.0.2a is a minor patch release for the 3.0.2 code base +to address, in particular, a problem when using pdbedit to +sanitize (--force-initialized-passwords) Samba's tdbsam +backend. This is the latest stable release of Samba. This +is the version that all production Samba servers should be +running for all current bug-fixes. + +******************* Attention! Achtung! Kree! ********************* + +Beginning with Samba 3.0.2, passwords for accounts with a last +change time (LCT-XXX in smbpasswd, sambaPwdLastSet attribute in +ldapsam, etc...) of zero (0) will be regarded as uninitialized +strings. This will cause authentication to fail for such +accounts. If you have valid passwords that meet this criteria, +you must update the last change time to a non-zero value. If you +do not, then 'pdbedit --force-initialized-passwords' will disable +these accounts and reset the password hashes to a string of X's. + +******************* Attention! Achtung! Kree! ********************* + + +Changes since 3.0.2 +------------------- + +commits +------- + +Please refer to the CVS log for the SAMBA_3_0 branch for complete +details. The list of changes per contributor are as follows: + + +o Jeremy Allison <jra@samba.org> + * Added paranoia checks in parsing code. + + +o Andrew Bartlett <abartlet@samba.org> + * Ensure that changes to uninitialized passwords in ldapsam + are written to the DIT. + + +o Gerald (Jerry) Carter <jerry@samba.org> + * Fixed iterator in tdbsam. + * Fix bug that disabled accounts with a valid NT password + hash, but no LanMan hash. + + +o Steve French <sfrench@us.ibm.com> + * Added missing nosetuid and noexec options. + + +o Bostjan Golob <golob@gimb.org> + * BUG 1046: Don't overwrite usernames of entries returned + by getpwent_list(). + + +o Sebastian Krahmer <krahmer@suse.de> + * Fixed potential crash bug in NTLMSSP parsing code. + + +o Tim Potter <tpot@samba.org> + * Fixed logic in tdb_brlock error checking. + + +o Urban Widmark <urban@teststation.com> + * Set nosuid,nodev flags in smbmnt by default. + + + -------------------------------------------------- + + ============================= + Release Notes for Samba 3.0.2 + February 9, 2004 + ============================= + +It has been confirmed that previous versions of Samba 3.0 are +susceptible to a password initialization bug that could grant an +attacker unauthorized access to a user account created by the +mksmbpasswd.sh shell script. + +The Common Vulnerabilities and Exposures project (cve.mitre.org) +has assigned the name CAN-2004-0082 to this issue. + +Samba administrators not wishing to upgrade to the current +version should download the 3.0.2 release, build the pdbedit +tool, and run + + root# pdbedit-3.0.2 --force-initialized-passwords + +This will disable all accounts not possessing a valid password +(e.g. the password field has been set a string of X's). + +Samba servers running 3.0.2 are not vulnerable to this bug +regardless of whether or not pdbedit has been used to sanitize +the passdb backend. + +Some of the more visible bugs in 3.0.1 addressed in the 3.0.2 +release include: + + o Joining a Samba domain from Pre-SP2 Windows 2000 clients. + o Logging onto a Samba domain from Windows XP clients. + o Problems with the %U and %u smb.conf variables in relation to + Windows 9x/ME clients. + o Kerberos failures due to an invalid in memory keytab detection + test. + o Updates to the ntlm_auth tool. + o Fixes for various SMB signing errors. + o Better separation of WINS and DNS queries for domain controllers. + o Issues with nss_winbind FreeBSD and Solaris. + o Several crash bugs in smbd and winbindd. + o Output formatting fixes for smbclient for better compatibility + with scripts based on the 2.2 version. + + +Changes since 3.0.1 +------------------- + +smb.conf changes +---------------- + + Parameter Name Action + -------------- ------ + ldap replication sleep New + read size removed (unused) + source environment removed (unused) + + +commits +------- + +Please refer to the CVS log for the SAMBA_3_0 branch for complete +details. The list of changes per contributor are as follows: + +o Jeremy Allison <jra@samba.org> + * Revert change that broke Exchange clear text samlogons. + * Fix gcc 3.4 warning in MS-DFS code. + * Tidy up of NTLMSSP code. + * Fixes for SMB signing errors + * BUG 815: Workaround NT4 bug to support plaintext + password logins and UNICODE. + * Fix SMB signing bug when copying large files. + * Correct error logic in mkdir_internals() (caused a panic + when combined with --enable-developer). + * BUG 830: Protect against crashes due to bad character + conversions. + + +o Petri Asikainen <paca@sci.fi> + * BUG 330, 387:Fix single valued attribute updates when + working with Novell NDS. + + +o Andrew Bartlett <abartlet@samba.org> + * Correctly handle per-pipe NTLMSSP inside a NULL session. + * Fix segfault in gencache + * Fix early free() of encrypted_session_key. + * Change DC lookup routines to more carefully separate + DNS names (realms) from NetBIOS domain names. + * Add new sid_to_dn() function for internal winbindd use. + * Refactor cli_ds_enum_domain_trusts(). + * BUG 707: Implement range retrieval of ADS attributes (based + on work from Volker <vl@samba.org> and Guenther Deschner + <gd@suse.com>). + * Automatically initialize the signing engine if a session key + is available. + * BUG 916: Do not perform a + -> ' ' substitution for squid URL + encoded strings, only form input in SWAT. + * Resets the NTLMSSP state for new negotiate packets. + * Add 2-byte alignments in net_samlogon() queries to parse + odd-length plain text passwords. + * Allow Windows groups with no members in winbindd. + * Allow normal authentication in the absence of a server + generated session key. + * More optimizations for looking up UNIX group lists. + * Clean up error codes and return values for pam_winbindd + and winbindd PAM interface. + * Fix string return values in ntlm_auth tool. + * Fix segfault when 'security = ads' but no realm is defined. + * BUG 722: Allow winbindd to map machine accounts to uids. + * More cleanups for winbindd's find_our_domain(). + * More clearly detect whether a domain controller is an NT4 + or mixed-mode AD DC (additional bug fixes by jerry & jmcd). + * Increase separation between DNS queries for hosts and queries + for AD domain controllers. + * Include additional NT_STATUS to PAM error mappings. + * Password initialization fixes. + + +o Justin Baugh <justin.baugh@request.com> + * BUG 948: Implement missing functions required for FreeBSD + nss_winbind support. + + +o Alexander Bokovoy <ab@samba.org> + * BUG 922: Make sure enable fast path for strlower_m() and + strupper_m(). + + +o Luca Bolcioni <Luca.Bolcioni@yacme.com> + * Fix crash when using 'security = server' and 'encrypt + passwords = no' by always initializing the session key. + + +o Dmitry Butskoj <buc@odusz.elektra.ru> + * Fix for special files being hidden from admins. + + +o Gerald (Jerry) Carter <jerry@samba.org> + * Fix bug in the lanman session key generation. Caused + "decode_pw: incorrect password length" error messages. + * Save the right case for the located user name in + fill_sam_account(). Fixes %U/%u expansion for win9x clients. + * BUG 897: Add well known rid for pre win2k compatible access + group. + * BUG 887: Correct typo in delete user script example. + * Use short lived TALLOC_CTX* for allocating printer objects + from the print handle cache. + * BUG 912: Fix check for HAVE_MEMORY_KEYTAB. + * Fix several warnings reported by the SUN Forte C compiler. + * Fully control DNS queries for AD DC's using 'name resolve order'. + * BUG 770: Send the SMBjobid for UNIX jobs back to the client. + * BUG 972: Fix segfault in cli_ds_getprimarydominfo(). + * BUG 936: fix bind credentials for schannel binds in smbd. + * BUG 446: Fix output of smbclient for better compatibility + with scripts based on the 2.2 version (including Amanda). + * BUG 891, 949: Fedora packaging fixes. + * Fix bug that caused rpcclient to incorrectly retrieve + the SID for a server (this causing all calls that required + this information to fail). + * BUG 977: Don't create a homes share for a user if a static + share already exists by the same name. + * Removed unused smb.conf options. + * Password initialization fixes. + * Set the disable flag for template accounts created by + mksmbpasswd.sh. + * Disable any account has no passwords and does not have the + ACB_PWNOTREQ bit set. + + +o Guenther Deschner <gd@suse.com> + * Install smbwrapper.so should be put into the $(libdir) + and not $(bindir). + * Add the capability to specify the new user password + for "net ads password" on the command line. + * Correctly detect AFS headers on SuSE. + + +o James Flemer <jflemer@uvm.edu> + * Fix AIX compile bug by linking HAVE_ATTR_LIST to + HAVE_SYS_ATTRIBUTES_H. + + +o Luke Howard <lukeh@PADL.COM> + * Fix segfault in session setup reply caused by a early free(). + + +o Stoian Ivanov <sdr@bultra.com> + * Implement grepable output for smbclient -L. + + +o LaMont Jones <lamont@debian.org> + * BUG 225328 (Debian): Correct false failure LFS test that resulted + in _GNU_SOURCE not being defined (thus resulting in strndup() + not being defined). + + +o Volker Lendecke <vl@samba.org> + * BUG 583: Ensure that user names always contain the short + version of the domain name. + * Fix our parsing of the LDAP uri. + * Don't show the 'afs username map' in the SWAT basic view. + * Fix SMB signing issues in relation to failed NTLMSSP logins. + * BUG 924: Fix return codes in smbtorture harness. + * Always lower-case usernames before handing it to AFS code. + * Add a German translation for SWAT. + * Fix a segfaults in winbindd. + * Fix the user's domain passed to register_vuid() from + reply_spnego_kerberos(). + * Add NSS example code in nss_winbind to convert UNIX + id's <-> Windows SIDs. + * Display more descriptive error messages for login via 'net'. + * Fix compiler warning in the net tool. + * Fix length bug when decoding base64 strings. + * Ensure we don't call getpwnam() inside a loop that is iterating + over users with getpwent(). This broke on glibc 2.3.2. + + +o Herb Lewis <herb@samba.org> + * Fix bit rot in psec. + + +o Jianliang Lu <j.lu@tiesse.com> + * Ensure we delete the group mapping before calling the delete + group script. + * Define well known RID for managing the "Power Users" group. + * BUG 381: check builtin (not local) group SID when updating + group membership. + * BUG 101: set the SV_TYPE_PRINTQ_SERVER flag in host announcement + packet. + + +o John Klinger <john.klinger@lmco.com> + * Implement initgroups() call in nss_winbind on Solaris. + + +o Jim McDonough <jmcd@us.ibm.com> + * Fix regression in net rpc join caused by recent changes + to cli_lsa_query_info_policy(). + * BUG 964: Fix crash bug in 'net rpc join' using a preexisting + machine account. + + +o MORIYAMA Masayuki <moriyama@miraclelinux.com> + * BUG 570: Ensure that configure honors the LDFLAGS variable. + + +o Stefan Metzmacher <metze@samba.org> + * Implement LDAP rebind sleep patch. + * Revert to 2.2 quota code because of so many broken quota files + out there. + * Fix XFS quotas: HAVE_XFS_QUOTA -> HAVE_XFS_QUOTAS + XFS_USER_QUOTA -> USRQUOTA + XFS_GROUP_QUOTA -> GRPQUOTA + * Fix disk_free calculation with group quotas. + * Add debug class 'quota' and a lot of DEBUG()'s + to the quota code. + * Fix sys_chown() when no chown() is present. + * Add SIGABRT to fault handling in order to catch got a + backtrace if an error occurs the OpenLDAP client libs. + + +o <ndb@theghet.to> + * Allow an existing LDAP machine account to be re-used when + joining an AD domain. + + +o James Peach <jpeach@sgi.com> + * BUG 889: Change smbd to use pread/pwrite on platforms that + support these calls. Can lead to a significant speed increase. + + +o Tim Potter <tpot@samba.org> + * BUG 905: Remove POBAD_CC to fix Solaris Forte compiles. + * BUG 924: Fix typo in RW2 torture test. + + +o Richard Sharpe <rsharpe@samba.org> + * Small fixes to torture.c to cleanup the error handling + and prevent crashes. + + +o J. Tournier <jerome.tournier@IDEALX.com> + * Small fixes for the smbldap-tool scripts. + + +o Andrew Tridgell <tridge@samba.org> + * Fix src len check in pull_usc2(). + + +o Jelmer Vernooij <jelmer@samba.org> + * Put functions for generating SQL queries in pdb_sql.c + * Add pgSQL backend (based on patch by Hamish Friedlander) + * BUG 908: Fix -s option to smbcontrol. + * Add smbget utility - a wget-clone for the SMB/CIFS protocol. + * Fix for libnss_wins on IRIX platforms. + * Fix swatdir for --with-fhs. + + + -------------------------------------------------- + + ============================= + Release Notes for Samba 3.0.1 + December 15, 2003 + ============================= + +Some of the more common bugs in 3.0.0 addressed in the release +include: + + o Substitution problems with smb.conf variables. + o Errors in return codes which caused some applications + to fail to open files. + o General Protection Faults on Windows 2000/XP clients + using Samba point-n-print features. + o Several miscellaneous crash bugs. + o Access problems when enumerating group mappings are + stored in an LDAP Directory. + o Several common SWAT bugs when writing changes to + smb.conf. + o Internal inconsistencies when 'winbind use default + domain = yes' + + + +Changes since 3.0.0 +---------------------- + + Parameter Name Action + -------------- ------ + hide local users Removed + mangled map Deprecated + mangled stack Removed + passwd chat timeout New + + +commits +------- + +o Change the interface for init_unistr2 to not take a length + but a flags field. We were assuming that + 2*strlen(mb_string) == length of ucs2-le string. (bug 480). +o Allow d_printf() to handle strings with escaped quotation + marks since the msg file includes the escape character (bug 489). +o Fix bad html table row termination in SWAT wizard code (bug 413). +o Fix to parse the level-2 strings. +o Fix for "valid users = %S" in [homes]. Fix read/write + list as well. +o Change AC_CHECK_LIB_EXT to prepend libraries instead of append. + This is the same way AC_CHECK_LIB works (bug 508). +o Testparm output fixes for clarity. +o Fix broken wins hook functionality -- i18n bug (bug 528). +o Take care of condition where DOS and NT error codes must differ. +o Default to using only built-in charsets when a working iconv + implementation cannot be located. +o Wrap internals of sys_setgroups() so the sys_XX() call can + be done unconditionally (bug 550). +o Remove duplicate smbspool link on SWAT's front page (bug 541). +o Save and restore CFLAGS before/after AC_PROG_CC. Ensures that + --enable-debug=[yes|no] works correctly. +o Allow ^C to interrupt smbpasswd if using our getpass + (e.g. smbpasswd command). +o Support signing only on RPC's (bug 167). +o Correct bug that prevented Excel 2000 clients from opening + files marked as read-only. +o Portability fix bugs 546 - 549). +o Explicitly initialize the value of AR for vendor makes that don't + do this (e.g. HPUX 11). (bug 552). +o More i18n fixes for SWAT (bug 413). +o Change the cwd before the postexec script to ensure that a + umount will succeed. +o Correct double free that caused winbindd to crash when a DC + is rebooted (bug 437). +o Fix incorrect mode sum (bug 562). +o Canonicalize SMB_INFO_ALLOCATION in the same was as + SMB_FS_FULL_SIZE_INFORMATION (bug 564). +o Add script to generate *msg files. +o Add Dutch SWAT translation file. +o Make sure to call get_user_groups() with the full winbindd + name for a user if he/she has one (bug 406). +o Fix up error code returns from Samba4 tester. Ensure invalid + paths are validated the same way. +o Allow Samba3 to pass the Samba4 RAW-READ tests. +o Refuse to configure if --with-expsam=$BACKEND was used but no + libraries were found for $BACKEND. +o Move sysquotas autoconf tests to a separate file. +o Match W2K w.r.t. writelock and writeclose. Samba4 torture + tester +o Make sure that the files that contain the static_init_$subsystem; + macro get recompiled after configure by removing the object + files. +o Ensure canceling a blocking lock returns the correct error + message. +o Match Samba 2.2 behavior; make ACB_NORMAL the default ACB value. +o Updated Japanese welcome file in SWAT. +o Fix to nt-time <-> unix-time functions reversible. +o Ensure that winbindd uses the the escaped DN when querying + an AD ldap server. +o Fix portability issues when compiling (bug 505, 550) +o Compile fix for tdbbackup when Samba needs to override + non-C99 compliant implementations of snprintf(). +o Use @PICSUFFIX@ instead of .po in Makefile.in (bug 574). +o Make sure we break out of samsync loop on error. +o Ensure error code path doesn't free unmalloc()'d memory + (bug 628). +o Add configure test for krb5_keytab_entry keyblock vs key + member (bug 636). +o Fixed spinlocks. +o Modified testparm so that all output so all debug output goes + to stderr, and all file processing goes to stdout. +o Fix error return code for BUFFER_TOO_SMALL in smbcacls + and smbcquotas. +o Fix "NULL dest in safe_strcpy()" log message by ensuring that + we have a devmode before copying a string to the devicename. +o Support mapping REALM.COM\user to a local user account (without + running winbindd) for compatibility with 2.2.x release. +o Ensure we don't use mmap() on blacklisted systems. +o fixed a number of bugs and memory leaks in the AIX + winbindd shim +o Call initgroups() in SWAT before becomming the user so that + secondary group permissions can be used when writing to + smb.conf. +o Fix signing problems when reverse connecting back to a + client for printer notify +o Fix signing problems caused by a miss-sequence bug. +o Missing map in errormap for ERROR_MORE_DATA -> ERRDOS, ERRmoredata. + Fixes NEXUS tools running on Win9x clients (bug 64). +o Don't leave the domain field uninitialized in cli_lsa.c if some + SID could not be mapped. +o Fix segfault in mount.cifs helper when there is no options + specified during mount. +o Change the \n after the password prompt to go to tty instead + of stdout (bug 668). +o Stop net -P from prompting for machine account password (bug 451). +o Change in behavior to Not only change the effective uid but also + the real uid when becoming unprivileged. +o Cope with Exchange 5.5 cleartext pop password auth. +o New files for support of initshutdown pipe. Win2k doesn't + respond properly to all requests on the winreg pipe, so we need + to handle this new pipe (bug 534). +o Added more va_copy() checks in configure.in. +o Include fixes for libsmbclient build problems. +o Missing UNIX -> DOS codepage conversion in lanman.c. +o Allow DFMS-S filenames can now have arbitrary case (bug 667). +o Parameterize the listen backlog in smbd and make it larger by + default. A backlog of 5 is way too small these days. +o Check for an invalid fid before dereferencing the fsp pointer + (bug 696). +o Remove invalid memory frees and return codes in pdb_ldap.c. +o Prompt for password when invoking --set-auth-user and no + password is given. +o Bind the nmbd sending socket to the 'socket address'. +o Re-order link command for smbd, rpcclient and smbpasswd to ensure + $LDFLAGS occurs before any library specification (bug 661). +o Fix large number of printf() calls for 64-bit size_t. +o Fix AC_CHECK_MEMBER so that SLES8 does correctly finds the + keyblock in the krb5 structs. +o Remove #include <compat.h> in hopes to avoid problems with + apache header files. +o Correct winbindd build problems on HP-UX 11. +o Lowercase netgroups lookups (bug 703). +o Use the actual size of the buffer in strftime instead of a made + up value which just happens to be less than sizeof(fstring). + (bug 713). +o Add ldaplibs to pdbedit link line (bug 651). +o Fix crash bug in smbclient completion (bug 659). +o Fix packet length for browse list reply (bug 771). +o Fix coredump in cli_get_backup_list(). +o Make sure that we expand %N (bug 612). +o Allow rpcclient adddriver command to specify printer driver + version (bug 514). +o Compile tdbdump by default. +o Apply patches to fix iconv detection for FreeBSD. +o Do not allow the 'guest account' to be added to a passdb backend + using smbpasswd or pdbedit (bug 624). +o Save LDFLAGS during iconv detection (bug 57). +o Run krb5 logins through the username map if the winbindd + lookup fails (bug 698). +o Add const for lp_set_name_resolve_order() to avoid compiler + warnings (bug 471). +o Add support for the %i macro in smb.conf to stand in for the for + the local IP address to which a client connected. +o Allow winbindd to match local accounts to domain SID when + 'winbind trusted domains only = yes' (bug 680). +o Remove code in idmap_ldap that searches the user suffix and group + suffix. It's not needed and provides inconsistent functionality + from the tdb backend. +o Patch to handle munged dial string for Windows 2000 TSE. + Thanks to Gaz de France, Direction de la Recherche, Service + Informatique Métier for their supporting this work by Aurelien + Degrémont <adegremont@idealx.com>. +o Correct the "smbldap_open: cannot access when not root error" + messages when looking up group information (bug 281). +o Skip over the winbind separator when looking up a user. + This fixes the bug that prevented local users from + matching an AD user when not running winbindd (bug 698). +o Fix a problem with configure on *BSD systems. Make sure + we add -liconv etc to LDFLAGS. +o Fix core dump bug when "security = server" and the authentication + server goes away. +o Correct crash bug due to an empty munged dial string. +o Show files locked by a specific user (smbstatus -u 'user') + (bug 590). +o Fix bug preventing print jobs from display in the queue + monitor used by Windows NT and later clients (bug 660). +o Fix several reported problems with point-n-print from + Windows 2000/XP clients due to a bug in the EnumPrinterDataEx() + reply (bug 338, 527 & 643). +o Fix a handful of potential memory leaks in the LDAP code used + by ldapsam[_compat] and the LDAP idmap backend. +o Fix for pdbedit error code returns (bug 763). +o Make sure we only enumerate group mapping entries (not + /etc/group) even when doing local aliases. +o Relax check on the pipe name in a dce/rpc bind response to work + around issues with establishing trusts to a Windows 2003 domain. +o Ensure we mangle names ending in '.' in hash2 mangling method. +o Correct parsing issues with munged dial string. +o Fix bugs in quota support for XFS. +o Add a cleaner method for applications that need to provide + name->SID mappings to do this via NSS rather than having to + know the winbindd pipe protocol. +o Adds a variant of the winbindd_getgroups() call called + winbindd_getusersids() that provides direct SID->SIDs listing of + a users supplementary groups. This is enough to allow non-Samba + applications to do ACL checking. +o Make sure we don't append the 'ldap suffix' when writing out the + 'ldap XXX suffix' values in SWAT (bug 328). +o Fix renames across file systems. +o Ensure that items in a list of strings containing whitespace are + written out surrounded by single quotes. This means that both + double and single quotes are now used to surround strings in + smb.conf (bug 481). +o Enable SWAT to correctly determine if winbindd is running (bug + 398). +o Include WWW-Authenticate field in 401 response for bad auth + attempt (bug 629). +o Add support for NTLM2 (NTLMv2 session security). +o Add support for variable-length session keys. +o More privilege fixes for group enumeration in LDAP (bug 281). +o Use the dns name (or IP) as the originating client name when + using CUPS (bug 467). +o Fix various SMB signing bugs. +o Fix ACL propagation on a DFS root (bug 263). +o Disable NTLM2 for RPC pipes. +o Allow the client to specify the NTLM2 flags got NTLMSSP + authentication. +o Change the name of the job passed off to cups from "Test Page" + to "smbprn.00000033 Test Page" so that we can get the smb + jobid back. This allow users to delete jobs with cups printing + backend (partial work on bug 770). +o Fix build of winbindd with static pdb modules. +o Retrieve the correct ACL group bits if the file has an ACL + (bug 802). +o Implement "net rpc group members": Get members of a domain group + in human-readable format. +o Add MacOSX (Darwin) specific charset module code. +o Use samr_dispinfo(level == 1) for enumerating domain users so we + can include the full name in gecos field (bug 587). +o Add support for winbind's NSS library on FeeeBSD 5.1 (bug 797). +o Implement 'net rpc group list [global|local|builtin]*' for a + select listing of the respective user databases. +o Don't automatically set NT status code flag unless client tells + us it can cope. +o Add 'net status [sessions|shares] [parseable]'. +o Don't mistake pre-existing UNIX jobs for smb jobs (remainder of + bug 770). +o Add 'Replicator' and 'RAS Servers' to list of builtin SIDs + (bug 608). +o Fix inverted logic in hosts allow/deny checks caused by + s/strcmp/strequal/ (bug 846). +o Implement correct version SamrRemoveSidForeignDomain() (bug 252). +o Fix typo in 'hash' mangling algorithm. +o Support munged dial for ldapsam (bug 800). +o Fix process_incoming_data() to return the number of bytes handled + this call whether we have a complete PDU or not; fixes bug + with multiple PDU request rpc's broken over SMBwriteX calls + each. +o Fix incorrect smb flags2 for connections to pre-NT servers + (causes smbclient to fail to OS2 for example) (bug 821). +o Update version string in smbldap-tools Makefile to 0.8.2. +o Correct a problem with "net rpc vampire" mis-parsing the + alias member info reply. +o Ensure the ${libdir} is created by the installclientlib script. +o Fix detection of Windows 2003 client architecture in the smb.conf + %a variable. +o Ensure that smbd calls the add user script for a missing UNIX + user on kerberos auth call (bug 445). +o Fix bugs in hosts allow/deny when using a mismatched + network/netmask pair. +o Protect alloc_sub_basic() from crashing when the source string + is NULL (partial work on bug 687). +o Fix spinlocks on IRIX. +o Corrected some bad destination paths when running "configure + --with-fhs". +o Add packaging files for Fedora Core 1. +o Correct bug in SWAT install script for non-english languages. +o Support character set ISO-8859-1 internally (bug 558). +o Fixed more LDAP access errors when looking up group mappings + (bug 281). +o Fix UNISTR2 length bug in LsaQueryInfo(3) that caused SID + resolution to fail on local files on on domain members + (bug 875). +o Fix uninitialized variable in passdb.c. +o Fix formal parameter type in get_static() in nsswitch/wins.c. +o Fix problem mounting directories when mount.cifs is installed + with the setuid bit on. +o Fix bug that prevent --mandir from overriding the defaults + given in the --with-fhs macro. +o Fix bug in in-memory Kerberos keytab detection routines + in configure.in + + + +###################################################################### + + The original 3.0.0 release notes follow + ======================================= + WHATS NEW IN Samba 3.0.0 + September 24, 2003 + ======================================= + + +Major new features: +------------------- + +1) Active Directory support. Samba 3.0 is now able to + join a ADS realm as a member server and authenticate + users using LDAP/Kerberos. + +2) Unicode support. Samba will now negotiate UNICODE on the wire + and internally there is now a much better infrastructure for + multi-byte and UNICODE character sets. + +3) New authentication system. The internal authentication system + has been almost completely rewritten. Most of the changes are + internal, but the new auth system is also very configurable. + +4) New default filename mangling system. + +5) A new "net" command has been added. It is somewhat similar to + the "net" command in windows. Eventually we plan to replace + numerous other utilities (such as smbpasswd) with subcommands + in "net". + +6) Samba now negotiates NT-style status32 codes on the wire. This + improves error handling a lot. + +7) Better Windows 2000/XP/2003 printing support including publishing + printer attributes in active directory. + +8) New loadable module support for passdb backends and character + sets. + +9) New default dual-daemon winbindd support for better performance. + +10) Support for migrating from a Windows NT 4.0 domain to a Samba + domain and maintaining user, group and domain SIDs. + +11) Support for establishing trust relationships with Windows NT 4.0 + domain controllers. + +12) Initial support for a distributed Winbind architecture using + an LDAP directory for storing SID to uid/gid mappings. + +13) Major updates to the Samba documentation tree. + +14) Full support for client and server SMB signing to ensure + compatibility with default Windows 2003 security settings. + +15) Improvement of ACL mapping features based on code donated by + Andreas Grünbacher. + + +Plus lots of other improvements! + + +Additional Documentation +------------------------ + +Please refer to Samba documentation tree (included in the docs/ +subdirectory) for extensive explanations of installing, configuring +and maintaining Samba 3.0 servers and clients. It is advised to +begin with the Samba-HOWTO-Collection for overviews and specific +tasks (the current book is up to approximately 400 pages) and to +refer to the various man pages for information on individual options. + +We are very glad to be able to include the second edition of +"Using Samba" by Jay Ts, Robert Eckstein, and David Collier-Brown +(O'Reilly & Associates) in this release. The book is available +on-line at http://samba.org/samba/docs/ and is included with +the Samba Web Administration Tool (SWAT). Thanks to the authors and +publisher for making "Using Samba" under the GNU Free Documentation +License. + + +###################################################################### +Upgrading from a previous Samba 3.0 beta +######################################## + +Beginning with Samba 3.0.0beta3, the RID allocation functions +have been moved into winbindd. Previously these were handled +by each passdb backend. This means that winbindd must be running +to automatically allocate RIDs for users and/or groups. Otherwise, +smbd will use the 2.2 algorithm for generating new RIDs. + +If you are using 'passdb backend = tdbsam' with a previous Samba +3.0 beta release (or possibly alpha), it may be necessary to +move the RID_COUNTER entry from /usr/local/samba/private/passdb.tdb +to winbindd_idmap.tdb. To do this: + +1) Ensure that winbindd_idmap.tdb exists (launch winbindd at least + once) +2) build tdbtool by executing 'make tdbtool' in the source/tdb/ + directory +3) run: (note that 'tdb>' is the tool's prompt for input) + + root# ./tdbtool /usr/local/samba/private/passdb.tdb + tdb> show RID_COUNTER + key 12 bytes + RID_COUNTER + data 4 bytes + [000] 0A 52 00 00 .R. + + tdb> move RID_COUNTER /usr/local/samba/var/locks/winbindd_idmap.tdb + .... + record moved + +If you are using 'passdb backend = ldapsam', it will be necessary to +store idmap entries in the LDAP directory as well (i.e. idmap backend += ldap). Refer to the 'net idmap' command for more information on +migrating SID<->UNIX id mappings from one backend to another. + +If the RID_COUNTER record does not exist, then these instructions are +unneccessary and the new RID_COUNTER record will be correctly generated +if needed. + + + +######################## +Upgrading from Samba 2.2 +######################## + +This section is provided to help administrators understand the details +involved with upgrading a Samba 2.2 server to Samba 3.0. + + +Building +-------- + +Many of the options to the GNU autoconf script have been modified +in the 3.0 release. The most noticeable are: + + * removal of --with-tdbsam (is now included by default; see section + on passdb backends and authentication for more details) + + * --with-ldapsam is now on used to provided backward compatible + parameters for LDAP enabled Samba 2.2 servers. Refer to the passdb + backend and authentication section for more details + + * inclusion of non-standard passdb modules may be enabled using + --with-expsam. This includes an XML backend and a mysql backend. + + * removal of --with-msdfs (is now enabled by default) + + * removal of --with-ssl (no longer supported) + + * --with-utmp now defaults to 'yes' on supported systems + + * --with-sendfile-support is now enabled by default on supported + systems + + +Parameters +---------- + +This section contains a brief listing of changes to smb.conf options +in the 3.0.0 release. Please refer to the smb.conf(5) man page for +complete descriptions of new or modified parameters. + +Removed Parameters (order alphabetically): + + * admin log + * alternate permissions + * character set + * client codepage + * code page directory + * coding system + * domain admin group + * domain guest group + * force unknown acl user + * hide local users + * mangled stack + * nt smb support + * postscript + * printer driver + * printer driver file + * printer driver location + * read size + * source environment + * status + * strip dot + * total print jobs + * use rhosts + * valid chars + * vfs options + +New Parameters (new parameters have been grouped by function): + + Remote management + ----------------- + * abort shutdown script + * shutdown script + + User and Group Account Management + --------------------------------- + * add group script + * add machine script + * add user to group script + * algorithmic rid base + * delete group script + * delete user from group script + * passdb backend + * set primary group script + + Authentication + -------------- + * auth methods + * realm + * passwd chat timeout + + Protocol Options + ---------------- + * client lanman auth + * client NTLMv2 auth + * client schannel + * client signing + * client use spnego + * disable netbios + * ntlm auth + * paranoid server security + * server schannel + * server signing + * smb ports + * use spnego + + File Service + ------------ + * get quota command + * hide special files + * hide unwriteable files + * hostname lookups + * kernel change notify + * mangle prefix + * map acl inherit + * msdfs proxy + * set quota command + * use sendfile + * vfs objects + + Printing + -------- + * max reported print jobs + + UNICODE and Character Sets + -------------------------- + * display charset + * dos charset + * unicode + * unix charset + + SID to uid/gid Mappings + ----------------------- + * idmap backend + * idmap gid + * idmap uid + * winbind enable local accounts + * winbind trusted domains only + * template primary group + * enable rid algorithm + + LDAP + ---- + * ldap delete dn + * ldap group suffix + * ldap idmap suffix + * ldap machine suffix + * ldap passwd sync + * ldap replication sleep + * ldap user suffix + + General Configuration + --------------------- + * preload modules + * private dir + +Modified Parameters (changes in behavior): + + * encrypt passwords (enabled by default) + * mangling method (set to 'hash2' by default) + * passwd chat + * passwd program + * restrict anonymous (integer value) + * security (new 'ads' value) + * strict locking (enabled by default) + * unix extensions (enabled by default) + * winbind cache time (increased to 5 minutes) + * winbind uid (deprecated in favor of 'idmap uid') + * winbind gid (deprecated in favor of 'idmap gid') + + +Databases +--------- + +This section contains brief descriptions of any new databases +introduced in Samba 3.0. Please remember to backup your existing +${lock directory}/*tdb before upgrading to Samba 3.0. Samba will +upgrade databases as they are opened (if necessary), but downgrading +from 3.0 to 2.2 is an unsupported path. + +Name Description Backup? +---- ----------- ------- +account_policy User policy settings yes +gencache Generic caching db no +group_mapping Mapping table from Windows yes + groups/SID to unix groups +winbindd_idmap ID map table from SIDS to UNIX yes + uids/gids. +namecache Name resolution cache entries no +netsamlogon_cache Cache of NET_USER_INFO_3 structure no + returned as part of a successful + net_sam_logon request +printing/*.tdb Cached output from 'lpq no + command' created on a per print + service basis +registry Read-only samba registry skeleton no + that provides support for exporting + various db tables via the winreg RPCs + + +Changes in Behavior +------------------- + +The following issues are known changes in behavior between Samba 2.2 and +Samba 3.0 that may affect certain installations of Samba. + + 1) When operating as a member of a Windows domain, Samba 2.2 would + map any users authenticated by the remote DC to the 'guest account' + if a uid could not be obtained via the getpwnam() call. Samba 3.0 + rejects the connection as NT_STATUS_LOGON_FAILURE. There is no + current work around to re-establish the 2.2 behavior. + + 2) When adding machines to a Samba 2.2 controlled domain, the + 'add user script' was used to create the UNIX identity of the + machine trust account. Samba 3.0 introduces a new 'add machine + script' that must be specified for this purpose. Samba 3.0 will + not fall back to using the 'add user script' in the absence of + an 'add machine script' + + +###################################################################### +Passdb Backends and Authentication +################################## + +There have been a few new changes that Samba administrators should be +aware of when moving to Samba 3.0. + + 1) encrypted passwords have been enabled by default in order to + inter-operate better with out-of-the-box Windows client + installations. This does mean that either (a) a samba account + must be created for each user, or (b) 'encrypt passwords = no' + must be explicitly defined in smb.conf. + + 2) Inclusion of new 'security = ads' option for integration + with an Active Directory domain using the native Windows + Kerberos 5 and LDAP protocols. + + MIT kerberos 1.3.1 supports the ARCFOUR-HMAC-MD5 encryption + type which is neccessary for servers on which the + administrator password has not been changed, or kerberos-enabled + SMB connections to servers that require Kerberos SMB signing. + Besides this one difference, either MIT or Heimdal Kerberos + distributions are usable by Samba 3.0. + + +Samba 3.0 also includes the possibility of setting up chains +of authentication methods (auth methods) and account storage +backends (passdb backend). Please refer to the smb.conf(5) +man page for details. While both parameters assume sane default +values, it is likely that you will need to understand what the +values actually mean in order to ensure Samba operates correctly. + +The recommended passdb backends at this time are + + * smbpasswd - 2.2 compatible flat file format + * tdbsam - attribute rich database intended as an smbpasswd + replacement for stand alone servers + * ldapsam - attribute rich account storage and retrieval + backend utilizing an LDAP directory. + * ldapsam_compat - a 2.2 backward compatible LDAP account + backend + +Certain functions of the smbpasswd(8) tool have been split between the +new smbpasswd(8) utility, the net(8) tool, and the new pdbedit(8) +utility. See the respective man pages for details. + + +###################################################################### +LDAP +#### + +This section outlines the new features affecting Samba / LDAP +integration. + +New Schema +---------- + +A new object class (sambaSamAccount) has been introduced to replace +the old sambaAccount. This change aids us in the renaming of +attributes to prevent clashes with attributes from other vendors. +There is a conversion script (examples/LDAP/convertSambaAccount) to +modify and LDIF file to the new schema. + +Example: + + $ ldapsearch .... -b "ou=people,dc=..." > sambaAcct.ldif + $ convertSambaAccount --sid=<Domain SID> \ + --input=sambaAcct.ldif --output=sambaSamAcct.ldif \ + --changetype=[modify|add] + +The <DOM SID> can be obtained by running 'net getlocalsid +<DOMAINNAME>' on the Samba PDC as root. The changetype determines +the format of the generated LDIF output--either create new entries +or modify existing entries. + +The old sambaAccount schema may still be used by specifying the +"ldapsam_compat" passdb backend. However, the sambaAccount and +associated attributes have been moved to the historical section of +the schema file and must be uncommented before use if needed. +The 2.2 object class declaration for a sambaAccount has not changed +in the 3.0 samba.schema file. + +Other new object classes and their uses include: + + * sambaDomain - domain information used to allocate rids + for users and groups as necessary. The attributes are added + in 'ldap suffix' directory entry automatically if + an idmap uid/gid range has been set and the 'ldapsam' + passdb backend has been selected. + + * sambaGroupMapping - an object representing the + relationship between a posixGroup and a Windows + group/SID. These entries are stored in the 'ldap + group suffix' and managed by the 'net groupmap' command. + + * sambaUnixIdPool - created in the 'ldap idmap suffix' entry + automatically and contains the next available 'idmap uid' and + 'idmap gid' + + * sambaIdmapEntry - object storing a mapping between a + SID and a UNIX uid/gid. These objects are created by the + idmap_ldap module as needed. + + * sambaSidEntry - object representing a SID alone, as a Structural + class on which to build the sambaIdmapEntry. + + +New Suffix for Searching +------------------------ + +The following new smb.conf parameters have been added to aid in directing +certain LDAP queries when 'passdb backend = ldapsam://...' has been +specified. + + * ldap suffix - used to search for user and computer accounts + * ldap user suffix - used to store user accounts + * ldap machine suffix - used to store machine trust accounts + * ldap group suffix - location of posixGroup/sambaGroupMapping entries + * ldap idmap suffix - location of sambaIdmapEntry objects + +If an 'ldap suffix' is defined, it will be appended to all of the +remaining sub-suffix parameters. In this case, the order of the suffix +listings in smb.conf is important. Always place the 'ldap suffix' first +in the list. + +Due to a limitation in Samba's smb.conf parsing, you should not surround +the DN's with quotation marks. + + +IdMap LDAP support +------------------ + +Samba 3.0 supports an ldap backend for the idmap subsystem. The +following options would inform Samba that the idmap table should be +stored on the directory server onterose in the "ou=idmap,dc=plainjoe, +dc=org" partition. + + [global] + ... + idmap backend = ldap:ldap://onterose/ + ldap idmap suffix = ou=idmap,dc=plainjoe,dc=org + idmap uid = 40000-50000 + idmap gid = 40000-50000 + +This configuration allows winbind installations on multiple servers to +share a uid/gid number space, thus avoiding the interoperability problems +with NFS that were present in Samba 2.2. + + + +###################################################################### +Trust Relationships and a Samba Domain +###################################### + +Samba 3.0.0beta2 is able to utilize winbindd as the means of +allocating uids and gids to trusted users and groups. More +information regarding Samba's support for establishing trust +relationships can be found in the Samba-HOWTO-Collection included +in the docs/ directory of this release. + +First create your Samba PDC and ensure that everything is +working correctly before moving on the trusts. + +To establish Samba as the trusting domain (named SAMBA) from a Windows NT +4.0 domain named WINDOWS: + + 1) create the trust account for SAMBA in "User Manager for Domains" + 2) connect the trust from the Samba domain using + 'net rpc trustdom establish GLASS' + +To create a trustlationship with SAMBA as the trusted domain: + + 1) create the initial trust account for GLASS using + 'smbpasswd -a -i GLASS'. You may need to create a UNIX + account for GLASS$ prior to this step (depending on your + local configuration). + 2) connect the trust from a WINDOWS DC using "User Manager + for Domains" + +Now join winbindd on the Samba PDC to the SAMBA domain using +the normal steps for adding a Samba server to an NT4 domain: +(note that smbd & nmbd must be running at this point) + + root# net rpc join -U root + Password: <enter root password from smbpasswd file here> + +Start winbindd and test the join with 'wbinfo -t'. + +Now test the trust relationship by connecting to the SAMBA DC +(e.g. POGO) as a user from the WINDOWS domain: + + $ smbclient //pogo/netlogon -U Administrator -W WINDOWS + Password: + +Now connect to the WINDOWS DC (e.g. CRYSTAL) as a Samba user: + + $ smbclient //crystal/netlogon -U root -W WINDOWS + Password: + +###################################################################### +Changes in Winbind +################## + +Beginning with Samba3.0.0beta3, winbindd has been given new account +manage functionality equivalent to the 'add user script' family of +smb.conf parameters. The idmap design has also been changed to +centralize control of foreign SID lookups and matching to UNIX +uids and gids. + + +Brief Description of Changes +---------------------------- + +1) The sid_to_uid() family of functions (smbd/uid.c) have been + reverted to the 2.2.x design. This means that when resolving a + SID to a UID or similar mapping: + + a) First consult winbindd + b) perform a local lookup only if winbindd fails to + return a successful answer + + There are some variations to this, but these two rules generally + apply. + +2) All idmap lookups have been moved into winbindd. This means that + a server must run winbindd (and support NSS) in order to achieve + any mappings of SID to dynamically allocated UNIX ids. This was + a conscious design choice. + +3) (OBSOLETE) New functions have been added to winbindd to emulate + the 'add user script' family of smbd functions without requiring + that external scripts be defined. This functionality is controlled + by the 'winbind enable local accounts' smb.conf parameter (enabled + by default). + + However, this account management functionality is only supported + in a local tdb (winbindd_idmap.tdb). If these new UNIX accounts + must be shared among multiple Samba servers (such as a PDC and BDCs), + it will be necessary to define your own 'add user script', et. al. + programs that place the accounts/groups in some form of directory + such as NIS or LDAP. This requirement was deemed beyond the scope + of winbind's account management functions. Solutions for + distributing UNIX system information have been deployed and tested + for many years. We saw no need to reinvent the wheel. + +4) A member of a Samba controlled domain running winbindd is now able + to map domain users directly onto existing UNIX accounts while still + automatically creating accounts for trusted users and groups. This + behavior is controlled by the 'winbind trusted domains only' smb.conf + parameter (disabled by default to provide 2.2.x winbind behavior). + +5) Group mapping support is wrapped in the local_XX_to_XX() functions + in smbd/uid.c. The reason that group mappings are not included + in winbindd is because the purpose of Samba's group map is to + match any Windows SID with an existing UNIX group. These UNIX + groups can be created by winbindd (see next section), but the + SID<->gid mapping is retreived by smbd, not winbindd. + + +Examples +-------- + +* security = server running winbindd to allocate accounts on demand + +* Samba PDC running winbindd to handle the automatic creation of UNIX + identities for machine trust accounts + +* Automtically creating UNIX user and groups when migrating a Windows NT + 4.0 PDC to a Samba PDC. Winbindd must be running when executing + 'net rpc vampire' for this to work. + + +###################################################################### +Known Issues +############ + +* There are several bugs currently logged against the 3.0 codebase + that affect the use of NT 4.0 GUI domain management tools when run + against a Samba 3.0 PDC. This bugs should be released in an early + 3.0.x release. + +Please refer to https://bugzilla.samba.org/ for a current list of bugs +filed against the Samba 3.0 codebase. + + +###################################################################### +Reporting bugs & Development Discussion +####################################### + +Please discuss this release on the samba-technical mailing list or by +joining the #samba-technical IRC channel on irc.freenode.net. + +If you do report problems then please try to send high quality +feedback. If you don't provide vital information to help us track down +the problem then you will probably be ignored. + +A new bugzilla installation has been established to help support the +Samba 3.0 community of users. This server, located at +https://bugzilla.samba.org/, has replaced the older jitterbug server +previously located at http://bugs.samba.org/. diff --git a/docs/README-NOW b/docs/README-NOW deleted file mode 100644 index cb9a4a68d50..00000000000 --- a/docs/README-NOW +++ /dev/null @@ -1,9 +0,0 @@ - ATTENTION - DOCS TREE REMOVED ---------------------------------------------------- - -This docs tree has been moved to a separate SVN -module on svn.samba.org named 'samba-docs'. -See http://svn.samba.org/samba/subversion.html -for details on accessing Samba svn trees. - diff --git a/examples/libsmbclient/smbwrapper/bsd-strlcat.c b/examples/libsmbclient/smbwrapper/bsd-strlcat.c deleted file mode 100644 index d82ced3e8a3..00000000000 --- a/examples/libsmbclient/smbwrapper/bsd-strlcat.c +++ /dev/null @@ -1,71 +0,0 @@ -/* $OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $ */ - -/* - * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This version has been modified for inclusion in Samba. - * It has been converted to ANSI C from old-style K&R C. - */ - -#include <sys/types.h> -#include <string.h> - -/* - * Appends src to string dst of size siz (unlike strncat, siz is the - * full size of dst, not space left). At most siz-1 characters - * will be copied. Always NUL terminates (unless siz <= strlen(dst)). - * Returns strlen(src) + MIN(siz, strlen(initial dst)). - * If retval >= siz, truncation occurred. - */ -size_t -smbw_strlcat(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - - if (n == 0) - return(dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(dlen + (s - src)); /* count does not include NUL */ -} diff --git a/examples/libsmbclient/smbwrapper/bsd-strlcpy.c b/examples/libsmbclient/smbwrapper/bsd-strlcpy.c deleted file mode 100644 index 9f7e55da8e0..00000000000 --- a/examples/libsmbclient/smbwrapper/bsd-strlcpy.c +++ /dev/null @@ -1,67 +0,0 @@ -/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ - -/* - * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This version has been modified for inclusion in Samba. - * It has been converted to ANSI C from old-style K&R C. - */ - -#include <sys/types.h> -#include <string.h> - -/* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. - */ -size_t -smbw_strlcpy(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0 && --n != 0) { - do { - if ((*d++ = *s++) == 0) - break; - } while (--n != 0); - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ -} diff --git a/examples/libsmbclient/smbwrapper/bsd-strlfunc.h b/examples/libsmbclient/smbwrapper/bsd-strlfunc.h deleted file mode 100644 index fb3a045ac6c..00000000000 --- a/examples/libsmbclient/smbwrapper/bsd-strlfunc.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __BSD_STRLFUNC_H__ - -extern size_t strlcpy(char *dst, const char *src, size_t siz); -extern size_t strlcat(char *dst, const char *src, size_t siz); - -#define __BSD_STRLFUNC_H__ -#endif diff --git a/examples/libsmbclient/teststat2.c b/examples/libsmbclient/teststat2.c deleted file mode 100644 index d1cdf285014..00000000000 --- a/examples/libsmbclient/teststat2.c +++ /dev/null @@ -1,72 +0,0 @@ -#include <libsmbclient.h> -#include <sys/stat.h> -#include <string.h> -#include <stdio.h> -#include <time.h> -#include "get_auth_data_fn.h" - -/* - * This test is intended to ensure that the timestamps returned by - * libsmbclient are the same as timestamps returned by the local system. To - * test this, we assume a working Samba environment, and and access the same - * file via SMB and locally (or NFS). - * - */ - - -static int gettime(const char * pUrl, - const char * pLocalPath); - - -int main(int argc, char* argv[]) -{ - if(argc != 3) - { - printf("usage: %s <file_url> <file_localpath>\n", argv[0]); - return 1; - } - - gettime(argv[1], argv[2]); - return 0; -} - - -static int gettime(const char * pUrl, - const char * pLocalPath) -{ - //char *pSmbPath = 0; - struct stat st; - char mtime[32]; - char ctime[32]; - char atime[32]; - - smbc_init(get_auth_data_fn, 0); - - if (smbc_stat(pUrl, &st) < 0) - { - perror("smbc_stat"); - return 1; - } - - printf("SAMBA\n mtime:%lu/%s ctime:%lu/%s atime:%lu/%s\n", - st.st_mtime, ctime_r(&st.st_mtime, mtime), - st.st_ctime, ctime_r(&st.st_ctime, ctime), - st.st_atime, ctime_r(&st.st_atime, atime)); - - - // check the stat on this file - if (stat(pLocalPath, &st) < 0) - { - perror("stat"); - return 1; - } - - printf("LOCAL\n mtime:%lu/%s ctime:%lu/%s atime:%lu/%s\n", - st.st_mtime, ctime_r(&st.st_mtime, mtime), - st.st_ctime, ctime_r(&st.st_ctime, ctime), - st.st_atime, ctime_r(&st.st_atime, atime)); - - - return 0; -} - diff --git a/make-tarball.sh b/make-tarball.sh deleted file mode 100644 index f3250d5c732..00000000000 --- a/make-tarball.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/sh - -## A simple script to build a tarball of the current CVS tree. -## You either need to include the using_samba cvs module in the -## parent directory or tell the script where to find it -## -## Usgae: ./make-tarball.sh - -DOCSDIR=../samba-docs/ -USING_SAMBA=../using_samba/ -SRCDIR=`pwd` - -if [ ! -d $USING_SAMBA ]; then - - echo Cannot find "Using Samba" directory \(assuming $USING_SAMBA\). - echo Please set the USING_SAMBA variable in this script to the correct - echo location. The html files are available in the using_samba CVS - echo module on cvs.samba.org. See http://cvs/samba.org/ for details - echo about anonymous CVS access. Exiting now.... - - exit 1 - -fi - -if [ ! -d $DOCSDIR ]; then - - echo Cannot find samba-docs \(assuming $DOCSDIR\). - echo Please set the DOCSDIR variable in this script - echo to the correct path. - - exit 1 - -fi - - -VERSION=`grep SAMBA_VERSION_OFFICIAL_STRING source/include/version.h | cut -d\" -f2 | sed 's/ /_/g'` -TARBALLDIR=/tmp/samba-$VERSION - -echo Creating the tarball source directory in $TARBALLDIR - -/bin/rm -rf $TARBALLDIR -/bin/rm -f samba-$VERSION.tar - -mkdir $TARBALLDIR -rsync -aC ./ $TARBALLDIR -/bin/rm -rf $TARBALLDIR/docs/* -rsync -aC $DOCSDIR/ $TARBALLDIR/docs/ -rsync -aC $USING_SAMBA $TARBALLDIR/docs/htmldocs/ - -echo Creating packaging scripts... -( cd $TARBALLDIR/packaging; sh bin/update-pkginfo $VERSION 1 ) - -echo Creating source/configure... -( cd $TARBALLDIR/source; ./autogen.sh ) - -echo Making tarball samba-$VERSION.tar in current directory... -( cd `dirname $TARBALLDIR`; tar cf $SRCDIR/samba-$VERSION.tar samba-$VERSION ) diff --git a/source/.indent.pro b/source/.indent.pro deleted file mode 100644 index 05445f44924..00000000000 --- a/source/.indent.pro +++ /dev/null @@ -1,30 +0,0 @@ --bad --bap --bbb --br --ce --ut --ts8 --i8 --di1 --brs --npsl --npcs --prs --bbo --hnl --bad --bap --bbb --br --ce --ut --ts8 --i8 --di1 --brs --npsl --npcs --prs --bbo --hnl diff --git a/source/Makefile.in b/source/Makefile.in index 15d22d8fa59..4cc662a18e2 100644 --- a/source/Makefile.in +++ b/source/Makefile.in @@ -104,9 +104,9 @@ LIBMSRPC_MINOR=1 LIBSMBSHAREMODES=bin/libsmbsharemodes.a @LIBSMBSHAREMODES_SHARED@ LIBSMBSHAREMODES_MAJOR=0 -LIBSMBSHAREMODES_MINOR=2 +LIBSMBSHAREMODES_MINOR=1 -FLAGS1 = $(CFLAGS) @FLAGS1@ -Iinclude -I$(srcdir)/include -I$(srcdir)/tdb @SMBWRAP_INC@ -I. $(CPPFLAGS) -I$(srcdir) -D_SAMBA_BUILD_ +FLAGS1 = $(CFLAGS) @FLAGS1@ -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/tdb @SMBWRAP_INC@ -I. $(CPPFLAGS) -I$(srcdir) -D_SAMBA_BUILD_ FLAGS2 = FLAGS3 = FLAGS4 = @@ -219,6 +219,9 @@ READLINE_OBJ = lib/readline.o # Be sure to include them into your application POPT_LIB_OBJ = lib/popt_common.o +UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \ + ubiqx/ubi_dLinkList.o ubiqx/ubi_sLinkList.o + PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o KRBCLIENT_OBJ = libads/kerberos.o libads/ads_status.o @@ -323,7 +326,7 @@ LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o PASSDB_GET_SET_OBJ = passdb/pdb_get_set.o PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \ - passdb/util_wellknown.o passdb/util_builtin.o passdb/pdb_compat.o \ + passdb/util_sam_sid.o passdb/pdb_compat.o \ passdb/lookup_sid.o \ passdb/login_cache.o @PDB_STATIC@ passdb/pdb_sql.o \ lib/system_smbd.o lib/account_pol.o lib/privileges.o @@ -347,7 +350,7 @@ PROFILES_OBJ = utils/profiles.o \ OPLOCK_OBJ = smbd/oplock.o smbd/oplock_irix.o smbd/oplock_linux.o -NOTIFY_OBJ = smbd/notify.o smbd/notify_hash.o smbd/notify_kernel.o smbd/notify_fam.o +NOTIFY_OBJ = smbd/notify.o smbd/notify_hash.o smbd/notify_kernel.o VFS_AUDIT_OBJ = modules/vfs_audit.o VFS_EXTD_AUDIT_OBJ = modules/vfs_extd_audit.o @@ -438,13 +441,13 @@ NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \ nmbd/nmbd_subnetdb.o nmbd/nmbd_winsproxy.o nmbd/nmbd_winsserver.o \ nmbd/nmbd_workgroupdb.o nmbd/nmbd_synclists.o -NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ +NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(UBIQX_OBJ) \ $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) WREPL_OBJ1 = wrepld/server.o wrepld/process.o wrepld/parser.o wrepld/socket.o \ wrepld/partners.o -WREPL_OBJ = $(WREPL_OBJ1) $(PARAM_OBJ) \ +WREPL_OBJ = $(WREPL_OBJ1) $(PARAM_OBJ) $(UBIQX_OBJ) \ $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) \ $(LIBSAMBA_OBJ) @@ -540,7 +543,7 @@ LIBSMBSHAREMODES_OBJ = libsmb/smb_share_modes.o tdb/tdb.o tdb/spinlock.o LIBBIGBALLOFMUD_MAJOR = 0 -LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) \ +LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(UBIQX_OBJ) $(SECRETS_OBJ) \ $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) \ $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) @@ -641,7 +644,7 @@ RPCTORTURE_OBJ = torture/rpctorture.o \ $(PARAM_OBJ) $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \ $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ) -DEBUG2HTML_OBJ = utils/debug2html.o utils/debugparse.o +DEBUG2HTML_OBJ = utils/debug2html.o ubiqx/debugparse.o SMBFILTER_OBJ = utils/smbfilter.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(SECRETS_OBJ) \ $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) @@ -815,7 +818,7 @@ MAKEDIR = || exec false; \ # of gcc-3.4 and run 'make pch' before you do the main build. pch: rm -f $(srcdir)/include/includes.h.gch - $(CC) -I. -I$(srcdir) $(FLAGS) @PIE_CFLAGS@ -c $(srcdir)/include/includes.h -o $(srcdir)/include/includes.h.gch + $(CC) -I. -I$(srcdir) $(FLAGS) -c $(srcdir)/include/includes.h -o $(srcdir)/include/includes.h.gch ## ## Targets for 'make test' @@ -877,7 +880,7 @@ bin/smbd@EXEEXT@: $(SMBD_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \ $(KRB5LIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \ - $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@ @SMBD_LIBS@ + $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@ bin/nmbd@EXEEXT@: $(NMBD_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @@ -1008,7 +1011,7 @@ bin/nsstest@EXEEXT@: $(NSSTEST_OBJ) bin/.dummy bin/vfstest@EXEEXT@: $(VFSTEST_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(ACL_LIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) @SMBD_LIBS@ + @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(ACL_LIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) bin/smbiconv@EXEEXT@: $(SMBICONV_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @@ -1239,12 +1242,12 @@ bin/smbpasswd.@SHLIBEXT@: passdb/pdb_smbpasswd.@PICSUFFIX@ @$(SHLD) $(LDSHFLAGS) -o $@ passdb/pdb_smbpasswd.@PICSUFFIX@ \ @SONAMEFLAG@`basename $@` -bin/rid.@SHLIBEXT@: sam/idmap_rid.@PICSUFFIX@ +bin/idmap_rid.@SHLIBEXT@: sam/idmap_rid.@PICSUFFIX@ @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ sam/idmap_rid.@PICSUFFIX@ \ @SONAMEFLAG@`basename $@` -bin/ad.@SHLIBEXT@: sam/idmap_ad.@PICSUFFIX@ +bin/idmap_ad.@SHLIBEXT@: sam/idmap_ad.@PICSUFFIX@ @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ sam/idmap_ad.@PICSUFFIX@ \ @SONAMEFLAG@`basename $@` diff --git a/source/VERSION b/source/VERSION index 5119a954012..36aca8bb1f3 100644 --- a/source/VERSION +++ b/source/VERSION @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=3 SAMBA_VERSION_MINOR=0 -SAMBA_VERSION_RELEASE=22 +SAMBA_VERSION_RELEASE=21 ######################################################## # If a official release has a serious bug # @@ -37,7 +37,7 @@ SAMBA_VERSION_RELEASE=22 # e.g. SAMBA_VERSION_REVISION=a # # -> "2.2.8a" # ######################################################## -SAMBA_VERSION_REVISION= +SAMBA_VERSION_REVISION=b ######################################################## # For 'pre' releases the version will be # @@ -47,7 +47,7 @@ SAMBA_VERSION_REVISION= # e.g. SAMBA_VERSION_PRE_RELEASE=1 # # -> "2.2.9pre1" # ######################################################## -SAMBA_VERSION_PRE_RELEASE=1 +SAMBA_VERSION_PRE_RELEASE= ######################################################## # For 'rc' releases the version will be # @@ -69,7 +69,7 @@ SAMBA_VERSION_RC_RELEASE= # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_SVN_SNAPSHOT=yes +SAMBA_VERSION_IS_SVN_SNAPSHOT= ######################################################## # This can be set by vendors if they want... # diff --git a/source/aclocal.m4 b/source/aclocal.m4 index 86c43f80dc0..af93aa23685 100644 --- a/source/aclocal.m4 +++ b/source/aclocal.m4 @@ -56,7 +56,7 @@ AC_DEFUN(SMB_MODULE, [$6] string_shared_modules="$string_shared_modules $1" elif test x"$DEST" = xSTATIC; then - [init_static_modules_]translit([$4], [A-Z], [a-z])="$[init_static_modules_]translit([$4], [A-Z], [a-z]) $1_init();" + [init_static_modules_]translit([$4], [A-Z], [a-z])="$[init_static_modules_]translit([$4], [A-Z], [a-z]) $1_init();" string_static_modules="$string_static_modules $1" $4_STATIC="$$4_STATIC $2" AC_SUBST($4_STATIC) diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c index eb15fff7c8d..483686a9dee 100644 --- a/source/auth/auth_util.c +++ b/source/auth/auth_util.c @@ -591,36 +591,33 @@ static NTSTATUS create_nt_user_token(const DOM_SID *user_sid, const DOM_SID *gro (strlen(lp_log_nt_token_command()) > 0)) { TALLOC_CTX *mem_ctx; char *command; - char *group_sidstr; + fstring sidstr; + char *user_sidstr, *group_sidstr; mem_ctx = talloc_init("setnttoken"); if (mem_ctx == NULL) return NT_STATUS_NO_MEMORY; + sid_to_string(sidstr, &ptoken->user_sids[0]); + user_sidstr = talloc_strdup(mem_ctx, sidstr); + group_sidstr = talloc_strdup(mem_ctx, ""); for (i=1; i<ptoken->num_sids; i++) { - group_sidstr = talloc_asprintf( - mem_ctx, "%s %s", group_sidstr, - sid_string_static(&ptoken->user_sids[i])); - } - - command = talloc_string_sub( - mem_ctx, lp_log_nt_token_command(), - "%s", sid_string_static(&ptoken->user_sids[0])); - command = talloc_string_sub( - mem_ctx, command, "%t", group_sidstr); - - if (command == NULL) { - talloc_destroy(mem_ctx); - return NT_STATUS_NO_MEMORY; + sid_to_string(sidstr, &ptoken->user_sids[i]); + group_sidstr = talloc_asprintf(mem_ctx, "%s %s", + group_sidstr, sidstr); } + command = SMB_STRDUP(lp_log_nt_token_command()); + command = realloc_string_sub(command, "%s", user_sidstr); + command = realloc_string_sub(command, "%t", group_sidstr); DEBUG(8, ("running command: [%s]\n", command)); if (smbrun(command, NULL) != 0) { DEBUG(0, ("Could not log NT token\n")); nt_status = NT_STATUS_ACCESS_DENIED; } talloc_destroy(mem_ctx); + SAFE_FREE(command); } *token = ptoken; @@ -1603,7 +1600,7 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) Check for a SID in an NT_USER_TOKEN ****************************************************************************/ -static BOOL nt_token_check_sid ( DOM_SID *sid, NT_USER_TOKEN *token ) +BOOL nt_token_check_sid ( DOM_SID *sid, NT_USER_TOKEN *token ) { int i; @@ -1651,6 +1648,8 @@ BOOL nt_token_check_domain_rid( NT_USER_TOKEN *token, uint32 rid ) BOOL is_trusted_domain(const char* dom_name) { DOM_SID trustdom_sid; + char *pass = NULL; + time_t lct; BOOL ret; /* no trusted domains for a standalone server */ @@ -1664,8 +1663,9 @@ BOOL is_trusted_domain(const char* dom_name) become_root(); DEBUG (5,("is_trusted_domain: Checking for domain trust with [%s]\n", dom_name )); - ret = secrets_fetch_trusted_domain_password(dom_name, NULL, NULL, NULL); + ret = secrets_fetch_trusted_domain_password(dom_name, &pass, &trustdom_sid, &lct); unbecome_root(); + SAFE_FREE(pass); if (ret) return True; } diff --git a/source/auth/pass_check.c b/source/auth/pass_check.c index 507e8a3836e..0425e01cdcb 100644 --- a/source/auth/pass_check.c +++ b/source/auth/pass_check.c @@ -452,9 +452,9 @@ static NTSTATUS string_combinations2(char *s, int offset, NTSTATUS (*fn) (const for (i = offset; i < (len - (N - 1)); i++) { char c = s[i]; - if (!islower_ascii(c)) + if (!islower(c)) continue; - s[i] = toupper_ascii(c); + s[i] = toupper(c); if (!NT_STATUS_EQUAL(nt_status = string_combinations2(s, i + 1, fn, N - 1),NT_STATUS_WRONG_PASSWORD)) { return (nt_status); } diff --git a/source/client/client.c b/source/client/client.c index 7ac64970f81..f95bbea6718 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -3326,7 +3326,6 @@ static int do_message_op(void) POPT_TABLEEND }; - load_case_tables(); #ifdef KANJI pstrcpy(term_code, KANJI); diff --git a/source/client/clitar.c b/source/client/clitar.c index c15d24d619a..5afe154cbbe 100644 --- a/source/client/clitar.c +++ b/source/client/clitar.c @@ -482,7 +482,7 @@ static int strslashcmp(char *s1, char *s2) { char *s1_0=s1; - while(*s1 && *s2 && (*s1 == *s2 || tolower_ascii(*s1) == tolower_ascii(*s2) || + while(*s1 && *s2 && (*s1 == *s2 || tolower(*s1) == tolower(*s2) || (*s1 == '\\' && *s2=='/') || (*s1 == '/' && *s2=='\\'))) { s1++; s2++; } diff --git a/source/configure.in b/source/configure.in index 44517ae6eab..ec1bdacad84 100644 --- a/source/configure.in +++ b/source/configure.in @@ -795,7 +795,7 @@ AC_CHECK_HEADERS(shadow.h netinet/tcp.h netinet/in_systm.h netinet/in_ip.h) AC_CHECK_HEADERS(nss.h nss_common.h nsswitch.h ns_api.h sys/security.h security/pam_appl.h) AC_CHECK_HEADERS(stropts.h poll.h) AC_CHECK_HEADERS(sys/capability.h syscall.h sys/syscall.h) -AC_CHECK_HEADERS(sys/acl.h sys/attributes.h attr/xattr.h sys/xattr.h sys/extattr.h sys/uio.h sys/proplist.h) +AC_CHECK_HEADERS(sys/acl.h sys/attributes.h attr/xattr.h sys/xattr.h sys/extattr.h sys/uio.h) AC_CHECK_HEADERS(sys/cdefs.h glob.h) AC_CHECK_HEADERS(netinet/ip.h,,,[[ @@ -1345,23 +1345,12 @@ AC_LIBTESTFUNC(sec, getprpwnam) ############################################ # Check if we have libattr -case "$host_os" in - *osf*) - AC_SEARCH_LIBS(getproplist, [proplist]) - AC_CHECK_FUNCS(getproplist fgetproplist setproplist fsetproplist) - AC_CHECK_FUNCS(delproplist fdelproplist add_proplist_entry get_proplist_entry) - AC_CHECK_FUNCS(sizeof_proplist_entry) - ;; - *) - AC_SEARCH_LIBS(getxattr, [attr]) - AC_CHECK_FUNCS(getxattr lgetxattr fgetxattr listxattr llistxattr) - AC_CHECK_FUNCS(flistxattr removexattr lremovexattr fremovexattr) - AC_CHECK_FUNCS(setxattr lsetxattr fsetxattr) - AC_CHECK_FUNCS(attr_get attr_list attr_set attr_remove) - AC_CHECK_FUNCS(attr_getf attr_listf attr_setf attr_removef) - ;; -esac - +AC_SEARCH_LIBS(getxattr, [attr]) +AC_CHECK_FUNCS(getxattr lgetxattr fgetxattr listxattr llistxattr) +AC_CHECK_FUNCS(flistxattr removexattr lremovexattr fremovexattr) +AC_CHECK_FUNCS(setxattr lsetxattr fsetxattr) +AC_CHECK_FUNCS(attr_get attr_list attr_set attr_remove) +AC_CHECK_FUNCS(attr_getf attr_listf attr_setf attr_removef) # Check if we have extattr case "$host_os" in *freebsd4* | *dragonfly* ) @@ -1471,7 +1460,7 @@ if test "$enable_shared" = "yes"; then *aix*) AC_DEFINE(AIX,1,[Whether the host os is aix]) BLDSHARED="true" LDSHFLAGS="-Wl,-bexpall,-bM:SRE,-bnoentry,-berok" - DYNEXP="-Wl,-brtl,-bexpall,-bbigtoc" + DYNEXP="-Wl,-brtl,-bexpall" PICFLAGS="-O2" if test "${GCC}" != "yes"; then ## for funky AIX compiler using strncpy() @@ -1639,11 +1628,7 @@ if test x"$samba_cv_HAVE_OFF64_T" = x"yes"; then fi AC_CACHE_CHECK([for 64 bit ino_t],samba_cv_SIZEOF_INO_T,[ -AC_TRY_RUN([ -#if defined(HAVE_UNISTD_H) -#include <unistd.h> -#endif -#include <stdio.h> +AC_TRY_RUN([#include <stdio.h> #include <sys/stat.h> main() { exit((sizeof(ino_t) == 8) ? 0 : 1); }], samba_cv_SIZEOF_INO_T=yes,samba_cv_SIZEOF_INO_T=no,samba_cv_SIZEOF_INO_T=cross)]) @@ -1664,19 +1649,6 @@ if test x"$samba_cv_HAVE_INO64_T" = x"yes"; then AC_DEFINE(HAVE_INO64_T,1,[Whether the 'ino64_t' type is available]) fi -AC_CACHE_CHECK([for 64 bit dev_t],samba_cv_SIZEOF_DEV_T,[ -AC_TRY_RUN([ -#if defined(HAVE_UNISTD_H) -#include <unistd.h> -#endif -#include <stdio.h> -#include <sys/stat.h> -main() { exit((sizeof(dev_t) == 8) ? 0 : 1); }], -samba_cv_SIZEOF_DEV_T=yes,samba_cv_SIZEOF_DEV_T=no,samba_cv_SIZEOF_DEV_T=cross)]) -if test x"$samba_cv_SIZEOF_DEV_T" = x"yes"; then - AC_DEFINE(SIZEOF_DEV_T,8,[The size of the 'dev_t' type]) -fi - AC_CACHE_CHECK([for dev64_t],samba_cv_HAVE_DEV64_T,[ AC_TRY_RUN([ #if defined(HAVE_UNISTD_H) @@ -2174,33 +2146,6 @@ if test x"$samba_cv_HAVE_KERNEL_CHANGE_NOTIFY" = x"yes"; then AC_DEFINE(HAVE_KERNEL_CHANGE_NOTIFY,1,[Whether kernel notifies changes]) fi -################################################# -# Check if FAM notifications are available. For FAM info, see -# http://oss.sgi.com/projects/fam/ -# http://savannah.nongnu.org/projects/fam/ - -AC_CHECK_HEADERS(fam.h, [samba_cv_HAVE_FAM_H=yes], [samba_cv_HAVE_FAM_H=no]) -if test x"$samba_cv_HAVE_FAM_H" = x"yes"; then - # On IRIX, libfam requires libC, but other FAM implementations might not - # need it. - AC_CHECK_LIB(fam, FAMOpen2, - [samba_cv_HAVE_LIBFAM=yes; samba_fam_libs="-lfam"], - [samba_cv_HAVE_LIBFAM=no]) - - if test x"$samba_cv_HAVE_LIBFAM" = x"no" ; then - samba_fam_xtra=-lC - AC_CHECK_LIB_EXT(fam, samba_fam_xtra, FAMOpen2, - [samba_cv_HAVE_LIBFAM=yes; samba_fam_libs="-lfam -lC"], - [samba_cv_HAVE_LIBFAM=no]) - unset samba_fam_xtra - fi -fi - -if test x"$samba_cv_HAVE_LIBFAM" = x"yes" ; then - AC_DEFINE(HAVE_FAM_CHANGE_NOTIFY, 1, - [Whether FAM is file notifications are available]) -fi - AC_CACHE_CHECK([for kernel share modes],samba_cv_HAVE_KERNEL_SHARE_MODES,[ AC_TRY_RUN([ #include <sys/types.h> @@ -2221,6 +2166,8 @@ if test x"$samba_cv_HAVE_KERNEL_SHARE_MODES" = x"yes"; then fi + + AC_CACHE_CHECK([for IRIX kernel oplock type definitions],samba_cv_HAVE_KERNEL_OPLOCKS_IRIX,[ AC_TRY_COMPILE([#include <sys/types.h> #include <fcntl.h>], @@ -4530,11 +4477,10 @@ AC_ARG_WITH(aio-support, AC_MSG_RESULT(yes) case "$host_os" in *) - AC_CHECK_LIB(rt,aio_read,[AIO_LIBS="$AIO_LIBS -lrt"]) - AC_CHECK_LIB(aio,aio_read,[AIO_LIBS="$AIO_LIBS -laio"]) + AC_CHECK_LIB(rt,aio_read,[AIO_LIBS="$ACL_LIBS -lrt"]) AC_CACHE_CHECK([for asynchronous io support],samba_cv_HAVE_AIO,[ aio_LIBS=$LIBS - LIBS=$AIO_LIBS + LIBS="$LIBS -lrt" AC_TRY_LINK([#include <sys/types.h> #include <aio.h>], [ struct aiocb a; return aio_read(&a);], @@ -4542,7 +4488,7 @@ samba_cv_HAVE_AIO=yes,samba_cv_HAVE_AIO=no) LIBS=$aio_LIBS]) AC_CACHE_CHECK([for 64-bit asynchronous io support],samba_cv_HAVE_AIO64,[ aio_LIBS=$LIBS - LIBS=$AIO_LIBS + LIBS="$LIBS -lrt" AC_TRY_LINK([#include <sys/types.h> #include <aio.h>], [ struct aiocb64 a; return aio_read64(&a);], @@ -4551,10 +4497,10 @@ samba_cv_HAVE_AIO64=yes,samba_cv_HAVE_AIO64=no) if test x"$samba_cv_HAVE_AIO64" = x"yes"; then AC_DEFINE(HAVE_AIOCB64,1,[Whether 64 bit aio is available]) AC_DEFINE(WITH_AIO, 1, [Using asynchronous io]) - LIBS=$AIO_LIBS + LIBS="$LIBS -lrt" elif test x"$samba_cv_HAVE_AIO" = x"yes"; then AC_DEFINE(WITH_AIO, 1, [Using asynchronous io]) - LIBS=$AIO_LIBS + LIBS="$LIBS -lrt" fi if test x"$samba_cv_HAVE_AIO" = x"yes"; then @@ -5185,10 +5131,10 @@ SMB_MODULE(rpc_samr, \$(RPC_SAMR_OBJ), "bin/librpc_samr.$SHLIBEXT", RPC) SMB_MODULE(rpc_echo, \$(RPC_ECHO_OBJ), "bin/librpc_echo.$SHLIBEXT", RPC) SMB_SUBSYSTEM(RPC,smbd/server.o) -SMB_MODULE(idmap_ldap, sam/idmap_ldap.o, "bin/ldap.$SHLIBEXT", IDMAP) -SMB_MODULE(idmap_tdb, sam/idmap_tdb.o, "bin/tdb.$SHLIBEXT", IDMAP) -SMB_MODULE(idmap_rid, sam/idmap_rid.o, "bin/rid.$SHLIBEXT", IDMAP) -SMB_MODULE(idmap_ad, sam/idmap_ad.o, "bin/ad.$SHLIBEXT", IDMAP) +SMB_MODULE(idmap_ldap, sam/idmap_ldap.o, "bin/idmap_ldap.$SHLIBEXT", IDMAP) +SMB_MODULE(idmap_tdb, sam/idmap_tdb.o, "bin/idmap_tdb.$SHLIBEXT", IDMAP) +SMB_MODULE(idmap_rid, sam/idmap_rid.o, "bin/idmap_rid.$SHLIBEXT", IDMAP) +SMB_MODULE(idmap_ad, sam/idmap_ad.o, "bin/idmap_ad.$SHLIBEXT", IDMAP) SMB_SUBSYSTEM(IDMAP,sam/idmap.o) SMB_MODULE(charset_weird, modules/weird.o, "bin/weird.$SHLIBEXT", CHARSET) @@ -5219,7 +5165,7 @@ SMB_MODULE(vfs_cap, \$(VFS_CAP_OBJ), "bin/cap.$SHLIBEXT", VFS) SMB_MODULE(vfs_expand_msdfs, \$(VFS_EXPAND_MSDFS_OBJ), "bin/expand_msdfs.$SHLIBEXT", VFS) SMB_MODULE(vfs_shadow_copy, \$(VFS_SHADOW_COPY_OBJ), "bin/shadow_copy.$SHLIBEXT", VFS) SMB_MODULE(vfs_afsacl, \$(VFS_AFSACL_OBJ), "bin/afsacl.$SHLIBEXT", VFS) -SMB_MODULE(vfs_catia, \$(VFS_CATIA_OBJ), "bin/catia.$SHLIBEXT", VFS) +SMB_MODULE(vfs_catia, \$(VFS_AFSACL_OBJ), "bin/catia.$SHLIBEXT", VFS) SMB_SUBSYSTEM(VFS,smbd/vfs.o) AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules]) @@ -5256,10 +5202,6 @@ AC_TRY_RUN([#include "${srcdir-.}/tests/summary.c"], builddir=`pwd` AC_SUBST(builddir) -# Stuff the FAM libraries at the end of the smbd link path (if we have them). -SMBD_LIBS="$samba_fam_libs" -AC_SUBST(SMBD_LIBS) - dnl Remove -L/usr/lib/? from LDFLAGS and LIBS LIB_REMOVE_USR_LIB(LDFLAGS) LIB_REMOVE_USR_LIB(LIBS) diff --git a/source/groupdb/mapping.c b/source/groupdb/mapping.c index 7dc0426c449..1e8586786cd 100644 --- a/source/groupdb/mapping.c +++ b/source/groupdb/mapping.c @@ -36,6 +36,45 @@ static TDB_CONTEXT *tdb; /* used for driver files */ #define MEMBEROF_PREFIX "MEMBEROF/" /**************************************************************************** +dump the mapping group mapping to a text file +****************************************************************************/ +char *decode_sid_name_use(fstring group, enum SID_NAME_USE name_use) +{ + static fstring group_type; + + switch(name_use) { + case SID_NAME_USER: + fstrcpy(group_type,"User"); + break; + case SID_NAME_DOM_GRP: + fstrcpy(group_type,"Domain group"); + break; + case SID_NAME_DOMAIN: + fstrcpy(group_type,"Domain"); + break; + case SID_NAME_ALIAS: + fstrcpy(group_type,"Local group"); + break; + case SID_NAME_WKN_GRP: + fstrcpy(group_type,"Builtin group"); + break; + case SID_NAME_DELETED: + fstrcpy(group_type,"Deleted"); + break; + case SID_NAME_INVALID: + fstrcpy(group_type,"Invalid"); + break; + case SID_NAME_UNKNOWN: + default: + fstrcpy(group_type,"Unknown type"); + break; + } + + fstrcpy(group, group_type); + return group_type; +} + +/**************************************************************************** initialise first time the mapping list - called from init_group_mapping() ****************************************************************************/ static BOOL default_group_mapping(void) @@ -366,6 +405,7 @@ static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **pp_rm { TDB_DATA kbuf, dbuf, newkey; fstring string_sid; + fstring group_type; GROUP_MAP map; GROUP_MAP *mapt; int ret; @@ -415,9 +455,8 @@ static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **pp_rm string_to_sid(&map.sid, string_sid); - DEBUG(11,("enum_group_mapping: returning group %s of " - "type %s\n", map.nt_name, - sid_type_lookup(map.sid_name_use))); + decode_sid_name_use(group_type, map.sid_name_use); + DEBUG(11,("enum_group_mapping: returning group %s of type %s\n", map.nt_name ,group_type)); mapt= SMB_REALLOC_ARRAY((*pp_rmap), GROUP_MAP, entries+1); if (!mapt) { @@ -887,6 +926,34 @@ BOOL get_builtin_group_from_sid(DOM_SID *sid, GROUP_MAP *map) return True; } + + +/**************************************************************************** +Returns a GROUP_MAP struct based on the gid. +****************************************************************************/ +BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map) +{ + BOOL ret; + + if(!init_group_mapping()) { + DEBUG(0,("failed to initialize group mapping\n")); + return(False); + } + + if ( getgrgid(gid) == NULL) + return False; + + become_root(); + ret = pdb_getgrgid(map, gid); + unbecome_root(); + + if ( !ret ) { + return False; + } + + return True; +} + /**************************************************************************** Create a UNIX group on demand. ****************************************************************************/ @@ -1099,22 +1166,11 @@ NTSTATUS pdb_default_create_alias(struct pdb_methods *methods, enum SID_NAME_USE type; uint32 new_rid; gid_t gid; - BOOL exists; - GROUP_MAP map; - - TALLOC_CTX *mem_ctx = talloc_new(NULL); - if (mem_ctx == NULL) { - return NT_STATUS_NO_MEMORY; - } - - exists = lookup_name(mem_ctx, name, LOOKUP_NAME_ISOLATED, - NULL, NULL, &sid, &type); - talloc_free(mem_ctx); + GROUP_MAP map; - if (exists) { + if (lookup_name(get_global_sam_name(), name, &sid, &type)) return NT_STATUS_ALIAS_EXISTS; - } if (!winbind_allocate_rid_and_gid(&new_rid, &gid)) return NT_STATUS_ACCESS_DENIED; diff --git a/source/include/auth.h b/source/include/auth.h index 03206c03c6a..f3dae1108b3 100644 --- a/source/include/auth.h +++ b/source/include/auth.h @@ -58,7 +58,7 @@ typedef struct auth_serversupplied_info { gid_t gid; /* This groups info is needed for when we become_user() for this uid */ - size_t n_groups; + int n_groups; gid_t *groups; /* NT group information taken from the info3 structure */ diff --git a/source/include/debug.h b/source/include/debug.h index b6fb50a9acb..99c96e6bb18 100644 --- a/source/include/debug.h +++ b/source/include/debug.h @@ -43,12 +43,6 @@ int Debug1( const char *, ... ) PRINTF_ATTRIBUTE(1,2); BOOL dbgtext( const char *, ... ) PRINTF_ATTRIBUTE(1,2); BOOL dbghdr( int level, const char *file, const char *func, int line ); -#if defined(sgi) && (_COMPILER_VERSION >= 730) -#pragma mips_frequency_hint NEVER Debug1 -#pragma mips_frequency_hint NEVER dbgtext -#pragma mips_frequency_hint NEVER dbghdr -#endif - extern XFILE *dbf; extern pstring debugf; diff --git a/source/include/includes.h b/source/include/includes.h index a9b792d5f67..6342925877c 100644 --- a/source/include/includes.h +++ b/source/include/includes.h @@ -880,6 +880,8 @@ extern int errno; /* Lists, trees, caching, database... */ #include "xfile.h" #include "intl.h" +#include "ubi_sLinkList.h" +#include "ubi_dLinkList.h" #include "dlinklist.h" #include "tdb/tdb.h" #include "tdb/spinlock.h" @@ -902,6 +904,10 @@ extern int errno; #include "util_getent.h" +#ifndef UBI_BINTREE_H +#include "ubi_Cache.h" +#endif /* UBI_BINTREE_H */ + #include "debugparse.h" #include "version.h" diff --git a/source/include/libsmb_internal.h b/source/include/libsmb_internal.h index 04264303288..081bb415e56 100644 --- a/source/include/libsmb_internal.h +++ b/source/include/libsmb_internal.h @@ -47,12 +47,11 @@ struct _SMBCFILE { struct smbc_internal_data { - /* - * Is this handle initialized ? + /** INTERNAL: is this handle initialized ? */ - BOOL _initialized; + int _initialized; - /* dirent pointer location + /** INTERNAL: dirent pointer location * * Leave room for any urlencoded filename and the comment field. * @@ -65,20 +64,13 @@ struct smbc_internal_data { */ char _dirent[1024]; - /* - * server connection list + /** INTERNAL: server connection list */ SMBCSRV * _servers; - /* - * open file/dir list + /** INTERNAL: open file/dir list */ SMBCFILE * _files; - - /* - * Log to standard error instead of the more typical standard output - */ - BOOL _debug_stderr; }; diff --git a/source/include/messages.h b/source/include/messages.h index 4b1732d42d1..abe219374ed 100644 --- a/source/include/messages.h +++ b/source/include/messages.h @@ -68,7 +68,6 @@ #define MSG_SMB_ASYNC_LEVEL2_BREAK 3008 #define MSG_SMB_OPEN_RETRY 3009 #define MSG_SMB_KERNEL_BREAK 3010 -#define MSG_SMB_FILE_RENAME 3011 /* winbind messages */ #define MSG_WINBIND_FINISHED 4001 diff --git a/source/include/nameserv.h b/source/include/nameserv.h index 9f6bf76a093..ec3d56c06b7 100644 --- a/source/include/nameserv.h +++ b/source/include/nameserv.h @@ -217,7 +217,7 @@ struct nmb_data { /* This structure represents an entry in a local netbios name list. */ struct name_record { - struct name_record *prev, *next; + ubi_trNode node[1]; struct subnet_record *subnet; struct nmb_name name; /* The netbios name. */ struct nmb_data data; /* The netbios data. */ @@ -225,7 +225,7 @@ struct name_record { /* Browser cache for synchronising browse lists. */ struct browse_cache_record { - struct browse_cache_record *prev, *next; + ubi_dlNode node[1]; unstring lmb_name; unstring work_group; struct in_addr ip; @@ -425,7 +425,7 @@ struct subnet_record { enum subnet_type type; /* To catagorize the subnet. */ struct work_record *workgrouplist; /* List of workgroups. */ - struct name_record *namelist; /* List of netbios names. */ + ubi_trRoot namelist[1]; /* List of netbios names. */ struct response_record *responselist; /* List of responses expected. */ BOOL namelist_changed; diff --git a/source/include/passdb.h b/source/include/passdb.h index f1896710dc9..0589b9a7cd4 100644 --- a/source/include/passdb.h +++ b/source/include/passdb.h @@ -200,6 +200,29 @@ typedef struct sam_passwd { } SAM_ACCOUNT; +typedef struct sam_group { + TALLOC_CTX *mem_ctx; + + void (*free_fn)(struct sam_group **); + + struct pdb_methods *methods; + + struct group_data { + /* initialization flags */ + struct bitmap *change_flags; + struct bitmap *set_flags; + + const char *name; /* Windows group name string */ + + DOM_SID sid; /* Group SID */ + enum SID_NAME_USE sid_name_use; /* Group type */ + + uint32 mem_num; /* Number of member SIDs */ + DOM_SID *members; /* SID array */ + } private_g; + +} SAM_GROUP; + struct acct_info { fstring acct_name; /* account name */ fstring acct_desc; /* account name */ @@ -353,13 +376,6 @@ typedef struct pdb_context const char **pp_names, uint32 *attrs); - NTSTATUS (*pdb_lookup_names)(struct pdb_context *context, - const DOM_SID *domain_sid, - size_t num_names, - const char **names, - uint32 *rids, - uint32 *attrs); - NTSTATUS (*pdb_get_account_policy)(struct pdb_context *context, int policy_index, uint32 *value); @@ -483,13 +499,6 @@ typedef struct pdb_methods const char **pp_names, uint32 *attrs); - NTSTATUS (*lookup_names)(struct pdb_methods *methods, - const DOM_SID *domain_sid, - int num_names, - const char **pp_names, - uint32 *rids, - uint32 *attrs); - NTSTATUS (*get_account_policy)(struct pdb_methods *methods, int policy_index, uint32 *value); diff --git a/source/include/smb.h b/source/include/smb.h index f899a71dc6d..b6f471c1a6f 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -172,9 +172,6 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN]; /* turn a 7 bit character into a ucs2 character */ #define UCS2_CHAR(c) ((c) << UCS2_SHIFT) -/* return an ascii version of a ucs2 character */ -#define UCS2_TO_CHAR(c) ((c) & 0xff) - /* Copy into a smb_ucs2_t from a possibly unaligned buffer. Return the copied smb_ucs2_t */ #define COPY_UCS2_CHAR(dest,src) (((unsigned char *)(dest))[0] = ((unsigned char *)(src))[0],\ ((unsigned char *)(dest))[1] = ((unsigned char *)(src))[1], (dest)) @@ -267,10 +264,6 @@ enum SID_NAME_USE SID_NAME_COMPUTER /* sid for a computer */ }; -#define LOOKUP_NAME_ISOLATED 1 /* Look up unqualified names */ -#define LOOKUP_NAME_REMOTE 2 /* Ask others */ -#define LOOKUP_NAME_ALL (LOOKUP_NAME_ISOLATED|LOOKUP_NAME_REMOTE) - /** * @brief Security Identifier * @@ -333,6 +326,49 @@ typedef struct _nt_user_token { SE_PRIV privileges; } NT_USER_TOKEN; +/*** query a local group, get a list of these: shows who is in that group ***/ + +/* local group member info */ +typedef struct local_grp_member_info +{ + DOM_SID sid ; /* matches with name */ + uint8 sid_use; /* usr=1 grp=2 dom=3 alias=4 wkng=5 del=6 inv=7 unk=8 */ + fstring name ; /* matches with sid: must be of the form "DOMAIN\account" */ + +} LOCAL_GRP_MEMBER; + +/* enumerate these to get list of local groups */ + +/* local group info */ +typedef struct local_grp_info +{ + fstring name; + fstring comment; + +} LOCAL_GRP; + +/*** enumerate these to get list of domain groups ***/ + +/* domain group member info */ +typedef struct domain_grp_info +{ + fstring name; + fstring comment; + uint32 rid; /* group rid */ + uint8 attr; /* attributes forced to be set to 0x7: SE_GROUP_xxx */ + +} DOMAIN_GRP; + +/*** query a domain group, get a list of these: shows who is in that group ***/ + +/* domain group info */ +typedef struct domain_grp_member_info +{ + fstring name; + uint8 attr; /* attributes forced to be set to 0x7: SE_GROUP_xxx */ + +} DOMAIN_GRP_MEMBER; + /* 32 bit time (sec) since 01jan1970 - cifs6.txt, section 3.5, page 30 */ typedef struct time_info { @@ -514,7 +550,7 @@ typedef struct connection_struct /* following groups stuff added by ih */ /* This groups info is valid for the user that *opened* the connection */ - size_t ngroups; + int ngroups; gid_t *groups; NT_USER_TOKEN *nt_user_token; @@ -619,9 +655,9 @@ struct share_mode_entry { struct process_id pid; uint16 op_mid; uint16 op_type; - uint32 access_mask; /* NTCreateX access bits (FILE_READ_DATA etc.) */ - uint32 share_access; /* NTCreateX share constants (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE). */ - uint32 private_options; /* NT Create options, but we only look at + uint32_t access_mask; /* NTCreateX access bits (FILE_READ_DATA etc.) */ + uint32_t share_access; /* NTCreateX share constants (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE). */ + uint32_t private_options; /* NT Create options, but we only look at * NTCREATEX_OPTIONS_PRIVATE_DENY_DOS and * NTCREATEX_OPTIONS_PRIVATE_DENY_FCB for * smbstatus and swat */ @@ -651,7 +687,6 @@ Offset Data length. #define MSG_SMB_SHARE_MODE_ENTRY_SIZE 48 struct share_mode_lock { - const char *servicepath; /* canonicalized. */ const char *filename; SMB_DEV_T dev; SMB_INO_T ino; @@ -1587,9 +1622,11 @@ struct pwd_info { BOOL cleartext; fstring password; + }; -typedef struct user_struct { +typedef struct user_struct +{ struct user_struct *next, *prev; uint16 vuid; /* Tag for this entry. */ uid_t uid; /* uid of a validated user */ diff --git a/source/include/smb_macros.h b/source/include/smb_macros.h index 41eac7e9942..e1bed76f5be 100644 --- a/source/include/smb_macros.h +++ b/source/include/smb_macros.h @@ -24,6 +24,12 @@ #ifndef _SMB_MACROS_H #define _SMB_MACROS_H +/* no ops to help reduce the diff between the current 3.0 and release branch */ + +#define toupper_ascii(x) toupper(x) +#define tolower_ascii(x) tolower(x) + + /* Misc bit macros */ #define BOOLSTR(b) ((b) ? "Yes" : "No") #define BITSETW(ptr,bit) ((SVAL(ptr,0) & (1<<(bit)))!=0) diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c index c4eeab135e9..4fbad0f3d18 100644 --- a/source/lib/charcnv.c +++ b/source/lib/charcnv.c @@ -84,6 +84,15 @@ static const char *charset_name(charset_t ch) } ret = ln; } +#ifdef HAVE_SETLOCALE + /* We set back the locale to C to get ASCII-compatible toupper/lower functions. + For now we do not need any other POSIX localisations anyway. When we should + really need localized string functions one day we need to write our own + ascii_tolower etc. + */ + setlocale(LC_ALL, "C"); + #endif + #endif if (!ret || !*ret) ret = "ASCII"; @@ -738,7 +747,7 @@ char *strdup_upper(const char *s) while (1) { if (*p & 0x80) break; - *q++ = toupper_ascii(*p); + *q++ = toupper(*p); if (!*p) break; p++; @@ -772,7 +781,7 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) smb_ucs2_t *buffer = NULL; size = convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, srclen, - (void **)(void *)&buffer, True); + (void **) &buffer, True); if (size == (size_t)-1 || !buffer) { smb_panic("failed to create UCS2 buffer"); } diff --git a/source/lib/replace.c b/source/lib/replace.c index 120fd3a4688..57ee6ea11e6 100644 --- a/source/lib/replace.c +++ b/source/lib/replace.c @@ -390,7 +390,7 @@ char *rep_inet_ntoa(struct in_addr ip) if (isdigit(c)) c -= '0'; else if (isalpha(c)) - c -= isupper_ascii(c) ? 'A' - 10 : 'a' - 10; + c -= isupper(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c index 609816b8774..a3ebe72df21 100644 --- a/source/lib/smbldap.c +++ b/source/lib/smbldap.c @@ -664,21 +664,21 @@ int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version) open a connection to the ldap server (just until the bind) ******************************************************************/ -int smb_ldap_setup_full_conn(LDAP **ldap_struct, const char *uri) +int smb_ldap_setup_full_conn(LDAP *ldap_struct, const char *uri) { int rc, version; - rc = smb_ldap_setup_conn(ldap_struct, uri); + rc = smb_ldap_setup_conn(&ldap_struct, uri); if (rc) { return rc; } - rc = smb_ldap_upgrade_conn(*ldap_struct, &version); + rc = smb_ldap_upgrade_conn(ldap_struct, &version); if (rc) { return rc; } - rc = smb_ldap_start_tls(*ldap_struct, version); + rc = smb_ldap_start_tls(ldap_struct, version); if (rc) { return rc; } diff --git a/source/lib/system_smbd.c b/source/lib/system_smbd.c index 6c65f61ad7a..1afd44b7091 100644 --- a/source/lib/system_smbd.c +++ b/source/lib/system_smbd.c @@ -190,8 +190,8 @@ static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grp return retval; } -static BOOL getgroups_user(const char *user, gid_t primary_gid, - gid_t **ret_groups, size_t *p_ngroups) +BOOL getgroups_user(const char *user, gid_t primary_gid, + gid_t **ret_groups, size_t *p_ngroups) { size_t ngrp; int max_grp; diff --git a/source/lib/username.c b/source/lib/username.c index 7d66b320adf..4dd5b5f7ce7 100644 --- a/source/lib/username.c +++ b/source/lib/username.c @@ -35,6 +35,34 @@ static BOOL name_is_local(const char *name) return !(strchr_m(name, *lp_winbind_separator())); } +/***************************************************************** + Splits passed user or group name to domain and user/group name parts + Returns True if name was splitted and False otherwise. +*****************************************************************/ + +BOOL split_domain_and_name(const char *name, char *domain, char* username) +{ + char *p = strchr(name,*lp_winbind_separator()); + + + /* Parse a string of the form DOMAIN/user into a domain and a user */ + DEBUG(10,("split_domain_and_name: checking whether name |%s| local or not\n", name)); + + if (p) { + fstrcpy(username, p+1); + fstrcpy(domain, name); + domain[PTR_DIFF(p, name)] = 0; + } else if (lp_winbind_use_default_domain()) { + fstrcpy(username, name); + fstrcpy(domain, lp_workgroup()); + } else { + return False; + } + + DEBUG(10,("split_domain_and_name: all is fine, domain is |%s| and name is |%s|\n", domain, username)); + return True; +} + /**************************************************************************** Get a users home directory. ****************************************************************************/ @@ -669,7 +697,7 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups, if ( winbind_lookup_name(domain, groupname, &g_sid, &name_type) - && ( name_type==SID_NAME_DOM_GRP || + && ( name_type==SID_NAME_DOM_GRP || (strequal(lp_workgroup(), domain) && name_type==SID_NAME_ALIAS) ) ) { @@ -716,9 +744,9 @@ static struct passwd *uname_string_combinations2(char *s,int offset,struct passw for (i=offset;i<(len-(N-1));i++) { char c = s[i]; - if (!islower_ascii((int)c)) + if (!islower((int)c)) continue; - s[i] = toupper_ascii(c); + s[i] = toupper(c); ret = uname_string_combinations2(s,i+1,fn,N-1); if(ret) return(ret); diff --git a/source/lib/util_getent.c b/source/lib/util_getent.c index 7c045fccb22..475b0da87bf 100644 --- a/source/lib/util_getent.c +++ b/source/lib/util_getent.c @@ -239,37 +239,6 @@ static struct sys_userlist *add_members_to_userlist(struct sys_userlist *list_he return list_head; } -/***************************************************************** - Splits passed user or group name to domain and user/group name parts - Returns True if name was splitted and False otherwise. -*****************************************************************/ - -static BOOL split_domain_and_name(const char *name, char *domain, - char* username) -{ - char *p = strchr(name,*lp_winbind_separator()); - - - /* Parse a string of the form DOMAIN/user into a domain and a user */ - DEBUG(10,("split_domain_and_name: checking whether name |%s| local or " - "not\n", name)); - - if (p) { - fstrcpy(username, p+1); - fstrcpy(domain, name); - domain[PTR_DIFF(p, name)] = 0; - } else if (lp_winbind_use_default_domain()) { - fstrcpy(username, name); - fstrcpy(domain, lp_workgroup()); - } else { - return False; - } - - DEBUG(10,("split_domain_and_name: all is fine, domain is |%s| and " - "name is |%s|\n", domain, username)); - return True; -} - /**************************************************************** Get the list of UNIX users in a group. We have to enumerate the /etc/group file as some UNIX getgrnam() diff --git a/source/lib/util_sid.c b/source/lib/util_sid.c index e2b2ebf28ca..4c274b5e01d 100644 --- a/source/lib/util_sid.c +++ b/source/lib/util_sid.c @@ -75,14 +75,11 @@ const DOM_SID global_sid_Builtin_Backup_Operators = /* Builtin backup operators const DOM_SID global_sid_Builtin_Replicator = /* Builtin replicator */ { 1, 2, {0,0,0,0,0,5}, {32,552,0,0,0,0,0,0,0,0,0,0,0,0,0}}; -/* Unused, left here for documentary purposes */ -#if 0 #define SECURITY_NULL_SID_AUTHORITY 0 #define SECURITY_WORLD_SID_AUTHORITY 1 #define SECURITY_LOCAL_SID_AUTHORITY 2 #define SECURITY_CREATOR_SID_AUTHORITY 3 #define SECURITY_NT_AUTHORITY 5 -#endif /* * An NT compatible anonymous token. @@ -156,6 +153,59 @@ const char *get_global_sam_name(void) return global_myname(); } +/************************************************************************** + Splits a name of format \DOMAIN\name or name into its two components. + Sets the DOMAIN name to global_myname() if it has not been specified. +***************************************************************************/ + +void split_domain_name(const char *fullname, char *domain, char *name) +{ + pstring full_name; + const char *sep; + char *p; + + sep = lp_winbind_separator(); + + *domain = *name = '\0'; + + if (fullname[0] == sep[0] || fullname[0] == '\\') + fullname++; + + pstrcpy(full_name, fullname); + p = strchr_m(full_name+1, '\\'); + if (!p) p = strchr_m(full_name+1, sep[0]); + + if (p != NULL) { + *p = 0; + fstrcpy(domain, full_name); + fstrcpy(name, p+1); + } else { + fstrcpy(domain, get_global_sam_name()); + fstrcpy(name, full_name); + } + + DEBUG(10,("split_domain_name:name '%s' split into domain :'%s' and user :'%s'\n", + fullname, domain, name)); +} + +/**************************************************************************** + Test if a SID is wellknown and resolvable. +****************************************************************************/ + +BOOL resolvable_wellknown_sid(DOM_SID *sid) +{ + uint32 ia = (sid->id_auth[5]) + + (sid->id_auth[4] << 8 ) + + (sid->id_auth[3] << 16) + + (sid->id_auth[2] << 24); + + if (sid->sid_rev_num != SEC_DESC_REVISION || sid->num_auths < 1) + return False; + + return (ia == SECURITY_WORLD_SID_AUTHORITY || + ia == SECURITY_CREATOR_SID_AUTHORITY); +} + /***************************************************************** Convert a SID to an ascii string. *****************************************************************/ @@ -213,7 +263,7 @@ BOOL string_to_sid(DOM_SID *sidout, const char *sidstr) uint32 conv; if ((sidstr[0] != 'S' && sidstr[0] != 's') || sidstr[1] != '-') { - DEBUG(3,("string_to_sid: Sid %s does not start with 'S-'.\n", sidstr)); + DEBUG(0,("string_to_sid: Sid %s does not start with 'S-'.\n", sidstr)); return False; } @@ -223,7 +273,7 @@ BOOL string_to_sid(DOM_SID *sidout, const char *sidstr) p = sidstr + 2; conv = (uint32) strtoul(p, &q, 10); if (!q || (*q != '-')) { - DEBUG(3,("string_to_sid: Sid %s is not in a valid format.\n", sidstr)); + DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr)); return False; } sidout->sid_rev_num = (uint8) conv; @@ -483,6 +533,30 @@ BOOL sid_equal(const DOM_SID *sid1, const DOM_SID *sid2) } /***************************************************************** + Check if the SID is the builtin SID (S-1-5-32). +*****************************************************************/ + +BOOL sid_check_is_builtin(const DOM_SID *sid) +{ + return sid_equal(sid, &global_sid_Builtin); +} + +/***************************************************************** + Check if the SID is one of the builtin SIDs (S-1-5-32-a). +*****************************************************************/ + +BOOL sid_check_is_in_builtin(const DOM_SID *sid) +{ + DOM_SID dom_sid; + uint32 rid; + + sid_copy(&dom_sid, sid); + sid_split_rid(&dom_sid, &rid); + + return sid_equal(&dom_sid, &global_sid_Builtin); +} + +/***************************************************************** Calculates size of a sid. *****************************************************************/ @@ -619,9 +693,3 @@ void del_sid_from_array(const DOM_SID *sid, DOM_SID **sids, size_t *num) return; } - -BOOL is_null_sid(const DOM_SID *sid) -{ - static const DOM_SID null_sid = {0}; - return sid_equal(sid, &null_sid); -} diff --git a/source/lib/util_smbd.c b/source/lib/util_smbd.c new file mode 100644 index 00000000000..c6f6bc0a32a --- /dev/null +++ b/source/lib/util_smbd.c @@ -0,0 +1,86 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions, used in smbd only + Copyright (C) Andrew Tridgell 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + This function requires sys_getgrouplist - which is only + available in smbd due to it's use of become_root() in a + legacy systems hack. +*/ + +/* + return a full list of groups for a user + + returns the number of groups the user is a member of. The return will include the + users primary group. + + remember to free the resulting gid_t array + + NOTE! uses become_root() to gain correct priviages on systems + that lack a native getgroups() call (uses initgroups and getgroups) +*/ +BOOL getgroups_user(const char *user, gid_t primary_gid, gid_t **ret_groups, int *ngroups) +{ + int ngrp, max_grp; + gid_t *temp_groups; + gid_t *groups; + int i; + + max_grp = groups_max(); + temp_groups = SMB_MALLOC_ARRAY(gid_t, max_grp); + if (! temp_groups) { + return False; + } + + if (sys_getgrouplist(user, primary_gid, temp_groups, &max_grp) == -1) { + + gid_t *groups_tmp; + + groups_tmp = SMB_REALLOC_ARRAY(temp_groups, gid_t, max_grp); + + if (!groups_tmp) { + SAFE_FREE(temp_groups); + return False; + } + temp_groups = groups_tmp; + + if (sys_getgrouplist(user, primary_gid, temp_groups, &max_grp) == -1) { + DEBUG(0, ("get_user_groups: failed to get the unix group list\n")); + SAFE_FREE(temp_groups); + return False; + } + } + + ngrp = 0; + groups = NULL; + + /* Add in primary group first */ + add_gid_to_array_unique(NULL, primary_gid, &groups, &ngrp); + + for (i=0; i<max_grp; i++) + add_gid_to_array_unique(NULL, temp_groups[i], &groups, &ngrp); + + *ngroups = ngrp; + *ret_groups = groups; + SAFE_FREE(temp_groups); + return True; +} + diff --git a/source/lib/util_str.c b/source/lib/util_str.c index 0b02487f774..9b14dcfaf0f 100644 --- a/source/lib/util_str.c +++ b/source/lib/util_str.c @@ -201,8 +201,8 @@ int StrCaseCmp(const char *s, const char *t) /* not ascii anymore, do it the hard way from here on in */ break; - us = toupper_ascii(*ps); - ut = toupper_ascii(*pt); + us = toupper(*ps); + ut = toupper(*pt); if (us == ut) continue; else if (us < ut) @@ -309,7 +309,7 @@ int strwicmp(const char *psz1, const char *psz2) psz1++; while (isspace((int)*psz2)) psz2++; - if (toupper_ascii(*psz1) != toupper_ascii(*psz2) || *psz1 == '\0' + if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0') break; psz1++; @@ -680,7 +680,7 @@ char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, con for(i = 0; i < len; i++) { int val = (src[i] & 0xff); - if (isupper_ascii(val) || islower_ascii(val) || isdigit(val) || strchr_m(other_safe_chars, val)) + if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val)) dest[i] = src[i]; else dest[i] = '_'; @@ -774,12 +774,12 @@ size_t strhex_to_str(char *p, size_t len, const char *strhex) continue; } - if (!(p1 = strchr_m(hexchars, toupper_ascii(strhex[i])))) + if (!(p1 = strchr_m(hexchars, toupper(strhex[i])))) break; i++; /* next hex digit */ - if (!(p2 = strchr_m(hexchars, toupper_ascii(strhex[i])))) + if (!(p2 = strchr_m(hexchars, toupper(strhex[i])))) break; /* get the two nybbles */ @@ -1003,8 +1003,7 @@ void pstring_sub(char *s,const char *pattern,const char *insert) as string. **/ -char *realloc_string_sub(char *string, const char *pattern, - const char *insert) +char *realloc_string_sub(char *string, const char *pattern, const char *insert) { char *p, *in; char *s; @@ -1064,77 +1063,6 @@ char *realloc_string_sub(char *string, const char *pattern, return string; } -/* Same as string_sub, but returns a talloc'ed string */ - -char *talloc_string_sub(TALLOC_CTX *mem_ctx, const char *src, - const char *pattern, const char *insert) -{ - char *p, *in; - char *s; - char *string; - ssize_t ls,lp,li,ld, i; - - if (!insert || !pattern || !*pattern || !src || !*src) - return NULL; - - string = talloc_strdup(mem_ctx, src); - if (string == NULL) { - DEBUG(0, ("talloc_strdup failed\n")); - return NULL; - } - - s = string; - - in = SMB_STRDUP(insert); - if (!in) { - DEBUG(0, ("talloc_string_sub: out of memory!\n")); - return NULL; - } - ls = (ssize_t)strlen(s); - lp = (ssize_t)strlen(pattern); - li = (ssize_t)strlen(insert); - ld = li - lp; - for (i=0;i<li;i++) { - switch (in[i]) { - case '`': - case '"': - case '\'': - case ';': - case '$': - case '%': - case '\r': - case '\n': - in[i] = '_'; - default: - /* ok */ - break; - } - } - - while ((p = strstr_m(s,pattern))) { - if (ld > 0) { - int offset = PTR_DIFF(s,string); - char *t = TALLOC_REALLOC(mem_ctx, string, ls + ld + 1); - if (!t) { - DEBUG(0, ("talloc_string_sub: out of " - "memory!\n")); - SAFE_FREE(in); - return NULL; - } - string = t; - p = t + offset + (p - s); - } - if (li != lp) { - memmove(p+li,p+lp,strlen(p+lp)+1); - } - memcpy(p, in, li); - s = p + li; - ls += ld; - } - SAFE_FREE(in); - return string; -} - /** Similar to string_sub() but allows for any character to be substituted. Use with caution! @@ -1510,7 +1438,7 @@ void strlower_m(char *s) (ie. they match for the first 128 chars) */ while (*s && !(((unsigned char)s[0]) & 0x80)) { - *s = tolower_ascii((unsigned char)*s); + *s = tolower((unsigned char)*s); s++; } @@ -1544,7 +1472,7 @@ void strupper_m(char *s) (ie. they match for the first 128 chars) */ while (*s && !(((unsigned char)s[0]) & 0x80)) { - *s = toupper_ascii((unsigned char)*s); + *s = toupper((unsigned char)*s); s++; } diff --git a/source/lib/util_unistr.c b/source/lib/util_unistr.c index 880416a5491..b979745d366 100644 --- a/source/lib/util_unistr.c +++ b/source/lib/util_unistr.c @@ -51,7 +51,6 @@ static uint8 doschar_table[8192]; /* 65536 characters / 8 bits/byte */ void load_case_tables(void) { static int initialised; - char *old_locale = NULL, *saved_locale = NULL; int i; if (initialised) { @@ -62,17 +61,6 @@ void load_case_tables(void) upcase_table = map_file(lib_path("upcase.dat"), 0x20000); lowcase_table = map_file(lib_path("lowcase.dat"), 0x20000); -#ifdef HAVE_SETLOCALE - /* Get the name of the current locale. */ - old_locale = setlocale(LC_ALL, NULL); - - /* Save it as it is in static storage. */ - saved_locale = SMB_STRDUP(old_locale); - - /* We set back the locale to C to get ASCII-compatible toupper/lower functions. */ - setlocale(LC_ALL, "C"); -#endif - /* we would like Samba to limp along even if these tables are not available */ if (!upcase_table) { @@ -104,12 +92,6 @@ void load_case_tables(void) lowcase_table[v] = UCS2_CHAR(isupper(i)?tolower(i):i); } } - -#ifdef HAVE_SETLOCALE - /* Restore the old locale. */ - setlocale (LC_ALL, saved_locale); - SAFE_FREE(saved_locale); -#endif } /* @@ -1015,41 +997,3 @@ UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src) return dst; } - -/************************************************************* - ascii only toupper - saves the need for smbd to be in C locale. -*************************************************************/ - -int toupper_ascii(int c) -{ - smb_ucs2_t uc = toupper_w(UCS2_CHAR(c)); - return UCS2_TO_CHAR(uc); -} - -/************************************************************* - ascii only tolower - saves the need for smbd to be in C locale. -*************************************************************/ - -int tolower_ascii(int c) -{ - smb_ucs2_t uc = tolower_w(UCS2_CHAR(c)); - return UCS2_TO_CHAR(uc); -} - -/************************************************************* - ascii only isupper - saves the need for smbd to be in C locale. -*************************************************************/ - -int isupper_ascii(int c) -{ - return isupper_w(UCS2_CHAR(c)); -} - -/************************************************************* - ascii only islower - saves the need for smbd to be in C locale. -*************************************************************/ - -int islower_ascii(int c) -{ - return islower_w(UCS2_CHAR(c)); -} diff --git a/source/lib/version.c b/source/lib/version.c index 3bd8304012c..99f836c2d5b 100644 --- a/source/lib/version.c +++ b/source/lib/version.c @@ -27,7 +27,6 @@ const char *samba_version_string(void) return SAMBA_VERSION_OFFICIAL_STRING; #else static fstring samba_version; - fstring tmp_version; static BOOL init_samba_version; if (init_samba_version) @@ -37,11 +36,6 @@ const char *samba_version_string(void) SAMBA_VERSION_OFFICIAL_STRING, SAMBA_VERSION_VENDOR_SUFFIX); -#ifdef SAMBA_VENDOR_PATCH - fstr_sprintf( tmp_version, "-%d", SAMBA_VENDOR_PATCH ); - fstrcat( samba_version, tmp_version ); -#endif - init_samba_version = True; return samba_version; #endif diff --git a/source/libsmb/clilist.c b/source/libsmb/clilist.c index 48780e28dfa..252dafcfa8b 100644 --- a/source/libsmb/clilist.c +++ b/source/libsmb/clilist.c @@ -169,7 +169,11 @@ static size_t interpret_long_filename(struct cli_state *cli, int level,char *p,f int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, void (*fn)(const char *, file_info *, const char *, void *), void *state) { - int max_matches = 1366; +#if 1 + int max_matches = 1366; /* Match W2k - was 512. */ +#else + int max_matches = 512; +#endif int info_level; char *p, *p2; pstring mask; diff --git a/source/libsmb/climessage.c b/source/libsmb/climessage.c index 1aa659c1ba3..f646096a4e5 100644 --- a/source/libsmb/climessage.c +++ b/source/libsmb/climessage.c @@ -85,7 +85,7 @@ int cli_message_text_build(struct cli_state *cli, char *msg, int len, int grp) p = smb_buf(cli->outbuf); *p++ = 1; - if ((lendos = (int)convert_string_allocate(NULL,CH_UNIX, CH_DOS, msg,len, (void **)(void *)&msgdos, True)) < 0 || !msgdos) { + if ((lendos = (int)convert_string_allocate(NULL,CH_UNIX, CH_DOS, msg,len, (void **) &msgdos, True)) < 0 || !msgdos) { DEBUG(3,("Conversion failed, sending message in UNIX charset\n")); SSVAL(p, 0, len); p += 2; memcpy(p, msg, len); diff --git a/source/libsmb/clirap.c b/source/libsmb/clirap.c index 6716971fe2c..172dea4090a 100644 --- a/source/libsmb/clirap.c +++ b/source/libsmb/clirap.c @@ -592,18 +592,18 @@ BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname, if (!rdata || data_len < 22) { return False; } - + if (c_time) { *c_time = interpret_long_date(rdata+0); } if (a_time) { *a_time = interpret_long_date(rdata+8); } - if (w_time) { - *w_time = interpret_long_date(rdata+16); - } if (m_time) { - *m_time = interpret_long_date(rdata+24); + *m_time = interpret_long_date(rdata+16); + } + if (w_time) { + *w_time = interpret_long_date(rdata+24); } if (mode) { *mode = SVAL(rdata, 32); diff --git a/source/libsmb/libsmbclient.c b/source/libsmb/libsmbclient.c index 51f94e42e37..15210664b07 100644 --- a/source/libsmb/libsmbclient.c +++ b/source/libsmb/libsmbclient.c @@ -82,15 +82,11 @@ static int DLIST_CONTAINS(SMBCFILE * list, SMBCFILE *p) { /* * Find an lsa pipe handle associated with a cli struct. */ -static struct rpc_pipe_client * -find_lsa_pipe_hnd(struct cli_state *ipc_cli) +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) { - + for (pipe_hnd = ipc_cli->pipe_list; pipe_hnd; pipe_hnd = pipe_hnd->next) { if (pipe_hnd->pipe_idx == PI_LSARPC) { return pipe_hnd; } @@ -99,14 +95,8 @@ find_lsa_pipe_hnd(struct cli_state *ipc_cli) 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); +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; @@ -325,9 +315,7 @@ smbc_parse_path(SMBCCTX *context, if (*p == '/') { strncpy(server, context->workgroup, - ((strlen(context->workgroup) < 16) - ? strlen(context->workgroup) - : 16)); + (strlen(context->workgroup) < 16)?strlen(context->workgroup):16); return 0; } @@ -408,15 +396,9 @@ smbc_parse_path(SMBCCTX *context, /* * Verify that the options specified in a URL are valid */ -static int -smbc_check_options(char *server, - char *share, - char *path, - char *options) +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)); + 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; @@ -428,9 +410,7 @@ smbc_check_options(char *server, /* * Convert an SMB error into a UNIX error ... */ -static int -smbc_errno(SMBCCTX *context, - struct cli_state *c) +static int smbc_errno(SMBCCTX *context, struct cli_state *c) { int ret = cli_errno(c); @@ -461,9 +441,7 @@ smbc_errno(SMBCCTX *context, * Also useable outside libsmbclient to enable external cache * to do some checks too. */ -static int -smbc_check_server(SMBCCTX * context, - SMBCSRV * server) +int smbc_check_server(SMBCCTX * context, SMBCSRV * server) { if ( send_keepalive(server->cli.fd) == False ) return 1; @@ -478,9 +456,7 @@ smbc_check_server(SMBCCTX * context, * * Also useable outside libsmbclient */ -int -smbc_remove_unused_server(SMBCCTX * context, - SMBCSRV * srv) +int smbc_remove_unused_server(SMBCCTX * context, SMBCSRV * srv) { SMBCFILE * file; @@ -493,8 +469,7 @@ smbc_remove_unused_server(SMBCCTX * context, 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", + DEBUG(3, ("smbc_remove_usused_server: %p still used by %p.\n", srv, file)); return 1; } @@ -513,13 +488,12 @@ smbc_remove_unused_server(SMBCCTX * context, return 0; } -static SMBCSRV * -find_server(SMBCCTX *context, - const char *server, - const char *share, - fstring workgroup, - fstring username, - fstring password) +SMBCSRV *find_server(SMBCCTX *context, + const char *server, + const char *share, + fstring workgroup, + fstring username, + fstring password) { SMBCSRV *srv; int auth_called = 0; @@ -587,14 +561,10 @@ find_server(SMBCCTX *context, * info we need, unless the username and password were passed in. */ -static SMBCSRV * -smbc_server(SMBCCTX *context, - BOOL connect_if_not_found, - const char *server, - const char *share, - fstring workgroup, - fstring username, - fstring password) +SMBCSRV *smbc_server(SMBCCTX *context, + const char *server, const char *share, + fstring workgroup, fstring username, + fstring password) { SMBCSRV *srv=NULL; struct cli_state c; @@ -645,18 +615,13 @@ smbc_server(SMBCCTX *context, errno = smbc_errno(context, &srv->cli); cli_shutdown(&srv->cli); - context->callbacks.remove_cached_srv_fn(context, - srv); + context->callbacks.remove_cached_srv_fn(context, srv); srv = NULL; } - /* - * Regenerate the dev value since it's based on both - * server and share - */ + /* 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)); + srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share)); } } } @@ -668,12 +633,6 @@ smbc_server(SMBCCTX *context, 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; - } - make_nmb_name(&calling, context->netbios_name, 0x0); make_nmb_name(&called , server, 0x20); @@ -852,14 +811,11 @@ smbc_server(SMBCCTX *context, * Connect to a server for getting/setting attributes, possibly on an existing * connection. This works similarly to smbc_server(). */ -static SMBCSRV * -smbc_attr_server(SMBCCTX *context, - const char *server, - const char *share, - fstring workgroup, - fstring username, - fstring password, - POLICY_HND *pol) +SMBCSRV *smbc_attr_server(SMBCCTX *context, + const char *server, const char *share, + fstring workgroup, + fstring username, fstring password, + POLICY_HND *pol) { struct in_addr ip; struct cli_state *ipc_cli; @@ -971,15 +927,11 @@ smbc_attr_server(SMBCCTX *context, * Routine to open() a file ... */ -static SMBCFILE * -smbc_open_ctx(SMBCCTX *context, - const char *fname, - int flags, - mode_t mode) +static SMBCFILE *smbc_open_ctx(SMBCCTX *context, const char *fname, int flags, mode_t mode) { fstring server, share, user, password, workgroup; pstring path; - pstring targetpath; + pstring targetpath; struct cli_state *targetcli; SMBCSRV *srv = NULL; SMBCFILE *file = NULL; @@ -1015,8 +967,7 @@ smbc_open_ctx(SMBCCTX *context, fstrcpy(workgroup, context->workgroup); - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { @@ -1137,10 +1088,7 @@ smbc_open_ctx(SMBCCTX *context, 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) +static SMBCFILE *smbc_creat_ctx(SMBCCTX *context, const char *path, mode_t mode) { if (!context || !context->internal || @@ -1158,11 +1106,7 @@ smbc_creat_ctx(SMBCCTX *context, * Routine to read() a file ... */ -static ssize_t -smbc_read_ctx(SMBCCTX *context, - SMBCFILE *file, - void *buf, - size_t count) +static ssize_t smbc_read_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_t count) { int ret; fstring server, share, user, password; @@ -1219,8 +1163,7 @@ smbc_read_ctx(SMBCCTX *context, } /*d_printf(">>>read: resolving %s\n", path);*/ - if (!cli_resolve_path("", &file->srv->cli, path, - &targetcli, targetpath)) + if (!cli_resolve_path( "", &file->srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); return -1; @@ -1248,20 +1191,14 @@ smbc_read_ctx(SMBCCTX *context, * Routine to write() a file ... */ -static ssize_t -smbc_write_ctx(SMBCCTX *context, - SMBCFILE *file, - void *buf, - size_t count) +static ssize_t smbc_write_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_t count) { int ret; - off_t offset; + off_t offset = file->offset; /* See "offset" comment in smbc_read_ctx() */ fstring server, share, user, password; pstring path, targetpath; struct cli_state *targetcli; - offset = file->offset; /* See "offset" comment in smbc_read_ctx() */ - if (!context || !context->internal || !context->internal->_initialized) { @@ -1299,8 +1236,7 @@ smbc_write_ctx(SMBCCTX *context, } /*d_printf(">>>write: resolving %s\n", path);*/ - if (!cli_resolve_path("", &file->srv->cli, path, - &targetcli, targetpath)) + if (!cli_resolve_path( "", &file->srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); return -1; @@ -1326,9 +1262,7 @@ smbc_write_ctx(SMBCCTX *context, * Routine to close() a file ... */ -static int -smbc_close_ctx(SMBCCTX *context, - SMBCFILE *file) +static int smbc_close_ctx(SMBCCTX *context, SMBCFILE *file) { SMBCSRV *srv; fstring server, share, user, password; @@ -1370,8 +1304,7 @@ smbc_close_ctx(SMBCCTX *context, } /*d_printf(">>>close: resolving %s\n", path);*/ - if (!cli_resolve_path("", &file->srv->cli, path, - &targetcli, targetpath)) + if (!cli_resolve_path( "", &file->srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); return -1; @@ -1406,21 +1339,14 @@ smbc_close_ctx(SMBCCTX *context, * 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, - time_t *c_time, - time_t *a_time, - time_t *m_time, - SMB_INO_T *ino) +static BOOL smbc_getatr(SMBCCTX * context, SMBCSRV *srv, char *path, + uint16 *mode, SMB_OFF_T *size, + time_t *c_time, time_t *a_time, time_t *m_time, + SMB_INO_T *ino) { pstring fixedpath; pstring targetpath; struct cli_state *targetcli; - if (!context || !context->internal || !context->internal->_initialized) { @@ -1450,15 +1376,12 @@ smbc_getatr(SMBCCTX * context, { pstring temppath; pstrcpy(temppath, targetpath); - cli_dfs_make_full_path(targetpath, targetcli->desthost, - targetcli->share, temppath); + cli_dfs_make_full_path( targetpath, targetcli->desthost, targetcli->share, temppath); } if (!srv->no_pathinfo2 && - cli_qpathinfo2(targetcli, targetpath, - c_time, a_time, m_time, NULL, size, mode, ino)) { - return True; - } + cli_qpathinfo2(targetcli, targetpath, c_time, a_time, m_time, NULL, + size, mode, ino)) return True; /* if this is NT then don't bother with the getatr */ if (targetcli->capabilities & CAP_NT_SMBS) { @@ -1490,10 +1413,9 @@ smbc_getatr(SMBCCTX * context, * * "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 c_time, time_t a_time, time_t m_time, - uint16 mode) +static BOOL smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, + time_t c_time, time_t a_time, time_t m_time, + uint16 mode) { int fd; int ret; @@ -1620,9 +1542,7 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, * Routine to unlink() a file */ -static int -smbc_unlink_ctx(SMBCCTX *context, - const char *fname) + static int smbc_unlink_ctx(SMBCCTX *context, const char *fname) { fstring server, share, user, password, workgroup; pstring path, targetpath; @@ -1659,8 +1579,7 @@ smbc_unlink_ctx(SMBCCTX *context, fstrcpy(workgroup, context->workgroup); - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { @@ -1719,27 +1638,12 @@ smbc_unlink_ctx(SMBCCTX *context, * Routine to rename() a file */ -static int -smbc_rename_ctx(SMBCCTX *ocontext, - const char *oname, - SMBCCTX *ncontext, - const char *nname) +static int smbc_rename_ctx(SMBCCTX *ocontext, const char *oname, + SMBCCTX *ncontext, const char *nname) { - fstring server1; - fstring share1; - fstring server2; - fstring share2; - fstring user1; - fstring user2; - fstring password1; - fstring password2; - fstring workgroup; - pstring path1; - pstring path2; - pstring targetpath1; - pstring targetpath2; - struct cli_state *targetcli1; - struct cli_state *targetcli2; + fstring server1, share1, server2, share2, user1, user2, password1, password2, workgroup; + pstring path1, path2, targetpath1, targetpath2; + struct cli_state *targetcli1, *targetcli2; SMBCSRV *srv = NULL; if (!ocontext || !ncontext || @@ -1792,9 +1696,8 @@ smbc_rename_ctx(SMBCCTX *ocontext, } fstrcpy(workgroup, ocontext->workgroup); - - srv = smbc_server(ocontext, True, - server1, share1, workgroup, user1, password1); + /* HELP !!! Which workgroup should I use ? Or are they always the same -- Tom */ + srv = smbc_server(ocontext, server1, share1, workgroup, user1, password1); if (!srv) { return -1; @@ -1816,8 +1719,7 @@ smbc_rename_ctx(SMBCCTX *ocontext, } /*d_printf(">>>rename: resolved path as %s\n", targetpath2);*/ - if (strcmp(targetcli1->desthost, targetcli2->desthost) || - strcmp(targetcli1->share, targetcli2->share)) + if (strcmp(targetcli1->desthost, targetcli2->desthost) || strcmp(targetcli1->share, targetcli2->share)) { /* can't rename across file systems */ @@ -1846,11 +1748,7 @@ smbc_rename_ctx(SMBCCTX *ocontext, * A routine to lseek() a file */ -static off_t -smbc_lseek_ctx(SMBCCTX *context, - SMBCFILE *file, - off_t offset, - int whence) +static off_t smbc_lseek_ctx(SMBCCTX *context, SMBCFILE *file, off_t offset, int whence) { SMB_OFF_T size; fstring server, share, user, password; @@ -1891,32 +1789,30 @@ smbc_lseek_ctx(SMBCCTX *context, case SEEK_END: /*d_printf(">>>lseek: parsing %s\n", file->fname);*/ if (smbc_parse_path(context, file->fname, - server, sizeof(server), - share, sizeof(share), - path, sizeof(path), - user, sizeof(user), - password, sizeof(password), - NULL, 0)) { - + server, sizeof(server), + share, sizeof(share), + path, sizeof(path), + user, sizeof(user), + password, sizeof(password), + NULL, 0)) { errno = EINVAL; return -1; } /*d_printf(">>>lseek: resolving %s\n", path);*/ - if (!cli_resolve_path("", &file->srv->cli, path, - &targetcli, targetpath)) + if (!cli_resolve_path( "", &file->srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); 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)) + 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)) + if (!cli_getattrE(targetcli, file->cli_fd, NULL, &b_size, NULL, NULL, + NULL)) { errno = EINVAL; return -1; @@ -1940,9 +1836,8 @@ smbc_lseek_ctx(SMBCCTX *context, * Generate an inode number from file name for those things that need it */ -static ino_t -smbc_inode(SMBCCTX *context, - const char *name) +static +ino_t smbc_inode(SMBCCTX *context, const char *name) { if (!context || !context->internal || @@ -1963,12 +1858,9 @@ smbc_inode(SMBCCTX *context, * fstat below. */ -static int -smbc_setup_stat(SMBCCTX *context, - struct stat *st, - char *fname, - SMB_OFF_T size, - int mode) +static +int smbc_setup_stat(SMBCCTX *context, struct stat *st, char *fname, + SMB_OFF_T size, int mode) { st->st_mode = 0; @@ -2012,21 +1904,12 @@ smbc_setup_stat(SMBCCTX *context, * Routine to stat a file given a name */ -static int -smbc_stat_ctx(SMBCCTX *context, - const char *fname, - struct stat *st) +static int smbc_stat_ctx(SMBCCTX *context, const char *fname, struct stat *st) { SMBCSRV *srv; - fstring server; - fstring share; - fstring user; - fstring password; - fstring workgroup; + fstring server, share, user, password, workgroup; pstring path; - time_t m_time = 0; - time_t a_time = 0; - time_t c_time = 0; + time_t m_time = 0, a_time = 0, c_time = 0; SMB_OFF_T size = 0; uint16 mode = 0; SMB_INO_T ino = 0; @@ -2063,8 +1946,7 @@ smbc_stat_ctx(SMBCCTX *context, fstrcpy(workgroup, context->workgroup); - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { return -1; /* errno set by smbc_server */ @@ -2095,22 +1977,13 @@ smbc_stat_ctx(SMBCCTX *context, * Routine to stat a file given an fd */ -static int -smbc_fstat_ctx(SMBCCTX *context, - SMBCFILE *file, - struct stat *st) +static int smbc_fstat_ctx(SMBCCTX *context, SMBCFILE *file, struct stat *st) { - time_t c_time; - time_t a_time; - time_t m_time; + time_t c_time, a_time, m_time; SMB_OFF_T size; uint16 mode; - fstring server; - fstring share; - fstring user; - fstring password; - pstring path; - pstring targetpath; + fstring server, share, user, password; + pstring path, targetpath; struct cli_state *targetcli; SMB_INO_T ino = 0; @@ -2148,18 +2021,17 @@ smbc_fstat_ctx(SMBCCTX *context, } /*d_printf(">>>fstat: resolving %s\n", path);*/ - if (!cli_resolve_path("", &file->srv->cli, path, - &targetcli, targetpath)) + if (!cli_resolve_path( "", &file->srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); return -1; } /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/ - if (!cli_qfileinfo(targetcli, file->cli_fd, &mode, &size, - &c_time, &a_time, &m_time, NULL, &ino)) { - if (!cli_getattrE(targetcli, file->cli_fd, &mode, &size, - &c_time, &a_time, &m_time)) { + if (!cli_qfileinfo(targetcli, file->cli_fd, + &mode, &size, &c_time, &a_time, &m_time, NULL, &ino)) { + if (!cli_getattrE(targetcli, file->cli_fd, + &mode, &size, &c_time, &a_time, &m_time)) { errno = EINVAL; return -1; @@ -2184,8 +2056,7 @@ smbc_fstat_ctx(SMBCCTX *context, * We accept the URL syntax explained in smbc_parse_path(), above. */ -static void -smbc_remove_dir(SMBCFILE *dir) +static void smbc_remove_dir(SMBCFILE *dir) { struct smbc_dir_list *d,*f; @@ -2203,11 +2074,7 @@ smbc_remove_dir(SMBCFILE *dir) } -static int -add_dirent(SMBCFILE *dir, - const char *name, - const char *comment, - uint32 type) +static int add_dirent(SMBCFILE *dir, const char *name, const char *comment, uint32 type) { struct smbc_dirent *dirent; int size; @@ -2280,10 +2147,7 @@ add_dirent(SMBCFILE *dir, } static void -list_unique_wg_fn(const char *name, - uint32 type, - const char *comment, - void *state) +list_unique_wg_fn(const char *name, uint32 type, const char *comment, void *state) { SMBCFILE *dir = (SMBCFILE *)state; struct smbc_dir_list *dir_list; @@ -2324,10 +2188,7 @@ list_unique_wg_fn(const char *name, } static void -list_fn(const char *name, - uint32 type, - const char *comment, - void *state) +list_fn(const char *name, uint32 type, const char *comment, void *state) { SMBCFILE *dir = (SMBCFILE *)state; int dirent_type; @@ -2383,10 +2244,7 @@ list_fn(const char *name, } static void -dir_list_fn(const char *mnt, - file_info *finfo, - const char *mask, - void *state) +dir_list_fn(const char *mnt, file_info *finfo, const char *mask, void *state) { if (add_dirent((SMBCFILE *)state, finfo->name, "", @@ -2482,9 +2340,7 @@ done: -static SMBCFILE * -smbc_opendir_ctx(SMBCCTX *context, - const char *fname) +static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname) { fstring server, share, user, password, options; pstring workgroup; @@ -2521,9 +2377,7 @@ smbc_opendir_ctx(SMBCCTX *context, return NULL; } - DEBUG(4, ("parsed path: fname='%s' server='%s' share='%s' " - "path='%s' options='%s'\n", - fname, server, share, path, options)); + 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)) { @@ -2607,12 +2461,9 @@ smbc_opendir_ctx(SMBCCTX *context, } for (i = 0; i < count && i < max_lmb_count; i++) { - DEBUG(99, ("Found master browser %d of %d: %s\n", - i+1, MAX(count, max_lmb_count), - inet_ntoa(ip_list[i].ip))); + DEBUG(99, ("Found master browser %d of %d: %s\n", i+1, MAX(count, max_lmb_count), inet_ntoa(ip_list[i].ip))); - cli = get_ipc_connect_master_ip(&ip_list[i], - workgroup, &u_info); + cli = get_ipc_connect_master_ip(&ip_list[i], workgroup, &u_info); /* cli == NULL is the master browser refused to talk or could not be found */ if ( !cli ) @@ -2621,8 +2472,7 @@ smbc_opendir_ctx(SMBCCTX *context, fstrcpy(server, cli->desthost); cli_shutdown(cli); - DEBUG(4, ("using workgroup %s %s\n", - workgroup, server)); + DEBUG(4, ("using workgroup %s %s\n", workgroup, server)); /* * For each returned master browser IP address, get a @@ -2631,8 +2481,8 @@ smbc_opendir_ctx(SMBCCTX *context, * workgroups/domains that it knows about. */ - srv = smbc_server(context, True, server, "IPC$", - workgroup, user, password); + srv = smbc_server(context, server, + "IPC$", workgroup, user, password); if (!srv) { continue; } @@ -2657,10 +2507,10 @@ smbc_opendir_ctx(SMBCCTX *context, * Server not an empty string ... Check the rest and see what * gives */ - if (*share == '\0') { - if (*path != '\0') { + if (share[0] == (char)0) { + + if (path[0] != (char)0) { /* Should not have empty share with path */ - /* Should not have empty share with path */ errno = EINVAL + 8197; if (dir) { SAFE_FREE(dir->fname); @@ -2670,32 +2520,12 @@ smbc_opendir_ctx(SMBCCTX *context, } - /* - * We don't know if <server> 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 <server><1D>, - * <server><1B>, or <server><20> translates. We check - * to see if <server> 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(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_ip, 0x1d) || /* LMB */ - resolve_name(server, &rem_ip, 0x1b) )) { /* DMB */ + /* Check to see if <server><1D>, <server><1B>, or <server><20> translates */ + /* However, we check to see if <server> is an IP address first */ + if (!is_ipaddress(server) && /* Not an IP addr so check next */ + (resolve_name(server, &rem_ip, 0x1d) || /* Found LMB */ + resolve_name(server, &rem_ip, 0x1b) )) { /* Found DMB */ fstring buserver; dir->dir_type = SMBC_SERVER; @@ -2703,24 +2533,22 @@ smbc_opendir_ctx(SMBCCTX *context, /* * Get the backup list ... */ - if (!name_status_find(server, 0, 0, - rem_ip, buserver)) { - DEBUG(0, ("Could not get name of " - "local/domain master browser " - "for server %s\n", server)); - errno = EPERM; + + if (!name_status_find(server, 0, 0, rem_ip, buserver)) { + + DEBUG(0, ("Could not get name of local/domain master browser for server %s\n", server)); + errno = EPERM; /* FIXME, is this correct */ return NULL; } /* - * Get a connection to IPC$ on the server if - * we do not already have one - */ - srv = smbc_server(context, True, - buserver, "IPC$", - workgroup, user, password); + * Get a connection to IPC$ on the server if we do not already have one + */ + + srv = smbc_server(context, buserver, "IPC$", workgroup, user, password); + if (!srv) { DEBUG(0, ("got no contact to IPC$\n")); if (dir) { @@ -2734,8 +2562,8 @@ smbc_opendir_ctx(SMBCCTX *context, dir->srv = srv; /* Now, list the servers ... */ - if (!cli_NetServerEnum(&srv->cli, server, - 0x0000FFFE, list_fn, + + if (!cli_NetServerEnum(&srv->cli, server, 0x0000FFFE, list_fn, (void *)dir)) { if (dir) { @@ -2743,73 +2571,75 @@ smbc_opendir_ctx(SMBCCTX *context, SAFE_FREE(dir); } return NULL; + } - } else if (srv || - (resolve_name(server, &rem_ip, 0x20))) { - - /* If we hadn't found the server, get one now */ - if (!srv) { - srv = smbc_server(context, True, - server, "IPC$", - workgroup, - user, password); - } + } + else { - if (!srv) { - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - return NULL; + if (resolve_name(server, &rem_ip, 0x20)) { - } + /* Now, list the shares ... */ + + dir->dir_type = SMBC_FILE_SHARE; + + srv = smbc_server(context, server, "IPC$", workgroup, user, password); - dir->dir_type = SMBC_FILE_SHARE; - dir->srv = srv; + if (!srv) { - /* List the shares ... */ + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + return NULL; - if (net_share_enum_rpc( - &srv->cli, - list_fn, - (void *) dir) < 0 && - cli_RNetShareEnum( - &srv->cli, - list_fn, - (void *)dir) < 0) { + } + + dir->srv = srv; + + /* Now, list the servers ... */ + + 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); - } - return NULL; + errno = cli_errno(&srv->cli); + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + return NULL; + + } + + } + else { + + errno = ECONNREFUSED; /* Neither the workgroup nor server exists */ + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + return NULL; + + } - } - } else { - /* Neither the workgroup nor server exists */ - errno = ECONNREFUSED; - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - return NULL; } } - else { - /* - * The server and share are specified ... work from - * there ... - */ + else { /* The server and share are specified ... work from there ... */ pstring targetpath; struct cli_state *targetcli; - /* We connect to the server and list the directory */ + /* Well, we connect to the server and list the directory */ + dir->dir_type = SMBC_FILE_SHARE; - srv = smbc_server(context, True, server, share, - workgroup, user, password); + srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { @@ -2828,16 +2658,14 @@ smbc_opendir_ctx(SMBCCTX *context, p = path + strlen(path); pstrcat(path, "\\*"); - if (!cli_resolve_path("", &srv->cli, path, - &targetcli, targetpath)) + if (!cli_resolve_path( "", &srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); return NULL; } - if (cli_list(targetcli, targetpath, - aDIR | aSYSTEM | aHIDDEN, - dir_list_fn, (void *)dir) < 0) { + if (cli_list(targetcli, targetpath, aDIR | aSYSTEM | aHIDDEN, dir_list_fn, + (void *)dir) < 0) { if (dir) { SAFE_FREE(dir->fname); @@ -2881,9 +2709,7 @@ smbc_opendir_ctx(SMBCCTX *context, * Routine to close a directory */ -static int -smbc_closedir_ctx(SMBCCTX *context, - SMBCFILE *dir) +static int smbc_closedir_ctx(SMBCCTX *context, SMBCFILE *dir) { if (!context || !context->internal || @@ -2915,11 +2741,10 @@ smbc_closedir_ctx(SMBCCTX *context, } -static void -smbc_readdir_internal(SMBCCTX * context, - struct smbc_dirent *dest, - struct smbc_dirent *src, - int max_namebuf_len) +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) { @@ -2961,9 +2786,7 @@ smbc_readdir_internal(SMBCCTX * context, * Routine to get a directory entry */ -struct smbc_dirent * -smbc_readdir_ctx(SMBCCTX *context, - SMBCFILE *dir) +struct smbc_dirent *smbc_readdir_ctx(SMBCCTX *context, SMBCFILE *dir) { int maxlen; struct smbc_dirent *dirp, *dirent; @@ -3022,11 +2845,10 @@ smbc_readdir_ctx(SMBCCTX *context, * Routine to get directory entries */ -static int -smbc_getdents_ctx(SMBCCTX *context, - SMBCFILE *dir, - struct smbc_dirent *dirp, - int count) +static int smbc_getdents_ctx(SMBCCTX *context, + SMBCFILE *dir, + struct smbc_dirent *dirp, + int count) { int rem = count; int reqd; @@ -3124,17 +2946,10 @@ smbc_getdents_ctx(SMBCCTX *context, * Routine to create a directory ... */ -static int -smbc_mkdir_ctx(SMBCCTX *context, - const char *fname, - mode_t mode) +static int smbc_mkdir_ctx(SMBCCTX *context, const char *fname, mode_t mode) { SMBCSRV *srv; - fstring server; - fstring share; - fstring user; - fstring password; - fstring workgroup; + fstring server, share, user, password, workgroup; pstring path, targetpath; struct cli_state *targetcli; @@ -3170,8 +2985,7 @@ smbc_mkdir_ctx(SMBCCTX *context, fstrcpy(workgroup, context->workgroup); - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { @@ -3204,35 +3018,23 @@ smbc_mkdir_ctx(SMBCCTX *context, static int smbc_rmdir_dirempty = True; -static void -rmdir_list_fn(const char *mnt, - file_info *finfo, - const char *mask, - void *state) +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) { - + + 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) +static int smbc_rmdir_ctx(SMBCCTX *context, const char *fname) { SMBCSRV *srv; - fstring server; - fstring share; - fstring user; - fstring password; - fstring workgroup; - pstring path; - pstring targetpath; + fstring server, share, user, password, workgroup; + pstring path, targetpath; struct cli_state *targetcli; if (!context || !context->internal || @@ -3268,8 +3070,7 @@ smbc_rmdir_ctx(SMBCCTX *context, fstrcpy(workgroup, context->workgroup); - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { @@ -3277,6 +3078,27 @@ smbc_rmdir_ctx(SMBCCTX *context, } + /* if (strncmp(srv->cli.dev, "IPC", 3) == 0) { + + mode = aDIR | aRONLY; + + } + else if (strncmp(srv->cli.dev, "LPT", 3) == 0) { + + if (strcmp(path, "\\") == 0) { + + mode = aDIR | aRONLY; + + } + else { + + mode = aRONLY; + smbc_stat_printjob(srv, path, &size, &m_time); + c_time = a_time = m_time; + + } + else { */ + /*d_printf(">>>rmdir: resolving %s\n", path);*/ if (!cli_resolve_path( "", &srv->cli, path, &targetcli, targetpath)) { @@ -3292,21 +3114,19 @@ smbc_rmdir_ctx(SMBCCTX *context, if (errno == EACCES) { /* Check if the dir empty or not */ - /* Local storage to avoid buffer overflows */ - pstring lpath; + pstring lpath; /* Local storage to avoid buffer overflows */ smbc_rmdir_dirempty = True; /* Make this so ... */ pstrcpy(lpath, targetpath); pstrcat(lpath, "\\*"); - if (cli_list(targetcli, lpath, - aDIR | aSYSTEM | aHIDDEN, - rmdir_list_fn, NULL) < 0) { + 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", + + DEBUG(5, ("smbc_rmdir: cli_list returned an error: %d\n", smbc_errno(context, targetcli))); errno = EACCES; @@ -3331,9 +3151,7 @@ smbc_rmdir_ctx(SMBCCTX *context, * Routine to return the current directory position */ -static off_t -smbc_telldir_ctx(SMBCCTX *context, - SMBCFILE *dir) +static off_t smbc_telldir_ctx(SMBCCTX *context, SMBCFILE *dir) { off_t ret_val; /* Squash warnings about cast */ @@ -3371,9 +3189,8 @@ smbc_telldir_ctx(SMBCCTX *context, * 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) +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 */ @@ -3402,10 +3219,7 @@ smbc_check_dir_ent(struct smbc_dir_list *list, * Routine to seek on a directory */ -static int -smbc_lseekdir_ctx(SMBCCTX *context, - SMBCFILE *dir, - off_t offset) +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; @@ -3455,10 +3269,7 @@ smbc_lseekdir_ctx(SMBCCTX *context, * Routine to fstat a dir */ -static int -smbc_fstatdir_ctx(SMBCCTX *context, - SMBCFILE *dir, - struct stat *st) +static int smbc_fstatdir_ctx(SMBCCTX *context, SMBCFILE *dir, struct stat *st) { if (!context || !context->internal || @@ -3475,17 +3286,10 @@ smbc_fstatdir_ctx(SMBCCTX *context, } -static int -smbc_chmod_ctx(SMBCCTX *context, - const char *fname, - mode_t newmode) +int smbc_chmod_ctx(SMBCCTX *context, const char *fname, mode_t newmode) { SMBCSRV *srv; - fstring server; - fstring share; - fstring user; - fstring password; - fstring workgroup; + fstring server, share, user, password, workgroup; pstring path; uint16 mode; @@ -3521,8 +3325,7 @@ smbc_chmod_ctx(SMBCCTX *context, fstrcpy(workgroup, context->workgroup); - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { return -1; /* errno set by smbc_server */ @@ -3543,17 +3346,10 @@ smbc_chmod_ctx(SMBCCTX *context, return 0; } -static int -smbc_utimes_ctx(SMBCCTX *context, - const char *fname, - struct timeval *tbuf) +int smbc_utimes_ctx(SMBCCTX *context, const char *fname, struct timeval *tbuf) { SMBCSRV *srv; - fstring server; - fstring share; - fstring user; - fstring password; - fstring workgroup; + fstring server, share, user, password, workgroup; pstring path; time_t a_time; time_t m_time; @@ -3617,8 +3413,7 @@ smbc_utimes_ctx(SMBCCTX *context, fstrcpy(workgroup, context->workgroup); - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { return -1; /* errno set by smbc_server */ @@ -3637,9 +3432,7 @@ smbc_utimes_ctx(SMBCCTX *context, computer running Windows NT 5.0" if denied ACEs do not appear before allowed ACEs. */ -static int -ace_compare(SEC_ACE *ace1, - SEC_ACE *ace2) +static int ace_compare(SEC_ACE *ace1, SEC_ACE *ace2) { if (sec_ace_equal(ace1, ace2)) return 0; @@ -3663,14 +3456,12 @@ ace_compare(SEC_ACE *ace1, } -static void -sort_acl(SEC_ACL *the_acl) +static void sort_acl(SEC_ACL *the_acl) { uint32 i; if (!the_acl) return; - qsort(the_acl->ace, the_acl->num_aces, sizeof(the_acl->ace[0]), - QSORT_CAST ace_compare); + qsort(the_acl->ace, the_acl->num_aces, sizeof(the_acl->ace[0]), QSORT_CAST ace_compare); for (i=1;i<the_acl->num_aces;) { if (sec_ace_equal(&the_acl->ace[i-1], &the_acl->ace[i])) { @@ -3686,12 +3477,11 @@ sort_acl(SEC_ACL *the_acl) } /* 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) +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; @@ -3724,12 +3514,11 @@ convert_sid_to_string(struct cli_state *ipc_cli, } /* 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) +static BOOL convert_string_to_sid(struct cli_state *ipc_cli, + POLICY_HND *pol, + BOOL numeric, + DOM_SID *sid, + const char *str) { uint32 *types = NULL; DOM_SID *sids = NULL; @@ -3764,19 +3553,16 @@ convert_string_to_sid(struct cli_state *ipc_cli, /* 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) +static BOOL parse_ace(struct cli_state *ipc_cli, + POLICY_HND *pol, + SEC_ACE *ace, + BOOL numeric, + char *str) { char *p; const char *cp; fstring tok; - unsigned int atype; - unsigned int aflags; - unsigned int amask; + unsigned atype, aflags, amask; DOM_SID sid; SEC_ACCESS mask; const struct perm_value *v; @@ -3887,14 +3673,10 @@ parse_ace(struct cli_state *ipc_cli, } /* 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) +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; @@ -3903,8 +3685,7 @@ add_ace(SEC_ACL **the_acl, aces = SMB_CALLOC_ARRAY(SEC_ACE, 1+(*the_acl)->num_aces); memcpy(aces, (*the_acl)->ace, (*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); + newacl = make_sec_acl(ctx,(*the_acl)->revision,1+(*the_acl)->num_aces, aces); SAFE_FREE(aces); (*the_acl) = newacl; return True; @@ -3912,19 +3693,17 @@ add_ace(SEC_ACL **the_acl, /* 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) +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; fstring tok; SEC_DESC *ret; size_t sd_size; - DOM_SID *grp_sid=NULL; - DOM_SID *owner_sid=NULL; + DOM_SID *grp_sid=NULL, *owner_sid=NULL; SEC_ACL *dacl=NULL; int revision=1; @@ -4024,11 +3803,10 @@ sec_desc_parse(TALLOC_CTX *ctx, /* Obtain the current dos attributes */ -static DOS_ATTR_DESC * -dos_attr_query(SMBCCTX *context, - TALLOC_CTX *ctx, - const char *filename, - SMBCSRV *srv) +static DOS_ATTR_DESC *dos_attr_query(SMBCCTX *context, + TALLOC_CTX *ctx, + const char *filename, + SMBCSRV *srv) { time_t m_time = 0, a_time = 0, c_time = 0; SMB_OFF_T size = 0; @@ -4065,11 +3843,10 @@ dos_attr_query(SMBCCTX *context, /* parse a ascii version of a security descriptor */ -static void -dos_attr_parse(SMBCCTX *context, - DOS_ATTR_DESC *dad, - SMBCSRV *srv, - char *str) +static void dos_attr_parse(SMBCCTX *context, + DOS_ATTR_DESC *dad, + SMBCSRV *srv, + char *str) { const char *p = str; fstring tok; @@ -4112,16 +3889,9 @@ dos_attr_parse(SMBCCTX *context, 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) +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; @@ -4184,9 +3954,7 @@ cacl_get(SMBCCTX *context, if (all || all_nt || all_dos) { /* Exclusions are delimited by '!' */ - for (; - pExclude != NULL; - pExclude = (p == NULL ? NULL : p + 1)) { + for (; pExclude != NULL; pExclude = (p == NULL ? NULL : p + 1)) { /* Find end of this exclusion name */ if ((p = strchr(pExclude, '!')) != NULL) @@ -4278,8 +4046,7 @@ cacl_get(SMBCCTX *context, n = strlen(p); } else { n = snprintf(buf, bufsize, - "REVISION:%d", - sd->revision); + "REVISION:%d", sd->revision); } } else if (StrCaseCmp(name, "revision") == 0) { if (determine_size) { @@ -4383,8 +4150,7 @@ cacl_get(SMBCCTX *context, } n = strlen(p); } else { - n = snprintf(buf, bufsize, - "%s", sidstr); + n = snprintf(buf, bufsize, "%s", sidstr); } } @@ -4431,9 +4197,9 @@ cacl_get(SMBCCTX *context, ace->info.mask); } } else if ((StrnCaseCmp(name, "acl", 3) == 0 && - StrCaseCmp(name+3, sidstr) == 0) || + StrCaseCmp(name + 3, sidstr) == 0) || (StrnCaseCmp(name, "acl+", 4) == 0 && - StrCaseCmp(name+4, sidstr) == 0)) { + StrCaseCmp(name + 4, sidstr) == 0)) { if (determine_size) { p = talloc_asprintf( ctx, @@ -4538,8 +4304,7 @@ cacl_get(SMBCCTX *context, } n = strlen(p); } else { - n = snprintf(buf, bufsize, - "0x%x", mode); + n = snprintf(buf, bufsize, "0x%x", mode); } } @@ -4620,8 +4385,7 @@ cacl_get(SMBCCTX *context, } n = strlen(p); } else { - n = snprintf(buf, bufsize, - "%lu", c_time); + n = snprintf(buf, bufsize, "%lu", c_time); } } @@ -4658,8 +4422,7 @@ cacl_get(SMBCCTX *context, } n = strlen(p); } else { - n = snprintf(buf, bufsize, - "%lu", a_time); + n = snprintf(buf, bufsize, "%lu", a_time); } } @@ -4696,8 +4459,7 @@ cacl_get(SMBCCTX *context, } n = strlen(p); } else { - n = snprintf(buf, bufsize, - "%lu", m_time); + n = snprintf(buf, bufsize, "%lu", m_time); } } @@ -4770,15 +4532,10 @@ cacl_get(SMBCCTX *context, /***************************************************** 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) +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; @@ -4853,8 +4610,7 @@ cacl_set(TALLOC_CTX *ctx, &old->dacl->ace[j])) { uint32 k; for (k=j; k<old->dacl->num_aces-1;k++) { - old->dacl->ace[k] = - old->dacl->ace[k+1]; + old->dacl->ace[k] = old->dacl->ace[k+1]; } old->dacl->num_aces--; if (old->dacl->num_aces == 0) { @@ -4958,23 +4714,18 @@ cacl_set(TALLOC_CTX *ctx, } -static int -smbc_setxattr_ctx(SMBCCTX *context, - const char *fname, - const char *name, - const void *value, - size_t size, - int flags) +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; SMBCSRV *ipc_srv; - fstring server; - fstring share; - fstring user; - fstring password; - fstring workgroup; + fstring server, share, user, password, workgroup; pstring path; TALLOC_CTX *ctx; POLICY_HND pol; @@ -4995,8 +4746,7 @@ smbc_setxattr_ctx(SMBCCTX *context, } - DEBUG(4, ("smbc_setxattr(%s, %s, %.*s)\n", - fname, name, (int) size, (const char*)value)); + DEBUG(4, ("smbc_setxattr(%s, %s, %.*s)\n", fname, name, (int) size, (const char*)value)); if (smbc_parse_path(context, fname, server, sizeof(server), @@ -5013,8 +4763,7 @@ smbc_setxattr_ctx(SMBCCTX *context, fstrcpy(workgroup, context->workgroup); - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { return -1; /* errno set by smbc_server */ } @@ -5041,8 +4790,7 @@ smbc_setxattr_ctx(SMBCCTX *context, StrCaseCmp(name, "system.*+") == 0) { /* Yup. */ char *namevalue = - talloc_asprintf(ctx, "%s:%s", - name+7, (const char *) value); + talloc_asprintf(ctx, "%s:%s", name+7, (const char *) value); if (! namevalue) { errno = ENOMEM; ret = -1; @@ -5103,8 +4851,7 @@ smbc_setxattr_ctx(SMBCCTX *context, /* Yup. */ char *namevalue = - talloc_asprintf(ctx, "%s:%s", - name+19, (const char *) value); + talloc_asprintf(ctx, "%s:%s", name+19, (const char *) value); if (! ipc_srv) { ret = -1; /* errno set by smbc_server() */ @@ -5133,8 +4880,7 @@ smbc_setxattr_ctx(SMBCCTX *context, /* Yup. */ char *namevalue = - talloc_asprintf(ctx, "%s:%s", - name+19, (const char *) value); + talloc_asprintf(ctx, "%s:%s", name+19, (const char *) value); if (! ipc_srv) { @@ -5160,8 +4906,7 @@ smbc_setxattr_ctx(SMBCCTX *context, /* Yup. */ char *namevalue = - talloc_asprintf(ctx, "%s:%s", - name+19, (const char *) value); + talloc_asprintf(ctx, "%s:%s", name+19, (const char *) value); if (! ipc_srv) { /* errno set by smbc_server() */ @@ -5192,8 +4937,7 @@ smbc_setxattr_ctx(SMBCCTX *context, dad = dos_attr_query(context, ctx, path, srv); if (dad) { char *namevalue = - talloc_asprintf(ctx, "%s:%s", - name+16, (const char *) value); + talloc_asprintf(ctx, "%s:%s", name+16, (const char *) value); if (! namevalue) { errno = ENOMEM; ret = -1; @@ -5229,21 +4973,16 @@ smbc_setxattr_ctx(SMBCCTX *context, return -1; } -static int -smbc_getxattr_ctx(SMBCCTX *context, - const char *fname, - const char *name, - const void *value, - size_t size) +int smbc_getxattr_ctx(SMBCCTX *context, + const char *fname, + const char *name, + const void *value, + size_t size) { int ret; SMBCSRV *srv; SMBCSRV *ipc_srv; - fstring server; - fstring share; - fstring user; - fstring password; - fstring workgroup; + fstring server, share, user, password, workgroup; pstring path; TALLOC_CTX *ctx; POLICY_HND pol; @@ -5281,8 +5020,7 @@ smbc_getxattr_ctx(SMBCCTX *context, fstrcpy(workgroup, context->workgroup); - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { return -1; /* errno set by smbc_server */ } @@ -5349,19 +5087,14 @@ smbc_getxattr_ctx(SMBCCTX *context, } -static int -smbc_removexattr_ctx(SMBCCTX *context, - const char *fname, - const char *name) +int smbc_removexattr_ctx(SMBCCTX *context, + const char *fname, + const char *name) { int ret; SMBCSRV *srv; SMBCSRV *ipc_srv; - fstring server; - fstring share; - fstring user; - fstring password; - fstring workgroup; + fstring server, share, user, password, workgroup; pstring path; TALLOC_CTX *ctx; POLICY_HND pol; @@ -5398,8 +5131,7 @@ smbc_removexattr_ctx(SMBCCTX *context, fstrcpy(workgroup, context->workgroup); - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { return -1; /* errno set by smbc_server */ } @@ -5461,11 +5193,10 @@ smbc_removexattr_ctx(SMBCCTX *context, return -1; } -static int -smbc_listxattr_ctx(SMBCCTX *context, - const char *fname, - char *list, - size_t size) +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 @@ -5511,14 +5242,9 @@ smbc_listxattr_ctx(SMBCCTX *context, * Open a print file to be written to by other calls */ -static SMBCFILE * -smbc_open_print_job_ctx(SMBCCTX *context, - const char *fname) +static SMBCFILE *smbc_open_print_job_ctx(SMBCCTX *context, const char *fname) { - fstring server; - fstring share; - fstring user; - fstring password; + fstring server, share, user, password; pstring path; if (!context || !context->internal || @@ -5562,17 +5288,10 @@ smbc_open_print_job_ctx(SMBCCTX *context, * 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) +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; + SMBCFILE *fid1, *fid2; + int bytes, saverr, tot_bytes = 0; char buf[4096]; if (!c_file || !c_file->internal->_initialized || !c_print || @@ -5645,17 +5364,10 @@ smbc_print_file_ctx(SMBCCTX *c_file, * 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) +static int smbc_list_print_jobs_ctx(SMBCCTX *context, const char *fname, smbc_list_print_job_fn fn) { SMBCSRV *srv; - fstring server; - fstring share; - fstring user; - fstring password; - fstring workgroup; + fstring server, share, user, password, workgroup; pstring path; if (!context || !context->internal || @@ -5690,8 +5402,7 @@ smbc_list_print_jobs_ctx(SMBCCTX *context, fstrcpy(workgroup, context->workgroup); - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { @@ -5699,8 +5410,7 @@ smbc_list_print_jobs_ctx(SMBCCTX *context, } - if (cli_print_queue(&srv->cli, - (void (*)(struct print_job_info *))fn) < 0) { + if (cli_print_queue(&srv->cli, (void (*)(struct print_job_info *))fn) < 0) { errno = smbc_errno(context, &srv->cli); return -1; @@ -5715,17 +5425,10 @@ smbc_list_print_jobs_ctx(SMBCCTX *context, * Delete a print job from a remote printer share */ -static int -smbc_unlink_print_job_ctx(SMBCCTX *context, - const char *fname, - int id) +static int smbc_unlink_print_job_ctx(SMBCCTX *context, const char *fname, int id) { SMBCSRV *srv; - fstring server; - fstring share; - fstring user; - fstring password; - fstring workgroup; + fstring server, share, user, password, workgroup; pstring path; int err; @@ -5761,8 +5464,7 @@ smbc_unlink_print_job_ctx(SMBCCTX *context, fstrcpy(workgroup, context->workgroup); - srv = smbc_server(context, True, - server, share, workgroup, user, password); + srv = smbc_server(context, server, share, workgroup, user, password); if (!srv) { @@ -5787,10 +5489,9 @@ smbc_unlink_print_job_ctx(SMBCCTX *context, /* * Get a new empty handle to fill in with your own info */ -SMBCCTX * -smbc_new_context(void) +SMBCCTX * smbc_new_context(void) { - SMBCCTX *context; + SMBCCTX * context; context = SMB_MALLOC_P(SMBCCTX); if (!context) { @@ -5862,9 +5563,7 @@ smbc_new_context(void) * and thus you'll be leaking memory if not handled properly. * */ -int -smbc_free_context(SMBCCTX *context, - int shutdown_ctx) +int smbc_free_context(SMBCCTX * context, int shutdown_ctx) { if (!context) { errno = EBADF; @@ -5886,15 +5585,12 @@ smbc_free_context(SMBCCTX *context, if (context->callbacks.purge_cached_fn(context)) { SMBCSRV * s; SMBCSRV * next; - DEBUG(1, ("Could not purge all servers, " - "Nice way shutdown failed.\n")); + 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)); + DEBUG(1, ("Forced shutdown: %p (fd=%d)\n", s, s->cli.fd)); cli_shutdown(&s->cli); - context->callbacks.remove_cached_srv_fn(context, - s); + context->callbacks.remove_cached_srv_fn(context, s); next = s->next; DLIST_REMOVE(context->internal->_servers, s); SAFE_FREE(s); @@ -5906,20 +5602,17 @@ smbc_free_context(SMBCCTX *context, else { /* This is the polite way */ if (context->callbacks.purge_cached_fn(context)) { - DEBUG(1, ("Could not purge all servers, " - "free_context failed.\n")); + 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")); + 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")); + DEBUG(1, ("Active files in context, free_context failed.\n")); errno = EBUSY; return 1; } @@ -5938,48 +5631,17 @@ smbc_free_context(SMBCCTX *context, /* - * 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, - ...) -{ - va_list args; - - va_start(args, option_name); - - if (strcmp(option_name, "debug_stderr") == 0) { - /* - * Log to standard error instead of standard output. - * - * optional parameters: none (it can't be turned off once on) - */ - context->internal->_debug_stderr = True; - } - - va_end(args); -} - - -/* * 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) +SMBCCTX * smbc_init_context(SMBCCTX * context) { pstring conf; int pid; - char *user = NULL; - char *home = NULL; + char *user = NULL, *home = NULL; if (!context || !context->internal) { errno = EBADF; @@ -5991,9 +5653,7 @@ smbc_init_context(SMBCCTX *context) return 0; } - if (!context->callbacks.auth_fn || - context->debug < 0 || - context->debug > 100) { + if (!context->callbacks.auth_fn || context->debug < 0 || context->debug > 100) { errno = EINVAL; return NULL; @@ -6001,25 +5661,18 @@ smbc_init_context(SMBCCTX *context) } if (!smbc_initialized) { - /* - * Do some library-wide intializations the first time we get - * called - */ + /* Do some library wide intialisations the first time we get called */ BOOL conf_loaded = False; /* 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); - } + setup_logging( "libsmbclient", True); /* Here we would open the smb.conf file if needed ... */ + load_interfaces(); /* Load the list of interfaces ... */ + in_client = True; /* FIXME, make a param */ home = getenv("HOME"); @@ -6061,8 +5714,6 @@ smbc_init_context(SMBCCTX *context) } } - load_interfaces(); /* Load the list of interfaces ... */ - reopen_logs(); /* Get logging working ... */ /* @@ -6088,17 +5739,15 @@ smbc_init_context(SMBCCTX *context) 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 + * 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 + * Hmmm, I want to get hostname as well, but I am too lazy for the moment */ pid = sys_getpid(); context->netbios_name = SMB_MALLOC(17); @@ -6106,8 +5755,7 @@ smbc_init_context(SMBCCTX *context) errno = ENOMEM; return NULL; } - slprintf(context->netbios_name, 16, - "smbc%s%d", context->user, pid); + slprintf(context->netbios_name, 16, "smbc%s%d", context->user, pid); } } @@ -6133,7 +5781,7 @@ smbc_init_context(SMBCCTX *context) * FIXME: Should we check the function pointers here? */ - context->internal->_initialized = True; + context->internal->_initialized = 1; return context; } diff --git a/source/libsmb/smb_share_modes.c b/source/libsmb/smb_share_modes.c index 43f25cd3787..40ccf15f946 100644 --- a/source/libsmb/smb_share_modes.c +++ b/source/libsmb/smb_share_modes.c @@ -255,12 +255,11 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx, * Create an entry in the Samba share mode db. */ -int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx, +int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx, uint64_t dev, uint64_t ino, const struct smb_share_mode_entry *new_entry, - const char *sharepath, /* Must be absolute utf8 path. */ - const char *filename) /* Must be relative utf8 path. */ + const char *filename) /* Must be abolute utf8 path. */ { TDB_DATA db_data; TDB_DATA locking_key = get_locking_key(dev, ino); @@ -273,9 +272,7 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx, db_data = tdb_fetch(db_ctx->smb_tdb, locking_key); if (!db_data.dptr) { /* We must create the entry. */ - db_data.dptr = malloc((2*sizeof(struct share_mode_entry)) + - strlen(sharepath) + 1 + - strlen(filename) + 1); + db_data.dptr = malloc((2*sizeof(struct share_mode_entry)) + strlen(filename) + 1); if (!db_data.dptr) { return -1; } @@ -284,18 +281,11 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx, ld->u.s.delete_on_close = 0; shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry)); create_share_mode_entry(shares, new_entry); - memcpy(db_data.dptr + 2*sizeof(struct share_mode_entry), - sharepath, - strlen(sharepath) + 1); - memcpy(db_data.dptr + 2*sizeof(struct share_mode_entry) + - strlen(sharepath) + 1, filename, strlen(filename) + 1); - db_data.dsize = 2*sizeof(struct share_mode_entry) + - strlen(sharepath) + 1 + - strlen(filename) + 1; + db_data.dsize = 2*sizeof(struct share_mode_entry) + strlen(filename) + 1; if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_INSERT) == -1) { free(db_data.dptr); return -1; @@ -346,25 +336,6 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx, return 0; } -/* - * Create an entry in the Samba share mode db. Original interface - doesn't - * Distinguish between share path and filename. Fudge this by using a - * sharepath of / and a relative filename of (filename+1). - */ - -int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx, - uint64_t dev, - uint64_t ino, - const struct smb_share_mode_entry *new_entry, - const char *filename) /* Must be absolute utf8 path. */ -{ - if (*filename != '/') { - abort(); - } - return smb_create_share_mode_entry_ex(db_ctx, dev, ino, new_entry, - "/", &filename[1]); -} - int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx, uint64_t dev, uint64_t ino, diff --git a/source/locking/locking.c b/source/locking/locking.c index d9737895ba1..591d1d0423d 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -464,15 +464,10 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) } } - /* Save off the associated service path and filename. */ - lck->servicepath = talloc_strdup(lck, dbuf.dptr + sizeof(*data) + - (lck->num_share_modes * - sizeof(struct share_mode_entry))); - + /* Save off the associated filename. */ lck->filename = talloc_strdup(lck, dbuf.dptr + sizeof(*data) + - (lck->num_share_modes * - sizeof(struct share_mode_entry)) + - strlen(lck->servicepath) + 1 ); + lck->num_share_modes * + sizeof(struct share_mode_entry)); /* * Ensure that each entry has a real process attached. @@ -500,7 +495,6 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) int i; struct locking_data *data; ssize_t offset; - ssize_t sp_len; result.dptr = NULL; result.dsize = 0; @@ -515,11 +509,8 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) return result; } - sp_len = strlen(lck->servicepath); - result.dsize = sizeof(*data) + lck->num_share_modes * sizeof(struct share_mode_entry) + - sp_len + 1 + strlen(lck->filename) + 1; result.dptr = talloc_size(lck, result.dsize); @@ -538,9 +529,6 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) sizeof(struct share_mode_entry)*lck->num_share_modes); offset = sizeof(*data) + sizeof(struct share_mode_entry)*lck->num_share_modes; - safe_strcpy(result.dptr + offset, lck->servicepath, - result.dsize - offset - 1); - offset += sp_len + 1; safe_strcpy(result.dptr + offset, lck->filename, result.dsize - offset - 1); print_share_mode_table(data); @@ -581,9 +569,8 @@ static int share_mode_lock_destructor(void *p) } struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, - SMB_DEV_T dev, SMB_INO_T ino, - const char *servicepath, - const char *fname) + SMB_DEV_T dev, SMB_INO_T ino, + const char *fname) { struct share_mode_lock *lck; TDB_DATA key = locking_key(dev, ino); @@ -598,7 +585,6 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, /* Ensure we set every field here as the destructor must be valid even if parse_share_modes fails. */ - lck->servicepath = NULL; lck->filename = NULL; lck->dev = dev; lck->ino = ino; @@ -624,15 +610,13 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, lck->fresh = (data.dptr == NULL); if (lck->fresh) { - - if (fname == NULL || servicepath == NULL) { - DEBUG(0, ("New file, but no filename or servicepath supplied\n")); + if (fname == NULL) { + DEBUG(0, ("New file, but no filename supplied\n")); talloc_free(lck); return NULL; } lck->filename = talloc_strdup(lck, fname); - lck->servicepath = talloc_strdup(lck, servicepath); - if (lck->filename == NULL || lck->servicepath == NULL) { + if (lck->filename == NULL) { DEBUG(0, ("talloc failed\n")); talloc_free(lck); return NULL; @@ -651,98 +635,12 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, return lck; } -/******************************************************************* - Sets the service name and filename for rename. - At this point we emit "file renamed" messages to all - process id's that have this file open. - Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp> -********************************************************************/ - -BOOL rename_share_filename(struct share_mode_lock *lck, - const char *servicepath, - const char *newname) -{ - size_t sp_len; - size_t fn_len; - size_t msg_len; - char *frm = NULL; - int i; - - if (!lck) { - return False; - } - - DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n", - servicepath, newname)); - - /* - * rename_internal_fsp() and rename_internals() add './' to - * head of newname if newname does not contain a '/'. - */ - while (newname[0] && newname[1] && newname[0] == '.' && newname[1] == '/') { - newname += 2; - } - - lck->servicepath = talloc_strdup(lck, servicepath); - lck->filename = talloc_strdup(lck, newname); - if (lck->filename == NULL || lck->servicepath == NULL) { - DEBUG(0, ("rename_share_filename: talloc failed\n")); - return False; - } - lck->modified = True; - - sp_len = strlen(lck->servicepath); - fn_len = strlen(lck->filename); - - msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + fn_len + 1; - - /* Set up the name changed message. */ - frm = TALLOC(lck, msg_len); - if (!frm) { - return False; - } - - SDEV_T_VAL(frm,0,lck->dev); - SINO_T_VAL(frm,8,lck->ino); - - DEBUG(10,("rename_share_filename: msg_len = %d\n", msg_len )); - - safe_strcpy(&frm[16], lck->servicepath, sp_len); - safe_strcpy(&frm[16 + sp_len + 1], lck->filename, fn_len); - - /* Send the messages. */ - for (i=0; i<lck->num_share_modes; i++) { - struct share_mode_entry *se = &lck->share_modes[i]; - if (!is_valid_share_mode_entry(se)) { - continue; - } - /* But not to ourselves... */ - if (procid_is_me(&se->pid)) { - continue; - } - - DEBUG(10,("rename_share_filename: sending rename message to pid %u " - "dev %x, inode %.0f sharepath %s newname %s\n", - (unsigned int)procid_to_pid(&se->pid), - (unsigned int)lck->dev, (double)lck->ino, - lck->servicepath, lck->filename )); - - become_root(); - message_send_pid(se->pid, MSG_SMB_FILE_RENAME, - frm, msg_len, True); - unbecome_root(); - } - - return True; -} - -BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode) +BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode, + const char *fname) { BOOL result; - struct share_mode_lock *lck = get_share_mode_lock(NULL, dev, inode, NULL, NULL); - if (!lck) { - return False; - } + struct share_mode_lock *lck = get_share_mode_lock(NULL, dev, inode, + fname); result = lck->delete_on_close; talloc_free(lck); return result; @@ -1076,7 +974,7 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close) return True; } - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); if (lck == NULL) { return False; } @@ -1094,10 +992,9 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, { struct locking_data *data; struct share_mode_entry *shares; - const char *sharepath; - const char *fname; + char *name; int i; - void (*traverse_callback)(struct share_mode_entry *, const char *, const char *) = state; + void (*traverse_callback)(struct share_mode_entry *, char *) = state; /* Ensure this is a locking_key record. */ if (kbuf.dsize != sizeof(struct locking_key)) @@ -1105,14 +1002,11 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, data = (struct locking_data *)dbuf.dptr; shares = (struct share_mode_entry *)(dbuf.dptr + sizeof(*data)); - sharepath = dbuf.dptr + sizeof(*data) + + name = dbuf.dptr + sizeof(*data) + data->u.s.num_share_mode_entries*sizeof(*shares); - fname = dbuf.dptr + sizeof(*data) + - data->u.s.num_share_mode_entries*sizeof(*shares) + - strlen(sharepath) + 1; for (i=0;i<data->u.s.num_share_mode_entries;i++) { - traverse_callback(&shares[i], sharepath, fname); + traverse_callback(&shares[i], name); } return 0; } @@ -1122,7 +1016,7 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, share mode system. ********************************************************************/ -int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *, const char *)) +int share_mode_forall(void (*fn)(const struct share_mode_entry *, char *)) { if (tdb == NULL) return 0; diff --git a/source/modules/vfs_afsacl.c b/source/modules/vfs_afsacl.c index 3794299b9a0..41f40d1e3c4 100644 --- a/source/modules/vfs_afsacl.c +++ b/source/modules/vfs_afsacl.c @@ -105,6 +105,27 @@ static struct afs_ace *clone_afs_ace(TALLOC_CTX *mem_ctx, struct afs_ace *ace) return result; } + +/* Ok, this is sort-of a hack. We assume here that we have winbind users in + * AFS. And yet another copy of parse_domain_user.... */ + +static BOOL parse_domain_user(const char *domuser, fstring domain, + fstring user) +{ + char *p = strchr(domuser,*lp_winbind_separator()); + + if (p==NULL) { + return False; + } + + fstrcpy(user, p+1); + fstrcpy(domain, domuser); + domain[PTR_DIFF(p, domuser)] = 0; + strupper_m(domain); + + return True; +} + static struct afs_ace *new_afs_ace(TALLOC_CTX *mem_ctx, BOOL positive, const char *name, uint32 rights) @@ -147,16 +168,14 @@ static struct afs_ace *new_afs_ace(TALLOC_CTX *mem_ctx, } else { - fstring domain, uname; - char *p; + fstring user, domain; - p = strchr_m(name, lp_winbind_separator()); - if (p != NULL) { - *p = '\\'; + if (!parse_domain_user(name, domain, user)) { + fstrcpy(user, name); + fstrcpy(domain, lp_workgroup()); } - - if (!lookup_name(name, LOOKUP_NAME_FULL, - domain, uname, &sid, &type)) { + + if (!lookup_name(domain, user, &sid, &type)) { DEBUG(10, ("Could not find AFS user %s\n", name)); sid_copy(&sid, &global_sid_NULL); diff --git a/source/nmbd/asyncdns.c b/source/nmbd/asyncdns.c index c8caa3fee29..4db54ea198c 100644 --- a/source/nmbd/asyncdns.c +++ b/source/nmbd/asyncdns.c @@ -34,18 +34,16 @@ static struct name_record *add_dns_result(struct nmb_name *question, struct in_a if (!addr.s_addr) { /* add the fail to WINS cache of names. give it 1 hour in the cache */ DEBUG(3,("add_dns_result: Negative DNS answer for %s\n", qname)); - add_name_to_subnet( wins_server_subnet, qname, name_type, + (void)add_name_to_subnet( wins_server_subnet, qname, name_type, NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr ); - return NULL; + return( NULL ); } /* add it to our WINS cache of names. give it 2 hours in the cache */ DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr))); - add_name_to_subnet( wins_server_subnet, qname, name_type, - NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr); - - return find_name_on_subnet(wins_server_subnet, question, FIND_ANY_NAME); + return( add_name_to_subnet( wins_server_subnet, qname, name_type, + NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr ) ); } #ifndef SYNC_DNS @@ -285,7 +283,8 @@ void run_dns_queue(void) queue a DNS query ****************************************************************************/ -BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question) +BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question, + struct name_record **n) { if (in_dns || fd_in == -1) return False; @@ -317,13 +316,13 @@ BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question) we use this when we can't do async DNS lookups ****************************************************************************/ -BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question) +BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question, + struct name_record **n) { - struct name_record *namerec = NULL; struct in_addr dns_ip; unstring qname; - pull_ascii_nstring(qname, sizeof(qname), question->name); + pull_ascii_nstring(qname, question->name); DEBUG(3,("DNS search for %s - ", nmb_namestr(question))); @@ -335,12 +334,11 @@ BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question) /* Re-block TERM signal. */ BlockSignals(True, SIGTERM); - namerec = add_dns_result(question, dns_ip); - if(namerec == NULL) { + *n = add_dns_result(question, dns_ip); + if(*n == NULL) send_wins_name_query_response(NAM_ERR, p, NULL); - } else { - send_wins_name_query_response(0, p, namerec); - } + else + send_wins_name_query_response(0, p, *n); return False; } diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c index ea7e9a5288f..e9d7f8d1851 100644 --- a/source/nmbd/nmbd.c +++ b/source/nmbd/nmbd.c @@ -58,7 +58,7 @@ static void terminate(void) DEBUG(0,("Got SIGTERM: going down...\n")); /* Write out wins.dat file if samba is a WINS server */ - wins_write_database(0,False); + wins_write_database(False); /* Remove all SELF registered names from WINS */ release_wins_names(); @@ -670,8 +670,6 @@ static BOOL open_sockets(BOOL isdaemon, int port) { NULL } }; - load_case_tables(); - global_nmb_port = NMB_PORT; pc = poptGetContext("nmbd", argc, argv, long_options, 0); diff --git a/source/nmbd/nmbd_browserdb.c b/source/nmbd/nmbd_browserdb.c index e27e483702a..e8797a99d51 100644 --- a/source/nmbd/nmbd_browserdb.c +++ b/source/nmbd/nmbd_browserdb.c @@ -35,7 +35,7 @@ * lmb_browserlist - This is our local master browser list. */ -struct browse_cache_record *lmb_browserlist; +ubi_dlNewList( lmb_browserlist ); /* -------------------------------------------------------------------------- ** * Functions... @@ -52,8 +52,7 @@ struct browse_cache_record *lmb_browserlist; */ static void remove_lmb_browser_entry( struct browse_cache_record *browc ) { - DLIST_REMOVE(lmb_browserlist, browc); - SAFE_FREE(browc); + safe_free( ubi_dlRemThis( lmb_browserlist, browc ) ); } /* ************************************************************************** ** @@ -86,7 +85,6 @@ struct browse_cache_record *create_browser_in_lmb_cache( const char *work_name, struct in_addr ip ) { struct browse_cache_record *browc; - struct browse_cache_record *tmp_browc; time_t now = time( NULL ); browc = SMB_MALLOC_P(struct browse_cache_record); @@ -115,7 +113,7 @@ struct browse_cache_record *create_browser_in_lmb_cache( const char *work_name, browc->ip = ip; - DLIST_ADD_END(lmb_browserlist, browc, tmp_browc); + (void)ubi_dlAddTail( lmb_browserlist, browc ); if( DEBUGLVL( 3 ) ) { Debug1( "nmbd_browserdb:create_browser_in_lmb_cache()\n" ); @@ -140,13 +138,12 @@ struct browse_cache_record *find_browser_in_lmb_cache( const char *browser_name { struct browse_cache_record *browc; - for( browc = lmb_browserlist; browc; browc = browc->next ) { - if( strequal( browser_name, browc->lmb_name ) ) { + for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist ); + browc; browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) + if( strequal( browser_name, browc->lmb_name ) ) break; - } - } - return browc; + return( browc ); } /* ************************************************************************** ** @@ -163,8 +160,9 @@ void expire_lmb_browsers( time_t t ) struct browse_cache_record *browc; struct browse_cache_record *nextbrowc; - for( browc = lmb_browserlist; browc; browc = nextbrowc) { - nextbrowc = browc->next; + for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist ); + browc; browc = nextbrowc ) { + nextbrowc = (struct browse_cache_record *)ubi_dlNext( browc ); if( browc->death_time < t ) { if( DEBUGLVL( 3 ) ) { diff --git a/source/nmbd/nmbd_browsesync.c b/source/nmbd/nmbd_browsesync.c index 9535a3115a6..03234bb98fa 100644 --- a/source/nmbd/nmbd_browsesync.c +++ b/source/nmbd/nmbd_browsesync.c @@ -24,7 +24,7 @@ #include "includes.h" /* This is our local master browser list database. */ -extern struct browse_cache_record *lmb_browserlist; +extern ubi_dlList lmb_browserlist[]; /**************************************************************************** As a domain master browser, do a sync with a local master browser. @@ -87,7 +87,9 @@ void dmb_expire_and_sync_browser_lists(time_t t) expire_lmb_browsers(t); - for( browc = lmb_browserlist; browc; browc = browc->next ) { + for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist ); + browc; + browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) { if (browc->sync_time < t) sync_with_lmb(browc); } diff --git a/source/nmbd/nmbd_incomingrequests.c b/source/nmbd/nmbd_incomingrequests.c index eaef7097b4a..7fac8c25739 100644 --- a/source/nmbd/nmbd_incomingrequests.c +++ b/source/nmbd/nmbd_incomingrequests.c @@ -339,7 +339,7 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name), names_added = 0; - namerec = subrec->namelist; + namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); while (buf < bufend) { if( (namerec->data.source == SELF_NAME) || (namerec->data.source == PERMANENT_NAME) ) { @@ -389,7 +389,7 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name), buf = buf0 + 18*names_added; - namerec = namerec->next; + namerec = (struct name_record *)ubi_trNext( namerec ); if (!namerec) { /* End of the subnet specific name list. Now @@ -398,7 +398,7 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name), if (uni_subrec != subrec) { subrec = uni_subrec; - namerec = subrec->namelist; + namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); } } if (!namerec) diff --git a/source/nmbd/nmbd_mynames.c b/source/nmbd/nmbd_mynames.c index f34d98172c6..07247d5495e 100644 --- a/source/nmbd/nmbd_mynames.c +++ b/source/nmbd/nmbd_mynames.c @@ -182,8 +182,8 @@ void release_wins_names(void) struct subnet_record *subrec = unicast_subnet; struct name_record *namerec, *nextnamerec; - for (namerec = subrec->namelist; namerec; namerec = nextnamerec) { - nextnamerec = namerec->next; + for (namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = nextnamerec) { + nextnamerec = (struct name_record *)ubi_trNext( namerec ); if( (namerec->data.source == SELF_NAME) && !NAME_IS_DEREGISTERING(namerec) ) release_name( subrec, namerec, standard_success_release, @@ -202,7 +202,9 @@ void refresh_my_names(time_t t) if (wins_srv_count() < 1) return; - for (namerec = unicast_subnet->namelist; namerec; namerec = namerec->next) { + for (namerec = (struct name_record *)ubi_trFirst(unicast_subnet->namelist); + namerec; + namerec = (struct name_record *)ubi_trNext(namerec)) { /* Each SELF name has an individual time to be refreshed. */ if ((namerec->data.source == SELF_NAME) && (namerec->data.refresh_time < t) && diff --git a/source/nmbd/nmbd_namelistdb.c b/source/nmbd/nmbd_namelistdb.c index 60023a7ed5e..344d3c7ca19 100644 --- a/source/nmbd/nmbd_namelistdb.c +++ b/source/nmbd/nmbd_namelistdb.c @@ -32,26 +32,24 @@ uint16 samba_nb_type = 0; /* samba's NetBIOS name type */ void set_samba_nb_type(void) { - if( lp_wins_support() || wins_srv_count() ) { + if( lp_wins_support() || wins_srv_count() ) samba_nb_type = NB_HFLAG; /* samba is a 'hybrid' node type. */ - } else { + else samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type. */ - } } /*************************************************************************** Convert a NetBIOS name to upper case. ***************************************************************************/ -static void upcase_name( struct nmb_name *target, const struct nmb_name *source ) +static void upcase_name( struct nmb_name *target, struct nmb_name *source ) { int i; unstring targ; fstring scope; - if( NULL != source ) { + if( NULL != source ) memcpy( target, source, sizeof( struct nmb_name ) ); - } pull_ascii_nstring(targ, sizeof(targ), target->name); strupper_m( targ ); @@ -65,94 +63,90 @@ static void upcase_name( struct nmb_name *target, const struct nmb_name *source * unused space doesn't have garbage in it. */ - for( i = strlen( target->name ); i < sizeof( target->name ); i++ ) { + for( i = strlen( target->name ); i < sizeof( target->name ); i++ ) target->name[i] = '\0'; - } - for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ ) { + for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ ) target->scope[i] = '\0'; - } } /************************************************************************** - Remove a name from the namelist. + Add a new or overwrite an existing namelist entry. ***************************************************************************/ -void remove_name_from_namelist(struct subnet_record *subrec, - struct name_record *namerec ) +static void update_name_in_namelist( struct subnet_record *subrec, + struct name_record *namerec ) { - if (subrec == wins_server_subnet) - remove_name_from_wins_namelist(namerec); - else { - subrec->namelist_changed = True; - DLIST_REMOVE(subrec->namelist, namerec); + struct name_record *oldrec = NULL; + + ubi_trInsert( subrec->namelist, namerec, &(namerec->name), &oldrec ); + if( oldrec ) { + SAFE_FREE( oldrec->data.ip ); + SAFE_FREE( oldrec ); } +} + +/************************************************************************** + Remove a name from the namelist. +***************************************************************************/ +void remove_name_from_namelist( struct subnet_record *subrec, + struct name_record *namerec ) +{ + ubi_trRemove( subrec->namelist, namerec ); SAFE_FREE(namerec->data.ip); ZERO_STRUCTP(namerec); SAFE_FREE(namerec); + subrec->namelist_changed = True; } /************************************************************************** Find a name in a subnet. **************************************************************************/ -struct name_record *find_name_on_subnet(struct subnet_record *subrec, - const struct nmb_name *nmbname, - BOOL self_only) +struct name_record *find_name_on_subnet( struct subnet_record *subrec, + struct nmb_name *nmbname, + BOOL self_only ) { - struct nmb_name uc_name; + struct nmb_name uc_name[1]; struct name_record *name_ret; - upcase_name( &uc_name, nmbname ); - - if (subrec == wins_server_subnet) { - return find_name_on_wins_subnet(&uc_name, self_only); - } - - for( name_ret = subrec->namelist; name_ret; name_ret = name_ret->next) { - if (memcmp(&uc_name, &name_ret->name, sizeof(struct nmb_name)) == 0) { - break; - } - } - + upcase_name( uc_name, nmbname ); + name_ret = (struct name_record *)ubi_trFind( subrec->namelist, uc_name ); if( name_ret ) { /* Self names only - these include permanent names. */ if( self_only && (name_ret->data.source != SELF_NAME) && (name_ret->data.source != PERMANENT_NAME) ) { DEBUG( 9, ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n", subrec->subnet_name, nmb_namestr(nmbname) ) ); - return False; + return( NULL ); } DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n", subrec->subnet_name, nmb_namestr(nmbname), name_ret->data.source) ); - - return name_ret; + return( name_ret ); } DEBUG( 9, ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n", subrec->subnet_name, nmb_namestr(nmbname) ) ); - - return NULL; + return( NULL ); } /************************************************************************** Find a name over all known broadcast subnets. ************************************************************************/ -struct name_record *find_name_for_remote_broadcast_subnet(struct nmb_name *nmbname, - BOOL self_only) +struct name_record *find_name_for_remote_broadcast_subnet( + struct nmb_name *nmbname, + BOOL self_only ) { struct subnet_record *subrec; - struct name_record *namerec; + struct name_record *namerec = NULL; for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) { - namerec = find_name_on_subnet(subrec, nmbname, self_only); - if (namerec) { - return namerec; - } + if( NULL != (namerec = find_name_on_subnet(subrec, nmbname, self_only)) ) + break; } - return NULL; + return( namerec ); } /************************************************************************** @@ -163,40 +157,34 @@ void update_name_ttl( struct name_record *namerec, int ttl ) { time_t time_now = time(NULL); - if( namerec->data.death_time != PERMANENT_TTL) { + if( namerec->data.death_time != PERMANENT_TTL ) namerec->data.death_time = time_now + ttl; - } namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME); - if (namerec->subnet == wins_server_subnet) { - wins_store_changed_namerec(namerec); - } else { - namerec->subnet->namelist_changed = True; - } + namerec->subnet->namelist_changed = True; } /************************************************************************** Add an entry to a subnet name list. ***********************************************************************/ -BOOL add_name_to_subnet( struct subnet_record *subrec, - const char *name, - int type, - uint16 nb_flags, - int ttl, - enum name_source source, - int num_ips, - struct in_addr *iplist) +struct name_record *add_name_to_subnet( struct subnet_record *subrec, + const char *name, + int type, + uint16 nb_flags, + int ttl, + enum name_source source, + int num_ips, + struct in_addr *iplist) { - BOOL ret = False; struct name_record *namerec; time_t time_now = time(NULL); namerec = SMB_MALLOC_P(struct name_record); if( NULL == namerec ) { DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) ); - return False; + return( NULL ); } memset( (char *)namerec, '\0', sizeof(*namerec) ); @@ -205,7 +193,7 @@ BOOL add_name_to_subnet( struct subnet_record *subrec, DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) ); ZERO_STRUCTP(namerec); SAFE_FREE(namerec); - return False; + return NULL; } namerec->subnet = subrec; @@ -218,9 +206,8 @@ BOOL add_name_to_subnet( struct subnet_record *subrec, namerec->data.wins_flags = WINS_ACTIVE; /* If it's our primary name, flag it as so. */ - if (strequal( my_netbios_names(0), name )) { + if( strequal( my_netbios_names(0), name ) ) namerec->data.nb_flags |= NB_PERM; - } /* Copy the IPs. */ namerec->data.num_ips = num_ips; @@ -230,14 +217,16 @@ BOOL add_name_to_subnet( struct subnet_record *subrec, namerec->data.source = source; /* Setup the death_time and refresh_time. */ - if (ttl == PERMANENT_TTL) { + if( ttl == PERMANENT_TTL ) namerec->data.death_time = PERMANENT_TTL; - } else { + else namerec->data.death_time = time_now + ttl; - } namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME); + /* Now add the record to the name list. */ + update_name_in_namelist( subrec, namerec ); + DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \ ttl=%d nb_flags=%2x to subnet %s\n", nmb_namestr( &namerec->name ), @@ -246,20 +235,9 @@ ttl=%d nb_flags=%2x to subnet %s\n", (unsigned int)nb_flags, subrec->subnet_name ) ); - /* Now add the record to the name list. */ - - if (subrec == wins_server_subnet) { - ret = add_name_to_wins_subnet(namerec); - /* Free namerec - it's stored in the tdb. */ - SAFE_FREE(namerec->data.ip); - SAFE_FREE(namerec); - } else { - DLIST_ADD(subrec->namelist, namerec); - subrec->namelist_changed = True; - ret = True; - } + subrec->namelist_changed = True; - return ret; + return(namerec); } /******************************************************************* @@ -275,8 +253,8 @@ void standard_success_register(struct subnet_record *subrec, { struct name_record *namerec; - namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME); - if (namerec == NULL) { + namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME ); + if( NULL == namerec ) { unstring name; pull_ascii_nstring(name, sizeof(name), nmbname->name); add_name_to_subnet( subrec, name, nmbname->name_type, @@ -299,15 +277,14 @@ void standard_fail_register( struct subnet_record *subrec, { struct name_record *namerec; - namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME); + namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME ); DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \ on subnet %s\n", nmb_namestr(nmbname), subrec->subnet_name) ); /* Remove the name from the subnet. */ - if( namerec ) { + if( namerec ) remove_name_from_namelist(subrec, namerec); - } } /******************************************************************* @@ -316,18 +293,13 @@ on subnet %s\n", nmb_namestr(nmbname), subrec->subnet_name) ); static void remove_nth_ip_in_record( struct name_record *namerec, int ind) { - if( ind != namerec->data.num_ips ) { + if( ind != namerec->data.num_ips ) memmove( (char *)(&namerec->data.ip[ind]), (char *)(&namerec->data.ip[ind+1]), ( namerec->data.num_ips - ind - 1) * sizeof(struct in_addr) ); - } namerec->data.num_ips--; - if (namerec->subnet == wins_server_subnet) { - wins_store_changed_namerec(namerec); - } else { - namerec->subnet->namelist_changed = True; - } + namerec->subnet->namelist_changed = True; } /******************************************************************* @@ -338,11 +310,9 @@ BOOL find_ip_in_name_record( struct name_record *namerec, struct in_addr ip ) { int i; - for(i = 0; i < namerec->data.num_ips; i++) { - if(ip_equal( namerec->data.ip[i], ip)) { + for(i = 0; i < namerec->data.num_ips; i++) + if(ip_equal( namerec->data.ip[i], ip)) return True; - } - } return False; } @@ -356,9 +326,8 @@ void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip ) struct in_addr *new_list; /* Don't add one we already have. */ - if( find_ip_in_name_record( namerec, new_ip )) { + if( find_ip_in_name_record( namerec, new_ip ) ) return; - } new_list = SMB_MALLOC_ARRAY( struct in_addr, namerec->data.num_ips + 1); if( NULL == new_list ) { @@ -373,11 +342,7 @@ void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip ) namerec->data.ip = new_list; namerec->data.num_ips += 1; - if (namerec->subnet == wins_server_subnet) { - wins_store_changed_namerec(namerec); - } else { - namerec->subnet->namelist_changed = True; - } + namerec->subnet->namelist_changed = True; } /******************************************************************* @@ -423,29 +388,26 @@ on subnet %s. Name was not found on subnet.\n", nmb_namestr(nmbname), inet_ntoa( remove_ip_from_name_record( namerec, released_ip ); - if( namerec->data.num_ips == orig_num ) { + if( namerec->data.num_ips == orig_num ) DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \ on subnet %s. This ip is not known for this name.\n", nmb_namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name ) ); - } } - if( namerec->data.num_ips == 0 ) { + if( namerec->data.num_ips == 0 ) remove_name_from_namelist( subrec, namerec ); - } } /******************************************************************* - Expires old names in a subnet namelist. - NB. Does not touch the wins_subnet - no wins specific processing here. + Expires old names in a subnet namelist. ******************************************************************/ -static void expire_names_on_subnet(struct subnet_record *subrec, time_t t) +void expire_names_on_subnet(struct subnet_record *subrec, time_t t) { struct name_record *namerec; struct name_record *next_namerec; - for( namerec = subrec->namelist; namerec; namerec = next_namerec ) { - next_namerec = namerec->next; + for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = next_namerec ) { + next_namerec = (struct name_record *)ubi_trNext( namerec ); if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) { if( namerec->data.source == SELF_NAME ) { DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \ @@ -458,14 +420,13 @@ name %s\n", subrec->subnet_name, nmb_namestr(&namerec->name) ) ); DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n", subrec->subnet_name, nmb_namestr(&namerec->name))); - remove_name_from_namelist(subrec, namerec ); + remove_name_from_namelist( subrec, namerec ); } } } /******************************************************************* - Expires old names in all subnet namelists. - NB. Does not touch the wins_subnet. + Expires old names in all subnet namelists. ******************************************************************/ void expire_names(time_t t) @@ -518,85 +479,75 @@ void add_samba_names_to_subnet( struct subnet_record *subrec ) add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL, PERMANENT_NAME, num_ips, iplist); - if(iplist != &subrec->myip) { + if(iplist != &subrec->myip) SAFE_FREE(iplist); - } } /**************************************************************************** - Dump a name_record struct. + Dump the contents of the namelists on all the subnets (including unicast) + into a file. Initiated by SIGHUP - used to debug the state of the namelists. **************************************************************************/ -void dump_name_record( struct name_record *namerec, XFILE *fp) +static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp) { + struct name_record *namerec; const char *src_type; struct tm *tm; int i; - x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name)); - switch(namerec->data.source) { - case LMHOSTS_NAME: - src_type = "LMHOSTS_NAME"; - break; - case WINS_PROXY_NAME: - src_type = "WINS_PROXY_NAME"; - break; - case REGISTER_NAME: - src_type = "REGISTER_NAME"; - break; - case SELF_NAME: - src_type = "SELF_NAME"; - break; - case DNS_NAME: - src_type = "DNS_NAME"; - break; - case DNSFAIL_NAME: - src_type = "DNSFAIL_NAME"; - break; - case PERMANENT_NAME: - src_type = "PERMANENT_NAME"; - break; - default: - src_type = "unknown!"; - break; - } - - x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags); - - if(namerec->data.death_time != PERMANENT_TTL) { - tm = localtime(&namerec->data.death_time); - x_fprintf(fp, "death_time = %s\t", asctime(tm)); - } else { - x_fprintf(fp, "death_time = PERMANENT\t"); - } + x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name); + for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; + namerec = (struct name_record *)ubi_trNext( namerec ) ) { + + x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name)); + switch(namerec->data.source) { + case LMHOSTS_NAME: + src_type = "LMHOSTS_NAME"; + break; + case WINS_PROXY_NAME: + src_type = "WINS_PROXY_NAME"; + break; + case REGISTER_NAME: + src_type = "REGISTER_NAME"; + break; + case SELF_NAME: + src_type = "SELF_NAME"; + break; + case DNS_NAME: + src_type = "DNS_NAME"; + break; + case DNSFAIL_NAME: + src_type = "DNSFAIL_NAME"; + break; + case PERMANENT_NAME: + src_type = "PERMANENT_NAME"; + break; + default: + src_type = "unknown!"; + break; + } - if(namerec->data.refresh_time != PERMANENT_TTL) { - tm = localtime(&namerec->data.refresh_time); - x_fprintf(fp, "refresh_time = %s\n", asctime(tm)); - } else { - x_fprintf(fp, "refresh_time = PERMANENT\n"); - } + x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags); - x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips); - for(i = 0; i < namerec->data.num_ips; i++) { - x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i])); - } + if(namerec->data.death_time != PERMANENT_TTL) { + tm = localtime(&namerec->data.death_time); + x_fprintf(fp, "death_time = %s\t", asctime(tm)); + } else { + x_fprintf(fp, "death_time = PERMANENT\t"); + } - x_fprintf(fp, "\n\n"); - -} + if(namerec->data.refresh_time != PERMANENT_TTL) { + tm = localtime(&namerec->data.refresh_time); + x_fprintf(fp, "refresh_time = %s\n", asctime(tm)); + } else { + x_fprintf(fp, "refresh_time = PERMANENT\n"); + } -/**************************************************************************** - Dump the contents of the namelists on all the subnets (including unicast) - into a file. Initiated by SIGHUP - used to debug the state of the namelists. -**************************************************************************/ + x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips); + for(i = 0; i < namerec->data.num_ips; i++) + x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i])); -static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp) -{ - struct name_record *namerec; - x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name); - for( namerec = subrec->namelist; namerec; namerec = namerec->next) { - dump_name_record(namerec, fp); + x_fprintf(fp, "\n\n"); } } @@ -618,21 +569,16 @@ void dump_all_namelists(void) return; } - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) dump_subnet_namelist( subrec, fp ); - } - if (!we_are_a_wins_client()) { + if( !we_are_a_wins_client() ) dump_subnet_namelist( unicast_subnet, fp ); - } - if (remote_broadcast_subnet->namelist != NULL) { + if( remote_broadcast_subnet->namelist != NULL ) dump_subnet_namelist( remote_broadcast_subnet, fp ); - } - - if (wins_server_subnet != NULL) { - dump_wins_subnet_namelist(fp ); - } + if( wins_server_subnet != NULL ) + dump_subnet_namelist( wins_server_subnet, fp ); x_fclose( fp ); } diff --git a/source/nmbd/nmbd_subnetdb.c b/source/nmbd/nmbd_subnetdb.c index b2e1178bebc..b53a6d7328f 100644 --- a/source/nmbd/nmbd_subnetdb.c +++ b/source/nmbd/nmbd_subnetdb.c @@ -51,6 +51,34 @@ static void add_subnet(struct subnet_record *subrec) DLIST_ADD(subnetlist, subrec); } +/* ************************************************************************** ** + * Comparison routine for ordering the splay-tree based namelists assoicated + * with each subnet record. + * + * Input: Item - Pointer to the comparison key. + * Node - Pointer to a node the splay tree. + * + * Output: The return value will be <0 , ==0, or >0 depending upon the + * ordinal relationship of the two keys. + * + * ************************************************************************** ** + */ +static int namelist_entry_compare( ubi_trItemPtr Item, ubi_trNodePtr Node ) +{ + struct name_record *NR = (struct name_record *)Node; + + if( DEBUGLVL( 10 ) ) { + struct nmb_name *Iname = (struct nmb_name *)Item; + + Debug1( "nmbd_subnetdb:namelist_entry_compare()\n" ); + Debug1( "%d == memcmp( \"%s\", \"%s\", %d )\n", + memcmp( Item, &(NR->name), sizeof(struct nmb_name) ), + nmb_namestr(Iname), nmb_namestr(&NR->name), (int)sizeof(struct nmb_name) ); + } + + return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) ); +} + /**************************************************************************** stop listening on a subnet we don't free the record as we don't have proper reference counting for it @@ -128,7 +156,10 @@ static struct subnet_record *make_subnet(const char *name, enum subnet_type type return(NULL); } - ZERO_STRUCTP(subrec); + memset( (char *)subrec, '\0', sizeof(*subrec) ); + (void)ubi_trInitTree( subrec->namelist, + namelist_entry_compare, + ubi_trOVERWRITE ); if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) { DEBUG(0,("make_subnet: malloc fail for subnet name !\n")); diff --git a/source/nmbd/nmbd_winsproxy.c b/source/nmbd/nmbd_winsproxy.c index d6dc6261c84..75319724616 100644 --- a/source/nmbd/nmbd_winsproxy.c +++ b/source/nmbd/nmbd_winsproxy.c @@ -33,7 +33,7 @@ static void wins_proxy_name_query_request_success( struct subnet_record *subrec, unstring name; struct packet_struct *original_packet; struct subnet_record *orig_broadcast_subnet; - struct name_record *namerec = NULL; + struct name_record *namerec; uint16 nb_flags; int num_ips; int i; @@ -64,34 +64,22 @@ returned for name %s.\n", nmb_namestr(nmbname) )); return; } - for(i = 0; i < num_ips; i++) { + for(i = 0; i < num_ips; i++) putip( (char *)&iplist[i], (char *)&rrec->rdata[ (i*6) + 2]); - } } /* Add the queried name to the original subnet as a WINS_PROXY_NAME. */ - if(rrec == PERMANENT_TTL) { + if(rrec == PERMANENT_TTL) ttl = lp_max_ttl(); - } pull_ascii_nstring(name, sizeof(name), nmbname->name); - add_name_to_subnet( orig_broadcast_subnet, name, + namerec = add_name_to_subnet( orig_broadcast_subnet, name, nmbname->name_type, nb_flags, ttl, WINS_PROXY_NAME, num_ips, iplist ); - namerec = find_name_on_subnet(orig_broadcast_subnet, nmbname, FIND_ANY_NAME); - if (!namerec) { - DEBUG(0,("wins_proxy_name_query_request_success: failed to add " - "name %s to subnet %s !\n", - name, - orig_broadcast_subnet->subnet_name )); - return; - } - - if(iplist != &ip) { + if(iplist != &ip) SAFE_FREE(iplist); - } /* * Check that none of the IP addresses we are returning is on the diff --git a/source/nmbd/nmbd_winsserver.c b/source/nmbd/nmbd_winsserver.c index 9983efe5ebb..8a1f82c8b17 100644 --- a/source/nmbd/nmbd_winsserver.c +++ b/source/nmbd/nmbd_winsserver.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. NBT netbios routines and daemon - version 2 - Copyright (C) Jeremy Allison 1994-2005 + Copyright (C) Jeremy Allison 1994-2003 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 @@ -18,313 +18,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - Converted to store WINS data in a tdb. Dec 2005. JRA. */ #include "includes.h" #define WINS_LIST "wins.dat" #define WINS_VERSION 1 -#define WINSDB_VERSION 1 - -/**************************************************************************** - We don't store the NetBIOS scope in the wins.tdb. We key off the (utf8) netbios - name (65 bytes with the last byte being the name type). -*****************************************************************************/ - -TDB_CONTEXT *wins_tdb; - -/**************************************************************************** - Convert a wins.tdb record to a struct name_record. Add in our global_scope(). -*****************************************************************************/ - -static struct name_record *wins_record_to_name_record(TDB_DATA key, TDB_DATA data) -{ - struct name_record *namerec = NULL; - uint16 nb_flags; - unsigned char nr_src; - uint32 death_time, refresh_time; - uint32 id_low, id_high; - uint32 saddr; - uint32 wins_flags; - uint32 num_ips; - size_t len; - int i; - - if (data.dptr == NULL || data.dsize == 0) { - return NULL; - } - - /* Min size is "wbddddddd" + 1 ip address (4). */ - if (data.dsize < 2 + 1 + (7*4) + 4) { - return NULL; - } - - len = tdb_unpack(data.dptr, data.dsize, - "wbddddddd", - &nb_flags, - &nr_src, - &death_time, - &refresh_time, - &id_low, - &id_high, - &saddr, - &wins_flags, - &num_ips ); - - namerec = SMB_MALLOC_P(struct name_record); - if (!namerec) { - return NULL; - } - - namerec->data.ip = SMB_MALLOC_ARRAY(struct in_addr, num_ips); - if (!namerec->data.ip) { - SAFE_FREE(namerec); - return NULL; - } - - namerec->subnet = wins_server_subnet; - push_ascii_nstring(namerec->name.name, key.dptr); - namerec->name.name_type = key.dptr[sizeof(unstring)]; - /* Add the scope. */ - push_ascii(namerec->name.scope, global_scope(), 64, STR_TERMINATE); - - /* We're using a byte-by-byte compare, so we must be sure that - * unused space doesn't have garbage in it. - */ - - for( i = strlen( namerec->name.name ); i < sizeof( namerec->name.name ); i++ ) { - namerec->name.name[i] = '\0'; - } - for( i = strlen( namerec->name.scope ); i < sizeof( namerec->name.scope ); i++ ) { - namerec->name.scope[i] = '\0'; - } - - namerec->data.nb_flags = nb_flags; - namerec->data.source = (enum name_source)nr_src; - namerec->data.death_time = (time_t)death_time; - namerec->data.refresh_time = (time_t)refresh_time; - namerec->data.id = id_low; -#if defined(HAVE_LONGLONG) - namerec->data.id |= ((SMB_BIG_UINT)id_high << 32); -#endif - namerec->data.wins_ip.s_addr = saddr; - namerec->data.wins_flags = wins_flags, - namerec->data.num_ips = num_ips; - - for (i = 0; i < num_ips; i++) { - namerec->data.ip[i].s_addr = IVAL(data.dptr, len + (i*4)); - } - - return namerec; -} - -/**************************************************************************** - Convert a struct name_record to a wins.tdb record. Ignore the scope. -*****************************************************************************/ - -static TDB_DATA name_record_to_wins_record(const struct name_record *namerec) -{ - TDB_DATA data; - size_t len = 0; - int i; - uint32 id_low = (namerec->data.id & 0xFFFFFFFF); -#if defined(HAVE_LONGLONG) - uint32 id_high = (namerec->data.id >> 32) & 0xFFFFFFFF; -#else - uint32 id_high = 0; -#endif - - ZERO_STRUCT(data); - - len = (2 + 1 + (7*4)); /* "wbddddddd" */ - len += (namerec->data.num_ips * 4); - - data.dptr = SMB_MALLOC(len); - if (!data.dptr) { - return data; - } - data.dsize = len; - - len = tdb_pack(data.dptr, data.dsize, "wbddddddd", - namerec->data.nb_flags, - (unsigned char)namerec->data.source, - (uint32)namerec->data.death_time, - (uint32)namerec->data.refresh_time, - id_low, - id_high, - (uint32)namerec->data.wins_ip.s_addr, - (uint32)namerec->data.wins_flags, - (uint32)namerec->data.num_ips ); - - for (i = 0; i < namerec->data.num_ips; i++) { - SIVAL(data.dptr, len + (i*4), namerec->data.ip[i].s_addr); - } - - return data; -} - -/**************************************************************************** - Create key. Key is UNIX codepage namestring (usually utf8 64 byte len) with 1 byte type. -*****************************************************************************/ - -static TDB_DATA name_to_key(const struct nmb_name *nmbname) -{ - static char keydata[sizeof(unstring) + 1]; - TDB_DATA key; - - memset(keydata, '\0', sizeof(keydata)); - - pull_ascii_nstring(keydata, sizeof(unstring), nmbname->name); - strupper_m(keydata); - keydata[sizeof(unstring)] = nmbname->name_type; - key.dptr = keydata; - key.dsize = sizeof(keydata); - - return key; -} - -/**************************************************************************** - Lookup a given name in the wins.tdb and create a temporary malloc'ed data struct - on the linked list. We will free this later in XXXX(). -*****************************************************************************/ - -struct name_record *find_name_on_wins_subnet(const struct nmb_name *nmbname, BOOL self_only) -{ - TDB_DATA data, key; - struct name_record *nr = NULL; - struct name_record *namerec = NULL; - - if (!wins_tdb) { - return NULL; - } - - key = name_to_key(nmbname); - data = tdb_fetch(wins_tdb, key); - - if (data.dsize == 0) { - return NULL; - } - - namerec = wins_record_to_name_record(key, data); - if (!namerec) { - return NULL; - } - - /* Search for this name record on the list. Replace it if found. */ - - for( nr = wins_server_subnet->namelist; nr; nr = nr->next) { - if (memcmp(nmbname->name, nr->name.name, 16) == 0) { - /* Delete it. */ - DLIST_REMOVE(wins_server_subnet->namelist, nr); - SAFE_FREE(nr->data.ip); - SAFE_FREE(nr); - break; - } - } - - DLIST_ADD(wins_server_subnet->namelist, namerec); - return namerec; -} - -/**************************************************************************** - Overwrite or add a given name in the wins.tdb. -*****************************************************************************/ - -static BOOL store_or_replace_wins_namerec(const struct name_record *namerec, int tdb_flag) -{ - TDB_DATA key, data; - int ret; - - if (!wins_tdb) { - return False; - } - - key = name_to_key(&namerec->name); - data = name_record_to_wins_record(namerec); - - if (data.dptr == NULL) { - return False; - } - - ret = tdb_store(wins_tdb, key, data, tdb_flag); - - SAFE_FREE(data.dptr); - return (ret == 0) ? True : False; -} - -/**************************************************************************** - Overwrite a given name in the wins.tdb. -*****************************************************************************/ - -BOOL wins_store_changed_namerec(const struct name_record *namerec) -{ - return store_or_replace_wins_namerec(namerec, TDB_REPLACE); -} - -/**************************************************************************** - Primary interface into creating and overwriting records in the wins.tdb. -*****************************************************************************/ - -BOOL add_name_to_wins_subnet(const struct name_record *namerec) -{ - return store_or_replace_wins_namerec(namerec, TDB_INSERT); -} - -/**************************************************************************** - Delete a given name in the tdb and remove the temporary malloc'ed data struct - on the linked list. -*****************************************************************************/ - -BOOL remove_name_from_wins_namelist(struct name_record *namerec) -{ - TDB_DATA key; - int ret; - - if (!wins_tdb) { - return False; - } - - key = name_to_key(&namerec->name); - ret = tdb_delete(wins_tdb, key); - - DLIST_REMOVE(wins_server_subnet->namelist, namerec); - SAFE_FREE(namerec->data.ip); - - /* namerec must be freed by the caller */ - - return (ret == 0) ? True : False; -} - -/**************************************************************************** - Dump out the complete namelist. -*****************************************************************************/ - -static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) -{ - struct name_record *namerec = NULL; - XFILE *fp = (XFILE *)state; - - if (kbuf.dsize != sizeof(unstring) + 1) { - return 0; - } - - namerec = wins_record_to_name_record(kbuf, dbuf); - if (!namerec) { - return 0; - } - - dump_name_record(namerec, fp); - - SAFE_FREE(namerec->data.ip); - SAFE_FREE(namerec); - return 0; -} - -void dump_wins_subnet_namelist(XFILE *fp) -{ - tdb_traverse(wins_tdb, traverse_fn, (void *)fp); -} /**************************************************************************** Change the wins owner address in the record. @@ -332,6 +31,8 @@ void dump_wins_subnet_namelist(XFILE *fp) static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip) { + if (namerec==NULL) + return; namerec->data.wins_ip=wins_ip; } @@ -341,35 +42,34 @@ static void update_wins_owner(struct name_record *namerec, struct in_addr wins_i static void update_wins_flag(struct name_record *namerec, int flags) { + if (namerec==NULL) + return; + namerec->data.wins_flags=0x0; /* if it's a group, it can be a normal or a special one */ if (namerec->data.nb_flags & NB_GROUP) { - if (namerec->name.name_type==0x1C) { + if (namerec->name.name_type==0x1C) namerec->data.wins_flags|=WINS_SGROUP; - } else { - if (namerec->data.num_ips>1) { + else + if (namerec->data.num_ips>1) namerec->data.wins_flags|=WINS_SGROUP; - } else { + else namerec->data.wins_flags|=WINS_NGROUP; - } - } } else { /* can be unique or multi-homed */ - if (namerec->data.num_ips>1) { + if (namerec->data.num_ips>1) namerec->data.wins_flags|=WINS_MHOMED; - } else { + else namerec->data.wins_flags|=WINS_UNIQUE; - } } /* the node type are the same bits */ namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK; /* the static bit is elsewhere */ - if (namerec->data.death_time == PERMANENT_TTL) { + if (namerec->data.death_time == PERMANENT_TTL) namerec->data.wins_flags|=WINS_STATIC; - } /* and add the given bits */ namerec->data.wins_flags|=flags; @@ -395,14 +95,12 @@ static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update) *current_id = general_id; - if (update) { + if (update) general_id++; - } } /**************************************************************************** Possibly call the WINS hook external program when a WINS change is made. - Also stores the changed record back in the wins_tdb. *****************************************************************************/ static void wins_hook(const char *operation, struct name_record *namerec, int ttl) @@ -412,11 +110,7 @@ static void wins_hook(const char *operation, struct name_record *namerec, int tt char *p, *namestr; int i; - wins_store_changed_namerec(namerec); - - if (!cmd || !*cmd) { - return; - } + if (!cmd || !*cmd) return; for (p=namerec->name.name; *p; p++) { if (!(isalnum((int)*p) || strchr_m("._-",*p))) { @@ -428,9 +122,8 @@ static void wins_hook(const char *operation, struct name_record *namerec, int tt /* Use the name without the nametype (and scope) appended */ namestr = nmb_namestr(&namerec->name); - if ((p = strchr(namestr, '<'))) { + if ((p = strchr(namestr, '<'))) *p = 0; - } p = command; p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d", @@ -448,6 +141,7 @@ static void wins_hook(const char *operation, struct name_record *namerec, int tt smbrun(command, NULL); } + /**************************************************************************** Determine if this packet should be allocated to the WINS server. *****************************************************************************/ @@ -463,9 +157,8 @@ BOOL packet_is_for_wins_server(struct packet_struct *packet) } /* Check for node status requests. */ - if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) { + if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) return False; - } switch(nmb->header.opcode) { /* @@ -517,13 +210,11 @@ static int get_ttl_from_packet(struct nmb_packet *nmb) { int ttl = nmb->additional->ttl; - if (ttl < lp_min_wins_ttl()) { + if(ttl < lp_min_wins_ttl() ) ttl = lp_min_wins_ttl(); - } - if (ttl > lp_max_wins_ttl()) { + if(ttl > lp_max_wins_ttl() ) ttl = lp_max_wins_ttl(); - } return ttl; } @@ -538,19 +229,8 @@ BOOL initialise_wins(void) XFILE *fp; pstring line; - if(!lp_we_are_a_wins_server()) { + if(!lp_we_are_a_wins_server()) return True; - } - - /* Open the wins.tdb. */ - wins_tdb = tdb_open_log(lock_path("wins.tdb"), 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST, O_CREAT|O_RDWR, 0600); - if (!wins_tdb) { - DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n", - strerror(errno) )); - return False; - } - - tdb_store_int32(wins_tdb, "WINSDB_VERSION", WINSDB_VERSION); add_samba_names_to_subnet(wins_server_subnet); @@ -664,9 +344,8 @@ BOOL initialise_wins(void) continue; } - if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') { + if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') nb_flags_str[strlen(nb_flags_str)-1] = '\0'; - } /* Netbios name. # divides the name from the type (hex): netbios#xx */ pstrcpy(name,name_str); @@ -682,9 +361,8 @@ BOOL initialise_wins(void) /* add all entries that have 60 seconds or more to live */ if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) { - if(ttl != PERMANENT_TTL) { + if(ttl != PERMANENT_TTL) ttl -= time_now; - } DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n", name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); @@ -692,8 +370,7 @@ BOOL initialise_wins(void) (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags, ttl, REGISTER_NAME, num_ips, ip_list ); } else { - DEBUG(4, ("initialise_wins: not adding name (ttl problem) " - "%s#%02x ttl = %d first IP %s flags = %2x\n", + DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n", name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); } @@ -719,21 +396,16 @@ static void send_wins_wack_response(int ttl, struct packet_struct *p) identical bytes from the requesting packet header. */ rdata[0] = (nmb->header.opcode & 0xF) << 3; - if (nmb->header.nm_flags.authoritative && nmb->header.response) { + if (nmb->header.nm_flags.authoritative && nmb->header.response) rdata[0] |= 0x4; - } - if (nmb->header.nm_flags.trunc) { + if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2; - } - if (nmb->header.nm_flags.recursion_desired) { + if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1; - } - if (nmb->header.nm_flags.recursion_available && nmb->header.response) { + if (nmb->header.nm_flags.recursion_available && nmb->header.response) rdata[1] |= 0x80; - } - if (nmb->header.nm_flags.bcast) { + if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10; - } reply_netbios_packet(p, /* Packet to reply to. */ 0, /* Result code. */ @@ -873,7 +545,7 @@ void wins_process_name_refresh_request( struct subnet_record *subrec, * names update the ttl and return success. */ if( (!group || (group && (question->name_type == 0x1c))) - && find_ip_in_name_record(namerec, from_ip) ) { + && find_ip_in_name_record(namerec, from_ip) ) { /* * Update the ttl. */ @@ -912,7 +584,6 @@ void wins_process_name_refresh_request( struct subnet_record *subrec, * 255.255.255.255 so we can't search for the IP address. */ update_name_ttl(namerec, ttl); - wins_hook("refresh", namerec, ttl); send_wins_name_registration_response(0, ttl, p); return; } else if(!group && (question->name_type == 0x1d)) { @@ -998,19 +669,16 @@ static void wins_register_query_fail(struct subnet_record *subrec, namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); - if ((namerec != NULL) && (namerec->data.source == REGISTER_NAME) && - ip_equal(rrec->packet->ip, *namerec->data.ip)) { + if( (namerec != NULL) && (namerec->data.source == REGISTER_NAME) && ip_equal(rrec->packet->ip, *namerec->data.ip) ) { remove_name_from_namelist( subrec, namerec); namerec = NULL; } - if(namerec == NULL) { + if(namerec == NULL) wins_process_name_registration_request(subrec, orig_reg_packet); - } else { - DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between " - "querying for name %s in order to replace it and this reply.\n", - nmb_namestr(question_name) )); - } + else + DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \ +querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) )); orig_reg_packet->locked = False; free_packet(orig_reg_packet); @@ -1160,9 +828,8 @@ to register name %s. Name already exists in WINS with source type %d.\n", * Group names with type 0x1c are registered with individual IP addresses. */ - if(registering_group_name && (question->name_type != 0x1c)) { + if(registering_group_name && (question->name_type != 0x1c)) from_ip = *interpret_addr2("255.255.255.255"); - } /* * Ignore all attempts to register a unique 0x1d name, although return success. @@ -1209,7 +876,6 @@ to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) )); update_wins_owner(namerec, our_fake_ip); } update_name_ttl(namerec, ttl); - wins_hook("refresh", namerec, ttl); send_wins_name_registration_response(0, ttl, p); return; } else { @@ -1239,11 +905,8 @@ already exists in WINS as a GROUP name.\n", nmb_namestr(question) )); * reject without doing the query - we know we will reject it. */ - if ( namerec != NULL ) { + if ( namerec != NULL ) pull_ascii_nstring(name, sizeof(name), namerec->name.name); - } else { - name[0] = '\0'; - } if( is_myname(name) ) { if(!ismyip(from_ip)) { @@ -1256,8 +919,8 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio * It's one of our names and one of our IP's - update the ttl. */ update_name_ttl(namerec, ttl); - wins_hook("refresh", namerec, ttl); send_wins_name_registration_response(0, ttl, p); + wins_hook("refresh", namerec, ttl); return; } } @@ -1277,8 +940,8 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio && ip_equal( namerec->data.ip[0], from_ip ) && ip_equal(namerec->data.wins_ip, our_fake_ip) ) { update_name_ttl( namerec, ttl ); - wins_hook("refresh", namerec, ttl); send_wins_name_registration_response( 0, ttl, p ); + wins_hook("refresh", namerec, ttl); return; } @@ -1398,16 +1061,15 @@ a subsequent IP address.\n", nmb_namestr(question_name) )); return; } - if(!find_ip_in_name_record(namerec, from_ip)) { + if(!find_ip_in_name_record(namerec, from_ip)) add_ip_to_name_record(namerec, from_ip); - } get_global_id_and_update(&namerec->data.id, True); update_wins_owner(namerec, our_fake_ip); update_wins_flag(namerec, WINS_ACTIVE); update_name_ttl(namerec, ttl); - wins_hook("add", namerec, ttl); send_wins_name_registration_response(0, ttl, orig_reg_packet); + wins_hook("add", namerec, ttl); orig_reg_packet->locked = False; free_packet(orig_reg_packet); @@ -1575,17 +1237,18 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio * It's one of our names and one of our IP's. Ensure the IP is in the record and * update the ttl. Update the version ID to force replication. */ - update_name_ttl(namerec, ttl); - if(!find_ip_in_name_record(namerec, from_ip)) { get_global_id_and_update(&namerec->data.id, True); update_wins_owner(namerec, our_fake_ip); update_wins_flag(namerec, WINS_ACTIVE); add_ip_to_name_record(namerec, from_ip); + wins_hook("add", namerec, ttl); + } else { + wins_hook("refresh", namerec, ttl); } - wins_hook("refresh", namerec, ttl); + update_name_ttl(namerec, ttl); send_wins_name_registration_response(0, ttl, p); return; } @@ -1609,8 +1272,8 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio update_wins_flag(namerec, WINS_ACTIVE); } - wins_hook("refresh", namerec, ttl); send_wins_name_registration_response(0, ttl, p); + wins_hook("refresh", namerec, ttl); return; } @@ -1685,37 +1348,6 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio } /*********************************************************************** - Fetch all *<1b> names from the WINS db and store on the namelist. -***********************************************************************/ - -static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) -{ - struct name_record *namerec = NULL; - - if (kbuf.dsize != sizeof(unstring) + 1) { - return 0; - } - - /* Filter out all non-1b names. */ - if (kbuf.dptr[sizeof(unstring)] != 0x1b) { - return 0; - } - - namerec = wins_record_to_name_record(kbuf, dbuf); - if (!namerec) { - return 0; - } - - DLIST_ADD(wins_server_subnet->namelist, namerec); - return 0; -} - -void fetch_all_active_wins_1b_names(void) -{ - tdb_traverse(wins_tdb, fetch_1b_traverse_fn, NULL); -} - -/*********************************************************************** Deal with the special name query for *<1b>. ***********************************************************************/ @@ -1733,13 +1365,10 @@ static void process_wins_dmb_query_request(struct subnet_record *subrec, */ num_ips = 0; - - fetch_all_active_wins_1b_names(); - - for( namerec = subrec->namelist; namerec; namerec = namerec->next ) { - if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) { + for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); + namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) { + if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b ) num_ips += namerec->data.num_ips; - } } if(num_ips == 0) { @@ -1762,8 +1391,9 @@ static void process_wins_dmb_query_request(struct subnet_record *subrec, */ num_ips = 0; - for( namerec = subrec->namelist; namerec; namerec = namerec->next ) { - if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) { + for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); + namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) { + if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) { int i; for(i = 0; i < namerec->data.num_ips; i++) { set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags); @@ -1835,9 +1465,8 @@ void send_wins_name_query_response(int rcode, struct packet_struct *p, prdata, /* data to send. */ reply_data_len); /* data length. */ - if(prdata != rdata) { + if(prdata != rdata) SAFE_FREE(prdata); - } } /*********************************************************************** @@ -1919,7 +1548,7 @@ void wins_process_name_query_request(struct subnet_record *subrec, DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n", nmb_namestr(question) )); - queue_dns_query(p, question); + queue_dns_query(p, question, &namerec); return; } @@ -2051,7 +1680,6 @@ release name %s as this record is not active anymore.\n", nmb_namestr(question) remove_ip_from_name_record(namerec, from_ip); DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n", inet_ntoa(from_ip),nmb_namestr(question))); - wins_hook("delete", namerec, 0); send_wins_name_release_response(0, p); return; } @@ -2061,235 +1689,118 @@ release name %s as this record is not active anymore.\n", nmb_namestr(question) * Flag the name as released and update the ttl */ + send_wins_name_release_response(0, p); + namerec->data.wins_flags |= WINS_RELEASED; update_name_ttl(namerec, EXTINCTION_INTERVAL); wins_hook("delete", namerec, 0); - send_wins_name_release_response(0, p); } /******************************************************************* WINS time dependent processing. ******************************************************************/ -static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) -{ - time_t t = *(time_t *)state; - BOOL store_record = False; - struct name_record *namerec = NULL; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - if (kbuf.dsize != sizeof(unstring) + 1) { - return 0; - } - - namerec = wins_record_to_name_record(kbuf, dbuf); - if (!namerec) { - return 0; - } - - if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) { - if( namerec->data.source == SELF_NAME ) { - DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n", - wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) ); - namerec->data.death_time += 300; - store_record = True; - goto done; - } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) { - DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n", - nmb_namestr(&namerec->name))); - remove_name_from_wins_namelist(namerec ); - goto done; - } - - /* handle records, samba is the wins owner */ - if (ip_equal(namerec->data.wins_ip, our_fake_ip)) { - switch (namerec->data.wins_flags | WINS_STATE_MASK) { - case WINS_ACTIVE: - namerec->data.wins_flags&=~WINS_STATE_MASK; - namerec->data.wins_flags|=WINS_RELEASED; - namerec->data.death_time = t + EXTINCTION_INTERVAL; - DEBUG(3,("wins_processing_traverse_fn: expiring %s\n", - nmb_namestr(&namerec->name))); - store_record = True; - goto done; - case WINS_RELEASED: - namerec->data.wins_flags&=~WINS_STATE_MASK; - namerec->data.wins_flags|=WINS_TOMBSTONED; - namerec->data.death_time = t + EXTINCTION_TIMEOUT; - get_global_id_and_update(&namerec->data.id, True); - DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n", - nmb_namestr(&namerec->name))); - store_record = True; - goto done; - case WINS_TOMBSTONED: - DEBUG(3,("wins_processing_traverse_fn: deleting %s\n", - nmb_namestr(&namerec->name))); - remove_name_from_wins_namelist(namerec ); - goto done; - } - } else { - switch (namerec->data.wins_flags | WINS_STATE_MASK) { - case WINS_ACTIVE: - /* that's not as MS says it should be */ - namerec->data.wins_flags&=~WINS_STATE_MASK; - namerec->data.wins_flags|=WINS_TOMBSTONED; - namerec->data.death_time = t + EXTINCTION_TIMEOUT; - DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n", - nmb_namestr(&namerec->name))); - store_record = True; - goto done; - case WINS_TOMBSTONED: - DEBUG(3,("wins_processing_traverse_fn: deleting %s\n", - nmb_namestr(&namerec->name))); - remove_name_from_wins_namelist(namerec ); - goto done; - case WINS_RELEASED: - DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\ -we are not the wins owner !\n", nmb_namestr(&namerec->name))); - goto done; - } - } - } - - done: - - if (store_record) { - wins_store_changed_namerec(namerec); - } - - SAFE_FREE(namerec->data.ip); - SAFE_FREE(namerec); - - return 0; -} - -/******************************************************************* - Time dependent wins processing. -******************************************************************/ - void initiate_wins_processing(time_t t) { static time_t lasttime = 0; - struct name_record *nr = NULL; - struct name_record *nrnext = NULL; - - if (!lasttime) { - lasttime = t; - } - if (t - lasttime < 20) { - return; - } + struct name_record *namerec; + struct name_record *next_namerec; + struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - if(!lp_we_are_a_wins_server()) { + if (!lasttime) lasttime = t; + if (t - lasttime < 20) return; - } - - tdb_traverse(wins_tdb, wins_processing_traverse_fn, &t); - - - /* Delete all temporary name records on the wins subnet linked list. */ - for( nr = wins_server_subnet->namelist; nr; nr = nrnext) { - nrnext = nr->next; - DLIST_REMOVE(wins_server_subnet->namelist, nr); - SAFE_FREE(nr->data.ip); - SAFE_FREE(nr); - } - - wins_write_database(t, True); lasttime = t; -} -/******************************************************************* - Write out one record. -******************************************************************/ - -void wins_write_name_record(struct name_record *namerec, XFILE *fp) -{ - int i; - struct tm *tm; + if(!lp_we_are_a_wins_server()) + return; - DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) )); + for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); + namerec; + namerec = next_namerec ) { + next_namerec = (struct name_record *)ubi_trNext( namerec ); + + if( (namerec->data.death_time != PERMANENT_TTL) + && (namerec->data.death_time < t) ) { + + if( namerec->data.source == SELF_NAME ) { + DEBUG( 3, ( "initiate_wins_processing: Subnet %s not expiring SELF name %s\n", + wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) ); + namerec->data.death_time += 300; + namerec->subnet->namelist_changed = True; + continue; + } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) { + DEBUG(3,("initiate_wins_processing: deleting timed out DNS name %s\n", + nmb_namestr(&namerec->name))); + remove_name_from_namelist( wins_server_subnet, namerec ); + continue; + } - if( namerec->data.death_time != PERMANENT_TTL ) { - char *ts, *nl; + /* handle records, samba is the wins owner */ + if (ip_equal(namerec->data.wins_ip, our_fake_ip)) { + switch (namerec->data.wins_flags | WINS_STATE_MASK) { + case WINS_ACTIVE: + namerec->data.wins_flags&=~WINS_STATE_MASK; + namerec->data.wins_flags|=WINS_RELEASED; + namerec->data.death_time = t + EXTINCTION_INTERVAL; + DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name))); + break; + case WINS_RELEASED: + namerec->data.wins_flags&=~WINS_STATE_MASK; + namerec->data.wins_flags|=WINS_TOMBSTONED; + namerec->data.death_time = t + EXTINCTION_TIMEOUT; + get_global_id_and_update(&namerec->data.id, True); + DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name))); + break; + case WINS_TOMBSTONED: + DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name))); + remove_name_from_namelist( wins_server_subnet, namerec ); + break; + } + } else { + switch (namerec->data.wins_flags | WINS_STATE_MASK) { + case WINS_ACTIVE: + /* that's not as MS says it should be */ + namerec->data.wins_flags&=~WINS_STATE_MASK; + namerec->data.wins_flags|=WINS_TOMBSTONED; + namerec->data.death_time = t + EXTINCTION_TIMEOUT; + DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name))); + case WINS_TOMBSTONED: + DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name))); + remove_name_from_namelist( wins_server_subnet, namerec ); + break; + case WINS_RELEASED: + DEBUG(0,("initiate_wins_processing: %s is in released state and\ +we are not the wins owner !\n", nmb_namestr(&namerec->name))); + break; + } + } - tm = localtime(&namerec->data.death_time); - ts = asctime(tm); - nl = strrchr( ts, '\n' ); - if( NULL != nl ) { - *nl = '\0'; } - DEBUGADD(4,("TTL = %s ", ts )); - } else { - DEBUGADD(4,("TTL = PERMANENT ")); - } - - for (i = 0; i < namerec->data.num_ips; i++) { - DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) )); } - DEBUGADD(4,("%2x\n", namerec->data.nb_flags )); - if( namerec->data.source == REGISTER_NAME ) { - unstring name; - pull_ascii_nstring(name, sizeof(name), namerec->name.name); - x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */ - (int)namerec->data.death_time); + if(wins_server_subnet->namelist_changed) + wins_write_database(True); - for (i = 0; i < namerec->data.num_ips; i++) - x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) ); - x_fprintf( fp, "%2xR\n", namerec->data.nb_flags ); - } + wins_server_subnet->namelist_changed = False; } /******************************************************************* Write out the current WINS database. ******************************************************************/ -static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) +void wins_write_database(BOOL background) { - struct name_record *namerec = NULL; - XFILE *fp = (XFILE *)state; - - if (kbuf.dsize != sizeof(unstring) + 1) { - return 0; - } - - namerec = wins_record_to_name_record(kbuf, dbuf); - if (!namerec) { - return 0; - } - - wins_write_name_record(namerec, fp); - - SAFE_FREE(namerec->data.ip); - SAFE_FREE(namerec); - return 0; -} - - -void wins_write_database(time_t t, BOOL background) -{ - static time_t last_write_time = 0; + struct name_record *namerec; pstring fname, fnamenew; XFILE *fp; - if (background) { - if (!last_write_time) { - last_write_time = t; - } - if (t - last_write_time < 120) { - return; - } - - } - - if(!lp_we_are_a_wins_server()) { + if(!lp_we_are_a_wins_server()) return; - } /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */ if (background) { @@ -2297,11 +1808,6 @@ void wins_write_database(time_t t, BOOL background) if (sys_fork()) { return; } - if (tdb_reopen(wins_tdb)) { - DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n", - strerror(errno))); - return; - } } slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST); @@ -2320,8 +1826,41 @@ void wins_write_database(time_t t, BOOL background) x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0); - tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp); + for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) { + int i; + struct tm *tm; + + DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) )); + + if( namerec->data.death_time != PERMANENT_TTL ) { + char *ts, *nl; + + tm = localtime(&namerec->data.death_time); + ts = asctime(tm); + nl = strrchr( ts, '\n' ); + if( NULL != nl ) + *nl = '\0'; + DEBUGADD(4,("TTL = %s ", ts )); + } else { + DEBUGADD(4,("TTL = PERMANENT ")); + } + for (i = 0; i < namerec->data.num_ips; i++) + DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) )); + DEBUGADD(4,("%2x\n", namerec->data.nb_flags )); + + if( namerec->data.source == REGISTER_NAME ) { + unstring name; + pull_ascii_nstring(name, sizeof(name), namerec->name.name); + x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */ + (int)namerec->data.death_time); + + for (i = 0; i < namerec->data.num_ips; i++) + x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) ); + x_fprintf( fp, "%2xR\n", namerec->data.nb_flags ); + } + } + x_fclose(fp); chmod(fnamenew,0644); unlink(fname); @@ -2331,8 +1870,6 @@ void wins_write_database(time_t t, BOOL background) } } -#if 0 - Until winsrepl is done. /**************************************************************************** Process a internal Samba message receiving a wins record. ***************************************************************************/ @@ -2348,9 +1885,8 @@ void nmbd_wins_new_entry(int msg_type, struct process_id src, struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); int i; - if (buf==NULL) { + if (buf==NULL) return; - } /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */ record=(WINS_RECORD *)buf; @@ -2364,15 +1900,8 @@ void nmbd_wins_new_entry(int msg_type, struct process_id src, DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n", record->name, record->type, inet_ntoa(record->wins_ip))); - new_namerec=add_name_to_subnet( wins_server_subnet, - record->name, - record->type, - record->nb_flags, - EXTINCTION_INTERVAL, - REGISTER_NAME, - record->num_ips, - record->ip); - + new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags, + EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip); if (new_namerec!=NULL) { update_wins_owner(new_namerec, record->wins_ip); update_wins_flag(new_namerec, record->wins_flags); @@ -2490,4 +2019,3 @@ void nmbd_wins_new_entry(int msg_type, struct process_id src, } } -#endif diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c index 61c01daa165..a87ccb4972e 100644 --- a/source/nsswitch/pam_winbind.c +++ b/source/nsswitch/pam_winbind.c @@ -57,11 +57,6 @@ static int _pam_parse(int argc, const char **argv) return ctrl; } -static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int error_status) -{ - SAFE_FREE(data); -} - /* --- authentication management functions --- */ /* Attempt a conversation */ @@ -513,22 +508,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, } /* Now use the username to look up password */ - retval = winbind_auth_request(username, password, member, ctrl); - if (retval == PAM_NEW_AUTHTOK_REQD || - retval == PAM_AUTHTOK_EXPIRED) { - - char *buf; - - if (!asprintf(&buf, "%d", retval)) { - return PAM_BUF_ERR; - } - - pam_set_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (void *)buf, _pam_winbind_cleanup_func); - - return PAM_SUCCESS; - } - - return retval; + return winbind_auth_request(username, password, member, ctrl); } PAM_EXTERN @@ -547,8 +527,6 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { const char *username; - void *tmp = NULL; - int retval = PAM_USER_UNKNOWN; /* parse arguments */ @@ -577,26 +555,6 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, return PAM_IGNORE; return PAM_USER_UNKNOWN; case 0: - pam_get_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (const void **)&tmp); - - if (tmp != NULL) { - retval = atoi(tmp); - switch (retval) { - case PAM_AUTHTOK_EXPIRED: - /* fall through, since new token is required in this case */ - case PAM_NEW_AUTHTOK_REQD: - _pam_log(LOG_WARNING, "pam_sm_acct_mgmt success but %s is set", - PAM_WINBIND_NEW_AUTHTOK_REQD); - _pam_log(LOG_NOTICE, "user '%s' needs new password", username); - /* PAM_AUTHTOKEN_REQD does not exist, but is documented in the manpage */ - return PAM_NEW_AUTHTOK_REQD; - default: - _pam_log(LOG_WARNING, "pam_sm_acct_mgmt success"); - _pam_log(LOG_NOTICE, "user '%s' granted access", username); - return PAM_SUCCESS; - } - } - /* Otherwise, the authentication looked good */ _pam_log(LOG_NOTICE, "user '%s' granted access", username); return PAM_SUCCESS; diff --git a/source/nsswitch/pam_winbind.h b/source/nsswitch/pam_winbind.h index 86ba9772879..7cae477714b 100644 --- a/source/nsswitch/pam_winbind.h +++ b/source/nsswitch/pam_winbind.h @@ -84,8 +84,6 @@ do { \ #define WINBIND__OLD_PASSWORD (1<<5) #define WINBIND_REQUIRED_MEMBERSHIP (1<<6) -#define PAM_WINBIND_NEW_AUTHTOK_REQD "PAM_WINBIND_NEW_AUTHTOK_REQD" - /* * here is the string to inform the user that the new passwords they * typed were not the same. diff --git a/source/nsswitch/wb_client.c b/source/nsswitch/wb_client.c index fcab76b033a..db56cf04441 100644 --- a/source/nsswitch/wb_client.c +++ b/source/nsswitch/wb_client.c @@ -64,53 +64,39 @@ BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid, /* Call winbindd to convert sid to name */ -BOOL winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, - const char **domain, const char **name, +BOOL winbind_lookup_sid(const DOM_SID *sid, + fstring dom_name, fstring name, enum SID_NAME_USE *name_type) { struct winbindd_request request; struct winbindd_response response; NSS_STATUS result; + fstring sid_str; /* Initialise request */ ZERO_STRUCT(request); ZERO_STRUCT(response); - fstrcpy(request.data.sid, sid_string_static(sid)); + sid_to_string(sid_str, sid); + fstrcpy(request.data.sid, sid_str); /* Make request */ - result = winbindd_request_response(WINBINDD_LOOKUPSID, &request, - &response); - - if (result != NSS_STATUS_SUCCESS) { - return False; - } + result = winbindd_request_response(WINBINDD_LOOKUPSID, &request, &response); /* Copy out result */ - if (domain != NULL) { - *domain = talloc_strdup(mem_ctx, response.data.name.dom_name); - if (*domain == NULL) { - DEBUG(0, ("talloc failed\n")); - return False; - } - } - if (name != NULL) { - *name = talloc_strdup(mem_ctx, response.data.name.name); - if (*name == NULL) { - DEBUG(0, ("talloc failed\n")); - return False; - } - } + if (result == NSS_STATUS_SUCCESS) { + fstrcpy(dom_name, response.data.name.dom_name); + fstrcpy(name, response.data.name.name); + *name_type = (enum SID_NAME_USE)response.data.name.type; - *name_type = (enum SID_NAME_USE)response.data.name.type; + DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n", + sid_str, dom_name, name)); + } - DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n", - sid_string_static(sid), response.data.name.dom_name, - response.data.name.name)); - return True; + return (result == NSS_STATUS_SUCCESS); } /* Call winbindd to convert SID to uid */ diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c index e9b9ed42c4f..60a4e2f6c01 100644 --- a/source/nsswitch/winbindd.c +++ b/source/nsswitch/winbindd.c @@ -932,8 +932,6 @@ int main(int argc, char **argv) fault_setup((void (*)(void *))fault_quit ); - load_case_tables(); - /* Initialise for running in non-root mode */ sec_init(); diff --git a/source/nsswitch/winbindd_ads.c b/source/nsswitch/winbindd_ads.c index 29129e823a2..ac24b35229c 100644 --- a/source/nsswitch/winbindd_ads.c +++ b/source/nsswitch/winbindd_ads.c @@ -621,7 +621,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, goto done; } - rc = ads_search_retry_dn(ads, (void**)(void *)&msg, user_dn, attrs); + rc = ads_search_retry_dn(ads, (void**)&msg, user_dn, attrs); if (!ADS_ERR_OK(rc)) { status = ads_ntstatus(rc); DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: %s\n", diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c index 1d047b8356f..841b114a785 100644 --- a/source/nsswitch/winbindd_cache.c +++ b/source/nsswitch/winbindd_cache.c @@ -546,10 +546,8 @@ static void centry_put_string(struct cache_entry *centry, const char *s) len = strlen(s); /* can't handle more than 254 char strings. Truncating is probably best */ - if (len > 254) { - DEBUG(10,("centry_put_string: truncating len (%d) to: 254\n", len)); + if (len > 254) len = 254; - } centry_put_uint8(centry, len); centry_expand(centry, len); memcpy(centry->data + centry->ofs, s, len); @@ -991,11 +989,8 @@ do_query: /* and save it */ wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type); - if (NT_STATUS_IS_OK(status)) { - strupper_m(CONST_DISCARD(char *,domain_name)); - strlower_m(CONST_DISCARD(char *,name)); - wcache_save_sid_to_name(domain, status, sid, domain_name, name, *type); - } + /* We can't save the sid to name mapping as we don't know the + correct case of the name without looking it up */ return status; } diff --git a/source/nsswitch/winbindd_ldap.c b/source/nsswitch/winbindd_ldap.c index 736d852a74e..4eedf0ce9f3 100644 --- a/source/nsswitch/winbindd_ldap.c +++ b/source/nsswitch/winbindd_ldap.c @@ -34,7 +34,7 @@ struct ldap_message_queue { }; struct rw_buffer { - uint8 *data; + uint8_t *data; size_t ofs, length; }; @@ -67,7 +67,7 @@ struct pending_ldap_message { struct pending_ldap_message *pending_messages; -static BOOL append_to_buf(struct rw_buffer *buf, uint8 *data, size_t length) +static BOOL append_to_buf(struct rw_buffer *buf, uint8_t *data, size_t length) { buf->data = SMB_REALLOC(buf->data, buf->length+length); @@ -92,7 +92,7 @@ static BOOL read_into_buf(int fd, struct rw_buffer *buf) return append_to_buf(buf, tmp_buf, len); } -static void peek_into_buf(struct rw_buffer *buf, uint8 **out, +static void peek_into_buf(struct rw_buffer *buf, uint8_t **out, size_t *out_length) { *out = buf->data; @@ -101,7 +101,7 @@ static void peek_into_buf(struct rw_buffer *buf, uint8 **out, static void consumed_from_buf(struct rw_buffer *buf, size_t length) { - uint8 *new = memdup(buf->data+length, buf->length-length); + uint8_t *new = memdup(buf->data+length, buf->length-length); free(buf->data); buf->data = new; buf->length -= length; @@ -109,7 +109,7 @@ static void consumed_from_buf(struct rw_buffer *buf, size_t length) static BOOL write_out_of_buf(int fd, struct rw_buffer *buf) { - uint8 *tmp; + uint8_t *tmp; size_t tmp_length, written; peek_into_buf(buf, &tmp, &tmp_length); @@ -176,7 +176,7 @@ static void new_ldap_client(int listen_sock) static struct ldap_message *get_msg_from_buf(struct rw_buffer *buffer, BOOL *error) { - uint8 *buf; + uint8_t *buf; int buf_length, msg_length; DATA_BLOB blob; ASN1_DATA data; diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c index 890007ae389..5f1d37751df 100644 --- a/source/nsswitch/winbindd_pam.c +++ b/source/nsswitch/winbindd_pam.c @@ -419,21 +419,16 @@ done: if ( NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_AFS_TOKEN) ) { - char *afsname = talloc_strdup(state->mem_ctx, - lp_afs_username_map()); + char *afsname = SMB_STRDUP(lp_afs_username_map()); char *cell; if (afsname == NULL) { goto no_token; } - afsname = talloc_string_sub(state->mem_ctx, - lp_afs_username_map(), - "%D", name_domain); - afsname = talloc_string_sub(state->mem_ctx, afsname, - "%u", name_user); - afsname = talloc_string_sub(state->mem_ctx, afsname, - "%U", name_user); + afsname = realloc_string_sub(afsname, "%D", name_domain); + afsname = realloc_string_sub(afsname, "%u", name_user); + afsname = realloc_string_sub(afsname, "%U", name_user); { DOM_SID user_sid; @@ -442,8 +437,7 @@ done: sid_copy(&user_sid, &info3.dom_sid.sid); sid_append_rid(&user_sid, info3.user_rid); sid_to_string(sidstr, &user_sid); - afsname = talloc_string_sub(state->mem_ctx, afsname, - "%s", sidstr); + afsname = realloc_string_sub(afsname, "%s", sidstr); } if (afsname == NULL) { @@ -472,7 +466,7 @@ done: strlen(state->response.extra_data)+1; no_token: - talloc_free(afsname); + SAFE_FREE(afsname); } return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; diff --git a/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c index fc878cb5ccb..2685e98555c 100644 --- a/source/nsswitch/winbindd_sid.c +++ b/source/nsswitch/winbindd_sid.c @@ -83,10 +83,10 @@ void winbindd_lookupname(struct winbindd_cli_state *state) char *p; /* Ensure null termination */ - state->request.data.name.dom_name[sizeof(state->request.data.name.dom_name)-1]='\0'; + state->request.data.sid[sizeof(state->request.data.name.dom_name)-1]='\0'; /* Ensure null termination */ - state->request.data.name.name[sizeof(state->request.data.name.name)-1]='\0'; + state->request.data.sid[sizeof(state->request.data.name.name)-1]='\0'; /* cope with the name being a fully qualified name */ p = strstr(state->request.data.name.name, lp_winbind_separator()); diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c index 4c3306a8aca..efae9568845 100644 --- a/source/nsswitch/winbindd_util.c +++ b/source/nsswitch/winbindd_util.c @@ -106,6 +106,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const { struct winbindd_domain *domain; const char *alternative_name = NULL; + static const DOM_SID null_sid = {0}; /* ignore alt_name if we are not in an AD domain */ @@ -127,7 +128,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const } } if (sid) { - if (is_null_sid(sid)) { + if (sid_equal(sid, &null_sid) ) { } else if (sid_equal(sid, &domain->sid)) { return domain; diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 83a5b2fc3cf..526bce9b60e 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -294,7 +294,6 @@ typedef struct BOOL bUnixExtensions; BOOL bDisableNetbios; BOOL bKernelChangeNotify; - BOOL bFamChangeNotify; BOOL bUseKerberosKeytab; BOOL bDeferSharingViolations; BOOL bEnablePrivileges; @@ -993,7 +992,6 @@ static struct parm_struct parm_table[] = { {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL, NULL, FLAG_ADVANCED}, {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL, NULL, FLAG_ADVANCED}, {"kernel change notify", P_BOOL, P_GLOBAL, &Globals.bKernelChangeNotify, NULL, NULL, FLAG_ADVANCED}, - {"fam change notify", P_BOOL, P_GLOBAL, &Globals.bFamChangeNotify, NULL, NULL, FLAG_ADVANCED}, {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL, NULL, FLAG_ADVANCED}, {"max smbd processes", P_INTEGER, P_GLOBAL, &Globals.iMaxSmbdProcesses, NULL, NULL, FLAG_ADVANCED}, @@ -1488,7 +1486,6 @@ static void init_globals(void) Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */ Globals.change_notify_timeout = 60; /* 1 minute default. */ Globals.bKernelChangeNotify = True; /* On if we have it. */ - Globals.bFamChangeNotify = True; /* On if we have it. */ Globals.lm_announce = 2; /* = Auto: send only if LM clients found */ Globals.lm_interval = 60; Globals.announce_as = ANNOUNCE_AS_NT_SERVER; @@ -1871,7 +1868,6 @@ FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego) FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego) FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups) FN_GLOBAL_BOOL(lp_kernel_change_notify, &Globals.bKernelChangeNotify) -FN_GLOBAL_BOOL(lp_fam_change_notify, &Globals.bFamChangeNotify) FN_GLOBAL_BOOL(lp_use_kerberos_keytab, &Globals.bUseKerberosKeytab) FN_GLOBAL_BOOL(lp_defer_sharing_violations, &Globals.bDeferSharingViolations) FN_GLOBAL_BOOL(lp_enable_privileges, &Globals.bEnablePrivileges) diff --git a/source/passdb/lookup_sid.c b/source/passdb/lookup_sid.c index 4640eb6ae58..b397e084c33 100644 --- a/source/passdb/lookup_sid.c +++ b/source/passdb/lookup_sid.c @@ -22,247 +22,43 @@ #include "includes.h" /***************************************************************** - Dissect a user-provided name into domain, name, sid and type. - - If an explicit domain name was given in the form domain\user, it - has to try that. If no explicit domain name was given, we have - to do guesswork. + *THE CANONICAL* convert name to SID function. + Tries local lookup first - for local domains - then uses winbind. *****************************************************************/ -BOOL lookup_name(TALLOC_CTX *mem_ctx, - const char *full_name, int flags, - const char **ret_domain, const char **ret_name, - DOM_SID *ret_sid, enum SID_NAME_USE *ret_type) +BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) { - char *p; - const char *tmp; - const char *domain = NULL; - const char *name = NULL; - uint32 rid; - DOM_SID sid; - enum SID_NAME_USE type; - TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); - - if (tmp_ctx == NULL) { - DEBUG(0, ("talloc_new failed\n")); - return False; - } - - p = strchr_m(full_name, '\\'); - - if (p != NULL) { - domain = talloc_strndup(tmp_ctx, full_name, - PTR_DIFF(p, full_name)); - name = talloc_strdup(tmp_ctx, p+1); - } else { - domain = talloc_strdup(tmp_ctx, ""); - name = talloc_strdup(tmp_ctx, full_name); - } - - if ((domain == NULL) || (name == NULL)) { - DEBUG(0, ("talloc failed\n")); - return False; - } + fstring sid; + BOOL local_lookup = False; + + *name_type = SID_NAME_UNKNOWN; + /* If we are looking up a domain user, make sure it is + for the local machine only */ + if (strequal(domain, get_global_sam_name())) { - - /* It's our own domain, lookup the name in passdb */ - if (lookup_global_sam_name(name, &rid, &type)) { - sid_copy(&sid, get_global_sam_sid()); - sid_append_rid(&sid, rid); - goto ok; - } - goto failed; - } - - if (strequal(domain, builtin_domain_name())) { - - /* Explicit request for a name in BUILTIN */ - if (lookup_builtin_name(name, &rid)) { - sid_copy(&sid, &global_sid_Builtin); - sid_append_rid(&sid, rid); - type = SID_NAME_ALIAS; - goto ok; - } - goto failed; - } - - if (domain[0] != '\0') { - /* An explicit domain name was given, here our last resort is - * winbind. */ - if (winbind_lookup_name(domain, name, &sid, &type)) { - goto ok; - } - goto failed; - } - - if (!(flags & LOOKUP_NAME_ISOLATED)) { - goto failed; - } - - /* Now the guesswork begins, we haven't been given an explicit - * domain. Try the sequence as documented on - * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp - * November 27, 2005 */ - - /* 1. well-known names */ - - { - if (lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) { - type = SID_NAME_WKN_GRP; - goto ok; - } - } - - /* 2. Builtin domain as such */ - - if (strequal(name, builtin_domain_name())) { - /* Swap domain and name */ - tmp = name; name = domain; domain = tmp; - sid_copy(&sid, &global_sid_Builtin); - type = SID_NAME_DOMAIN; - goto ok; - } - - /* 3. Account domain */ - - if (strequal(name, get_global_sam_name())) { - if (!secrets_fetch_domain_sid(name, &sid)) { - DEBUG(3, ("Could not fetch my SID\n")); - goto failed; - } - /* Swap domain and name */ - tmp = name; name = domain; domain = tmp; - type = SID_NAME_DOMAIN; - goto ok; - } - - /* 4. Primary domain */ - - if (!IS_DC && strequal(name, lp_workgroup())) { - if (!secrets_fetch_domain_sid(name, &sid)) { - DEBUG(3, ("Could not fetch the domain SID\n")); - goto failed; - } - /* Swap domain and name */ - tmp = name; name = domain; domain = tmp; - type = SID_NAME_DOMAIN; - goto ok; - } - - /* 5. Trusted domains as such, to me it looks as if members don't do - this, tested an XP workstation in a NT domain -- vl */ - - if (IS_DC && (secrets_fetch_trusted_domain_password(name, NULL, - &sid, NULL))) { - /* Swap domain and name */ - tmp = name; name = domain; domain = tmp; - type = SID_NAME_DOMAIN; - goto ok; - } - - /* 6. Builtin aliases */ - - if (lookup_builtin_name(name, &rid)) { - domain = talloc_strdup(tmp_ctx, builtin_domain_name()); - sid_copy(&sid, &global_sid_Builtin); - sid_append_rid(&sid, rid); - type = SID_NAME_ALIAS; - goto ok; - } - - /* 7. Local systems' SAM (DCs don't have a local SAM) */ - /* 8. Primary SAM (On members, this is the domain) */ - - /* Both cases are done by looking at our passdb */ - - if (lookup_global_sam_name(name, &rid, &type)) { - domain = talloc_strdup(tmp_ctx, get_global_sam_name()); - sid_copy(&sid, get_global_sam_sid()); - sid_append_rid(&sid, rid); - goto ok; - } - - /* Now our local possibilities are exhausted. */ - - if (!(flags & LOOKUP_NAME_REMOTE)) { - goto failed; - } - - /* If we are not a DC, we have to ask in our primary domain. Let - * winbind do that. */ - - if (!IS_DC && - (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) { - domain = talloc_strdup(tmp_ctx, lp_workgroup()); - goto ok; - } - - /* 9. Trusted domains */ - - /* If we're a DC we have to ask all trusted DC's. Winbind does not do - * that (yet), but give it a chance. */ - - if (IS_DC && winbind_lookup_name("", name, &sid, &type)) { - DOM_SID dom_sid; - uint32 tmp_rid; - enum SID_NAME_USE domain_type; - - if (type == SID_NAME_DOMAIN) { - /* Swap name and type */ - tmp = name; name = domain; domain = tmp; - goto ok; + if (local_lookup_name(name, psid, name_type)) { + DEBUG(10, + ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n", + domain, name, sid_to_string(sid,psid), + sid_type_lookup(*name_type), (unsigned int)*name_type)); + return True; } - - /* Here we have to cope with a little deficiency in the - * winbind API: We have to ask it again for the name of the - * domain it figured out itself. Maybe fix that later... */ - - sid_copy(&dom_sid, &sid); - sid_split_rid(&dom_sid, &tmp_rid); - - if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL, - &domain_type) || - (domain_type != SID_NAME_DOMAIN)) { - DEBUG(2, ("winbind could not find the domain's name " - "it just looked up for us\n")); - goto failed; + } else { + /* Remote */ + if (winbind_lookup_name(domain, name, psid, name_type)) { + + DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n", + domain, name, sid_to_string(sid, psid), + (unsigned int)*name_type)); + return True; } - goto ok; } + + DEBUG(10, ("lookup_name: %s lookup for [%s]\\[%s] failed\n", + local_lookup ? "local" : "winbind", domain, name)); - /* 10. Don't translate */ - failed: - talloc_free(tmp_ctx); return False; - - ok: - if ((domain == NULL) || (name == NULL)) { - DEBUG(0, ("talloc failed\n")); - talloc_free(tmp_ctx); - return False; - } - - if (ret_name != NULL) { - *ret_name = talloc_steal(mem_ctx, name); - } - - if (ret_domain != NULL) { - char *tmp_dom = talloc_strdup(tmp_ctx, domain); - strupper_m(tmp_dom); - *ret_domain = talloc_steal(mem_ctx, tmp_dom); - } - - if (ret_sid != NULL) { - sid_copy(ret_sid, &sid); - } - - if (ret_type != NULL) { - *ret_type = type; - } - - talloc_free(tmp_ctx); - return True; } /***************************************************************** @@ -270,28 +66,22 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, Tries local lookup first - for local sids, then tries winbind. *****************************************************************/ -BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, - const char **ret_domain, const char **ret_name, - enum SID_NAME_USE *ret_type) +BOOL lookup_sid(const DOM_SID *sid, fstring dom_name, fstring name, + enum SID_NAME_USE *name_type) { - const char *domain = NULL; - const char *name = NULL; - enum SID_NAME_USE type; - TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + if (!name_type) + return False; + + *name_type = SID_NAME_UNKNOWN; /* Check if this is our own sid. This should perhaps be done by winbind? For the moment handle it here. */ - if (tmp_ctx == NULL) { - DEBUG(0, ("talloc_new failed\n")); - return False; - } - if (sid_check_is_domain(sid)) { - domain = talloc_strdup(tmp_ctx, get_global_sam_name()); - name = talloc_strdup(tmp_ctx, ""); - type = SID_NAME_DOMAIN; - goto ok; + fstrcpy(dom_name, get_global_sam_name()); + fstrcpy(name, ""); + *name_type = SID_NAME_DOMAIN; + return True; } if (sid_check_is_in_our_domain(sid)) { @@ -299,22 +89,22 @@ BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, SMB_ASSERT(sid_peek_rid(sid, &rid)); /* For our own domain passdb is responsible */ - if (!lookup_global_sam_rid(tmp_ctx, rid, &name, &type)) { - goto failed; - } - - domain = talloc_strdup(tmp_ctx, get_global_sam_name()); - goto ok; + fstrcpy(dom_name, get_global_sam_name()); + return lookup_global_sam_rid(rid, name, name_type); } if (sid_check_is_builtin(sid)) { - domain = talloc_strdup(tmp_ctx, builtin_domain_name()); + /* Got through map_domain_sid_to_name here so that the mapping + * of S-1-5-32 to the name "BUILTIN" in as few places as + * possible. We might add i18n... */ + SMB_ASSERT(map_domain_sid_to_name(sid, dom_name)); /* Yes, W2k3 returns "BUILTIN" both as domain and name here */ - name = talloc_strdup(tmp_ctx, builtin_domain_name()); - type = SID_NAME_DOMAIN; - goto ok; + fstrcpy(name, dom_name); + + *name_type = SID_NAME_DOMAIN; + return True; } if (sid_check_is_in_builtin(sid)) { @@ -322,56 +112,39 @@ BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, SMB_ASSERT(sid_peek_rid(sid, &rid)); - if (!lookup_builtin_rid(tmp_ctx, rid, &name)) { - goto failed; - } + /* Got through map_domain_sid_to_name here so that the mapping + * of S-1-5-32 to the name "BUILTIN" in as few places as + * possible. We might add i18n... */ + SMB_ASSERT(map_domain_sid_to_name(&global_sid_Builtin, + dom_name)); /* There's only aliases in S-1-5-32 */ - type = SID_NAME_ALIAS; - domain = talloc_strdup(tmp_ctx, builtin_domain_name()); + *name_type = SID_NAME_ALIAS; - goto ok; + return lookup_builtin_rid(rid, name); } - if (winbind_lookup_sid(tmp_ctx, sid, &domain, &name, &type)) { - goto ok; + if (winbind_lookup_sid(sid, dom_name, name, name_type)) { + return True; } DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying " "special SIDs.\n", sid_string_static(sid))); - if (lookup_wellknown_sid(tmp_ctx, sid, &domain, &name)) { - type = SID_NAME_WKN_GRP; - goto ok; - } - - failed: - DEBUG(10, ("Failed to lookup sid %s\n", sid_string_static(sid))); - talloc_free(tmp_ctx); - return False; - - ok: - - if ((domain == NULL) || (name == NULL)) { - DEBUG(0, ("talloc failed\n")); - talloc_free(tmp_ctx); - return False; - } - - if (ret_domain != NULL) { - *ret_domain = talloc_steal(mem_ctx, domain); - } - - if (ret_name != NULL) { - *ret_name = talloc_steal(mem_ctx, name); + { + const char *dom, *obj_name; + + if (lookup_special_sid(sid, &dom, &obj_name, name_type)) { + DEBUG(10, ("found %s\\%s\n", dom, obj_name)); + fstrcpy(dom_name, dom); + fstrcpy(name, obj_name); + return True; + } } - if (ret_type != NULL) { - *ret_type = type; - } + DEBUG(10, ("lookup_sid failed\n")); - talloc_free(tmp_ctx); - return True; + return False; } /***************************************************************** @@ -414,9 +187,10 @@ static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid) for (pc = uid_sid_cache_head; pc; pc = pc->next) { if (pc->uid == uid) { + fstring sid; *psid = pc->sid; DEBUG(3,("fetch sid from uid cache %u -> %s\n", - (unsigned int)uid, sid_string_static(psid))); + (unsigned int)uid, sid_to_string(sid, psid))); DLIST_PROMOTE(uid_sid_cache_head, pc); return True; } @@ -434,9 +208,10 @@ static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid ) for (pc = uid_sid_cache_head; pc; pc = pc->next) { if (sid_compare(&pc->sid, psid) == 0) { + fstring sid; *puid = pc->uid; DEBUG(3,("fetch uid from cache %u -> %s\n", - (unsigned int)*puid, sid_string_static(psid))); + (unsigned int)*puid, sid_to_string(sid, psid))); DLIST_PROMOTE(uid_sid_cache_head, pc); return True; } @@ -486,9 +261,10 @@ static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid) for (pc = gid_sid_cache_head; pc; pc = pc->next) { if (pc->gid == gid) { + fstring sid; *psid = pc->sid; DEBUG(3,("fetch sid from gid cache %u -> %s\n", - (unsigned int)gid, sid_string_static(psid))); + (unsigned int)gid, sid_to_string(sid, psid))); DLIST_PROMOTE(gid_sid_cache_head, pc); return True; } @@ -506,9 +282,10 @@ static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid) for (pc = gid_sid_cache_head; pc; pc = pc->next) { if (sid_compare(&pc->sid, psid) == 0) { + fstring sid; *pgid = pc->gid; DEBUG(3,("fetch gid from cache %u -> %s\n", - (unsigned int)*pgid, sid_string_static(psid))); + (unsigned int)*pgid, sid_to_string(sid, psid))); DLIST_PROMOTE(gid_sid_cache_head, pc); return True; } @@ -554,6 +331,7 @@ static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid) NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) { + fstring sid; uid_t low, high; ZERO_STRUCTP(psid); @@ -570,7 +348,7 @@ NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) if (winbind_uid_to_sid(psid, uid)) { DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", - (unsigned int)uid, sid_string_static(psid))); + (unsigned int)uid, sid_to_string(sid, psid))); if (psid) store_uid_sid_cache(psid, uid); @@ -583,8 +361,7 @@ NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) return NT_STATUS_UNSUCCESSFUL; } - DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, - sid_string_static(psid))); + DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); store_uid_sid_cache(psid, uid); return NT_STATUS_OK; @@ -596,6 +373,7 @@ NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) { + fstring sid; gid_t low, high; ZERO_STRUCTP(psid); @@ -612,7 +390,7 @@ NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) if (winbind_gid_to_sid(psid, gid)) { DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", - (unsigned int)gid, sid_string_static(psid))); + (unsigned int)gid, sid_to_string(sid, psid))); if (psid) store_gid_sid_cache(psid, gid); @@ -625,8 +403,7 @@ NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) return NT_STATUS_UNSUCCESSFUL; } - DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, - sid_string_static(psid))); + DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); store_gid_sid_cache(psid, gid); return NT_STATUS_OK; @@ -638,6 +415,7 @@ NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) { + fstring dom_name, name, sid_str; enum SID_NAME_USE name_type; if (fetch_uid_from_cache(puid, psid)) @@ -659,7 +437,7 @@ NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) /* If it is not our local domain, only hope is winbindd */ - if ( !winbind_lookup_sid(NULL, psid, NULL, NULL, &name_type) ) { + if ( !winbind_lookup_sid(psid, dom_name, name, &name_type) ) { DEBUG(10,("sid_to_uid: winbind lookup for non-local sid %s failed\n", sid_string_static(psid) )); @@ -678,12 +456,12 @@ NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) if ( !winbind_sid_to_uid(puid, psid) ) { DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n", - sid_string_static(psid))); + sid_to_string(sid_str, psid) )); return NT_STATUS_UNSUCCESSFUL; } success: - DEBUG(10,("sid_to_uid: %s -> %u\n", sid_string_static(psid), + DEBUG(10,("sid_to_uid: %s -> %u\n", sid_to_string(sid_str, psid), (unsigned int)*puid )); store_uid_sid_cache(psid, *puid); @@ -697,6 +475,7 @@ success: NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid) { + fstring dom_name, name, sid_str; enum SID_NAME_USE name_type; if (fetch_gid_from_cache(pgid, psid)) @@ -710,9 +489,8 @@ NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid) if ( local_sid_to_gid(pgid, psid, &name_type) ) goto success; - if (!winbind_lookup_sid(NULL, psid, NULL, NULL, &name_type)) { - DEBUG(10,("sid_to_gid: no one knows the SID %s (tried local, then " - "winbind)\n", sid_string_static(psid))); + if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { + DEBUG(10,("sid_to_gid: no one knows the SID %s (tried local, then winbind)\n", sid_to_string(sid_str, psid))); return NT_STATUS_UNSUCCESSFUL; } @@ -736,13 +514,13 @@ NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid) if ( !winbind_sid_to_gid(pgid, psid) ) { DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid for sid %s\n", - sid_string_static(psid))); + sid_to_string(sid_str, psid) )); return NT_STATUS_UNSUCCESSFUL; } success: - DEBUG(10,("sid_to_gid: %s -> %u\n", sid_string_static(psid), - (unsigned int)*pgid )); + DEBUG(10,("sid_to_gid: %s -> %u\n", sid_to_string(sid_str, psid), + (unsigned int)*pgid )); store_gid_sid_cache(psid, *pgid); diff --git a/source/passdb/machine_sid.c b/source/passdb/machine_sid.c index 074a516bcb6..87ec27d34ea 100644 --- a/source/passdb/machine_sid.c +++ b/source/passdb/machine_sid.c @@ -198,27 +198,3 @@ void reset_global_sam_sid(void) { SAFE_FREE(global_sam_sid); } - -/***************************************************************** - Check if the SID is our domain SID (S-1-5-21-x-y-z). -*****************************************************************/ - -BOOL sid_check_is_domain(const DOM_SID *sid) -{ - return sid_equal(sid, get_global_sam_sid()); -} - -/***************************************************************** - Check if the SID is our domain SID (S-1-5-21-x-y-z). -*****************************************************************/ - -BOOL sid_check_is_in_our_domain(const DOM_SID *sid) -{ - DOM_SID dom_sid; - uint32 rid; - - sid_copy(&dom_sid, sid); - sid_split_rid(&dom_sid, &rid); - - return sid_equal(&dom_sid, get_global_sam_sid()); -} diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c index f9f6021d81b..20aa4e04f2f 100644 --- a/source/passdb/passdb.c +++ b/source/passdb/passdb.c @@ -566,8 +566,8 @@ BOOL pdb_gethexpwd(const char *p, unsigned char *pwd) return (False); for (i = 0; i < 32; i += 2) { - hinybble = toupper_ascii(p[i]); - lonybble = toupper_ascii(p[i + 1]); + hinybble = toupper(p[i]); + lonybble = toupper(p[i + 1]); p1 = strchr(hexchars, hinybble); p2 = strchr(hexchars, lonybble); @@ -616,8 +616,8 @@ BOOL pdb_gethexhours(const char *p, unsigned char *hours) } for (i = 0; i < 42; i += 2) { - hinybble = toupper_ascii(p[i]); - lonybble = toupper_ascii(p[i + 1]); + hinybble = toupper(p[i]); + lonybble = toupper(p[i + 1]); p1 = strchr(hexchars, hinybble); p2 = strchr(hexchars, lonybble); @@ -735,7 +735,7 @@ BOOL algorithmic_pdb_rid_is_user(uint32 rid) Look up a rid in the SAM we're responsible for (i.e. passdb) ********************************************************************/ -BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid, const char **name, +BOOL lookup_global_sam_rid(uint32 rid, fstring name, enum SID_NAME_USE *psid_name_use) { SAM_ACCOUNT *sam_account = NULL; @@ -760,7 +760,7 @@ BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid, const char **name, become_root(); if (pdb_getsampwsid(sam_account, &sid)) { unbecome_root(); /* -----> EXIT BECOME_ROOT() */ - *name = talloc_strdup(mem_ctx, pdb_get_username(sam_account)); + fstrcpy(name, pdb_get_username(sam_account)); *psid_name_use = SID_NAME_USER; pdb_free_sam(&sam_account); @@ -784,14 +784,14 @@ BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid, const char **name, map.nt_name)); } - *name = talloc_strdup(mem_ctx, map.nt_name); + fstrcpy(name, map.nt_name); *psid_name_use = map.sid_name_use; return True; } if (rid == DOMAIN_USER_RID_ADMIN) { *psid_name_use = SID_NAME_USER; - *name = talloc_strdup(mem_ctx, "Administrator"); + fstrcpy(name, "Administrator"); return True; } @@ -807,15 +807,13 @@ BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid, const char **name, DEBUG(5,("lookup_global_sam_rid: looking up uid %u %s\n", (unsigned int)uid, pw ? "succeeded" : "failed" )); - if ( !pw ) { - *name = talloc_asprintf(mem_ctx, "unix_user.%u", - (unsigned int)uid); - } else { - *name = talloc_strdup(mem_ctx, pw->pw_name ); - } + if ( !pw ) + fstr_sprintf(name, "unix_user.%u", (unsigned int)uid); + else + fstrcpy( name, pw->pw_name ); DEBUG(5,("lookup_global_sam_rid: found user %s for rid %u\n", - *name, (unsigned int)rid )); + name, (unsigned int)rid )); *psid_name_use = SID_NAME_USER; @@ -832,15 +830,13 @@ BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid, const char **name, DEBUG(5,("lookup_global_sam_rid: looking up gid %u %s\n", (unsigned int)gid, gr ? "succeeded" : "failed" )); - if( !gr ) { - *name = talloc_asprintf(mem_ctx, "unix_group.%u", - (unsigned int)gid); - } else { - *name = talloc_strdup(mem_ctx, gr->gr_name); - } + if( !gr ) + fstr_sprintf(name, "unix_group.%u", (unsigned int)gid); + else + fstrcpy( name, gr->gr_name); DEBUG(5,("lookup_global_sam_rid: found group %s for rid %u\n", - *name, (unsigned int)rid )); + name, (unsigned int)rid )); /* assume algorithmic groups are domain global groups */ @@ -854,13 +850,17 @@ BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid, const char **name, Convert a name into a SID. Used in the lookup name rpc. ********************************************************************/ -BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE *type) +BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psid_name_use) { + DOM_SID local_sid; + DOM_SID sid; fstring user; SAM_ACCOUNT *sam_account = NULL; struct group *grp; GROUP_MAP map; + *psid_name_use = SID_NAME_UNKNOWN; + /* * user may be quoted a const string, and map_username and * friends can modify it. Make a modifiable copy. JRA. @@ -868,6 +868,17 @@ BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE fstrcpy(user, c_user); + sid_copy(&local_sid, get_global_sam_sid()); + + if (map_name_to_wellknown_sid(&sid, psid_name_use, user)){ + fstring sid_str; + sid_copy( psid, &sid); + sid_to_string(sid_str, &sid); + DEBUG(10,("lookup_name: name %s = SID %s, type = %u\n", user, sid_str, + (unsigned int)*psid_name_use )); + return True; + } + (void)map_username(user); if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) { @@ -878,28 +889,10 @@ BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE become_root(); if (pdb_getsampwnam(sam_account, user)) { - const DOM_SID *user_sid; - unbecome_root(); - - user_sid = pdb_get_user_sid(sam_account); - - if (!sid_check_is_in_our_domain(user_sid)) { - DEBUG(0, ("User %s with invalid SID %s in passdb\n", - user, sid_string_static(user_sid))); - return False; - } - - sid_peek_rid(user_sid, rid); - - if (pdb_get_acct_ctrl(sam_account) & - (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST)) { - /* We have to filter them out in lsa_lookupnames, - * indicate that this is not a real user. */ - *type = SID_NAME_COMPUTER; - } else { - *type = SID_NAME_USER; - } + sid_copy(psid, pdb_get_user_sid(sam_account)); + *psid_name_use = SID_NAME_USER; + pdb_free_sam(&sam_account); return True; } @@ -912,51 +905,41 @@ BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE /* check if it's a mapped group */ if (pdb_getgrnam(&map, user)) { - - unbecome_root(); - - /* BUILTIN groups are looked up elsewhere */ - if (!sid_check_is_in_our_domain(&map.sid)) { - DEBUG(10, ("Found group %s (%s) not in our domain -- " - "ignoring.", user, - sid_string_static(&map.sid))); + /* yes it's a mapped group */ + sid_copy(&local_sid, &map.sid); + *psid_name_use = map.sid_name_use; + } else { + /* it's not a mapped group */ + grp = getgrnam(user); + if(!grp) { + unbecome_root(); /* ---> exit form block */ return False; } - /* yes it's a mapped group */ - sid_peek_rid(&map.sid, rid); - *type = map.sid_name_use; - return True; - } - - /* it's not a mapped group */ - grp = getgrnam(user); - if(!grp) { - unbecome_root(); /* ---> exit form block */ - return False; - } + /* + *check if it's mapped, if it is reply it doesn't exist + * + * that's to prevent this case: + * + * unix group ug is mapped to nt group ng + * someone does a lookup on ug + * we must not reply as it doesn't "exist" anymore + * for NT. For NT only ng exists. + * JFM, 30/11/2001 + */ - /* - *check if it's mapped, if it is reply it doesn't exist - * - * that's to prevent this case: - * - * unix group ug is mapped to nt group ng - * someone does a lookup on ug - * we must not reply as it doesn't "exist" anymore - * for NT. For NT only ng exists. - * JFM, 30/11/2001 - */ + if (pdb_getgrgid(&map, grp->gr_gid)){ + unbecome_root(); /* ---> exit form block */ + return False; + } - if (pdb_getgrgid(&map, grp->gr_gid)) { - unbecome_root(); /* ---> exit form block */ - return False; + sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid)); + *psid_name_use = SID_NAME_ALIAS; } unbecome_root(); /* END ROOT BLOCK */ - *rid = pdb_gid_to_group_rid(grp->gr_gid); - *type = SID_NAME_ALIAS; + sid_copy( psid, &local_sid); return True; } diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c index 4808af39081..875e264bf01 100644 --- a/source/passdb/pdb_interface.c +++ b/source/passdb/pdb_interface.c @@ -699,25 +699,6 @@ static NTSTATUS context_lookup_rids(struct pdb_context *context, rids, pp_names, pp_attrs); } -static NTSTATUS context_lookup_names(struct pdb_context *context, - const DOM_SID *domain_sid, - size_t num_names, - const char **pp_names, - uint32 *rids, - uint32 *pp_attrs) -{ - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - - if ((!context) || (!context->pdb_methods)) { - DEBUG(0, ("invalid pdb_context specified!\n")); - return ret; - } - - return context->pdb_methods->lookup_names(context->pdb_methods, - domain_sid, num_names, - pp_names, rids, pp_attrs); -} - static NTSTATUS context_get_account_policy(struct pdb_context *context, int policy_index, uint32 *value) { @@ -925,7 +906,6 @@ static NTSTATUS make_pdb_context(struct pdb_context **context) (*context)->pdb_enum_aliasmem = context_enum_aliasmem; (*context)->pdb_enum_alias_memberships = context_enum_alias_memberships; (*context)->pdb_lookup_rids = context_lookup_rids; - (*context)->pdb_lookup_names = context_lookup_names; (*context)->pdb_get_account_policy = context_get_account_policy; (*context)->pdb_set_account_policy = context_set_account_policy; @@ -1433,22 +1413,6 @@ NTSTATUS pdb_lookup_rids(const DOM_SID *domain_sid, num_rids, rids, names, attrs); } -NTSTATUS pdb_lookup_names(const DOM_SID *domain_sid, - int num_names, - const char **names, - uint32 *rids, - uint32 *attrs) -{ - struct pdb_context *pdb_context = pdb_get_static_context(False); - - if (!pdb_context) { - return NT_STATUS_NOT_IMPLEMENTED; - } - - return pdb_context->pdb_lookup_names(pdb_context, domain_sid, - num_names, names, rids, attrs); -} - BOOL pdb_get_account_policy(int policy_index, uint32 *value) { struct pdb_context *pdb_context = pdb_get_static_context(False); @@ -1691,11 +1655,14 @@ NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods, if (sid_check_is_builtin(domain_sid)) { for (i=0; i<num_rids; i++) { - const char *name; + fstring name; - if (lookup_builtin_rid(names, rids[i], &name)) { + if (lookup_builtin_rid(rids[i], name)) { attrs[i] = SID_NAME_ALIAS; - names[i] = name; + names[i] = talloc_strdup(names, name); + if (names[i] == NULL) { + return NT_STATUS_NO_MEMORY; + } DEBUG(5,("lookup_rids: %s:%d\n", names[i], attrs[i])); have_mapped = True; @@ -1713,69 +1680,14 @@ NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods, } for (i = 0; i < num_rids; i++) { - const char *name; - - if (lookup_global_sam_rid(names, rids[i], &name, &attrs[i])) { - names[i] = name; - DEBUG(5,("lookup_rids: %s:%d\n", names[i], attrs[i])); - have_mapped = True; - } else { - have_unmapped = True; - attrs[i] = SID_NAME_UNKNOWN; - } - } - - done: - - result = NT_STATUS_NONE_MAPPED; - - if (have_mapped) - result = have_unmapped ? STATUS_SOME_UNMAPPED : NT_STATUS_OK; - - return result; -} - -NTSTATUS pdb_default_lookup_names(struct pdb_methods *methods, - const DOM_SID *domain_sid, - int num_names, - const char **names, - uint32 *rids, - uint32 *attrs) -{ - int i; - NTSTATUS result; - BOOL have_mapped = False; - BOOL have_unmapped = False; - - if (sid_check_is_builtin(domain_sid)) { - - for (i=0; i<num_names; i++) { - uint32 rid; - - if (lookup_builtin_name(names[i], &rid)) { - attrs[i] = SID_NAME_ALIAS; - rids[i] = rid; - DEBUG(5,("lookup_rids: %s:%d\n", - names[i], attrs[i])); - have_mapped = True; - } else { - have_unmapped = True; - attrs[i] = SID_NAME_UNKNOWN; - } - } - goto done; - } - - /* Should not happen, but better check once too many */ - if (!sid_check_is_domain(domain_sid)) { - return NT_STATUS_INVALID_HANDLE; - } - - for (i = 0; i < num_names; i++) { - const char *name; - - if (lookup_global_sam_rid(names, rids[i], &name, &attrs[i])) { - names[i] = name; + fstring tmpname; + enum SID_NAME_USE type; + + if (lookup_global_sam_rid(rids[i], tmpname, &type)) { + attrs[i] = (uint32)type; + names[i] = talloc_strdup(names, tmpname); + if (names[i] == NULL) + return NT_STATUS_NO_MEMORY; DEBUG(5,("lookup_rids: %s:%d\n", names[i], attrs[i])); have_mapped = True; } else { diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c index b35ce18eee5..9f0d530424e 100644 --- a/source/passdb/pdb_ldap.c +++ b/source/passdb/pdb_ldap.c @@ -3638,10 +3638,6 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods, goto done; } - if (msg != NULL) { - ldap_msgfree(msg); - } - /* Same game for groups */ { @@ -3727,7 +3723,8 @@ char *get_ldap_filter(TALLOC_CTX *mem_ctx, const char *username) escaped = escape_ldap_string_alloc(username); if (escaped == NULL) goto done; - result = talloc_string_sub(mem_ctx, filter, "%u", username); + filter = realloc_string_sub(filter, "%u", username); + result = talloc_strdup(mem_ctx, filter); done: SAFE_FREE(filter); @@ -4074,9 +4071,6 @@ static BOOL ldapgroup2displayentry(struct ldap_search_state *state, vals = ldap_get_values(ld, entry, "sambaGroupType"); if ((vals == NULL) || (vals[0] == NULL)) { DEBUG(5, ("\"sambaGroupType\" not found\n")); - if (vals != NULL) { - ldap_value_free(vals); - } return False; } @@ -4084,12 +4078,9 @@ static BOOL ldapgroup2displayentry(struct ldap_search_state *state, if ((state->group_type != 0) && ((state->group_type != group_type))) { - ldap_value_free(vals); return False; } - ldap_value_free(vals); - /* display name is the NT group name */ vals = ldap_get_values(ld, entry, "displayName"); @@ -4129,9 +4120,6 @@ static BOOL ldapgroup2displayentry(struct ldap_search_state *state, vals = ldap_get_values(ld, entry, "sambaSid"); if ((vals == NULL) || (vals[0] == NULL)) { DEBUG(0, ("\"objectSid\" not found\n")); - if (vals != NULL) { - ldap_value_free(vals); - } return False; } diff --git a/source/passdb/pdb_nds.c b/source/passdb/pdb_nds.c index cf2d1d7c8a8..1ec96932231 100644 --- a/source/passdb/pdb_nds.c +++ b/source/passdb/pdb_nds.c @@ -807,7 +807,7 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods, if((success != True) || (got_clear_text_pw == True)) { - rc = smb_ldap_setup_full_conn(&ld, ldap_state->location); + rc = smb_ldap_setup_full_conn(ld, ldap_state->location); if (rc) { return NT_STATUS_INVALID_CONNECTION; } diff --git a/source/passdb/pdb_pgsql.c b/source/passdb/pdb_pgsql.c index 196fe8f855d..632903c1ac3 100644 --- a/source/passdb/pdb_pgsql.c +++ b/source/passdb/pdb_pgsql.c @@ -368,7 +368,7 @@ static NTSTATUS pgsqlsam_getsampwnam ( struct pdb_methods *methods, SAM_ACCOUNT lowercasename = smb_xstrdup(sname); l = strlen(lowercasename); for(i = 0; i < l; i++) { - lowercasename[i] = tolower_ascii(lowercasename[i]); + lowercasename[i] = tolower(lowercasename[i]); } result = pgsqlsam_select_by_field( methods, user, SQL_SEARCH_USER_NAME, lowercasename ) ; diff --git a/source/passdb/util_builtin.c b/source/passdb/util_builtin.c deleted file mode 100644 index 12a98d24ddb..00000000000 --- a/source/passdb/util_builtin.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Translate BUILTIN names to SIDs and vice versa - Copyright (C) Volker Lendecke 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -struct rid_name_map { - uint32 rid; - const char *name; -}; - -static const struct rid_name_map builtin_aliases[] = { - { BUILTIN_ALIAS_RID_ADMINS, "Administrators" }, - { BUILTIN_ALIAS_RID_USERS, "Users" }, - { BUILTIN_ALIAS_RID_GUESTS, "Guests" }, - { BUILTIN_ALIAS_RID_POWER_USERS, "Power Users" }, - { BUILTIN_ALIAS_RID_ACCOUNT_OPS, "Account Operators" }, - { BUILTIN_ALIAS_RID_SYSTEM_OPS, "Server Operators" }, - { BUILTIN_ALIAS_RID_PRINT_OPS, "Print Operators" }, - { BUILTIN_ALIAS_RID_BACKUP_OPS, "Backup Operators" }, - { BUILTIN_ALIAS_RID_REPLICATOR, "Replicator" }, - { BUILTIN_ALIAS_RID_RAS_SERVERS, "RAS Servers" }, - { BUILTIN_ALIAS_RID_PRE_2K_ACCESS, "Pre-Windows 2000 Compatible Access" }, - { 0, NULL}}; - -/******************************************************************* - Look up a rid in the BUILTIN domain - ********************************************************************/ -BOOL lookup_builtin_rid(TALLOC_CTX *mem_ctx, uint32 rid, const char **name) -{ - const struct rid_name_map *aliases = builtin_aliases; - - while (aliases->name != NULL) { - if (rid == aliases->rid) { - *name = talloc_strdup(mem_ctx, aliases->name); - return True; - } - aliases++; - } - - return False; -} - -/******************************************************************* - Look up a name in the BUILTIN domain - ********************************************************************/ -BOOL lookup_builtin_name(const char *name, uint32 *rid) -{ - const struct rid_name_map *aliases = builtin_aliases; - - while (aliases->name != NULL) { - if (strequal(name, aliases->name)) { - *rid = aliases->rid; - return True; - } - aliases++; - } - - return False; -} - -/***************************************************************** - Return the name of the BUILTIN domain -*****************************************************************/ - -const char *builtin_domain_name(void) -{ - return "BUILTIN"; -} - -/***************************************************************** - Check if the SID is the builtin SID (S-1-5-32). -*****************************************************************/ - -BOOL sid_check_is_builtin(const DOM_SID *sid) -{ - return sid_equal(sid, &global_sid_Builtin); -} - -/***************************************************************** - Check if the SID is one of the builtin SIDs (S-1-5-32-a). -*****************************************************************/ - -BOOL sid_check_is_in_builtin(const DOM_SID *sid) -{ - DOM_SID dom_sid; - uint32 rid; - - sid_copy(&dom_sid, sid); - sid_split_rid(&dom_sid, &rid); - - return sid_equal(&dom_sid, &global_sid_Builtin); -} - diff --git a/source/passdb/util_sam_sid.c b/source/passdb/util_sam_sid.c new file mode 100644 index 00000000000..822b7f6a349 --- /dev/null +++ b/source/passdb/util_sam_sid.c @@ -0,0 +1,238 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Luke Kenneth Caseson Leighton 1998-1999 + Copyright (C) Jeremy Allison 1999 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#define MAX_SID_NAMES 7 + +typedef struct _known_sid_users { + uint32 rid; + enum SID_NAME_USE sid_name_use; + const char *known_user_name; +} known_sid_users; + +struct sid_name_map_info +{ + const DOM_SID *sid; + const char *name; + const known_sid_users *known_users; +}; + +static const known_sid_users everyone_users[] = { + { 0, SID_NAME_WKN_GRP, "Everyone" }, + {0, (enum SID_NAME_USE)0, NULL}}; + +static const known_sid_users creator_owner_users[] = { + { 0, SID_NAME_WKN_GRP, "Creator Owner" }, + { 1, SID_NAME_WKN_GRP, "Creator Group" }, + {0, (enum SID_NAME_USE)0, NULL}}; + +static const known_sid_users nt_authority_users[] = { + { 1, SID_NAME_WKN_GRP, "Dialup" }, + { 2, SID_NAME_WKN_GRP, "Network"}, + { 3, SID_NAME_WKN_GRP, "Batch"}, + { 4, SID_NAME_WKN_GRP, "Interactive"}, + { 6, SID_NAME_WKN_GRP, "Service"}, + { 7, SID_NAME_WKN_GRP, "AnonymousLogon"}, + { 8, SID_NAME_WKN_GRP, "Proxy"}, + { 9, SID_NAME_WKN_GRP, "ServerLogon"}, + { 10, SID_NAME_WKN_GRP, "Self"}, + { 11, SID_NAME_WKN_GRP, "Authenticated Users"}, + { 12, SID_NAME_WKN_GRP, "Restricted"}, + { 13, SID_NAME_WKN_GRP, "Terminal Server User"}, + { 14, SID_NAME_WKN_GRP, "Remote Interactive Logon"}, + { 15, SID_NAME_WKN_GRP, "This Organization"}, + { 18, SID_NAME_WKN_GRP, "SYSTEM"}, + { 19, SID_NAME_WKN_GRP, "Local Service"}, + { 20, SID_NAME_WKN_GRP, "Network Service"}, + { 0, (enum SID_NAME_USE)0, NULL}}; + +static const known_sid_users builtin_groups[] = { + { BUILTIN_ALIAS_RID_ADMINS, SID_NAME_ALIAS, "Administrators" }, + { BUILTIN_ALIAS_RID_USERS, SID_NAME_ALIAS, "Users" }, + { BUILTIN_ALIAS_RID_GUESTS, SID_NAME_ALIAS, "Guests" }, + { BUILTIN_ALIAS_RID_POWER_USERS, SID_NAME_ALIAS, "Power Users" }, + { BUILTIN_ALIAS_RID_ACCOUNT_OPS, SID_NAME_ALIAS, "Account Operators" }, + { BUILTIN_ALIAS_RID_SYSTEM_OPS, SID_NAME_ALIAS, "Server Operators" }, + { BUILTIN_ALIAS_RID_PRINT_OPS, SID_NAME_ALIAS, "Print Operators" }, + { BUILTIN_ALIAS_RID_BACKUP_OPS, SID_NAME_ALIAS, "Backup Operators" }, + { BUILTIN_ALIAS_RID_REPLICATOR, SID_NAME_ALIAS, "Replicator" }, + { BUILTIN_ALIAS_RID_RAS_SERVERS, SID_NAME_ALIAS, "RAS Servers" }, + { BUILTIN_ALIAS_RID_PRE_2K_ACCESS, SID_NAME_ALIAS, "Pre-Windows 2000 Compatible Access" }, + { 0, (enum SID_NAME_USE)0, NULL}}; + +static struct sid_name_map_info special_domains[] = { + { &global_sid_Builtin, "BUILTIN", builtin_groups }, + { &global_sid_World_Domain, "", everyone_users }, + { &global_sid_Creator_Owner_Domain, "", creator_owner_users }, + { &global_sid_NT_Authority, "NT Authority", nt_authority_users }, + { NULL, NULL, NULL }}; + +/************************************************************************** + Turns a domain SID into a name, returned in the nt_domain argument. +***************************************************************************/ + +BOOL map_domain_sid_to_name(const DOM_SID *sid, fstring nt_domain) +{ + fstring sid_str; + int i = 0; + + sid_to_string(sid_str, sid); + + DEBUG(5,("map_domain_sid_to_name: %s\n", sid_str)); + + while (special_domains[i].sid != NULL) { + DEBUG(5,("map_domain_sid_to_name: compare: %s\n", + sid_string_static(special_domains[i].sid))); + if (sid_equal(special_domains[i].sid, sid)) { + fstrcpy(nt_domain, special_domains[i].name); + DEBUG(5,("map_domain_sid_to_name: found '%s'\n", + nt_domain)); + return True; + } + i++; + } + + DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n", + sid_string_static(sid))); + + return False; +} + +/************************************************************************** + Looks up a known username from one of the known domains. +***************************************************************************/ + +BOOL lookup_special_sid(const DOM_SID *sid, const char **domain, + const char **name, enum SID_NAME_USE *type) +{ + int i; + DOM_SID dom_sid; + uint32 rid; + const known_sid_users *users = NULL; + + sid_copy(&dom_sid, sid); + if (!sid_split_rid(&dom_sid, &rid)) { + DEBUG(2, ("Could not split rid from SID\n")); + return False; + } + + for (i=0; special_domains[i].sid != NULL; i++) { + if (sid_equal(&dom_sid, special_domains[i].sid)) { + *domain = special_domains[i].name; + users = special_domains[i].known_users; + break; + } + } + + if (users == NULL) { + DEBUG(10, ("SID %s is no special sid\n", + sid_string_static(sid))); + return False; + } + + for (i=0; users[i].known_user_name != NULL; i++) { + if (rid == users[i].rid) { + *name = users[i].known_user_name; + *type = users[i].sid_name_use; + return True; + } + } + + DEBUG(10, ("RID of special SID %s not found\n", + sid_string_static(sid))); + + return False; +} + +/******************************************************************* + Look up a rid in the BUILTIN domain + ********************************************************************/ +BOOL lookup_builtin_rid(uint32 rid, fstring name) +{ + const known_sid_users *aliases = builtin_groups; + int i; + + for (i=0; aliases[i].known_user_name != NULL; i++) { + if (rid == aliases[i].rid) { + fstrcpy(name, aliases[i].known_user_name); + return True; + } + } + + return False; +} + +/***************************************************************** + Check if the SID is our domain SID (S-1-5-21-x-y-z). +*****************************************************************/ + +BOOL sid_check_is_domain(const DOM_SID *sid) +{ + return sid_equal(sid, get_global_sam_sid()); +} + +/***************************************************************** + Check if the SID is our domain SID (S-1-5-21-x-y-z). +*****************************************************************/ + +BOOL sid_check_is_in_our_domain(const DOM_SID *sid) +{ + DOM_SID dom_sid; + uint32 rid; + + sid_copy(&dom_sid, sid); + sid_split_rid(&dom_sid, &rid); + + return sid_equal(&dom_sid, get_global_sam_sid()); +} + +/************************************************************************** + Try and map a name to one of the well known SIDs. +***************************************************************************/ + +BOOL map_name_to_wellknown_sid(DOM_SID *sid, enum SID_NAME_USE *use, const char *name) +{ + int i, j; + + DEBUG(10,("map_name_to_wellknown_sid: looking up %s\n", name)); + + for (i=0; special_domains[i].sid != NULL; i++) { + const known_sid_users *users = special_domains[i].known_users; + + if (users == NULL) + continue; + + for (j=0; users[j].known_user_name != NULL; j++) { + if ( strequal(users[j].known_user_name, name) ) { + sid_copy(sid, special_domains[i].sid); + sid_append_rid(sid, users[j].rid); + *use = users[j].sid_name_use; + return True; + } + } + } + + return False; +} + + diff --git a/source/passdb/util_wellknown.c b/source/passdb/util_wellknown.c deleted file mode 100644 index 8caae3b2a01..00000000000 --- a/source/passdb/util_wellknown.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Lookup routines for well-known SIDs - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Luke Kenneth Caseson Leighton 1998-1999 - Copyright (C) Jeremy Allison 1999 - Copyright (C) Volker Lendecke 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -struct rid_name_map { - uint32 rid; - const char *name; -}; - -struct sid_name_map_info -{ - const DOM_SID *sid; - const char *name; - const struct rid_name_map *known_users; -}; - -static const struct rid_name_map everyone_users[] = { - { 0, "Everyone" }, - { 0, NULL}}; - -static const struct rid_name_map creator_owner_users[] = { - { 0, "Creator Owner" }, - { 1, "Creator Group" }, - { 0, NULL}}; - -static const struct rid_name_map nt_authority_users[] = { - { 1, "Dialup" }, - { 2, "Network"}, - { 3, "Batch"}, - { 4, "Interactive"}, - { 6, "Service"}, - { 7, "AnonymousLogon"}, - { 8, "Proxy"}, - { 9, "ServerLogon"}, - { 10, "Self"}, - { 11, "Authenticated Users"}, - { 12, "Restricted"}, - { 13, "Terminal Server User"}, - { 14, "Remote Interactive Logon"}, - { 15, "This Organization"}, - { 18, "SYSTEM"}, - { 19, "Local Service"}, - { 20, "Network Service"}, - { 0, NULL}}; - -static struct sid_name_map_info special_domains[] = { - { &global_sid_World_Domain, "", everyone_users }, - { &global_sid_Creator_Owner_Domain, "", creator_owner_users }, - { &global_sid_NT_Authority, "NT Authority", nt_authority_users }, - { NULL, NULL, NULL }}; - -/************************************************************************** - Looks up a known username from one of the known domains. -***************************************************************************/ - -BOOL lookup_wellknown_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, - const char **domain, const char **name) -{ - int i; - DOM_SID dom_sid; - uint32 rid; - const struct rid_name_map *users = NULL; - - sid_copy(&dom_sid, sid); - if (!sid_split_rid(&dom_sid, &rid)) { - DEBUG(2, ("Could not split rid from SID\n")); - return False; - } - - for (i=0; special_domains[i].sid != NULL; i++) { - if (sid_equal(&dom_sid, special_domains[i].sid)) { - *domain = talloc_strdup(mem_ctx, - special_domains[i].name); - users = special_domains[i].known_users; - break; - } - } - - if (users == NULL) { - DEBUG(10, ("SID %s is no special sid\n", - sid_string_static(sid))); - return False; - } - - for (i=0; users[i].name != NULL; i++) { - if (rid == users[i].rid) { - *name = talloc_strdup(mem_ctx, users[i].name); - return True; - } - } - - DEBUG(10, ("RID of special SID %s not found\n", - sid_string_static(sid))); - - return False; -} - -/************************************************************************** - Try and map a name to one of the well known SIDs. -***************************************************************************/ - -BOOL lookup_wellknown_name(TALLOC_CTX *mem_ctx, const char *name, - DOM_SID *sid, const char **domain) -{ - int i, j; - - DEBUG(10,("map_name_to_wellknown_sid: looking up %s\n", name)); - - for (i=0; special_domains[i].sid != NULL; i++) { - const struct rid_name_map *users = - special_domains[i].known_users; - - if (users == NULL) - continue; - - for (j=0; users[j].name != NULL; j++) { - if ( strequal(users[j].name, name) ) { - sid_copy(sid, special_domains[i].sid); - sid_append_rid(sid, users[j].rid); - *domain = talloc_strdup( - mem_ctx, special_domains[i].name); - return True; - } - } - } - - return False; -} diff --git a/source/rpc_server/srv_lsa_nt.c b/source/rpc_server/srv_lsa_nt.c index 6cd673550ec..15d420538ef 100644 --- a/source/rpc_server/srv_lsa_nt.c +++ b/source/rpc_server/srv_lsa_nt.c @@ -96,7 +96,7 @@ static void init_dom_query(DOM_QUERY *d_q, const char *dom_name, DOM_SID *dom_si init_dom_ref - adds a domain if it's not already in, returns the index. ***************************************************************************/ -static int init_dom_ref(DOM_R_REF *ref, const char *dom_name, DOM_SID *dom_sid) +static int init_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid) { int num = 0; @@ -135,76 +135,67 @@ static int init_dom_ref(DOM_R_REF *ref, const char *dom_name, DOM_SID *dom_sid) init_lsa_rid2s ***************************************************************************/ -static int init_lsa_rid2s(TALLOC_CTX *mem_ctx, - DOM_R_REF *ref, DOM_RID2 *rid2, - int num_entries, UNISTR2 *name, - int flags) +static void init_lsa_rid2s(DOM_R_REF *ref, DOM_RID2 *rid2, + int num_entries, UNISTR2 *name, + uint32 *mapped_count, BOOL endian) { - int mapped_count, i; + int i; + int total = 0; + *mapped_count = 0; SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS); - mapped_count = 0; - become_root(); /* lookup_name can require root privs */ for (i = 0; i < num_entries; i++) { BOOL status = False; DOM_SID sid; - uint32 rid; - int dom_idx; - char *full_name; - const char *domain; - enum SID_NAME_USE type = SID_NAME_UNKNOWN; + uint32 rid = 0xffffffff; + int dom_idx = -1; + pstring full_name; + fstring dom_name, user; + enum SID_NAME_USE name_type = SID_NAME_UNKNOWN; /* Split name into domain and user component */ - if (rpcstr_pull_unistr2_talloc(mem_ctx, &full_name, - &name[i]) < 0) { - DEBUG(0, ("pull_ucs2_talloc failed\n")); - return 0; - } + unistr2_to_ascii(full_name, &name[i], sizeof(full_name)); + split_domain_name(full_name, dom_name, user); - DEBUG(5, ("init_lsa_rid2s: looking up name %s\n", full_name)); + /* Lookup name */ - /* We can ignore the result of lookup_name, it will not touch - "type" if it's not successful */ + DEBUG(5, ("init_lsa_rid2s: looking up name %s\n", full_name)); - lookup_name(mem_ctx, full_name, flags, &domain, NULL, - &sid, &type); + status = lookup_name(dom_name, user, &sid, &name_type); - DEBUG(5, ("init_lsa_rid2s: %s\n", status ? "found" : - "not found")); + if((name_type == SID_NAME_UNKNOWN) && (lp_server_role() == ROLE_DOMAIN_MEMBER) && (strncmp(dom_name, full_name, strlen(dom_name)) != 0)) { + DEBUG(5, ("init_lsa_rid2s: domain name not provided and local account not found, using member domain\n")); + fstrcpy(dom_name, lp_workgroup()); + status = lookup_name(dom_name, user, &sid, &name_type); + } - switch (type) { - case SID_NAME_USER: - case SID_NAME_DOM_GRP: - case SID_NAME_DOMAIN: - case SID_NAME_ALIAS: - case SID_NAME_WKN_GRP: - /* Leave these unchanged */ - break; - default: - /* Don't hand out anything but the list above */ - type = SID_NAME_UNKNOWN; - break; + if (name_type == SID_NAME_WKN_GRP) { + /* BUILTIN aliases are still aliases :-) */ + name_type = SID_NAME_ALIAS; } - rid = 0; - dom_idx = -1; + DEBUG(5, ("init_lsa_rid2s: %s\n", status ? "found" : + "not found")); - if (type != SID_NAME_UNKNOWN) { + if (status && name_type != SID_NAME_UNKNOWN) { sid_split_rid(&sid, &rid); - dom_idx = init_dom_ref(ref, domain, &sid); - mapped_count++; + dom_idx = init_dom_ref(ref, dom_name, &sid); + (*mapped_count)++; + } else { + dom_idx = -1; + rid = 0; + name_type = SID_NAME_UNKNOWN; } - init_dom_rid2(&rid2[i], rid, type, dom_idx); + init_dom_rid2(&rid2[total], rid, name_type, dom_idx); + total++; } unbecome_root(); - - return mapped_count; } /*************************************************************************** @@ -259,44 +250,42 @@ static void init_lsa_trans_names(TALLOC_CTX *ctx, DOM_R_REF *ref, LSA_TRANS_NAME DOM_SID find_sid = sid[i].sid; uint32 rid = 0xffffffff; int dom_idx = -1; - const char *name, *domain; - enum SID_NAME_USE type = SID_NAME_UNKNOWN; + fstring name, dom_name; + enum SID_NAME_USE sid_name_use = (enum SID_NAME_USE)0; - DEBUG(5, ("init_lsa_trans_names: looking up sid %s\n", - sid_string_static(&find_sid))); + sid_to_string(name, &find_sid); + DEBUG(5, ("init_lsa_trans_names: looking up sid %s\n", name)); /* Lookup sid from winbindd */ - status = lookup_sid(ctx, &find_sid, &domain, &name, &type); + status = lookup_sid(&find_sid, dom_name, name, &sid_name_use); DEBUG(5, ("init_lsa_trans_names: %s\n", status ? "found" : "not found")); if (!status) { - type = SID_NAME_UNKNOWN; - domain = talloc_strdup(ctx, ""); - name = talloc_strdup(ctx, - sid_string_static(&find_sid)); + sid_name_use = SID_NAME_UNKNOWN; + memset(dom_name, '\0', sizeof(dom_name)); + sid_to_string(name, &find_sid); dom_idx = -1; - DEBUG(10,("init_lsa_trans_names: added unknown user " - "'%s' to referenced list.\n", name )); + DEBUG(10,("init_lsa_trans_names: added unknown user '%s' to " + "referenced list.\n", name )); } else { (*mapped_count)++; /* Store domain sid in ref array */ if (find_sid.num_auths == 5) { sid_split_rid(&find_sid, &rid); } - dom_idx = init_dom_ref(ref, domain, &find_sid); + dom_idx = init_dom_ref(ref, dom_name, &find_sid); - DEBUG(10,("init_lsa_trans_names: added %s '%s\\%s' " - "(%d) to referenced list.\n", - sid_type_lookup(type), domain, name, type)); + DEBUG(10,("init_lsa_trans_names: added %s '%s\\%s' (%d) to referenced list.\n", + sid_type_lookup(sid_name_use), dom_name, name, sid_name_use )); } init_lsa_trans_name(&trn->name[total], &trn->uni_name[total], - type, name, dom_idx); + sid_name_use, name, dom_idx); total++; } @@ -512,7 +501,7 @@ NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_E uint32 num_domains; NTSTATUS nt_status; - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; /* check if the user have enough rights */ @@ -550,7 +539,7 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF r_u->status = NT_STATUS_OK; - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) return NT_STATUS_INVALID_HANDLE; switch (q_u->info_class) { @@ -668,7 +657,7 @@ NTSTATUS _lsa_lookup_sids(pipes_struct *p, LSA_Q_LOOKUP_SIDS *q_u, LSA_R_LOOKUP_ ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF); names = TALLOC_ZERO_P(p->mem_ctx, LSA_TRANS_NAME_ENUM); - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) { + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) { r_u->status = NT_STATUS_INVALID_HANDLE; goto done; } @@ -708,22 +697,16 @@ NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP DOM_R_REF *ref; DOM_RID2 *rids; uint32 mapped_count = 0; - int flags = 0; if (num_entries > MAX_LOOKUP_SIDS) { num_entries = MAX_LOOKUP_SIDS; DEBUG(5,("_lsa_lookup_names: truncating name lookup list to %d\n", num_entries)); } - /* Probably the lookup_level is some sort of bitmask. */ - if (q_u->lookup_level == 1) { - flags = LOOKUP_NAME_ALL; - } - ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF); rids = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_RID2, num_entries); - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) { + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) { r_u->status = NT_STATUS_INVALID_HANDLE; goto done; } @@ -737,11 +720,10 @@ NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP if (!ref || !rids) return NT_STATUS_NO_MEMORY; - /* set up the LSA Lookup RIDs response */ - mapped_count = init_lsa_rid2s(p->mem_ctx, ref, rids, num_entries, - names, flags); done: + /* set up the LSA Lookup RIDs response */ + init_lsa_rid2s(ref, rids, num_entries, names, &mapped_count, p->endian); if (NT_STATUS_IS_OK(r_u->status)) { if (mapped_count == 0) r_u->status = NT_STATUS_NONE_MAPPED; @@ -835,7 +817,7 @@ NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIV DEBUG(10,("_lsa_enum_privs: enum_context:%d total entries:%d\n", enum_context, num_privs)); - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) return NT_STATUS_INVALID_HANDLE; /* check if the user have enough rights @@ -882,7 +864,7 @@ NTSTATUS _lsa_priv_get_dispname(pipes_struct *p, LSA_Q_PRIV_GET_DISPNAME *q_u, L fstring name_asc; const char *description; - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) return NT_STATUS_INVALID_HANDLE; /* check if the user have enough rights */ @@ -930,7 +912,7 @@ NTSTATUS _lsa_enum_accounts(pipes_struct *p, LSA_Q_ENUM_ACCOUNTS *q_u, LSA_R_ENU LSA_SID_ENUM *sids=&r_u->sids; NTSTATUS ret; - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) return NT_STATUS_INVALID_HANDLE; if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION)) @@ -1006,7 +988,7 @@ NTSTATUS _lsa_create_account(pipes_struct *p, LSA_Q_CREATEACCOUNT *q_u, LSA_R_CR struct lsa_info *info; /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) return NT_STATUS_INVALID_HANDLE; /* check if the user have enough rights */ @@ -1054,7 +1036,7 @@ NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENAC struct lsa_info *info; /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) return NT_STATUS_INVALID_HANDLE; /* check if the user have enough rights */ @@ -1097,7 +1079,7 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, prs_struct *ps, LSA_Q_ENUMPRIVS PRIVILEGE_SET privileges; /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; if ( !get_privileges_for_sids( &mask, &info->sid, 1 ) ) @@ -1127,13 +1109,15 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, prs_struct *ps, LSA_Q_ENUMPRIVS NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA_R_GETSYSTEMACCOUNT *r_u) { struct lsa_info *info=NULL; + fstring name, dom_name; + enum SID_NAME_USE type; /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; - if (!lookup_sid(p->mem_ctx, &info->sid, NULL, NULL, NULL)) + if (!lookup_sid(&info->sid, dom_name, name, &type)) return NT_STATUS_ACCESS_DENIED; /* @@ -1161,7 +1145,7 @@ NTSTATUS _lsa_setsystemaccount(pipes_struct *p, LSA_Q_SETSYSTEMACCOUNT *q_u, LSA r_u->status = NT_STATUS_OK; /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; /* check to see if the pipe_user is a Domain Admin since @@ -1191,7 +1175,7 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u struct current_user user; /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; /* check to see if the pipe_user is root or a Domain Admin since @@ -1232,7 +1216,7 @@ NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEP struct current_user user; /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; /* check to see if the pipe_user is root or a Domain Admin since @@ -1275,7 +1259,7 @@ NTSTATUS _lsa_query_secobj(pipes_struct *p, LSA_Q_QUERY_SEC_OBJ *q_u, LSA_R_QUER r_u->status = NT_STATUS_OK; /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) return NT_STATUS_INVALID_HANDLE; /* check if the user have enough rights */ @@ -1332,7 +1316,7 @@ NTSTATUS _lsa_query_info2(pipes_struct *p, LSA_Q_QUERY_INFO2 *q_u, LSA_R_QUERY_I ZERO_STRUCT(guid); r_u->status = NT_STATUS_OK; - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) return NT_STATUS_INVALID_HANDLE; switch (q_u->info_class) { @@ -1394,7 +1378,7 @@ NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; /* check to see if the pipe_user is a Domain Admin since @@ -1452,7 +1436,7 @@ NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u, /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; /* check to see if the pipe_user is a Domain Admin since @@ -1514,7 +1498,7 @@ NTSTATUS _lsa_enum_acct_rights(pipes_struct *p, LSA_Q_ENUM_ACCT_RIGHTS *q_u, LSA /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; /* according to an NT4 PDC, you can add privileges to SIDs even without @@ -1555,7 +1539,7 @@ NTSTATUS _lsa_lookup_priv_value(pipes_struct *p, LSA_Q_LOOKUP_PRIV_VALUE *q_u, L /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; unistr2_to_ascii(name, &q_u->privname.unistring, sizeof(name)); diff --git a/source/rpc_server/srv_samr.c b/source/rpc_server/srv_samr.c index e8fd86ba467..cbfad5688e1 100644 --- a/source/rpc_server/srv_samr.c +++ b/source/rpc_server/srv_samr.c @@ -679,37 +679,6 @@ static BOOL api_samr_connect4(pipes_struct *p) return True; } -/******************************************************************* - api_samr_connect5 - ********************************************************************/ - -static BOOL api_samr_connect5(pipes_struct *p) -{ - SAMR_Q_CONNECT5 q_u; - SAMR_R_CONNECT5 r_u; - prs_struct *data = &p->in_data.data; - prs_struct *rdata = &p->out_data.rdata; - - ZERO_STRUCT(q_u); - ZERO_STRUCT(r_u); - - /* grab the samr open policy */ - if(!samr_io_q_connect5("", &q_u, data, 0)) { - DEBUG(0,("api_samr_connect5: unable to unmarshall SAMR_Q_CONNECT5.\n")); - return False; - } - - r_u.status = _samr_connect5(p, &q_u, &r_u); - - /* store the response in the SMB stream */ - if(!samr_io_r_connect5("", &r_u, rdata, 0)) { - DEBUG(0,("api_samr_connect5: unable to marshall SAMR_R_CONNECT5.\n")); - return False; - } - - return True; -} - /********************************************************************** api_samr_lookup_domain **********************************************************************/ @@ -1523,8 +1492,7 @@ static struct api_struct api_samr_cmds [] = {"SAMR_GET_USRDOM_PWINFO" , SAMR_GET_USRDOM_PWINFO, api_samr_get_usrdom_pwinfo}, {"SAMR_QUERY_DOMAIN_INFO2", SAMR_QUERY_DOMAIN_INFO2, api_samr_query_domain_info2}, {"SAMR_SET_DOMAIN_INFO" , SAMR_SET_DOMAIN_INFO , api_samr_set_dom_info }, - {"SAMR_CONNECT4" , SAMR_CONNECT4 , api_samr_connect4 }, - {"SAMR_CONNECT5" , SAMR_CONNECT5 , api_samr_connect5 } + {"SAMR_CONNECT4" , SAMR_CONNECT4 , api_samr_connect4 } }; void samr_get_pipe_fns( struct api_struct **fns, int *n_fns ) diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c index 8f8c035c9cd..d2ec30142b3 100644 --- a/source/rpc_server/srv_samr_nt.c +++ b/source/rpc_server/srv_samr_nt.c @@ -573,7 +573,7 @@ NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN /* find the connection policy handle. */ - if ( !find_policy_by_hnd(p, &q_u->pol, (void**)(void *)&info) ) + if ( !find_policy_by_hnd(p, &q_u->pol, (void**)&info) ) return NT_STATUS_INVALID_HANDLE; status = access_check_samr_function( info->acc_granted, @@ -627,7 +627,7 @@ NTSTATUS _samr_get_usrdom_pwinfo(pipes_struct *p, SAMR_Q_GET_USRDOM_PWINFO *q_u, r_u->status = NT_STATUS_OK; /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->user_pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->user_pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; if (!sid_check_is_in_our_domain(&info->sid)) @@ -665,7 +665,7 @@ static BOOL get_lsa_policy_samr_sid( pipes_struct *p, POLICY_HND *pol, struct samr_info *info = NULL; /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, pol, (void **)&info)) return False; if (!info) @@ -803,7 +803,7 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u, r_u->status = NT_STATUS_OK; /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, @@ -936,7 +936,7 @@ NTSTATUS _samr_enum_dom_groups(pipes_struct *p, SAMR_Q_ENUM_DOM_GROUPS *q_u, SAM r_u->status = NT_STATUS_OK; /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; r_u->status = access_check_samr_function(info->acc_granted, @@ -995,7 +995,7 @@ NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, S uint32 num_aliases = 0; /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; r_u->status = access_check_samr_function(info->acc_granted, @@ -1061,7 +1061,7 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, r_u->status = NT_STATUS_UNSUCCESSFUL; /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; /* @@ -1366,7 +1366,9 @@ NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAM NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LOOKUP_NAMES *r_u) { uint32 rid[MAX_SAM_ENTRIES]; + uint32 local_rid; enum SID_NAME_USE type[MAX_SAM_ENTRIES]; + enum SID_NAME_USE local_type; int i; int num_rids = q_u->num_names2; DOM_SID pol_sid; @@ -1398,30 +1400,42 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO for (i = 0; i < num_rids; i++) { fstring name; + DOM_SID sid; int ret; r_u->status = NT_STATUS_NONE_MAPPED; - type[i] = SID_NAME_UNKNOWN; rid [i] = 0xffffffff; + type[i] = SID_NAME_UNKNOWN; ret = rpcstr_pull(name, q_u->uni_name[i].buffer, sizeof(name), q_u->uni_name[i].uni_str_len*2, 0); - if (ret <= 0) { - continue; - } - - if (sid_check_is_builtin(&pol_sid)) { - if (lookup_builtin_name(name, &rid[i])) { - type[i] = SID_NAME_ALIAS; + /* + * we are only looking for a name + * the SID we get back can be outside + * the scope of the pol_sid + * + * in clear: it prevents to reply to domain\group: yes + * when only builtin\group exists. + * + * a cleaner code is to add the sid of the domain we're looking in + * to the local_lookup_name function. + */ + + if ((ret > 0) && local_lookup_name(name, &sid, &local_type)) { + sid_split_rid(&sid, &local_rid); + + if (sid_equal(&sid, &pol_sid)) { + rid[i]=local_rid; + + /* Windows does not return WKN_GRP here, even + * on lookups in builtin */ + type[i] = (local_type == SID_NAME_WKN_GRP) ? + SID_NAME_ALIAS : local_type; + + r_u->status = NT_STATUS_OK; } - } else { - lookup_global_sam_name(name, &rid[i], &type[i]); - } - - if (type[i] != SID_NAME_UNKNOWN) { - r_u->status = NT_STATUS_OK; - } + } } init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, (uint32 *)type, r_u->status); @@ -1672,41 +1686,6 @@ static NTSTATUS get_user_info_7(TALLOC_CTX *mem_ctx, SAM_USER_INFO_7 *id7, DOM_S return NT_STATUS_OK; } - -/************************************************************************* - get_user_info_9. Only gives out primary group SID. - *************************************************************************/ -static NTSTATUS get_user_info_9(TALLOC_CTX *mem_ctx, SAM_USER_INFO_9 * id9, DOM_SID *user_sid) -{ - SAM_ACCOUNT *smbpass=NULL; - BOOL ret; - NTSTATUS nt_status; - - nt_status = pdb_init_sam_talloc(mem_ctx, &smbpass); - - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - - become_root(); - ret = pdb_getsampwsid(smbpass, user_sid); - unbecome_root(); - - if (ret==False) { - DEBUG(4,("User %s not found\n", sid_string_static(user_sid))); - return NT_STATUS_NO_SUCH_USER; - } - - DEBUG(3,("User:[%s]\n", pdb_get_username(smbpass) )); - - ZERO_STRUCTP(id9); - init_sam_user_info9(id9, pdb_get_group_rid(smbpass) ); - - pdb_free_sam(&smbpass); - - return NT_STATUS_OK; -} - /************************************************************************* get_user_info_16. Safe. Only gives out acb bits. *************************************************************************/ @@ -1878,7 +1857,7 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_ r_u->status=NT_STATUS_OK; /* search for the handle */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; domain_sid = info->sid; @@ -1899,8 +1878,6 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_ /* ok! user info levels (lots: see MSDEV help), off we go... */ ctr->switch_value = q_u->switch_value; - DEBUG(5,("_samr_query_userinfo: user info level: %d\n", q_u->switch_value)); - switch (q_u->switch_value) { case 7: ctr->info.id7 = TALLOC_ZERO_P(p->mem_ctx, SAM_USER_INFO_7); @@ -1910,14 +1887,6 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_ if (!NT_STATUS_IS_OK(r_u->status = get_user_info_7(p->mem_ctx, ctr->info.id7, &info->sid))) return r_u->status; break; - case 9: - ctr->info.id9 = TALLOC_ZERO_P(p->mem_ctx, SAM_USER_INFO_9); - if (ctr->info.id9 == NULL) - return NT_STATUS_NO_MEMORY; - - if (!NT_STATUS_IS_OK(r_u->status = get_user_info_9(p->mem_ctx, ctr->info.id9, &info->sid))) - return r_u->status; - break; case 16: ctr->info.id16 = TALLOC_ZERO_P(p->mem_ctx, SAM_USER_INFO_16); if (ctr->info.id16 == NULL) @@ -2125,7 +2094,7 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA DEBUG(5,("_samr_query_dom_info: %d\n", __LINE__)); /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)(void *)&info)) { + if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)&info)) { return NT_STATUS_INVALID_HANDLE; } @@ -2196,11 +2165,7 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA /* AS ROOT !!! */ - { - uint32 ul; - pdb_get_account_policy(AP_TIME_TO_LOGOUT, &ul); - u_logout = (time_t)ul; - } + pdb_get_account_policy(AP_TIME_TO_LOGOUT, (unsigned int *)&u_logout); /* !AS ROOT */ @@ -2278,44 +2243,6 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA return r_u->status; } -/* W2k3 seems to use the same check for all 3 objects that can be created via - * SAMR, if you try to create for example "Dialup" as an alias it says - * "NT_STATUS_USER_EXISTS". This is racy, but we can't really lock the user - * database. */ - -static NTSTATUS can_create(TALLOC_CTX *mem_ctx, const char *new_name) -{ - enum SID_NAME_USE type; - BOOL result; - - DEBUG(10, ("Checking whether [%s] can be created\n", new_name)); - - become_root(); - /* Lookup in our local databases (only LOOKUP_NAME_ISOLATED set) - * whether the name already exists */ - result = lookup_name(mem_ctx, new_name, LOOKUP_NAME_ISOLATED, - NULL, NULL, NULL, &type); - unbecome_root(); - - if (!result) { - DEBUG(10, ("%s does not exist, can create it\n", new_name)); - return NT_STATUS_OK; - } - - DEBUG(5, ("trying to create %s, exists as %s\n", - new_name, sid_type_lookup(type))); - - if (type == SID_NAME_DOM_GRP) { - return NT_STATUS_GROUP_EXISTS; - } - if (type == SID_NAME_ALIAS) { - return NT_STATUS_ALIAS_EXISTS; - } - - /* Yes, the default is NT_STATUS_USER_EXISTS */ - return NT_STATUS_USER_EXISTS; -} - /******************************************************************* _samr_create_user Create an account, can be either a normal user or a machine. @@ -2363,11 +2290,19 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA rpcstr_pull(account, user_account.buffer, sizeof(account), user_account.uni_str_len*2, 0); strlower_m(account); - nt_status = can_create(p->mem_ctx, account); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; + pdb_init_sam(&sam_pass); + + become_root(); + ret = pdb_getsampwnam(sam_pass, account); + unbecome_root(); + if (ret == True) { + /* this account exists: say so */ + pdb_free_sam(&sam_pass); + return NT_STATUS_USER_EXISTS; } + pdb_free_sam(&sam_pass); + /********************************************************************* * HEADS UP! If we have to create a new user account, we have to get * a new RID from somewhere. This used to be done by the passdb @@ -2640,60 +2575,6 @@ NTSTATUS _samr_connect4(pipes_struct *p, SAMR_Q_CONNECT4 *q_u, SAMR_R_CONNECT4 * return r_u->status; } -/******************************************************************* - samr_connect5 - ********************************************************************/ - -NTSTATUS _samr_connect5(pipes_struct *p, SAMR_Q_CONNECT5 *q_u, SAMR_R_CONNECT5 *r_u) -{ - struct samr_info *info = NULL; - SEC_DESC *psd = NULL; - uint32 acc_granted; - uint32 des_access = q_u->access_mask; - NTSTATUS nt_status; - POLICY_HND pol; - size_t sd_size; - - - DEBUG(5,("_samr_connect5: %d\n", __LINE__)); - - ZERO_STRUCTP(r_u); - - /* Access check */ - - if (!pipe_access_check(p)) { - DEBUG(3, ("access denied to samr_connect5\n")); - r_u->status = NT_STATUS_ACCESS_DENIED; - return r_u->status; - } - - make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0); - se_map_generic(&des_access, &sam_generic_mapping); - - nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, - NULL, 0, des_access, &acc_granted, "_samr_connect5"); - - if ( !NT_STATUS_IS_OK(nt_status) ) - return nt_status; - - /* associate the user's SID and access granted with the new handle. */ - if ((info = get_samr_info_by_sid(NULL)) == NULL) - return NT_STATUS_NO_MEMORY; - - info->acc_granted = acc_granted; - info->status = q_u->access_mask; - - /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, &pol, free_samr_info, (void *)info)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - - DEBUG(5,("_samr_connect: %d\n", __LINE__)); - - init_samr_r_connect5(r_u, &pol, NT_STATUS_OK); - - return r_u->status; -} - /********************************************************************** api_samr_lookup_domain **********************************************************************/ @@ -2706,7 +2587,7 @@ NTSTATUS _samr_lookup_domain(pipes_struct *p, SAMR_Q_LOOKUP_DOMAIN *q_u, SAMR_R_ r_u->status = NT_STATUS_OK; - if (!find_policy_by_hnd(p, &q_u->connect_pol, (void**)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->connect_pol, (void**)&info)) return NT_STATUS_INVALID_HANDLE; /* win9x user manager likes to use SA_RIGHT_SAM_ENUM_DOMAINS here. @@ -2722,12 +2603,8 @@ NTSTATUS _samr_lookup_domain(pipes_struct *p, SAMR_Q_LOOKUP_DOMAIN *q_u, SAMR_R_ ZERO_STRUCT(sid); - if (strequal(domain_name, builtin_domain_name())) { - sid_copy(&sid, &global_sid_Builtin); - } else { - if (!secrets_fetch_domain_sid(domain_name, &sid)) { - r_u->status = NT_STATUS_NO_SUCH_DOMAIN; - } + if (!secrets_fetch_domain_sid(domain_name, &sid)) { + r_u->status = NT_STATUS_NO_SUCH_DOMAIN; } DEBUG(2,("Returning domain sid for domain %s -> %s\n", domain_name, sid_string_static(&sid))); @@ -2786,7 +2663,7 @@ NTSTATUS _samr_enum_domains(pipes_struct *p, SAMR_Q_ENUM_DOMAINS *q_u, SAMR_R_EN r_u->status = NT_STATUS_OK; - if (!find_policy_by_hnd(p, &q_u->pol, (void**)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void**)&info)) return NT_STATUS_INVALID_HANDLE; if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, SA_RIGHT_SAM_ENUM_DOMAINS, "_samr_enum_domains"))) { @@ -2841,7 +2718,7 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A /* append the alias' RID to it */ if (!sid_append_rid(&sid, alias_rid)) - return NT_STATUS_NO_SUCH_ALIAS; + return NT_STATUS_NO_SUCH_USER; /*check if access can be granted as requested by client. */ @@ -2858,21 +2735,12 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A if ( !NT_STATUS_IS_OK(status) ) return status; - { - /* Check we actually have the requested alias */ - enum SID_NAME_USE type; - BOOL result; - - become_root(); - result = lookup_sid(NULL, &sid, NULL, NULL, &type); - unbecome_root(); - - if (!result || (type != SID_NAME_ALIAS)) { - return NT_STATUS_NO_SUCH_ALIAS; - } - } + /* + * we should check if the rid really exist !!! + * JFM. + */ - /* associate the alias SID with the new handle. */ + /* associate the user's SID with the new handle. */ if ((info = get_samr_info_by_sid(&sid)) == NULL) return NT_STATUS_NO_MEMORY; @@ -2888,11 +2756,12 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A /******************************************************************* set_user_info_7 ********************************************************************/ -static NTSTATUS set_user_info_7(TALLOC_CTX *mem_ctx, - const SAM_USER_INFO_7 *id7, SAM_ACCOUNT *pwd) +static NTSTATUS set_user_info_7(const SAM_USER_INFO_7 *id7, SAM_ACCOUNT *pwd) { fstring new_name; + SAM_ACCOUNT *check_acct = NULL; NTSTATUS rc; + BOOL check_rc; if (id7 == NULL) { DEBUG(5, ("set_user_info_7: NULL id7\n")); @@ -2915,9 +2784,13 @@ static NTSTATUS set_user_info_7(TALLOC_CTX *mem_ctx, simply that the rename fails with a slightly different status code (like UNSUCCESSFUL instead of ALREADY_EXISTS). */ - rc = can_create(mem_ctx, new_name); - if (!NT_STATUS_IS_OK(rc)) { - return rc; + pdb_init_sam(&check_acct); + check_rc = pdb_getsampwnam(check_acct, new_name); + pdb_free_sam(&check_acct); + + if (check_rc == True) { + /* this account exists: say so */ + return NT_STATUS_USER_EXISTS; } rc = pdb_rename_sam_account(pwd, new_name); @@ -3434,8 +3307,7 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_ switch (switch_value) { case 7: - r_u->status = set_user_info_7(p->mem_ctx, - ctr->info.id7, pwd); + r_u->status = set_user_info_7(ctr->info.id7, pwd); break; case 16: if (!set_user_info_16(ctr->info.id16, pwd)) @@ -3492,7 +3364,7 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u, DEBUG(5,("_samr_query_useraliases: %d\n", __LINE__)); /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; ntstatus1 = access_check_samr_function(info->acc_granted, SA_RIGHT_DOMAIN_LOOKUP_ALIAS_BY_MEM, "_samr_query_useraliases"); @@ -4269,10 +4141,9 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S unistr2_to_ascii(name, &q_u->uni_acct_desc, sizeof(name)-1); - r_u->status = can_create(p->mem_ctx, name); - if (!NT_STATUS_IS_OK(r_u->status)) { - return r_u->status; - } + /* check if group already exist */ + if ((grp=getgrnam(name)) != NULL) + return NT_STATUS_GROUP_EXISTS; se_priv_copy( &se_rights, &se_add_users ); can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); @@ -4365,11 +4236,6 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S se_priv_copy( &se_rights, &se_add_users ); can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); - result = can_create(p->mem_ctx, name); - if (!NT_STATUS_IS_OK(result)) { - return result; - } - /******** BEGIN SeAddUsers BLOCK *********/ if ( can_add_accounts ) @@ -4786,7 +4652,7 @@ NTSTATUS _samr_query_domain_info2(pipes_struct *p, DEBUG(5,("_samr_query_domain_info2: %d\n", __LINE__)); /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)(void *)&info)) + if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; switch (q_u->switch_value) { diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c index 5a179dbf478..fed73db043f 100644 --- a/source/smbd/chgpasswd.c +++ b/source/smbd/chgpasswd.c @@ -153,13 +153,9 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, DEBUG(3, ("More weirdness, could not open %s\n", slavedev)); return (False); } -#if defined(I_PUSH) && defined(I_FIND) - if (ioctl(slave, I_FIND, "ptem") == 0) { - ioctl(slave, I_PUSH, "ptem"); - } - if (ioctl(slave, I_FIND, "ldterm") == 0) { - ioctl(slave, I_PUSH, "ldterm"); - } +#ifdef I_PUSH + ioctl(slave, I_PUSH, "ptem"); + ioctl(slave, I_PUSH, "ldterm"); #elif defined(TIOCSCTTY) if (ioctl(slave, TIOCSCTTY, 0) < 0) { diff --git a/source/smbd/close.c b/source/smbd/close.c index c0d87b1b212..24ca7a40927 100644 --- a/source/smbd/close.c +++ b/source/smbd/close.c @@ -130,13 +130,9 @@ static void notify_deferred_opens(struct share_mode_lock *lck) */ schedule_deferred_open_smb_message(e->op_mid); } else { - char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; - - share_mode_entry_to_message(msg, e); - become_root(); message_send_pid(e->pid, MSG_SMB_OPEN_RETRY, - msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + e, sizeof(*e), True); unbecome_root(); } } @@ -198,7 +194,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) * This prevents race conditions with the file being created. JRA. */ - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fsp->fsp_name); if (lck == NULL) { DEBUG(0, ("close_file: Could not get share mode lock for file %s\n", fsp->fsp_name)); @@ -233,43 +229,20 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) */ if (normal_close && delete_file) { - SMB_STRUCT_STAT sbuf; - DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", fsp->fsp_name)); - - /* We can only delete the file if the name we have - is still valid and hasn't been renamed. */ - - if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) { - DEBUG(5,("close_file: file %s. Delete on close was set " - "and stat failed with error %s\n", - fsp->fsp_name, strerror(errno) )); - } else { - if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) { - DEBUG(5,("close_file: file %s. Delete on close was set and " - "dev and/or inode does not match\n", - fsp->fsp_name )); - DEBUG(5,("close_file: file %s. stored dev = %x, inode = %.0f " - "stat dev = %x, inode = %.0f\n", - fsp->fsp_name, - (unsigned int)fsp->dev, (double)fsp->inode, - (unsigned int)sbuf.st_dev, (double)sbuf.st_ino )); - - } else if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { - /* - * This call can potentially fail as another smbd may have - * had the file open with delete on close set and deleted - * it when its last reference to this file went away. Hence - * we log this but not at debug level zero. - */ - - DEBUG(5,("close_file: file %s. Delete on close was set " - "and unlink failed with error %s\n", - fsp->fsp_name, strerror(errno) )); - } - process_pending_change_notify_queue((time_t)0); + if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { + /* + * This call can potentially fail as another smbd may have + * had the file open with delete on close set and deleted + * it when its last reference to this file went away. Hence + * we log this but not at debug level zero. + */ + + DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \ +with error %s\n", fsp->fsp_name, strerror(errno) )); } + process_pending_change_notify_queue((time_t)0); } talloc_free(lck); @@ -334,7 +307,7 @@ static int close_directory(files_struct *fsp, BOOL normal_close) * reference to a directory also. */ - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fsp->fsp_name); if (lck == NULL) { DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name)); diff --git a/source/smbd/lanman.c b/source/smbd/lanman.c index 4778702e7ac..1e2a2488515 100644 --- a/source/smbd/lanman.c +++ b/source/smbd/lanman.c @@ -1837,6 +1837,9 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para gid_t *gids; size_t num_groups; size_t i; + fstring grp_domain; + fstring grp_name; + enum SID_NAME_USE grp_type; struct passwd *passwd; NTSTATUS result; @@ -1893,12 +1896,9 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para goto out; for (i=0; i<num_groups; i++) { - - const char *grp_name; - if ( lookup_sid(sampw->mem_ctx, &sids[i], NULL, &grp_name, - NULL) ) { - pstrcpy(p, grp_name); + if ( lookup_sid(&sids[i], grp_domain, grp_name, &grp_type) ) { + pstrcpy(p, grp_name); p += 21; count++; } diff --git a/source/smbd/mangle_hash.c b/source/smbd/mangle_hash.c index 2092f430c07..30befd2c849 100644 --- a/source/smbd/mangle_hash.c +++ b/source/smbd/mangle_hash.c @@ -372,8 +372,8 @@ static BOOL is_mangled(const char *s, int snum) magic = strchr_m( s, magic_char ); while( magic && magic[1] && magic[2] ) { /* 3 chars, 1st is magic. */ if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */ - && isbasechar( toupper_ascii(magic[1]) ) /* is 2nd char basechar? */ - && isbasechar( toupper_ascii(magic[2]) ) ) /* is 3rd char basechar? */ + && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */ + && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */ return( True ); /* If all above, then true, */ magic = strchr_m( magic+1, magic_char ); /* else seek next magic. */ } @@ -426,7 +426,7 @@ static void cache_mangled_name( const char mangled_name[13], char *raw_name ) s1 = strrchr( mangled_name_key, '.' ); if( s1 && (s2 = strrchr( raw_name, '.' )) ) { size_t i = 1; - while( s1[i] && (tolower_ascii( s1[i] ) == s2[i]) ) + while( s1[i] && (tolower( s1[i] ) == s2[i]) ) i++; if( !s1[i] && !s2[i] ) { /* Truncate at the '.' */ diff --git a/source/smbd/mangle_hash2.c b/source/smbd/mangle_hash2.c index 0a161c9e769..335ba8e2ef9 100644 --- a/source/smbd/mangle_hash2.c +++ b/source/smbd/mangle_hash2.c @@ -560,7 +560,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, if (! FLAG_CHECK(lead_chars[i], FLAG_ASCII)) { lead_chars[i] = '_'; } - lead_chars[i] = toupper_ascii(lead_chars[i]); + lead_chars[i] = toupper(lead_chars[i]); } for (;i<mangle_prefix;i++) { lead_chars[i] = '_'; @@ -580,7 +580,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, for (i=1; extension_length < 3 && dot_p[i]; i++) { char c = dot_p[i]; if (FLAG_CHECK(c, FLAG_ASCII)) { - extension[extension_length++] = toupper_ascii(c); + extension[extension_length++] = toupper(c); } } } @@ -679,10 +679,10 @@ static void init_tables(void) char_flags[c2] |= FLAG_POSSIBLE2; char_flags[c3] |= FLAG_POSSIBLE3; char_flags[c4] |= FLAG_POSSIBLE4; - char_flags[tolower_ascii(c1)] |= FLAG_POSSIBLE1; - char_flags[tolower_ascii(c2)] |= FLAG_POSSIBLE2; - char_flags[tolower_ascii(c3)] |= FLAG_POSSIBLE3; - char_flags[tolower_ascii(c4)] |= FLAG_POSSIBLE4; + char_flags[tolower(c1)] |= FLAG_POSSIBLE1; + char_flags[tolower(c2)] |= FLAG_POSSIBLE2; + char_flags[tolower(c3)] |= FLAG_POSSIBLE3; + char_flags[tolower(c4)] |= FLAG_POSSIBLE4; char_flags[(unsigned char)'.'] |= FLAG_POSSIBLE4; } diff --git a/source/smbd/message.c b/source/smbd/message.c index fd28df0d801..e975da3e153 100644 --- a/source/smbd/message.c +++ b/source/smbd/message.c @@ -65,7 +65,7 @@ static void msg_deliver(void) * Incoming message is in DOS codepage format. Convert to UNIX. */ - if ((len = (int)convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **)(void *)&msg, True)) < 0 || !msg) { + if ((len = (int)convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **) &msg, True)) < 0 || !msg) { DEBUG(3,("Conversion failed, delivering message in DOS codepage format\n")); for (i = 0; i < msgpos;) { if (msgbuf[i] == '\r' && i < (msgpos-1) && msgbuf[i+1] == '\n') { diff --git a/source/smbd/msdfs.c b/source/smbd/msdfs.c index 1279fe185d2..a4f371b18ff 100644 --- a/source/smbd/msdfs.c +++ b/source/smbd/msdfs.c @@ -146,7 +146,7 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) return False; } - set_conn_connectpath(conn, connpath); + string_set(&conn->connectpath, connpath); if (!smbd_vfs_init(conn)) { DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n")); diff --git a/source/smbd/notify.c b/source/smbd/notify.c index df3d45d20b5..bc76cfb322f 100644 --- a/source/smbd/notify.c +++ b/source/smbd/notify.c @@ -212,16 +212,10 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, BOOL init_change_notify(void) { - cnotify = NULL; - #if HAVE_KERNEL_CHANGE_NOTIFY - if (cnotify == NULL && lp_kernel_change_notify()) + if (lp_kernel_change_notify()) cnotify = kernel_notify_init(); #endif -#if HAVE_FAM_CHANGE_NOTIFY - if (cnotify == NULL && lp_fam_change_notify()) - cnotify = fam_notify_init(); -#endif if (!cnotify) cnotify = hash_notify_init(); if (!cnotify) { diff --git a/source/smbd/notify_fam.c b/source/smbd/notify_fam.c deleted file mode 100644 index 413340266ec..00000000000 --- a/source/smbd/notify_fam.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * FAM file notification support. - * - * Copyright (c) James Peach 2005 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "includes.h" - -#ifdef HAVE_FAM_CHANGE_NOTIFY - -#include <fam.h> - -/* NOTE: There are multiple versions of FAM floating around the net, each with - * slight differences from the original SGI FAM implementation. In this file, - * we rely only on the SGI features and do not assume any extensions. For - * example, we do not look at FAMErrno, because it is not set by the original - * implementation. - * - * Random FAM links: - * http://oss.sgi.com/projects/fam/ - * http://savannah.nongnu.org/projects/fam/ - * http://sourceforge.net/projects/bsdfam/ - */ - -struct fam_req_info -{ - FAMRequest req; - int generation; - enum FAMCodes code; - enum - { - /* We are waiting for an event. */ - FAM_REQ_MONITORING, - /* An event has been receive, but we haven't been able to send it back - * to the client yet. It is stashed in the code member. - */ - FAM_REQ_FIRED - } state; -}; - -/* Don't initialise this until the first register request. We want a single - * FAM connection for each worker smbd. If we allow the master (parent) smbd to - * open a FAM connection, multiple processes talking on the same socket will - * undoubtedly create havoc. - */ -static FAMConnection global_fc; -static int global_fc_generation; - -#define FAM_TRACE 8 -#define FAM_TRACE_LOW 10 - -#define FAM_NOTIFY_CHECK_TIMEOUT 1 /* secs */ -#define FAM_EVENT_DRAIN ((uint32_t)(-1)) - -/* Turn a FAM event code into a string. Don't rely on specific code values, - * because that might not work across all flavours of FAM. - */ -static const char * -fam_event_str(enum FAMCodes code) -{ - static struct { enum FAMCodes code; const char * name; } evstr[] = - { - { FAMChanged, "FAMChanged"}, - { FAMDeleted, "FAMDeleted"}, - { FAMStartExecuting, "FAMStartExecuting"}, - { FAMStopExecuting, "FAMStopExecuting"}, - { FAMCreated, "FAMCreated"}, - { FAMMoved, "FAMMoved"}, - { FAMAcknowledge, "FAMAcknowledge"}, - { FAMExists, "FAMExists"}, - { FAMEndExist, "FAMEndExist"} - }; - - int i; - - for (i = 0; i < ARRAY_SIZE(evstr); ++i) { - if (code == evstr[i].code) - return(evstr[i].name); - } - - return("<unknown>"); -} - -static BOOL -fam_check_reconnect(void) -{ - if (FAMCONNECTION_GETFD(&global_fc) < 0) { - fstring name; - - global_fc_generation++; - snprintf(name, sizeof(name), "smbd (%lu)", (unsigned long)sys_getpid()); - - if (FAMOpen2(&global_fc, name) < 0) { - DEBUG(0, ("failed to connect to FAM service\n")); - return(False); - } - } - - return(True); -} - -static BOOL -fam_monitor_path(connection_struct * conn, - struct fam_req_info * info, - const char * path, - uint32 flags) -{ - SMB_STRUCT_STAT st; - pstring fullpath; - - DEBUG(FAM_TRACE, ("requesting FAM notifications for '%s'\n", path)); - - /* FAM needs an absolute pathname. */ - - /* It would be better to use reduce_name() here, but reduce_name does not - * actually return the reduced result. How utterly un-useful. - */ - pstrcpy(fullpath, path); - if (!canonicalize_path(conn, fullpath)) { - DEBUG(0, ("failed to canonicalize path '%s'\n", path)); - return(False); - } - - if (*fullpath != '/') { - DEBUG(0, ("canonicalized path '%s' into `%s`\n", path, fullpath)); - DEBUGADD(0, ("but expected an absolute path\n")); - return(False); - } - - if (SMB_VFS_STAT(conn, path, &st) < 0) { - DEBUG(0, ("stat of '%s' failed: %s\n", path, strerror(errno))); - return(False); - } - /* Start monitoring this file or directory. We hand the state structure to - * both the caller and the FAM library so we can match up the caller's - * status requests with FAM notifications. - */ - if (S_ISDIR(st.st_mode)) { - FAMMonitorDirectory(&global_fc, fullpath, &(info->req), info); - } else { - FAMMonitorFile(&global_fc, fullpath, &(info->req), info); - } - - /* Grr. On IRIX, neither of the monitor functions return a status. */ - - /* We will stay in initialising state until we see the FAMendExist message - * for this file. - */ - info->state = FAM_REQ_MONITORING; - info->generation = global_fc_generation; - return(True); -} - -static BOOL -fam_handle_event(enum FAMCodes code, uint32 flags) -{ -#define F_CHANGE_MASK (FILE_NOTIFY_CHANGE_FILE | \ - FILE_NOTIFY_CHANGE_ATTRIBUTES | \ - FILE_NOTIFY_CHANGE_SIZE | \ - FILE_NOTIFY_CHANGE_LAST_WRITE | \ - FILE_NOTIFY_CHANGE_LAST_ACCESS | \ - FILE_NOTIFY_CHANGE_CREATION | \ - FILE_NOTIFY_CHANGE_EA | \ - FILE_NOTIFY_CHANGE_SECURITY) - -#define F_DELETE_MASK (FILE_NOTIFY_CHANGE_FILE_NAME | \ - FILE_NOTIFY_CHANGE_DIR_NAME) - -#define F_CREATE_MASK (FILE_NOTIFY_CHANGE_FILE_NAME | \ - FILE_NOTIFY_CHANGE_DIR_NAME) - - switch (code) { - case FAMChanged: - if (flags & F_CHANGE_MASK) - return(True); - break; - case FAMDeleted: - if (flags & F_DELETE_MASK) - return(True); - break; - case FAMCreated: - if (flags & F_CREATE_MASK) - return(True); - break; - default: - /* Ignore anything else. */ - break; - } - - return(False); - -#undef F_CHANGE_MASK -#undef F_DELETE_MASK -#undef F_CREATE_MASK -} - -static BOOL -fam_pump_events(struct fam_req_info * info, uint32_t flags) -{ - FAMEvent ev; - - for (;;) { - - /* If we are draining the event queue we must keep going until we find - * the correct FAMAcknowledge event or the connection drops. Otherwise - * we should stop when there are no more events pending. - */ - if (flags != FAM_EVENT_DRAIN && !FAMPending(&global_fc)) { - break; - } - - if (FAMNextEvent(&global_fc, &ev) < 0) { - DEBUG(0, ("failed to fetch pending FAM event\n")); - DEBUGADD(0, ("resetting FAM connection\n")); - FAMClose(&global_fc); - FAMCONNECTION_GETFD(&global_fc) = -1; - return(False); - } - - DEBUG(FAM_TRACE_LOW, ("FAM event %s on '%s' for request %d\n", - fam_event_str(ev.code), ev.filename, ev.fr.reqnum)); - - switch (ev.code) { - case FAMAcknowledge: - /* FAM generates an ACK event when we cancel a monitor. We need - * this to know when it is safe to free out request state - * structure. - */ - if (info->generation == global_fc_generation && - info->req.reqnum == ev.fr.reqnum && - flags == FAM_EVENT_DRAIN) { - return(True); - } - - case FAMEndExist: - case FAMExists: - /* Ignore these. FAM sends these enumeration events when we - * start monitoring. If we are monitoring a directory, we will - * get a FAMExists event for each directory entry. - */ - - /* TODO: we might be able to use these to implement recursive - * monitoring of entire subtrees. - */ - case FAMMoved: - /* These events never happen. A move or rename shows up as a - * create/delete pair. - */ - case FAMStartExecuting: - case FAMStopExecuting: - /* We might get these, but we just don't care. */ - break; - - case FAMChanged: - case FAMDeleted: - case FAMCreated: - if (info->generation != global_fc_generation) { - /* Ignore this; the req number can't be matched. */ - break; - } - - if (info->req.reqnum == ev.fr.reqnum) { - /* This is the event the caller was interested in. */ - DEBUG(FAM_TRACE, ("handling FAM %s event on '%s'\n", - fam_event_str(ev.code), ev.filename)); - /* Ignore events if we are draining this request. */ - if (flags != FAM_EVENT_DRAIN) { - return(fam_handle_event(ev.code, flags)); - } - break; - } else { - /* Caller doesn't want this event. Stash the result so we - * can come back to it. Unfortunately, FAM doesn't - * guarantee to give us back evinfo. - */ - struct fam_req_info * evinfo = - (struct fam_req_info *)ev.userdata; - - if (evinfo) { - DEBUG(FAM_TRACE, ("storing FAM %s event for winter\n", - fam_event_str(ev.code))); - evinfo->state = FAM_REQ_FIRED; - evinfo->code = ev.code; - } else { - DEBUG(2, ("received FAM %s notification for %s, " - "but userdata was unexpectedly NULL\n", - fam_event_str(ev.code), ev.filename)); - } - break; - } - - default: - DEBUG(0, ("ignoring unknown FAM event code %d for `%s`\n", - ev.code, ev.filename)); - } - } - - /* No more notifications pending. */ - return(False); -} - -static BOOL -fam_test_connection(void) -{ - FAMConnection fc; - - /* On IRIX FAMOpen2 leaks 960 bytes in 48 blocks. It's a deliberate leak - * in the library and there's nothing we can do about it here. - */ - if (FAMOpen2(&fc, "smbd probe") < 0) - return(False); - - FAMClose(&fc); - return(True); -} - -/* ------------------------------------------------------------------------- */ - -static void * -fam_register_notify(connection_struct * conn, - char * path, - uint32 flags) -{ - struct fam_req_info * info; - - if (!fam_check_reconnect()) { - return(False); - } - - if ((info = SMB_MALLOC_P(struct fam_req_info)) == NULL) { - DEBUG(0, ("malloc of %d bytes failed\n", sizeof(struct fam_req_info))); - return(NULL); - } - - if (fam_monitor_path(conn, info, path, flags)) { - return(info); - } else { - SAFE_FREE(info); - return(NULL); - } -} - -static BOOL -fam_check_notify(connection_struct * conn, - uint16_t vuid, - char * path, - uint32_t flags, - void * data, - time_t when) -{ - struct fam_req_info * info; - - info = (struct fam_req_info *)data; - SMB_ASSERT(info != NULL); - - DEBUG(10, ("checking FAM events for `%s`\n", path)); - - if (info->state == FAM_REQ_FIRED) { - DEBUG(FAM_TRACE, ("handling previously fired FAM %s event\n", - fam_event_str(info->code))); - info->state = FAM_REQ_MONITORING; - return(fam_handle_event(info->code, flags)); - } - - if (!fam_check_reconnect()) { - return(False); - } - - if (info->generation != global_fc_generation) { - DEBUG(FAM_TRACE, ("reapplying stale FAM monitor to %s\n", path)); - fam_monitor_path(conn, info, path, flags); - return(False); - } - - return(fam_pump_events(info, flags)); -} - -static void -fam_remove_notify(void * data) -{ - struct fam_req_info * info; - - if ((info = (struct fam_req_info *)data) == NULL) - return; - - /* No need to reconnect. If the FAM connection is gone, there's no need to - * cancel and we can safely let FAMCancelMonitor fail. If it we - * reconnected, then the generation check will stop us cancelling the wrong - * request. - */ - - if (info->generation == global_fc_generation) { - DEBUG(FAM_TRACE, ("removing FAM notification for request %d\n", - info->req.reqnum)); - FAMCancelMonitor(&global_fc, &(info->req)); - - /* Soak up all events until the FAMAcknowledge. We can't free - * our request state until we are sure there are no more events in - * flight. - */ - fam_pump_events(info, FAM_EVENT_DRAIN); - } - - SAFE_FREE(info); -} - -struct cnotify_fns * fam_notify_init(void) -{ - static struct cnotify_fns global_fam_notify = - { - fam_register_notify, - fam_check_notify, - fam_remove_notify, - FAM_NOTIFY_CHECK_TIMEOUT - }; - - /* TODO: rather than relying on FAM_NOTIFY_CHECK_TIMEOUT, we should have an - * API to push the FAM fd into the global server fd set. - */ - - FAMCONNECTION_GETFD(&global_fc) = -1; - - if (!fam_test_connection()) { - DEBUG(0, ("FAM file change notifications not available\n")); - return(NULL); - } - - DEBUG(FAM_TRACE, ("enabling FAM change notifications\n")); - return &global_fam_notify; -} - -#endif /* HAVE_FAM_CHANGE_NOTIFY */ diff --git a/source/smbd/open.c b/source/smbd/open.c index 0ccac592d61..27e83b76983 100644 --- a/source/smbd/open.c +++ b/source/smbd/open.c @@ -683,17 +683,12 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) if (delay_it) { BOOL ret; - char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; - DEBUG(10, ("Sending break request to PID %s\n", procid_str_static(&exclusive->pid))); exclusive->op_mid = get_current_mid(); - - share_mode_entry_to_message(msg, exclusive); - become_root(); ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, - msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + exclusive, sizeof(*exclusive), True); unbecome_root(); if (!ret) { DEBUG(3, ("Could not send oplock break message\n")); @@ -1132,7 +1127,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, spurious oplock break. */ /* Now remove the deferred open entry under lock. */ - lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, state->dev, state->inode, + fname); if (lck == NULL) { DEBUG(0, ("could not get share mode lock\n")); } else { @@ -1342,9 +1338,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, dev = psbuf->st_dev; inode = psbuf->st_ino; - lck = get_share_mode_lock(NULL, dev, inode, - conn->connectpath, - fname); + lck = get_share_mode_lock(NULL, dev, inode, fname); if (lck == NULL) { DEBUG(0, ("Could not get share mode lock\n")); @@ -1543,9 +1537,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, dev = fsp->dev; inode = fsp->inode; - lck = get_share_mode_lock(NULL, dev, inode, - conn->connectpath, - fname); + lck = get_share_mode_lock(NULL, dev, inode, fname); if (lck == NULL) { DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); @@ -1952,9 +1944,7 @@ files_struct *open_directory(connection_struct *conn, fsp->is_stat = False; string_set(&fsp->fsp_name,fname); - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, - conn->connectpath, - fname); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fname); if (lck == NULL) { DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname)); @@ -2051,55 +2041,3 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, return fsp; } - -/**************************************************************************** - Receive notification that one of our open files has been renamed by another - smbd process. -****************************************************************************/ - -void msg_file_was_renamed(int msg_type, struct process_id src, void *buf, size_t len) -{ - files_struct *fsp; - char *frm = (char *)buf; - SMB_DEV_T dev; - SMB_INO_T inode; - const char *sharepath; - const char *newname; - size_t sp_len; - - if (buf == NULL || len < MSG_FILE_RENAMED_MIN_SIZE + 2) { - DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", (int)len)); - return; - } - - /* Unpack the message. */ - dev = DEV_T_VAL(frm,0); - inode = INO_T_VAL(frm,8); - sharepath = &frm[16]; - newname = sharepath + strlen(sharepath) + 1; - sp_len = strlen(sharepath); - - DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, " - "dev %x, inode %.0f\n", - sharepath, newname, (unsigned int)dev, (double)inode )); - - for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { - if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) { - DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n", - fsp->fnum, fsp->fsp_name, newname )); - string_set(&fsp->fsp_name, newname); - } else { - /* TODO. JRA. */ - /* Now we have the complete path we can work out if this is - actually within this share and adjust newname accordingly. */ - DEBUG(10,("msg_file_was_renamed: share mismatch (sharepath %s " - "not sharepath %s) " - "fnum %d from %s -> %s\n", - fsp->conn->connectpath, - sharepath, - fsp->fnum, - fsp->fsp_name, - newname )); - } - } -} diff --git a/source/smbd/oplock.c b/source/smbd/oplock.c index 6739d29470b..52a61c0061b 100644 --- a/source/smbd/oplock.c +++ b/source/smbd/oplock.c @@ -192,7 +192,7 @@ BOOL remove_oplock(files_struct *fsp) struct share_mode_lock *lck; /* Remove the oplock flag from the sharemode. */ - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); if (lck == NULL) { DEBUG(0,("remove_oplock: failed to lock share entry for " "file %s\n", fsp->fsp_name )); @@ -220,7 +220,7 @@ BOOL downgrade_oplock(files_struct *fsp) BOOL ret; struct share_mode_lock *lck; - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); if (lck == NULL) { DEBUG(0,("downgrade_oplock: failed to lock share entry for " "file %s\n", fsp->fsp_name )); @@ -233,7 +233,7 @@ BOOL downgrade_oplock(files_struct *fsp) fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); } - + downgrade_file_oplock(fsp); talloc_free(lck); return ret; @@ -670,7 +670,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) return; - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); if (lck == NULL) { DEBUG(0,("release_level_2_oplocks_on_change: failed to lock " "share mode entry for file %s.\n", fsp->fsp_name )); diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c index e485dc1eb12..7187f61b023 100644 --- a/source/smbd/posix_acls.c +++ b/source/smbd/posix_acls.c @@ -4224,7 +4224,7 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) connection_struct conn; files_struct finfo; struct fd_handle fh; - pstring path; + fstring path; pstring filename; ZERO_STRUCT( conn ); @@ -4235,8 +4235,8 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) return NULL; } - pstrcpy( path, "/" ); - set_conn_connectpath(&conn, path); + fstrcpy( path, "/" ); + string_set(&conn.connectpath, path); if (!smbd_vfs_init(&conn)) { DEBUG(0,("novfs_get_nt_acl: Unable to create a fake connection struct!\n")); diff --git a/source/smbd/quotas.c b/source/smbd/quotas.c index d6ba7bc2d55..de31376d6c6 100644 --- a/source/smbd/quotas.c +++ b/source/smbd/quotas.c @@ -206,8 +206,6 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB uid_t euser_id; gid_t egrp_id; - ZERO_STRUCT(D); - euser_id = geteuid(); egrp_id = getegid(); diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 69c71c74b59..81240fcb92d 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -1888,19 +1888,7 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b return NT_STATUS_OBJECT_NAME_INVALID; #endif /* JRATEST */ - /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com> - - On a Windows share, a file with read-only dosmode can be opened with - DELETE_ACCESS. But on a Samba share (delete readonly = no), it - fails with NT_STATUS_CANNOT_DELETE error. - - This semantic causes a problem that a user can not - rename a file with read-only dosmode on a Samba share - from a Windows command prompt (i.e. cmd.exe, but can rename - from Windows Explorer). - */ - - if (!check_is_at_open && !lp_delete_readonly(SNUM(conn))) { + if (!lp_delete_readonly(SNUM(conn))) { if (fattr & aRONLY) { return NT_STATUS_CANNOT_DELETE; } @@ -4094,24 +4082,15 @@ static BOOL resolve_wildcards(const char *name1, char *name2) } /**************************************************************************** - Ensure open files have their names updated. Updated to notify other smbd's - asynchronously. + Ensure open files have their names updates. ****************************************************************************/ -static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck, - SMB_DEV_T dev, SMB_INO_T inode, const char *newname) +static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname) { files_struct *fsp; BOOL did_rename = False; for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { - /* fsp_name is a relative path under the fsp. To change this for other - sharepaths we need to manipulate relative paths. */ - /* TODO - create the absolute path and manipulate the newname - relative to the sharepath. */ - if (fsp->conn != conn) { - continue; - } DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n", fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fsp_name, newname )); @@ -4119,13 +4098,9 @@ static void rename_open_files(connection_struct *conn, struct share_mode_lock *l did_rename = True; } - if (!did_rename) { + if (!did_rename) DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n", (unsigned int)dev, (double)inode, newname )); - } - - /* Send messages to all smbd's (not ourself) that the name has changed. */ - rename_share_filename(lck, conn->connectpath, newname); } /**************************************************************************** @@ -4169,7 +4144,6 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * NTSTATUS error = NT_STATUS_OK; BOOL dest_exists; BOOL rcdest = True; - struct share_mode_lock *lck = NULL; ZERO_STRUCT(sbuf); rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf); @@ -4257,23 +4231,17 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * return NT_STATUS_ACCESS_DENIED; } - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); - if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) { DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n", fsp->fsp_name,newname)); - rename_open_files(conn, lck, fsp->dev, fsp->inode, newname); - talloc_free(lck); + rename_open_files(conn, fsp->dev, fsp->inode, newname); return NT_STATUS_OK; } - talloc_free(lck); - - if (errno == ENOTDIR || errno == EISDIR) { + if (errno == ENOTDIR || errno == EISDIR) error = NT_STATUS_OBJECT_NAME_COLLISION; - } else { + else error = map_nt_error_from_unix(errno); - } DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n", nt_errstr(error), fsp->fsp_name,newname)); @@ -4300,7 +4268,6 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui BOOL rc = True; BOOL rcdest = True; SMB_STRUCT_STAT sbuf1, sbuf2; - struct share_mode_lock *lck = NULL; *directory = *mask = 0; @@ -4471,7 +4438,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", */ if (strcsequal(directory, newname)) { - rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname); + rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory)); return NT_STATUS_OK; } @@ -4486,17 +4453,13 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", return NT_STATUS_SHARING_VIOLATION; } - lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL); - if(SMB_VFS_RENAME(conn,directory, newname) == 0) { DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n", directory,newname)); - rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname); - talloc_free(lck); + rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); return NT_STATUS_OK; } - talloc_free(lck); if (errno == ENOTDIR || errno == EISDIR) error = NT_STATUS_OBJECT_NAME_COLLISION; else @@ -4574,7 +4537,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", } if (strcsequal(fname,destname)) { - rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname); + rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname)); count++; error = NT_STATUS_OK; @@ -4592,14 +4555,11 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", return NT_STATUS_SHARING_VIOLATION; } - lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL); - if (!SMB_VFS_RENAME(conn,fname,destname)) { - rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname); + rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); count++; error = NT_STATUS_OK; } - talloc_free(lck); DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } CloseDir(dir_hnd); @@ -4994,7 +4954,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } else { ok = vfs_directory_exist(conn,newdir,NULL); if (ok) - set_conn_connectpath(conn,newdir); + string_set(&conn->connectpath,newdir); } if (!ok) { @@ -5477,7 +5437,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, outsize = set_message(outbuf,0,0,True); if(!fsp || (fsp->conn != conn)) { - END_PROFILE(SMBsetattrE); + END_PROFILE(SMBgetattrE); return ERROR_DOS(ERRDOS,ERRbadfid); } diff --git a/source/smbd/server.c b/source/smbd/server.c index 620bf3ebbdd..1bf9dbc374a 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -330,7 +330,6 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ message_register(MSG_SMB_SAM_SYNC, msg_sam_sync); message_register(MSG_SMB_SAM_REPL, msg_sam_repl); message_register(MSG_SHUTDOWN, msg_exit_server); - message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed); /* now accept incoming connections - forking a new process for each incoming connection */ @@ -718,8 +717,6 @@ void build_options(BOOL screen); { NULL } }; - load_case_tables(); - #ifdef HAVE_SET_AUTH_PARAMETERS set_auth_parameters(argc,argv); #endif @@ -744,6 +741,8 @@ void build_options(BOOL screen); sec_init(); + load_case_tables(); + set_remote_machine_name("smbd", False); if (interactive) { @@ -826,10 +825,8 @@ void build_options(BOOL screen); init_structs(); - if (!init_guest_info()) { - DEBUG(0,("ERROR: failed to setup guest info.\n")); + if (!init_guest_info()) return -1; - } #ifdef WITH_PROFILE if (!profile_setup(False)) { diff --git a/source/smbd/service.c b/source/smbd/service.c index 7640559d538..52f9229ee1c 100644 --- a/source/smbd/service.c +++ b/source/smbd/service.c @@ -24,108 +24,6 @@ extern struct timeval smb_last_time; extern userdom_struct current_user_info; /**************************************************************************** - Ensure when setting connectpath it is a canonicalized (no ./ // or ../) - absolute path stating in / and not ending in /. - Observent people will notice a similarity between this and check_path_syntax :-). -****************************************************************************/ - -void set_conn_connectpath(connection_struct *conn, const pstring connectpath) -{ - pstring destname; - char *d = destname; - const char *s = connectpath; - BOOL start_of_name_component = True; - - *d++ = '/'; /* Always start with root. */ - - while (*s) { - if (*s == '/') { - /* Eat multiple '/' */ - while (*s == '/') { - s++; - } - if ((d > destname + 1) && (*s != '\0')) { - *d++ = '/'; - } - start_of_name_component = True; - continue; - } - - if (start_of_name_component) { - if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) { - /* Uh oh - "/../" or "/..\0" ! */ - - /* Go past the ../ or .. */ - if (s[2] == '/') { - s += 3; - } else { - s += 2; /* Go past the .. */ - } - - /* If we just added a '/' - delete it */ - if ((d > destname) && (*(d-1) == '/')) { - *(d-1) = '\0'; - d--; - } - - /* Are we at the start ? Can't go back further if so. */ - if (d <= destname) { - *d++ = '/'; /* Can't delete root */ - continue; - } - /* Go back one level... */ - /* Decrement d first as d points to the *next* char to write into. */ - for (d--; d > destname; d--) { - if (*d == '/') { - break; - } - } - /* We're still at the start of a name component, just the previous one. */ - continue; - } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) { - /* Component of pathname can't be "." only - skip the '.' . */ - if (s[1] == '/') { - s += 2; - } else { - s++; - } - continue; - } - } - - if (!(*s & 0x80)) { - *d++ = *s++; - } else { - switch(next_mb_char_size(s)) { - case 4: - *d++ = *s++; - case 3: - *d++ = *s++; - case 2: - *d++ = *s++; - case 1: - *d++ = *s++; - break; - default: - break; - } - } - start_of_name_component = False; - } - *d = '\0'; - - /* And must not end in '/' */ - if (d > destname + 1 && (*(d-1) == '/')) { - *(d-1) = '\0'; - } - - DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n", - lp_servicename(SNUM(conn)), destname )); - - string_set(&conn->connectpath, destname); -} - -/**************************************************************************** Load parameters specific to a connection/service. ****************************************************************************/ @@ -366,8 +264,7 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) static connection_struct *make_connection_snum(int snum, user_struct *vuser, DATA_BLOB password, - const char *pdev, - NTSTATUS *status) + const char *pdev, NTSTATUS *status) { struct passwd *pass = NULL; BOOL guest = False; @@ -397,8 +294,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, guest = True; pass = getpwnam_alloc(guestname); if (!pass) { - DEBUG(0,("make_connection_snum: Invalid guest " - "account %s??\n",guestname)); + DEBUG(0,("make_connection_snum: Invalid guest account %s??\n",guestname)); conn_free(conn); *status = NT_STATUS_NO_SUCH_USER; return NULL; @@ -413,20 +309,14 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } else if (vuser) { if (vuser->guest) { if (!lp_guest_ok(snum)) { - DEBUG(2, ("guest user (from session setup) " - "not permitted to access this share " - "(%s)\n", lp_servicename(snum))); + DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)\n", lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; return NULL; } } else { - if (!user_ok(vuser->user.unix_name, snum, - vuser->groups, vuser->n_groups)) { - DEBUG(2, ("user '%s' (from session setup) not " - "permitted to access this share " - "(%s)\n", vuser->user.unix_name, - lp_servicename(snum))); + if (!user_ok(vuser->user.unix_name, snum, vuser->groups, vuser->n_groups)) { + DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)\n", vuser->user.unix_name, lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; return NULL; @@ -473,14 +363,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->service = snum; conn->used = True; conn->printer = (strncmp(dev,"LPT",3) == 0); - conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || - ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) ); + conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) ); conn->dirptr = NULL; /* Case options for the share. */ if (lp_casesensitive(snum) == Auto) { - /* We will be setting this per packet. Set to be case - * insensitive for now. */ + /* We will be setting this per packet. Set to be case insensitive for now. */ conn->case_sensitive = False; } else { conn->case_sensitive = (BOOL)lp_casesensitive(snum); @@ -555,30 +443,30 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, pstring_sub(gname,"%S",lp_servicename(snum)); gid = nametogid(gname); - if (gid == (gid_t)-1) { - DEBUG(1,("Couldn't find group %s\n",gname)); - conn_free(conn); - *status = NT_STATUS_NO_SUCH_GROUP; - return NULL; - } + if (gid != (gid_t)-1) { - /* - * If the user has been forced and the forced group starts - * with a '+', then we only set the group to be the forced - * group if the forced user is a member of that group. - * Otherwise, the meaning of the '+' would be ignored. - */ - if (conn->force_user && user_must_be_member) { - if (user_in_group_list( user, gname, NULL, 0)) { + /* + * If the user has been forced and the forced group starts + * with a '+', then we only set the group to be the forced + * group if the forced user is a member of that group. + * Otherwise, the meaning of the '+' would be ignored. + */ + if (conn->force_user && user_must_be_member) { + if (user_in_group_list( user, gname, NULL, 0)) { + conn->gid = gid; + DEBUG(3,("Forced group %s for member %s\n",gname,user)); + } + } else { conn->gid = gid; - DEBUG(3,("Forced group %s for member %s\n", - gname,user)); + DEBUG(3,("Forced group %s\n",gname)); } + conn->force_group = True; } else { - conn->gid = gid; - DEBUG(3,("Forced group %s\n",gname)); + DEBUG(1,("Couldn't find group %s\n",gname)); + conn_free(conn); + *status = NT_STATUS_NO_SUCH_GROUP; + return NULL; } - conn->force_group = True; } #endif /* HAVE_GETGRNAM */ @@ -586,13 +474,11 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, pstring s; pstrcpy(s,lp_pathname(snum)); standard_sub_conn(conn,s,sizeof(s)); - set_conn_connectpath(conn,s); - DEBUG(3,("Connect path is '%s' for service [%s]\n",s, - lp_servicename(snum))); + string_set(&conn->connectpath,s); + DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum))); } if (conn->force_user || conn->force_group) { - int ngroups = 0; /* groups stuff added by ih */ conn->ngroups = 0; @@ -601,13 +487,11 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Find all the groups this uid is in and store them. Used by change_to_user() */ initialise_groups(conn->user, conn->uid, conn->gid); - get_current_groups(conn->gid, &ngroups, &conn->groups); - conn->ngroups = ngroups; + get_current_groups(conn->gid, &conn->ngroups,&conn->groups); - conn->nt_user_token = - create_nt_token(conn->uid, conn->gid, - conn->ngroups, conn->groups, - guest); + conn->nt_user_token = create_nt_token(conn->uid, conn->gid, + conn->ngroups, conn->groups, + guest); } /* @@ -618,16 +502,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, */ { - BOOL can_write = share_access_check(conn, snum, vuser, - FILE_WRITE_DATA); + BOOL can_write = share_access_check(conn, snum, vuser, FILE_WRITE_DATA); if (!can_write) { - if (!share_access_check(conn, snum, vuser, - FILE_READ_DATA)) { + if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) { /* No access, read or write. */ - DEBUG(0,("make_connection: connection to %s " - "denied due to security " - "descriptor.\n", + DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n", lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; @@ -640,25 +520,24 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Initialise VFS function pointers */ if (!smbd_vfs_init(conn)) { - DEBUG(0, ("vfs_init failed for service %s\n", - lp_servicename(snum))); + DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } /* - * If widelinks are disallowed we need to canonicalise the connect - * path here to ensure we don't have any symlinks in the - * connectpath. We will be checking all paths on this connection are - * below this directory. We must do this after the VFS init as we - * depend on the realpath() pointer in the vfs table. JRA. + * If widelinks are disallowed we need to canonicalise the + * connect path here to ensure we don't have any symlinks in + * the connectpath. We will be checking all paths on this + * connection are below this directory. We must do this after + * the VFS init as we depend on the realpath() pointer in the vfs table. JRA. */ if (!lp_widelinks(snum)) { pstring s; pstrcpy(s,conn->connectpath); canonicalize_path(conn, s); - set_conn_connectpath(conn,s); + string_set(&conn->connectpath,s); } /* ROOT Activities: */ @@ -673,8 +552,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } - /* Preexecs are done here as they might make the dir we are to ChDir - * to below */ + /* Preexecs are done here as they might make the dir we are to ChDir to below */ /* execute any "root preexec = " line */ if (*lp_rootpreexec(snum)) { pstring cmd; @@ -683,8 +561,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, DEBUG(5,("cmd=%s\n",cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_rootpreexec_close(snum)) { - DEBUG(1,("root preexec gave %d - failing " - "connection\n", ret)); + DEBUG(1,("root preexec gave %d - failing connection\n", ret)); yield_connection(conn, lp_servicename(snum)); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; @@ -702,12 +579,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } - /* Remember that a different vuid can connect later without these - * checks... */ + /* Remember that a different vuid can connect later without these checks... */ - /* Preexecs are done here as they might make the dir we are to ChDir - * to below */ - + /* Preexecs are done here as they might make the dir we are to ChDir to below */ /* execute any "preexec = " line */ if (*lp_preexec(snum)) { pstring cmd; @@ -715,8 +589,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, standard_sub_conn(conn,cmd,sizeof(cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_preexec_close(snum)) { - DEBUG(1,("preexec gave %d - failing connection\n", - ret)); + DEBUG(1,("preexec gave %d - failing connection\n", ret)); change_to_root_user(); yield_connection(conn, lp_servicename(snum)); conn_free(conn); @@ -738,9 +611,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum)); } - /* Invoke VFS make connection hook - do this before the VFS_STAT call - to allow any filesystems needing user credentials to initialize - themselves. */ + /* Invoke VFS make connection hook - do this before the VFS_STAT call to allow + any filesystems needing user credentials to initialize themselves. */ if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) { DEBUG(0,("make_connection: VFS make connection failed!\n")); @@ -756,17 +628,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, check during individual operations. To match this behaviour I have disabled this chdir check (tridge) */ /* the alternative is just to check the directory exists */ - if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 || - !S_ISDIR(st.st_mode)) { + if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 || !S_ISDIR(st.st_mode)) { if (ret == 0 && !S_ISDIR(st.st_mode)) { - DEBUG(0,("'%s' is not a directory, when connecting to " - "[%s]\n", conn->connectpath, - lp_servicename(snum))); + DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(snum))); } else { - DEBUG(0,("'%s' does not exist or permission denied " - "when connecting to [%s] Error was %s\n", - conn->connectpath, lp_servicename(snum), - strerror(errno) )); + DEBUG(0,("'%s' does not exist or permission denied when connecting to [%s] " + "Error was %s\n", conn->connectpath, lp_servicename(snum), strerror(errno) )); } change_to_root_user(); /* Call VFS disconnect hook */ @@ -785,7 +652,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, pstring s; pstrcpy(s,conn->connectpath); vfs_GetWd(conn,s); - set_conn_connectpath(conn,s); + string_set(&conn->connectpath,s); vfs_ChDir(conn,conn->connectpath); } #endif @@ -797,8 +664,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, */ if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { - dbgtext( "%s (%s) ", get_remote_machine_name(), - conn->client_address ); + dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address ); dbgtext( "%s", srv_is_signing_active() ? "signed " : ""); dbgtext( "connect to service %s ", lp_servicename(snum) ); dbgtext( "initially as user %s ", user ); @@ -816,10 +682,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, vfs_chdir() **************************************************************************************/ -connection_struct *make_connection_with_chdir(const char *service_in, - DATA_BLOB password, - const char *dev, uint16 vuid, - NTSTATUS *status) +connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password, + const char *dev, uint16 vuid, NTSTATUS *status) { connection_struct *conn = NULL; @@ -831,8 +695,7 @@ connection_struct *make_connection_with_chdir(const char *service_in, */ if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) { - DEBUG(0,("move_driver_to_download_area: Can't change " - "directory to %s for [print$] (%s)\n", + DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n", conn->connectpath,strerror(errno))); yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); @@ -850,8 +713,7 @@ connection_struct *make_connection_with_chdir(const char *service_in, ****************************************************************************/ connection_struct *make_connection(const char *service_in, DATA_BLOB password, - const char *pdev, uint16 vuid, - NTSTATUS *status) + const char *pdev, uint16 vuid, NTSTATUS *status) { uid_t euid; user_struct *vuser = NULL; @@ -861,52 +723,43 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, fstrcpy(dev, pdev); - /* This must ONLY BE CALLED AS ROOT. As it exits this function as - * root. */ + /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */ if (!non_root_mode() && (euid = geteuid()) != 0) { - DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot " - "(%u)\n", (unsigned int)euid )); + DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid )); smb_panic("make_connection: PANIC ERROR. Called as nonroot\n"); } if(lp_security() != SEC_SHARE) { vuser = get_valid_user_struct(vuid); if (!vuser) { - DEBUG(1,("make_connection: refusing to connect with " - "no session setup\n")); + DEBUG(1,("make_connection: refusing to connect with no session setup\n")); *status = NT_STATUS_ACCESS_DENIED; return NULL; } } - /* Logic to try and connect to the correct [homes] share, preferably - without too many getpwnam() lookups. This is particulary nasty for - winbind usernames, where the share name isn't the same as unix - username. + /* Logic to try and connect to the correct [homes] share, preferably without too many + getpwnam() lookups. This is particulary nasty for winbind usernames, where the + share name isn't the same as unix username. - The snum of the homes share is stored on the vuser at session setup - time. + The snum of the homes share is stored on the vuser at session setup time. */ if (strequal(service_in,HOMES_NAME)) { if(lp_security() != SEC_SHARE) { DATA_BLOB no_pw = data_blob(NULL, 0); if (vuser->homes_snum == -1) { - DEBUG(2, ("[homes] share not available for " - "this user because it was not found " - "or created at session setup " - "time\n")); + DEBUG(2, ("[homes] share not available for this user because it was not found or created at session setup time\n")); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } - DEBUG(5, ("making a connection to [homes] service " - "created at session setup time\n")); + DEBUG(5, ("making a connection to [homes] service created at session setup time\n")); return make_connection_snum(vuser->homes_snum, vuser, no_pw, dev, status); } else { - /* Security = share. Try with - * current_user_info.smb_name as the username. */ + /* Security = share. Try with current_user_info.smb_name + * as the username. */ if (*current_user_info.smb_name) { fstring unix_username; fstrcpy(unix_username, @@ -915,20 +768,16 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, snum = find_service(unix_username); } if (snum != -1) { - DEBUG(5, ("making a connection to 'homes' " - "service %s based on " - "security=share\n", service_in)); + DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in)); return make_connection_snum(snum, NULL, password, dev, status); } } } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1) - && strequal(service_in, - lp_servicename(vuser->homes_snum))) { + && strequal(service_in, lp_servicename(vuser->homes_snum))) { DATA_BLOB no_pw = data_blob(NULL, 0); - DEBUG(5, ("making a connection to 'homes' service [%s] " - "created at session setup time\n", service_in)); + DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in)); return make_connection_snum(vuser->homes_snum, vuser, no_pw, dev, status); @@ -941,8 +790,9 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, snum = find_service(service); if (snum < 0) { - if (strequal(service,"IPC$") || - (lp_enable_asu_support() && strequal(service,"ADMIN$"))) { + if (strequal(service,"IPC$") + || (lp_enable_asu_support() && strequal(service,"ADMIN$"))) + { DEBUG(3,("refusing IPC connection to %s\n", service)); *status = NT_STATUS_ACCESS_DENIED; return NULL; @@ -956,8 +806,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, /* Handle non-Dfs clients attempting connections to msdfs proxy */ if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) { - DEBUG(3, ("refusing connection to dfs proxy share '%s' " - "(pointing to %s)\n", + DEBUG(3, ("refusing connection to dfs proxy share '%s' (pointing to %s)\n", service, lp_msdfs_proxy(snum))); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; @@ -986,8 +835,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) change_to_root_user(); DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n", - get_remote_machine_name(), - conn->client_address, + get_remote_machine_name(),conn->client_address, lp_servicename(SNUM(conn)))); /* Call VFS disconnect hook */ diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index 8ff219b468c..fc2a7686bd1 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -1436,8 +1436,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p +=4; } SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */ - SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */ - SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */ + SIVAL(p,0,sbuf.st_dev); p += 4; + SIVAL(p,0,sbuf.st_ino); p += 4; len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(q, 0, len); p += len; @@ -1486,8 +1486,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } p += 26; SSVAL(p,0,0); p += 2; /* Reserved ? */ - SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */ - SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */ + SIVAL(p,0,sbuf.st_dev); p += 4; + SIVAL(p,0,sbuf.st_ino); p += 4; len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(q,0,len); p += len; @@ -2824,7 +2824,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } - delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); + delete_pending = + get_delete_on_close_flag(sbuf.st_dev, + sbuf.st_ino, + fname); } else { /* * Original code - this is an open file. @@ -2837,7 +2840,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return(UNIXERROR(ERRDOS,ERRbadfid)); } pos = fsp->fh->position_information; - delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); + delete_pending = + get_delete_on_close_flag(sbuf.st_dev, + sbuf.st_ino, + fname); access_mask = fsp->access_mask; } } else { @@ -2879,7 +2885,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } - delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); + delete_pending = get_delete_on_close_flag(sbuf.st_dev, + sbuf.st_ino, + fname); if (delete_pending) { return ERROR_NT(NT_STATUS_DELETE_PENDING); } @@ -3216,8 +3224,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd BasicFileInformationTest. -tpot */ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n")); - SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */ - SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */ + SIVAL(pdata,0,sbuf.st_dev); + SIVAL(pdata,4,sbuf.st_ino); data_size = 8; break; diff --git a/source/smbd/uid.c b/source/smbd/uid.c index 9db3d97ab2d..d1ecaf6625f 100644 --- a/source/smbd/uid.c +++ b/source/smbd/uid.c @@ -81,53 +81,45 @@ BOOL change_to_guest(void) Readonly share for this user ? ****************************************************************************/ -static BOOL is_share_read_only_for_user(int snum, user_struct *vuser) +static BOOL is_share_read_only_for_user(connection_struct *conn, user_struct *vuser) { char **list; - const char *service = lp_servicename(snum); - BOOL read_only_ret = lp_readonly(snum); + const char *service = lp_servicename(conn->service); + BOOL read_only_ret = lp_readonly(conn->service); if (!service) return read_only_ret; - str_list_copy(&list, lp_readlist(snum)); + str_list_copy(&list, lp_readlist(conn->service)); if (list) { if (!str_list_sub_basic(list, vuser->user.smb_name) ) { - DEBUG(0, ("is_share_read_only_for_user: ERROR: read " - "list substitution failed\n")); + DEBUG(0, ("is_share_read_only_for_user: ERROR: read list substitution failed\n")); } if (!str_list_substitute(list, "%S", service)) { - DEBUG(0, ("is_share_read_only_for_user: ERROR: read " - "list service substitution failed\n")); + DEBUG(0, ("is_share_read_only_for_user: ERROR: read list service substitution failed\n")); } - if (user_in_list(vuser->user.unix_name, (const char **)list, - vuser->groups, vuser->n_groups)) { + if (user_in_list(vuser->user.unix_name, (const char **)list, vuser->groups, vuser->n_groups)) { read_only_ret = True; } str_list_free(&list); } - str_list_copy(&list, lp_writelist(snum)); + str_list_copy(&list, lp_writelist(conn->service)); if (list) { if (!str_list_sub_basic(list, vuser->user.smb_name) ) { - DEBUG(0, ("is_share_read_only_for_user: ERROR: write " - "list substitution failed\n")); + DEBUG(0, ("is_share_read_only_for_user: ERROR: write list substitution failed\n")); } if (!str_list_substitute(list, "%S", service)) { - DEBUG(0, ("is_share_read_only_for_user: ERROR: write " - "list service substitution failed\n")); + DEBUG(0, ("is_share_read_only_for_user: ERROR: write list service substitution failed\n")); } - if (user_in_list(vuser->user.unix_name, (const char **)list, - vuser->groups, vuser->n_groups)) { + if (user_in_list(vuser->user.unix_name, (const char **)list, vuser->groups, vuser->n_groups)) { read_only_ret = False; } str_list_free(&list); } - DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user " - "%s\n", service, - read_only_ret ? "read-only" : "read-write", - vuser->user.unix_name )); + DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user %s\n", + service, read_only_ret ? "read-only" : "read-write", vuser->user.unix_name )); return read_only_ret; } @@ -154,7 +146,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) if (!user_ok(vuser->user.unix_name,snum, vuser->groups, vuser->n_groups)) return(False); - readonly_share = is_share_read_only_for_user(conn->service, vuser); + readonly_share = is_share_read_only_for_user(conn, vuser); if (!readonly_share && !share_access_check(conn, snum, vuser, FILE_WRITE_DATA)) { @@ -190,7 +182,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) /**************************************************************************** Become the user of a connection number without changing the security context - stack, but modify the current_user entries. + stack, but modify the currnet_user entries. ****************************************************************************/ BOOL change_to_user(connection_struct *conn, uint16 vuid) diff --git a/source/torture/torture.c b/source/torture/torture.c index e995c3cc58a..0bd9aa1728b 100644 --- a/source/torture/torture.c +++ b/source/torture/torture.c @@ -4914,8 +4914,6 @@ static void usage(void) setbuffer(stdout, NULL, 0); #endif - load_case_tables(); - lp_load(dyn_CONFIGFILE,True,False,False); load_interfaces(); diff --git a/source/torture/vfstest.c b/source/torture/vfstest.c index 1914a4acb50..b5ccf930bc6 100644 --- a/source/torture/vfstest.c +++ b/source/torture/vfstest.c @@ -495,7 +495,6 @@ int main(int argc, char *argv[]) POPT_TABLEEND }; - load_case_tables(); setlinebuf(stdout); diff --git a/source/ubiqx/COPYING.LIB b/source/ubiqx/COPYING.LIB new file mode 100644 index 00000000000..8c8377da464 --- /dev/null +++ b/source/ubiqx/COPYING.LIB @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/source/ubiqx/README.UBI b/source/ubiqx/README.UBI new file mode 100644 index 00000000000..a2c14ca62c9 --- /dev/null +++ b/source/ubiqx/README.UBI @@ -0,0 +1,18 @@ +Fri Apr 17 10:21:56 CDT 1998 + +The C code files in the samba/source/ubiqx directory are licensed under +the terms of the GNU LIBRARY GENERAL PUBLIC LICENSE (LGPL). A copy of the +LGPL should also be included in this directory under the name COPYING.LIB. +If this file is not present, you can obtain a copy of the LGPL by writing +to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +USA. + +The versions of the ubiqx modules distributed with Samba may have been +modified for inclusion with Samba. The main distribution, which contains +additional available modules, can be found at: + + http://www.interads.co.uk/~crh/ubiqx/ + +Chris Hertel +Samba Team +ubiqx@ubiqx.mn.org diff --git a/source/utils/debugparse.c b/source/ubiqx/debugparse.c index c5fe3e2ee85..c5fe3e2ee85 100644 --- a/source/utils/debugparse.c +++ b/source/ubiqx/debugparse.c diff --git a/source/include/debugparse.h b/source/ubiqx/debugparse.h index fb7f00f7792..458eee74558 100644 --- a/source/include/debugparse.h +++ b/source/ubiqx/debugparse.h @@ -31,7 +31,7 @@ * ========================================================================== ** */ -#include "includes.h" +#include "sys_include.h" /* This module compiles quite nicely outside of the Samba environment. * You'll need the following headers: diff --git a/source/ubiqx/sys_include.h b/source/ubiqx/sys_include.h new file mode 100644 index 00000000000..8ff270afe85 --- /dev/null +++ b/source/ubiqx/sys_include.h @@ -0,0 +1,52 @@ +#ifndef SYS_INCLUDE_H +#define SYS_INCLUDE_H +/* ========================================================================== ** + * sys_include.h + * + * Copyright (C) 1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * This header provides system declarations and data types used internally + * by the ubiqx modules. + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * Samba version of sys_include.h + * + * ========================================================================== ** + */ + +#ifndef _INCLUDES_H + +/* Block the inclusion of some Samba headers so that ubiqx types won't be + * used before the headers that define them. These headers are not needed + * in the ubiqx modules anyway. + */ +#define _PROTO_H_ +#define _NAMESERV_H_ +#define _HASH_H_ + +/* The main Samba system-adaptive header file. + */ +#include "includes.h" + +#endif /* _INCLUDES_H */ + +/* ================================ The End ================================= */ +#endif /* SYS_INCLUDE_H */ diff --git a/source/ubiqx/ubi_BinTree.c b/source/ubiqx/ubi_BinTree.c new file mode 100644 index 00000000000..e452ac10dc2 --- /dev/null +++ b/source/ubiqx/ubi_BinTree.c @@ -0,0 +1,1172 @@ +/* ========================================================================== ** + * ubi_BinTree.c + * + * Copyright (C) 1991-1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module implements a simple binary tree. + * + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * Log: ubi_BinTree.c,v + * Revision 4.12 2004/06/06 04:51:56 crh + * Fixed a small typo in ubi_BinTree.c (leftover testing cruft). + * Did a small amount of formatting touchup to ubi_BinTree.h. + * + * Revision 4.11 2004/06/06 03:14:09 crh + * Rewrote the ubi_btLeafNode() function. It now takes several paths in an + * effort to find a deeper leaf node. There is a small amount of extra + * overhead, but it is limited. + * + * Revision 4.10 2000/06/06 20:38:40 crh + * In the ReplaceNode() function, the old node header was being copied + * to the new node header using a byte-by-byte copy. This was causing + * the 'insure' software testing program to report a memory leak. The + * fix was to do a simple assignement: *newnode = *oldnode; + * This quieted the (errant) memory leak reports and is probably a bit + * faster than the bytewise copy. + * + * Revision 4.9 2000/01/08 23:24:30 crh + * Clarified a variety of if( pointer ) lines, replacing them with + * if( NULL != pointer ). This is more correct, and I have heard + * of at least one (obscure?) system out there that uses a non-zero + * value for NULL. + * Also, speed improvement in Neighbor(). It was comparing pointers + * when it could have compared two gender values. The pointer + * comparison was somewhat indirect (does pointer equal the pointer + * of the parent of the node pointed to by pointer). Urq. + * + * Revision 4.8 1999/09/22 03:40:30 crh + * Modified ubi_btTraverse() and ubi_btKillTree(). They now return an + * unsigned long indicating the number of nodes processed. The change + * is subtle. An empty tree formerly returned False, and now returns + * zero. + * + * Revision 4.7 1998/10/21 06:14:42 crh + * Fixed bugs in FirstOf() and LastOf() reported by Massimo Campostrini. + * See function comments. + * + * Revision 4.6 1998/07/25 17:02:10 crh + * Added the ubi_trNewTree() macro. + * + * Revision 4.5 1998/06/04 21:29:27 crh + * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files. + * This is more "standard", and is what people expect. Weird, eh? + * + * Revision 4.4 1998/06/03 17:42:46 crh + * Further fiddling with sys_include.h. It's now in ubi_BinTree.h which is + * included by all of the binary tree files. + * + * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in + * ubi_AVLtree.h and ubi_SplayTree.h. This allows easy swapping + * of tree types by simply changing a header. Unfortunately, the + * macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will + * conflict if used together. You must either choose a single tree + * type, or use the underlying function calls directly. Compare + * the two header files for more information. + * + * Revision 4.3 1998/06/02 01:28:43 crh + * Changed ubi_null.h to sys_include.h to make it more generic. + * + * Revision 4.2 1998/05/20 04:32:36 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * Also, the balance and gender fields of the node were declared as + * signed char. As I understand it, at least one SunOS or Solaris + * compiler doesn't like "signed char". The declarations were + * wrong anyway, so I changed them to simple "char". + * + * Revision 4.1 1998/03/31 06:11:57 crh + * Thomas Aglassinger sent E'mail pointing out errors in the + * dereferencing of function pointers, and a missing typecast. + * Thanks, Thomas! + * + * Revision 4.0 1998/03/10 03:19:22 crh + * Added the AVL field 'balance' to the ubi_btNode structure. This means + * that all BinTree modules now use the same basic node structure, which + * greatly simplifies the AVL module. + * Decided that this was a big enough change to justify a new major revision + * number. 3.0 was an error, so we're at 4.0. + * + * Revision 2.6 1998/01/24 06:27:46 crh + * Added ubi_trCount() macro. + * + * Revision 2.5 1997/12/23 03:56:29 crh + * In this version, all constants & macros defined in the header file have + * the ubi_tr prefix. Also cleaned up anything that gcc complained about + * when run with '-pedantic -fsyntax-only -Wall'. + * + * Revision 2.4 1997/07/26 04:11:10 crh + * + Just to be annoying I changed ubi_TRUE and ubi_FALSE to ubi_trTRUE + * and ubi_trFALSE. + * + There is now a type ubi_trBool to go with ubi_trTRUE and ubi_trFALSE. + * + There used to be something called "ubi_TypeDefs.h". I got rid of it. + * + Added function ubi_btLeafNode(). + * + * Revision 2.3 1997/06/03 05:16:17 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid conflicts. + * Also changed the interface to function InitTree(). See the comments + * for this function for more information. + * + * Revision 2.2 1995/10/03 22:00:07 CRH + * Ubisized! + * + * Revision 2.1 95/03/09 23:37:10 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:00:17 CRH + * Revision 2.0 of this program includes the following changes: + * + * 1) A fix to a major typo in the RepaceNode() function. + * 2) The addition of the static function Border(). + * 3) The addition of the public functions FirstOf() and LastOf(), which + * use Border(). These functions are used with trees that allow + * duplicate keys. + * 4) A complete rewrite of the Locate() function. Locate() now accepts + * a "comparison" operator. + * 5) Overall enhancements to both code and comments. + * + * I decided to give this a new major rev number because the interface has + * changed. In particular, there are two new functions, and changes to the + * Locate() function. + * + * Revision 1.0 93/10/15 22:44:59 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_SplayTree, the locate function was + * called "ubi_sptLocate", but the next and previous functions remained + * "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * V0.0 - June, 1991 - Written by Christopher R. Hertel (CRH). + * + * ========================================================================== ** + */ + +#include "ubi_BinTree.h" /* Header for this module. */ + + +/* ========================================================================== ** + * Static data. + */ + +static char ModuleID[] = "ubi_BinTree\n\ +\tRevision: 4.12\n\ +\tDate: 2004/06/06 04:51:56\n\ +\tAuthor: crh\n"; + +/* ========================================================================== ** + * Internal (private) functions. + */ + +static ubi_btNodePtr qFind( ubi_btCompFunc cmp, + ubi_btItemPtr FindMe, + register ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for a node + * matching a specific key. It is called "qFind()" because it is + * faster that TreeFind (below). + * + * Input: + * cmp - a pointer to the tree's comparison function. + * FindMe - a pointer to the key value for which to search. + * p - a pointer to the starting point of the search. <p> + * is considered to be the root of a subtree, and only + * the subtree will be searched. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. + * ------------------------------------------------------------------------ ** + */ + { + int tmp; + + while( (NULL != p) + && ((tmp = ubi_trAbNormal( (*cmp)(FindMe, p) )) != ubi_trEQUAL) ) + p = p->Link[tmp]; + + return( p ); + } /* qFind */ + +static ubi_btNodePtr TreeFind( ubi_btItemPtr findme, + ubi_btNodePtr p, + ubi_btNodePtr *parentp, + char *gender, + ubi_btCompFunc CmpFunc ) + /* ------------------------------------------------------------------------ ** + * TreeFind() searches a tree for a given value (findme). It will return a + * pointer to the target node, if found, or NULL if the target node was not + * found. + * + * TreeFind() also returns, via parameters, a pointer to the parent of the + * target node, and a LEFT or RIGHT value indicating which child of the + * parent is the target node. *If the target is not found*, then these + * values indicate the place at which the target *should be found*. This + * is useful when inserting a new node into a tree or searching for nodes + * "near" the target node. + * + * The parameters are: + * + * findme - is a pointer to the key information to be searched for. + * p - points to the root of the tree to be searched. + * parentp - will return a pointer to a pointer to the !parent! of the + * target node, which can be especially usefull if the target + * was not found. + * gender - returns LEFT or RIGHT to indicate which child of *parentp + * was last searched. + * CmpFunc - points to the comparison function. + * + * This function is called by ubi_btLocate() and ubi_btInsert(). + * ------------------------------------------------------------------------ ** + */ + { + register ubi_btNodePtr tmp_p = p; + ubi_btNodePtr tmp_pp = NULL; + char tmp_gender = ubi_trEQUAL; + int tmp_cmp; + + while( (NULL != tmp_p) + && (ubi_trEQUAL != (tmp_cmp = ubi_trAbNormal((*CmpFunc)(findme, tmp_p)))) ) + { + tmp_pp = tmp_p; /* Keep track of previous node. */ + tmp_gender = (char)tmp_cmp; /* Keep track of sex of child. */ + tmp_p = tmp_p->Link[tmp_cmp]; /* Go to child. */ + } + *parentp = tmp_pp; /* Return results. */ + *gender = tmp_gender; + return( tmp_p ); + } /* TreeFind */ + +static void ReplaceNode( ubi_btNodePtr *parent, + ubi_btNodePtr oldnode, + ubi_btNodePtr newnode ) + /* ------------------------------------------------------------------------ ** + * Remove node oldnode from the tree, replacing it with node newnode. + * + * Input: + * parent - A pointer to he parent pointer of the node to be + * replaced. <parent> may point to the Link[] field of + * a parent node, or it may indicate the root pointer at + * the top of the tree. + * oldnode - A pointer to the node that is to be replaced. + * newnode - A pointer to the node that is to be installed in the + * place of <*oldnode>. + * + * Notes: Don't forget to free oldnode. + * Also, this function used to have a really nasty typo + * bug. "oldnode" and "newnode" were swapped in the line + * that now reads: + * ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i]; + * Bleah! + * ------------------------------------------------------------------------ ** + */ + { + *newnode = *oldnode; /* Copy node internals to new node. */ + + (*parent) = newnode; /* Old node's parent points to new child. */ + /* Now tell the children about their new step-parent. */ + if( oldnode->Link[ubi_trLEFT] ) + (oldnode->Link[ubi_trLEFT])->Link[ubi_trPARENT] = newnode; + if( oldnode->Link[ubi_trRIGHT] ) + (oldnode->Link[ubi_trRIGHT])->Link[ubi_trPARENT] = newnode; + } /* ReplaceNode */ + +static void SwapNodes( ubi_btRootPtr RootPtr, + ubi_btNodePtr Node1, + ubi_btNodePtr Node2 ) + /* ------------------------------------------------------------------------ ** + * This function swaps two nodes in the tree. Node1 will take the place of + * Node2, and Node2 will fill in the space left vacant by Node 1. + * + * Input: + * RootPtr - pointer to the tree header structure for this tree. + * Node1 - \ + * > These are the two nodes which are to be swapped. + * Node2 - / + * + * Notes: + * This function does a three step swap, using a dummy node as a place + * holder. This function is used by ubi_btRemove(). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr *Parent; + ubi_btNode dummy; + ubi_btNodePtr dummy_p = &dummy; + + /* Replace Node 1 with the dummy, thus removing Node1 from the tree. */ + if( NULL != Node1->Link[ubi_trPARENT] ) + Parent = &((Node1->Link[ubi_trPARENT])->Link[(int)(Node1->gender)]); + else + Parent = &(RootPtr->root); + ReplaceNode( Parent, Node1, dummy_p ); + + /* Swap Node 1 with Node 2, placing Node 1 back into the tree. */ + if( NULL != Node2->Link[ubi_trPARENT] ) + Parent = &((Node2->Link[ubi_trPARENT])->Link[(int)(Node2->gender)]); + else + Parent = &(RootPtr->root); + ReplaceNode( Parent, Node2, Node1 ); + + /* Swap Node 2 and the dummy, thus placing Node 2 back into the tree. */ + if( NULL != dummy_p->Link[ubi_trPARENT] ) + Parent = &((dummy_p->Link[ubi_trPARENT])->Link[(int)(dummy_p->gender)]); + else + Parent = &(RootPtr->root); + ReplaceNode( Parent, dummy_p, Node2 ); + } /* SwapNodes */ + +/* -------------------------------------------------------------------------- ** + * These routines allow you to walk through the tree, forwards or backwards. + */ + +static ubi_btNodePtr SubSlide( register ubi_btNodePtr P, + register int whichway ) + /* ------------------------------------------------------------------------ ** + * Slide down the side of a subtree. + * + * Given a starting node, this function returns a pointer to the LEFT-, or + * RIGHT-most descendent, *or* (if whichway is PARENT) to the tree root. + * + * Input: P - a pointer to a starting place. + * whichway - the direction (LEFT, RIGHT, or PARENT) in which to + * travel. + * Output: A pointer to a node that is either the root, or has no + * whichway-th child but is within the subtree of P. Note that + * the return value may be the same as P. The return value *will + * be* NULL if P is NULL. + * ------------------------------------------------------------------------ ** + */ + { + + if( NULL != P ) + while( NULL != P->Link[ whichway ] ) + P = P->Link[ whichway ]; + return( P ); + } /* SubSlide */ + +static ubi_btNodePtr Neighbor( register ubi_btNodePtr P, + register int whichway ) + /* ------------------------------------------------------------------------ ** + * Given starting point p, return the (key order) next or preceeding node + * in the tree. + * + * Input: P - Pointer to our starting place node. + * whichway - the direction in which to travel to find the + * neighbor, i.e., the RIGHT neighbor or the LEFT + * neighbor. + * + * Output: A pointer to the neighboring node, or NULL if P was NULL. + * + * Notes: If whichway is PARENT, the results are unpredictable. + * ------------------------------------------------------------------------ ** + */ + { + if( P ) + { + if( NULL != P->Link[ whichway ] ) + return( SubSlide( P->Link[ whichway ], (char)ubi_trRevWay(whichway) ) ); + else + while( NULL != P->Link[ ubi_trPARENT ] ) + { + if( whichway == P->gender ) + P = P->Link[ ubi_trPARENT ]; + else + return( P->Link[ ubi_trPARENT ] ); + } + } + return( NULL ); + } /* Neighbor */ + +static ubi_btNodePtr Border( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_btNodePtr p, + int whichway ) + /* ------------------------------------------------------------------------ ** + * Given starting point p, which has a key value equal to *FindMe, locate + * the first (index order) node with the same key value. + * + * This function is useful in trees that have can have duplicate keys. + * For example, consider the following tree: + * Tree Traversal + * 2 If <p> points to the root and <whichway> is RIGHT, 3 + * / \ then the return value will be a pointer to the / \ + * 2 2 RIGHT child of the root node. The tree on 2 5 + * / / \ the right shows the order of traversal. / / \ + * 1 2 3 1 4 6 + * + * Input: RootPtr - Pointer to the tree root structure. + * FindMe - Key value for comparisons. + * p - Pointer to the starting-point node. + * whichway - the direction in which to travel to find the + * neighbor, i.e., the RIGHT neighbor or the LEFT + * neighbor. + * + * Output: A pointer to the first (index, or "traversal", order) node with + * a Key value that matches *FindMe. + * + * Notes: If whichway is PARENT, or if the tree does not allow duplicate + * keys, this function will return <p>. + * ------------------------------------------------------------------------ ** + */ + { + register ubi_btNodePtr q; + + /* Exit if there's nothing that can be done. */ + if( !ubi_trDups_OK( RootPtr ) || (ubi_trPARENT == whichway) ) + return( p ); + + /* First, if needed, move up the tree. We need to get to the root of the + * subtree that contains all of the matching nodes. + */ + q = p->Link[ubi_trPARENT]; + while( (NULL != q) + && (ubi_trEQUAL == ubi_trAbNormal( (*(RootPtr->cmp))(FindMe, q) )) ) + { + p = q; + q = p->Link[ubi_trPARENT]; + } + + /* Next, move back down in the "whichway" direction. */ + q = p->Link[whichway]; + while( NULL != q ) + { + q = qFind( RootPtr->cmp, FindMe, q ); + if( q ) + { + p = q; + q = p->Link[whichway]; + } + } + return( p ); + } /* Border */ + + +/* ========================================================================== ** + * Exported utilities. + */ + +long ubi_btSgn( register long x ) + /* ------------------------------------------------------------------------ ** + * Return the sign of x; {negative,zero,positive} ==> {-1, 0, 1}. + * + * Input: x - a signed long integer value. + * + * Output: the "sign" of x, represented as follows: + * -1 == negative + * 0 == zero (no sign) + * 1 == positive + * + * Note: This utility is provided in order to facilitate the conversion + * of C comparison function return values into BinTree direction + * values: {LEFT, PARENT, EQUAL}. It is INCORPORATED into the + * ubi_trAbNormal() conversion macro! + * + * ------------------------------------------------------------------------ ** + */ + { + return( (x)?((x>0)?(1):(-1)):(0) ); + } /* ubi_btSgn */ + +ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr ) + /* ------------------------------------------------------------------------ ** + * Initialize a tree node. + * + * Input: a pointer to a ubi_btNode structure to be initialized. + * Output: a pointer to the initialized ubi_btNode structure (ie. the + * same as the input pointer). + * ------------------------------------------------------------------------ ** + */ + { + NodePtr->Link[ ubi_trLEFT ] = NULL; + NodePtr->Link[ ubi_trPARENT ] = NULL; + NodePtr->Link[ ubi_trRIGHT ] = NULL; + NodePtr->gender = ubi_trEQUAL; + NodePtr->balance = ubi_trEQUAL; + return( NodePtr ); + } /* ubi_btInitNode */ + +ubi_btRootPtr ubi_btInitTree( ubi_btRootPtr RootPtr, + ubi_btCompFunc CompFunc, + char Flags ) + /* ------------------------------------------------------------------------ ** + * Initialize the fields of a Tree Root header structure. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure to be + * initialized. + * CompFunc - a pointer to a comparison function that will be used + * whenever nodes in the tree must be compared against + * outside values. + * Flags - One bytes worth of flags. Flags include + * ubi_trOVERWRITE and ubi_trDUPKEY. See the header + * file for more info. + * + * Output: a pointer to the initialized ubi_btRoot structure (ie. the + * same value as RootPtr). + * + * Note: The interface to this function has changed from that of + * previous versions. The <Flags> parameter replaces two + * boolean parameters that had the same basic effect. + * + * ------------------------------------------------------------------------ ** + */ + { + if( RootPtr ) + { + RootPtr->root = NULL; + RootPtr->count = 0L; + RootPtr->cmp = CompFunc; + RootPtr->flags = (Flags & ubi_trDUPKEY) ? ubi_trDUPKEY : Flags; + } /* There are only two supported flags, and they are + * mutually exclusive. ubi_trDUPKEY takes precedence + * over ubi_trOVERWRITE. + */ + return( RootPtr ); + } /* ubi_btInitTree */ + +ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ) + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr OtherP, + parent = NULL; + char tmp; + + if( NULL == OldNode ) /* If they didn't give us a pointer, supply our own. */ + OldNode = &OtherP; + + (void)ubi_btInitNode( NewNode ); /* Init the new node's BinTree fields. */ + + /* Find a place for the new node. */ + *OldNode = TreeFind(ItemPtr, (RootPtr->root), &parent, &tmp, (RootPtr->cmp)); + + /* Now add the node to the tree... */ + if( NULL == (*OldNode) ) /* The easy one: we have a space for a new node! */ + { + if( NULL == parent ) + RootPtr->root = NewNode; + else + { + parent->Link[(int)tmp] = NewNode; + NewNode->Link[ubi_trPARENT] = parent; + NewNode->gender = tmp; + } + (RootPtr->count)++; + return( ubi_trTRUE ); + } + + /* If we reach this point, we know that a duplicate node exists. This + * section adds the node to the tree if duplicate keys are allowed. + */ + if( ubi_trDups_OK(RootPtr) ) /* Key exists, add duplicate */ + { + ubi_btNodePtr q; + + tmp = ubi_trRIGHT; + q = (*OldNode); + *OldNode = NULL; + while( NULL != q ) + { + parent = q; + if( tmp == ubi_trEQUAL ) + tmp = ubi_trRIGHT; + q = q->Link[(int)tmp]; + if ( q ) + tmp = ubi_trAbNormal( (*(RootPtr->cmp))(ItemPtr, q) ); + } + parent->Link[(int)tmp] = NewNode; + NewNode->Link[ubi_trPARENT] = parent; + NewNode->gender = tmp; + (RootPtr->count)++; + return( ubi_trTRUE ); + } + + /* If we get to *this* point, we know that we are not allowed to have + * duplicate nodes, but our node keys match, so... may we replace the + * old one? + */ + if( ubi_trOvwt_OK(RootPtr) ) /* Key exists, we replace */ + { + if( NULL == parent ) + ReplaceNode( &(RootPtr->root), *OldNode, NewNode ); + else + ReplaceNode( &(parent->Link[(int)((*OldNode)->gender)]), + *OldNode, NewNode ); + return( ubi_trTRUE ); + } + + return( ubi_trFALSE ); /* Failure: could not replace an existing node. */ + } /* ubi_btInsert */ + +ubi_btNodePtr ubi_btRemove( ubi_btRootPtr RootPtr, + ubi_btNodePtr DeadNode ) + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p, + *parentp; + int tmp; + + /* if the node has both left and right subtrees, then we have to swap + * it with another node. The other node we choose will be the Prev()ious + * node, which is garunteed to have no RIGHT child. + */ + if( (NULL != DeadNode->Link[ubi_trLEFT]) + && (NULL != DeadNode->Link[ubi_trRIGHT]) ) + SwapNodes( RootPtr, DeadNode, ubi_btPrev( DeadNode ) ); + + /* The parent of the node to be deleted may be another node, or it may be + * the root of the tree. Since we're not sure, it's best just to have + * a pointer to the parent pointer, whatever it is. + */ + if( NULL == DeadNode->Link[ubi_trPARENT] ) + parentp = &( RootPtr->root ); + else + parentp = &((DeadNode->Link[ubi_trPARENT])->Link[(int)(DeadNode->gender)]); + + /* Now link the parent to the only grand-child and patch up the gender. */ + tmp = ((DeadNode->Link[ubi_trLEFT])?ubi_trLEFT:ubi_trRIGHT); + + p = (DeadNode->Link[tmp]); + if( NULL != p ) + { + p->Link[ubi_trPARENT] = DeadNode->Link[ubi_trPARENT]; + p->gender = DeadNode->gender; + } + (*parentp) = p; + + /* Finished, reduce the node count and return. */ + (RootPtr->count)--; + return( DeadNode ); + } /* ubi_btRemove */ + +ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ) + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + { + register ubi_btNodePtr p; + ubi_btNodePtr parent; + char whichkid; + + /* Start by searching for a matching node. */ + p = TreeFind( FindMe, + RootPtr->root, + &parent, + &whichkid, + RootPtr->cmp ); + + if( NULL != p ) /* If we have found a match, we can resolve as follows: */ + { + switch( CompOp ) + { + case ubi_trLT: /* It's just a jump to the left... */ + p = Border( RootPtr, FindMe, p, ubi_trLEFT ); + return( Neighbor( p, ubi_trLEFT ) ); + case ubi_trGT: /* ...and then a jump to the right. */ + p = Border( RootPtr, FindMe, p, ubi_trRIGHT ); + return( Neighbor( p, ubi_trRIGHT ) ); + default: + p = Border( RootPtr, FindMe, p, ubi_trLEFT ); + return( p ); + } + } + + /* Else, no match. */ + if( ubi_trEQ == CompOp ) /* If we were looking for an exact match... */ + return( NULL ); /* ...forget it. */ + + /* We can still return a valid result for GT, GE, LE, and LT. + * <parent> points to a node with a value that is either just before or + * just after the target value. + * Remaining possibilities are LT and GT (including LE & GE). + */ + if( (ubi_trLT == CompOp) || (ubi_trLE == CompOp) ) + return( (ubi_trLEFT == whichkid) ? Neighbor( parent, whichkid ) : parent ); + else + return( (ubi_trRIGHT == whichkid) ? Neighbor( parent, whichkid ) : parent ); + } /* ubi_btLocate */ + +ubi_btNodePtr ubi_btFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ) + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_btLocate(). + * ------------------------------------------------------------------------ ** + */ + { + return( qFind( RootPtr->cmp, FindMe, RootPtr->root ) ); + } /* ubi_btFind */ + +ubi_btNodePtr ubi_btNext( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Next node in the + * tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "next" node in the tree, or NULL if P pointed + * to the "last" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + { + return( Neighbor( P, ubi_trRIGHT ) ); + } /* ubi_btNext */ + +ubi_btNodePtr ubi_btPrev( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Previous node in + * the tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "previous" node in the tree, or NULL if P + * pointed to the "first" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + { + return( Neighbor( P, ubi_trLEFT ) ); + } /* ubi_btPrev */ + +ubi_btNodePtr ubi_btFirst( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) First node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "first" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + { + return( SubSlide( P, ubi_trLEFT ) ); + } /* ubi_btFirst */ + +ubi_btNodePtr ubi_btLast( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Last node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "last" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + { + return( SubSlide( P, ubi_trRIGHT ) ); + } /* ubi_btLast */ + +ubi_btNodePtr ubi_btFirstOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the first (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the first node in the set of nodes with keys + * matching <FindMe>. + * Notes: Node *p MUST be in the set of nodes with keys matching + * <FindMe>. If not, this function will return NULL. + * + * 4.7: Bug found & fixed by Massimo Campostrini, + * Istituto Nazionale di Fisica Nucleare, Sezione di Pisa. + * + * ------------------------------------------------------------------------ ** + */ + { + /* If our starting point is invalid, return NULL. */ + if( (NULL == p) + || (ubi_trEQUAL != ubi_trAbNormal( (*(RootPtr->cmp))( MatchMe, p ) )) ) + return( NULL ); + return( Border( RootPtr, MatchMe, p, ubi_trLEFT ) ); + } /* ubi_btFirstOf */ + +ubi_btNodePtr ubi_btLastOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the last (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the last node in the set of nodes with keys + * matching <FindMe>. + * Notes: Node *p MUST be in the set of nodes with keys matching + * <FindMe>. If not, this function will return NULL. + * + * 4.7: Bug found & fixed by Massimo Campostrini, + * Istituto Nazionale di Fisica Nucleare, Sezione di Pisa. + * + * ------------------------------------------------------------------------ ** + */ + { + /* If our starting point is invalid, return NULL. */ + if( (NULL != p) + || (ubi_trEQUAL != ubi_trAbNormal( (*(RootPtr->cmp))( MatchMe, p ) )) ) + return( NULL ); + return( Border( RootPtr, MatchMe, p, ubi_trRIGHT ) ); + } /* ubi_btLastOf */ + +unsigned long ubi_btTraverse( ubi_btRootPtr RootPtr, + ubi_btActionRtn EachNode, + void *UserData ) + /* ------------------------------------------------------------------------ ** + * Traverse a tree in sorted order (non-recursively). At each node, call + * (*EachNode)(), passing a pointer to the current node, and UserData as the + * second parameter. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the tree to be traversed. + * EachNode - a pointer to a function to be called at each node + * as the node is visited. + * UserData - a generic pointer that may point to anything that + * you choose. + * + * Output: A count of the number of nodes visited. This will be zero + * if the tree is empty. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p = ubi_btFirst( RootPtr->root ); + unsigned long count = 0; + + while( NULL != p ) + { + (*EachNode)( p, UserData ); + count++; + p = ubi_btNext( p ); + } + return( count ); + } /* ubi_btTraverse */ + +unsigned long ubi_btKillTree( ubi_btRootPtr RootPtr, + ubi_btKillNodeRtn FreeNode ) + /* ------------------------------------------------------------------------ ** + * Delete an entire tree (non-recursively) and reinitialize the ubi_btRoot + * structure. Return a count of the number of nodes deleted. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the root of the tree to delete. + * FreeNode - a function that will be called for each node in the + * tree to deallocate the memory used by the node. + * + * Output: The number of nodes removed from the tree. + * A value of 0 will be returned if: + * - The tree actually contains 0 entries. + * - the value of <RootPtr> is NULL, in which case the tree is + * assumed to be empty + * - the value of <FreeNode> is NULL, in which case entries + * cannot be removed, so 0 is returned. *Make sure that you + * provide a valid value for <FreeNode>*. + * In all other cases, you should get a positive value equal to + * the value of RootPtr->count upon entry. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p, q; + unsigned long count = 0; + + if( (NULL == RootPtr) || (NULL == FreeNode) ) + return( 0 ); + + p = ubi_btFirst( RootPtr->root ); + while( NULL != p ) + { + q = p; + while( q->Link[ubi_trRIGHT] ) + q = SubSlide( q->Link[ubi_trRIGHT], ubi_trLEFT ); + p = q->Link[ubi_trPARENT]; + if( NULL != p ) + p->Link[ ((p->Link[ubi_trLEFT] == q)?ubi_trLEFT:ubi_trRIGHT) ] = NULL; + (*FreeNode)((void *)q); + count++; + } + + /* overkill... */ + (void)ubi_btInitTree( RootPtr, + RootPtr->cmp, + RootPtr->flags ); + return( count ); + } /* ubi_btKillTree */ + +ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader ) + /* ------------------------------------------------------------------------ ** + * Returns a pointer to a leaf node. + * + * Input: leader - Pointer to a node at which to start the descent. + * + * Output: A pointer to a leaf node, selected in a somewhat arbitrary + * manner but with an effort to dig deep. + * + * Notes: I wrote this function because I was using splay trees as a + * database cache. The cache had a maximum size on it, and I + * needed a way of choosing a node to sacrifice if the cache + * became full. In a splay tree, less recently accessed nodes + * tend toward the bottom of the tree, meaning that leaf nodes + * are good candidates for removal. (I really can't think of + * any other reason to use this function.) + * + In a simple binary tree, or in an AVL tree, the most recently + * added nodes tend to be nearer the bottom, making this a *bad* + * way to choose which node to remove from the cache. + * + Randomizing the traversal order is probably a good idea. You + * can improve the randomization of leaf node selection by passing + * in pointers to nodes other than the root node each time. A + * pointer to any node in the tree will do. Of course, if you + * pass a pointer to a leaf node you'll get the same thing back. + * + In an unbalanced splay tree, if you simply traverse downward + * until you hit a leaf node it is possible to accidentally + * stumble onto a short path. The result will be a leaf node + * that is actually very high in the tree--possibly a very + * recently accessed node. Not good. This function can follow + * multiple paths in an effort to find a leaf node deeper + * in the tree. Following a single path, of course, is the + * fastest way to find a leaf node. A complete traversal would + * be sure to find the deepest leaf but would be very costly in + * terms of time. This function uses a compromise that has + * worked well in testing. + * + * ------------------------------------------------------------------------ ** + */ + { + #define MAXPATHS 4 /* Set higher for more maximum paths, lower for fewer. */ + ubi_trNodePtr p[MAXPATHS]; + ubi_trNodePtr q[MAXPATHS]; + int whichway = ubi_trLEFT; + int paths; + int i, j; + + /* If the subtree is empty, return NULL. + */ + if( NULL == leader ) + return( NULL ); + + /* Initialize the p[] array with a pointer to the single node we've been + * given as a starting point. + */ + p[0] = leader; + paths = 1; + while( paths > 0 ) + { + for( i = 0; i < paths; i++ ) + q[i] = p[i]; + + for( i = j = 0; (i < paths) && (j < MAXPATHS); i++ ) + { + if( NULL != q[i]->Link[whichway] ) + p[j++] = q[i]->Link[whichway]; + whichway = ubi_trRevWay( whichway ); + if( (j < MAXPATHS) && (NULL != q[i]->Link[whichway]) ) + p[j++] = q[i]->Link[whichway]; + } + paths = j; + } + + return( q[0] ); + } /* ubi_btLeafNode */ + +int ubi_btModuleID( int size, char *list[] ) + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + { + if( size > 0 ) + { + list[0] = ModuleID; + if( size > 1 ) + list[1] = NULL; + return( 1 ); + } + return( 0 ); + } /* ubi_btModuleID */ + + +/* ========================================================================== */ diff --git a/source/ubiqx/ubi_BinTree.h b/source/ubiqx/ubi_BinTree.h new file mode 100644 index 00000000000..43ca1a98716 --- /dev/null +++ b/source/ubiqx/ubi_BinTree.h @@ -0,0 +1,887 @@ +#ifndef UBI_BINTREE_H +#define UBI_BINTREE_H +/* ========================================================================== ** + * ubi_BinTree.h + * + * Copyright (C) 1991-1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module implements a simple binary tree. + * + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * Log: ubi_BinTree.h,v + * Revision 4.12 2004/06/06 04:51:56 crh + * Fixed a small typo in ubi_BinTree.c (leftover testing cruft). + * Did a small amount of formatting touchup to ubi_BinTree.h. + * + * Revision 4.11 2004/06/06 03:14:09 crh + * Rewrote the ubi_btLeafNode() function. It now takes several paths in an + * effort to find a deeper leaf node. There is a small amount of extra + * overhead, but it is limited. + * + * Revision 4.10 2000/06/06 20:38:40 crh + * In the ReplaceNode() function, the old node header was being copied + * to the new node header using a byte-by-byte copy. This was causing + * the 'insure' software testing program to report a memory leak. The + * fix was to do a simple assignement: *newnode = *oldnode; + * This quieted the (errant) memory leak reports and is probably a bit + * faster than the bytewise copy. + * + * Revision 4.9 2000/01/08 23:24:30 crh + * Clarified a variety of if( pointer ) lines, replacing them with + * if( NULL != pointer ). This is more correct, and I have heard + * of at least one (obscure?) system out there that uses a non-zero + * value for NULL. + * Also, speed improvement in Neighbor(). It was comparing pointers + * when it could have compared two gender values. The pointer + * comparison was somewhat indirect (does pointer equal the pointer + * of the parent of the node pointed to by pointer). Urq. + * + * Revision 4.8 1999/09/22 03:40:30 crh + * Modified ubi_btTraverse() and ubi_btKillTree(). They now return an + * unsigned long indicating the number of nodes processed. The change + * is subtle. An empty tree formerly returned False, and now returns + * zero. + * + * Revision 4.7 1998/10/21 06:15:07 crh + * Fixed bugs in FirstOf() and LastOf() reported by Massimo Campostrini. + * See function comments. + * + * Revision 4.6 1998/07/25 17:02:10 crh + * Added the ubi_trNewTree() macro. + * + * Revision 4.5 1998/06/04 21:29:27 crh + * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files. + * This is more "standard", and is what people expect. Weird, eh? + * + * Revision 4.4 1998/06/03 17:42:46 crh + * Further fiddling with sys_include.h. It's now in ubi_BinTree.h which is + * included by all of the binary tree files. + * + * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in + * ubi_AVLtree.h and ubi_SplayTree.h. This allows easy swapping + * of tree types by simply changing a header. Unfortunately, the + * macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will + * conflict if used together. You must either choose a single tree + * type, or use the underlying function calls directly. Compare + * the two header files for more information. + * + * Revision 4.3 1998/06/02 01:28:43 crh + * Changed ubi_null.h to sys_include.h to make it more generic. + * + * Revision 4.2 1998/05/20 04:32:36 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * Also, the balance and gender fields of the node were declared as + * signed char. As I understand it, at least one SunOS or Solaris + * compiler doesn't like "signed char". The declarations were + * wrong anyway, so I changed them to simple "char". + * + * Revision 4.1 1998/03/31 06:13:47 crh + * Thomas Aglassinger sent E'mail pointing out errors in the + * dereferencing of function pointers, and a missing typecast. + * Thanks, Thomas! + * + * Revision 4.0 1998/03/10 03:16:04 crh + * Added the AVL field 'balance' to the ubi_btNode structure. This means + * that all BinTree modules now use the same basic node structure, which + * greatly simplifies the AVL module. + * Decided that this was a big enough change to justify a new major revision + * number. 3.0 was an error, so we're at 4.0. + * + * Revision 2.6 1998/01/24 06:27:30 crh + * Added ubi_trCount() macro. + * + * Revision 2.5 1997/12/23 03:59:21 crh + * In this version, all constants & macros defined in the header file have + * the ubi_tr prefix. Also cleaned up anything that gcc complained about + * when run with '-pedantic -fsyntax-only -Wall'. + * + * Revision 2.4 1997/07/26 04:11:14 crh + * + Just to be annoying I changed ubi_TRUE and ubi_FALSE to ubi_trTRUE + * and ubi_trFALSE. + * + There is now a type ubi_trBool to go with ubi_trTRUE and ubi_trFALSE. + * + There used to be something called "ubi_TypeDefs.h". I got rid of it. + * + Added function ubi_btLeafNode(). + * + * Revision 2.3 1997/06/03 05:15:27 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid conflicts. + * Also changed the interface to function InitTree(). See the comments + * for this function for more information. + * + * Revision 2.2 1995/10/03 22:00:40 CRH + * Ubisized! + * + * Revision 2.1 95/03/09 23:43:46 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:00:33 CRH + * Revision 2.0 of this program includes the following changes: + * + * 1) A fix to a major typo in the RepaceNode() function. + * 2) The addition of the static function Border(). + * 3) The addition of the public functions FirstOf() and LastOf(), which + * use Border(). These functions are used with trees that allow + * duplicate keys. + * 4) A complete rewrite of the Locate() function. Locate() now accepts + * a "comparison" operator. + * 5) Overall enhancements to both code and comments. + * + * I decided to give this a new major rev number because the interface has + * changed. In particular, there are two new functions, and changes to the + * Locate() function. + * + * Revision 1.0 93/10/15 22:55:04 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_SplayTree, the locate function was + * called "ubi_sptLocate", but the next and previous functions remained + * "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * V0.0 - June, 1991 - Written by Christopher R. Hertel (CRH). + * + * ========================================================================== ** + */ + +#include "sys_include.h" /* Global include file, used to adapt the ubiqx + * modules to the host environment and the project + * with which the modules will be used. See + * sys_include.h for more info. + */ + +/* -------------------------------------------------------------------------- ** + * Macros and constants. + * + * General purpose: + * ubi_trTRUE - Boolean TRUE. + * ubi_trFALSE - Boolean FALSE. + * + * Flags used in the tree header: + * ubi_trOVERWRITE - This flag indicates that an existing node may be + * overwritten by a new node with a matching key. + * ubi_trDUPKEY - This flag indicates that the tree allows duplicate + * keys. If the tree does allow duplicates, the + * overwrite flag is ignored. + * + * Node link array index constants: (Each node has an array of three + * pointers. One to the left, one to the right, and one back to the + * parent.) + * ubi_trLEFT - Left child pointer. + * ubi_trPARENT - Parent pointer. + * ubi_trRIGHT - Right child pointer. + * ubi_trEQUAL - Synonym for PARENT. + * + * ubi_trCompOps: These values are used in the ubi_trLocate() function. + * ubi_trLT - request the first instance of the greatest key less than + * the search key. + * ubi_trLE - request the first instance of the greatest key that is less + * than or equal to the search key. + * ubi_trEQ - request the first instance of key that is equal to the + * search key. + * ubi_trGE - request the first instance of a key that is greater than + * or equal to the search key. + * ubi_trGT - request the first instance of the first key that is greater + * than the search key. + * -------------------------------------------------------------------------- ** + */ + +#define ubi_trTRUE 0xFF +#define ubi_trFALSE 0x00 + +#define ubi_trOVERWRITE 0x01 /* Turn on allow overwrite */ +#define ubi_trDUPKEY 0x02 /* Turn on allow duplicate keys */ + +/* Pointer array index constants... */ +#define ubi_trLEFT 0x00 +#define ubi_trPARENT 0x01 +#define ubi_trRIGHT 0x02 +#define ubi_trEQUAL ubi_trPARENT + +typedef enum { + ubi_trLT = 1, + ubi_trLE, + ubi_trEQ, + ubi_trGE, + ubi_trGT + } ubi_trCompOps; + +/* -------------------------------------------------------------------------- ** + * These three macros allow simple manipulation of pointer index values (LEFT, + * RIGHT, and PARENT). + * + * Normalize() - converts {LEFT, PARENT, RIGHT} into {-1, 0 ,1}. C + * uses {negative, zero, positive} values to indicate + * {less than, equal to, greater than}. + * AbNormal() - converts {negative, zero, positive} to {LEFT, PARENT, + * RIGHT} (opposite of Normalize()). Note: C comparison + * functions, such as strcmp(), return {negative, zero, + * positive} values, which are not necessarily {-1, 0, + * 1}. This macro uses the the ubi_btSgn() function to + * compensate. + * RevWay() - converts LEFT to RIGHT and RIGHT to LEFT. PARENT (EQUAL) + * is left as is. + * -------------------------------------------------------------------------- ** + */ + +#define ubi_trNormalize(W) ((char)( (W) - ubi_trEQUAL )) +#define ubi_trAbNormal(W) ((char)( ((char)ubi_btSgn( (long)(W) )) \ + + ubi_trEQUAL )) +#define ubi_trRevWay(W) ((char)( ubi_trEQUAL - ((W) - ubi_trEQUAL) )) + +/* -------------------------------------------------------------------------- ** + * These macros allow us to quickly read the values of the OVERWRITE and + * DUPlicate KEY bits of the tree root flags field. + * -------------------------------------------------------------------------- ** + */ + +#define ubi_trDups_OK(A) \ + ((ubi_trDUPKEY & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE)) +#define ubi_trOvwt_OK(A) \ + ((ubi_trOVERWRITE & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE)) + +/* -------------------------------------------------------------------------- ** + * Additional Macros... + * + * ubi_trCount() - Given a pointer to a tree root, this macro returns the + * number of nodes currently in the tree. + * + * ubi_trNewTree() - This macro makes it easy to declare and initialize a + * tree header in one step. The line + * + * static ubi_trNewTree( MyTree, cmpfn, ubi_trDUPKEY ); + * + * is equivalent to + * + * static ubi_trRoot MyTree[1] + * = {{ NULL, cmpfn, 0, ubi_trDUPKEY }}; + * + * -------------------------------------------------------------------------- ** + */ + +#define ubi_trCount( R ) (((ubi_trRootPtr)(R))->count) + +#define ubi_trNewTree( N, C, F ) ubi_trRoot (N)[1] = {{ NULL, (C), 0, (F) }} + +/* -------------------------------------------------------------------------- ** + * Typedefs... + * + * ubi_trBool - Your typcial true or false... + * + * Item Pointer: The ubi_btItemPtr is a generic pointer. It is used to + * indicate a key that is being searched for within the tree. + * Searching occurs whenever the ubi_trFind(), ubi_trLocate(), + * or ubi_trInsert() functions are called. + * -------------------------------------------------------------------------- ** + */ + +typedef unsigned char ubi_trBool; + +typedef void *ubi_btItemPtr; /* A pointer to key data within a node. */ + +/* ------------------------------------------------------------------------- ** + * Binary Tree Node Structure: This structure defines the basic elements of + * the tree nodes. In general you *SHOULD NOT PLAY WITH THESE FIELDS*! + * But, of course, I have to put the structure into this header so that + * you can use it as a building block. + * + * The fields are as follows: + * Link - an array of pointers. These pointers are manipulated by + * the BT routines. The pointers indicate the left and right + * child nodes and the parent node. By keeping track of the + * parent pointer, we avoid the need for recursive routines or + * hand-tooled stacks to keep track of our path back to the + * root. The use of these pointers is subject to change without + * notice. + * gender - a one-byte field indicating whether the node is the RIGHT or + * LEFT child of its parent. If the node is the root of the + * tree, gender will be PARENT. + * balance - only used by the AVL tree module. This field indicates + * the height balance at a given node. See ubi_AVLtree for + * details. + * + * ------------------------------------------------------------------------- ** + */ + +typedef struct ubi_btNodeStruct { + struct ubi_btNodeStruct *Link[ 3 ]; + char gender; + char balance; + } ubi_btNode; + +typedef ubi_btNode *ubi_btNodePtr; /* Pointer to an ubi_btNode structure. */ + +/* ------------------------------------------------------------------------- ** + * The next three typedefs define standard function types used by the binary + * tree management routines. In particular: + * + * ubi_btCompFunc is a pointer to a comparison function. Comparison + * functions are passed an ubi_btItemPtr and an + * ubi_btNodePtr. They return a value that is (<0), 0, + * or (>0) to indicate that the Item is (respectively) + * "less than", "equal to", or "greater than" the Item + * contained within the node. (See ubi_btInitTree()). + * ubi_btActionRtn is a pointer to a function that may be called for each + * node visited when performing a tree traversal (see + * ubi_btTraverse()). The function will be passed two + * parameters: the first is a pointer to a node in the + * tree, the second is a generic pointer that may point to + * anything that you like. + * ubi_btKillNodeRtn is a pointer to a function that will deallocate the + * memory used by a node (see ubi_btKillTree()). Since + * memory management is left up to you, deallocation may + * mean anything that you want it to mean. Just remember + * that the tree *will* be destroyed and that none of the + * node pointers will be valid any more. + * ------------------------------------------------------------------------- ** + */ + +typedef int (*ubi_btCompFunc)( ubi_btItemPtr, ubi_btNodePtr ); + +typedef void (*ubi_btActionRtn)( ubi_btNodePtr, void * ); + +typedef void (*ubi_btKillNodeRtn)( ubi_btNodePtr ); + +/* -------------------------------------------------------------------------- ** + * Tree Root Structure: This structure gives us a convenient handle for + * accessing whole binary trees. The fields are: + * root - A pointer to the root node of the tree. + * count - A count of the number of nodes stored in the tree. + * cmp - A pointer to the comparison routine to be used when building or + * searching the tree. + * flags - A set of bit flags. Two flags are currently defined: + * + * ubi_trOVERWRITE - If set, this flag indicates that a new node should + * (bit 0x01) overwrite an old node if the two have identical + * keys (ie., the keys are equal). + * ubi_trDUPKEY - If set, this flag indicates that the tree is + * (bit 0x02) allowed to contain nodes with duplicate keys. + * + * NOTE: ubi_trInsert() tests ubi_trDUPKEY before ubi_trOVERWRITE. + * + * All of these values are set when you initialize the root structure by + * calling ubi_trInitTree(). + * -------------------------------------------------------------------------- ** + */ + +typedef struct { + ubi_btNodePtr root; /* A pointer to the root node of the tree */ + ubi_btCompFunc cmp; /* A pointer to the tree's comparison function */ + unsigned long count; /* A count of the number of nodes in the tree */ + char flags; /* Overwrite Y|N, Duplicate keys Y|N... */ + } ubi_btRoot; + +typedef ubi_btRoot *ubi_btRootPtr; /* Pointer to an ubi_btRoot structure. */ + + +/* -------------------------------------------------------------------------- ** + * Function Prototypes. + */ + +long ubi_btSgn( long x ); + /* ------------------------------------------------------------------------ ** + * Return the sign of x; {negative,zero,positive} ==> {-1, 0, 1}. + * + * Input: x - a signed long integer value. + * + * Output: the "sign" of x, represented as follows: + * -1 == negative + * 0 == zero (no sign) + * 1 == positive + * + * Note: This utility is provided in order to facilitate the conversion + * of C comparison function return values into BinTree direction + * values: {LEFT, PARENT, EQUAL}. It is INCORPORATED into the + * AbNormal() conversion macro! + * + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr ); + /* ------------------------------------------------------------------------ ** + * Initialize a tree node. + * + * Input: a pointer to a ubi_btNode structure to be initialized. + * Output: a pointer to the initialized ubi_btNode structure (ie. the + * same as the input pointer). + * ------------------------------------------------------------------------ ** + */ + +ubi_btRootPtr ubi_btInitTree( ubi_btRootPtr RootPtr, + ubi_btCompFunc CompFunc, + char Flags ); + /* ------------------------------------------------------------------------ ** + * Initialize the fields of a Tree Root header structure. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure to be + * initialized. + * CompFunc - a pointer to a comparison function that will be used + * whenever nodes in the tree must be compared against + * outside values. + * Flags - One bytes worth of flags. Flags include + * ubi_trOVERWRITE and ubi_trDUPKEY. See the header + * file for more info. + * + * Output: a pointer to the initialized ubi_btRoot structure (ie. the + * same value as RootPtr). + * + * Note: The interface to this function has changed from that of + * previous versions. The <Flags> parameter replaces two + * boolean parameters that had the same basic effect. + * ------------------------------------------------------------------------ ** + */ + +ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ); + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btRemove( ubi_btRootPtr RootPtr, + ubi_btNodePtr DeadNode ); + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ); + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ); + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_btLocate(). + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btNext( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Next node in the + * tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "next" node in the tree, or NULL if P pointed + * to the "last" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btPrev( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Previous node in + * the tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "previous" node in the tree, or NULL if P + * pointed to the "first" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btFirst( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) First node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "first" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLast( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Last node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "last" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btFirstOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ); + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the first (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the first node in the set of nodes with keys + * matching <FindMe>. + * Notes: Node *p MUST be in the set of nodes with keys matching + * <FindMe>. If not, this function will return NULL. + * + * 4.7: Bug found & fixed by Massimo Campostrini, + * Istituto Nazionale di Fisica Nucleare, Sezione di Pisa. + * + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLastOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ); + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the last (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the last node in the set of nodes with keys + * matching <FindMe>. + * Notes: Node *p MUST be in the set of nodes with keys matching + * <FindMe>. If not, this function will return NULL. + * + * 4.7: Bug found & fixed by Massimo Campostrini, + * Istituto Nazionale di Fisica Nucleare, Sezione di Pisa. + * + * ------------------------------------------------------------------------ ** + */ + +unsigned long ubi_btTraverse( ubi_btRootPtr RootPtr, + ubi_btActionRtn EachNode, + void *UserData ); + /* ------------------------------------------------------------------------ ** + * Traverse a tree in sorted order (non-recursively). At each node, call + * (*EachNode)(), passing a pointer to the current node, and UserData as the + * second parameter. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the tree to be traversed. + * EachNode - a pointer to a function to be called at each node + * as the node is visited. + * UserData - a generic pointer that may point to anything that + * you choose. + * + * Output: A count of the number of nodes visited. This will be zero + * if the tree is empty. + * + * ------------------------------------------------------------------------ ** + */ + + +unsigned long ubi_btKillTree( ubi_btRootPtr RootPtr, + ubi_btKillNodeRtn FreeNode ); + /* ------------------------------------------------------------------------ ** + * Delete an entire tree (non-recursively) and reinitialize the ubi_btRoot + * structure. Return a count of the number of nodes deleted. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the root of the tree to delete. + * FreeNode - a function that will be called for each node in the + * tree to deallocate the memory used by the node. + * + * Output: The number of nodes removed from the tree. + * A value of 0 will be returned if: + * - The tree actually contains 0 entries. + * - the value of <RootPtr> is NULL, in which case the tree is + * assumed to be empty + * - the value of <FreeNode> is NULL, in which case entries + * cannot be removed, so 0 is returned. *Make sure that you + * provide a valid value for <FreeNode>*. + * In all other cases, you should get a positive value equal to + * the value of RootPtr->count upon entry. + * + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader ); + /* ------------------------------------------------------------------------ ** + * Returns a pointer to a leaf node. + * + * Input: leader - Pointer to a node at which to start the descent. + * + * Output: A pointer to a leaf node, selected in a somewhat arbitrary + * manner but with an effort to dig deep. + * + * Notes: I wrote this function because I was using splay trees as a + * database cache. The cache had a maximum size on it, and I + * needed a way of choosing a node to sacrifice if the cache + * became full. In a splay tree, less recently accessed nodes + * tend toward the bottom of the tree, meaning that leaf nodes + * are good candidates for removal. (I really can't think of + * any other reason to use this function.) + * + In a simple binary tree, or in an AVL tree, the most recently + * added nodes tend to be nearer the bottom, making this a *bad* + * way to choose which node to remove from the cache. + * + Randomizing the traversal order is probably a good idea. You + * can improve the randomization of leaf node selection by passing + * in pointers to nodes other than the root node each time. A + * pointer to any node in the tree will do. Of course, if you + * pass a pointer to a leaf node you'll get the same thing back. + * + In an unbalanced splay tree, if you simply traverse downward + * until you hit a leaf node it is possible to accidentally + * stumble onto a short path. The result will be a leaf node + * that is actually very high in the tree--possibly a very + * recently accessed node. Not good. This function can follow + * multiple paths in an effort to find a leaf node deeper + * in the tree. Following a single path, of course, is the + * fastest way to find a leaf node. A complete traversal would + * be sure to find the deepest leaf but would be very costly in + * terms of time. This function uses a compromise that has + * worked well in testing. + * + * ------------------------------------------------------------------------ ** + */ + + +int ubi_btModuleID( int size, char *list[] ); + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + +/* -------------------------------------------------------------------------- ** + * Masquarade... + * + * This set of defines allows you to write programs that will use any of the + * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). + * Instead of using ubi_bt..., use ubi_tr..., and select the tree type by + * including the appropriate module header. + */ + +#define ubi_trItemPtr ubi_btItemPtr + +#define ubi_trNode ubi_btNode +#define ubi_trNodePtr ubi_btNodePtr + +#define ubi_trRoot ubi_btRoot +#define ubi_trRootPtr ubi_btRootPtr + +#define ubi_trCompFunc ubi_btCompFunc +#define ubi_trActionRtn ubi_btActionRtn +#define ubi_trKillNodeRtn ubi_btKillNodeRtn + +#define ubi_trSgn( x ) ubi_btSgn( x ) + +#define ubi_trInitNode( Np ) ubi_btInitNode( (ubi_btNodePtr)(Np) ) + +#define ubi_trInitTree( Rp, Cf, Fl ) \ + ubi_btInitTree( (ubi_btRootPtr)(Rp), (ubi_btCompFunc)(Cf), (Fl) ) + +#define ubi_trInsert( Rp, Nn, Ip, On ) \ + ubi_btInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \ + (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) ) + +#define ubi_trRemove( Rp, Dn ) \ + ubi_btRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) ) + +#define ubi_trLocate( Rp, Ip, Op ) \ + ubi_btLocate( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_trCompOps)(Op) ) + +#define ubi_trFind( Rp, Ip ) \ + ubi_btFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) + +#define ubi_trNext( P ) ubi_btNext( (ubi_btNodePtr)(P) ) + +#define ubi_trPrev( P ) ubi_btPrev( (ubi_btNodePtr)(P) ) + +#define ubi_trFirst( P ) ubi_btFirst( (ubi_btNodePtr)(P) ) + +#define ubi_trLast( P ) ubi_btLast( (ubi_btNodePtr)(P) ) + +#define ubi_trFirstOf( Rp, Ip, P ) \ + ubi_btFirstOf( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_btNodePtr)(P) ) + +#define ubi_trLastOf( Rp, Ip, P ) \ + ubi_btLastOf( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_btNodePtr)(P) ) + +#define ubi_trTraverse( Rp, En, Ud ) \ + ubi_btTraverse((ubi_btRootPtr)(Rp), (ubi_btActionRtn)(En), (void *)(Ud)) + +#define ubi_trKillTree( Rp, Fn ) \ + ubi_btKillTree( (ubi_btRootPtr)(Rp), (ubi_btKillNodeRtn)(Fn) ) + +#define ubi_trLeafNode( Nd ) \ + ubi_btLeafNode( (ubi_btNodePtr)(Nd) ) + +#define ubi_trModuleID( s, l ) ubi_btModuleID( s, l ) + +/* ========================================================================== */ +#endif /* UBI_BINTREE_H */ diff --git a/source/ubiqx/ubi_Cache.c b/source/ubiqx/ubi_Cache.c new file mode 100644 index 00000000000..f428dcefe97 --- /dev/null +++ b/source/ubiqx/ubi_Cache.c @@ -0,0 +1,505 @@ +/* ========================================================================== ** + * ubi_Cache.c + * + * Copyright (C) 1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module implements a generic cache. + * + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * This module uses a splay tree to implement a simple cache. The cache + * module adds a thin layer of functionality to the splay tree. In + * particular: + * + * - The tree (cache) may be limited in size by the number of + * entries permitted or the amount of memory used. When either + * limit is exceeded cache entries are removed until the cache + * conforms. + * - Some statistical information is kept so that an approximate + * "hit ratio" can be calculated. + * - There are several functions available that provide access to + * and management of cache size limits, hit ratio, and tree + * trimming. + * + * The splay tree is used because recently accessed items tend toward the + * top of the tree and less recently accessed items tend toward the bottom. + * This makes it easy to purge less recently used items should the cache + * exceed its limits. + * + * To use this module, you will need to supply a comparison function of + * type ubi_trCompFunc and a node-freeing function of type + * ubi_trKillNodeRtn. See ubi_BinTree.h for more information on + * these. (This is all basic ubiqx tree management stuff.) + * + * Notes: + * + * - Cache performance will start to suffer dramatically if the + * cache becomes large enough to force the OS to start swapping + * memory to disk. This is because the nodes of the underlying tree + * will be scattered across memory in an order that is completely + * unrelated to their traversal order. As more and more of the + * cache is placed into swap space, more and more swaps will be + * required for a simple traversal (...and then there's the splay + * operation). + * + * In one simple test under Linux, the load and dump of a cache of + * 400,000 entries took only 1min, 40sec of real time. The same + * test with 450,000 records took 2 *hours* and eight minutes. + * + * - In an effort to save memory, I considered using an unsigned + * short to save the per-entry entry size. I would have tucked this + * value into some unused space in the tree node structure. On + * 32-bit word aligned systems this would have saved an additional + * four bytes per entry. I may revisit this issue, but for now I've + * decided against it. + * + * Using an unsigned short would limit the size of an entry to 64K + * bytes. That's probably more than enough for most applications. + * The key word in that last sentence, however, is "probably". I + * really dislike imposing such limits on things. + * + * - Each entry keeps track of the amount of memory it used and the + * cache header keeps the total. This information is provided via + * the EntrySize parameter in ubi_cachePut(), so it is up to you to + * make sure that the numbers are accurate. (The numbers don't even + * have to represent bytes used.) + * + * As you consider this, note that the strdup() function--as an + * example--will call malloc(). The latter generally allocates a + * multiple of the system word size, which may be more than the + * number of bytes needed to store the string. + * + * -------------------------------------------------------------------------- ** + * + * Log: ubi_Cache.c,v + * Revision 0.4 1999/09/22 03:42:24 crh + * Fixed a minor typo. + * + * Revision 0.3 1998/06/03 18:00:15 crh + * Further fiddling with sys_include.h, which is no longer explicitly + * included by this module since it is inherited from ubi_BinTree.h. + * + * Revision 0.2 1998/06/02 01:36:18 crh + * Changed include name from ubi_null.h to sys_include.h to make it + * more generic. + * + * Revision 0.1 1998/05/20 04:36:02 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * + * Revision 0.0 1997/12/18 06:24:33 crh + * Initial Revision. + * + * ========================================================================== ** + */ + +#include "ubi_Cache.h" /* Header for *this* module. */ + +/* -------------------------------------------------------------------------- ** + * Static data... + */ + +/* commented out until I make use of it... +static char ModuleID[] = +"ubi_Cache\n\ +\tRevision: 0.4 \n\ +\tDate: 1999/09/22 03:42:24 \n\ +\tAuthor: crh \n"; +*/ + +/* -------------------------------------------------------------------------- ** + * Internal functions... + */ + +static void free_entry( ubi_cacheRootPtr CachePtr, ubi_cacheEntryPtr EntryPtr ) + /* ------------------------------------------------------------------------ ** + * Free a ubi_cacheEntry, and adjust the mem_used counter accordingly. + * + * Input: CachePtr - A pointer to the cache from which the entry has + * been removed. + * EntryPtr - A pointer to the already removed entry. + * + * Output: none. + * + * Notes: The entry must be removed from the cache *before* this function + * is called!!!! + * ------------------------------------------------------------------------ ** + */ + { + CachePtr->mem_used -= EntryPtr->entry_size; + (*CachePtr->free_func)( (void *)EntryPtr ); + } /* free_entry */ + +static void cachetrim( ubi_cacheRootPtr crptr ) + /* ------------------------------------------------------------------------ ** + * Remove entries from the cache until the number of entries and the amount + * of memory used are *both* below or at the maximum. + * + * Input: crptr - pointer to the cache to be trimmed. + * + * Output: None. + * + * ------------------------------------------------------------------------ ** + */ + { + while( ( crptr->max_entries && (crptr->max_entries < crptr->root.count) ) + || ( crptr->max_memory && (crptr->max_memory < crptr->mem_used) ) ) + { + if( !ubi_cacheReduce( crptr, 1 ) ) + return; + } + } /* cachetrim */ + + +/* -------------------------------------------------------------------------- ** + * Exported functions... + */ + +ubi_cacheRootPtr ubi_cacheInit( ubi_cacheRootPtr CachePtr, + ubi_trCompFunc CompFunc, + ubi_trKillNodeRtn FreeFunc, + unsigned long MaxEntries, + unsigned long MaxMemory ) + /* ------------------------------------------------------------------------ ** + * Initialize a cache header structure. + * + * Input: CachePtr - A pointer to a ubi_cacheRoot structure that is + * to be initialized. + * CompFunc - A pointer to the function that will be called + * to compare two cache values. See the module + * comments, above, for more information. + * FreeFunc - A pointer to a function that will be called + * to free a cache entry. If you allocated + * the cache entry using malloc(), then this + * will likely be free(). If you are allocating + * cache entries from a free list, then this will + * likely be a function that returns memory to the + * free list, etc. + * MaxEntries - The maximum number of entries that will be + * allowed to exist in the cache. If this limit + * is exceeded, then existing entries will be + * removed from the cache. A value of zero + * indicates that there is no limit on the number + * of cache entries. See ubi_cachePut(). + * MaxMemory - The maximum amount of memory, in bytes, to be + * allocated to the cache (excluding the cache + * header). If this is exceeded, existing entries + * in the cache will be removed until enough memory + * has been freed to meet the condition. See + * ubi_cachePut(). + * + * Output: A pointer to the initialized cache (i.e., the same as CachePtr). + * + * Notes: Both MaxEntries and MaxMemory may be changed after the cache + * has been created. See + * ubi_cacheSetMaxEntries() + * ubi_cacheSetMaxMemory() + * ubi_cacheGetMaxEntries() + * ubi_cacheGetMaxMemory() (the latter two are macros). + * + * - Memory is allocated in multiples of the word size. The + * return value of the strlen() function does not reflect + * this; it will allways be less than or equal to the amount + * of memory actually allocated. Keep this in mind when + * choosing a value for MaxMemory. + * + * ------------------------------------------------------------------------ ** + */ + { + if( CachePtr ) + { + (void)ubi_trInitTree( CachePtr, CompFunc, ubi_trOVERWRITE ); + CachePtr->free_func = FreeFunc; + CachePtr->max_entries = MaxEntries; + CachePtr->max_memory = MaxMemory; + CachePtr->mem_used = 0; + CachePtr->cache_hits = 0; + CachePtr->cache_trys = 0; + } + return( CachePtr ); + } /* ubi_cacheInit */ + +ubi_cacheRootPtr ubi_cacheClear( ubi_cacheRootPtr CachePtr ) + /* ------------------------------------------------------------------------ ** + * Remove and free all entries in an existing cache. + * + * Input: CachePtr - A pointer to the cache that is to be cleared. + * + * Output: A pointer to the cache header (i.e., the same as CachePtr). + * This function re-initializes the cache header. + * + * ------------------------------------------------------------------------ ** + */ + { + if( CachePtr ) + { + (void)ubi_trKillTree( CachePtr, CachePtr->free_func ); + CachePtr->mem_used = 0; + CachePtr->cache_hits = 0; + CachePtr->cache_trys = 0; + } + return( CachePtr ); + } /* ubi_cacheClear */ + +void ubi_cachePut( ubi_cacheRootPtr CachePtr, + unsigned long EntrySize, + ubi_cacheEntryPtr EntryPtr, + ubi_trItemPtr Key ) + /* ------------------------------------------------------------------------ ** + * Add an entry to the cache. + * + * Input: CachePtr - A pointer to the cache into which the entry + * will be added. + * EntrySize - The size, in bytes, of the memory block indicated + * by EntryPtr. This will be copied into the + * EntryPtr->entry_size field. + * EntryPtr - A pointer to a memory block that begins with a + * ubi_cacheEntry structure. The entry structure + * should be followed immediately by the data to be + * cached (even if that is a pointer to yet more data). + * Key - Pointer used to identify the lookup key within the + * Entry. + * + * Output: None. + * + * Notes: After adding the new node, the cache is "trimmed". This + * removes extra nodes if the tree has exceeded it's memory or + * entry count limits. It is unlikely that the newly added node + * will be purged from the cache (assuming a reasonably large + * cache), since new nodes in a splay tree (which is what this + * module was designed to use) are moved to the top of the tree + * and the cache purge process removes nodes from the bottom of + * the tree. + * - The underlying splay tree is opened in OVERWRITE mode. If + * the input key matches an existing key, the existing entry will + * be politely removed from the tree and freed. + * - Memory is allocated in multiples of the word size. The + * return value of the strlen() function does not reflect + * this; it will allways be less than or equal to the amount + * of memory actually allocated. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_trNodePtr OldNode; + + EntryPtr->entry_size = EntrySize; + CachePtr->mem_used += EntrySize; + (void)ubi_trInsert( CachePtr, EntryPtr, Key, &OldNode ); + if( OldNode ) + free_entry( CachePtr, (ubi_cacheEntryPtr)OldNode ); + + cachetrim( CachePtr ); + } /* ubi_cachePut */ + +ubi_cacheEntryPtr ubi_cacheGet( ubi_cacheRootPtr CachePtr, + ubi_trItemPtr FindMe ) + /* ------------------------------------------------------------------------ ** + * Attempt to retrieve an entry from the cache. + * + * Input: CachePtr - A ponter to the cache that is to be searched. + * FindMe - A ubi_trItemPtr that indicates the key for which + * to search. + * + * Output: A pointer to the cache entry that was found, or NULL if no + * matching entry was found. + * + * Notes: This function also updates the hit ratio counters. + * The counters are unsigned short. If the number of cache tries + * reaches 32768, then both the number of tries and the number of + * hits are divided by two. This prevents the counters from + * overflowing. See the comments in ubi_cacheHitRatio() for + * additional notes. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_trNodePtr FoundPtr; + + FoundPtr = ubi_trFind( CachePtr, FindMe ); + + if( FoundPtr ) + CachePtr->cache_hits++; + CachePtr->cache_trys++; + + if( CachePtr->cache_trys & 0x8000 ) + { + CachePtr->cache_hits = CachePtr->cache_hits / 2; + CachePtr->cache_trys = CachePtr->cache_trys / 2; + } + + return( (ubi_cacheEntryPtr)FoundPtr ); + } /* ubi_cacheGet */ + +ubi_trBool ubi_cacheDelete( ubi_cacheRootPtr CachePtr, ubi_trItemPtr DeleteMe ) + /* ------------------------------------------------------------------------ ** + * Find and delete the specified cache entry. + * + * Input: CachePtr - A pointer to the cache. + * DeleteMe - The key of the entry to be deleted. + * + * Output: TRUE if the entry was found & freed, else FALSE. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_trNodePtr FoundPtr; + + FoundPtr = ubi_trFind( CachePtr, DeleteMe ); + if( FoundPtr ) + { + (void)ubi_trRemove( CachePtr, FoundPtr ); + free_entry( CachePtr, (ubi_cacheEntryPtr)FoundPtr ); + return( ubi_trTRUE ); + } + return( ubi_trFALSE ); + } /* ubi_cacheDelete */ + +ubi_trBool ubi_cacheReduce( ubi_cacheRootPtr CachePtr, unsigned long count ) + /* ------------------------------------------------------------------------ ** + * Remove <count> entries from the bottom of the cache. + * + * Input: CachePtr - A pointer to the cache which is to be reduced in + * size. + * count - The number of entries to remove. + * + * Output: The function will return TRUE if <count> entries were removed, + * else FALSE. A return value of FALSE should indicate that + * there were less than <count> entries in the cache, and that the + * cache is now empty. + * + * Notes: This function forces a reduction in the number of cache entries + * without requiring that the MaxMemory or MaxEntries values be + * changed. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_trNodePtr NodePtr; + + while( count ) + { + NodePtr = ubi_trLeafNode( CachePtr->root.root ); + if( NULL == NodePtr ) + return( ubi_trFALSE ); + else + { + (void)ubi_trRemove( CachePtr, NodePtr ); + free_entry( CachePtr, (ubi_cacheEntryPtr)NodePtr ); + } + count--; + } + return( ubi_trTRUE ); + } /* ubi_cacheReduce */ + +unsigned long ubi_cacheSetMaxEntries( ubi_cacheRootPtr CachePtr, + unsigned long NewSize ) + /* ------------------------------------------------------------------------ ** + * Change the maximum number of entries allowed to exist in the cache. + * + * Input: CachePtr - A pointer to the cache to be modified. + * NewSize - The new maximum number of cache entries. + * + * Output: The maximum number of entries previously allowed to exist in + * the cache. + * + * Notes: If the new size is less than the old size, this function will + * trim the cache (remove excess entries). + * - A value of zero indicates an unlimited number of entries. + * + * ------------------------------------------------------------------------ ** + */ + { + unsigned long oldsize = CachePtr->max_entries; /* Save the old value. */ + + CachePtr->max_entries = NewSize; /* Apply the new value. */ + if( (NewSize < oldsize) || (NewSize && !oldsize) ) /* If size is smaller, */ + cachetrim( CachePtr ); /* remove excess. */ + return( oldsize ); + } /* ubi_cacheSetMaxEntries */ + +unsigned long ubi_cacheSetMaxMemory( ubi_cacheRootPtr CachePtr, + unsigned long NewSize ) + /* ------------------------------------------------------------------------ ** + * Change the maximum amount of memory to be used for storing cache + * entries. + * + * Input: CachePtr - A pointer to the cache to be modified. + * NewSize - The new cache memory size. + * + * Output: The previous maximum memory size. + * + * Notes: If the new size is less than the old size, this function will + * trim the cache (remove excess entries). + * - A value of zero indicates that the cache has no memory limit. + * + * ------------------------------------------------------------------------ ** + */ + { + unsigned long oldsize = CachePtr->max_memory; /* Save the old value. */ + + CachePtr->max_memory = NewSize; /* Apply the new value. */ + if( (NewSize < oldsize) || (NewSize && !oldsize) ) /* If size is smaller, */ + cachetrim( CachePtr ); /* remove excess. */ + return( oldsize ); + } /* ubi_cacheSetMaxMemory */ + +int ubi_cacheHitRatio( ubi_cacheRootPtr CachePtr ) + /* ------------------------------------------------------------------------ ** + * Returns a value that is 10,000 times the slightly weighted average hit + * ratio for the cache. + * + * Input: CachePtr - Pointer to the cache to be queried. + * + * Output: An integer that is 10,000 times the number of successful + * cache hits divided by the number of cache lookups, or: + * (10000 * hits) / trys + * You can easily convert this to a float, or do something + * like this (where i is the return value of this function): + * + * printf( "Hit rate : %d.%02d%%\n", (i/100), (i%100) ); + * + * Notes: I say "slightly-weighted", because the numerator and + * denominator are both accumulated in locations of type + * 'unsigned short'. If the number of cache trys becomes + * large enough, both are divided by two. (See function + * ubi_cacheGet().) + * Dividing both numerator and denominator by two does not + * change the ratio (much...it is an integer divide), but it + * does mean that subsequent increments to either counter will + * have twice as much significance as previous ones. + * + * - The value returned by this function will be in the range + * [0..10000] because ( 0 <= cache_hits <= cache_trys ) will + * always be true. + * + * ------------------------------------------------------------------------ ** + */ + { + int tmp = 0; + + if( CachePtr->cache_trys ) + tmp = (int)( (10000 * (long)(CachePtr->cache_hits) ) + / (long)(CachePtr->cache_trys) ); + return( tmp ); + } /* ubi_cacheHitRatio */ + +/* -------------------------------------------------------------------------- */ diff --git a/source/ubiqx/ubi_Cache.h b/source/ubiqx/ubi_Cache.h new file mode 100644 index 00000000000..0fc3a074f72 --- /dev/null +++ b/source/ubiqx/ubi_Cache.h @@ -0,0 +1,412 @@ +#ifndef UBI_CACHE_H +#define UBI_CACHE_H +/* ========================================================================== ** + * ubi_Cache.h + * + * Copyright (C) 1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module implements a generic cache. + * + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * This module uses a splay tree to implement a simple cache. The cache + * module adds a thin layer of functionality to the splay tree. In + * particular: + * + * - The tree (cache) may be limited in size by the number of + * entries permitted or the amount of memory used. When either + * limit is exceeded cache entries are removed until the cache + * conforms. + * - Some statistical information is kept so that an approximate + * "hit ratio" can be calculated. + * - There are several functions available that provide access to + * and management of cache size limits, hit ratio, and tree + * trimming. + * + * The splay tree is used because recently accessed items tend toward the + * top of the tree and less recently accessed items tend toward the bottom. + * This makes it easy to purge less recently used items should the cache + * exceed its limits. + * + * To use this module, you will need to supply a comparison function of + * type ubi_trCompFunc and a node-freeing function of type + * ubi_trKillNodeRtn. See ubi_BinTree.h for more information on + * these. (This is all basic ubiqx tree management stuff.) + * + * Notes: + * + * - Cache performance will start to suffer dramatically if the + * cache becomes large enough to force the OS to start swapping + * memory to disk. This is because the nodes of the underlying tree + * will be scattered across memory in an order that is completely + * unrelated to their traversal order. As more and more of the + * cache is placed into swap space, more and more swaps will be + * required for a simple traversal (...and then there's the splay + * operation). + * + * In one simple test under Linux, the load and dump of a cache of + * 400,000 entries took only 1min, 40sec of real time. The same + * test with 450,000 records took 2 *hours* and eight minutes. + * + * - In an effort to save memory, I considered using an unsigned + * short to save the per-entry entry size. I would have tucked this + * value into some unused space in the tree node structure. On + * 32-bit word aligned systems this would have saved an additional + * four bytes per entry. I may revisit this issue, but for now I've + * decided against it. + * + * Using an unsigned short would limit the size of an entry to 64K + * bytes. That's probably more than enough for most applications. + * The key word in that last sentence, however, is "probably". I + * really dislike imposing such limits on things. + * + * - Each entry keeps track of the amount of memory it used and the + * cache header keeps the total. This information is provided via + * the EntrySize parameter in ubi_cachePut(), so it is up to you to + * make sure that the numbers are accurate. (The numbers don't even + * have to represent bytes used.) + * + * As you consider this, note that the strdup() function--as an + * example--will call malloc(). The latter generally allocates a + * multiple of the system word size, which may be more than the + * number of bytes needed to store the string. + * + * -------------------------------------------------------------------------- ** + * + * Log: ubi_Cache.h,v + * Revision 0.4 1999/09/22 03:42:24 crh + * Fixed a minor typo. + * + * Revision 0.3 1998/06/03 18:00:15 crh + * Further fiddling with sys_include.h, which is no longer explicitly + * included by this module since it is inherited from ubi_BinTree.h. + * + * Revision 0.2 1998/06/02 01:36:18 crh + * Changed include name from ubi_null.h to sys_include.h to make it + * more generic. + * + * Revision 0.1 1998/05/20 04:36:02 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * + * Revision 0.0 1997/12/18 06:25:23 crh + * Initial Revision. + * + * ========================================================================== ** + */ + +#include "ubi_SplayTree.h" + +/* -------------------------------------------------------------------------- ** + * Typedefs... + * + * ubi_cacheRoot - Cache header structure, which consists of a binary + * tree root and other required housekeeping fields, as + * listed below. + * ubi_cacheRootPtr - Pointer to a Cache. + * + * ubi_cacheEntry - A cache Entry, which consists of a tree node + * structure and the size (in bytes) of the entry + * data. The entry size should be supplied via + * the EntrySize parameter of the ubi_cachePut() + * function. + * + * ubi_cacheEntryPtr - Pointer to a ubi_cacheEntry. + * + */ + +typedef struct + { + ubi_trRoot root; /* Splay tree control structure. */ + ubi_trKillNodeRtn free_func; /* Function used to free entries. */ + unsigned long max_entries; /* Max cache entries. 0 == unlimited */ + unsigned long max_memory; /* Max memory to use. 0 == unlimited */ + unsigned long mem_used; /* Memory currently in use (bytes). */ + unsigned short cache_hits; /* Incremented on succesful find. */ + unsigned short cache_trys; /* Incremented on cache lookup. */ + } ubi_cacheRoot; + +typedef ubi_cacheRoot *ubi_cacheRootPtr; + + +typedef struct + { + ubi_trNode node; /* Tree node structure. */ + unsigned long entry_size; /* Entry size. Used when managing + * caches with maximum memory limits. + */ + } ubi_cacheEntry; + +typedef ubi_cacheEntry *ubi_cacheEntryPtr; + + +/* -------------------------------------------------------------------------- ** + * Macros... + * + * ubi_cacheGetMaxEntries() - Report the current maximum number of entries + * allowed in the cache. Zero indicates no + * maximum. + * ubi_cacheGetMaxMemory() - Report the current maximum amount of memory + * that may be used in the cache. Zero + * indicates no maximum. + * ubi_cacheGetEntryCount() - Report the current number of entries in the + * cache. + * ubi_cacheGetMemUsed() - Report the amount of memory currently in use + * by the cache. + */ + +#define ubi_cacheGetMaxEntries( Cptr ) (((ubi_cacheRootPtr)(Cptr))->max_entries) +#define ubi_cacheGetMaxMemory( Cptr ) (((ubi_cacheRootPtr)(Cptr))->max_memory) + +#define ubi_cacheGetEntryCount( Cptr ) (((ubi_cacheRootPtr)(Cptr))->root.count) +#define ubi_cacheGetMemUsed( Cptr ) (((ubi_cacheRootPtr)(Cptr))->mem_used) + +/* -------------------------------------------------------------------------- ** + * Prototypes... + */ + +ubi_cacheRootPtr ubi_cacheInit( ubi_cacheRootPtr CachePtr, + ubi_trCompFunc CompFunc, + ubi_trKillNodeRtn FreeFunc, + unsigned long MaxEntries, + unsigned long MaxMemory ); + /* ------------------------------------------------------------------------ ** + * Initialize a cache header structure. + * + * Input: CachePtr - A pointer to a ubi_cacheRoot structure that is + * to be initialized. + * CompFunc - A pointer to the function that will be called + * to compare two cache values. See the module + * comments, above, for more information. + * FreeFunc - A pointer to a function that will be called + * to free a cache entry. If you allocated + * the cache entry using malloc(), then this + * will likely be free(). If you are allocating + * cache entries from a free list, then this will + * likely be a function that returns memory to the + * free list, etc. + * MaxEntries - The maximum number of entries that will be + * allowed to exist in the cache. If this limit + * is exceeded, then existing entries will be + * removed from the cache. A value of zero + * indicates that there is no limit on the number + * of cache entries. See ubi_cachePut(). + * MaxMemory - The maximum amount of memory, in bytes, to be + * allocated to the cache (excluding the cache + * header). If this is exceeded, existing entries + * in the cache will be removed until enough memory + * has been freed to meet the condition. See + * ubi_cachePut(). + * + * Output: A pointer to the initialized cache (i.e., the same as CachePtr). + * + * Notes: Both MaxEntries and MaxMemory may be changed after the cache + * has been created. See + * ubi_cacheSetMaxEntries() + * ubi_cacheSetMaxMemory() + * ubi_cacheGetMaxEntries() + * ubi_cacheGetMaxMemory() (the latter two are macros). + * + * - Memory is allocated in multiples of the word size. The + * return value of the strlen() function does not reflect + * this; it will allways be less than or equal to the amount + * of memory actually allocated. Keep this in mind when + * choosing a value for MaxMemory. + * + * ------------------------------------------------------------------------ ** + */ + +ubi_cacheRootPtr ubi_cacheClear( ubi_cacheRootPtr CachePtr ); + /* ------------------------------------------------------------------------ ** + * Remove and free all entries in an existing cache. + * + * Input: CachePtr - A pointer to the cache that is to be cleared. + * + * Output: A pointer to the cache header (i.e., the same as CachePtr). + * This function re-initializes the cache header. + * + * ------------------------------------------------------------------------ ** + */ + +void ubi_cachePut( ubi_cacheRootPtr CachePtr, + unsigned long EntrySize, + ubi_cacheEntryPtr EntryPtr, + ubi_trItemPtr Key ); + /* ------------------------------------------------------------------------ ** + * Add an entry to the cache. + * + * Input: CachePtr - A pointer to the cache into which the entry + * will be added. + * EntrySize - The size, in bytes, of the memory block indicated + * by EntryPtr. This will be copied into the + * EntryPtr->entry_size field. + * EntryPtr - A pointer to a memory block that begins with a + * ubi_cacheEntry structure. The entry structure + * should be followed immediately by the data to be + * cached (even if that is a pointer to yet more data). + * Key - Pointer used to identify the lookup key within the + * Entry. + * + * Output: None. + * + * Notes: After adding the new node, the cache is "trimmed". This + * removes extra nodes if the tree has exceeded it's memory or + * entry count limits. It is unlikely that the newly added node + * will be purged from the cache (assuming a reasonably large + * cache), since new nodes in a splay tree (which is what this + * module was designed to use) are moved to the top of the tree + * and the cache purge process removes nodes from the bottom of + * the tree. + * - The underlying splay tree is opened in OVERWRITE mode. If + * the input key matches an existing key, the existing entry will + * be politely removed from the tree and freed. + * - Memory is allocated in multiples of the word size. The + * return value of the strlen() function does not reflect + * this; it will allways be less than or equal to the amount + * of memory actually allocated. + * + * ------------------------------------------------------------------------ ** + */ + +ubi_cacheEntryPtr ubi_cacheGet( ubi_cacheRootPtr CachePtr, + ubi_trItemPtr FindMe ); + /* ------------------------------------------------------------------------ ** + * Attempt to retrieve an entry from the cache. + * + * Input: CachePtr - A ponter to the cache that is to be searched. + * FindMe - A ubi_trItemPtr that indicates the key for which + * to search. + * + * Output: A pointer to the cache entry that was found, or NULL if no + * matching entry was found. + * + * Notes: This function also updates the hit ratio counters. + * The counters are unsigned short. If the number of cache tries + * reaches 32768, then both the number of tries and the number of + * hits are divided by two. This prevents the counters from + * overflowing. See the comments in ubi_cacheHitRatio() for + * additional notes. + * + * ------------------------------------------------------------------------ ** + */ + +ubi_trBool ubi_cacheDelete( ubi_cacheRootPtr CachePtr, ubi_trItemPtr DeleteMe ); + /* ------------------------------------------------------------------------ ** + * Find and delete the specified cache entry. + * + * Input: CachePtr - A pointer to the cache. + * DeleteMe - The key of the entry to be deleted. + * + * Output: TRUE if the entry was found & freed, else FALSE. + * + * ------------------------------------------------------------------------ ** + */ + +ubi_trBool ubi_cacheReduce( ubi_cacheRootPtr CachePtr, unsigned long count ); + /* ------------------------------------------------------------------------ ** + * Remove <count> entries from the bottom of the cache. + * + * Input: CachePtr - A pointer to the cache which is to be reduced in + * size. + * count - The number of entries to remove. + * + * Output: The function will return TRUE if <count> entries were removed, + * else FALSE. A return value of FALSE should indicate that + * there were less than <count> entries in the cache, and that the + * cache is now empty. + * + * Notes: This function forces a reduction in the number of cache entries + * without requiring that the MaxMemory or MaxEntries values be + * changed. + * + * ------------------------------------------------------------------------ ** + */ + +unsigned long ubi_cacheSetMaxEntries( ubi_cacheRootPtr CachePtr, + unsigned long NewSize ); + /* ------------------------------------------------------------------------ ** + * Change the maximum number of entries allowed to exist in the cache. + * + * Input: CachePtr - A pointer to the cache to be modified. + * NewSize - The new maximum number of cache entries. + * + * Output: The maximum number of entries previously allowed to exist in + * the cache. + * + * Notes: If the new size is less than the old size, this function will + * trim the cache (remove excess entries). + * - A value of zero indicates an unlimited number of entries. + * + * ------------------------------------------------------------------------ ** + */ + +unsigned long ubi_cacheSetMaxMemory( ubi_cacheRootPtr CachePtr, + unsigned long NewSize ); + /* ------------------------------------------------------------------------ ** + * Change the maximum amount of memory to be used for storing cache + * entries. + * + * Input: CachePtr - A pointer to the cache to be modified. + * NewSize - The new cache memory size. + * + * Output: The previous maximum memory size. + * + * Notes: If the new size is less than the old size, this function will + * trim the cache (remove excess entries). + * - A value of zero indicates that the cache has no memory limit. + * + * ------------------------------------------------------------------------ ** + */ + +int ubi_cacheHitRatio( ubi_cacheRootPtr CachePtr ); + /* ------------------------------------------------------------------------ ** + * Returns a value that is 10,000 times the slightly weighted average hit + * ratio for the cache. + * + * Input: CachePtr - Pointer to the cache to be queried. + * + * Output: An integer that is 10,000 times the number of successful + * cache hits divided by the number of cache lookups, or: + * (10000 * hits) / trys + * You can easily convert this to a float, or do something + * like this (where i is the return value of this function): + * + * printf( "Hit rate : %d.%02d%%\n", (i/100), (i%100) ); + * + * Notes: I say "slightly-weighted", because the numerator and + * denominator are both accumulated in locations of type + * 'unsigned short'. If the number of cache trys becomes + * large enough, both are divided by two. (See function + * ubi_cacheGet().) + * Dividing both numerator and denominator by two does not + * change the ratio (much...it is an integer divide), but it + * does mean that subsequent increments to either counter will + * have twice as much significance as previous ones. + * + * - The value returned by this function will be in the range + * [0..10000] because ( 0 <= cache_hits <= cache_trys ) will + * always be true. + * + * ------------------------------------------------------------------------ ** + */ + +/* -------------------------------------------------------------------------- */ +#endif /* ubi_CACHE_H */ diff --git a/source/ubiqx/ubi_SplayTree.c b/source/ubiqx/ubi_SplayTree.c new file mode 100644 index 00000000000..222506bd06b --- /dev/null +++ b/source/ubiqx/ubi_SplayTree.c @@ -0,0 +1,512 @@ +/* ========================================================================== ** + * ubi_SplayTree.c + * + * Copyright (C) 1993-1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module implements "splay" trees. Splay trees are binary trees + * that are rearranged (splayed) whenever a node is accessed. The + * splaying process *tends* to make the tree bushier (improves balance), + * and the nodes that are accessed most frequently *tend* to be closer to + * the top. + * + * References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and + * Robert Tarjan. Journal of the Association for Computing + * Machinery Vol 32, No. 3, July 1985 pp. 652-686 + * + * See also: http://www.cs.cmu.edu/~sleator/ + * + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * Log: ubi_SplayTree.c,v + * Revision 4.5 2000/01/08 23:26:49 crh + * Added ubi_trSplay() macro, which does a type cast for us. + * + * Revision 4.4 1998/06/04 21:29:27 crh + * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files. + * This is more "standard", and is what people expect. Weird, eh? + * + * Revision 4.3 1998/06/03 17:45:05 crh + * Further fiddling with sys_include.h. It's now in ubi_BinTree.h which is + * included by all of the binary tree files. + * + * Also fixed some warnings produced by lint on Irix 6.2, which doesn't seem + * to like syntax like this: + * + * if( (a = b) ) + * + * The fix was to change lines like the above to: + * + * if( 0 != (a=b) ) + * + * Which means the same thing. + * + * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in + * ubi_AVLtree.h and ubi_SplayTree.h. This allows easy swapping + * of tree types by simply changing a header. Unfortunately, the + * macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will + * conflict if used together. You must either choose a single tree + * type, or use the underlying function calls directly. Compare + * the two header files for more information. + * + * Revision 4.2 1998/06/02 01:29:14 crh + * Changed ubi_null.h to sys_include.h to make it more generic. + * + * Revision 4.1 1998/05/20 04:37:54 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * + * Revision 4.0 1998/03/10 03:41:33 crh + * Minor comment changes. The revision number is now 4.0 to match the + * BinTree and AVLtree modules. + * + * Revision 2.7 1998/01/24 06:37:08 crh + * Added a URL for more information. + * + * Revision 2.6 1997/12/23 04:01:12 crh + * In this version, all constants & macros defined in the header file have + * the ubi_tr prefix. Also cleaned up anything that gcc complained about + * when run with '-pedantic -fsyntax-only -Wall'. + * + * Revision 2.5 1997/07/26 04:15:42 crh + * + Cleaned up a few minor syntax annoyances that gcc discovered for me. + * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. + * + * Revision 2.4 1997/06/03 04:42:21 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing + * problems. + * + * Revision 2.3 1995/10/03 22:19:07 CRH + * Ubisized! + * Also, added the function ubi_sptSplay(). + * + * Revision 2.1 95/03/09 23:54:42 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:34:46 CRH + * This module was updated to match the interface changes made to the + * ubi_BinTree module. In particular, the interface to the Locate() function + * has changed. See ubi_BinTree for more information on changes and new + * functions. + * + * The revision number was also upped to match ubi_BinTree. + * + * Revision 1.1 93/10/18 20:35:16 CRH + * I removed the hard-coded logical device names from the include file + * specifications. CRH + * + * Revision 1.0 93/10/15 23:00:15 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_SplayTree, the locate function was + * called "ubi_sptLocate", but the next and previous functions remained + * "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * Revision 0.1 93/04/25 22:03:32 CRH + * Simply changed the <exec/types.h> #include reference the .c file to + * use <stdlib.h> instead. The latter is portable, the former is not. + * + * Revision 0.0 93/04/21 23:05:52 CRH + * Initial version, written by Christopher R. Hertel. + * This module implements Splay Trees using the ubi_BinTree module as a basis. + * + * ========================================================================== ** + */ + +#include "ubi_SplayTree.h" /* Header for THIS module. */ + +/* ========================================================================== ** + * Static data. + */ + +static char ModuleID[] = "ubi_SplayTree\n\ +\tRevision: 4.5 \n\ +\tDate: 2000/01/08 23:26:49 \n\ +\tAuthor: crh \n"; + + +/* ========================================================================== ** + * Private functions... + */ + +static void Rotate( ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * This function performs a single rotation, moving node *p up one level + * in the tree. + * + * Input: p - a pointer to an ubi_btNode in a tree. + * + * Output: None. + * + * Notes: This implements a single rotation in either direction (left + * or right). This is the basic building block of all splay + * tree rotations. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr parentp; + ubi_btNodePtr tmp; + char way; + char revway; + + parentp = p->Link[ubi_trPARENT]; /* Find parent. */ + + if( parentp ) /* If no parent, then we're already the root. */ + { + way = p->gender; + revway = ubi_trRevWay(way); + tmp = p->Link[(int)revway]; + + parentp->Link[(int)way] = tmp; + if( tmp ) + { + tmp->Link[ubi_trPARENT] = parentp; + tmp->gender = way; + } + + tmp = parentp->Link[ubi_trPARENT]; + p->Link[ubi_trPARENT] = tmp; + p->gender = parentp->gender; + if( tmp ) + tmp->Link[(int)(p->gender)] = p; + + parentp->Link[ubi_trPARENT] = p; + parentp->gender = revway; + p->Link[(int)revway] = parentp; + } + } /* Rotate */ + +static ubi_btNodePtr Splay( ubi_btNodePtr SplayWithMe ) + /* ------------------------------------------------------------------------ ** + * Move the node indicated by SplayWithMe to the root of the tree by + * splaying the tree. + * + * Input: SplayWithMe - A pointer to an ubi_btNode within a tree. + * + * Output: A pointer to the root of the splay tree (i.e., the same as + * SplayWithMe). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr parent; + + while( NULL != (parent = SplayWithMe->Link[ubi_trPARENT]) ) + { + if( parent->gender == SplayWithMe->gender ) /* Zig-Zig */ + Rotate( parent ); + else + { + if( ubi_trEQUAL != parent->gender ) /* Zig-Zag */ + Rotate( SplayWithMe ); + } + Rotate( SplayWithMe ); /* Zig */ + } /* while */ + return( SplayWithMe ); + } /* Splay */ + +/* ========================================================================== ** + * Exported utilities. + */ + +ubi_trBool ubi_sptInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ) + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * splay tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr OtherP; + + if( !(OldNode) ) + OldNode = &OtherP; + + if( ubi_btInsert( RootPtr, NewNode, ItemPtr, OldNode ) ) + { + RootPtr->root = Splay( NewNode ); + return( ubi_trTRUE ); + } + + /* Splay the unreplacable, duplicate keyed, unique, old node. */ + RootPtr->root = Splay( (*OldNode) ); + return( ubi_trFALSE ); + } /* ubi_sptInsert */ + +ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode ) + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p; + + (void)Splay( DeadNode ); /* Move dead node to root. */ + if( NULL != (p = DeadNode->Link[ubi_trLEFT]) ) + { /* If left subtree exists... */ + ubi_btNodePtr q = DeadNode->Link[ubi_trRIGHT]; + + p->Link[ubi_trPARENT] = NULL; /* Left subtree node becomes root.*/ + p->gender = ubi_trPARENT; + p = ubi_btLast( p ); /* Find rightmost left node... */ + p->Link[ubi_trRIGHT] = q; /* ...attach right tree. */ + if( q ) + q->Link[ubi_trPARENT] = p; + RootPtr->root = Splay( p ); /* Resplay at p. */ + } + else + { + if( NULL != (p = DeadNode->Link[ubi_trRIGHT]) ) + { /* No left, but right subtree exists... */ + p->Link[ubi_trPARENT] = NULL; /* Right subtree root becomes... */ + p->gender = ubi_trPARENT; /* ...overall tree root. */ + RootPtr->root = p; + } + else + RootPtr->root = NULL; /* No subtrees => empty tree. */ + } + + (RootPtr->count)--; /* Decrement node count. */ + return( DeadNode ); /* Return pointer to pruned node. */ + } /* ubi_sptRemove */ + +ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ) + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p; + + p = ubi_btLocate( RootPtr, FindMe, CompOp ); + if( p ) + RootPtr->root = Splay( p ); + return( p ); + } /* ubi_sptLocate */ + +ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ) + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_sptLocate(). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p; + + p = ubi_btFind( RootPtr, FindMe ); + if( p ) + RootPtr->root = Splay( p ); + return( p ); + } /* ubi_sptFind */ + +void ubi_sptSplay( ubi_btRootPtr RootPtr, + ubi_btNodePtr SplayMe ) + /* ------------------------------------------------------------------------ ** + * This function allows you to splay the tree at a given node, thus moving + * the node to the top of the tree. + * + * Input: + * RootPtr - a pointer to the header of the tree to be splayed. + * SplayMe - a pointer to a node within the tree. This will become + * the new root node. + * Output: None. + * + * Notes: This is an uncharacteristic function for this group of modules + * in that it provides access to the internal balancing routines, + * which would normally be hidden. + * Splaying the tree will not damage it (assuming that I've done + * *my* job), but there is overhead involved. I don't recommend + * that you use this function unless you understand the underlying + * Splay Tree principles involved. + * ------------------------------------------------------------------------ ** + */ + { + RootPtr->root = Splay( SplayMe ); + } /* ubi_sptSplay */ + +int ubi_sptModuleID( int size, char *list[] ) + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + { + if( size > 0 ) + { + list[0] = ModuleID; + if( size > 1 ) + return( 1 + ubi_btModuleID( --size, &(list[1]) ) ); + return( 1 ); + } + return( 0 ); + } /* ubi_sptModuleID */ + +/* ================================ The End ================================= */ + diff --git a/source/ubiqx/ubi_SplayTree.h b/source/ubiqx/ubi_SplayTree.h new file mode 100644 index 00000000000..e4fac796a91 --- /dev/null +++ b/source/ubiqx/ubi_SplayTree.h @@ -0,0 +1,377 @@ +#ifndef UBI_SPLAYTREE_H +#define UBI_SPLAYTREE_H +/* ========================================================================== ** + * ubi_SplayTree.h + * + * Copyright (C) 1993-1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module implements "splay" trees. Splay trees are binary trees + * that are rearranged (splayed) whenever a node is accessed. The + * splaying process *tends* to make the tree bushier (improves balance), + * and the nodes that are accessed most frequently *tend* to be closer to + * the top. + * + * References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and + * Robert Tarjan. Journal of the Association for Computing + * Machinery Vol 32, No. 3, July 1985 pp. 652-686 + * + * See also: http://www.cs.cmu.edu/~sleator/ + * + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * Log: ubi_SplayTree.h,v + * Revision 4.5 2000/01/08 23:26:49 crh + * Added ubi_trSplay() macro, which does a type cast for us. + * + * Revision 4.4 1998/06/04 21:29:27 crh + * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files. + * This is more "standard", and is what people expect. Weird, eh? + * + * Revision 4.3 1998/06/03 17:45:05 crh + * Further fiddling with sys_include.h. It's now in ubi_BinTree.h which is + * included by all of the binary tree files. + * + * Also fixed some warnings produced by lint on Irix 6.2, which doesn't seem + * to like syntax like this: + * + * if( (a = b) ) + * + * The fix was to change lines like the above to: + * + * if( 0 != (a=b) ) + * + * Which means the same thing. + * + * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in + * ubi_AVLtree.h and ubi_SplayTree.h. This allows easy swapping + * of tree types by simply changing a header. Unfortunately, the + * macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will + * conflict if used together. You must either choose a single tree + * type, or use the underlying function calls directly. Compare + * the two header files for more information. + * + * Revision 4.2 1998/06/02 01:29:14 crh + * Changed ubi_null.h to sys_include.h to make it more generic. + * + * Revision 4.1 1998/05/20 04:37:54 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * + * Revision 4.0 1998/03/10 03:40:57 crh + * Minor comment changes. The revision number is now 4.0 to match the + * BinTree and AVLtree modules. + * + * Revision 2.7 1998/01/24 06:37:57 crh + * Added a URL for more information. + * + * Revision 2.6 1997/12/23 04:02:20 crh + * In this version, all constants & macros defined in the header file have + * the ubi_tr prefix. Also cleaned up anything that gcc complained about + * when run with '-pedantic -fsyntax-only -Wall'. + * + * Revision 2.5 1997/07/26 04:15:46 crh + * + Cleaned up a few minor syntax annoyances that gcc discovered for me. + * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. + * + * Revision 2.4 1997/06/03 05:22:56 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing + * problems. + * + * Revision 2.3 1995/10/03 22:19:37 CRH + * Ubisized! + * Also, added the function ubi_sptSplay(). + * + * Revision 2.1 95/03/09 23:55:04 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:34:55 CRH + * This module was updated to match the interface changes made to the + * ubi_BinTree module. In particular, the interface to the Locate() function + * has changed. See ubi_BinTree for more information on changes and new + * functions. + * + * The revision number was also upped to match ubi_BinTree. + * + * + * Revision 1.0 93/10/15 22:59:36 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_SplayTree, the locate function was + * called "ubi_sptLocate", but the next and previous functions remained + * "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * Revision 0.0 93/04/21 23:07:13 CRH + * Initial version, written by Christopher R. Hertel. + * This module implements Splay Trees using the ubi_BinTree module as a basis. + * + * ========================================================================== ** + */ + +#include "ubi_BinTree.h" /* Base binary tree functions, types, etc. */ + +/* ========================================================================== ** + * Function prototypes... + */ + +ubi_trBool ubi_sptInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ); + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * splay tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode ); + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ); + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ); + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_sptLocate(). + * ------------------------------------------------------------------------ ** + */ + +void ubi_sptSplay( ubi_btRootPtr RootPtr, + ubi_btNodePtr SplayMe ); + /* ------------------------------------------------------------------------ ** + * This function allows you to splay the tree at a given node, thus moving + * the node to the top of the tree. + * + * Input: + * RootPtr - a pointer to the header of the tree to be splayed. + * SplayMe - a pointer to a node within the tree. This will become + * the new root node. + * Output: None. + * + * Notes: This is an uncharacteristic function for this group of modules + * in that it provides access to the internal balancing routines, + * which would normally be hidden. + * Splaying the tree will not damage it (assuming that I've done + * *my* job), but there is overhead involved. I don't recommend + * that you use this function unless you understand the underlying + * Splay Tree principles involved. + * ------------------------------------------------------------------------ ** + */ + +int ubi_sptModuleID( int size, char *list[] ); + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + +/* -------------------------------------------------------------------------- ** + * Masquarade... + * + * This set of defines allows you to write programs that will use any of the + * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). + * Instead of using ubi_bt..., use ubi_tr..., and select the tree type by + * including the appropriate module header. + */ + +#undef ubi_trInsert +#undef ubi_trRemove +#undef ubi_trLocate +#undef ubi_trFind +#undef ubi_trModuleID + +#define ubi_trInsert( Rp, Nn, Ip, On ) \ + ubi_sptInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \ + (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) ) + +#define ubi_trRemove( Rp, Dn ) \ + ubi_sptRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) ) + +#define ubi_trLocate( Rp, Ip, Op ) \ + ubi_sptLocate( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_trCompOps)(Op) ) + +#define ubi_trFind( Rp, Ip ) \ + ubi_sptFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) + +#define ubi_trSplay( Rp, Sm ) \ + ubi_sptSplay( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Sm) ) + +#define ubi_trModuleID( s, l ) ubi_sptModuleID( s, l ) + +/* ================================ The End ================================= */ +#endif /* UBI_SPLAYTREE_H */ diff --git a/source/ubiqx/ubi_dLinkList.c b/source/ubiqx/ubi_dLinkList.c new file mode 100644 index 00000000000..eb95033c695 --- /dev/null +++ b/source/ubiqx/ubi_dLinkList.c @@ -0,0 +1,171 @@ +/* ========================================================================== ** + * ubi_dLinkList.c + * + * Copyright (C) 1997, 1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * This module implements simple doubly-linked lists. + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * Log: ubi_dLinkList.c,v + * Revision 0.11 1999/06/19 16:58:06 crh + * Renamed the ubi_slRemove() function in ubi_sLinkList to + * ubi_slRemoveNext(). I was bothered by the fact that it didn't + * match the functionality of the ubi_dlRemove() function in + * ubi_dLinkList. The new name is more 'correct'. + * + * Revision 0.10 1998/07/24 07:30:20 crh + * Added the ubi_dlNewList() macro. + * + * Revision 0.9 1998/06/04 21:29:27 crh + * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files. + * This is more "standard", and is what people expect. Weird, eh? + * + * Revision 0.8 1998/06/03 18:06:03 crh + * Further fiddling with sys_include.h, which has been moved from the .c file + * to the .h file. + * + * Revision 0.7 1998/06/02 01:38:47 crh + * Changed include file name from ubi_null.h to sys_include.h to make it + * more generic. + * + * Revision 0.6 1998/05/20 04:38:05 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * + * Revision 0.5 1998/03/10 02:55:00 crh + * Simplified the code and added macros for stack & queue manipulations. + * + * Revision 0.4 1998/01/03 01:53:56 crh + * Added ubi_dlCount() macro. + * + * Revision 0.3 1997/10/15 03:05:39 crh + * Added some handy type casting to the macros. Added AddHere and RemThis + * macros. + * + * Revision 0.2 1997/10/08 03:07:21 crh + * Fixed a few forgotten link-ups in Insert(), and fixed the AddHead() + * macro, which was passing the wrong value for <After> to Insert(). + * + * Revision 0.1 1997/10/07 04:34:07 crh + * Initial Revision. + * + * -------------------------------------------------------------------------- ** + * This module is similar to the ubi_sLinkList module, but it is neither a + * descendant type nor an easy drop-in replacement for the latter. One key + * difference is that the ubi_dlRemove() function removes the indicated node, + * while the ubi_slRemoveNext() function (in ubi_sLinkList) removes the node + * *following* the indicated node. + * + * ========================================================================== ** + */ + +#include "ubi_dLinkList.h" /* Header for *this* module. */ + +/* ========================================================================== ** + * Functions... + */ + +ubi_dlListPtr ubi_dlInitList( ubi_dlListPtr ListPtr ) + /* ------------------------------------------------------------------------ ** + * Initialize a doubly-linked list header. + * + * Input: ListPtr - A pointer to the list structure that is to be + * initialized for use. + * + * Output: A pointer to the initialized list header (i.e., same as + * <ListPtr>). + * + * ------------------------------------------------------------------------ ** + */ + { + ListPtr->Head = NULL; + ListPtr->Tail = NULL; + ListPtr->count = 0; + return( ListPtr ); + } /* ubi_dlInitList */ + +ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr, + ubi_dlNodePtr New, + ubi_dlNodePtr After ) + /* ------------------------------------------------------------------------ ** + * Insert a new node into the list. + * + * Input: ListPtr - A pointer to the list into which the node is to + * be inserted. + * New - Pointer to the new node. + * After - NULL, or a pointer to a node that is already in the + * list. + * If NULL, then <New> will be added at the head of the + * list, else it will be added following <After>. + * + * Output: A pointer to the node that was inserted into the list (i.e., + * the same as <New>). + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_dlNodePtr PredNode = After ? After : (ubi_dlNodePtr)ListPtr; + + New->Next = PredNode->Next; + New->Prev = After; + PredNode->Next = New; + if( New->Next ) + New->Next->Prev = New; + else + ListPtr->Tail = New; + + (ListPtr->count)++; + + return( New ); + } /* ubi_dlInsert */ + +ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old ) + /* ------------------------------------------------------------------------ ** + * Remove a node from the list. + * + * Input: ListPtr - A pointer to the list from which <Old> is to be + * removed. + * Old - A pointer to the node that is to be removed from the + * list. + * + * Output: A pointer to the node that was removed (i.e., <Old>). + * + * ------------------------------------------------------------------------ ** + */ + { + if( Old ) + { + if( Old->Next ) + Old->Next->Prev = Old->Prev; + else + ListPtr->Tail = Old->Prev; + + if( Old->Prev ) + Old->Prev->Next = Old->Next; + else + ListPtr->Head = Old->Next; + + (ListPtr->count)--; + } + + return( Old ); + } /* ubi_dlRemove */ + +/* ================================ The End ================================= */ diff --git a/source/ubiqx/ubi_dLinkList.h b/source/ubiqx/ubi_dLinkList.h new file mode 100644 index 00000000000..682e566ee67 --- /dev/null +++ b/source/ubiqx/ubi_dLinkList.h @@ -0,0 +1,242 @@ +#ifndef UBI_DLINKLIST_H +#define UBI_DLINKLIST_H +/* ========================================================================== ** + * ubi_dLinkList.h + * + * Copyright (C) 1997, 1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * This module implements simple doubly-linked lists. + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * Log: ubi_dLinkList.h,v + * Revision 0.11 1999/06/19 16:58:06 crh + * Renamed the ubi_slRemove() function in ubi_sLinkList to + * ubi_slRemoveNext(). I was bothered by the fact that it didn't + * match the functionality of the ubi_dlRemove() function in + * ubi_dLinkList. The new name is more 'correct'. + * + * Revision 0.10 1998/07/24 07:30:20 crh + * Added the ubi_dlNewList() macro. + * + * Revision 0.9 1998/06/04 21:29:27 crh + * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files. + * This is more "standard", and is what people expect. Weird, eh? + * + * Revision 0.8 1998/06/03 18:06:03 crh + * Further fiddling with sys_include.h, which has been moved from the .c file + * to the .h file. + * + * Revision 0.7 1998/06/02 01:38:47 crh + * Changed include file name from ubi_null.h to sys_include.h to make it + * more generic. + * + * Revision 0.6 1998/05/20 04:38:05 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * + * Revision 0.5 1998/03/10 02:54:04 crh + * Simplified the code and added macros for stack & queue manipulations. + * + * Revision 0.4 1998/01/03 01:53:44 crh + * Added ubi_dlCount() macro. + * + * Revision 0.3 1997/10/15 03:04:31 crh + * Added some handy type casting to the macros. Added AddHere and RemThis + * macros. + * + * Revision 0.2 1997/10/08 03:08:16 crh + * Fixed a few forgotten link-ups in Insert(), and fixed the AddHead() + * macro, which was passing the wrong value for <After> to Insert(). + * + * Revision 0.1 1997/10/07 04:34:38 crh + * Initial Revision. + * + * -------------------------------------------------------------------------- ** + * This module is similar to the ubi_sLinkList module, but it is neither a + * descendant type nor an easy drop-in replacement for the latter. One key + * difference is that the ubi_dlRemove() function removes the indicated node, + * while the ubi_slRemoveNext() function (in ubi_sLinkList) removes the node + * *following* the indicated node. + * + * ========================================================================== ** + */ + +#include "sys_include.h" /* System-specific includes. */ + +/* ========================================================================== ** + * Typedefs... + * + * ubi_dlNode - This is the basic node structure. + * ubi_dlNodePtr - Pointer to a node. + * ubi_dlList - This is the list header structure. + * ubi_dlListPtr - Pointer to a List (i.e., a list header structure). + * + */ + +typedef struct ubi_dlListNode + { + struct ubi_dlListNode *Next; + struct ubi_dlListNode *Prev; + } ubi_dlNode; + +typedef ubi_dlNode *ubi_dlNodePtr; + +typedef struct + { + ubi_dlNodePtr Head; + ubi_dlNodePtr Tail; + unsigned long count; + } ubi_dlList; + +typedef ubi_dlList *ubi_dlListPtr; + +/* ========================================================================== ** + * Macros... + * + * ubi_dlNewList - Macro used to declare and initialize a new list in one + * swell foop. It is used when defining a variable of + * type ubi_dlList. The definition + * static ubi_dlNewList( gerbil ); + * is translated to + * static ubi_dlList gerbil[1] = {{ NULL, NULL, 0 }}; + * + * ubi_dlCount - Return the number of entries currently in the list. + * + * ubi_dlAddHead - Add a new node at the head of the list. + * ubi_dlAddNext - Add a node following the given node. + * ubi_dlAddTail - Add a new node at the tail of the list. + * Note: AddTail evaluates the L parameter twice. + * + * ubi_dlRemHead - Remove the node at the head of the list, if any. + * Note: RemHead evaluates the L parameter twice. + * ubi_dlRemThis - Remove the indicated node. + * ubi_dlRemTail - Remove the node at the tail of the list, if any. + * Note: RemTail evaluates the L parameter twice. + * + * ubi_dlFirst - Return a pointer to the first node in the list, if any. + * ubi_dlLast - Return a pointer to the last node in the list, if any. + * ubi_dlNext - Given a node, return a pointer to the next node. + * ubi_dlPrev - Given a node, return a pointer to the previous node. + * + * ubi_dlPush - Add a node at the head of the list (synonym of AddHead). + * ubi_dlPop - Remove a node at the head of the list (synonym of RemHead). + * ubi_dlEnqueue - Add a node at the tail of the list (sysnonym of AddTail). + * ubi_dlDequeue - Remove a node at the head of the list (synonym of RemHead). + * + * Note that all of these provide type casting of the parameters. The + * Add and Rem macros are nothing more than nice front-ends to the + * Insert and Remove operations. + * + * Also note that the First, Next and Last macros do no parameter checking! + * + */ + +#define ubi_dlNewList( L ) ubi_dlList (L)[1] = {{ NULL, NULL, 0 }} + +#define ubi_dlCount( L ) (((ubi_dlListPtr)(L))->count) + +#define ubi_dlAddHead( L, N ) \ + ubi_dlInsert( (ubi_dlListPtr)(L), (ubi_dlNodePtr)(N), NULL ) + +#define ubi_dlAddNext( L, N, A ) \ + ubi_dlInsert( (ubi_dlListPtr)(L), \ + (ubi_dlNodePtr)(N), \ + (ubi_dlNodePtr)(A) ) + +#define ubi_dlAddTail( L, N ) \ + ubi_dlInsert( (ubi_dlListPtr)(L), \ + (ubi_dlNodePtr)(N), \ + (((ubi_dlListPtr)(L))->Tail) ) + +#define ubi_dlRemHead( L ) ubi_dlRemove( (ubi_dlListPtr)(L), \ + (((ubi_dlListPtr)(L))->Head) ) + +#define ubi_dlRemThis( L, N ) ubi_dlRemove( (ubi_dlListPtr)(L), \ + (ubi_dlNodePtr)(N) ) + +#define ubi_dlRemTail( L ) ubi_dlRemove( (ubi_dlListPtr)(L), \ + (((ubi_dlListPtr)(L))->Tail) ) + +#define ubi_dlFirst( L ) (((ubi_dlListPtr)(L))->Head) + +#define ubi_dlLast( L ) (((ubi_dlListPtr)(L))->Tail) + +#define ubi_dlNext( N ) (((ubi_dlNodePtr)(N))->Next) + +#define ubi_dlPrev( N ) (((ubi_dlNodePtr)(N))->Prev) + +#define ubi_dlPush ubi_dlAddHead +#define ubi_dlPop ubi_dlRemHead +#define ubi_dlEnqueue ubi_dlAddTail +#define ubi_dlDequeue ubi_dlRemHead + +/* ========================================================================== ** + * Function prototypes... + */ + +ubi_dlListPtr ubi_dlInitList( ubi_dlListPtr ListPtr ); + /* ------------------------------------------------------------------------ ** + * Initialize a doubly-linked list header. + * + * Input: ListPtr - A pointer to the list structure that is to be + * initialized for use. + * + * Output: A pointer to the initialized list header (i.e., same as + * <ListPtr>). + * + * ------------------------------------------------------------------------ ** + */ + +ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr, + ubi_dlNodePtr New, + ubi_dlNodePtr After ); + /* ------------------------------------------------------------------------ ** + * Insert a new node into the list. + * + * Input: ListPtr - A pointer to the list into which the node is to + * be inserted. + * New - Pointer to the new node. + * After - NULL, or a pointer to a node that is already in the + * list. + * If NULL, then <New> will be added at the head of the + * list, else it will be added following <After>. + * + * Output: A pointer to the node that was inserted into the list (i.e., + * the same as <New>). + * + * ------------------------------------------------------------------------ ** + */ + +ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old ); + /* ------------------------------------------------------------------------ ** + * Remove a node from the list. + * + * Input: ListPtr - A pointer to the list from which <Old> is to be + * removed. + * Old - A pointer to the node that is to be removed from the + * list. + * + * Output: A pointer to the node that was removed (i.e., <Old>). + * + * ------------------------------------------------------------------------ ** + */ + +/* ================================ The End ================================= */ +#endif /* UBI_DLINKLIST_H */ diff --git a/source/ubiqx/ubi_sLinkList.c b/source/ubiqx/ubi_sLinkList.c new file mode 100644 index 00000000000..ff75931b470 --- /dev/null +++ b/source/ubiqx/ubi_sLinkList.c @@ -0,0 +1,187 @@ +/* ========================================================================== ** + * ubi_sLinkList.c + * + * Copyright (C) 1997, 1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * This module implements a simple singly-linked list. + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * Log: ubi_sLinkList.c,v + * Revision 0.10 1999/06/19 16:58:06 crh + * Renamed the ubi_slRemove() function in ubi_sLinkList to + * ubi_slRemoveNext(). I was bothered by the fact that it didn't + * match the functionality of the ubi_dlRemove() function in + * ubi_dLinkList. The new name is more 'correct'. + * + * Revision 0.9 1998/07/24 07:30:20 crh + * Added the ubi_slNewList() macro. + * + * Revision 0.8 1998/06/04 21:29:27 crh + * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files. + * This is more "standard", and is what people expect. Weird, eh? + * + * Revision 0.7 1998/06/03 18:06:03 crh + * Further fiddling with sys_include.h, which has been moved from the .c file + * to the .h file. + * + * Revision 0.6 1998/06/02 01:38:47 crh + * Changed include file name from ubi_null.h to sys_include.h to make it + * more generic. + * + * Revision 0.5 1998/05/20 04:38:05 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * + * Revision 0.4 1998/03/10 02:23:20 crh + * Combined ubi_StackQueue and ubi_sLinkList into one module. Redesigned + * the functions and macros. Not a complete rewrite but close to it. + * + * Revision 0.3 1998/01/03 01:59:52 crh + * Added ubi_slCount() macro. + * + * Revision 0.2 1997/10/21 03:35:18 crh + * Added parameter <After> in function Insert(). Made necessary changes + * to macro AddHead() and added macro AddHere(). + * + * Revision 0.1 1997/10/16 02:53:45 crh + * Initial Revision. + * + * -------------------------------------------------------------------------- ** + * This module implements a singly-linked list which may also be used as a + * queue or a stack. For a queue, entries are added at the tail and removed + * from the head of the list. For a stack, the entries are entered and + * removed from the head of the list. A traversal of the list will always + * start at the head of the list and proceed toward the tail. This is all + * mind-numbingly simple, but I'm surprised by the number of programs out + * there which re-implement this a dozen or so times. + * + * Note: When the list header is initialized, the Tail pointer is set to + * point to the Head pointer. This simplifies things a great deal, + * except that you can't initialize a stack or queue by simply + * zeroing it out. One sure way to initialize the header is to call + * ubi_slInit(). Another option would be something like this: + * + * ubi_slNewList( MyList ); + * + * Which translates to: + * + * ubi_slList MyList[1] = { NULL, (ubi_slNodePtr)MyList, 0 }; + * + * See ubi_slInit(), ubi_slNewList(), and the ubi_slList structure + * for more info. + * + * + Also, note that this module is similar to the ubi_dLinkList + * module. There are three key differences: + * - This is a singly-linked list, the other is a doubly-linked + * list. + * - In this module, if the list is empty, the tail pointer will + * point back to the head of the list as described above. This + * is not done in ubi_dLinkList. + * - The ubi_slRemoveNext() function, by necessity, removes the + * 'next' node. In ubi_dLinkList, the ubi_dlRemove() function + * removes the 'current' node. + * + * ========================================================================== ** + */ + +#include "ubi_sLinkList.h" /* Header for *this* module. */ + +/* ========================================================================== ** + * Functions... + */ + +ubi_slListPtr ubi_slInitList( ubi_slListPtr ListPtr ) + /* ------------------------------------------------------------------------ ** + * Initialize a singly-linked list header. + * + * Input: ListPtr - A pointer to the list structure that is to be + * initialized for use. + * + * Output: A pointer to the initialized list header (i.e., same as + * <ListPtr>). + * + * ------------------------------------------------------------------------ ** + */ + { + ListPtr->Head = NULL; + ListPtr->Tail = (ubi_slNodePtr)ListPtr; + ListPtr->count = 0; + return( ListPtr ); + } /* ubi_slInitList */ + +ubi_slNodePtr ubi_slInsert( ubi_slListPtr ListPtr, + ubi_slNodePtr New, + ubi_slNodePtr After ) + /* ------------------------------------------------------------------------ ** + * Add a node to the list. + * + * Input: ListPtr - A pointer to the list into which the node is to + * be inserted. + * New - Pointer to the node that is to be added to the list. + * After - Pointer to a list in a node after which the new node + * will be inserted. If NULL, then the new node will + * be added at the head of the list. + * + * Output: A pointer to the node that was inserted into the list (i.e., + * the same as <New>). + * + * ------------------------------------------------------------------------ ** + */ + { + After = After ? After : (ubi_slNodePtr)ListPtr; + New->Next = After->Next; + After->Next = New; + if( !(New->Next) ) + ListPtr->Tail = New; + (ListPtr->count)++; + return( New ); + } /* ubi_slInsert */ + +ubi_slNodePtr ubi_slRemoveNext( ubi_slListPtr ListPtr, ubi_slNodePtr AfterMe ) + /* ------------------------------------------------------------------------ ** + * Remove the node followng <AfterMe>. If <AfterMe> is NULL, remove from + * the head of the list. + * + * Input: ListPtr - A pointer to the list from which the node is to be + * removed. + * AfterMe - Pointer to the node preceeding the node to be + * removed. + * + * Output: A pointer to the node that was removed, or NULL if the list is + * empty. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_slNodePtr DelNode; + + AfterMe = AfterMe ? AfterMe : (ubi_slNodePtr)ListPtr; + DelNode = AfterMe->Next; + if( DelNode ) + { + if( !(DelNode->Next) ) + ListPtr->Tail = AfterMe; + AfterMe->Next = DelNode->Next; + (ListPtr->count)--; + } + return( DelNode ); + } /* ubi_slRemoveNext */ + +/* ================================ The End ================================= */ diff --git a/source/ubiqx/ubi_sLinkList.h b/source/ubiqx/ubi_sLinkList.h new file mode 100644 index 00000000000..53bfa400671 --- /dev/null +++ b/source/ubiqx/ubi_sLinkList.h @@ -0,0 +1,254 @@ +#ifndef UBI_SLINKLIST_H +#define UBI_SLINKLIST_H +/* ========================================================================== ** + * ubi_sLinkList.h + * + * Copyright (C) 1997, 1998 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * This module implements a simple singly-linked list. + * -------------------------------------------------------------------------- ** + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * Log: ubi_sLinkList.h,v + * Revision 0.10 1999/06/19 16:58:06 crh + * Renamed the ubi_slRemove() function in ubi_sLinkList to + * ubi_slRemoveNext(). I was bothered by the fact that it didn't + * match the functionality of the ubi_dlRemove() function in + * ubi_dLinkList. The new name is more 'correct'. + * + * Revision 0.9 1998/07/24 07:30:20 crh + * Added the ubi_slNewList() macro. + * + * Revision 0.8 1998/06/04 21:29:27 crh + * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files. + * This is more "standard", and is what people expect. Weird, eh? + * + * Revision 0.7 1998/06/03 18:06:03 crh + * Further fiddling with sys_include.h, which has been moved from the .c file + * to the .h file. + * + * Revision 0.6 1998/06/02 01:38:47 crh + * Changed include file name from ubi_null.h to sys_include.h to make it + * more generic. + * + * Revision 0.5 1998/05/20 04:38:05 crh + * The C file now includes ubi_null.h. See ubi_null.h for more info. + * + * Revision 0.4 1998/03/10 02:22:39 crh + * Combined ubi_StackQueue and ubi_sLinkList into one module. Redesigned + * the functions and macros. Not a complete rewrite but close to it. + * + * Revision 0.3 1998/01/03 02:00:02 crh + * Added ubi_slCount() macro. + * + * Revision 0.2 1997/10/21 03:36:14 crh + * Added parameter <After> in function Insert(). Made necessary changes + * to macro AddHead() and added macro AddHere(). + * + * Revision 0.1 1997/10/16 02:54:08 crh + * Initial Revision. + * + * -------------------------------------------------------------------------- ** + * This module implements a singly-linked list which may also be used as a + * queue or a stack. For a queue, entries are added at the tail and removed + * from the head of the list. For a stack, the entries are entered and + * removed from the head of the list. A traversal of the list will always + * start at the head of the list and proceed toward the tail. This is all + * mind-numbingly simple, but I'm surprised by the number of programs out + * there which re-implement this a dozen or so times. + * + * Note: When the list header is initialized, the Tail pointer is set to + * point to the Head pointer. This simplifies things a great deal, + * except that you can't initialize a stack or queue by simply + * zeroing it out. One sure way to initialize the header is to call + * ubi_slInit(). Another option would be something like this: + * + * ubi_slNewList( MyList ); + * + * Which translates to: + * + * ubi_slList MyList[1] = { NULL, (ubi_slNodePtr)MyList, 0 }; + * + * See ubi_slInit(), ubi_slNewList(), and the ubi_slList structure + * for more info. + * + * + Also, note that this module is similar to the ubi_dLinkList + * module. There are three key differences: + * - This is a singly-linked list, the other is a doubly-linked + * list. + * - In this module, if the list is empty, the tail pointer will + * point back to the head of the list as described above. This + * is not done in ubi_dLinkList. + * - The ubi_slRemoveNext() function, by necessity, removes the + * 'next' node. In ubi_dLinkList, the ubi_dlRemove() function + * removes the 'current' node. + * + * ========================================================================== ** + */ + +#include "sys_include.h" /* System-specific includes. */ + +/* ========================================================================== ** + * Typedefs... + * + * ubi_slNode - This is the basic node structure. + * ubi_slNodePtr - Pointer to a node. + * ubi_slList - This is the list header structure. + * ubi_slListPtr - Pointer to a List (i.e., a list header structure). + * + */ + +typedef struct ubi_slListNode + { + struct ubi_slListNode *Next; + } ubi_slNode; + +typedef ubi_slNode *ubi_slNodePtr; + +typedef struct + { + ubi_slNodePtr Head; + ubi_slNodePtr Tail; + unsigned long count; + } ubi_slList; + +typedef ubi_slList *ubi_slListPtr; + + +/* ========================================================================== ** + * Macros... + * + * ubi_slNewList - Macro used to declare and initialize a list header in + * one step. + * + * ubi_slCount - Returns the current number of entries in the list. + * + * ubi_slAddHead - Add a new node at the head of the list. + * ubi_slAddNext - Add a new node following the indicated node. + * ubi_slAddTail - Add a new node to the tail of the list. + * Note: AddTail evaluates the L parameter twice. + * + * ubi_slRemHead - Remove the node at the head of the list, if any. + * ubi_slRemNext - Remove the node following the given node. + * + * ubi_slFirst - Return a pointer to the first node in the list, if any. + * ubi_slNext - Given a node, return a pointer to the next node. + * ubi_slLast - Return a pointer to the last node in the list, if any. + * + * ubi_slPush - Add a node at the head of the list (synonym of AddHead). + * ubi_slPop - Remove a node at the head of the list (synonym of RemHead). + * ubi_slEnqueue - Add a node at the tail of the list (sysnonym of AddTail). + * ubi_slDequeue - Remove a node at the head of the list (synonym of RemHead). + * + * Note that all of these provide type casting of the parameters. The + * Add and Rem macros are nothing more than nice front-ends to the + * Insert and Remove functions. + * + * Also note that the First, Next and Last macros do no parameter checking! + * + */ + +#define ubi_slNewList( L ) ubi_slList (L)[1] = {{ NULL, (ubi_slNodePtr)(L), 0 }} + +#define ubi_slCount( L ) (((ubi_slListPtr)(L))->count) + +#define ubi_slAddHead( L, N ) \ + ubi_slInsert( (ubi_slListPtr)(L), (ubi_slNodePtr)(N), NULL ) + +#define ubi_slAddNext( L, N, A ) \ + ubi_slInsert( (ubi_slListPtr)(L), \ + (ubi_slNodePtr)(N), \ + (ubi_slNodePtr)(A) ) + +#define ubi_slAddTail( L, N ) \ + ubi_slInsert( (ubi_slListPtr)(L), \ + (ubi_slNodePtr)(N), \ + ((ubi_slListPtr)(L))->Tail ) + +#define ubi_slRemHead( L ) ubi_slRemoveNext( (ubi_slListPtr)(L), NULL ) + +#define ubi_slRemNext( L, N ) \ + ubi_slRemoveNext( (ubi_slListPtr)(L), (ubi_slNodePtr)(N) ) + +#define ubi_slFirst( L ) (((ubi_slListPtr)(L))->Head) + +#define ubi_slNext( N ) (((ubi_slNodePtr)(N))->Next) + +#define ubi_slLast( L ) (((ubi_slListPtr)(L))->Tail) + +#define ubi_slPush ubi_slAddHead +#define ubi_slPop ubi_slRemHead +#define ubi_slEnqueue ubi_slAddTail +#define ubi_slDequeue ubi_slRemHead + +/* ========================================================================== ** + * Function prototypes... + */ + +ubi_slListPtr ubi_slInitList( ubi_slListPtr ListPtr ); + /* ------------------------------------------------------------------------ ** + * Initialize a singly-linked list header. + * + * Input: ListPtr - A pointer to the list structure that is to be + * initialized for use. + * + * Output: A pointer to the initialized list header (i.e., same as + * <ListPtr>). + * + * ------------------------------------------------------------------------ ** + */ + +ubi_slNodePtr ubi_slInsert( ubi_slListPtr ListPtr, + ubi_slNodePtr New, + ubi_slNodePtr After ); + /* ------------------------------------------------------------------------ ** + * Add a node to the list. + * + * Input: ListPtr - A pointer to the list into which the node is to + * be inserted. + * New - Pointer to the node that is to be added to the list. + * After - Pointer to a list in a node after which the new node + * will be inserted. If NULL, then the new node will + * be added at the head of the list. + * + * Output: A pointer to the node that was inserted into the list (i.e., + * the same as <New>). + * + * ------------------------------------------------------------------------ ** + */ + +ubi_slNodePtr ubi_slRemoveNext( ubi_slListPtr ListPtr, ubi_slNodePtr AfterMe ); + /* ------------------------------------------------------------------------ ** + * Remove the node followng <AfterMe>. If <AfterMe> is NULL, remove from + * the head of the list. + * + * Input: ListPtr - A pointer to the list from which the node is to be + * removed. + * AfterMe - Pointer to the node preceeding the node to be + * removed. + * + * Output: A pointer to the node that was removed, or NULL if the list is + * empty. + * + * ------------------------------------------------------------------------ ** + */ + +/* ================================ The End ================================= */ +#endif /* UBI_SLINKLIST_H */ diff --git a/source/utils/net_groupmap.c b/source/utils/net_groupmap.c index 1cff120c393..9e897d8efc7 100644 --- a/source/utils/net_groupmap.c +++ b/source/utils/net_groupmap.c @@ -87,15 +87,19 @@ static BOOL get_sid_from_input(DOM_SID *sid, char *input) static void print_map_entry ( GROUP_MAP map, BOOL long_list ) { + fstring string_sid; + fstring group_type; + + decode_sid_name_use(group_type, map.sid_name_use); + sid_to_string(string_sid, &map.sid); + if (!long_list) - d_printf("%s (%s) -> %s\n", map.nt_name, - sid_string_static(&map.sid), gidtoname(map.gid)); + d_printf("%s (%s) -> %s\n", map.nt_name, string_sid, gidtoname(map.gid)); else { d_printf("%s\n", map.nt_name); - d_printf("\tSID : %s\n", sid_string_static(&map.sid)); + d_printf("\tSID : %s\n", string_sid); d_printf("\tUnix group: %s\n", gidtoname(map.gid)); - d_printf("\tGroup type: %s\n", - sid_type_lookup(map.sid_name_use)); + d_printf("\tGroup type: %s\n", group_type); d_printf("\tComment : %s\n", map.comment); } @@ -122,19 +126,19 @@ static int net_groupmap_list(int argc, const char **argv) else if ( !StrnCaseCmp(argv[i], "ntgroup", strlen("ntgroup")) ) { fstrcpy( ntgroup, get_string_param( argv[i] ) ); if ( !ntgroup[0] ) { - d_fprintf(stderr, "must supply a name\n"); + d_printf("must supply a name\n"); return -1; } } else if ( !StrnCaseCmp(argv[i], "sid", strlen("sid")) ) { fstrcpy( sid_string, get_string_param( argv[i] ) ); if ( !sid_string[0] ) { - d_fprintf(stderr, "must supply a SID\n"); + d_printf("must supply a SID\n"); return -1; } } else { - d_fprintf(stderr, "Bad option: %s\n", argv[i]); + d_printf("Bad option: %s\n", argv[i]); return -1; } } @@ -153,7 +157,7 @@ static int net_groupmap_list(int argc, const char **argv) /* Get the current mapping from the database */ if(!pdb_getgrsid(&map, sid)) { - d_fprintf(stderr, "Failure to local group SID in the database\n"); + d_printf("Failure to local group SID in the database\n"); return -1; } @@ -197,35 +201,35 @@ static int net_groupmap_add(int argc, const char **argv) if ( !StrnCaseCmp(argv[i], "rid", strlen("rid")) ) { rid = get_int_param(argv[i]); if ( rid < DOMAIN_GROUP_RID_ADMINS ) { - d_fprintf(stderr, "RID must be greater than %d\n", (uint32)DOMAIN_GROUP_RID_ADMINS-1); + d_printf("RID must be greater than %d\n", (uint32)DOMAIN_GROUP_RID_ADMINS-1); return -1; } } else if ( !StrnCaseCmp(argv[i], "unixgroup", strlen("unixgroup")) ) { fstrcpy( unixgrp, get_string_param( argv[i] ) ); if ( !unixgrp[0] ) { - d_fprintf(stderr, "must supply a name\n"); + d_printf("must supply a name\n"); return -1; } } else if ( !StrnCaseCmp(argv[i], "ntgroup", strlen("ntgroup")) ) { fstrcpy( ntgroup, get_string_param( argv[i] ) ); if ( !ntgroup[0] ) { - d_fprintf(stderr, "must supply a name\n"); + d_printf("must supply a name\n"); return -1; } } else if ( !StrnCaseCmp(argv[i], "sid", strlen("sid")) ) { fstrcpy( string_sid, get_string_param( argv[i] ) ); if ( !string_sid[0] ) { - d_fprintf(stderr, "must supply a SID\n"); + d_printf("must supply a SID\n"); return -1; } } else if ( !StrnCaseCmp(argv[i], "comment", strlen("comment")) ) { fstrcpy( ntcomment, get_string_param( argv[i] ) ); if ( !ntcomment[0] ) { - d_fprintf(stderr, "must supply a comment string\n"); + d_printf("must supply a comment string\n"); return -1; } } @@ -247,7 +251,7 @@ static int net_groupmap_add(int argc, const char **argv) } } else { - d_fprintf(stderr, "Bad option: %s\n", argv[i]); + d_printf("Bad option: %s\n", argv[i]); return -1; } } @@ -258,7 +262,7 @@ static int net_groupmap_add(int argc, const char **argv) } if ( (gid = nametogid(unixgrp)) == (gid_t)-1 ) { - d_fprintf(stderr, "Can't lookup UNIX group %s\n", unixgrp); + d_printf("Can't lookup UNIX group %s\n", unixgrp); return -1; } @@ -296,7 +300,7 @@ static int net_groupmap_add(int argc, const char **argv) if (!add_initial_entry(gid, string_sid, sid_type, ntgroup, ntcomment)) { - d_fprintf(stderr, "adding entry for group %s failed!\n", ntgroup); + d_printf("adding entry for group %s failed!\n", ntgroup); return -1; } @@ -322,28 +326,28 @@ static int net_groupmap_modify(int argc, const char **argv) if ( !StrnCaseCmp(argv[i], "ntgroup", strlen("ntgroup")) ) { fstrcpy( ntgroup, get_string_param( argv[i] ) ); if ( !ntgroup[0] ) { - d_fprintf(stderr, "must supply a name\n"); + d_printf("must supply a name\n"); return -1; } } else if ( !StrnCaseCmp(argv[i], "sid", strlen("sid")) ) { fstrcpy( sid_string, get_string_param( argv[i] ) ); if ( !sid_string[0] ) { - d_fprintf(stderr, "must supply a name\n"); + d_printf("must supply a name\n"); return -1; } } else if ( !StrnCaseCmp(argv[i], "comment", strlen("comment")) ) { fstrcpy( ntcomment, get_string_param( argv[i] ) ); if ( !ntcomment[0] ) { - d_fprintf(stderr, "must supply a comment string\n"); + d_printf("must supply a comment string\n"); return -1; } } else if ( !StrnCaseCmp(argv[i], "unixgroup", strlen("unixgroup")) ) { fstrcpy( unixgrp, get_string_param( argv[i] ) ); if ( !unixgrp[0] ) { - d_fprintf(stderr, "must supply a group name\n"); + d_printf("must supply a group name\n"); return -1; } } @@ -361,7 +365,7 @@ static int net_groupmap_modify(int argc, const char **argv) } } else { - d_fprintf(stderr, "Bad option: %s\n", argv[i]); + d_printf("Bad option: %s\n", argv[i]); return -1; } } @@ -388,7 +392,7 @@ static int net_groupmap_modify(int argc, const char **argv) /* Get the current mapping from the database */ if(!pdb_getgrsid(&map, sid)) { - d_fprintf(stderr, "Failure to local group SID in the database\n"); + d_printf("Failure to local group SID in the database\n"); return -1; } @@ -398,7 +402,7 @@ static int net_groupmap_modify(int argc, const char **argv) */ if (sid_type != SID_NAME_UNKNOWN) { if (map.sid_name_use == SID_NAME_WKN_GRP) { - d_fprintf(stderr, "You can only change between domain and local groups.\n"); + d_printf("You can only change between domain and local groups.\n"); return -1; } @@ -415,7 +419,7 @@ static int net_groupmap_modify(int argc, const char **argv) if ( unixgrp[0] ) { gid = nametogid( unixgrp ); if ( gid == -1 ) { - d_fprintf(stderr, "Unable to lookup UNIX group %s. Make sure the group exists.\n", + d_printf("Unable to lookup UNIX group %s. Make sure the group exists.\n", unixgrp); return -1; } @@ -424,7 +428,7 @@ static int net_groupmap_modify(int argc, const char **argv) } if ( !pdb_update_group_mapping_entry(&map) ) { - d_fprintf(stderr, "Could not update group database\n"); + d_printf("Could not update group database\n"); return -1; } @@ -445,19 +449,19 @@ static int net_groupmap_delete(int argc, const char **argv) if ( !StrnCaseCmp(argv[i], "ntgroup", strlen("ntgroup")) ) { fstrcpy( ntgroup, get_string_param( argv[i] ) ); if ( !ntgroup[0] ) { - d_fprintf(stderr, "must supply a name\n"); + d_printf("must supply a name\n"); return -1; } } else if ( !StrnCaseCmp(argv[i], "sid", strlen("sid")) ) { fstrcpy( sid_string, get_string_param( argv[i] ) ); if ( !sid_string[0] ) { - d_fprintf(stderr, "must supply a SID\n"); + d_printf("must supply a SID\n"); return -1; } } else { - d_fprintf(stderr, "Bad option: %s\n", argv[i]); + d_printf("Bad option: %s\n", argv[i]); return -1; } } @@ -473,12 +477,12 @@ static int net_groupmap_delete(int argc, const char **argv) fstrcpy( ntgroup, sid_string ); if ( !get_sid_from_input(&sid, ntgroup) ) { - d_fprintf(stderr, "Unable to resolve group %s to a SID\n", ntgroup); + d_printf("Unable to resolve group %s to a SID\n", ntgroup); return -1; } if ( !pdb_delete_group_mapping_entry(sid) ) { - d_fprintf(stderr, "Failed to removing group %s from the mapping db!\n", ntgroup); + printf("Failed to removing group %s from the mapping db!\n", ntgroup); return -1; } @@ -511,7 +515,7 @@ static int net_groupmap_set(int argc, const char **argv) grp = getgrnam(argv[1]); if (grp == NULL) { - d_fprintf(stderr, "Could not find unix group %s\n", argv[1]); + d_printf("Could not find unix group %s\n", argv[1]); return -1; } } @@ -530,7 +534,7 @@ static int net_groupmap_set(int argc, const char **argv) /* Ok, add it */ if (grp == NULL) { - d_fprintf(stderr, "Could not find group mapping for %s\n", + d_printf("Could not find group mapping for %s\n", ntgroup); return -1; } @@ -549,7 +553,7 @@ static int net_groupmap_set(int argc, const char **argv) fstrcpy(map.comment, ""); if (!pdb_add_group_mapping_entry(&map)) { - d_fprintf(stderr, "Could not add mapping entry for %s\n", + d_printf("Could not add mapping entry for %s\n", ntgroup); return -1; } @@ -559,7 +563,7 @@ static int net_groupmap_set(int argc, const char **argv) if ( opt_localgroup || opt_domaingroup ) { if (map.sid_name_use == SID_NAME_WKN_GRP) { - d_fprintf(stderr, "Can't change type of the BUILTIN group %s\n", + d_printf("Can't change type of the BUILTIN group %s\n", map.nt_name); return -1; } @@ -583,7 +587,7 @@ static int net_groupmap_set(int argc, const char **argv) map.gid = grp->gr_gid; if (!pdb_update_group_mapping_entry(&map)) { - d_fprintf(stderr, "Could not update group mapping for %s\n", ntgroup); + d_printf("Could not update group mapping for %s\n", ntgroup); return -1; } @@ -597,7 +601,7 @@ static int net_groupmap_cleanup(int argc, const char **argv) if (!pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &entries, ENUM_ALL_MAPPED)) { - d_fprintf(stderr, "Could not list group mappings\n"); + d_printf("Could not list group mappings\n"); return -1; } @@ -634,7 +638,7 @@ static int net_groupmap_addmem(int argc, const char **argv) } if (!pdb_add_aliasmem(&alias, &member)) { - d_fprintf(stderr, "Could not add sid %s to alias %s\n", + d_printf("Could not add sid %s to alias %s\n", argv[1], argv[0]); return -1; } @@ -654,7 +658,7 @@ static int net_groupmap_delmem(int argc, const char **argv) } if (!pdb_del_aliasmem(&alias, &member)) { - d_fprintf(stderr, "Could not delete sid %s from alias %s\n", + d_printf("Could not delete sid %s from alias %s\n", argv[1], argv[0]); return -1; } @@ -678,7 +682,7 @@ static int net_groupmap_listmem(int argc, const char **argv) num = 0; if (!pdb_enum_aliasmem(&alias, &members, &num)) { - d_fprintf(stderr, "Could not list members for sid %s\n", argv[0]); + d_printf("Could not list members for sid %s\n", argv[0]); return -1; } @@ -703,7 +707,7 @@ static BOOL print_alias_memberships(TALLOC_CTX *mem_ctx, if (!pdb_enum_alias_memberships(mem_ctx, domain_sid, member, 1, &alias_rids, &num_alias_rids)) { - d_fprintf(stderr, "Could not list memberships for sid %s\n", + d_printf("Could not list memberships for sid %s\n", sid_string_static(member)); return False; } @@ -731,14 +735,14 @@ static int net_groupmap_memberships(int argc, const char **argv) mem_ctx = talloc_init("net_groupmap_memberships"); if (mem_ctx == NULL) { - d_fprintf(stderr, "talloc_init failed\n"); + d_printf("talloc_init failed\n"); return -1; } domain_sid = get_global_sam_sid(); builtin_sid = string_sid_talloc(mem_ctx, "S-1-5-32"); if ((domain_sid == NULL) || (builtin_sid == NULL)) { - d_fprintf(stderr, "Could not get domain sid\n"); + d_printf("Could not get domain sid\n"); return -1; } @@ -800,7 +804,7 @@ int net_groupmap(int argc, const char **argv) /* we shouldn't have silly checks like this */ if (getuid() != 0) { - d_fprintf(stderr, "You must be root to edit group mappings.\nExiting...\n"); + d_printf("You must be root to edit group mappings.\nExiting...\n"); return -1; } diff --git a/source/utils/net_idmap.c b/source/utils/net_idmap.c index 0b5f68101ed..8109bef5225 100644 --- a/source/utils/net_idmap.c +++ b/source/utils/net_idmap.c @@ -59,7 +59,7 @@ static int net_idmap_dump(int argc, const char **argv) idmap_tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDONLY, 0); if (idmap_tdb == NULL) { - d_fprintf(stderr, "Could not open idmap: %s\n", argv[0]); + d_printf("Could not open idmap: %s\n", argv[0]); return -1; } @@ -102,7 +102,7 @@ static int net_idmap_find_max_id(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, } if (idptr == NULL) { - d_fprintf(stderr, "Illegal idmap entry: [%s]->[%s]\n", + d_printf("Illegal idmap entry: [%s]->[%s]\n", key.dptr, data.dptr); hwms->ok = False; return -1; @@ -132,7 +132,7 @@ static NTSTATUS net_idmap_fixup_hwm(void) if (!lp_idmap_uid(&hwms.user_hwm, &highest.user_hwm) || !lp_idmap_gid(&hwms.group_hwm, &highest.group_hwm)) { - d_fprintf(stderr, "idmap range missing\n"); + d_printf("idmap range missing\n"); return NT_STATUS_UNSUCCESSFUL; } @@ -145,7 +145,7 @@ static NTSTATUS net_idmap_fixup_hwm(void) idmap_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR, 0); if (idmap_tdb == NULL) { - d_fprintf(stderr, "Could not open idmap: %s\n", tdbfile); + d_printf("Could not open idmap: %s\n", tdbfile); return NT_STATUS_NO_SUCH_FILE; } @@ -161,18 +161,18 @@ static NTSTATUS net_idmap_fixup_hwm(void) hwms.user_hwm, hwms.group_hwm); if (hwms.user_hwm >= highest.user_hwm) { - d_fprintf(stderr, "Highest UID out of uid range\n"); + d_printf("Highest UID out of uid range\n"); goto done; } if (hwms.group_hwm >= highest.group_hwm) { - d_fprintf(stderr, "Highest GID out of gid range\n"); + d_printf("Highest GID out of gid range\n"); goto done; } if ((tdb_store_int32(idmap_tdb, "USER HWM", (int32)hwms.user_hwm) != 0) || (tdb_store_int32(idmap_tdb, "GROUP HWM", (int32)hwms.group_hwm) != 0)) { - d_fprintf(stderr, "Could not store HWMs\n"); + d_printf("Could not store HWMs\n"); goto done; } @@ -188,7 +188,7 @@ static NTSTATUS net_idmap_fixup_hwm(void) static int net_idmap_restore(int argc, const char **argv) { if (!idmap_init(lp_idmap_backend())) { - d_fprintf(stderr, "Could not init idmap\n"); + d_printf("Could not init idmap\n"); return -1; } @@ -230,7 +230,7 @@ static int net_idmap_restore(int argc, const char **argv) } if (!NT_STATUS_IS_OK(idmap_set_mapping(&sid, id, type))) { - d_fprintf(stderr, "Could not set mapping of %s %lu to sid %s\n", + d_printf("Could not set mapping of %s %lu to sid %s\n", (type == ID_GROUPID) ? "GID" : "UID", (type == ID_GROUPID) ? (unsigned long)id.gid: (unsigned long)id.uid, @@ -260,14 +260,14 @@ static int net_idmap_delete(int argc, const char **argv) idmap_tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDWR, 0); if (idmap_tdb == NULL) { - d_fprintf(stderr, "Could not open idmap: %s\n", argv[0]); + d_printf("Could not open idmap: %s\n", argv[0]); return -1; } fstrcpy(sid, argv[1]); if (strncmp(sid, "S-1-5-", strlen("S-1-5-")) != 0) { - d_fprintf(stderr, "Can only delete SIDs, %s is does not start with " + d_printf("Can only delete SIDs, %s is does not start with " "S-1-5-\n", sid); return -1; } @@ -278,17 +278,17 @@ static int net_idmap_delete(int argc, const char **argv) data = tdb_fetch(idmap_tdb, key); if (data.dptr == NULL) { - d_fprintf(stderr, "Could not find sid %s\n", argv[1]); + d_printf("Could not find sid %s\n", argv[1]); return -1; } if (tdb_delete(idmap_tdb, key) != 0) { - d_fprintf(stderr, "Could not delete key %s\n", argv[1]); + d_printf("Could not delete key %s\n", argv[1]); return -1; } if (tdb_delete(idmap_tdb, data) != 0) { - d_fprintf(stderr, "Could not delete key %s\n", data.dptr); + d_printf("Could not delete key %s\n", data.dptr); return -1; } diff --git a/source/utils/net_lookup.c b/source/utils/net_lookup.c index 8ee63515d45..cd62245600d 100644 --- a/source/utils/net_lookup.c +++ b/source/utils/net_lookup.c @@ -211,7 +211,7 @@ static int net_lookup_kdc(int argc, const char **argv) realm.length = strlen(realm.data); } - rc = krb5_locate_kdc(ctx, &realm, (struct sockaddr **)(void *)&addrs, &num_kdcs, 0); + rc = krb5_locate_kdc(ctx, &realm, (struct sockaddr **) &addrs, &num_kdcs, 0); if (rc) { DEBUG(1, ("krb5_locate_kdc failed (%s)\n", error_message(rc))); return -1; diff --git a/source/utils/smbget.c b/source/utils/smbget.c index 4a2670e0c16..eab5e5ac02f 100644 --- a/source/utils/smbget.c +++ b/source/utils/smbget.c @@ -22,10 +22,8 @@ #if _FILE_OFFSET_BITS==64 #define OFF_T_FORMAT "%lld" -#define OFF_T_FORMAT_CAST long long #else #define OFF_T_FORMAT "%ld" -#define OFF_T_FORMAT_CAST long #endif int columns = 0; @@ -78,7 +76,7 @@ void human_readable(off_t s, char *buffer, int l) if(s > 1024 * 1024 * 1024) snprintf(buffer, l, "%.2fGb", 1.0 * s / (1024 * 1024 * 1024)); else if(s > 1024 * 1024) snprintf(buffer, l, "%.2fMb", 1.0 * s / (1024 * 1024)); else if(s > 1024) snprintf(buffer, l, "%.2fkb", 1.0 * s / 1024); - else snprintf(buffer, l, OFF_T_FORMAT"b", (OFF_T_FORMAT_CAST)s); + else snprintf(buffer, l, OFF_T_FORMAT"b", s); } void get_auth_data(const char *srv, const char *shr, char *wg, int wglen, char *un, int unlen, char *pw, int pwlen) @@ -329,10 +327,8 @@ int smb_download_file(const char *base, const char *name, int recursive, int res offset_download = localstat.st_size - RESUME_DOWNLOAD_OFFSET; offset_check = localstat.st_size - RESUME_CHECK_OFFSET; if(verbose)printf("Trying to start resume of %s at "OFF_T_FORMAT"\n" - "At the moment "OFF_T_FORMAT" of "OFF_T_FORMAT" bytes have been retrieved\n", - newpath, (OFF_T_FORMAT_CAST)offset_check, - (OFF_T_FORMAT_CAST)localstat.st_size, - (OFF_T_FORMAT_CAST)remotestat.st_size); + "At the moment "OFF_T_FORMAT" of "OFF_T_FORMAT" bytes have been retrieved\n", newpath, offset_check, + localstat.st_size, remotestat.st_size); } if(offset_check) { @@ -340,24 +336,20 @@ int smb_download_file(const char *base, const char *name, int recursive, int res /* First, check all bytes from offset_check to offset_download */ off1 = lseek(localhandle, offset_check, SEEK_SET); if(off1 < 0) { - fprintf(stderr, "Can't seek to "OFF_T_FORMAT" in local file %s\n", - (OFF_T_FORMAT_CAST)offset_check, newpath); + fprintf(stderr, "Can't seek to "OFF_T_FORMAT" in local file %s\n", offset_check, newpath); smbc_close(remotehandle); close(localhandle); return 0; } off2 = smbc_lseek(remotehandle, offset_check, SEEK_SET); if(off2 < 0) { - fprintf(stderr, "Can't seek to "OFF_T_FORMAT" in remote file %s\n", - (OFF_T_FORMAT_CAST)offset_check, newpath); + fprintf(stderr, "Can't seek to "OFF_T_FORMAT" in remote file %s\n", offset_check, newpath); smbc_close(remotehandle); close(localhandle); return 0; } if(off1 != off2) { - fprintf(stderr, "Offset in local and remote files is different (local: "OFF_T_FORMAT", remote: "OFF_T_FORMAT")\n", - (OFF_T_FORMAT_CAST)off1, - (OFF_T_FORMAT_CAST)off2); + fprintf(stderr, "Offset in local and remote files is different (local: "OFF_T_FORMAT", remote: "OFF_T_FORMAT")\n", off1, off2); return 0; } @@ -374,7 +366,7 @@ int smb_download_file(const char *base, const char *name, int recursive, int res } if(memcmp(checkbuf[0], checkbuf[1], RESUME_CHECK_SIZE) == 0) { - if(verbose)printf("Current local and remote file appear to be the same. Starting download from offset "OFF_T_FORMAT"\n", (OFF_T_FORMAT_CAST)offset_download); + if(verbose)printf("Current local and remote file appear to be the same. Starting download from offset "OFF_T_FORMAT"\n", offset_download); } else { fprintf(stderr, "Local and remote file appear to be different, not doing resume for %s\n", path); smbc_close(remotehandle); close(localhandle); @@ -394,7 +386,7 @@ int smb_download_file(const char *base, const char *name, int recursive, int res for(curpos = offset_download; curpos < remotestat.st_size; curpos+=blocksize) { ssize_t bytesread = smbc_read(remotehandle, readbuf, blocksize); if(bytesread < 0) { - fprintf(stderr, "Can't read %u bytes at offset "OFF_T_FORMAT", file %s\n", (unsigned int)blocksize, (OFF_T_FORMAT_CAST)curpos, path); + fprintf(stderr, "Can't read %d bytes at offset "OFF_T_FORMAT", file %s\n", blocksize, curpos, path); smbc_close(remotehandle); if (localhandle != STDOUT_FILENO) close(localhandle); free(readbuf); @@ -404,7 +396,7 @@ int smb_download_file(const char *base, const char *name, int recursive, int res total_bytes += bytesread; if(write(localhandle, readbuf, bytesread) < 0) { - fprintf(stderr, "Can't write %u bytes to local file %s at offset "OFF_T_FORMAT"\n", (unsigned int)bytesread, path, (OFF_T_FORMAT_CAST)curpos); + fprintf(stderr, "Can't write %d bytes to local file %s at offset "OFF_T_FORMAT"\n", bytesread, path, curpos); free(readbuf); smbc_close(remotehandle); if (localhandle != STDOUT_FILENO) close(localhandle); @@ -544,8 +536,6 @@ int main(int argc, const char **argv) }; poptContext pc; - load_case_tables(); - /* only read rcfile if it exists */ asprintf(&rcfile, "%s/.smbgetrc", getenv("HOME")); if(access(rcfile, F_OK) == 0) diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c index 7659bb2997a..708d44df9f0 100644 --- a/source/utils/smbpasswd.c +++ b/source/utils/smbpasswd.c @@ -92,7 +92,7 @@ static int process_options(int argc, char **argv, int local_flags) user_name[0] = '\0'; - while ((ch = getopt(argc, argv, "c:axdehminjr:sw:R:D:U:LW")) != EOF) { + while ((ch = getopt(argc, argv, "c:axdehminjr:sw:R:D:U:L")) != EOF) { switch(ch) { case 'L': local_flags |= LOCAL_AM_ROOT; @@ -153,10 +153,6 @@ static int process_options(int argc, char **argv, int local_flags) got_username = True; fstrcpy(user_name, optarg); break; - case 'W': - local_flags |= LOCAL_SET_LDAP_ADMIN_PW; - *ldap_secret = '\0'; - break; } case 'h': default: @@ -329,10 +325,6 @@ static int process_root(int local_flags) if (local_flags & LOCAL_SET_LDAP_ADMIN_PW) { printf("Setting stored password for \"%s\" in secrets.tdb\n", lp_ldap_admin_dn()); - if ( ! *ldap_secret ) { - new_passwd = prompt_for_new_password(stdin_passwd_get); - fstrcpy(ldap_secret, new_passwd); - } if (!store_ldap_admin_pw(ldap_secret)) DEBUG(0,("ERROR: Failed to store the ldap admin password!\n")); goto done; @@ -577,8 +569,6 @@ int main(int argc, char **argv) local_flags = LOCAL_AM_ROOT; } - load_case_tables(); - local_flags = process_options(argc, argv, local_flags); setup_logging("smbpasswd", True); |