r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need
authorJeremy Allison <jra@samba.org>
Tue, 11 Jul 2006 18:01:26 +0000 (18:01 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:19:14 +0000 (11:19 -0500)
to do the upper layer directories but this is what
everyone is waiting for....

Jeremy.

259 files changed:
source/Doxyfile
source/Makefile.in
source/aclocal.m4
source/auth/auth_domain.c
source/auth/auth_server.c
source/auth/auth_util.c
source/client/client.c
source/client/clitar.c
source/client/mount.cifs.c
source/client/smbctool.c
source/client/smbmount.c
source/configure.in
source/include/client.h
source/include/idmap.h
source/include/includes.h
source/include/libsmb_internal.h
source/include/locking.h [new file with mode: 0644]
source/include/mangle.h
source/include/nt_status.h
source/include/ntdomain.h
source/include/nterr.h
source/include/passdb.h
source/include/rpc_netlogon.h
source/include/rpc_reg.h
source/include/rpc_samr.h
source/include/rpc_secdes.h
source/include/rpc_srvsvc.h
source/include/rpc_unixinfo.h [new file with mode: 0644]
source/include/session.h
source/include/smb.h
source/include/smb_macros.h
source/include/smbprofile.h
source/include/talloc.h
source/include/vfs.h
source/include/vfs_macros.h
source/lib/account_pol.c
source/lib/afs.c
source/lib/charcnv.c
source/lib/data_blob.c
source/lib/debug.c
source/lib/popt_common.c
source/lib/socket_wrapper.c
source/lib/substitute.c
source/lib/system.c
source/lib/talloc.c
source/lib/talloctort.c
source/lib/time.c
source/lib/util.c
source/lib/util_reg.c [new file with mode: 0644]
source/lib/util_str.c
source/libads/dns.c
source/libads/ldap.c
source/libads/sasl.c
source/libmsrpc/cac_lsarpc.c
source/libmsrpc/cac_samr.c
source/libmsrpc/cac_svcctl.c
source/libmsrpc/cac_winreg.c
source/libmsrpc/libmsrpc_internal.c
source/libndr/libndr.h [new file with mode: 0644]
source/libndr/misc.h [new file with mode: 0644]
source/libndr/ndr.c [new file with mode: 0644]
source/libndr/ndr_basic.c [new file with mode: 0644]
source/libndr/ndr_misc.c [new file with mode: 0644]
source/libndr/ndr_sec.h [new file with mode: 0644]
source/libndr/ndr_sec_helper.c [new file with mode: 0644]
source/libndr/ndr_string.c [new file with mode: 0644]
source/libndr/security.h [new file with mode: 0644]
source/libndr/sid.c [new file with mode: 0644]
source/libsmb/cliconnect.c
source/libsmb/clidfs.c
source/libsmb/clientgen.c
source/libsmb/clikrb5.c
source/libsmb/clirap2.c
source/libsmb/libsmb_cache.c
source/libsmb/libsmbclient.c
source/libsmb/passchange.c
source/libsmb/trusts_util.c
source/locking/brlock.c
source/locking/locking.c
source/locking/posix.c
source/modules/charset_macosxfs.c
source/modules/vfs_afsacl.c
source/modules/vfs_audit.c
source/modules/vfs_cacheprime.c [new file with mode: 0644]
source/modules/vfs_cap.c
source/modules/vfs_catia.c
source/modules/vfs_commit.c [new file with mode: 0644]
source/modules/vfs_default.c [new file with mode: 0644]
source/modules/vfs_default_quota.c
source/modules/vfs_expand_msdfs.c
source/modules/vfs_extd_audit.c
source/modules/vfs_fake_perms.c
source/modules/vfs_full_audit.c
source/modules/vfs_netatalk.c
source/modules/vfs_prealloc.c [new file with mode: 0644]
source/modules/vfs_readonly.c
source/modules/vfs_recycle.c
source/modules/vfs_shadow_copy.c
source/nmbd/nmbd_synclists.c
source/nsswitch/pam_winbind.c
source/nsswitch/wb_client.c
source/nsswitch/wbinfo.c
source/nsswitch/winbindd.c
source/nsswitch/winbindd.h
source/nsswitch/winbindd_ads.c
source/nsswitch/winbindd_async.c
source/nsswitch/winbindd_cache.c
source/nsswitch/winbindd_cm.c
source/nsswitch/winbindd_dual.c
source/nsswitch/winbindd_nss.h
source/nsswitch/winbindd_passdb.c
source/nsswitch/winbindd_reconnect.c
source/nsswitch/winbindd_rpc.c
source/nsswitch/winbindd_sid.c
source/nsswitch/winbindd_user.c
source/nsswitch/winbindd_util.c
source/param/loadparm.c
source/passdb/login_cache.c
source/passdb/lookup_sid.c
source/passdb/passdb.c
source/passdb/pdb_get_set.c
source/passdb/pdb_interface.c
source/passdb/pdb_ldap.c
source/passdb/pdb_nds.c
source/passdb/pdb_smbpasswd.c
source/passdb/pdb_tdb.c
source/passdb/secrets.c
source/printing/nt_printing.c
source/printing/print_generic.c
source/printing/printfsp.c
source/printing/printing.c
source/profile/profile.c
source/python/py_smb.c
source/registry/reg_printing.c
source/rpc_client/cli_lsarpc.c
source/rpc_client/cli_srvsvc.c
source/rpc_client/cli_unixinfo.c [new file with mode: 0644]
source/rpc_client/ndr.c [new file with mode: 0644]
source/rpc_parse/parse_eventlog.c
source/rpc_parse/parse_lsa.c
source/rpc_parse/parse_ntsvcs.c
source/rpc_parse/parse_prs.c
source/rpc_parse/parse_reg.c
source/rpc_parse/parse_rpc.c
source/rpc_parse/parse_samr.c
source/rpc_parse/parse_shutdown.c
source/rpc_parse/parse_spoolss.c
source/rpc_parse/parse_srv.c
source/rpc_parse/parse_svcctl.c
source/rpc_parse/parse_unixinfo.c [new file with mode: 0644]
source/rpc_server/srv_dfs_nt.c
source/rpc_server/srv_lsa_nt.c
source/rpc_server/srv_pipe.c
source/rpc_server/srv_pipe_hnd.c
source/rpc_server/srv_samr_nt.c
source/rpc_server/srv_samr_util.c
source/rpc_server/srv_spoolss_nt.c
source/rpc_server/srv_srvsvc.c
source/rpc_server/srv_srvsvc_nt.c
source/rpc_server/srv_svcctl_nt.c
source/rpc_server/srv_unixinfo.c [new file with mode: 0644]
source/rpc_server/srv_unixinfo_nt.c [new file with mode: 0644]
source/rpcclient/cmd_samr.c
source/rpcclient/cmd_spoolss.c
source/rpcclient/cmd_unixinfo.c [new file with mode: 0644]
source/rpcclient/rpcclient.c
source/sam/idmap.c
source/sam/idmap_ad.c
source/sam/idmap_ldap.c
source/sam/idmap_rid.c
source/sam/idmap_smbldap.c
source/sam/idmap_tdb.c
source/sam/idmap_util.c
source/script/mkproto.awk
source/script/mkproto.sh
source/script/tests/selftest.sh
source/script/tests/test_posix_s3.sh
source/script/tests/test_smbtorture_s3.sh
source/services/svc_netlogon.c
source/smbd/blocking.c
source/smbd/change_trust_pw.c
source/smbd/conn.c
source/smbd/connection.c
source/smbd/dir.c
source/smbd/dosmode.c
source/smbd/error.c
source/smbd/fake_file.c
source/smbd/filename.c
source/smbd/files.c
source/smbd/lanman.c
source/smbd/mangle.c
source/smbd/mangle_hash.c
source/smbd/mangle_hash2.c
source/smbd/mangle_map.c
source/smbd/message.c
source/smbd/msdfs.c
source/smbd/nttrans.c
source/smbd/open.c
source/smbd/password.c
source/smbd/pipes.c
source/smbd/posix_acls.c
source/smbd/process.c
source/smbd/reply.c
source/smbd/server.c
source/smbd/service.c
source/smbd/session.c
source/smbd/share_access.c
source/smbd/statcache.c
source/smbd/statvfs.c
source/smbd/trans2.c
source/smbd/uid.c
source/smbd/vfs-wrap.c [deleted file]
source/smbd/vfs.c
source/smbwrapper/smbw.c
source/smbwrapper/smbw.h
source/tdb/dump.c [new file with mode: 0644]
source/tdb/error.c [new file with mode: 0644]
source/tdb/freelist.c [new file with mode: 0644]
source/tdb/io.c [new file with mode: 0644]
source/tdb/lock.c [new file with mode: 0644]
source/tdb/open.c [new file with mode: 0644]
source/tdb/spinlock.c [deleted file]
source/tdb/spinlock.h [deleted file]
source/tdb/tdb.c
source/tdb/tdb.h
source/tdb/tdb_private.h [new file with mode: 0644]
source/tdb/tdbback.c
source/tdb/tdbutil.c
source/tdb/tdbutil.h
source/tdb/transaction.c [new file with mode: 0644]
source/tdb/traverse.c [new file with mode: 0644]
source/torture/cmd_vfs.c
source/torture/locktest.c
source/torture/locktest2.c
source/torture/masktest.c
source/torture/nsstest.c
source/torture/pdbtest.c [new file with mode: 0644]
source/torture/rpctorture.c
source/torture/scanner.c
source/torture/torture.c
source/torture/vfstest.c
source/utils/debug2html.c
source/utils/net.c
source/utils/net_ads.c
source/utils/net_idmap.c
source/utils/net_rpc.c
source/utils/net_rpc_printer.c
source/utils/net_rpc_registry.c
source/utils/net_rpc_samsync.c
source/utils/net_time.c
source/utils/ntlm_auth.c
source/utils/ntlm_auth_diagnostics.c
source/utils/sharesec.c [new file with mode: 0644]
source/utils/smbcontrol.c
source/utils/status.c
source/utils/status_profile.c [new file with mode: 0644]
source/web/diagnose.c
source/web/neg_lang.c
source/web/swat.c

index c1040781d84577fe7bb704b0168e1d1cbbd191ef..cdcb658908aad1153b9bf0f5e647bd9def45f0fe 100644 (file)
@@ -168,9 +168,3 @@ DOT_CLEANUP            = YES
 # configuration::additions related to the search engine   
 #---------------------------------------------------------------------------
 SEARCHENGINE           = NO
-CGI_NAME               = search.cgi
-CGI_URL                = 
-DOC_URL                = 
-DOC_ABSPATH            = 
-BIN_ABSPATH            = /usr/local/bin/
-EXT_DOC_PATHS          = 
index 127936125bf675ffe8f29d90d6dcdbd6a11bee54..3f586180f048669359004358d1a7184b94d2b5af 100644 (file)
@@ -145,11 +145,12 @@ BIN_PROGS2 = bin/smbcontrol@EXEEXT@ bin/smbtree@EXEEXT@ bin/tdbbackup@EXEEXT@ \
        bin/tdbtool@EXEEXT@
 BIN_PROGS3 = bin/smbpasswd@EXEEXT@ bin/rpcclient@EXEEXT@ bin/smbcacls@EXEEXT@ \
        bin/profiles@EXEEXT@ bin/ntlm_auth@EXEEXT@ \
-       bin/smbcquotas@EXEEXT@ bin/eventlogadm@EXEEXT@ 
+       bin/smbcquotas@EXEEXT@ bin/eventlogadm@EXEEXT@ bin/sharesec@EXEEXT@
 
 TORTURE_PROGS = bin/smbtorture@EXEEXT@ bin/msgtest@EXEEXT@ \
        bin/masktest@EXEEXT@ bin/locktest@EXEEXT@ \
-       bin/locktest2@EXEEXT@ bin/nsstest@EXEEXT@ bin/vfstest@EXEEXT@
+       bin/locktest2@EXEEXT@ bin/nsstest@EXEEXT@ bin/vfstest@EXEEXT@ \
+       bin/pdbtest@EXEEXT@
 
 BIN_PROGS = $(BIN_PROGS1) $(BIN_PROGS2) $(BIN_PROGS3) @EXTRA_BIN_PROGS@
 
@@ -174,7 +175,8 @@ MODULES = $(VFS_MODULES) $(PDB_MODULES) $(RPC_MODULES) $(IDMAP_MODULES) $(CHARSE
 # object file lists
 ######################################################################
 
-TDBBASE_OBJ = tdb/tdb.o tdb/spinlock.o
+TDBBASE_OBJ = tdb/tdb.o tdb/dump.o tdb/error.o tdb/freelist.o tdb/io.o \
+       tdb/lock.o tdb/open.o tdb/transaction.o tdb/traverse.o
 
 TDB_OBJ = $(TDBBASE_OBJ) tdb/tdbutil.o tdb/tdbback.o
 
@@ -200,6 +202,9 @@ PASSCHANGE_OBJ = libsmb/passchange.o
 
 SOCKET_WRAPPER_OBJ = lib/socket_wrapper.o
 
+LIBNDR_OBJ = libndr/ndr_basic.o libndr/ndr.o libndr/ndr_misc.o \
+               libndr/ndr_sec_helper.o libndr/ndr_string.o libndr/sid.o
+
 RPC_PARSE_OBJ0 = rpc_parse/parse_prs.o rpc_parse/parse_misc.o
 
 LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
@@ -209,7 +214,7 @@ LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
          lib/ufc.o lib/genrand.o lib/username.o \
          lib/util_pw.o lib/access.o lib/smbrun.o \
          lib/bitmap.o lib/crc32.o $(SNPRINTF_OBJ) lib/dprintf.o \
-         lib/xfile.o lib/wins_srv.o \
+         lib/xfile.o lib/wins_srv.o lib/util_reg.o \
          lib/util_str.o lib/clobber.o lib/util_sid.o lib/util_uuid.o \
          lib/util_unistr.o lib/util_file.o lib/data_blob.o \
          lib/util.o lib/util_sock.o lib/sock_exec.o lib/util_sec.o \
@@ -272,7 +277,8 @@ LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
               rpc_client/cli_reg.o $(RPC_CLIENT_OBJ) \
               rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o  \
               rpc_client/cli_ds.o rpc_client/cli_echo.o \
-              rpc_client/cli_shutdown.o rpc_client/cli_svcctl.o 
+              rpc_client/cli_shutdown.o rpc_client/cli_svcctl.o \
+              rpc_client/cli_unixinfo.o
 
 REGOBJS_OBJ = registry/reg_objects.o
 
@@ -287,6 +293,7 @@ RPC_NETLOG_OBJ = rpc_server/srv_netlog.o rpc_server/srv_netlog_nt.o
 RPC_SAMR_OBJ = rpc_server/srv_samr.o rpc_server/srv_samr_nt.o \
                rpc_server/srv_samr_util.o
 
+RPC_UNIXINFO_OBJ = rpc_server/srv_unixinfo.o rpc_server/srv_unixinfo_nt.o
 REGFIO_OBJ = registry/regfio.o
 
 RPC_REG_OBJ =  rpc_server/srv_reg.o rpc_server/srv_reg_nt.o $(REGFIO_OBJ)
@@ -327,9 +334,9 @@ RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_net.o \
                 rpc_parse/parse_wks.o rpc_parse/parse_ds.o \
                rpc_parse/parse_spoolss.o rpc_parse/parse_dfs.o \
                rpc_parse/parse_echo.o rpc_parse/parse_shutdown.o \
-               rpc_parse/parse_svcctl.o \
+               rpc_parse/parse_svcctl.o rpc_parse/parse_unixinfo.o \
                rpc_parse/parse_eventlog.o rpc_parse/parse_buffer.o \
-                rpc_parse/parse_ntsvcs.o $(REGOBJS_OBJ)
+                rpc_parse/parse_ntsvcs.o $(REGOBJS_OBJ) $(LIBNDR_OBJ)
 
 RPC_CLIENT_OBJ = rpc_client/cli_pipe.o
 
@@ -361,6 +368,7 @@ 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
 
+VFS_DEFAULT_OBJ = modules/vfs_default.o
 VFS_AUDIT_OBJ = modules/vfs_audit.o
 VFS_EXTD_AUDIT_OBJ = modules/vfs_extd_audit.o
 VFS_FULL_AUDIT_OBJ = modules/vfs_full_audit.o
@@ -374,6 +382,9 @@ VFS_EXPAND_MSDFS_OBJ = modules/vfs_expand_msdfs.o
 VFS_SHADOW_COPY_OBJ = modules/vfs_shadow_copy.o
 VFS_AFSACL_OBJ = modules/vfs_afsacl.o
 VFS_CATIA_OBJ = modules/vfs_catia.o
+VFS_CACHEPRIME_OBJ = modules/vfs_cacheprime.o
+VFS_PREALLOC_OBJ = modules/vfs_prealloc.o
+VFS_COMMIT_OBJ = modules/vfs_commit.o
 
 PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o
 
@@ -408,7 +419,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
                smbd/reply.o smbd/sesssetup.o smbd/trans2.o smbd/uid.o \
               smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o \
               smbd/blocking.o smbd/sec_ctx.o smbd/srvstr.o \
-              smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \
+              smbd/vfs.o smbd/statcache.o \
                smbd/posix_acls.o lib/sysacls.o $(SERVER_MUTEX_OBJ) \
               smbd/process.o smbd/service.o smbd/error.o \
               printing/printfsp.o lib/sysquotas.o lib/sysquotas_linux.o \
@@ -453,6 +464,13 @@ NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \
 NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_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) \
+           $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) \
+           $(LIBSAMBA_OBJ)
+
 SWAT_OBJ1 = web/cgi.o web/diagnose.o web/startstop.o web/statuspage.o \
            web/swat.o web/neg_lang.o 
 
@@ -466,7 +484,8 @@ SMBSH_OBJ = smbwrapper/smbsh.o smbwrapper/shared.o \
             $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) \
            $(DOSERR_OBJ) $(SECRETS_OBJ)
 
-STATUS_OBJ = utils/status.o $(LOCKING_OBJ) $(PARAM_OBJ) \
+STATUS_OBJ = utils/status.o utils/status_profile.o \
+            $(LOCKING_OBJ) $(PARAM_OBJ) \
              $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
             $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(ERRORMAP_OBJ) $(RPC_PARSE_OBJ1) \
              $(DOSERR_OBJ)
@@ -496,7 +515,7 @@ SMBPASSWD_OBJ = utils/smbpasswd.o utils/passwd_util.o $(PASSCHANGE_OBJ) \
 PDBEDIT_OBJ = utils/pdbedit.o utils/passwd_util.o $(PARAM_OBJ) $(PASSDB_OBJ) \
                $(LIBSAMBA_OBJ) $(LIB_NONSMBD_OBJ) $(GROUPDB_OBJ) \
                $(SECRETS_OBJ) $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) libsmb/asn1.o \
-               $(RPC_PARSE_OBJ1) $(DOSERR_OBJ)
+               $(RPC_PARSE_OBJ1) $(DOSERR_OBJ) libsmb/errormap.o
 
 SMBGET_OBJ = utils/smbget.o $(POPT_LIB_OBJ) $(LIBSMBCLIENT_OBJ)
 
@@ -506,7 +525,7 @@ RPCCLIENT_OBJ1 = rpcclient/rpcclient.o rpcclient/cmd_lsarpc.o \
                 rpcclient/cmd_dfs.o rpcclient/cmd_reg.o \
                 rpcclient/cmd_ds.o rpcclient/cmd_echo.o \
                 rpcclient/cmd_shutdown.o rpcclient/cmd_test.o \
-                lib/display_sec.o
+                rpcclient/cmd_unixinfo.o lib/display_sec.o
 
 RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
              $(PARAM_OBJ) $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) \
@@ -542,7 +561,7 @@ CAC_OBJ = $(LIBSMBCLIENT_OBJ) \
                         libmsrpc/cac_lsarpc.o libmsrpc/cac_winreg.o libmsrpc/cac_samr.o \
                         libmsrpc/cac_svcctl.o
 
-LIBSMBSHAREMODES_OBJ = libsmb/smb_share_modes.o tdb/tdb.o tdb/spinlock.o
+LIBSMBSHAREMODES_OBJ = libsmb/smb_share_modes.o tdb/tdb.o
 
 # This shared library is intended for linking with unit test programs
 # to test Samba internals.  It's called libbigballofmud.so to
@@ -595,7 +614,7 @@ MOUNT_OBJ = client/smbmount.o \
 
 MNT_OBJ = client/smbmnt.o lib/replace.o lib/timegm.o $(VERSION_OBJ) $(SNPRINTF_OBJ) @SOCKWRAP@
 
-UMOUNT_OBJ = client/smbumount.o  @SOCKWRAP@
+UMOUNT_OBJ = client/smbumount.o @SOCKWRAP@
 
 CIFS_MOUNT_OBJ = client/mount.cifs.o
 
@@ -622,6 +641,11 @@ LOCKTEST_OBJ = torture/locktest.o $(PARAM_OBJ) $(LOCKING_OBJ) $(KRBCLIENT_OBJ) \
 NSSTEST_OBJ = torture/nsstest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
                  $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ)
 
+PDBTEST_OBJ = torture/pdbtest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
+               $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
+               $(SMBLDAP_OBJ) $(POPT_LIB_OBJ) 
+
+
 VFSTEST_OBJ = torture/cmd_vfs.o torture/vfstest.o $(SMBD_OBJ_BASE) $(READLINE_OBJ)
 
 SMBICONV_OBJ = $(PARAM_OBJ) torture/smbiconv.o $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) $(LIBSAMBA_OBJ)
@@ -650,6 +674,11 @@ EVTLOGADM_OBJ      = $(EVTLOGADM_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(REGOBJS_OBJ)
                registry/reg_eventlog.o rpc_server/srv_eventlog_lib.o registry/reg_util.o \
                registry/reg_db.o 
 
+SHARESEC_OBJ0 = utils/sharesec.o 
+SHARESEC_OBJ  = $(SHARESEC_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(REGOBJS_OBJ) \
+               $(ERRORMAP_OBJ) $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(DOSERR_OBJ) \
+                $(POPT_LIB_OBJ) $(SECRETS_OBJ)
+
 TALLOCTORT_OBJ = lib/talloctort.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
                  $(RPC_PARSE_OBJ1) $(DOSERR_OBJ) $(LIBSAMBA_OBJ) $(SECRETS_OBJ)
 
@@ -668,7 +697,7 @@ DEBUG2HTML_OBJ = utils/debug2html.o utils/debugparse.o
 SMBFILTER_OBJ = utils/smbfilter.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(SECRETS_OBJ) \
                  $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) 
 
-PROTO_OBJ = $(SMBD_OBJ_MAIN) \
+PROTO_OBJ = $(SMBD_OBJ_MAIN) $(LIBNDR_OBJ) \
            $(SMBD_OBJ_SRV) $(NMBD_OBJ1) $(SWAT_OBJ1) $(LIB_OBJ) $(LIBSMB_OBJ) \
            $(SMBTORTURE_OBJ1) $(RPCCLIENT_OBJ1) \
            $(LIBMSRPC_OBJ) @SMBWRAP_OBJS@ \
@@ -681,7 +710,7 @@ PROTO_OBJ = $(SMBD_OBJ_MAIN) \
            $(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) $(RPC_LSA_DS_OBJ) \
            $(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) $(RPC_SPOOLSS_OBJ) \
            $(RPC_ECHO_OBJ) $(RPC_SVCCTL_OBJ) $(RPC_EVENTLOG_OBJ) $(SMBLDAP_OBJ) \
-            $(IDMAP_OBJ) libsmb/spnego.o $(PASSCHANGE_OBJ) \
+            $(IDMAP_OBJ) libsmb/spnego.o $(PASSCHANGE_OBJ) $(RPC_UNIXINFO_OBJ) \
             $(RPC_NTSVCS_OBJ) utils/passwd_util.o
 
 WINBIND_WINS_NSS_OBJ = nsswitch/wins.o $(PARAM_OBJ) \
@@ -760,7 +789,8 @@ NTLM_AUTH_OBJ = ${NTLM_AUTH_OBJ1} $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \
                libsmb/asn1.o libsmb/spnego.o libsmb/clikrb5.o libads/kerberos.o \
                libads/kerberos_verify.o $(SECRETS_OBJ) $(SERVER_MUTEX_OBJ) \
                libads/authdata.o $(RPC_PARSE_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
-               $(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o $(LIBNMB_OBJ)
+               $(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o $(LIBNMB_OBJ) \
+               libsmb/errormap.o
 
 ######################################################################
 # now the rules...
@@ -802,6 +832,8 @@ smbfilter : SHOWFLAGS bin/smbfilter@EXEEXT@
 
 eventlogadm: SHOWFLAGS bin/eventlogadm@EXEEXT@
 
+sharesec: SHOWFLAGS bin/sharesec@EXEEXT@
+
 talloctort : SHOWFLAGS bin/talloctort@EXEEXT@
 
 timelimit : SHOWFLAGS bin/timelimit@EXEEXT@
@@ -916,6 +948,10 @@ bin/nmbd@EXEEXT@: $(NMBD_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
 
+bin/wrepld@EXEEXT@: $(WREPL_OBJ) @BUILD_POPT@ bin/.dummy
+       @echo Linking $@
+       @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(WREPL_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@
+
 bin/swat@EXEEXT@: $(SWAT_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINT_LIBS) \
@@ -1035,6 +1071,10 @@ bin/eventlogadm@EXEEXT@: $(EVTLOGADM_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@
 
+bin/sharesec@EXEEXT@: $(SHARESEC_OBJ) @BUILD_POPT@ bin/.dummy
+       @echo Linking $@
+       @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SHARESEC_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ 
+
 bin/locktest@EXEEXT@: $(LOCKTEST_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
@@ -1043,6 +1083,10 @@ bin/nsstest@EXEEXT@: $(NSSTEST_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS)  $(LDAP_LIBS)
 
+bin/pdbtest@EXEEXT@: $(PDBTEST_OBJ) bin/.dummy
+       @echo Linking $@
+       @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(PDBTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@
+
 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@
@@ -1141,6 +1185,11 @@ bin/librpc_samr.@SHLIBEXT@: $(RPC_SAMR_OBJ)
        @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_SAMR_OBJ) -lc \
                @SONAMEFLAG@`basename $@`
 
+bin/librpc_unixinfo.@SHLIBEXT@: $(RPC_UNIXINFO_OBJ)
+       @echo "Linking $@"
+       @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_UNIXINFO_OBJ) -lc \
+               @SONAMEFLAG@`basename $@`
+
 bin/librpc_srvsvc.@SHLIBEXT@: $(RPC_SVC_OBJ)
        @echo "Linking $@"
        @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_SVC_OBJ) -lc \
@@ -1293,6 +1342,9 @@ bin/macosxfs.@SHLIBEXT@: $(CHARSET_MACOSXFS_OBJ:.o=.@PICSUFFIX@)
        @$(SHLD) $(LDSHFLAGS) -o $@ $(CHARSET_MACOSXFS_OBJ:.o=.@PICSUFFIX@) \
                -framework CoreFoundation @SONAMEFLAG@`basename $@`
 
+# NOTE, there is no build rule for a dynamic default VFS module because
+# this one MUST MUST MUST be built statically.
+
 bin/audit.@SHLIBEXT@: $(VFS_AUDIT_OBJ:.o=.@PICSUFFIX@)
        @echo "Building plugin $@"
        @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AUDIT_OBJ:.o=.@PICSUFFIX@) \
@@ -1358,6 +1410,20 @@ bin/catia.@SHLIBEXT@: $(VFS_CATIA_OBJ:.o=.@PICSUFFIX@)
        @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CATIA_OBJ:.o=.@PICSUFFIX@) \
                @SONAMEFLAG@`basename $@`
 
+bin/cacheprime.@SHLIBEXT@: $(VFS_CACHEPRIME_OBJ:.o=.@PICSUFFIX@)
+       @echo "Building plugin $@"
+       @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CACHEPRIME_OBJ:.o=.@PICSUFFIX@) \
+               @SONAMEFLAG@`basename $@`
+
+bin/prealloc.@SHLIBEXT@: $(VFS_PREALLOC_OBJ:.o=.@PICSUFFIX@)
+       @echo "Building plugin $@"
+       @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_PREALLOC_OBJ:.o=.@PICSUFFIX@) \
+               @SONAMEFLAG@`basename $@`
+
+bin/commit.@SHLIBEXT@: $(VFS_COMMIT_OBJ:.o=.@PICSUFFIX@)
+       @echo "Building plugin $@"
+       @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_COMMIT_OBJ:.o=.@PICSUFFIX@) \
+               @SONAMEFLAG@`basename $@`
 
 bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
@@ -1605,13 +1671,13 @@ clean: delheaders python_clean
 # exist, not necessarily that they are up to date.  Since they're
 # removed by "make clean" this will always be run when you do anything
 # afterwards.
-proto_exists: include/proto.h include/build_env.h \
+proto_exists: include/proto.h include/wrepld_proto.h include/build_env.h \
        nsswitch/winbindd_proto.h web/swat_proto.h \
        client/client_proto.h utils/net_proto.h utils/ntlm_auth_proto.h smbd/build_options.c
 
 delheaders:
        @echo Removing prototype headers
-       @rm -f include/proto.h include/build_env.h  \
+       @rm -f include/proto.h include/build_env.h  include/wrepld_proto.h \
                nsswitch/winbindd_proto.h web/swat_proto.h \
                client/client_proto.h utils/net_proto.h \
                smbd/build_options.c utils/ntlm_auth_proto.h \
@@ -1630,6 +1696,12 @@ include/build_env.h: script/build_env.sh
        @$(SHELL) $(srcdir)/script/build_env.sh $(srcdir) $(builddir) $(CC) \
          > $(builddir)/include/build_env.h
 
+include/wrepld_proto.h:
+       @echo Building include/wrepld_proto.h
+       @cd $(srcdir) && $(SHELL) $(MKPROTO_SH) $(AWK) \
+         -h _WREPLD_PROTO_H_ $(builddir)/include/wrepld_proto.h \
+         $(WREPL_OBJ1)
+
 nsswitch/winbindd_proto.h:
        @cd $(srcdir) && $(SHELL) $(MKPROTO_SH) $(AWK) \
          -h _WINBINDD_PROTO_H_ $(builddir)/nsswitch/winbindd_proto.h \
@@ -1668,6 +1740,7 @@ headers:
        $(MAKE) smbd/build_options.c; \
        $(MAKE) include/proto.h; \
        $(MAKE) include/build_env.h; \
+       $(MAKE) include/wrepld_proto.h; \
        $(MAKE) nsswitch/winbindd_proto.h; \
        $(MAKE) web/swat_proto.h; \
        $(MAKE) client/client_proto.h; \
index af7ed7b40680fec6e7f87063432af7bd960daef6..1f2120c68b3f538edd05b9a051376d0a3045ff8e 100644 (file)
@@ -981,3 +981,97 @@ clockid_t clk = $1;
        AC_MSG_RESULT(no)
     ])
 ])
+
+dnl SMB_IF_RTSIGNAL_BUG([actions if true],
+dnl                    [actions if false],
+dnl                    [actions if cross compiling])
+dnl Test whether we can call sigaction with RT_SIGNAL_NOTIFY and
+dnl RT_SIGNAL_LEASE (also RT_SIGNAL_AIO for good measure, though
+dnl I don't believe that triggers any bug.
+dnl
+dnl See the samba-technical thread titled "Failed to setup
+dnl RT_SIGNAL_NOTIFY handler" for details on the bug in question.
+AC_DEFUN([SMB_IF_RTSIGNAL_BUG],
+[
+    rt_signal_notify_works=yes
+    rt_signal_lease_works=yes
+    rt_signal_aio_works=yes
+
+    AC_MSG_CHECKING(if sigaction works with realtime signals)
+    AC_TRY_RUN(
+       [
+#include <sys/types.h>
+#include <fcntl.h>
+#include <signal.h>
+
+/* from smbd/notify_kernel.c */
+#ifndef RT_SIGNAL_NOTIFY
+#define RT_SIGNAL_NOTIFY (SIGRTMIN+2)
+#endif
+
+/* from smbd/aio.c */
+#ifndef RT_SIGNAL_AIO
+#define RT_SIGNAL_AIO (SIGRTMIN+3)
+#endif
+
+/* from smbd/oplock_linux.c */
+#ifndef RT_SIGNAL_LEASE
+#define RT_SIGNAL_LEASE (SIGRTMIN+1)
+#endif
+
+static void signal_handler(int sig, siginfo_t *info, void *unused)
+{
+    int do_nothing = 0;
+}
+
+int main(void)
+{
+    int result = 0;
+    struct sigaction act = {0};
+
+    act.sa_sigaction = signal_handler;
+    act.sa_flags = SA_SIGINFO;
+    sigemptyset( &act.sa_mask );
+
+    if (sigaction(RT_SIGNAL_LEASE, &act, 0) != 0) {
+           /* Failed to setup RT_SIGNAL_LEASE handler */
+           result += 1;
+    }
+
+    if (sigaction(RT_SIGNAL_NOTIFY, &act, 0) != 0) {
+           /* Failed to setup RT_SIGNAL_NOTIFY handler */
+           result += 10;
+    }
+
+    if (sigaction(RT_SIGNAL_AIO, &act, 0) != 0) {
+           /* Failed to setup RT_SIGNAL_AIO handler */
+           result += 100;
+    }
+
+    /* zero on success */
+    return result;
+}
+       ],
+       [
+           AC_MSG_RESULT(yes)
+           $2
+       ],
+       [
+           AC_MSG_RESULT(no)
+           case "$ac_status" in
+               1|11|101|111)  rt_signal_lease_ok=no ;;
+           esac
+           case "$ac_status" in
+               10|11|110|111)  rt_signal_notify_ok=no ;;
+           esac
+           case "$ac_status" in
+               100|110|101|111)  rt_signal_aio_ok=no ;;
+           esac
+           $2
+       ],
+       [
+           AC_MSG_RESULT(cross)
+           $3
+       ])
+])
+
index bedd318c3c3e5deaf29b7122694fdb74ca57ad84..8ad6329da9818cb6eddec2437ed17605b5d9b054 100644 (file)
@@ -50,6 +50,8 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
         NTSTATUS result;
        struct rpc_pipe_client *netlogon_pipe = NULL;
 
+       *cli = NULL;
+
        *pipe_ret = NULL;
 
        /* TODO: Send a SAMLOGON request to determine whether this is a valid
@@ -81,6 +83,11 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
                        result = NT_STATUS_NO_LOGON_SERVERS;
                }
 
+               if (*cli) {
+                       cli_shutdown(*cli);
+                       *cli = NULL;
+               }
+
                release_server_mutex();
                return result;
        }
@@ -111,6 +118,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
                DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \
 machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
                cli_shutdown(*cli);
+               *cli = NULL;
                release_server_mutex();
                return result;
        }
@@ -126,6 +134,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
                        "trust account password for domain '%s'\n",
                                domain));
                        cli_shutdown(*cli);
+                       *cli = NULL;
                        release_server_mutex();
                        return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
                }
@@ -141,6 +150,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
 
                if (!NT_STATUS_IS_OK(result)) {
                        cli_shutdown(*cli);
+                       *cli = NULL;
                        release_server_mutex();
                        return result;
                }
@@ -150,6 +160,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
                DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \
 machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli)));
                cli_shutdown(*cli);
+               *cli = NULL;
                release_server_mutex();
                return NT_STATUS_NO_LOGON_SERVERS;
        }
index 7bec1b4128daa4c5e47ad5d63a57d689f416db3e..6e4dba0be2d437c60ceafc81765f2703632ec8fd 100644 (file)
@@ -39,7 +39,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
        char *pserver;
        BOOL connected_ok = False;
 
-       if (!(cli = cli_initialise(cli)))
+       if (!(cli = cli_initialise()))
                return NULL;
 
        /* security = server just can't function with spnego */
@@ -49,7 +49,8 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
        p = pserver;
 
         while(next_token( &p, desthost, LIST_SEP, sizeof(desthost))) {
-               standard_sub_basic(current_user_info.smb_name, desthost, sizeof(desthost));
+               standard_sub_basic(current_user_info.smb_name, current_user_info.domain,
+                                  desthost, sizeof(desthost));
                strupper_m(desthost);
 
                if(!resolve_name( desthost, &dest_ip, 0x20)) {
@@ -85,7 +86,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
                return NULL;
        }
        
-       if (!attempt_netbios_session_request(cli, global_myname(), 
+       if (!attempt_netbios_session_request(&cli, global_myname(), 
                                             desthost, &dest_ip)) {
                release_server_mutex();
                DEBUG(1,("password server fails session request\n"));
@@ -129,7 +130,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
        }
        
        release_server_mutex();
-       
+
        DEBUG(3,("password server OK\n"));
        
        return cli;
index 493d7393d072eb0ab046f94c77cc79b67d3e943f..823bf8c32282f439a2c4ead0e5f3f6a1aad6bc65 100644 (file)
@@ -611,12 +611,17 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
  * Add alias SIDs from memberships within the partially created token SID list
  */
 
-static NTSTATUS add_aliases(TALLOC_CTX *tmp_ctx, const DOM_SID *domain_sid,
+static NTSTATUS add_aliases(const DOM_SID *domain_sid,
                            struct nt_user_token *token)
 {
        uint32 *aliases;
        size_t i, num_aliases;
        NTSTATUS status;
+       TALLOC_CTX *tmp_ctx;
+
+       if (!(tmp_ctx = talloc_init("add_aliases"))) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
        aliases = NULL;
        num_aliases = 0;
@@ -629,6 +634,7 @@ static NTSTATUS add_aliases(TALLOC_CTX *tmp_ctx, const DOM_SID *domain_sid,
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10, ("pdb_enum_alias_memberships failed: %s\n",
                           nt_errstr(status)));
+               TALLOC_FREE(tmp_ctx);
                return status;
        }
 
@@ -640,10 +646,12 @@ static NTSTATUS add_aliases(TALLOC_CTX *tmp_ctx, const DOM_SID *domain_sid,
                                        &token->num_sids);
                if (token->user_sids == NULL) {
                        DEBUG(0, ("add_sid_to_array failed\n"));
+                       TALLOC_FREE(tmp_ctx);
                        return NT_STATUS_NO_MEMORY;
                }
        }
 
+       TALLOC_FREE(tmp_ctx);
        return NT_STATUS_OK;
 }
 
@@ -686,7 +694,7 @@ static NTSTATUS log_nt_token(TALLOC_CTX *tmp_ctx, NT_USER_TOKEN *token)
 /*******************************************************************
 *******************************************************************/
 
-static NTSTATUS add_builtin_administrators( TALLOC_CTX *ctx, struct nt_user_token *token )
+static NTSTATUS add_builtin_administrators( struct nt_user_token *token )
 {
        DOM_SID domadm;
 
@@ -808,22 +816,14 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
                                                   int num_groupsids,
                                                   const DOM_SID *groupsids)
 {
-       TALLOC_CTX *tmp_ctx;
        struct nt_user_token *result = NULL;
        int i;
        NTSTATUS status;
        gid_t gid;
 
-       tmp_ctx = talloc_new(mem_ctx);
-       if (tmp_ctx == NULL) {
-               DEBUG(0, ("talloc_new failed\n"));
-               return NULL;
-       }
-
-       result = TALLOC_ZERO_P(tmp_ctx, NT_USER_TOKEN);
-       if (result == NULL) {
+       if (!(result = TALLOC_ZERO_P(mem_ctx, NT_USER_TOKEN))) {
                DEBUG(0, ("talloc failed\n"));
-               goto done;
+               return NULL;
        }
 
        /* Add the user and primary group sid */
@@ -875,7 +875,7 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
                        unbecome_root();
                }
                else {
-                       status = add_builtin_administrators( tmp_ctx, result ); 
+                       status = add_builtin_administrators( result );
                        if ( !NT_STATUS_IS_OK(status) ) {
                                /* just log a complaint but do not fail */
                                DEBUG(3,("create_local_nt_token: failed to check for local Administrators"
@@ -896,7 +896,7 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
                        become_root();
                        status = create_builtin_users( );
                        if ( !NT_STATUS_IS_OK(status) ) {
-                               DEBUG(0,("create_local_nt_token: Failed to create BUILTIN\\Administrators group!\n"));
+                               DEBUG(0,("create_local_nt_token: Failed to create BUILTIN\\Users group!\n"));
                                /* don't fail, just log the message */
                        }
                        unbecome_root();
@@ -909,31 +909,26 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
 
                /* Now add the aliases. First the one from our local SAM */
 
-               status = add_aliases(tmp_ctx, get_global_sam_sid(), result);
+               status = add_aliases(get_global_sam_sid(), result);
 
                if (!NT_STATUS_IS_OK(status)) {
-                       result = NULL;
-                       goto done;
+                       TALLOC_FREE(result);
+                       return NULL;
                }
 
                /* Finally the builtin ones */
 
-               status = add_aliases(tmp_ctx, &global_sid_Builtin, result);
+               status = add_aliases(&global_sid_Builtin, result);
 
                if (!NT_STATUS_IS_OK(status)) {
-                       result = NULL;
-                       goto done;
+                       TALLOC_FREE(result);
+                       return NULL;
                }
        } 
 
 
        get_privileges_for_sids(&result->privileges, result->user_sids,
                                result->num_sids);
-
-       talloc_steal(mem_ctx, result);
-
- done:
-       TALLOC_FREE(tmp_ctx);
        return result;
 }
 
@@ -1443,6 +1438,65 @@ NTSTATUS make_server_info_guest(auth_serversupplied_info **server_info)
        return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
 }
 
+BOOL copy_current_user(struct current_user *dst, struct current_user *src)
+{
+       gid_t *groups;
+       NT_USER_TOKEN *nt_token;
+
+       groups = memdup(src->ut.groups, sizeof(gid_t) * src->ut.ngroups);
+       if ((src->ut.ngroups != 0) && (groups == NULL)) {
+               return False;
+       }
+
+       nt_token = dup_nt_token(NULL, src->nt_user_token);
+       if (nt_token == NULL) {
+               SAFE_FREE(groups);
+               return False;
+       }
+
+       dst->conn = src->conn;
+       dst->vuid = src->vuid;
+       dst->ut.uid = src->ut.uid;
+       dst->ut.gid = src->ut.gid;
+       dst->ut.ngroups = src->ut.ngroups;
+       dst->ut.groups = groups;
+       dst->nt_user_token = nt_token;
+       return True;
+}
+
+BOOL set_current_user_guest(struct current_user *dst)
+{
+       gid_t *groups;
+       NT_USER_TOKEN *nt_token;
+
+       groups = memdup(guest_info->groups,
+                       sizeof(gid_t) * guest_info->n_groups);
+       if (groups == NULL) {
+               return False;
+       }
+
+       nt_token = dup_nt_token(NULL, guest_info->ptok);
+       if (nt_token == NULL) {
+               SAFE_FREE(groups);
+               return False;
+       }
+
+       TALLOC_FREE(dst->nt_user_token);
+       SAFE_FREE(dst->ut.groups);
+
+       /* dst->conn is never really dereferenced, it's only tested for
+        * equality in uid.c */
+       dst->conn = NULL;
+
+       dst->vuid = UID_FIELD_INVALID;
+       dst->ut.uid = guest_info->uid;
+       dst->ut.gid = guest_info->gid;
+       dst->ut.ngroups = guest_info->n_groups;
+       dst->ut.groups = groups;
+       dst->nt_user_token = nt_token;
+       return True;
+}
+
 /***************************************************************************
  Purely internal function for make_server_info_info3
  Fill the sam account from getpwnam
index 3c2d7afe2d65d1804402b8dd6e9100f645ba6098..99fffa712321cf921dcffdc173297be0371c886a 100644 (file)
@@ -3352,7 +3352,7 @@ static int do_message_op(void)
 
        msg_port = port ? port : 139;
 
-       if (!(cli=cli_initialise(NULL)) || (cli_set_port(cli, msg_port) != msg_port) ||
+       if (!(cli=cli_initialise()) || (cli_set_port(cli, msg_port) != msg_port) ||
            !cli_connect(cli, server_name, &ip)) {
                d_printf("Connection to %s failed\n", desthost);
                return 1;
index 14c28acfc5a712302c8fe8f26c940bee9c9bd958..f0d0ac595c2ed716eda1c18aeae49ec5a49e58f5 100644 (file)
@@ -201,7 +201,11 @@ static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t m
        oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.uid);
        oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.gid);
        oct_it((SMB_BIG_UINT) size, 13, hb.dbuf.size);
+#ifdef HAVE_LONGLONG
        if (size > (SMB_BIG_UINT)077777777777LL) {    
+#else
+       if (size > (SMB_BIG_UINT)077777777777) {    
+#endif
 
                /* This is a non-POSIX compatible extention to store files
                        greater than 8GB. */
index ac98b992bb2187f7deb6ba01f4d2849b5fab24ea..ab1f203412ff9aaeb3a4876f574724459c7a8e22 100755 (executable)
@@ -935,10 +935,20 @@ int main(int argc, char ** argv)
                    ++nomtab;
                    break;
                case 'b':
+#ifdef MS_BIND
                        flags |= MS_BIND;
+#else
+                       fprintf(stderr,
+                               "option 'b' (MS_BIND) not supported\n");
+#endif
                        break;
                case 'm':
+#ifdef MS_MOVE               
                        flags |= MS_MOVE;
+#else
+                       fprintf(stderr,
+                               "option 'm' (MS_MOVE) not supported\n");
+#endif
                        break;
                case 'o':
                        orgoptions = strdup(optarg);
index fd385ee68176baca8810cbce5e18d1ec8f8ec8a0..b7042f99cb2a5a8dc6389addeb133548a06397fc 100644 (file)
@@ -3494,7 +3494,7 @@ static int do_message_op(void)
 
        msg_port = port ? port : 139;
 
-       if (!(cli=cli_initialise(NULL)) || (cli_set_port(cli, msg_port) != msg_port) ||
+       if (!(cli=cli_initialise()) || (cli_set_port(cli, msg_port) != msg_port) ||
                !cli_connect(cli, server_name, &ip)) {
                d_printf("Connection to %s failed\n", desthost);
                return 1;
index 7a3ccb7630dee184894a1f848aaf66945b356047..f1cd81198f01288e7fe37573f77fe844ce39f410 100644 (file)
@@ -149,7 +149,7 @@ static struct cli_state *do_connection(char *the_service)
        if (have_ip) ip = dest_ip;
 
        /* have to open a new connection */
-       if (!(c=cli_initialise(NULL)) || (cli_set_port(c, smb_port) != smb_port) ||
+       if (!(c=cli_initialise()) || (cli_set_port(c, smb_port) != smb_port) ||
            !cli_connect(c, server_n, &ip)) {
                DEBUG(0,("%d: Connection to %s failed\n", sys_getpid(), server_n));
                if (c) {
index 884c2cea6abd172515f2e10af1a0c386e72b8577..5359ff8bf41d9d7903a83b0457fb38c4d29856fd 100644 (file)
@@ -579,7 +579,7 @@ DYNEXP=
 
 dnl Add modules that have to be built by default here
 dnl These have to be built static:
-default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_svcctl rpc_ntsvcs rpc_net rpc_netdfs rpc_srv rpc_spoolss rpc_eventlog auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin"
+default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_svcctl rpc_ntsvcs rpc_net rpc_netdfs rpc_srv rpc_spoolss rpc_eventlog rpc_unixinfo auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin vfs_default"
 
 dnl These are preferably build shared, and static if dlopen() is not available
 default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy charset_CP850 charset_CP437 auth_script"
@@ -864,6 +864,7 @@ AC_CHECK_HEADERS(sys/termio.h sys/statfs.h sys/dustat.h sys/statvfs.h stdarg.h s
 AC_CHECK_HEADERS(sys/sysmacros.h security/_pam_macros.h dlfcn.h)
 AC_CHECK_HEADERS(sys/syslog.h syslog.h)
 AC_CHECK_HEADERS(langinfo.h locale.h)
+AC_CHECK_HEADERS(xfs/libxfs.h)
 
 AC_CHECK_HEADERS(rpcsvc/yp_prot.h,,,[[
 #if HAVE_RPC_RPC_H
@@ -969,6 +970,8 @@ AC_CHECK_TYPE(loff_t,off_t)
 AC_CHECK_TYPE(offset_t,loff_t)
 AC_CHECK_TYPE(ssize_t, int)
 AC_CHECK_TYPE(wchar_t, unsigned short)
+AC_CHECK_TYPE(comparison_fn_t, 
+[AC_DEFINE(HAVE_COMPARISON_FN_T, 1,[Whether or not we have comparison_fn_t])])
 
 ############################################
 # for cups support we need libcups, and a handful of header files
@@ -1263,7 +1266,8 @@ if test x"$ac_cv_func_execl" = x"no"; then
     EXTRA_BIN_PROGS="$EXTRA_BIN_PROGS bin/smbrun\$(EXEEXT)"
 fi
 
-AC_CHECK_FUNCS(dlopen dlclose dlsym dlerror waitpid getcwd strdup strndup strnlen strtoul strerror chown fchown chmod fchmod chroot link mknod mknod64)
+AC_CHECK_FUNCS(dlopen dlclose dlsym dlerror waitpid getcwd strdup strndup strnlen strerror chown fchown chmod fchmod chroot link mknod mknod64)
+AC_CHECK_FUNCS(strtol strtoll strtoul strtoull)
 AC_CHECK_FUNCS(fstat strchr utime utimes getrlimit fsync memset strlcpy strlcat setpgid)
 AC_CHECK_FUNCS(memmove vsnprintf snprintf asprintf vasprintf setsid glob strpbrk pipe crypt16 getauthuid)
 AC_CHECK_FUNCS(strftime sigprocmask sigblock sigaction sigset innetgr setnetgrent getnetgrent endnetgrent)
@@ -2072,15 +2076,11 @@ if test x"$samba_cv_WITH_PROFILE" = x"yes"; then
 
     AC_LIBTESTFUNC(rt, clock_gettime,
            [
-               SMB_IS_LIBPTHREAD_LINKED(
-                       [ SMB_REMOVELIB(rt) ],
-                       [
-                           AC_DEFINE(HAVE_CLOCK_GETTIME, 1,
-                               [Whether clock_gettime is available])
-                           SMB_CHECK_CLOCK_ID(CLOCK_MONOTONIC)
-                           SMB_CHECK_CLOCK_ID(CLOCK_PROCESS_CPUTIME_ID)
-                           SMB_CHECK_CLOCK_ID(CLOCK_REALTIME)
-                       ])
+               AC_DEFINE(HAVE_CLOCK_GETTIME, 1,
+                   [Whether clock_gettime is available])
+               SMB_CHECK_CLOCK_ID(CLOCK_MONOTONIC)
+               SMB_CHECK_CLOCK_ID(CLOCK_PROCESS_CPUTIME_ID)
+               SMB_CHECK_CLOCK_ID(CLOCK_REALTIME)
            ])
 
 fi
@@ -3169,6 +3169,18 @@ if test x"$with_ldap_support" != x"no"; then
        
        with_ldap_support=no
   fi
+
+  ##################################################################
+  # HP/UX does not have ber_tag_t, disable LDAP there
+  AC_CHECK_TYPE(ber_tag_t,,,[#include <lber.h>])
+  if test x"$ac_cv_type_ber_tag_t" != x"yes"; then
+       if test x"$with_ldap_support" = x"yes"; then
+        AC_MSG_ERROR(ber_tag_t is needed for LDAP support)
+       else
+        AC_MSG_WARN(ber_tag_t is needed for LDAP support)
+       fi
+       with_ldap_support=no
+  fi
 fi
 
 if test x"$with_ldap_support" != x"no"; then
@@ -4569,6 +4581,16 @@ if test $space = no; then
   fi
 fi
 
+# smbd/statvfs.c assumes that statvfs.f_fsid is an integer.
+# This is not the case on ancient Linux systems.
+
+AC_CACHE_CHECK([that statvfs.f_fsid is an integer],samba_cv_fsid_int, [
+    AC_TRY_COMPILE([#include <sys/statvfs.h>],[struct statvfs buf; buf.f_fsid = 0],
+       samba_cv_fsid_int=yes,samba_cv_fsid_int=no)])
+if test x"$samba_cv_fsid_int" = x"yes"; then
+    AC_DEFINE(HAVE_FSID_INT, 1, [Whether statvfs.f_fsid is an integer])
+fi
+
 if test $space = no; then
   # DEC Alpha running OSF/1
   AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)])
@@ -5545,6 +5567,7 @@ SMB_MODULE(rpc_spoolss, \$(RPC_SPOOLSS_OBJ), "bin/librpc_spoolss.$SHLIBEXT", RPC
 SMB_MODULE(rpc_eventlog, \$(RPC_EVENTLOG_OBJ), "bin/librpc_eventlog.$SHLIBEXT", RPC)
 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_MODULE(rpc_unixinfo, \$(RPC_UNIXINFO_OBJ), "bin/librpc_unixinfo.$SHLIBEXT", RPC)
 SMB_SUBSYSTEM(RPC,smbd/server.o)
 
 SMB_MODULE(idmap_ldap, sam/idmap_ldap.o, "bin/ldap.$SHLIBEXT", IDMAP)
@@ -5568,6 +5591,7 @@ SMB_MODULE(auth_builtin, \$(AUTH_BUILTIN_OBJ), "bin/builtin.$SHLIBEXT", AUTH)
 SMB_MODULE(auth_script, \$(AUTH_SCRIPT_OBJ), "bin/script.$SHLIBEXT", AUTH)
 SMB_SUBSYSTEM(AUTH,auth/auth.o)
 
+SMB_MODULE(vfs_default, \$(VFS_DEFAULT_OBJ), "bin/default.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_recycle, \$(VFS_RECYCLE_OBJ), "bin/recycle.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_audit, \$(VFS_AUDIT_OBJ), "bin/audit.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_extd_audit, \$(VFS_EXTD_AUDIT_OBJ), "bin/extd_audit.$SHLIBEXT", VFS)
@@ -5581,6 +5605,10 @@ SMB_MODULE(vfs_expand_msdfs, \$(VFS_EXPAND_MSDFS_OBJ), "bin/expand_msdfs.$SHLIBE
 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_cacheprime, \$(VFS_CACHEPRIME_OBJ), "bin/cacheprime.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_prealloc, \$(VFS_PREALLOC_OBJ), "bin/prealloc.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_commit, \$(VFS_COMMIT_OBJ), "bin/commit.$SHLIBEXT", VFS)
+
 SMB_SUBSYSTEM(VFS,smbd/vfs.o)
 
 AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules])
@@ -5592,6 +5620,89 @@ if test "${ac_cv_prog_CC}" = "insure"; then
        CPPFLAGS="$CPPFLAGS -D__INSURE__"
 fi
 
+#################################################
+# If run from the build farm, enable NASTY hacks
+#################################################
+AC_MSG_CHECKING(whether to enable build farm hacks)
+if test x"$RUN_FROM_BUILD_FARM" = x"yes"; then
+       AC_MSG_RESULT(yes)
+       AC_DEFINE(ENABLE_BUILD_FARM_HACKS, 1, [Defined if running in the build farm])
+else
+       AC_MSG_RESULT(no)
+fi
+
+#################################################
+# check for bad librt/libpthread interactions
+
+if test x"$samba_cv_HAVE_KERNEL_OPLOCKS_LINUX" = x"yes" -o \
+    x"$samba_cv_HAVE_KERNEL_CHANGE_NOTIFY" = x"yes" -o \
+    x"$samba_cv_HAVE_AIO64" = x"yes" -o \
+    x"$samba_cv_HAVE_AIO" = x"yes" ; then
+
+SMB_IF_RTSIGNAL_BUG(
+       [
+           # Have RT_SIGNAL bug, need to check whether the problem will
+           # affect anything we have configured.
+
+           rt_do_error=no
+           if test x"$samba_cv_HAVE_KERNEL_OPLOCKS_LINUX" = x"yes"; then
+               if test x"$rt_signal_lease_ok" = x"no" ; then
+                   rt_do_error=yes
+               fi
+           fi
+
+           if test x"$samba_cv_HAVE_KERNEL_CHANGE_NOTIFY" = x"yes"; then
+               if test x"$rt_signal_notify_ok" = x"no" ; then
+                   rt_do_error=yes
+               fi
+           fi
+
+           if test x"$samba_cv_HAVE_AIO64" = x"yes" -o \
+                   x"$samba_cv_HAVE_AIO" = x"yes" ; then
+               if test x"$rt_signal_aio_ok" = x"no" ; then
+                   rt_do_error=yes
+               fi
+           fi
+
+           if test x"$rt_do_error" = x"yes" ; then
+               SMB_IS_LIBPTHREAD_LINKED(
+                   [
+                       cat<<MSG
+
+*** On this platforms, linking Samba against pthreads causes problems
+*** with the oplock and change notification mechanisms. You may be
+*** using pthreads as a side-effect of using the --with-aio-support
+*** or --with-profiling-data options. Please remove these and try again.
+
+MSG
+                   ],
+                   [
+                       cat<<MSG
+
+*** On this platform, the oplock and change notification mechanisms do not
+*** appear to work. Please report this problem to samba-technical@samba.org
+*** and attach the config.log file from this directory.
+
+MSG
+                   ])
+               AC_MSG_ERROR(unable to use realtime signals on this platform)
+           fi
+       ],
+       [
+           # no RT_SIGNAL bug, we are golden
+           SMB_IS_LIBPTHREAD_LINKED(
+               [
+                   AC_MSG_WARN(using libpthreads - this may degrade performance)
+               ])
+
+       ],
+       [
+           # cross compiling, I hope you know what you are doing
+           true
+       ])
+
+fi
+
 #################################################
 # Display summary of libraries detected
 
index c6d7b162fcd311c97f62801e37f3b7d8e352dbb2..d11d198e1a5f592a7c79b5b4b9893a456b7aa374 100644 (file)
@@ -171,10 +171,6 @@ struct cli_state {
 
        BOOL force_dos_errors;
        BOOL case_sensitive; /* False by default. */
-
-       /* was this structure allocated by cli_initialise? If so, then
-           free in cli_shutdown() */
-       BOOL allocated;
 };
 
 #define CLI_FULL_CONNECTION_DONT_SPNEGO 0x0001
index 474982f2926eacfa88cbdf0050d13596d54863c4..ee248ef26f2895ce62416f00eb64ea13ef1d08f0 100644 (file)
    Boston, MA  02111-1307, USA.   
 */
 
-/* idmap version determines auto-conversion */
-#define IDMAP_VERSION 2
+/* idmap version determines auto-conversion - this is the database
+   structure version specifier. */
 
-#define SMB_IDMAP_INTERFACE_VERSION    2
+#define IDMAP_VERSION 2
 
+/* The interface version specifier. 
+   Updated to 3 for enum types by JRA. */
 
-#define ID_EMPTY       0x00
-#define ID_USERID      0x01
-#define ID_GROUPID     0x02
-#define ID_OTHER       0x04
+#define SMB_IDMAP_INTERFACE_VERSION    3
 
-#define ID_TYPEMASK    0x0f
+enum idmap_type { ID_USERID, ID_GROUPID };
 
-#define ID_QUERY_ONLY  0x10
-#define ID_CACHE_ONLY   0x20
+#define IDMAP_FLAG_NONE                0x0
+#define IDMAP_FLAG_QUERY_ONLY  0x1     /* Don't ever allocate, just query. */
+#define IDMAP_FLAG_CACHE_ONLY   0x2    /* Only look in our local cache, not remote. */
 
 /* Filled out by IDMAP backends */
 struct idmap_methods {
 
        /* Called when backend is first loaded */
-       NTSTATUS (*init)( char *params );
+       NTSTATUS (*init)( const char *params );
 
-       NTSTATUS (*allocate_id)(unid_t *id, int id_type);
-       NTSTATUS (*get_sid_from_id)(DOM_SID *sid, unid_t id, int id_type);
-       NTSTATUS (*get_id_from_sid)(unid_t *id, int *id_type, const DOM_SID *sid);
-       NTSTATUS (*set_mapping)(const DOM_SID *sid, unid_t id, int id_type);
+       NTSTATUS (*allocate_id)(unid_t *id, enum idmap_type id_type);
+       NTSTATUS (*get_sid_from_id)(DOM_SID *sid, unid_t id, enum idmap_type id_type, int flags);
+       NTSTATUS (*get_id_from_sid)(unid_t *id, enum idmap_type *id_type, const DOM_SID *sid, int flags);
+       NTSTATUS (*set_mapping)(const DOM_SID *sid, unid_t id, enum idmap_type id_type);
 
        /* Called when backend is unloaded */
        NTSTATUS (*close_fn)(void);
index 59e8e5cd0fb908a003bb80ac20e77392cd71d476..ab2f6a96410e4736f453db44313c00e637e574c8 100644 (file)
 #include <stdint.h>
 #endif
 
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
 #ifdef TIME_WITH_SYS_TIME
 #include <sys/time.h>
 #include <time.h>
@@ -873,6 +877,11 @@ struct timespec {
 #define MAX(a,b) ((a)>(b)?(a):(b))
 #endif
 
+#ifndef _BOOL
+typedef int BOOL;
+#define _BOOL       /* So we don't typedef BOOL again in vfs.h */
+#endif
+
 #ifndef HAVE_STRERROR
 extern char *sys_errlist[];
 #define strerror(i) sys_errlist[i]
@@ -905,8 +914,8 @@ extern int errno;
 #include "intl.h"
 #include "dlinklist.h"
 #include "tdb/tdb.h"
-#include "tdb/spinlock.h"
 #include "tdb/tdbutil.h"
+#include "tdb/tdbback.h"
 
 #include "talloc.h"
 /* And a little extension. Abort on type mismatch */
@@ -961,6 +970,7 @@ extern int errno;
 #include "rpc_ds.h"
 #include "rpc_echo.h"
 #include "rpc_shutdown.h"
+#include "rpc_unixinfo.h"
 #include "rpc_perfcount.h"
 #include "rpc_perfcount_defs.h"
 #include "nt_printing.h"
@@ -981,6 +991,8 @@ extern int errno;
 #include "rpc_client.h"
 #include "event.h"
 
+#include "libndr/libndr.h"
+
 /*
  * Type for wide character dirent structure.
  * Only d_name is defined by POSIX.
@@ -1054,6 +1066,10 @@ enum flush_reason_enum {
     /* NUM_FLUSH_REASONS must remain the last value in the enumeration. */
     NUM_FLUSH_REASONS};
 
+#ifndef HAVE_COMPARISON_FN_T
+typedef int (*comparison_fn_t)(const void *, const void *);
+#endif
+
 /***** automatically generated prototypes *****/
 #ifndef NO_PROTO_H
 #include "proto.h"
index 5aca12554f31761ae11edb25ec3db2b7097322eb..42bf2373c1b2551be4a3d8684cd1f02798b76336 100644 (file)
@@ -10,7 +10,7 @@
 
 
 struct _SMBCSRV {
-       struct cli_state cli;
+       struct cli_state *cli;
        dev_t dev;
        BOOL no_pathinfo;
        BOOL no_pathinfo2;
diff --git a/source/include/locking.h b/source/include/locking.h
new file mode 100644 (file)
index 0000000..983d59a
--- /dev/null
@@ -0,0 +1,88 @@
+/* 
+   Unix SMB/CIFS implementation.
+   SMB parameters and setup, plus a whole lot more.
+   
+   Copyright (C) Jeremy Allison   2006
+   
+   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.
+*/
+
+#ifndef _LOCKING_H
+#define _LOCKING_H
+
+/* passed to br lock code - the UNLOCK_LOCK should never be stored into the tdb
+   and is used in calculating POSIX unlock ranges only. */
+
+enum brl_type {READ_LOCK, WRITE_LOCK, PENDING_LOCK, UNLOCK_LOCK};
+enum brl_flavour {WINDOWS_LOCK = 0, POSIX_LOCK = 1};
+
+/* This contains elements that differentiate locks. The smbpid is a
+   client supplied pid, and is essentially the locking context for
+   this client */
+
+struct lock_context {
+       uint32 smbpid;
+       uint16 tid;
+       struct process_id pid;
+};
+
+/* The key used in the brlock database. */
+
+struct lock_key {
+       SMB_DEV_T device;
+       SMB_INO_T inode;
+};
+
+struct byte_range_lock {
+       files_struct *fsp;
+       unsigned int num_locks;
+       BOOL modified;
+       struct lock_key key;
+       void *lock_data;
+};
+
+#define BRLOCK_FN_CAST() \
+       void (*)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \
+                                enum brl_type lock_type, \
+                                enum brl_flavour lock_flav, \
+                                br_off start, br_off size)
+
+#define BRLOCK_FN(fn) \
+       void (*fn)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \
+                                enum brl_type lock_type, \
+                                enum brl_flavour lock_flav, \
+                                br_off start, br_off size)
+
+#define LOCKING_FN_CAST() \
+       void (*)(struct share_mode_entry *, const char *, const char *)
+
+#define LOCKING_FN(fn) \
+       void (*fn)(struct share_mode_entry *, const char *, const char *)
+
+/* Internal structure in brlock.tdb. 
+   The data in brlock records is an unsorted linear array of these
+   records.  It is unnecessary to store the count as tdb provides the
+   size of the record */
+
+struct lock_struct {
+       struct lock_context context;
+       br_off start;
+       br_off size;
+       uint16 fnum;
+       enum brl_type lock_type;
+       enum brl_flavour lock_flav;
+};
+
+#endif /* _LOCKING_H_ */
index 2bdef4ad6469440c4c0e8087c17f2b3c0e972959..3d19ef9ed4f41ba66479461426d18a322d0d750f 100644 (file)
@@ -6,9 +6,13 @@
 
 struct mangle_fns {
        void (*reset)(void);
-       BOOL (*is_mangled)(const char *s, int snum);
-       BOOL (*is_8_3)(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum);
-       BOOL (*check_cache)(char *s, size_t maxlen, int snum);
-       void (*name_map)(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum);
+       BOOL (*is_mangled)(const char *s, const struct share_params *p);
+       BOOL (*is_8_3)(const char *fname, BOOL check_case, BOOL allow_wildcards,
+                      const struct share_params *p);
+       BOOL (*check_cache)(char *s, size_t maxlen,
+                           const struct share_params *p);
+       void (*name_map)(char *OutName, BOOL need83, BOOL cache83,
+                        int default_case,
+                        const struct share_params *p);
 };
 #endif /* _MANGLE_H_ */
index 14c83eba4b37036901c2713018875d3cb9edb898..c48beafb6e7916780c7b6ee0a310a60845eefdae 100644 (file)
@@ -56,7 +56,6 @@ typedef uint32 WERROR;
 
 #define NT_STATUS_IS_OK(x) (NT_STATUS_V(x) == 0)
 #define NT_STATUS_IS_ERR(x) ((NT_STATUS_V(x) & 0xc0000000) == 0xc0000000)
-#define NT_STATUS_IS_INVALID(x) (NT_STATUS_V(x) == 0xFFFFFFFF)
 #define NT_STATUS_EQUAL(x,y) (NT_STATUS_V(x) == NT_STATUS_V(y))
 #define W_ERROR_IS_OK(x) (W_ERROR_V(x) == 0)
 #define W_ERROR_EQUAL(x,y) (W_ERROR_V(x) == W_ERROR_V(y))
@@ -67,4 +66,12 @@ typedef uint32 WERROR;
         }\
 } while (0)
 
+/* this defines special NTSTATUS codes to represent DOS errors.  I
+   have chosen this macro to produce status codes in the invalid
+   NTSTATUS range */
+#define NT_STATUS_DOS(class, code) NT_STATUS(0xF1000000 | ((class)<<16) | code)
+#define NT_STATUS_IS_DOS(status) ((NT_STATUS_V(status) & 0xFF000000) == 0xF1000000)
+#define NT_STATUS_DOS_CLASS(status) ((NT_STATUS_V(status) >> 16) & 0xFF)
+#define NT_STATUS_DOS_CODE(status) (NT_STATUS_V(status) & 0xFFFF)
+
 #endif
index c27ec3675b4f590d36c37a76b6eb505f27602b6f..0114df0e2d0ed7be149388fa5b64f8d7a7da2190 100644 (file)
@@ -234,17 +234,9 @@ typedef struct pipes_struct {
        struct dcinfo *dc; /* Keeps the creds data from netlogon. */
 
        /*
-        * Windows user info.
-        */
-       fstring user_name;
-       fstring domain;
-       fstring wks;
-
-       /*
-        * Unix user name and credentials used when a pipe is authenticated.
+        * Credentials used for the pipe operations
         */
 
-       fstring pipe_user_name;
        struct current_user pipe_user;
        DATA_BLOB session_key;
  
index 417719625e712d9f8af737a570197e7eb41ff815..6cf5a756d297ae4aa3a1e6062b1a2728fa4437ed 100644 (file)
@@ -37,9 +37,6 @@
 #define STATUS_NOTIFY_ENUM_DIR            NT_STATUS(0x010c)
 #define ERROR_INVALID_DATATYPE           NT_STATUS(0x070c)
 
-/* Special "invalid" NT status code. */
-#define NT_STATUS_INVALID                NT_STATUS(0xFFFFFFFF)
-
 /* Win32 Error codes extracted using a loop in smbclient then printing a
    netmon sniff to a file. */
 
index 74063d0fff1aa648fc9a441034c83662613265bd..35bb93aa31cc63b0e70fa7087b4003959e121e3d 100644 (file)
@@ -34,8 +34,8 @@
 #define ACCT_FULL_NAME         0x00000002
 #define ACCT_RID               0x00000004
 #define ACCT_PRIMARY_GID       0x00000008
-#define ACCT_ADMIN_DESC                0x00000010
-#define ACCT_DESCRIPTION       0x00000020
+#define ACCT_DESCRIPTION       0x00000010
+#define ACCT_COMMENT           0x00000020
 #define ACCT_HOME_DIR          0x00000040
 #define ACCT_HOME_DRIVE                0x00000080
 #define ACCT_LOGON_SCRIPT      0x00000100
@@ -90,7 +90,7 @@ enum pdb_elements {
        PDB_UNIXHOMEDIR,
        PDB_ACCTDESC,
        PDB_WORKSTATIONS,
-       PDB_UNKNOWNSTR,
+       PDB_COMMENT,
        PDB_MUNGEDDIAL,
        PDB_HOURS,
        PDB_FIELDS_PRESENT,
@@ -160,7 +160,7 @@ struct samu {
        const char *profile_path; /* profile path string */
        const char *acct_desc;    /* user description string */
        const char *workstations; /* login from workstations string */
-       const char *unknown_str;  /* don't know what this is, yet. */
+       const char *comment;
        const char *munged_dial;  /* munged path name and dial-back tel number */
                
        DOM_SID user_sid;  
index 9df7701de41b2910918b36e063241b20086c88ba..f80dc3121d16c543fcd6734102b432507eec6f60 100644 (file)
 #define NET_DSR_GETSITENAME    0x1c
 #define NET_SAMLOGON_EX                0x27
 
-/* Secure Channel types.  used in NetrServerAuthenticate negotiation */
-#define SEC_CHAN_WKSTA   2
-#define SEC_CHAN_DOMAIN  4
-#define SEC_CHAN_BDC     6
-
 /* Returned delta types */
 #define SAM_DELTA_DOMAIN_INFO    0x01
 #define SAM_DELTA_GROUP_INFO     0x02
 #define SAM_DELTA_DELETE_USER    0x15
 #define SAM_DELTA_MODIFIED_COUNT 0x16
 
-/* SAM database types */
-#define SAM_DATABASE_DOMAIN    0x00 /* Domain users and groups */
-#define SAM_DATABASE_BUILTIN   0x01 /* BUILTIN users and groups */
-#define SAM_DATABASE_PRIVS     0x02 /* Privileges */
-
 /* flags use when sending a NETLOGON_CONTROL request */
 
 #define NETLOGON_CONTROL_SYNC                  0x2
index c454a1d6f949d3ff02fff095bb35de49e72b7953..883e2a8146a73f1184d322381fd6c65f9c442866 100644 (file)
@@ -86,6 +86,7 @@
 #define REG_RESOURCE_LIST              8
 #define REG_FULL_RESOURCE_DESCRIPTOR   9
 #define REG_RESOURCE_REQUIREMENTS_LIST 10
+#define REG_QWORD                      11
 
 /*
  * Registry key types
index 910ccee113580028afdbc6dd4cdc5a2165cabf84..ed4e51837f717a62609014c8608ffc11906981d3 100644 (file)
@@ -174,7 +174,7 @@ typedef struct sam_user_info_23
        UNIHDR hdr_profile_path; /* profile path unicode string header */
        UNIHDR hdr_acct_desc  ;  /* user description */
        UNIHDR hdr_workstations; /* comma-separated workstations user can log in from */
-       UNIHDR hdr_unknown_str ; /* don't know what this is, yet. */
+       UNIHDR hdr_comment;
        UNIHDR hdr_munged_dial ; /* munged path name and dial-back tel number */
 
        uint8 lm_pwd[16];    /* lm user passwords */
@@ -211,7 +211,7 @@ typedef struct sam_user_info_23
        UNISTR2 uni_profile_path; /* profile path unicode string */
        UNISTR2 uni_acct_desc  ;  /* user description unicode string */
        UNISTR2 uni_workstations; /* login from workstations unicode string */
-       UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */
+       UNISTR2 uni_comment;
        UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel no */
 
        LOGON_HRS logon_hrs;
@@ -250,7 +250,7 @@ typedef struct sam_user_info_25
        UNIHDR hdr_profile_path; /* profile path unicode string header */
        UNIHDR hdr_acct_desc  ;  /* user description */
        UNIHDR hdr_workstations; /* comma-separated workstations user can log in from */
-       UNIHDR hdr_unknown_str ; /* don't know what this is, yet. */
+       UNIHDR hdr_comment;
        UNIHDR hdr_munged_dial ; /* munged path name and dial-back tel number */
 
        uint8 lm_pwd[16];    /* lm user passwords */
@@ -274,7 +274,7 @@ typedef struct sam_user_info_25
        UNISTR2 uni_profile_path; /* profile path unicode string */
        UNISTR2 uni_acct_desc  ;  /* user description unicode string */
        UNISTR2 uni_workstations; /* login from workstations unicode string */
-       UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */
+       UNISTR2 uni_comment;
        UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel no */
 } SAM_USER_INFO_25;
 
@@ -304,7 +304,7 @@ typedef struct sam_user_info_21
        UNIHDR hdr_profile_path; /* profile path unicode string header */
        UNIHDR hdr_acct_desc  ;  /* user description */
        UNIHDR hdr_workstations; /* comma-separated workstations user can log in from */
-       UNIHDR hdr_unknown_str ; /* don't know what this is, yet. */
+       UNIHDR hdr_comment;
        UNIHDR hdr_munged_dial ; /* munged path name and dial-back tel number */
 
        uint8 lm_pwd[16];    /* lm user passwords */
@@ -340,7 +340,7 @@ typedef struct sam_user_info_21
        UNISTR2 uni_profile_path; /* profile path unicode string */
        UNISTR2 uni_acct_desc  ;  /* user description unicode string */
        UNISTR2 uni_workstations; /* login from workstations unicode string */
-       UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */
+       UNISTR2 uni_comment;
        UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel number */
 
        LOGON_HRS logon_hrs;
index c385e41fd30954ad128bce8f392d458b1b7ee108..2ac60bd9b12b3336ac4514e96cf120bb257ec0ec 100644 (file)
 #define SEC_ACE_OBJECT_PRESENT           0x00000001 /* thanks for Jim McDonough <jmcd@us.ibm.com> */
 #define SEC_ACE_OBJECT_INHERITED_PRESENT 0x00000002
 
-#define SEC_ACE_FLAG_OBJECT_INHERIT            0x1
-#define SEC_ACE_FLAG_CONTAINER_INHERIT         0x2
-#define SEC_ACE_FLAG_NO_PROPAGATE_INHERIT      0x4
-#define SEC_ACE_FLAG_INHERIT_ONLY              0x8
-#define SEC_ACE_FLAG_INHERITED_ACE             0x10 /* New for Windows 2000 */
-#define SEC_ACE_FLAG_VALID_INHERIT             0xf
-#define SEC_ACE_FLAG_SUCCESSFUL_ACCESS         0x40
-#define SEC_ACE_FLAG_FAILED_ACCESS             0x80
-
-#define SEC_ACE_TYPE_ACCESS_ALLOWED            0x0
-#define SEC_ACE_TYPE_ACCESS_DENIED             0x1
-#define SEC_ACE_TYPE_SYSTEM_AUDIT              0x2
-#define SEC_ACE_TYPE_SYSTEM_ALARM              0x3
-#define SEC_ACE_TYPE_ALLOWED_COMPOUND          0x4
-#define SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT     0x5
-#define SEC_ACE_TYPE_ACCESS_DENIED_OBJECT      0x6
-#define SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT       0x7
-#define SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT       0x8
-
-#define SEC_DESC_OWNER_DEFAULTED       0x0001
-#define SEC_DESC_GROUP_DEFAULTED       0x0002
-#define SEC_DESC_DACL_PRESENT          0x0004
-#define SEC_DESC_DACL_DEFAULTED                0x0008
-#define SEC_DESC_SACL_PRESENT          0x0010
-#define SEC_DESC_SACL_DEFAULTED                0x0020
-#define SEC_DESC_DACL_TRUSTED          0x0040
-#define SEC_DESC_SERVER_SECURITY       0x0080
 /*
  * New Windows 2000 bits.
  */
 #define SE_DESC_DACL_PROTECTED         0x1000
 #define SE_DESC_SACL_PROTECTED         0x2000
 
-/* Don't know what this means. */
-#define SEC_DESC_RM_CONTROL_VALID      0x4000
-
-#define SEC_DESC_SELF_RELATIVE         0x8000
-
 /* security information */
 #define OWNER_SECURITY_INFORMATION     0x00000001
 #define GROUP_SECURITY_INFORMATION     0x00000002
@@ -134,10 +102,6 @@ typedef struct security_ace_info
 #define ACL_REVISION 0x3
 #endif
 
-#ifndef NT4_ACL_REVISION
-#define NT4_ACL_REVISION 0x2
-#endif
-
 #ifndef _SEC_ACL
 /* SEC_ACL */
 typedef struct security_acl_info
index f84054b878bc355348116e88fd935d67b55a8a60..31032f64a4debb2af9dfcbd364094072f09e2717 100644 (file)
@@ -5,6 +5,8 @@
    Copyright (C) Luke Kenneth Casson Leighton 1996-1997
    Copyright (C) Paul Ashton 1997
    Copyright (C) Nigel Williams 2001
+   Copyright (C) Gerald (Jerry) Carter 2006.
+
    
    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
@@ -72,128 +74,84 @@ typedef struct net_srv_disk_enum {
        WERROR status;               /* return status */
 } SRV_Q_NET_DISK_ENUM, SRV_R_NET_DISK_ENUM;
 
-typedef struct net_name_validate {
-       uint32 ptr_srv_name;
-       UNISTR2 uni_srv_name;
-       UNISTR2 uni_name; /*name to validate*/
+/***************************/
+
+typedef struct  {
+       UNISTR2 *servername;
+       UNISTR2 sharename;
        uint32 type;
        uint32 flags;
        WERROR status;
-} SRV_Q_NET_NAME_VALIDATE, SRV_R_NET_NAME_VALIDATE;
-
-/* SESS_INFO_0 (pointers to level 0 session info strings) */
-typedef struct ptr_sess_info0
-{
-       uint32 ptr_name; /* pointer to name. */
-
-} SESS_INFO_0;
+} SRV_Q_NET_NAME_VALIDATE;
 
-/* SESS_INFO_0_STR (level 0 session info strings) */
-typedef struct str_sess_info0
-{
-       UNISTR2 uni_name; /* unicode string of name */
+typedef struct  {
+       WERROR status;
+} SRV_R_NET_NAME_VALIDATE;
 
-} SESS_INFO_0_STR;
+/***************************/
 
 /* oops - this is going to take up a *massive* amount of stack. */
 /* the UNISTR2s already have 1024 uint16 chars in them... */
-#define MAX_SESS_ENTRIES 32
 
-/* SRV_SESS_INFO_0 */
-typedef struct srv_sess_info_0_info
-{
-       uint32 num_entries_read;                     /* EntriesRead */
-       uint32 ptr_sess_info;                       /* Buffer */
-       uint32 num_entries_read2;                    /* EntriesRead */
+#define MAX_SESS_ENTRIES 32
 
-       SESS_INFO_0     info_0    [MAX_SESS_ENTRIES]; /* session entry pointers */
-       SESS_INFO_0_STR info_0_str[MAX_SESS_ENTRIES]; /* session entry strings */
+typedef struct {
+       UNISTR2 *sharename;
+} SESS_INFO_0;
 
+typedef struct {
+       uint32 num_entries_read;
+       uint32 ptr_sess_info;
+       uint32 num_entries_read2;
+       SESS_INFO_0 info_0[MAX_SESS_ENTRIES];
 } SRV_SESS_INFO_0;
 
-/* SESS_INFO_1 (pointers to level 1 session info strings) */
-typedef struct ptr_sess_info1
-{
-       uint32 ptr_name; /* pointer to name. */
-       uint32 ptr_user; /* pointer to user name. */
-
+typedef struct {
+       UNISTR2 *sharename;
+       UNISTR2 *username;
        uint32 num_opens;
        uint32 open_time;
        uint32 idle_time;
        uint32 user_flags;
-
 } SESS_INFO_1;
 
-/* SESS_INFO_1_STR (level 1 session info strings) */
-typedef struct str_sess_info1
-{
-       UNISTR2 uni_name; /* unicode string of name */
-       UNISTR2 uni_user; /* unicode string of user */
-
-} SESS_INFO_1_STR;
-
-/* SRV_SESS_INFO_1 */
-typedef struct srv_sess_info_1_info
-{
-       uint32 num_entries_read;                     /* EntriesRead */
-       uint32 ptr_sess_info;                       /* Buffer */
-       uint32 num_entries_read2;                    /* EntriesRead */
-
-       SESS_INFO_1     info_1    [MAX_SESS_ENTRIES]; /* session entry pointers */
-       SESS_INFO_1_STR info_1_str[MAX_SESS_ENTRIES]; /* session entry strings */
-
+typedef struct {
+       uint32 num_entries_read;
+       uint32 ptr_sess_info;
+       uint32 num_entries_read2;
+       SESS_INFO_1 info_1[MAX_SESS_ENTRIES];
 } SRV_SESS_INFO_1;
 
-/* SRV_SESS_INFO_CTR */
-typedef struct srv_sess_info_ctr_info
-{
-       uint32 switch_value;         /* switch value */
-       uint32 ptr_sess_ctr;       /* pointer to sess info union */
-       union
-    {
-               SRV_SESS_INFO_0 info0; /* session info level 0 */
-               SRV_SESS_INFO_1 info1; /* session info level 1 */
-
-    } sess;
+typedef struct {
+       uint32 switch_value;
+       uint32 ptr_sess_ctr;
+       union {
+               SRV_SESS_INFO_0 info0; 
+               SRV_SESS_INFO_1 info1; 
+       } sess;
 
 } SRV_SESS_INFO_CTR;
 
-
-/* SRV_Q_NET_SESS_ENUM */
-typedef struct q_net_sess_enum_info
-{
-       uint32 ptr_srv_name;         /* pointer (to server name?) */
-       UNISTR2 uni_srv_name;        /* server name */
-
-       uint32 ptr_qual_name;         /* pointer (to qualifier name) */
-       UNISTR2 uni_qual_name;        /* qualifier name "\\qualifier" */
-
-       uint32 ptr_user_name;         /* pointer (to user name */
-       UNISTR2 uni_user_name;        /* user name */
-
-       uint32 sess_level;          /* session level */
-
+typedef struct {
+       UNISTR2 *servername;
+       UNISTR2 *qualifier;
+       UNISTR2 *username;
+       uint32 sess_level;
        SRV_SESS_INFO_CTR *ctr;
-
-       uint32 preferred_len;        /* preferred maximum length (0xffff ffff) */
+       uint32 preferred_len;
        ENUM_HND enum_hnd;
-
 } SRV_Q_NET_SESS_ENUM;
 
-/* SRV_R_NET_SESS_ENUM */
-typedef struct r_net_sess_enum_info
-{
-       uint32 sess_level;          /* share level */
-
+typedef struct {
+       uint32 sess_level; 
        SRV_SESS_INFO_CTR *ctr;
-
-       uint32 total_entries;                    /* total number of entries */
+       uint32 total_entries;
        ENUM_HND enum_hnd;
-
-       WERROR status;               /* return status */
-
+       WERROR status;
 } SRV_R_NET_SESS_ENUM;
 
+/***************************/
+
 /* SRV_Q_NET_SESS_DEL */
 typedef struct q_net_sess_del
 {
@@ -691,104 +649,47 @@ typedef struct r_net_share_del
 
 } SRV_R_NET_SHARE_DEL;
 
-/* FILE_INFO_3 (level 3 file info strings) */
-typedef struct file_info3_info
-{
+/***************************/
+
+typedef struct {
        uint32 id;            /* file index */
        uint32 perms;         /* file permissions. don't know what format */
        uint32 num_locks;     /* file locks */
-       uint32 ptr_path_name; /* file name */
-       uint32 ptr_user_name; /* file owner */
-
+       UNISTR2 *path;        /* file name */
+       UNISTR2 *user;        /* file owner */
 } FILE_INFO_3;
 
-/* FILE_INFO_3_STR (level 3 file info strings) */
-typedef struct str_file_info3_info
-{
-       UNISTR2 uni_path_name; /* unicode string of file name */
-       UNISTR2 uni_user_name; /* unicode string of file owner. */
-
-} FILE_INFO_3_STR;
-
-/* SRV_FILE_INFO_3 */
-typedef struct srv_file_info_3
-{
-       uint32 num_entries_read;                     /* EntriesRead */
-       uint32 ptr_file_info;                        /* Buffer */
-
-       uint32 num_entries_read2;                    /* EntriesRead */
-       FILE_INFO_3     info_3;     /* file entry details */
-       FILE_INFO_3_STR info_3_str; /* file entry strings */
-} SRV_FILE_INFO_3;
-
-/* SRV_FILE_INFO_CTR */
-typedef struct srv_file_info_3_info
-{
-       uint32 switch_value;         /* switch value */
+typedef struct {
+       uint32 level;                /* switch value */
        uint32 ptr_file_info;        /* pointer to file info union */
 
        uint32 num_entries;
        uint32 ptr_entries;
        uint32 num_entries2;
-       union
-       {
-               SRV_FILE_INFO_3 *info3;
+       union {
+               FILE_INFO_3 *info3;
        } file;
 
 } SRV_FILE_INFO_CTR;
 
-
-/* SRV_Q_NET_FILE_ENUM */
-typedef struct q_net_file_enum_info
-{
-       uint32 ptr_srv_name;         /* pointer (to server name?) */
-       UNISTR2 uni_srv_name;        /* server name */
-
-       uint32 ptr_qual_name;         /* pointer (to qualifier name) */
-       UNISTR2 uni_qual_name;        /* qualifier name "\\qualifier" */
-
-       uint32 ptr_user_name;         /* pointer (to user name) */
-       UNISTR2 uni_user_name;        /* user name */
-
-       uint32 file_level;          /* file level */
-
+typedef struct {
+       UNISTR2 *servername;
+       UNISTR2 *qualifier;
+       UNISTR2 *username;
+       uint32 level;
        SRV_FILE_INFO_CTR ctr;
-
-       uint32 preferred_len; /* preferred maximum length (0xffff ffff) */
+       uint32 preferred_len;     /* preferred maximum length (0xffff ffff) */
        ENUM_HND enum_hnd;
-
 } SRV_Q_NET_FILE_ENUM;
 
-
-/* SRV_R_NET_FILE_ENUM */
-typedef struct r_net_file_enum_info
-{
-       uint32 file_level;          /* file level */
-
+typedef struct {
+       uint32 level;   
        SRV_FILE_INFO_CTR ctr;
-
-       uint32 total_entries;                    /* total number of files */
+       uint32 total_entries;
        ENUM_HND enum_hnd;
-
-       WERROR status;        /* return status */
-
+       WERROR status;      
 } SRV_R_NET_FILE_ENUM;
 
-/* SRV_Q_NET_FILE_CLOSE */
-typedef struct q_net_file_close
-{
-       uint32 ptr_srv_name;         /* pointer to server name */
-       UNISTR2 uni_srv_name;        /* server name */
-       
-       uint32 file_id;
-} SRV_Q_NET_FILE_CLOSE;
-
-/* SRV_R_NET_FILE_CLOSE */
-typedef struct r_net_file_close
-{
-       WERROR status;               /* return status */
-} SRV_R_NET_FILE_CLOSE;
-
 /* SRV_INFO_100 */
 typedef struct srv_info_100_info
 {
@@ -973,4 +874,17 @@ typedef struct r_net_file_set_secdesc
        WERROR status;
 } SRV_R_NET_FILE_SET_SECDESC;
 
+/***************************/
+
+typedef struct {
+       UNISTR2 *servername;
+       uint32 file_id;
+} SRV_Q_NET_FILE_CLOSE;
+
+typedef struct {
+       WERROR status;
+} SRV_R_NET_FILE_CLOSE;
+
+/***************************/
+
 #endif /* _RPC_SRVSVC_H */
diff --git a/source/include/rpc_unixinfo.h b/source/include/rpc_unixinfo.h
new file mode 100644 (file)
index 0000000..f2f4382
--- /dev/null
@@ -0,0 +1,172 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   Unixinfo definitions.
+
+   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.
+*/
+
+#ifndef _RPC_UNIXINFO_H
+#define _RPC_UNIXINFO_H
+
+#define UNIXINFO_SID_TO_UID    0x00
+#define UNIXINFO_UID_TO_SID    0x01
+#define UNIXINFO_SID_TO_GID    0x02
+#define UNIXINFO_GID_TO_SID    0x03
+#define UNIXINFO_GETPWUID              0x04
+
+typedef struct unixinfo_q_sid_to_uid {
+       DOM_SID sid;
+} UNIXINFO_Q_SID_TO_UID;
+
+typedef struct unixinfo_r_sid_to_uid {
+       UINT64_S uid;
+       NTSTATUS status;
+} UNIXINFO_R_SID_TO_UID;
+
+typedef struct unixinfo_q_uid_to_sid {
+       UINT64_S uid;
+} UNIXINFO_Q_UID_TO_SID;
+
+typedef struct unixinfo_r_uid_to_sid {
+       uint32 sidptr;
+       DOM_SID sid;
+       NTSTATUS status;
+} UNIXINFO_R_UID_TO_SID;
+
+typedef struct unixinfo_q_sid_to_gid {
+       DOM_SID sid;
+} UNIXINFO_Q_SID_TO_GID;
+
+typedef struct unixinfo_r_sid_to_gid {
+       UINT64_S gid;
+       NTSTATUS status;
+} UNIXINFO_R_SID_TO_GID;
+
+typedef struct unixinfo_q_gid_to_sid {
+       UINT64_S gid;
+} UNIXINFO_Q_GID_TO_SID;
+
+typedef struct unixinfo_r_gid_to_sid {
+       uint32 sidptr;
+       DOM_SID sid;
+       NTSTATUS status;
+} UNIXINFO_R_GID_TO_SID;
+
+typedef struct unixinfo_q_getpwuid {
+       uint32 count;
+       UINT64_S *uid;
+} UNIXINFO_Q_GETPWUID;
+
+struct unixinfo_getpwuid {
+       /* name, gid and gecos explicitly excluded, these values can be
+          retrieved via other means */
+       NTSTATUS status;
+       const char *homedir;
+       const char *shell;
+};
+
+typedef struct unixinfo_r_getpwuid {
+       uint32 count;
+       struct unixinfo_getpwuid *info;
+       NTSTATUS status;
+} UNIXINFO_R_GETPWUID;
+
+#endif  
+/* 
+   Unix SMB/CIFS implementation.
+
+   Unixinfo definitions.
+
+   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.
+*/
+
+#ifndef _RPC_UNIXINFO_H
+#define _RPC_UNIXINFO_H
+
+#define UNIXINFO_SID_TO_UID    0x00
+#define UNIXINFO_UID_TO_SID    0x01
+#define UNIXINFO_SID_TO_GID    0x02
+#define UNIXINFO_GID_TO_SID    0x03
+#define UNIXINFO_GETPWUID              0x04
+
+typedef struct unixinfo_q_sid_to_uid {
+       DOM_SID sid;
+} UNIXINFO_Q_SID_TO_UID;
+
+typedef struct unixinfo_r_sid_to_uid {
+       UINT64_S uid;
+       NTSTATUS status;
+} UNIXINFO_R_SID_TO_UID;
+
+typedef struct unixinfo_q_uid_to_sid {
+       UINT64_S uid;
+} UNIXINFO_Q_UID_TO_SID;
+
+typedef struct unixinfo_r_uid_to_sid {
+       uint32 sidptr;
+       DOM_SID sid;
+       NTSTATUS status;
+} UNIXINFO_R_UID_TO_SID;
+
+typedef struct unixinfo_q_sid_to_gid {
+       DOM_SID sid;
+} UNIXINFO_Q_SID_TO_GID;
+
+typedef struct unixinfo_r_sid_to_gid {
+       UINT64_S gid;
+       NTSTATUS status;
+} UNIXINFO_R_SID_TO_GID;
+
+typedef struct unixinfo_q_gid_to_sid {
+       UINT64_S gid;
+} UNIXINFO_Q_GID_TO_SID;
+
+typedef struct unixinfo_r_gid_to_sid {
+       uint32 sidptr;
+       DOM_SID sid;
+       NTSTATUS status;
+} UNIXINFO_R_GID_TO_SID;
+
+typedef struct unixinfo_q_getpwuid {
+       UINT64_S uid;
+} UNIXINFO_Q_GETPWUID;
+
+typedef struct unixinfo_r_getpwuid {
+       /* name and gid explicitly excluded, these values can be retrieved via
+          other means */
+       const char *gecos;
+       const char *homedir;
+       const char *shell;
+       NTSTATUS status;
+} UNIXINFO_R_GETPWUID;
+
+#endif  
index f613afee09a58c32a9e1f54ac444ffea9f434627..8c8faab53250695236eb5f4e506dfef4efa70039 100644 (file)
@@ -1,8 +1,10 @@
 /* 
    Unix SMB/CIFS implementation.
    session handling for recording currently vailid vuids
+   
    Copyright (C) tridge@samba.org 2001
    Copyright (C) Andew Bartlett <abartlet@samba.org> 2001
+   Copyright (C) Gerald (Jerry) Carter  2006
    
    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
@@ -36,5 +38,6 @@ struct sessionid {
        uint32  id_num;
        uint32  pid;
        fstring ip_addr;
+       time_t connect_start;
 };
 
index e0f2e8483cb3587e9403b1863b7ae92146443b3d..3109948f59ede6747e8e2d740eae234ff45cdc90 100644 (file)
 #define Auto (2)
 #define Required (3)
 
-#ifndef _BOOL
-typedef int BOOL;
-#define _BOOL       /* So we don't typedef BOOL again in vfs.h */
-#endif
-
 #define SIZEOFWORD 2
 
 #ifndef DEF_CREATE_MASK
@@ -197,6 +192,7 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN];
 #define PIPE_EPM      "\\PIPE\\epmapper"
 #define PIPE_SVCCTL   "\\PIPE\\svcctl"
 #define PIPE_EVENTLOG "\\PIPE\\eventlog"
+#define PIPE_UNIXINFO    "\\PIPE\\unixinfo"
 
 #define PIPE_NETLOGON_PLAIN "\\NETLOGON"
 
@@ -213,8 +209,9 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN];
 #define PI_SHUTDOWN            10
 #define PI_SVCCTL              11
 #define PI_EVENTLOG            12
-#define PI_NTSVCS              13
-#define PI_MAX_PIPES           14
+#define PI_UNIXINFO            13
+#define PI_NTSVCS              14
+#define PI_MAX_PIPES           15
 
 /* 64 bit time (100usec) since ????? - cifs6.txt, section 3.5, page 30 */
 typedef struct nttime_info {
@@ -411,6 +408,14 @@ struct timed_event;
 struct idle_event;
 struct share_mode_entry;
 
+struct vfs_fsp_data {
+    struct vfs_fsp_data *next;
+    struct vfs_handle_struct *owner;
+    /* NOTE: This structure contains two pointers so that we can guarantee
+     * that the end of the structure is always both 4-byte and 8-byte aligned.
+     */
+};
+
 typedef struct files_struct {
        struct files_struct *next, *prev;
        int fnum;
@@ -449,6 +454,8 @@ typedef struct files_struct {
        BOOL aio_write_behind;
        BOOL lockdb_clean;
        char *fsp_name;
+
+       struct vfs_fsp_data *vfs_extension;
        FAKE_FILE_HANDLE *fake_file_handle;
 } files_struct;
 
@@ -533,11 +540,15 @@ struct dfree_cached_info {
 
 struct dptr_struct;
 
+struct share_params {
+       int service;
+};
+
 typedef struct connection_struct {
        struct connection_struct *next, *prev;
        TALLOC_CTX *mem_ctx;
        unsigned cnum; /* an index passed over the wire */
-       int service;
+       struct share_params *params;
        BOOL force_user;
        BOOL force_group;
        struct vuid_cache vuid_cache;
@@ -733,6 +744,16 @@ struct locking_data {
         */
 };
 
+/* Used to store pipe open records for NetFileEnum() */
+
+struct pipe_open_rec {
+       struct process_id pid;
+       uid_t uid;
+       int pnum;
+       fstring name;
+};
+
+
 #define NT_HASH_LEN 16
 #define LM_HASH_LEN 16
 
@@ -836,54 +857,13 @@ struct parm_struct {
 #define FLAG_HIDE      0x2000 /* options that should be hidden in SWAT */
 #define FLAG_DOS_STRING 0x4000 /* convert from UNIX to DOS codepage when reading this string. */
 
-/* passed to br lock code - the UNLOCK_LOCK should never be stored into the tdb
-   and is used in calculating POSIX unlock ranges only. */
-
-enum brl_type {READ_LOCK, WRITE_LOCK, PENDING_LOCK, UNLOCK_LOCK};
-enum brl_flavour {WINDOWS_LOCK = 0, POSIX_LOCK = 1};
-
-/* The key used in the brlock database. */
-
-struct lock_key {
-       SMB_DEV_T device;
-       SMB_INO_T inode;
-};
-
-struct byte_range_lock {
-       files_struct *fsp;
-       unsigned int num_locks;
-       BOOL modified;
-       struct lock_key key;
-       void *lock_data;
-};
-
-#define BRLOCK_FN_CAST() \
-       void (*)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \
-                                enum brl_type lock_type, \
-                                enum brl_flavour lock_flav, \
-                                br_off start, br_off size)
-
-#define BRLOCK_FN(fn) \
-       void (*fn)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \
-                                enum brl_type lock_type, \
-                                enum brl_flavour lock_flav, \
-                                br_off start, br_off size)
-
-#define LOCKING_FN_CAST() \
-       void (*)(struct share_mode_entry *, const char *, const char *)
-
-#define LOCKING_FN(fn) \
-       void (*fn)(struct share_mode_entry *, const char *, const char *)
+#include "locking.h"
 
 struct bitmap {
        uint32 *b;
        unsigned int n;
 };
 
-#ifndef LOCKING_VERSION
-#define LOCKING_VERSION 4
-#endif /* LOCKING_VERSION */
-
 /* the basic packet size, assuming no words or bytes */
 #define smb_size 39
 
index 554dbbc0878dee0ebfad99452a93b3ec01b78cf5..e296ddd140326f097a876899eac96c72aa4577b5 100644 (file)
@@ -83,8 +83,6 @@
 #define SMB_ASSERT_ARRAY(a,n) SMB_ASSERT((sizeof(a)/sizeof((a)[0])) >= (n))
 
 /* these are useful macros for checking validity of handles */
-#define OPEN_FSP(fsp)    ((fsp) && !(fsp)->is_directory)
-#define OPEN_CONN(conn)    ((conn) && (conn)->open)
 #define IS_IPC(conn)       ((conn) && (conn)->ipc)
 #define IS_PRINT(conn)       ((conn) && (conn)->printer)
 /* you must add the following extern declaration to files using this macro
 #define FSP_BELONGS_CONN(fsp,conn) do {\
                        extern struct current_user current_user;\
                        if (!((fsp) && (conn) && ((conn)==(fsp)->conn) && (current_user.vuid==(fsp)->vuid))) \
-                               return(ERROR_DOS(ERRDOS,ERRbadfid));\
+                               return ERROR_NT(NT_STATUS_INVALID_HANDLE); \
                        } while(0)
 
-#define FNUM_OK(fsp,c) (OPEN_FSP(fsp) && (c)==(fsp)->conn && current_user.vuid==(fsp)->vuid)
+#define FNUM_OK(fsp,c) ((fsp) && !(fsp)->is_directory && (c)==(fsp)->conn && current_user.vuid==(fsp)->vuid)
 
 /* you must add the following extern declaration to files using this macro
  * extern struct current_user current_user;
  */
 #define CHECK_FSP(fsp,conn) do {\
                        extern struct current_user current_user;\
-                       if (!FNUM_OK(fsp,conn)) \
-                               return(ERROR_DOS(ERRDOS,ERRbadfid)); \
-                       else if((fsp)->fh->fd == -1) \
-                               return(ERROR_DOS(ERRDOS,ERRbadaccess));\
+                       if (!(fsp) || !(conn)) \
+                               return ERROR_NT(NT_STATUS_INVALID_HANDLE); \
+                       else if (((conn) != (fsp)->conn) || current_user.vuid != (fsp)->vuid) \
+                               return ERROR_NT(NT_STATUS_INVALID_HANDLE); \
+                       else if ((fsp)->is_directory) \
+                               return ERROR_NT(NT_STATUS_INVALID_DEVICE_REQUEST); \
+                       else if ((fsp)->fh->fd == -1) \
+                               return ERROR_NT(NT_STATUS_ACCESS_DENIED); \
                        (fsp)->num_smb_operations++;\
                        } while(0)
 
 /* the service number for the [globals] defaults */ 
 #define GLOBAL_SECTION_SNUM    (-1)
 /* translates a connection number into a service number */
-#define SNUM(conn)             ((conn)?(conn)->service:GLOBAL_SECTION_SNUM)
+#define SNUM(conn)             ((conn)?(conn)->params->service:GLOBAL_SECTION_SNUM)
 
 
 /* access various service details */
 #define GUEST_OK(snum)     (VALID_SNUM(snum) && lp_guest_ok(snum))
 #define GUEST_ONLY(snum)   (VALID_SNUM(snum) && lp_guest_only(snum))
 #define CAN_SETDIR(snum)   (!lp_no_set_dir(snum))
-#define CAN_PRINT(conn)    ((conn) && lp_print_ok((conn)->service))
-#define MAP_HIDDEN(conn)   ((conn) && lp_map_hidden((conn)->service))
-#define MAP_SYSTEM(conn)   ((conn) && lp_map_system((conn)->service))
-#define MAP_ARCHIVE(conn)   ((conn) && lp_map_archive((conn)->service))
+#define CAN_PRINT(conn)    ((conn) && lp_print_ok(SNUM(conn)))
+#define MAP_HIDDEN(conn)   ((conn) && lp_map_hidden(SNUM(conn)))
+#define MAP_SYSTEM(conn)   ((conn) && lp_map_system(SNUM(conn)))
+#define MAP_ARCHIVE(conn)   ((conn) && lp_map_archive(SNUM(conn)))
 #define IS_HIDDEN_PATH(conn,path)  ((conn) && is_in_path((path),(conn)->hide_list,(conn)->case_sensitive))
 #define IS_VETO_PATH(conn,path)  ((conn) && is_in_path((path),(conn)->veto_list,(conn)->case_sensitive))
 #define IS_VETO_OPLOCK_PATH(conn,path)  ((conn) && is_in_path((path),(conn)->veto_oplock_list,(conn)->case_sensitive))
 #define CACHED_ERROR(fsp) cached_error_packet(outbuf,fsp,__LINE__,__FILE__)
 
 #define ERROR_DOS(class,code) error_packet(outbuf,class,code,NT_STATUS_OK,__LINE__,__FILE__)
-#define ERROR_FORCE_DOS(class,code) error_packet(outbuf,class,code,NT_STATUS_INVALID,__LINE__,__FILE__)
 #define ERROR_NT(status) error_packet(outbuf,0,0,status,__LINE__,__FILE__)
 #define ERROR_FORCE_NT(status) error_packet(outbuf,-1,-1,status,__LINE__,__FILE__)
 #define ERROR_BOTH(status,class,code) error_packet(outbuf,class,code,status,__LINE__,__FILE__)
@@ -377,6 +378,6 @@ do { \
 } while (0)
 
 #define ADD_TO_LARGE_ARRAY(mem_ctx, type, elem, array, num, size) \
-       add_to_large_array((mem_ctx), sizeof(type), &(elem), (void **)(array), (num), (size));
+       add_to_large_array((mem_ctx), sizeof(type), &(elem), (void *)(array), (num), (size));
 
 #endif /* _SMB_MACROS_H */
index b8a9a49be1aba76e1916823cc13db73682f77569..d29f066796bc68a80393917e9fbfff587e34920c 100644 (file)
@@ -4,7 +4,8 @@
    Unix SMB/CIFS implementation.
    store smbd profiling information in shared memory
    Copyright (C) Andrew Tridgell 1999
-   
+   Copyright (C) James Peach 2006
+
    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
 
 #define PROF_SHMEM_KEY ((key_t)0x07021999)
 #define PROF_SHM_MAGIC 0x6349985
-#define PROF_SHM_VERSION 10
+#define PROF_SHM_VERSION 11
 
 /* time values in the following structure are in microseconds */
 
+#define __profile_stats_value(which, domain) domain[which]
+
+enum profile_stats_values
+{
+       PR_VALUE_SMBD_IDLE = 0,
+#define smbd_idle_count __profile_stats_value(PR_VALUE_SMBD_IDLE, count)
+#define smbd_idle_time __profile_stats_value(PR_VALUE_SMBD_IDLE, time)
+
+/* system call counters */
+       PR_VALUE_SYSCALL_OPENDIR,
+#define syscall_opendir_count __profile_stats_value(PR_VALUE_SYSCALL_OPENDIR, count)
+#define syscall_opendir_time __profile_stats_value(PR_VALUE_SYSCALL_OPENDIR, time)
+
+       PR_VALUE_SYSCALL_READDIR,
+#define syscall_readdir_count __profile_stats_value(PR_VALUE_SYSCALL_READDIR, count)
+#define syscall_readdir_time __profile_stats_value(PR_VALUE_SYSCALL_READDIR, time)
+
+       PR_VALUE_SYSCALL_SEEKDIR,
+#define syscall_seekdir_count __profile_stats_value(PR_VALUE_SYSCALL_SEEKDIR, count)
+#define syscall_seekdir_time __profile_stats_value(PR_VALUE_SYSCALL_SEEKDIR, time)
+
+       PR_VALUE_SYSCALL_TELLDIR,
+#define syscall_telldir_count __profile_stats_value(PR_VALUE_SYSCALL_TELLDIR, count)
+#define syscall_telldir_time __profile_stats_value(PR_VALUE_SYSCALL_TELLDIR, time)
+
+       PR_VALUE_SYSCALL_REWINDDIR,
+#define syscall_rewinddir_count __profile_stats_value(PR_VALUE_SYSCALL_REWINDDIR, count)
+#define syscall_rewinddir_time __profile_stats_value(PR_VALUE_SYSCALL_REWINDDIR, time)
+
+       PR_VALUE_SYSCALL_MKDIR,
+#define syscall_mkdir_count __profile_stats_value(PR_VALUE_SYSCALL_MKDIR, count)
+#define syscall_mkdir_time __profile_stats_value(PR_VALUE_SYSCALL_MKDIR, time)
+
+       PR_VALUE_SYSCALL_RMDIR,
+#define syscall_rmdir_count __profile_stats_value(PR_VALUE_SYSCALL_RMDIR, count)
+#define syscall_rmdir_time __profile_stats_value(PR_VALUE_SYSCALL_RMDIR, time)
+
+       PR_VALUE_SYSCALL_CLOSEDIR,
+#define syscall_closedir_count __profile_stats_value(PR_VALUE_SYSCALL_CLOSEDIR, count)
+#define syscall_closedir_time __profile_stats_value(PR_VALUE_SYSCALL_CLOSEDIR, time)
+
+       PR_VALUE_SYSCALL_OPEN,
+#define syscall_open_count __profile_stats_value(PR_VALUE_SYSCALL_OPEN, count)
+#define syscall_open_time __profile_stats_value(PR_VALUE_SYSCALL_OPEN, time)
+
+       PR_VALUE_SYSCALL_CLOSE,
+#define syscall_close_count __profile_stats_value(PR_VALUE_SYSCALL_CLOSE, count)
+#define syscall_close_time __profile_stats_value(PR_VALUE_SYSCALL_CLOSE, time)
+
+       PR_VALUE_SYSCALL_READ,
+#define syscall_read_count __profile_stats_value(PR_VALUE_SYSCALL_READ, count)
+#define syscall_read_time __profile_stats_value(PR_VALUE_SYSCALL_READ, time)
+
+       PR_VALUE_SYSCALL_PREAD,
+#define syscall_pread_count __profile_stats_value(PR_VALUE_SYSCALL_PREAD, count)
+#define syscall_pread_time __profile_stats_value(PR_VALUE_SYSCALL_PREAD, time)
+
+       PR_VALUE_SYSCALL_WRITE,
+#define syscall_write_count __profile_stats_value(PR_VALUE_SYSCALL_WRITE, count)
+#define syscall_write_time __profile_stats_value(PR_VALUE_SYSCALL_WRITE, time)
+
+       PR_VALUE_SYSCALL_PWRITE,
+#define syscall_pwrite_count __profile_stats_value(PR_VALUE_SYSCALL_PWRITE, count)
+#define syscall_pwrite_time __profile_stats_value(PR_VALUE_SYSCALL_PWRITE, time)
+
+       PR_VALUE_SYSCALL_LSEEK,
+#define syscall_lseek_count __profile_stats_value(PR_VALUE_SYSCALL_LSEEK, count)
+#define syscall_lseek_time __profile_stats_value(PR_VALUE_SYSCALL_LSEEK, time)
+
+       PR_VALUE_SYSCALL_SENDFILE,
+#define syscall_sendfile_count __profile_stats_value(PR_VALUE_SYSCALL_SENDFILE, count)
+#define syscall_sendfile_time __profile_stats_value(PR_VALUE_SYSCALL_SENDFILE, time)
+
+       PR_VALUE_SYSCALL_RENAME,
+#define syscall_rename_count __profile_stats_value(PR_VALUE_SYSCALL_RENAME, count)
+#define syscall_rename_time __profile_stats_value(PR_VALUE_SYSCALL_RENAME, time)
+
+       PR_VALUE_SYSCALL_FSYNC,
+#define syscall_fsync_count __profile_stats_value(PR_VALUE_SYSCALL_FSYNC, count)
+#define syscall_fsync_time __profile_stats_value(PR_VALUE_SYSCALL_FSYNC, time)
+
+       PR_VALUE_SYSCALL_STAT,
+#define syscall_stat_count __profile_stats_value(PR_VALUE_SYSCALL_STAT, count)
+#define syscall_stat_time __profile_stats_value(PR_VALUE_SYSCALL_STAT, time)
+
+       PR_VALUE_SYSCALL_FSTAT,
+#define syscall_fstat_count __profile_stats_value(PR_VALUE_SYSCALL_FSTAT, count)
+#define syscall_fstat_time __profile_stats_value(PR_VALUE_SYSCALL_FSTAT, time)
+
+       PR_VALUE_SYSCALL_LSTAT,
+#define syscall_lstat_count __profile_stats_value(PR_VALUE_SYSCALL_LSTAT, count)
+#define syscall_lstat_time __profile_stats_value(PR_VALUE_SYSCALL_LSTAT, time)
+
+       PR_VALUE_SYSCALL_UNLINK,
+#define syscall_unlink_count __profile_stats_value(PR_VALUE_SYSCALL_UNLINK, count)
+#define syscall_unlink_time __profile_stats_value(PR_VALUE_SYSCALL_UNLINK, time)
+
+       PR_VALUE_SYSCALL_CHMOD,
+#define syscall_chmod_count __profile_stats_value(PR_VALUE_SYSCALL_CHMOD, count)
+#define syscall_chmod_time __profile_stats_value(PR_VALUE_SYSCALL_CHMOD, time)
+
+       PR_VALUE_SYSCALL_FCHMOD,
+#define syscall_fchmod_count __profile_stats_value(PR_VALUE_SYSCALL_FCHMOD, count)
+#define syscall_fchmod_time __profile_stats_value(PR_VALUE_SYSCALL_FCHMOD, time)
+
+       PR_VALUE_SYSCALL_CHOWN,
+#define syscall_chown_count __profile_stats_value(PR_VALUE_SYSCALL_CHOWN, count)
+#define syscall_chown_time __profile_stats_value(PR_VALUE_SYSCALL_CHOWN, time)
+
+       PR_VALUE_SYSCALL_FCHOWN,
+#define syscall_fchown_count __profile_stats_value(PR_VALUE_SYSCALL_FCHOWN, count)
+#define syscall_fchown_time __profile_stats_value(PR_VALUE_SYSCALL_FCHOWN, time)
+
+       PR_VALUE_SYSCALL_CHDIR,
+#define syscall_chdir_count __profile_stats_value(PR_VALUE_SYSCALL_CHDIR, count)
+#define syscall_chdir_time __profile_stats_value(PR_VALUE_SYSCALL_CHDIR, time)
+
+       PR_VALUE_SYSCALL_GETWD,
+#define syscall_getwd_count __profile_stats_value(PR_VALUE_SYSCALL_GETWD, count)
+#define syscall_getwd_time __profile_stats_value(PR_VALUE_SYSCALL_GETWD, time)
+
+       PR_VALUE_SYSCALL_UTIME,
+#define syscall_utime_count __profile_stats_value(PR_VALUE_SYSCALL_UTIME, count)
+#define syscall_utime_time __profile_stats_value(PR_VALUE_SYSCALL_UTIME, time)
+
+       PR_VALUE_SYSCALL_FTRUNCATE,
+#define syscall_ftruncate_count __profile_stats_value(PR_VALUE_SYSCALL_FTRUNCATE, count)
+#define syscall_ftruncate_time __profile_stats_value(PR_VALUE_SYSCALL_FTRUNCATE, time)
+
+       PR_VALUE_SYSCALL_FCNTL_LOCK,
+#define syscall_fcntl_lock_count __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_LOCK, count)
+#define syscall_fcntl_lock_time __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_LOCK, time)
+
+       PR_VALUE_SYSCALL_FCNTL_GETLOCK,
+#define syscall_fcntl_getlock_count __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_GETLOCK, count)
+#define syscall_fcntl_getlock_time __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_GETLOCK, time)
+
+       PR_VALUE_SYSCALL_READLINK,
+#define syscall_readlink_count __profile_stats_value(PR_VALUE_SYSCALL_READLINK, count)
+#define syscall_readlink_time __profile_stats_value(PR_VALUE_SYSCALL_READLINK, time)
+
+       PR_VALUE_SYSCALL_SYMLINK,
+#define syscall_symlink_count __profile_stats_value(PR_VALUE_SYSCALL_SYMLINK, count)
+#define syscall_symlink_time __profile_stats_value(PR_VALUE_SYSCALL_SYMLINK, time)
+
+       PR_VALUE_SYSCALL_LINK,
+#define syscall_link_count __profile_stats_value(PR_VALUE_SYSCALL_LINK, count)
+#define syscall_link_time __profile_stats_value(PR_VALUE_SYSCALL_LINK, time)
+
+       PR_VALUE_SYSCALL_MKNOD,
+#define syscall_mknod_count __profile_stats_value(PR_VALUE_SYSCALL_MKNOD, count)
+#define syscall_mknod_time __profile_stats_value(PR_VALUE_SYSCALL_MKNOD, time)
+
+       PR_VALUE_SYSCALL_REALPATH,
+#define syscall_realpath_count __profile_stats_value(PR_VALUE_SYSCALL_REALPATH, count)
+#define syscall_realpath_time __profile_stats_value(PR_VALUE_SYSCALL_REALPATH, time)
+
+       PR_VALUE_SYSCALL_GET_QUOTA,
+#define syscall_get_quota_count __profile_stats_value(PR_VALUE_SYSCALL_GET_QUOTA, count)
+#define syscall_get_quota_time __profile_stats_value(PR_VALUE_SYSCALL_GET_QUOTA, time)
+
+       PR_VALUE_SYSCALL_SET_QUOTA,
+#define syscall_set_quota_count __profile_stats_value(PR_VALUE_SYSCALL_SET_QUOTA, count)
+#define syscall_set_quota_time __profile_stats_value(PR_VALUE_SYSCALL_SET_QUOTA, time)
+
+/* counters for individual SMB types */
+       PR_VALUE_SMBMKDIR,
+#define SMBmkdir_count __profile_stats_value(PR_VALUE_SMBMKDIR, count)
+#define SMBmkdir_time __profile_stats_value(PR_VALUE_SMBMKDIR, time)
+
+       PR_VALUE_SMBRMDIR,
+#define SMBrmdir_count __profile_stats_value(PR_VALUE_SMBRMDIR, count)
+#define SMBrmdir_time __profile_stats_value(PR_VALUE_SMBRMDIR, time)
+
+       PR_VALUE_SMBOPEN,
+#define SMBopen_count __profile_stats_value(PR_VALUE_SMBOPEN, count)
+#define SMBopen_time __profile_stats_value(PR_VALUE_SMBOPEN, time)
+
+       PR_VALUE_SMBCREATE,
+#define SMBcreate_count __profile_stats_value(PR_VALUE_SMBCREATE, count)
+#define SMBcreate_time __profile_stats_value(PR_VALUE_SMBCREATE, time)
+
+       PR_VALUE_SMBCLOSE,
+#define SMBclose_count __profile_stats_value(PR_VALUE_SMBCLOSE, count)
+#define SMBclose_time __profile_stats_value(PR_VALUE_SMBCLOSE, time)
+
+       PR_VALUE_SMBFLUSH,
+#define SMBflush_count __profile_stats_value(PR_VALUE_SMBFLUSH, count)
+#define SMBflush_time __profile_stats_value(PR_VALUE_SMBFLUSH, time)
+
+       PR_VALUE_SMBUNLINK,
+#define SMBunlink_count __profile_stats_value(PR_VALUE_SMBUNLINK, count)
+#define SMBunlink_time __profile_stats_value(PR_VALUE_SMBUNLINK, time)
+
+       PR_VALUE_SMBMV,
+#define SMBmv_count __profile_stats_value(PR_VALUE_SMBMV, count)
+#define SMBmv_time __profile_stats_value(PR_VALUE_SMBMV, time)
+
+       PR_VALUE_SMBGETATR,
+#define SMBgetatr_count __profile_stats_value(PR_VALUE_SMBGETATR, count)
+#define SMBgetatr_time __profile_stats_value(PR_VALUE_SMBGETATR, time)
+
+       PR_VALUE_SMBSETATR,
+#define SMBsetatr_count __profile_stats_value(PR_VALUE_SMBSETATR, count)
+#define SMBsetatr_time __profile_stats_value(PR_VALUE_SMBSETATR, time)
+
+       PR_VALUE_SMBREAD,
+#define SMBread_count __profile_stats_value(PR_VALUE_SMBREAD, count)
+#define SMBread_time __profile_stats_value(PR_VALUE_SMBREAD, time)
+
+       PR_VALUE_SMBWRITE,
+#define SMBwrite_count __profile_stats_value(PR_VALUE_SMBWRITE, count)
+#define SMBwrite_time __profile_stats_value(PR_VALUE_SMBWRITE, time)
+
+       PR_VALUE_SMBLOCK,
+#define SMBlock_count __profile_stats_value(PR_VALUE_SMBLOCK, count)
+#define SMBlock_time __profile_stats_value(PR_VALUE_SMBLOCK, time)
+
+       PR_VALUE_SMBUNLOCK,
+#define SMBunlock_count __profile_stats_value(PR_VALUE_SMBUNLOCK, count)
+#define SMBunlock_time __profile_stats_value(PR_VALUE_SMBUNLOCK, time)
+
+       PR_VALUE_SMBCTEMP,
+#define SMBctemp_count __profile_stats_value(PR_VALUE_SMBCTEMP, count)
+#define SMBctemp_time __profile_stats_value(PR_VALUE_SMBCTEMP, time)
+
+       /* SMBmknew stats are currently combined with SMBcreate */
+       PR_VALUE_SMBMKNEW,
+#define SMBmknew_count __profile_stats_value(PR_VALUE_SMBMKNEW, count)
+#define SMBmknew_time __profile_stats_value(PR_VALUE_SMBMKNEW, time)
+
+       PR_VALUE_SMBCHKPTH,
+#define SMBchkpth_count __profile_stats_value(PR_VALUE_SMBCHKPTH, count)
+#define SMBchkpth_time __profile_stats_value(PR_VALUE_SMBCHKPTH, time)
+
+       PR_VALUE_SMBEXIT,
+#define SMBexit_count __profile_stats_value(PR_VALUE_SMBEXIT, count)
+#define SMBexit_time __profile_stats_value(PR_VALUE_SMBEXIT, time)
+
+       PR_VALUE_SMBLSEEK,
+#define SMBlseek_count __profile_stats_value(PR_VALUE_SMBLSEEK, count)
+#define SMBlseek_time __profile_stats_value(PR_VALUE_SMBLSEEK, time)
+
+       PR_VALUE_SMBLOCKREAD,
+#define SMBlockread_count __profile_stats_value(PR_VALUE_SMBLOCKREAD, count)
+#define SMBlockread_time __profile_stats_value(PR_VALUE_SMBLOCKREAD, time)
+
+       PR_VALUE_SMBWRITEUNLOCK,
+#define SMBwriteunlock_count __profile_stats_value(PR_VALUE_SMBWRITEUNLOCK, count)
+#define SMBwriteunlock_time __profile_stats_value(PR_VALUE_SMBWRITEUNLOCK, time)
+
+       PR_VALUE_SMBREADBRAW,
+#define SMBreadbraw_count __profile_stats_value(PR_VALUE_SMBREADBRAW, count)
+#define SMBreadbraw_time __profile_stats_value(PR_VALUE_SMBREADBRAW, time)
+
+       PR_VALUE_SMBREADBMPX,
+#define SMBreadBmpx_count __profile_stats_value(PR_VALUE_SMBREADBMPX, count)
+#define SMBreadBmpx_time __profile_stats_value(PR_VALUE_SMBREADBMPX, time)
+
+       PR_VALUE_SMBREADBS,
+#define SMBreadBs_count __profile_stats_value(PR_VALUE_SMBREADBS, count)
+#define SMBreadBs_time __profile_stats_value(PR_VALUE_SMBREADBS, time)
+
+       PR_VALUE_SMBWRITEBRAW,
+#define SMBwritebraw_count __profile_stats_value(PR_VALUE_SMBWRITEBRAW, count)
+#define SMBwritebraw_time __profile_stats_value(PR_VALUE_SMBWRITEBRAW, time)
+
+       PR_VALUE_SMBWRITEBMPX,
+#define SMBwriteBmpx_count __profile_stats_value(PR_VALUE_SMBWRITEBMPX, count)
+#define SMBwriteBmpx_time __profile_stats_value(PR_VALUE_SMBWRITEBMPX, time)
+
+       PR_VALUE_SMBWRITEBS,
+#define SMBwriteBs_count __profile_stats_value(PR_VALUE_SMBWRITEBS, count)
+#define SMBwriteBs_time __profile_stats_value(PR_VALUE_SMBWRITEBS, time)
+
+       PR_VALUE_SMBWRITEC,
+#define SMBwritec_count __profile_stats_value(PR_VALUE_SMBWRITEC, count)
+#define SMBwritec_time __profile_stats_value(PR_VALUE_SMBWRITEC, time)
+
+       PR_VALUE_SMBSETATTRE,
+#define SMBsetattrE_count __profile_stats_value(PR_VALUE_SMBSETATTRE, count)
+#define SMBsetattrE_time __profile_stats_value(PR_VALUE_SMBSETATTRE, time)
+
+       PR_VALUE_SMBGETATTRE,
+#define SMBgetattrE_count __profile_stats_value(PR_VALUE_SMBGETATTRE, count)
+#define SMBgetattrE_time __profile_stats_value(PR_VALUE_SMBGETATTRE, time)
+
+       PR_VALUE_SMBLOCKINGX,
+#define SMBlockingX_count __profile_stats_value(PR_VALUE_SMBLOCKINGX, count)
+#define SMBlockingX_time __profile_stats_value(PR_VALUE_SMBLOCKINGX, time)
+
+       PR_VALUE_SMBTRANS,
+#define SMBtrans_count __profile_stats_value(PR_VALUE_SMBTRANS, count)
+#define SMBtrans_time __profile_stats_value(PR_VALUE_SMBTRANS, time)
+
+       PR_VALUE_SMBTRANSS,
+#define SMBtranss_count __profile_stats_value(PR_VALUE_SMBTRANSS, count)
+#define SMBtranss_time __profile_stats_value(PR_VALUE_SMBTRANSS, time)
+
+       PR_VALUE_SMBIOCTL,
+#define SMBioctl_count __profile_stats_value(PR_VALUE_SMBIOCTL, count)
+#define SMBioctl_time __profile_stats_value(PR_VALUE_SMBIOCTL, time)
+
+       PR_VALUE_SMBIOCTLS,
+#define SMBioctls_count __profile_stats_value(PR_VALUE_SMBIOCTLS, count)
+#define SMBioctls_time __profile_stats_value(PR_VALUE_SMBIOCTLS, time)
+
+       PR_VALUE_SMBCOPY,
+#define SMBcopy_count __profile_stats_value(PR_VALUE_SMBCOPY, count)
+#define SMBcopy_time __profile_stats_value(PR_VALUE_SMBCOPY, time)
+
+       PR_VALUE_SMBMOVE,
+#define SMBmove_count __profile_stats_value(PR_VALUE_SMBMOVE, count)
+#define SMBmove_time __profile_stats_value(PR_VALUE_SMBMOVE, time)
+
+       PR_VALUE_SMBECHO,
+#define SMBecho_count __profile_stats_value(PR_VALUE_SMBECHO, count)
+#define SMBecho_time __profile_stats_value(PR_VALUE_SMBECHO, time)
+
+       PR_VALUE_SMBWRITECLOSE,
+#define SMBwriteclose_count __profile_stats_value(PR_VALUE_SMBWRITECLOSE, count)
+#define SMBwriteclose_time __profile_stats_value(PR_VALUE_SMBWRITECLOSE, time)
+
+       PR_VALUE_SMBOPENX,
+#define SMBopenX_count __profile_stats_value(PR_VALUE_SMBOPENX, count)
+#define SMBopenX_time __profile_stats_value(PR_VALUE_SMBOPENX, time)
+
+       PR_VALUE_SMBREADX,
+#define SMBreadX_count __profile_stats_value(PR_VALUE_SMBREADX, count)
+#define SMBreadX_time __profile_stats_value(PR_VALUE_SMBREADX, time)
+
+       PR_VALUE_SMBWRITEX,
+#define SMBwriteX_count __profile_stats_value(PR_VALUE_SMBWRITEX, count)
+#define SMBwriteX_time __profile_stats_value(PR_VALUE_SMBWRITEX, time)
+
+       PR_VALUE_SMBTRANS2,
+#define SMBtrans2_count __profile_stats_value(PR_VALUE_SMBTRANS2, count)
+#define SMBtrans2_time __profile_stats_value(PR_VALUE_SMBTRANS2, time)
+
+       PR_VALUE_SMBTRANSS2,
+#define SMBtranss2_count __profile_stats_value(PR_VALUE_SMBTRANSS2, count)
+#define SMBtranss2_time __profile_stats_value(PR_VALUE_SMBTRANSS2, time)
+
+       PR_VALUE_SMBFINDCLOSE,
+#define SMBfindclose_count __profile_stats_value(PR_VALUE_SMBFINDCLOSE, count)
+#define SMBfindclose_time __profile_stats_value(PR_VALUE_SMBFINDCLOSE, time)
+
+       PR_VALUE_SMBFINDNCLOSE,
+#define SMBfindnclose_count __profile_stats_value(PR_VALUE_SMBFINDNCLOSE, count)
+#define SMBfindnclose_time __profile_stats_value(PR_VALUE_SMBFINDNCLOSE, time)
+
+       PR_VALUE_SMBTCON,
+#define SMBtcon_count __profile_stats_value(PR_VALUE_SMBTCON, count)
+#define SMBtcon_time __profile_stats_value(PR_VALUE_SMBTCON, time)
+
+       PR_VALUE_SMBTDIS,
+#define SMBtdis_count __profile_stats_value(PR_VALUE_SMBTDIS, count)
+#define SMBtdis_time __profile_stats_value(PR_VALUE_SMBTDIS, time)
+
+       PR_VALUE_SMBNEGPROT,
+#define SMBnegprot_count __profile_stats_value(PR_VALUE_SMBNEGPROT, count)
+#define SMBnegprot_time __profile_stats_value(PR_VALUE_SMBNEGPROT, time)
+
+       PR_VALUE_SMBSESSSETUPX,
+#define SMBsesssetupX_count __profile_stats_value(PR_VALUE_SMBSESSSETUPX, count)
+#define SMBsesssetupX_time __profile_stats_value(PR_VALUE_SMBSESSSETUPX, time)
+
+       PR_VALUE_SMBULOGOFFX,
+#define SMBulogoffX_count __profile_stats_value(PR_VALUE_SMBULOGOFFX, count)
+#define SMBulogoffX_time __profile_stats_value(PR_VALUE_SMBULOGOFFX, time)
+
+       PR_VALUE_SMBTCONX,
+#define SMBtconX_count __profile_stats_value(PR_VALUE_SMBTCONX, count)
+#define SMBtconX_time __profile_stats_value(PR_VALUE_SMBTCONX, time)
+
+       PR_VALUE_SMBDSKATTR,
+#define SMBdskattr_count __profile_stats_value(PR_VALUE_SMBDSKATTR, count)
+#define SMBdskattr_time __profile_stats_value(PR_VALUE_SMBDSKATTR, time)
+
+       PR_VALUE_SMBSEARCH,
+#define SMBsearch_count __profile_stats_value(PR_VALUE_SMBSEARCH, count)
+#define SMBsearch_time __profile_stats_value(PR_VALUE_SMBSEARCH, time)
+
+       /* SBMffirst stats combined with SMBsearch */
+       PR_VALUE_SMBFFIRST,
+#define SMBffirst_count __profile_stats_value(PR_VALUE_SMBFFIRST, count)
+#define SMBffirst_time __profile_stats_value(PR_VALUE_SMBFFIRST, time)
+
+       /* SBMfunique stats combined with SMBsearch */
+       PR_VALUE_SMBFUNIQUE,
+#define SMBfunique_count __profile_stats_value(PR_VALUE_SMBFUNIQUE, count)
+#define SMBfunique_time __profile_stats_value(PR_VALUE_SMBFUNIQUE, time)
+
+       PR_VALUE_SMBFCLOSE,
+#define SMBfclose_count __profile_stats_value(PR_VALUE_SMBFCLOSE, count)
+#define SMBfclose_time __profile_stats_value(PR_VALUE_SMBFCLOSE, time)
+
+       PR_VALUE_SMBNTTRANS,
+#define SMBnttrans_count __profile_stats_value(PR_VALUE_SMBNTTRANS, count)
+#define SMBnttrans_time __profile_stats_value(PR_VALUE_SMBNTTRANS, time)
+
+       PR_VALUE_SMBNTTRANSS,
+#define SMBnttranss_count __profile_stats_value(PR_VALUE_SMBNTTRANSS, count)
+#define SMBnttranss_time __profile_stats_value(PR_VALUE_SMBNTTRANSS, time)
+
+       PR_VALUE_SMBNTCREATEX,
+#define SMBntcreateX_count __profile_stats_value(PR_VALUE_SMBNTCREATEX, count)
+#define SMBntcreateX_time __profile_stats_value(PR_VALUE_SMBNTCREATEX, time)
+
+       PR_VALUE_SMBNTCANCEL,
+#define SMBntcancel_count __profile_stats_value(PR_VALUE_SMBNTCANCEL, count)
+#define SMBntcancel_time __profile_stats_value(PR_VALUE_SMBNTCANCEL, time)
+
+       PR_VALUE_SMBNTRENAME,
+#define SMBntrename_count __profile_stats_value(PR_VALUE_SMBNTRENAME, count)
+#define SMBntrename_time __profile_stats_value(PR_VALUE_SMBNTRENAME, time)
+
+       PR_VALUE_SMBSPLOPEN,
+#define SMBsplopen_count __profile_stats_value(PR_VALUE_SMBSPLOPEN, count)
+#define SMBsplopen_time __profile_stats_value(PR_VALUE_SMBSPLOPEN, time)
+
+       PR_VALUE_SMBSPLWR,
+#define SMBsplwr_count __profile_stats_value(PR_VALUE_SMBSPLWR, count)
+#define SMBsplwr_time __profile_stats_value(PR_VALUE_SMBSPLWR, time)
+
+       PR_VALUE_SMBSPLCLOSE,
+#define SMBsplclose_count __profile_stats_value(PR_VALUE_SMBSPLCLOSE, count)
+#define SMBsplclose_time __profile_stats_value(PR_VALUE_SMBSPLCLOSE, time)
+
+       PR_VALUE_SMBSPLRETQ,
+#define SMBsplretq_count __profile_stats_value(PR_VALUE_SMBSPLRETQ, count)
+#define SMBsplretq_time __profile_stats_value(PR_VALUE_SMBSPLRETQ, time)
+
+       PR_VALUE_SMBSENDS,
+#define SMBsends_count __profile_stats_value(PR_VALUE_SMBSENDS, count)
+#define SMBsends_time __profile_stats_value(PR_VALUE_SMBSENDS, time)
+
+       PR_VALUE_SMBSENDB,
+#define SMBsendb_count __profile_stats_value(PR_VALUE_SMBSENDB, count)
+#define SMBsendb_time __profile_stats_value(PR_VALUE_SMBSENDB, time)
+
+       PR_VALUE_SMBFWDNAME,
+#define SMBfwdname_count __profile_stats_value(PR_VALUE_SMBFWDNAME, count)
+#define SMBfwdname_time __profile_stats_value(PR_VALUE_SMBFWDNAME, time)
+
+       PR_VALUE_SMBCANCELF,
+#define SMBcancelf_count __profile_stats_value(PR_VALUE_SMBCANCELF, count)
+#define SMBcancelf_time __profile_stats_value(PR_VALUE_SMBCANCELF, time)
+
+       PR_VALUE_SMBGETMAC,
+#define SMBgetmac_count __profile_stats_value(PR_VALUE_SMBGETMAC, count)
+#define SMBgetmac_time __profile_stats_value(PR_VALUE_SMBGETMAC, time)
+
+       PR_VALUE_SMBSENDSTRT,
+#define SMBsendstrt_count __profile_stats_value(PR_VALUE_SMBSENDSTRT, count)
+#define SMBsendstrt_time __profile_stats_value(PR_VALUE_SMBSENDSTRT, time)
+
+       PR_VALUE_SMBSENDEND,
+#define SMBsendend_count __profile_stats_value(PR_VALUE_SMBSENDEND, count)
+#define SMBsendend_time __profile_stats_value(PR_VALUE_SMBSENDEND, time)
+
+       PR_VALUE_SMBSENDTXT,
+#define SMBsendtxt_count __profile_stats_value(PR_VALUE_SMBSENDTXT, count)
+#define SMBsendtxt_time __profile_stats_value(PR_VALUE_SMBSENDTXT, time)
+
+       PR_VALUE_SMBINVALID,
+#define SMBinvalid_count __profile_stats_value(PR_VALUE_SMBINVALID, count)
+#define SMBinvalid_time __profile_stats_value(PR_VALUE_SMBINVALID, time)
+
+/* Pathworks setdir command */
+       PR_VALUE_PATHWORKS_SETDIR,
+#define pathworks_setdir_count __profile_stats_value(PR_VALUE_PATHWORKS_SETDIR, count)
+#define pathworks_setdir_time __profile_stats_value(PR_VALUE_PATHWORKS_SETDIR, time)
+
+/* These are the TRANS2 sub commands */
+       PR_VALUE_TRANS2_OPEN,
+#define Trans2_open_count __profile_stats_value(PR_VALUE_TRANS2_OPEN, count)
+#define Trans2_open_time __profile_stats_value(PR_VALUE_TRANS2_OPEN, time)
+
+       PR_VALUE_TRANS2_FINDFIRST,
+#define Trans2_findfirst_count __profile_stats_value(PR_VALUE_TRANS2_FINDFIRST, count)
+#define Trans2_findfirst_time __profile_stats_value(PR_VALUE_TRANS2_FINDFIRST, time)
+
+       PR_VALUE_TRANS2_FINDNEXT,
+#define Trans2_findnext_count __profile_stats_value(PR_VALUE_TRANS2_FINDNEXT, count)
+#define Trans2_findnext_time __profile_stats_value(PR_VALUE_TRANS2_FINDNEXT, time)
+
+       PR_VALUE_TRANS2_QFSINFO,
+#define Trans2_qfsinfo_count __profile_stats_value(PR_VALUE_TRANS2_QFSINFO, count)
+#define Trans2_qfsinfo_time __profile_stats_value(PR_VALUE_TRANS2_QFSINFO, time)
+
+       PR_VALUE_TRANS2_SETFSINFO,
+#define Trans2_setfsinfo_count __profile_stats_value(PR_VALUE_TRANS2_SETFSINFO, count)
+#define Trans2_setfsinfo_time __profile_stats_value(PR_VALUE_TRANS2_SETFSINFO, time)
+
+       PR_VALUE_TRANS2_QPATHINFO,
+#define Trans2_qpathinfo_count __profile_stats_value(PR_VALUE_TRANS2_QPATHINFO, count)
+#define Trans2_qpathinfo_time __profile_stats_value(PR_VALUE_TRANS2_QPATHINFO, time)
+
+       PR_VALUE_TRANS2_SETPATHINFO,
+#define Trans2_setpathinfo_count __profile_stats_value(PR_VALUE_TRANS2_SETPATHINFO, count)
+#define Trans2_setpathinfo_time __profile_stats_value(PR_VALUE_TRANS2_SETPATHINFO, time)
+
+       PR_VALUE_TRANS2_QFILEINFO,
+#define Trans2_qfileinfo_count __profile_stats_value(PR_VALUE_TRANS2_QFILEINFO, count)
+#define Trans2_qfileinfo_time __profile_stats_value(PR_VALUE_TRANS2_QFILEINFO, time)
+
+       PR_VALUE_TRANS2_SETFILEINFO,
+#define Trans2_setfileinfo_count __profile_stats_value(PR_VALUE_TRANS2_SETFILEINFO, count)
+#define Trans2_setfileinfo_time __profile_stats_value(PR_VALUE_TRANS2_SETFILEINFO, time)
+
+       PR_VALUE_TRANS2_FSCTL,
+#define Trans2_fsctl_count __profile_stats_value(PR_VALUE_TRANS2_FSCTL, count)
+#define Trans2_fsctl_time __profile_stats_value(PR_VALUE_TRANS2_FSCTL, time)
+
+       PR_VALUE_TRANS2_IOCTL,
+#define Trans2_ioctl_count __profile_stats_value(PR_VALUE_TRANS2_IOCTL, count)
+#define Trans2_ioctl_time __profile_stats_value(PR_VALUE_TRANS2_IOCTL, time)
+
+       PR_VALUE_TRANS2_FINDNOTIFYFIRST,
+#define Trans2_findnotifyfirst_count __profile_stats_value(PR_VALUE_TRANS2_FINDNOTIFYFIRST, count)
+#define Trans2_findnotifyfirst_time __profile_stats_value(PR_VALUE_TRANS2_FINDNOTIFYFIRST, time)
+
+       PR_VALUE_TRANS2_FINDNOTIFYNEXT,
+#define Trans2_findnotifynext_count __profile_stats_value(PR_VALUE_TRANS2_FINDNOTIFYNEXT, count)
+#define Trans2_findnotifynext_time __profile_stats_value(PR_VALUE_TRANS2_FINDNOTIFYNEXT, time)
+
+       PR_VALUE_TRANS2_MKDIR,
+#define Trans2_mkdir_count __profile_stats_value(PR_VALUE_TRANS2_MKDIR, count)
+#define Trans2_mkdir_time __profile_stats_value(PR_VALUE_TRANS2_MKDIR, time)
+
+       PR_VALUE_TRANS2_SESSION_SETUP,
+#define Trans2_session_setup_count __profile_stats_value(PR_VALUE_TRANS2_SESSION_SETUP, count)
+#define Trans2_session_setup_time __profile_stats_value(PR_VALUE_TRANS2_SESSION_SETUP, time)
+
+       PR_VALUE_TRANS2_GET_DFS_REFERRAL,
+#define Trans2_get_dfs_referral_count __profile_stats_value(PR_VALUE_TRANS2_GET_DFS_REFERRAL, count)
+#define Trans2_get_dfs_referral_time __profile_stats_value(PR_VALUE_TRANS2_GET_DFS_REFERRAL, time)
+
+       PR_VALUE_TRANS2_REPORT_DFS_INCONSISTANCY,
+#define Trans2_report_dfs_inconsistancy_count __profile_stats_value(PR_VALUE_TRANS2_REPORT_DFS_INCONSISTANCY, count)
+#define Trans2_report_dfs_inconsistancy_time __profile_stats_value(PR_VALUE_TRANS2_REPORT_DFS_INCONSISTANCY, time)
+
+/* These are the NT transact sub commands. */
+       PR_VALUE_NT_TRANSACT_CREATE,
+#define NT_transact_create_count __profile_stats_value(PR_VALUE_NT_TRANSACT_CREATE, count)
+#define NT_transact_create_time __profile_stats_value(PR_VALUE_NT_TRANSACT_CREATE, time)
+
+       PR_VALUE_NT_TRANSACT_IOCTL,
+#define NT_transact_ioctl_count __profile_stats_value(PR_VALUE_NT_TRANSACT_IOCTL, count)
+#define NT_transact_ioctl_time __profile_stats_value(PR_VALUE_NT_TRANSACT_IOCTL, time)
+
+       PR_VALUE_NT_TRANSACT_SET_SECURITY_DESC,
+#define NT_transact_set_security_desc_count __profile_stats_value(PR_VALUE_NT_TRANSACT_SET_SECURITY_DESC, count)
+#define NT_transact_set_security_desc_time __profile_stats_value(PR_VALUE_NT_TRANSACT_SET_SECURITY_DESC, time)
+
+       PR_VALUE_NT_TRANSACT_NOTIFY_CHANGE,
+#define NT_transact_notify_change_count __profile_stats_value(PR_VALUE_NT_TRANSACT_NOTIFY_CHANGE, count)
+#define NT_transact_notify_change_time __profile_stats_value(PR_VALUE_NT_TRANSACT_NOTIFY_CHANGE, time)
+
+       PR_VALUE_NT_TRANSACT_RENAME,
+#define NT_transact_rename_count __profile_stats_value(PR_VALUE_NT_TRANSACT_RENAME, count)
+#define NT_transact_rename_time __profile_stats_value(PR_VALUE_NT_TRANSACT_RENAME, time)
+
+       PR_VALUE_NT_TRANSACT_QUERY_SECURITY_DESC,
+#define NT_transact_query_security_desc_count __profile_stats_value(PR_VALUE_NT_TRANSACT_QUERY_SECURITY_DESC, count)
+#define NT_transact_query_security_desc_time __profile_stats_value(PR_VALUE_NT_TRANSACT_QUERY_SECURITY_DESC, time)
+
+       PR_VALUE_NT_TRANSACT_GET_USER_QUOTA,
+#define NT_transact_get_user_quota_count __profile_stats_value(PR_VALUE_NT_TRANSACT_GET_USER_QUOTA, count)
+#define NT_transact_get_user_quota_time __profile_stats_value(PR_VALUE_NT_TRANSACT_GET_USER_QUOTA, time)
+
+       PR_VALUE_NT_TRANSACT_SET_USER_QUOTA,
+#define NT_transact_set_user_quota_count __profile_stats_value(PR_VALUE_NT_TRANSACT_SET_USER_QUOTA, count)
+#define NT_transact_set_user_quota_time __profile_stats_value(PR_VALUE_NT_TRANSACT_SET_USER_QUOTA, time)
+
+/* These are ACL manipulation calls */
+       PR_VALUE_GET_NT_ACL,
+#define get_nt_acl_count __profile_stats_value(PR_VALUE_GET_NT_ACL, count)
+#define get_nt_acl_time __profile_stats_value(PR_VALUE_GET_NT_ACL, time)
+
+       PR_VALUE_FGET_NT_ACL,
+#define fget_nt_acl_count __profile_stats_value(PR_VALUE_FGET_NT_ACL, count)
+#define fget_nt_acl_time __profile_stats_value(PR_VALUE_FGET_NT_ACL, time)
+
+       PR_VALUE_SET_NT_ACL,
+#define set_nt_acl_count __profile_stats_value(PR_VALUE_SET_NT_ACL, count)
+#define set_nt_acl_time __profile_stats_value(PR_VALUE_SET_NT_ACL, time)
+
+       PR_VALUE_FSET_NT_ACL,
+#define fset_nt_acl_count __profile_stats_value(PR_VALUE_FSET_NT_ACL, count)
+#define fset_nt_acl_time __profile_stats_value(PR_VALUE_FSET_NT_ACL, time)
+
+       PR_VALUE_CHMOD_ACL,
+#define chmod_acl_count __profile_stats_value(PR_VALUE_CHMOD_ACL, count)
+#define chmod_acl_time __profile_stats_value(PR_VALUE_CHMOD_ACL, time)
+
+       PR_VALUE_FCHMOD_ACL,
+#define fchmod_acl_count __profile_stats_value(PR_VALUE_FCHMOD_ACL, count)
+#define fchmod_acl_time __profile_stats_value(PR_VALUE_FCHMOD_ACL, time)
+
+/* These are nmbd stats */
+       PR_VALUE_NAME_RELEASE,
+#define name_release_count __profile_stats_value(PR_VALUE_NAME_RELEASE, count)
+#define name_release_time __profile_stats_value(PR_VALUE_NAME_RELEASE, time)
+
+       PR_VALUE_NAME_REFRESH,
+#define name_refresh_count __profile_stats_value(PR_VALUE_NAME_REFRESH, count)
+#define name_refresh_time __profile_stats_value(PR_VALUE_NAME_REFRESH, time)
+
+       PR_VALUE_NAME_REGISTRATION,
+#define name_registration_count __profile_stats_value(PR_VALUE_NAME_REGISTRATION, count)
+#define name_registration_time __profile_stats_value(PR_VALUE_NAME_REGISTRATION, time)
+
+       PR_VALUE_NODE_STATUS,
+#define node_status_count __profile_stats_value(PR_VALUE_NODE_STATUS, count)
+#define node_status_time __profile_stats_value(PR_VALUE_NODE_STATUS, time)
+
+       PR_VALUE_NAME_QUERY,
+#define name_query_count __profile_stats_value(PR_VALUE_NAME_QUERY, count)
+#define name_query_time __profile_stats_value(PR_VALUE_NAME_QUERY, time)
+
+       PR_VALUE_HOST_ANNOUNCE,
+#define host_announce_count __profile_stats_value(PR_VALUE_HOST_ANNOUNCE, count)
+#define host_announce_time __profile_stats_value(PR_VALUE_HOST_ANNOUNCE, time)
+
+       PR_VALUE_WORKGROUP_ANNOUNCE,
+#define workgroup_announce_count __profile_stats_value(PR_VALUE_WORKGROUP_ANNOUNCE, count)
+#define workgroup_announce_time __profile_stats_value(PR_VALUE_WORKGROUP_ANNOUNCE, time)
+
+       PR_VALUE_LOCAL_MASTER_ANNOUNCE,
+#define local_master_announce_count __profile_stats_value(PR_VALUE_LOCAL_MASTER_ANNOUNCE, count)
+#define local_master_announce_time __profile_stats_value(PR_VALUE_LOCAL_MASTER_ANNOUNCE, time)
+
+       PR_VALUE_MASTER_BROWSER_ANNOUNCE,
+#define master_browser_announce_count __profile_stats_value(PR_VALUE_MASTER_BROWSER_ANNOUNCE, count)
+#define master_browser_announce_time __profile_stats_value(PR_VALUE_MASTER_BROWSER_ANNOUNCE, time)
+
+       PR_VALUE_LM_HOST_ANNOUNCE,
+#define lm_host_announce_count __profile_stats_value(PR_VALUE_LM_HOST_ANNOUNCE, count)
+#define lm_host_announce_time __profile_stats_value(PR_VALUE_LM_HOST_ANNOUNCE, time)
+
+       PR_VALUE_GET_BACKUP_LIST,
+#define get_backup_list_count __profile_stats_value(PR_VALUE_GET_BACKUP_LIST, count)
+#define get_backup_list_time __profile_stats_value(PR_VALUE_GET_BACKUP_LIST, time)
+
+       PR_VALUE_RESET_BROWSER,
+#define reset_browser_count __profile_stats_value(PR_VALUE_RESET_BROWSER, count)
+#define reset_browser_time __profile_stats_value(PR_VALUE_RESET_BROWSER, time)
+
+       PR_VALUE_ANNOUNCE_REQUEST,
+#define announce_request_count __profile_stats_value(PR_VALUE_ANNOUNCE_REQUEST, count)
+#define announce_request_time __profile_stats_value(PR_VALUE_ANNOUNCE_REQUEST, time)
+
+       PR_VALUE_LM_ANNOUNCE_REQUEST,
+#define lm_announce_request_count __profile_stats_value(PR_VALUE_LM_ANNOUNCE_REQUEST, count)
+#define lm_announce_request_time __profile_stats_value(PR_VALUE_LM_ANNOUNCE_REQUEST, time)
+
+       PR_VALUE_DOMAIN_LOGON,
+#define domain_logon_count __profile_stats_value(PR_VALUE_DOMAIN_LOGON, count)
+#define domain_logon_time __profile_stats_value(PR_VALUE_DOMAIN_LOGON, time)
+
+       PR_VALUE_SYNC_BROWSE_LISTS,
+#define sync_browse_lists_count __profile_stats_value(PR_VALUE_SYNC_BROWSE_LISTS, count)
+#define sync_browse_lists_time __profile_stats_value(PR_VALUE_SYNC_BROWSE_LISTS, time)
+
+       PR_VALUE_RUN_ELECTIONS,
+#define run_elections_count __profile_stats_value(PR_VALUE_RUN_ELECTIONS, count)
+#define run_elections_time __profile_stats_value(PR_VALUE_RUN_ELECTIONS, time)
+
+       PR_VALUE_ELECTION,
+#define election_count __profile_stats_value(PR_VALUE_ELECTION, count)
+#define election_time __profile_stats_value(PR_VALUE_ELECTION, time)
+
+       /* This mist remain the last value. */
+       PR_VALUE_MAX
+}; /* enum profile_stats_values */
+
+const char * profile_value_name(enum profile_stats_values val);
+
 struct profile_stats {
 /* general counters */
        unsigned smb_count; /* how many SMB packets we have processed */
        unsigned uid_changes; /* how many times we change our effective uid */
-/* system call counters */
-       unsigned syscall_opendir_count;
-       unsigned syscall_opendir_time;
-       unsigned syscall_readdir_count;
-       unsigned syscall_readdir_time;
-       unsigned syscall_seekdir_count;
-       unsigned syscall_seekdir_time;
-       unsigned syscall_telldir_count;
-       unsigned syscall_telldir_time;
-       unsigned syscall_rewinddir_count;
-       unsigned syscall_rewinddir_time;
-       unsigned syscall_mkdir_count;
-       unsigned syscall_mkdir_time;
-       unsigned syscall_rmdir_count;
-       unsigned syscall_rmdir_time;
-       unsigned syscall_closedir_count;
-       unsigned syscall_closedir_time;
-       unsigned syscall_open_count;
-       unsigned syscall_open_time;
-       unsigned syscall_close_count;
-       unsigned syscall_close_time;
-       unsigned syscall_read_count;
-       unsigned syscall_read_time;
-       unsigned syscall_read_bytes;    /* bytes read with read syscall */
-       unsigned syscall_pread_count;
-       unsigned syscall_pread_time;
-       unsigned syscall_pread_bytes;   /* bytes read with pread syscall */
-       unsigned syscall_write_count;
-       unsigned syscall_write_time;
-       unsigned syscall_write_bytes;   /* bytes written with write syscall */
-       unsigned syscall_pwrite_count;
-       unsigned syscall_pwrite_time;
-       unsigned syscall_pwrite_bytes;  /* bytes written with pwrite syscall */
-       unsigned syscall_lseek_count;
-       unsigned syscall_lseek_time;
-       unsigned syscall_sendfile_count;
-       unsigned syscall_sendfile_time;
-       unsigned syscall_sendfile_bytes; /* bytes read with sendfile syscall */
-       unsigned syscall_rename_count;
-       unsigned syscall_rename_time;
-       unsigned syscall_fsync_count;
-       unsigned syscall_fsync_time;
-       unsigned syscall_stat_count;
-       unsigned syscall_stat_time;
-       unsigned syscall_fstat_count;
-       unsigned syscall_fstat_time;
-       unsigned syscall_lstat_count;
-       unsigned syscall_lstat_time;
-       unsigned syscall_unlink_count;
-       unsigned syscall_unlink_time;
-       unsigned syscall_chmod_count;
-       unsigned syscall_chmod_time;
-       unsigned syscall_fchmod_count;
-       unsigned syscall_fchmod_time;
-       unsigned syscall_chown_count;
-       unsigned syscall_chown_time;
-       unsigned syscall_fchown_count;
-       unsigned syscall_fchown_time;
-       unsigned syscall_chdir_count;
-       unsigned syscall_chdir_time;
-       unsigned syscall_getwd_count;
-       unsigned syscall_getwd_time;
-       unsigned syscall_utime_count;
-       unsigned syscall_utime_time;
-       unsigned syscall_ftruncate_count;
-       unsigned syscall_ftruncate_time;
-       unsigned syscall_fcntl_lock_count;
-       unsigned syscall_fcntl_lock_time;
-       unsigned syscall_fcntl_getlock_count;
-       unsigned syscall_fcntl_getlock_time;
-       unsigned syscall_readlink_count;
-       unsigned syscall_readlink_time;
-       unsigned syscall_symlink_count;
-       unsigned syscall_symlink_time;
-       unsigned syscall_link_count;
-       unsigned syscall_link_time;
-       unsigned syscall_mknod_count;
-       unsigned syscall_mknod_time;
-       unsigned syscall_realpath_count;
-       unsigned syscall_realpath_time;
-       unsigned syscall_get_quota_count;
-       unsigned syscall_get_quota_time;
-       unsigned syscall_set_quota_count;
-       unsigned syscall_set_quota_time;
+
+/* system call and protocol operation counters and cumulative times */
+       unsigned count[PR_VALUE_MAX];
+       unsigned time[PR_VALUE_MAX];
+
+/* cumulative byte counts */
+       unsigned syscall_pread_bytes;
+       unsigned syscall_pwrite_bytes;
+       unsigned syscall_read_bytes;
+       unsigned syscall_write_bytes;
+       unsigned syscall_sendfile_bytes;
+
 /* stat cache counters */
        unsigned statcache_lookups;
        unsigned statcache_misses;
        unsigned statcache_hits;
+
 /* write cache counters */
        unsigned writecache_read_hits;
        unsigned writecache_abutted_writes;
@@ -133,265 +743,6 @@ struct profile_stats {
        unsigned writecache_num_perfect_writes;
        unsigned writecache_num_write_caches;
        unsigned writecache_allocated_write_caches;
-/* counters for individual SMB types */
-       unsigned SMBmkdir_count;        /* create directory */
-       unsigned SMBmkdir_time;
-       unsigned SMBrmdir_count;        /* delete directory */
-       unsigned SMBrmdir_time;
-       unsigned SMBopen_count;         /* open file */
-       unsigned SMBopen_time;
-       unsigned SMBcreate_count;       /* create file */
-       unsigned SMBcreate_time;
-       unsigned SMBclose_count;        /* close file */
-       unsigned SMBclose_time;
-       unsigned SMBflush_count;        /* flush file */
-       unsigned SMBflush_time;
-       unsigned SMBunlink_count;       /* delete file */
-       unsigned SMBunlink_time;
-       unsigned SMBmv_count;           /* rename file */
-       unsigned SMBmv_time;
-       unsigned SMBgetatr_count;       /* get file attributes */
-       unsigned SMBgetatr_time;
-       unsigned SMBsetatr_count;       /* set file attributes */
-       unsigned SMBsetatr_time;
-       unsigned SMBread_count;         /* read from file */
-       unsigned SMBread_time;
-       unsigned SMBwrite_count;        /* write to file */
-       unsigned SMBwrite_time;
-       unsigned SMBlock_count;         /* lock byte range */
-       unsigned SMBlock_time;
-       unsigned SMBunlock_count;       /* unlock byte range */
-       unsigned SMBunlock_time;
-       unsigned SMBctemp_count;        /* create temporary file */
-       unsigned SMBctemp_time;
-       /* SMBmknew stats are currently combined with SMBcreate */
-       unsigned SMBmknew_count;        /* make new file */
-       unsigned SMBmknew_time;
-       unsigned SMBchkpth_count;       /* check directory path */
-       unsigned SMBchkpth_time;
-       unsigned SMBexit_count;         /* process exit */
-       unsigned SMBexit_time;
-       unsigned SMBlseek_count;        /* seek */
-       unsigned SMBlseek_time;
-       unsigned SMBlockread_count;     /* Lock a range and read */
-       unsigned SMBlockread_time;
-       unsigned SMBwriteunlock_count;  /* Unlock a range then write */
-       unsigned SMBwriteunlock_time;
-       unsigned SMBreadbraw_count;     /* read a block of data with no smb header */
-       unsigned SMBreadbraw_time;
-       unsigned SMBreadBmpx_count;     /* read block multiplexed */
-       unsigned SMBreadBmpx_time;
-       unsigned SMBreadBs_count;       /* read block (secondary response) */
-       unsigned SMBreadBs_time;
-       unsigned SMBwritebraw_count;    /* write a block of data with no smb header */
-       unsigned SMBwritebraw_time;
-       unsigned SMBwriteBmpx_count;    /* write block multiplexed */
-       unsigned SMBwriteBmpx_time;
-       unsigned SMBwriteBs_count;      /* write block (secondary request) */
-       unsigned SMBwriteBs_time;
-       unsigned SMBwritec_count;       /* secondary write request */
-       unsigned SMBwritec_time;
-       unsigned SMBsetattrE_count;     /* set file attributes expanded */
-       unsigned SMBsetattrE_time;
-       unsigned SMBgetattrE_count;     /* get file attributes expanded */
-       unsigned SMBgetattrE_time;
-       unsigned SMBlockingX_count;     /* lock/unlock byte ranges and X */
-       unsigned SMBlockingX_time;
-       unsigned SMBtrans_count;        /* transaction - name, bytes in/out */
-       unsigned SMBtrans_time;
-       unsigned SMBtranss_count;       /* transaction (secondary request/response) */
-       unsigned SMBtranss_time;
-       unsigned SMBioctl_count;        /* IOCTL */
-       unsigned SMBioctl_time;
-       unsigned SMBioctls_count;       /* IOCTL  (secondary request/response) */
-       unsigned SMBioctls_time;
-       unsigned SMBcopy_count;         /* copy */
-       unsigned SMBcopy_time;
-       unsigned SMBmove_count;         /* move */
-       unsigned SMBmove_time;
-       unsigned SMBecho_count;         /* echo */
-       unsigned SMBecho_time;
-       unsigned SMBwriteclose_count;   /* write a file then close it */
-       unsigned SMBwriteclose_time;
-       unsigned SMBopenX_count;        /* open and X */
-       unsigned SMBopenX_time;
-       unsigned SMBreadX_count;        /* read and X */
-       unsigned SMBreadX_time;
-       unsigned SMBwriteX_count;       /* write and X */
-       unsigned SMBwriteX_time;
-       unsigned SMBtrans2_count;       /* TRANS2 protocol set */
-       unsigned SMBtrans2_time;
-       unsigned SMBtranss2_count;      /* TRANS2 protocol set, secondary command */
-       unsigned SMBtranss2_time;
-       unsigned SMBfindclose_count;    /* Terminate a TRANSACT2_FINDFIRST */
-       unsigned SMBfindclose_time;
-       unsigned SMBfindnclose_count;   /* Terminate a TRANSACT2_FINDNOTIFYFIRST */
-       unsigned SMBfindnclose_time;
-       unsigned SMBtcon_count;         /* tree connect */
-       unsigned SMBtcon_time;
-       unsigned SMBtdis_count;         /* tree disconnect */
-       unsigned SMBtdis_time;
-       unsigned SMBnegprot_count;      /* negotiate protocol */
-       unsigned SMBnegprot_time;
-       unsigned SMBsesssetupX_count;   /* Session Set Up & X (including User Logon) */
-       unsigned SMBsesssetupX_time;
-       unsigned SMBulogoffX_count;     /* user logoff */
-       unsigned SMBulogoffX_time;
-       unsigned SMBtconX_count;        /* tree connect and X*/
-       unsigned SMBtconX_time;
-       unsigned SMBdskattr_count;      /* get disk attributes */
-       unsigned SMBdskattr_time;
-       unsigned SMBsearch_count;       /* search directory */
-       unsigned SMBsearch_time;
-       /* SBMffirst stats combined with SMBsearch */
-       unsigned SMBffirst_count;       /* find first */
-       unsigned SMBffirst_time;
-       /* SBMfunique stats combined with SMBsearch */
-       unsigned SMBfunique_count;      /* find unique */
-       unsigned SMBfunique_time;
-       unsigned SMBfclose_count;       /* find close */
-       unsigned SMBfclose_time;
-       unsigned SMBnttrans_count;      /* NT transact */
-       unsigned SMBnttrans_time;
-       unsigned SMBnttranss_count;     /* NT transact secondary */
-       unsigned SMBnttranss_time;
-       unsigned SMBntcreateX_count;    /* NT create and X */
-       unsigned SMBntcreateX_time;
-       unsigned SMBntcancel_count;     /* NT cancel */
-       unsigned SMBntcancel_time;
-       unsigned SMBntrename_count;     /* NT rename file */
-       unsigned SMBntrename_time;
-       unsigned SMBsplopen_count;      /* open print spool file */
-       unsigned SMBsplopen_time;
-       unsigned SMBsplwr_count;        /* write to print spool file */
-       unsigned SMBsplwr_time;
-       unsigned SMBsplclose_count;     /* close print spool file */
-       unsigned SMBsplclose_time;
-       unsigned SMBsplretq_count;      /* return print queue */
-       unsigned SMBsplretq_time;
-       unsigned SMBsends_count;        /* send single block message */
-       unsigned SMBsends_time;
-       unsigned SMBsendb_count;        /* send broadcast message */
-       unsigned SMBsendb_time;
-       unsigned SMBfwdname_count;      /* forward user name */
-       unsigned SMBfwdname_time;
-       unsigned SMBcancelf_count;      /* cancel forward */
-       unsigned SMBcancelf_time;
-       unsigned SMBgetmac_count;       /* get machine name */
-       unsigned SMBgetmac_time;
-       unsigned SMBsendstrt_count;     /* send start of multi-block message */
-       unsigned SMBsendstrt_time;
-       unsigned SMBsendend_count;      /* send end of multi-block message */
-       unsigned SMBsendend_time;
-       unsigned SMBsendtxt_count;      /* send text of multi-block message */
-       unsigned SMBsendtxt_time;
-       unsigned SMBinvalid_count;      /* invalid command */
-       unsigned SMBinvalid_time;
-/* Pathworks setdir command */
-       unsigned pathworks_setdir_count;
-       unsigned pathworks_setdir_time;
-/* These are the TRANS2 sub commands */
-       unsigned Trans2_open_count;
-       unsigned Trans2_open_time;
-       unsigned Trans2_findfirst_count;
-       unsigned Trans2_findfirst_time;
-       unsigned Trans2_findnext_count;
-       unsigned Trans2_findnext_time;
-       unsigned Trans2_qfsinfo_count;
-       unsigned Trans2_qfsinfo_time;
-       unsigned Trans2_setfsinfo_count;
-       unsigned Trans2_setfsinfo_time;
-       unsigned Trans2_qpathinfo_count;
-       unsigned Trans2_qpathinfo_time;
-       unsigned Trans2_setpathinfo_count;
-       unsigned Trans2_setpathinfo_time;
-       unsigned Trans2_qfileinfo_count;
-       unsigned Trans2_qfileinfo_time;
-       unsigned Trans2_setfileinfo_count;
-       unsigned Trans2_setfileinfo_time;
-       unsigned Trans2_fsctl_count;
-       unsigned Trans2_fsctl_time;
-       unsigned Trans2_ioctl_count;
-       unsigned Trans2_ioctl_time;
-       unsigned Trans2_findnotifyfirst_count;
-       unsigned Trans2_findnotifyfirst_time;
-       unsigned Trans2_findnotifynext_count;
-       unsigned Trans2_findnotifynext_time;
-       unsigned Trans2_mkdir_count;
-       unsigned Trans2_mkdir_time;
-       unsigned Trans2_session_setup_count;
-       unsigned Trans2_session_setup_time;
-       unsigned Trans2_get_dfs_referral_count;
-       unsigned Trans2_get_dfs_referral_time;
-       unsigned Trans2_report_dfs_inconsistancy_count;
-       unsigned Trans2_report_dfs_inconsistancy_time;
-/* These are the NT transact sub commands. */
-       unsigned NT_transact_create_count;
-       unsigned NT_transact_create_time;
-       unsigned NT_transact_ioctl_count;
-       unsigned NT_transact_ioctl_time;
-       unsigned NT_transact_set_security_desc_count;
-       unsigned NT_transact_set_security_desc_time;
-       unsigned NT_transact_notify_change_count;
-       unsigned NT_transact_notify_change_time;
-       unsigned NT_transact_rename_count;
-       unsigned NT_transact_rename_time;
-       unsigned NT_transact_query_security_desc_count;
-       unsigned NT_transact_query_security_desc_time;
-       unsigned NT_transact_get_user_quota_count;
-       unsigned NT_transact_get_user_quota_time;
-       unsigned NT_transact_set_user_quota_count;
-       unsigned NT_transact_set_user_quota_time;
-/* These are ACL manipulation calls */
-       unsigned get_nt_acl_count;
-       unsigned get_nt_acl_time;
-       unsigned fget_nt_acl_count;
-       unsigned fget_nt_acl_time;
-       unsigned set_nt_acl_count;
-       unsigned set_nt_acl_time;
-       unsigned fset_nt_acl_count;
-       unsigned fset_nt_acl_time;
-       unsigned chmod_acl_count;
-       unsigned chmod_acl_time;
-       unsigned fchmod_acl_count;
-       unsigned fchmod_acl_time;
-/* These are nmbd stats */
-       unsigned name_release_count;
-       unsigned name_release_time;
-       unsigned name_refresh_count;
-       unsigned name_refresh_time;
-       unsigned name_registration_count;
-       unsigned name_registration_time;
-       unsigned node_status_count;
-       unsigned node_status_time;
-       unsigned name_query_count;
-       unsigned name_query_time;
-       unsigned host_announce_count;
-       unsigned host_announce_time;
-       unsigned workgroup_announce_count;
-       unsigned workgroup_announce_time;
-       unsigned local_master_announce_count;
-       unsigned local_master_announce_time;
-       unsigned master_browser_announce_count;
-       unsigned master_browser_announce_time;
-       unsigned lm_host_announce_count;
-       unsigned lm_host_announce_time;
-       unsigned get_backup_list_count;
-       unsigned get_backup_list_time;
-       unsigned reset_browser_count;
-       unsigned reset_browser_time;
-       unsigned announce_request_count;
-       unsigned announce_request_time;
-       unsigned lm_announce_request_count;
-       unsigned lm_announce_request_time;
-       unsigned domain_logon_count;
-       unsigned domain_logon_time;
-       unsigned sync_browse_lists_count;
-       unsigned sync_browse_lists_time;
-       unsigned run_elections_count;
-       unsigned run_elections_time;
-       unsigned election_count;
-       unsigned election_time;
 };
 
 struct profile_header {
index 17032ac7accc3382d823cd306842a84419495946..db88ce6ed5640a520aae7e1297c1a2a6c185c6a9 100644 (file)
@@ -114,7 +114,7 @@ void *talloc_parent(const void *ptr);
 void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
 int talloc_free(void *ptr);
 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name);
-void *talloc_steal(const void *new_ctx, const void *ptr);
+/* void *talloc_steal(const void *new_ctx, const void *ptr); */
 off_t talloc_total_size(const void *ptr);
 off_t talloc_total_blocks(const void *ptr);
 void talloc_report_full(const void *ptr, FILE *f);
@@ -128,6 +128,7 @@ char *talloc_strdup(const void *t, const char *p);
 char *talloc_strndup(const void *t, const char *p, size_t n);
 char *talloc_append_string(const void *t, char *orig, const char *append);
 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
 char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
 char *talloc_asprintf_append(char *s,
                             const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
index fb99d8241253797f5734ee05401043baaf79dceb..6ef9e829bccc54b67ac3965619afd47b3f84ac18 100644 (file)
@@ -62,7 +62,9 @@
 /* Changed to version 14 as we had to change DIR to SMB_STRUCT_DIR. JRA */
 /* Changed to version 15 as we added the statvfs call. JRA */
 /* Changed to version 16 as we added the getlock call. JRA */
-#define SMB_VFS_INTERFACE_VERSION 16
+/* Changed to version 17 as we removed redundant connection_struct parameters. --jpeach */
+/* Changed to version 18 to add fsp parameter to the open call -- jpeach */
+#define SMB_VFS_INTERFACE_VERSION 18
 
 
 /* to bug old modules which are trying to compile with the old functions */
@@ -219,29 +221,29 @@ struct vfs_ops {
        struct vfs_fn_pointers {
                /* Disk operations */
                
-               int (*connect_fn)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *service, const char *user);
-               void (*disconnect)(struct vfs_handle_struct *handle, struct connection_struct *conn);
-               SMB_BIG_UINT (*disk_free)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, 
+               int (*connect_fn)(struct vfs_handle_struct *handle, const char *service, const char *user);
+               void (*disconnect)(struct vfs_handle_struct *handle);
+               SMB_BIG_UINT (*disk_free)(struct vfs_handle_struct *handle, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,
                        SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
-               int (*get_quota)(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt);
-               int (*set_quota)(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt);
+               int (*get_quota)(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt);
+               int (*set_quota)(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt);
                int (*get_shadow_copy_data)(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels);
-               int (*statvfs)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, struct vfs_statvfs_struct *statbuf);
+               int (*statvfs)(struct vfs_handle_struct *handle, const char *path, struct vfs_statvfs_struct *statbuf);
                
                /* Directory operations */
                
-               SMB_STRUCT_DIR *(*opendir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, const char *mask, uint32 attributes);
-               SMB_STRUCT_DIRENT *(*readdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dirp);
-               void (*seekdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dirp, long offset);
-               long (*telldir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dirp);
-               void (*rewind_dir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dirp);
-               int (*mkdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode);
-               int (*rmdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path);
-               int (*closedir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dir);
+               SMB_STRUCT_DIR *(*opendir)(struct vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attributes);
+               SMB_STRUCT_DIRENT *(*readdir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp);
+               void (*seekdir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp, long offset);
+               long (*telldir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp);
+               void (*rewind_dir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp);
+               int (*mkdir)(struct vfs_handle_struct *handle, const char *path, mode_t mode);
+               int (*rmdir)(struct vfs_handle_struct *handle, const char *path);
+               int (*closedir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dir);
                
                /* File operations */
                
-               int (*open)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, int flags, mode_t mode);
+               int (*open)(struct vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode);
                int (*close_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd);
                ssize_t (*read)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, void *data, size_t n);
                ssize_t (*pread)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, void *data, size_t n, SMB_OFF_T offset);
@@ -249,27 +251,27 @@ struct vfs_ops {
                ssize_t (*pwrite)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, const void *data, size_t n, SMB_OFF_T offset);
                SMB_OFF_T (*lseek)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset, int whence);
                ssize_t (*sendfile)(struct vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count);
-               int (*rename)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldname, const char *newname);
+               int (*rename)(struct vfs_handle_struct *handle, const char *oldname, const char *newname);
                int (*fsync)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd);
-               int (*stat)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf);
+               int (*stat)(struct vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf);
                int (*fstat)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf);
-               int (*lstat)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf);
-               int (*unlink)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path);
-               int (*chmod)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode);
+               int (*lstat)(struct vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf);
+               int (*unlink)(struct vfs_handle_struct *handle, const char *path);
+               int (*chmod)(struct vfs_handle_struct *handle, const char *path, mode_t mode);
                int (*fchmod)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, mode_t mode);
-               int (*chown)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, uid_t uid, gid_t gid);
+               int (*chown)(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid);
                int (*fchown)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uid_t uid, gid_t gid);
-               int (*chdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path);
-               char *(*getwd)(struct vfs_handle_struct *handle, struct connection_struct *conn, char *buf);
-               int (*utime)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, struct utimbuf *times);
+               int (*chdir)(struct vfs_handle_struct *handle, const char *path);
+               char *(*getwd)(struct vfs_handle_struct *handle, char *buf);
+               int (*utime)(struct vfs_handle_struct *handle, const char *path, struct utimbuf *times);
                int (*ftruncate)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset);
                BOOL (*lock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
                BOOL (*getlock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid);
-               int (*symlink)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldpath, const char *newpath);
-               int (*readlink)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, char *buf, size_t bufsiz);
-               int (*link)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldpath, const char *newpath);
-               int (*mknod)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev);
-               char *(*realpath)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, char *resolved_path);
+               int (*symlink)(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath);
+               int (*readlink)(struct vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz);
+               int (*link)(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath);
+               int (*mknod)(struct vfs_handle_struct *handle, const char *path, mode_t mode, SMB_DEV_T dev);
+               char *(*realpath)(struct vfs_handle_struct *handle, const char *path, char *resolved_path);
                
                /* NT ACL operations. */
                
@@ -280,44 +282,44 @@ struct vfs_ops {
                
                /* POSIX ACL operations. */
                
-               int (*chmod_acl)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *name, mode_t mode);
+               int (*chmod_acl)(struct vfs_handle_struct *handle, const char *name, mode_t mode);
                int (*fchmod_acl)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, mode_t mode);
                
-               int (*sys_acl_get_entry)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p);
-               int (*sys_acl_get_tag_type)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p);
-               int (*sys_acl_get_permset)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p);
-               void * (*sys_acl_get_qualifier)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d);
-               SMB_ACL_T (*sys_acl_get_file)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type);
+               int (*sys_acl_get_entry)(struct vfs_handle_struct *handle, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p);
+               int (*sys_acl_get_tag_type)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p);
+               int (*sys_acl_get_permset)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p);
+               void * (*sys_acl_get_qualifier)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d);
+               SMB_ACL_T (*sys_acl_get_file)(struct vfs_handle_struct *handle, const char *path_p, SMB_ACL_TYPE_T type);
                SMB_ACL_T (*sys_acl_get_fd)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd);
-               int (*sys_acl_clear_perms)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_PERMSET_T permset);
-               int (*sys_acl_add_perm)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
-               char * (*sys_acl_to_text)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen);
-               SMB_ACL_T (*sys_acl_init)(struct vfs_handle_struct *handle, struct connection_struct *conn, int count);
-               int (*sys_acl_create_entry)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry);
-               int (*sys_acl_set_tag_type)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype);
-               int (*sys_acl_set_qualifier)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual);
-               int (*sys_acl_set_permset)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset);
-               int (*sys_acl_valid)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T theacl );
-               int (*sys_acl_set_file)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl);
+               int (*sys_acl_clear_perms)(struct vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset);
+               int (*sys_acl_add_perm)(struct vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
+               char * (*sys_acl_to_text)(struct vfs_handle_struct *handle, SMB_ACL_T theacl, ssize_t *plen);
+               SMB_ACL_T (*sys_acl_init)(struct vfs_handle_struct *handle, int count);
+               int (*sys_acl_create_entry)(struct vfs_handle_struct *handle, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry);
+               int (*sys_acl_set_tag_type)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype);
+               int (*sys_acl_set_qualifier)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, void *qual);
+               int (*sys_acl_set_permset)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset);
+               int (*sys_acl_valid)(struct vfs_handle_struct *handle, SMB_ACL_T theacl );
+               int (*sys_acl_set_file)(struct vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl);
                int (*sys_acl_set_fd)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_ACL_T theacl);
-               int (*sys_acl_delete_def_file)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path);
-               int (*sys_acl_get_perm)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
-               int (*sys_acl_free_text)(struct vfs_handle_struct *handle, struct connection_struct *conn, char *text);
-               int (*sys_acl_free_acl)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T posix_acl);
-               int (*sys_acl_free_qualifier)(struct vfs_handle_struct *handle, struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype);
+               int (*sys_acl_delete_def_file)(struct vfs_handle_struct *handle, const char *path);
+               int (*sys_acl_get_perm)(struct vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
+               int (*sys_acl_free_text)(struct vfs_handle_struct *handle, char *text);
+               int (*sys_acl_free_acl)(struct vfs_handle_struct *handle, SMB_ACL_T posix_acl);
+               int (*sys_acl_free_qualifier)(struct vfs_handle_struct *handle, void *qualifier, SMB_ACL_TAG_T tagtype);
 
                /* EA operations. */
-               ssize_t (*getxattr)(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size);
-               ssize_t (*lgetxattr)(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size);
+               ssize_t (*getxattr)(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size);
+               ssize_t (*lgetxattr)(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size);
                ssize_t (*fgetxattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size);
-               ssize_t (*listxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size);
-               ssize_t (*llistxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size);
+               ssize_t (*listxattr)(struct vfs_handle_struct *handle, const char *path, char *list, size_t size);
+               ssize_t (*llistxattr)(struct vfs_handle_struct *handle, const char *path, char *list, size_t size);
                ssize_t (*flistxattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size);
-               int (*removexattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name);
-               int (*lremovexattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name);
+               int (*removexattr)(struct vfs_handle_struct *handle, const char *path, const char *name);
+               int (*lremovexattr)(struct vfs_handle_struct *handle, const char *path, const char *name);
                int (*fremovexattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int filedes, const char *name);
-               int (*setxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags);
-               int (*lsetxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags);
+               int (*setxattr)(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags);
+               int (*lsetxattr)(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags);
                int (*fsetxattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int filedes, const char *name, const void *value, size_t size, int flags);
 
                /* aio operations */
@@ -530,6 +532,14 @@ typedef struct vfs_statvfs_struct {
        /* NB flags can come from FILE_SYSTEM_DEVICE_INFO call   */
 } vfs_statvfs_struct;
 
+#define VFS_ADD_FSP_EXTENSION(handle, fsp, type) \
+    vfs_add_fsp_extension_notype(handle, (fsp), sizeof(type))
+
+#define VFS_FETCH_FSP_EXTENSION(handle, fsp) \
+    vfs_fetch_fsp_extension(handle, (fsp))
+
+#define VFS_REMOVE_FSP_EXTENSION(handle, fsp) \
+    vfs_remove_fsp_extension((handle), (fsp))
 
 #define SMB_VFS_HANDLE_GET_DATA(handle, datap, type, ret) { \
        if (!(handle)||((datap=(type *)(handle)->data)==NULL)) { \
@@ -562,6 +572,7 @@ typedef struct vfs_statvfs_struct {
 
 #define SMB_VFS_OP(x) ((void *) x)
 
+#define DEFAULT_VFS_MODULE_NAME "/[Default VFS]/"
 
 #include "vfs_macros.h"
 
index e08b386a6ac7014788fd72b0a699e49253906000..2d6f8580f682df718e696166c87768a09b1ea07d 100644 (file)
 ********************************************************************/
 
 /* Disk operations */    
-#define SMB_VFS_CONNECT(conn, service, user) ((conn)->vfs.ops.connect_fn((conn)->vfs.handles.connect_hnd, (conn), (service), (user)))
-#define SMB_VFS_DISCONNECT(conn) ((conn)->vfs.ops.disconnect((conn)->vfs.handles.disconnect, (conn)))
-#define SMB_VFS_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs.ops.disk_free((conn)->vfs.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize)))
-#define SMB_VFS_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.get_quota((conn)->vfs.handles.get_quota, (conn), (qtype), (id), (qt)))
-#define SMB_VFS_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.set_quota((conn)->vfs.handles.set_quota, (conn), (qtype), (id), (qt)))
+#define SMB_VFS_CONNECT(conn, service, user) ((conn)->vfs.ops.connect_fn((conn)->vfs.handles.connect_hnd, (service), (user)))
+#define SMB_VFS_DISCONNECT(conn) ((conn)->vfs.ops.disconnect((conn)->vfs.handles.disconnect))
+#define SMB_VFS_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs.ops.disk_free((conn)->vfs.handles.disk_free, (path), (small_query), (bsize), (dfree), (dsize)))
+#define SMB_VFS_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.get_quota((conn)->vfs.handles.get_quota, (qtype), (id), (qt)))
+#define SMB_VFS_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.set_quota((conn)->vfs.handles.set_quota, (qtype), (id), (qt)))
 #define SMB_VFS_GET_SHADOW_COPY_DATA(fsp,shadow_copy_data,labels) ((fsp)->conn->vfs.ops.get_shadow_copy_data((fsp)->conn->vfs.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels)))
-#define SMB_VFS_STATVFS(conn, path, statbuf) ((conn)->vfs.ops.statvfs((conn)->vfs.handles.statvfs, (conn), (path), (statbuf)))
+#define SMB_VFS_STATVFS(conn, path, statbuf) ((conn)->vfs.ops.statvfs((conn)->vfs.handles.statvfs, (path), (statbuf)))
 
 /* Directory operations */
-#define SMB_VFS_OPENDIR(conn, fname, mask, attr) ((conn)->vfs.ops.opendir((conn)->vfs.handles.opendir, (conn), (fname), (mask), (attr)))
-#define SMB_VFS_READDIR(conn, dirp) ((conn)->vfs.ops.readdir((conn)->vfs.handles.readdir, (conn), (dirp))) 
-#define SMB_VFS_SEEKDIR(conn, dirp, offset) ((conn)->vfs.ops.seekdir((conn)->vfs.handles.seekdir, (conn), (dirp), (offset)))
-#define SMB_VFS_TELLDIR(conn, dirp) ((conn)->vfs.ops.telldir((conn)->vfs.handles.telldir, (conn), (dirp)))
-#define SMB_VFS_REWINDDIR(conn, dirp) ((conn)->vfs.ops.rewind_dir((conn)->vfs.handles.rewind_dir, (conn), (dirp)))
-#define SMB_VFS_MKDIR(conn, path, mode) ((conn)->vfs.ops.mkdir((conn)->vfs.handles.mkdir,(conn), (path), (mode)))
-#define SMB_VFS_RMDIR(conn, path) ((conn)->vfs.ops.rmdir((conn)->vfs.handles.rmdir, (conn), (path)))
-#define SMB_VFS_CLOSEDIR(conn, dir) ((conn)->vfs.ops.closedir((conn)->vfs.handles.closedir, (conn), dir))
+#define SMB_VFS_OPENDIR(conn, fname, mask, attr) ((conn)->vfs.ops.opendir((conn)->vfs.handles.opendir, (fname), (mask), (attr)))
+#define SMB_VFS_READDIR(conn, dirp) ((conn)->vfs.ops.readdir((conn)->vfs.handles.readdir, (dirp)))
+#define SMB_VFS_SEEKDIR(conn, dirp, offset) ((conn)->vfs.ops.seekdir((conn)->vfs.handles.seekdir, (dirp), (offset)))
+#define SMB_VFS_TELLDIR(conn, dirp) ((conn)->vfs.ops.telldir((conn)->vfs.handles.telldir, (dirp)))
+#define SMB_VFS_REWINDDIR(conn, dirp) ((conn)->vfs.ops.rewind_dir((conn)->vfs.handles.rewind_dir, (dirp)))
+#define SMB_VFS_MKDIR(conn, path, mode) ((conn)->vfs.ops.mkdir((conn)->vfs.handles.mkdir,(path), (mode)))
+#define SMB_VFS_RMDIR(conn, path) ((conn)->vfs.ops.rmdir((conn)->vfs.handles.rmdir, (path)))
+#define SMB_VFS_CLOSEDIR(conn, dir) ((conn)->vfs.ops.closedir((conn)->vfs.handles.closedir, dir))
     
 /* File operations */
-#define SMB_VFS_OPEN(conn, fname, flags, mode) ((conn)->vfs.ops.open((conn)->vfs.handles.open, (conn), (fname), (flags), (mode)))
+#define SMB_VFS_OPEN(conn, fname, fsp, flags, mode) ((conn)->vfs.ops.open((conn)->vfs.handles.open, (fname), (fsp), (flags), (mode)))
 #define SMB_VFS_CLOSE(fsp, fd) ((fsp)->conn->vfs.ops.close_fn((fsp)->conn->vfs.handles.close_hnd, (fsp), (fd)))
 #define SMB_VFS_READ(fsp, fd, data, n) ((fsp)->conn->vfs.ops.read((fsp)->conn->vfs.handles.read, (fsp), (fd), (data), (n)))
 #define SMB_VFS_PREAD(fsp, fd, data, n, off) ((fsp)->conn->vfs.ops.pread((fsp)->conn->vfs.handles.pread, (fsp), (fd), (data), (n), (off)))
 #define SMB_VFS_PWRITE(fsp, fd, data, n, off) ((fsp)->conn->vfs.ops.pwrite((fsp)->conn->vfs.handles.pwrite, (fsp), (fd), (data), (n), (off)))
 #define SMB_VFS_LSEEK(fsp, fd, offset, whence) ((fsp)->conn->vfs.ops.lseek((fsp)->conn->vfs.handles.lseek, (fsp), (fd), (offset), (whence)))
 #define SMB_VFS_SENDFILE(tofd, fsp, fromfd, header, offset, count) ((fsp)->conn->vfs.ops.sendfile((fsp)->conn->vfs.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count)))
-#define SMB_VFS_RENAME(conn, old, new) ((conn)->vfs.ops.rename((conn)->vfs.handles.rename, (conn), (old), (new)))
+#define SMB_VFS_RENAME(conn, old, new) ((conn)->vfs.ops.rename((conn)->vfs.handles.rename, (old), (new)))
 #define SMB_VFS_FSYNC(fsp, fd) ((fsp)->conn->vfs.ops.fsync((fsp)->conn->vfs.handles.fsync, (fsp), (fd)))
-#define SMB_VFS_STAT(conn, fname, sbuf) ((conn)->vfs.ops.stat((conn)->vfs.handles.stat, (conn), (fname), (sbuf)))
+#define SMB_VFS_STAT(conn, fname, sbuf) ((conn)->vfs.ops.stat((conn)->vfs.handles.stat, (fname), (sbuf)))
 #define SMB_VFS_FSTAT(fsp, fd, sbuf) ((fsp)->conn->vfs.ops.fstat((fsp)->conn->vfs.handles.fstat, (fsp) ,(fd) ,(sbuf)))
-#define SMB_VFS_LSTAT(conn, path, sbuf) ((conn)->vfs.ops.lstat((conn)->vfs.handles.lstat, (conn), (path), (sbuf)))
-#define SMB_VFS_UNLINK(conn, path) ((conn)->vfs.ops.unlink((conn)->vfs.handles.unlink, (conn), (path)))
-#define SMB_VFS_CHMOD(conn, path, mode) ((conn)->vfs.ops.chmod((conn)->vfs.handles.chmod, (conn), (path), (mode)))
+#define SMB_VFS_LSTAT(conn, path, sbuf) ((conn)->vfs.ops.lstat((conn)->vfs.handles.lstat, (path), (sbuf)))
+#define SMB_VFS_UNLINK(conn, path) ((conn)->vfs.ops.unlink((conn)->vfs.handles.unlink, (path)))
+#define SMB_VFS_CHMOD(conn, path, mode) ((conn)->vfs.ops.chmod((conn)->vfs.handles.chmod, (path), (mode)))
 #define SMB_VFS_FCHMOD(fsp, fd, mode) ((fsp)->conn->vfs.ops.fchmod((fsp)->conn->vfs.handles.fchmod, (fsp), (fd), (mode)))
-#define SMB_VFS_CHOWN(conn, path, uid, gid) ((conn)->vfs.ops.chown((conn)->vfs.handles.chown, (conn), (path), (uid), (gid)))
+#define SMB_VFS_CHOWN(conn, path, uid, gid) ((conn)->vfs.ops.chown((conn)->vfs.handles.chown, (path), (uid), (gid)))
 #define SMB_VFS_FCHOWN(fsp, fd, uid, gid) ((fsp)->conn->vfs.ops.fchown((fsp)->conn->vfs.handles.fchown, (fsp), (fd), (uid), (gid)))
-#define SMB_VFS_CHDIR(conn, path) ((conn)->vfs.ops.chdir((conn)->vfs.handles.chdir, (conn), (path)))
-#define SMB_VFS_GETWD(conn, buf) ((conn)->vfs.ops.getwd((conn)->vfs.handles.getwd, (conn), (buf)))
-#define SMB_VFS_UTIME(conn, path, times) ((conn)->vfs.ops.utime((conn)->vfs.handles.utime, (conn), (path), (times)))
+#define SMB_VFS_CHDIR(conn, path) ((conn)->vfs.ops.chdir((conn)->vfs.handles.chdir, (path)))
+#define SMB_VFS_GETWD(conn, buf) ((conn)->vfs.ops.getwd((conn)->vfs.handles.getwd, (buf)))
+#define SMB_VFS_UTIME(conn, path, times) ((conn)->vfs.ops.utime((conn)->vfs.handles.utime, (path), (times)))
 #define SMB_VFS_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs.ops.ftruncate((fsp)->conn->vfs.handles.ftruncate, (fsp), (fd), (offset)))
 #define SMB_VFS_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs.ops.lock((fsp)->conn->vfs.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
 #define SMB_VFS_GETLOCK(fsp, fd, poffset, pcount, ptype, ppid) ((fsp)->conn->vfs.ops.getlock((fsp)->conn->vfs.handles.getlock, (fsp), (fd) ,(poffset), (pcount), (ptype), (ppid)))
-#define SMB_VFS_SYMLINK(conn, oldpath, newpath) ((conn)->vfs.ops.symlink((conn)->vfs.handles.symlink, (conn), (oldpath), (newpath)))
-#define SMB_VFS_READLINK(conn, path, buf, bufsiz) ((conn)->vfs.ops.readlink((conn)->vfs.handles.readlink, (conn), (path), (buf), (bufsiz)))
-#define SMB_VFS_LINK(conn, oldpath, newpath) ((conn)->vfs.ops.link((conn)->vfs.handles.link, (conn), (oldpath), (newpath)))
-#define SMB_VFS_MKNOD(conn, path, mode, dev) ((conn)->vfs.ops.mknod((conn)->vfs.handles.mknod, (conn), (path), (mode), (dev)))
-#define SMB_VFS_REALPATH(conn, path, resolved_path) ((conn)->vfs.ops.realpath((conn)->vfs.handles.realpath, (conn), (path), (resolved_path)))
+#define SMB_VFS_SYMLINK(conn, oldpath, newpath) ((conn)->vfs.ops.symlink((conn)->vfs.handles.symlink, (oldpath), (newpath)))
+#define SMB_VFS_READLINK(conn, path, buf, bufsiz) ((conn)->vfs.ops.readlink((conn)->vfs.handles.readlink, (path), (buf), (bufsiz)))
+#define SMB_VFS_LINK(conn, oldpath, newpath) ((conn)->vfs.ops.link((conn)->vfs.handles.link, (oldpath), (newpath)))
+#define SMB_VFS_MKNOD(conn, path, mode, dev) ((conn)->vfs.ops.mknod((conn)->vfs.handles.mknod, (path), (mode), (dev)))
+#define SMB_VFS_REALPATH(conn, path, resolved_path) ((conn)->vfs.ops.realpath((conn)->vfs.handles.realpath, (path), (resolved_path)))
 
 /* NT ACL operations. */
 #define SMB_VFS_FGET_NT_ACL(fsp, fd, security_info, ppdesc) ((fsp)->conn->vfs.ops.fget_nt_acl((fsp)->conn->vfs.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc)))
 #define SMB_VFS_SET_NT_ACL(fsp, name, security_info_sent, psd) ((fsp)->conn->vfs.ops.set_nt_acl((fsp)->conn->vfs.handles.set_nt_acl, (fsp), (name), (security_info_sent), (psd)))
 
 /* POSIX ACL operations. */
-#define SMB_VFS_CHMOD_ACL(conn, name, mode) ((conn)->vfs.ops.chmod_acl((conn)->vfs.handles.chmod_acl, (conn), (name), (mode)))
+#define SMB_VFS_CHMOD_ACL(conn, name, mode) ((conn)->vfs.ops.chmod_acl((conn)->vfs.handles.chmod_acl, (name), (mode)))
 #define SMB_VFS_FCHMOD_ACL(fsp, fd, mode) ((fsp)->conn->vfs.ops.fchmod_acl((fsp)->conn->vfs.handles.chmod_acl, (fsp), (fd), (mode)))
 
-#define SMB_VFS_SYS_ACL_GET_ENTRY(conn, theacl, entry_id, entry_p) ((conn)->vfs.ops.sys_acl_get_entry((conn)->vfs.handles.sys_acl_get_entry, (conn), (theacl), (entry_id), (entry_p)))
-#define SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry_d, tag_type_p) ((conn)->vfs.ops.sys_acl_get_tag_type((conn)->vfs.handles.sys_acl_get_tag_type, (conn), (entry_d), (tag_type_p)))
-#define SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry_d, permset_p) ((conn)->vfs.ops.sys_acl_get_permset((conn)->vfs.handles.sys_acl_get_permset, (conn), (entry_d), (permset_p)))
-#define SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry_d) ((conn)->vfs.ops.sys_acl_get_qualifier((conn)->vfs.handles.sys_acl_get_qualifier, (conn), (entry_d)))
-#define SMB_VFS_SYS_ACL_GET_FILE(conn, path_p, type) ((conn)->vfs.ops.sys_acl_get_file((conn)->vfs.handles.sys_acl_get_file, (conn), (path_p), (type)))
+#define SMB_VFS_SYS_ACL_GET_ENTRY(conn, theacl, entry_id, entry_p) ((conn)->vfs.ops.sys_acl_get_entry((conn)->vfs.handles.sys_acl_get_entry, (theacl), (entry_id), (entry_p)))
+#define SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry_d, tag_type_p) ((conn)->vfs.ops.sys_acl_get_tag_type((conn)->vfs.handles.sys_acl_get_tag_type, (entry_d), (tag_type_p)))
+#define SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry_d, permset_p) ((conn)->vfs.ops.sys_acl_get_permset((conn)->vfs.handles.sys_acl_get_permset, (entry_d), (permset_p)))
+#define SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry_d) ((conn)->vfs.ops.sys_acl_get_qualifier((conn)->vfs.handles.sys_acl_get_qualifier, (entry_d)))
+#define SMB_VFS_SYS_ACL_GET_FILE(conn, path_p, type) ((conn)->vfs.ops.sys_acl_get_file((conn)->vfs.handles.sys_acl_get_file, (path_p), (type)))
 #define SMB_VFS_SYS_ACL_GET_FD(fsp, fd) ((fsp)->conn->vfs.ops.sys_acl_get_fd((fsp)->conn->vfs.handles.sys_acl_get_fd, (fsp), (fd)))
-#define SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, permset) ((conn)->vfs.ops.sys_acl_clear_perms((conn)->vfs.handles.sys_acl_clear_perms, (conn), (permset)))
-#define SMB_VFS_SYS_ACL_ADD_PERM(conn, permset, perm) ((conn)->vfs.ops.sys_acl_add_perm((conn)->vfs.handles.sys_acl_add_perm, (conn), (permset), (perm)))
-#define SMB_VFS_SYS_ACL_TO_TEXT(conn, theacl, plen) ((conn)->vfs.ops.sys_acl_to_text((conn)->vfs.handles.sys_acl_to_text, (conn), (theacl), (plen)))
-#define SMB_VFS_SYS_ACL_INIT(conn, count) ((conn)->vfs.ops.sys_acl_init((conn)->vfs.handles.sys_acl_init, (conn), (count)))
-#define SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, pacl, pentry) ((conn)->vfs.ops.sys_acl_create_entry((conn)->vfs.handles.sys_acl_create_entry, (conn), (pacl), (pentry)))
-#define SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, entry, tagtype) ((conn)->vfs.ops.sys_acl_set_tag_type((conn)->vfs.handles.sys_acl_set_tag_type, (conn), (entry), (tagtype)))
-#define SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, entry, qual) ((conn)->vfs.ops.sys_acl_set_qualifier((conn)->vfs.handles.sys_acl_set_qualifier, (conn), (entry), (qual)))
-#define SMB_VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) ((conn)->vfs.ops.sys_acl_set_permset((conn)->vfs.handles.sys_acl_set_permset, (conn), (entry), (permset)))
-#define SMB_VFS_SYS_ACL_VALID(conn, theacl) ((conn)->vfs.ops.sys_acl_valid((conn)->vfs.handles.sys_acl_valid, (conn), (theacl)))
-#define SMB_VFS_SYS_ACL_SET_FILE(conn, name, acltype, theacl) ((conn)->vfs.ops.sys_acl_set_file((conn)->vfs.handles.sys_acl_set_file, (conn), (name), (acltype), (theacl)))
+#define SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, permset) ((conn)->vfs.ops.sys_acl_clear_perms((conn)->vfs.handles.sys_acl_clear_perms, (permset)))
+#define SMB_VFS_SYS_ACL_ADD_PERM(conn, permset, perm) ((conn)->vfs.ops.sys_acl_add_perm((conn)->vfs.handles.sys_acl_add_perm, (permset), (perm)))
+#define SMB_VFS_SYS_ACL_TO_TEXT(conn, theacl, plen) ((conn)->vfs.ops.sys_acl_to_text((conn)->vfs.handles.sys_acl_to_text, (theacl), (plen)))
+#define SMB_VFS_SYS_ACL_INIT(conn, count) ((conn)->vfs.ops.sys_acl_init((conn)->vfs.handles.sys_acl_init, (count)))
+#define SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, pacl, pentry) ((conn)->vfs.ops.sys_acl_create_entry((conn)->vfs.handles.sys_acl_create_entry, (pacl), (pentry)))
+#define SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, entry, tagtype) ((conn)->vfs.ops.sys_acl_set_tag_type((conn)->vfs.handles.sys_acl_set_tag_type, (entry), (tagtype)))
+#define SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, entry, qual) ((conn)->vfs.ops.sys_acl_set_qualifier((conn)->vfs.handles.sys_acl_set_qualifier, (entry), (qual)))
+#define SMB_VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) ((conn)->vfs.ops.sys_acl_set_permset((conn)->vfs.handles.sys_acl_set_permset, (entry), (permset)))
+#define SMB_VFS_SYS_ACL_VALID(conn, theacl) ((conn)->vfs.ops.sys_acl_valid((conn)->vfs.handles.sys_acl_valid, (theacl)))
+#define SMB_VFS_SYS_ACL_SET_FILE(conn, name, acltype, theacl) ((conn)->vfs.ops.sys_acl_set_file((conn)->vfs.handles.sys_acl_set_file, (name), (acltype), (theacl)))
 #define SMB_VFS_SYS_ACL_SET_FD(fsp, fd, theacl) ((fsp)->conn->vfs.ops.sys_acl_set_fd((fsp)->conn->vfs.handles.sys_acl_set_fd, (fsp), (fd), (theacl)))
-#define SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, path) ((conn)->vfs.ops.sys_acl_delete_def_file((conn)->vfs.handles.sys_acl_delete_def_file, (conn), (path)))
-#define SMB_VFS_SYS_ACL_GET_PERM(conn, permset, perm) ((conn)->vfs.ops.sys_acl_get_perm((conn)->vfs.handles.sys_acl_get_perm, (conn), (permset), (perm)))
-#define SMB_VFS_SYS_ACL_FREE_TEXT(conn, text) ((conn)->vfs.ops.sys_acl_free_text((conn)->vfs.handles.sys_acl_free_text, (conn), (text)))
-#define SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl) ((conn)->vfs.ops.sys_acl_free_acl((conn)->vfs.handles.sys_acl_free_acl, (conn), (posix_acl)))
-#define SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, qualifier, tagtype) ((conn)->vfs.ops.sys_acl_free_qualifier((conn)->vfs.handles.sys_acl_free_qualifier, (conn), (qualifier), (tagtype)))
+#define SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, path) ((conn)->vfs.ops.sys_acl_delete_def_file((conn)->vfs.handles.sys_acl_delete_def_file, (path)))
+#define SMB_VFS_SYS_ACL_GET_PERM(conn, permset, perm) ((conn)->vfs.ops.sys_acl_get_perm((conn)->vfs.handles.sys_acl_get_perm, (permset), (perm)))
+#define SMB_VFS_SYS_ACL_FREE_TEXT(conn, text) ((conn)->vfs.ops.sys_acl_free_text((conn)->vfs.handles.sys_acl_free_text, (text)))
+#define SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl) ((conn)->vfs.ops.sys_acl_free_acl((conn)->vfs.handles.sys_acl_free_acl, (posix_acl)))
+#define SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, qualifier, tagtype) ((conn)->vfs.ops.sys_acl_free_qualifier((conn)->vfs.handles.sys_acl_free_qualifier, (qualifier), (tagtype)))
 
 /* EA operations. */
-#define SMB_VFS_GETXATTR(conn,path,name,value,size) ((conn)->vfs.ops.getxattr((conn)->vfs.handles.getxattr,(conn),(path),(name),(value),(size)))
-#define SMB_VFS_LGETXATTR(conn,path,name,value,size) ((conn)->vfs.ops.lgetxattr((conn)->vfs.handles.lgetxattr,(conn),(path),(name),(value),(size)))
+#define SMB_VFS_GETXATTR(conn,path,name,value,size) ((conn)->vfs.ops.getxattr((conn)->vfs.handles.getxattr,(path),(name),(value),(size)))
+#define SMB_VFS_LGETXATTR(conn,path,name,value,size) ((conn)->vfs.ops.lgetxattr((conn)->vfs.handles.lgetxattr,(path),(name),(value),(size)))
 #define SMB_VFS_FGETXATTR(fsp,fd,name,value,size) ((fsp)->conn->vfs.ops.fgetxattr((fsp)->conn->vfs.handles.fgetxattr,(fsp),(fd),(name),(value),(size)))
-#define SMB_VFS_LISTXATTR(conn,path,list,size) ((conn)->vfs.ops.listxattr((conn)->vfs.handles.listxattr,(conn),(path),(list),(size)))
-#define SMB_VFS_LLISTXATTR(conn,path,list,size) ((conn)->vfs.ops.llistxattr((conn)->vfs.handles.llistxattr,(conn),(path),(list),(size)))
+#define SMB_VFS_LISTXATTR(conn,path,list,size) ((conn)->vfs.ops.listxattr((conn)->vfs.handles.listxattr,(path),(list),(size)))
+#define SMB_VFS_LLISTXATTR(conn,path,list,size) ((conn)->vfs.ops.llistxattr((conn)->vfs.handles.llistxattr,(path),(list),(size)))
 #define SMB_VFS_FLISTXATTR(fsp,fd,list,size) ((fsp)->conn->vfs.ops.flistxattr((fsp)->conn->vfs.handles.flistxattr,(fsp),(fd),(list),(size)))
-#define SMB_VFS_REMOVEXATTR(conn,path,name) ((conn)->vfs.ops.removexattr((conn)->vfs.handles.removexattr,(conn),(path),(name)))
-#define SMB_VFS_LREMOVEXATTR(conn,path,name) ((conn)->vfs.ops.lremovexattr((conn)->vfs.handles.lremovexattr,(conn),(path),(name)))
+#define SMB_VFS_REMOVEXATTR(conn,path,name) ((conn)->vfs.ops.removexattr((conn)->vfs.handles.removexattr,(path),(name)))
+#define SMB_VFS_LREMOVEXATTR(conn,path,name) ((conn)->vfs.ops.lremovexattr((conn)->vfs.handles.lremovexattr,(path),(name)))
 #define SMB_VFS_FREMOVEXATTR(fsp,fd,name) ((fsp)->conn->vfs.ops.fremovexattr((fsp)->conn->vfs.handles.fremovexattr,(fsp),(fd),(name)))
-#define SMB_VFS_SETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.setxattr((conn)->vfs.handles.setxattr,(conn),(path),(name),(value),(size),(flags)))
-#define SMB_VFS_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.lsetxattr((conn)->vfs.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags)))
+#define SMB_VFS_SETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.setxattr((conn)->vfs.handles.setxattr,(path),(name),(value),(size),(flags)))
+#define SMB_VFS_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.lsetxattr((conn)->vfs.handles.lsetxattr,(path),(name),(value),(size),(flags)))
 #define SMB_VFS_FSETXATTR(fsp,fd,name,value,size,flags) ((fsp)->conn->vfs.ops.fsetxattr((fsp)->conn->vfs.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags)))
 
 /* AIO operations. */
 ********************************************************************/
 
 /* Disk operations */    
-#define SMB_VFS_OPAQUE_CONNECT(conn, service, user) ((conn)->vfs_opaque.ops.connect_fn((conn)->vfs_opaque.handles.connect_hnd, (conn), (service), (user)))
-#define SMB_VFS_OPAQUE_DISCONNECT(conn) ((conn)->vfs_opaque.ops.disconnect((conn)->vfs_opaque.handles.disconnect, (conn)))
-#define SMB_VFS_OPAQUE_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs_opaque.ops.disk_free((conn)->vfs_opaque.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize)))
-#define SMB_VFS_OPAQUE_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.get_quota((conn)->vfs_opaque.handles.get_quota, (conn), (qtype), (id), (qt)))
-#define SMB_VFS_OPAQUE_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.set_quota((conn)->vfs_opaque.handles.set_quota, (conn), (qtype), (id), (qt)))
+#define SMB_VFS_OPAQUE_CONNECT(conn, service, user) ((conn)->vfs_opaque.ops.connect_fn((conn)->vfs_opaque.handles.connect_hnd, (service), (user)))
+#define SMB_VFS_OPAQUE_DISCONNECT(conn) ((conn)->vfs_opaque.ops.disconnect((conn)->vfs_opaque.handles.disconnect))
+#define SMB_VFS_OPAQUE_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs_opaque.ops.disk_free((conn)->vfs_opaque.handles.disk_free, (path), (small_query), (bsize), (dfree), (dsize)))
+#define SMB_VFS_OPAQUE_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.get_quota((conn)->vfs_opaque.handles.get_quota, (qtype), (id), (qt)))
+#define SMB_VFS_OPAQUE_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.set_quota((conn)->vfs_opaque.handles.set_quota, (qtype), (id), (qt)))
 #define SMB_VFS_OPAQUE_GET_SHADOW_COPY_DATA(fsp,shadow_copy_data,labels) ((fsp)->conn->vfs_opaque.ops.get_shadow_copy_data((fsp)->conn->vfs_opaque.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels)))
-#define SMB_VFS_OPAQUE_STATVFS(conn, path, statbuf) ((conn)->vfs_opaque.ops.statvfs((conn)->vfs_opaque.handles.statvfs, (conn), (path), (statbuf)))
+#define SMB_VFS_OPAQUE_STATVFS(conn, path, statbuf) ((conn)->vfs_opaque.ops.statvfs((conn)->vfs_opaque.handles.statvfs, (path), (statbuf)))
 
 /* Directory operations */
-#define SMB_VFS_OPAQUE_OPENDIR(conn, fname, mask, attr) ((conn)->vfs_opaque.ops.opendir((conn)->vfs_opaque.handles.opendir, (conn), (fname), (mask), (attr)))
-#define SMB_VFS_OPAQUE_READDIR(conn, dirp) ((conn)->vfs_opaque.ops.readdir((conn)->vfs_opaque.handles.readdir, (conn), (dirp))) 
-#define SMB_VFS_OPAQUE_SEEKDIR(conn, dirp, offset) ((conn)->vfs_opaque.ops.seekdir((conn)->vfs_opaque.handles.seekdir, (conn), (dirp), (offset))) 
-#define SMB_VFS_OPAQUE_TELLDIR(conn, dirp) ((conn)->vfs_opaque.ops.telldir((conn)->vfs_opaque.handles.telldir, (conn), (dirp))) 
-#define SMB_VFS_OPAQUE_REWINDDIR(conn, dirp) ((conn)->vfs_opaque.ops.rewind_dir((conn)->vfs_opaque.handles.rewind_dir, (conn), (dirp))) 
-#define SMB_VFS_OPAQUE_MKDIR(conn, path, mode) ((conn)->vfs_opaque.ops.mkdir((conn)->vfs_opaque.handles.mkdir,(conn), (path), (mode)))
-#define SMB_VFS_OPAQUE_RMDIR(conn, path) ((conn)->vfs_opaque.ops.rmdir((conn)->vfs_opaque.handles.rmdir, (conn), (path)))
-#define SMB_VFS_OPAQUE_CLOSEDIR(conn, dir) ((conn)->vfs_opaque.ops.closedir((conn)->vfs_opaque.handles.closedir, (conn), dir))
+#define SMB_VFS_OPAQUE_OPENDIR(conn, fname, mask, attr) ((conn)->vfs_opaque.ops.opendir((conn)->vfs_opaque.handles.opendir, (fname), (mask), (attr)))
+#define SMB_VFS_OPAQUE_READDIR(conn, dirp) ((conn)->vfs_opaque.ops.readdir((conn)->vfs_opaque.handles.readdir, (dirp)))
+#define SMB_VFS_OPAQUE_SEEKDIR(conn, dirp, offset) ((conn)->vfs_opaque.ops.seekdir((conn)->vfs_opaque.handles.seekdir, (dirp), (offset)))
+#define SMB_VFS_OPAQUE_TELLDIR(conn, dirp) ((conn)->vfs_opaque.ops.telldir((conn)->vfs_opaque.handles.telldir, (dirp)))
+#define SMB_VFS_OPAQUE_REWINDDIR(conn, dirp) ((conn)->vfs_opaque.ops.rewind_dir((conn)->vfs_opaque.handles.rewind_dir, (dirp)))
+#define SMB_VFS_OPAQUE_MKDIR(conn, path, mode) ((conn)->vfs_opaque.ops.mkdir((conn)->vfs_opaque.handles.mkdir,(path), (mode)))
+#define SMB_VFS_OPAQUE_RMDIR(conn, path) ((conn)->vfs_opaque.ops.rmdir((conn)->vfs_opaque.handles.rmdir, (path)))
+#define SMB_VFS_OPAQUE_CLOSEDIR(conn, dir) ((conn)->vfs_opaque.ops.closedir((conn)->vfs_opaque.handles.closedir, dir))
     
 /* File operations */
-#define SMB_VFS_OPAQUE_OPEN(conn, fname, flags, mode) ((conn)->vfs_opaque.ops.open((conn)->vfs_opaque.handles.open, (conn), (fname), (flags), (mode)))
+#define SMB_VFS_OPAQUE_OPEN(conn, fname, fsp, flags, mode) ((conn)->vfs_opaque.ops.open((conn)->vfs_opaque.handles.open, (fname), (fsp), (flags), (mode)))
 #define SMB_VFS_OPAQUE_CLOSE(fsp, fd) ((fsp)->conn->vfs_opaque.ops.close_fn((fsp)->conn->vfs_opaque.handles.close_hnd, (fsp), (fd)))
 #define SMB_VFS_OPAQUE_READ(fsp, fd, data, n) ((fsp)->conn->vfs_opaque.ops.read((fsp)->conn->vfs_opaque.handles.read, (fsp), (fd), (data), (n)))
 #define SMB_VFS_OPAQUE_PREAD(fsp, fd, data, n, off) ((fsp)->conn->vfs_opaque.ops.pread((fsp)->conn->vfs_opaque.handles.pread, (fsp), (fd), (data), (n), (off)))
 #define SMB_VFS_OPAQUE_PWRITE(fsp, fd, data, n, off) ((fsp)->conn->vfs_opaque.ops.pwrite((fsp)->conn->vfs_opaque.handles.pwrite, (fsp), (fd), (data), (n), (off)))
 #define SMB_VFS_OPAQUE_LSEEK(fsp, fd, offset, whence) ((fsp)->conn->vfs_opaque.ops.lseek((fsp)->conn->vfs_opaque.handles.lseek, (fsp), (fd), (offset), (whence)))
 #define SMB_VFS_OPAQUE_SENDFILE(tofd, fsp, fromfd, header, offset, count) ((fsp)->conn->vfs_opaque.ops.sendfile((fsp)->conn->vfs_opaque.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count)))
-#define SMB_VFS_OPAQUE_RENAME(conn, old, new) ((conn)->vfs_opaque.ops.rename((conn)->vfs_opaque.handles.rename, (conn), (old), (new)))
+#define SMB_VFS_OPAQUE_RENAME(conn, old, new) ((conn)->vfs_opaque.ops.rename((conn)->vfs_opaque.handles.rename, (old), (new)))
 #define SMB_VFS_OPAQUE_FSYNC(fsp, fd) ((fsp)->conn->vfs_opaque.ops.fsync((fsp)->conn->vfs_opaque.handles.fsync, (fsp), (fd)))
-#define SMB_VFS_OPAQUE_STAT(conn, fname, sbuf) ((conn)->vfs_opaque.ops.stat((conn)->vfs_opaque.handles.stat, (conn), (fname), (sbuf)))
+#define SMB_VFS_OPAQUE_STAT(conn, fname, sbuf) ((conn)->vfs_opaque.ops.stat((conn)->vfs_opaque.handles.stat, (fname), (sbuf)))
 #define SMB_VFS_OPAQUE_FSTAT(fsp, fd, sbuf) ((fsp)->conn->vfs_opaque.ops.fstat((fsp)->conn->vfs_opaque.handles.fstat, (fsp) ,(fd) ,(sbuf)))
-#define SMB_VFS_OPAQUE_LSTAT(conn, path, sbuf) ((conn)->vfs_opaque.ops.lstat((conn)->vfs_opaque.handles.lstat, (conn), (path), (sbuf)))
-#define SMB_VFS_OPAQUE_UNLINK(conn, path) ((conn)->vfs_opaque.ops.unlink((conn)->vfs_opaque.handles.unlink, (conn), (path)))
-#define SMB_VFS_OPAQUE_CHMOD(conn, path, mode) ((conn)->vfs_opaque.ops.chmod((conn)->vfs_opaque.handles.chmod, (conn), (path), (mode)))
+#define SMB_VFS_OPAQUE_LSTAT(conn, path, sbuf) ((conn)->vfs_opaque.ops.lstat((conn)->vfs_opaque.handles.lstat, (path), (sbuf)))
+#define SMB_VFS_OPAQUE_UNLINK(conn, path) ((conn)->vfs_opaque.ops.unlink((conn)->vfs_opaque.handles.unlink, (path)))
+#define SMB_VFS_OPAQUE_CHMOD(conn, path, mode) ((conn)->vfs_opaque.ops.chmod((conn)->vfs_opaque.handles.chmod, (path), (mode)))
 #define SMB_VFS_OPAQUE_FCHMOD(fsp, fd, mode) ((fsp)->conn->vfs_opaque.ops.fchmod((fsp)->conn->vfs_opaque.handles.fchmod, (fsp), (fd), (mode)))
-#define SMB_VFS_OPAQUE_CHOWN(conn, path, uid, gid) ((conn)->vfs_opaque.ops.chown((conn)->vfs_opaque.handles.chown, (conn), (path), (uid), (gid)))
+#define SMB_VFS_OPAQUE_CHOWN(conn, path, uid, gid) ((conn)->vfs_opaque.ops.chown((conn)->vfs_opaque.handles.chown, (path), (uid), (gid)))
 #define SMB_VFS_OPAQUE_FCHOWN(fsp, fd, uid, gid) ((fsp)->conn->vfs_opaque.ops.fchown((fsp)->conn->vfs_opaque.handles.fchown, (fsp), (fd), (uid), (gid)))
-#define SMB_VFS_OPAQUE_CHDIR(conn, path) ((conn)->vfs_opaque.ops.chdir((conn)->vfs_opaque.handles.chdir, (conn), (path)))
-#define SMB_VFS_OPAQUE_GETWD(conn, buf) ((conn)->vfs_opaque.ops.getwd((conn)->vfs_opaque.handles.getwd, (conn), (buf)))
-#define SMB_VFS_OPAQUE_UTIME(conn, path, times) ((conn)->vfs_opaque.ops.utime((conn)->vfs_opaque.handles.utime, (conn), (path), (times)))
+#define SMB_VFS_OPAQUE_CHDIR(conn, path) ((conn)->vfs_opaque.ops.chdir((conn)->vfs_opaque.handles.chdir, (path)))
+#define SMB_VFS_OPAQUE_GETWD(conn, buf) ((conn)->vfs_opaque.ops.getwd((conn)->vfs_opaque.handles.getwd, (buf)))
+#define SMB_VFS_OPAQUE_UTIME(conn, path, times) ((conn)->vfs_opaque.ops.utime((conn)->vfs_opaque.handles.utime, (path), (times)))
 #define SMB_VFS_OPAQUE_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs_opaque.ops.ftruncate((fsp)->conn->vfs_opaque.handles.ftruncate, (fsp), (fd), (offset)))
 #define SMB_VFS_OPAQUE_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
 #define SMB_VFS_OPAQUE_GETLOCK(fsp, fd, poffset, pcount, ptype, ppid) ((fsp)->conn->vfs_opaque.ops.getlock((fsp)->conn->vfs_opaque.handles.getlock, (fsp), (fd), (poffset), (pcount), (ptype), (ppid)))
-#define SMB_VFS_OPAQUE_SYMLINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.symlink((conn)->vfs_opaque.handles.symlink, (conn), (oldpath), (newpath)))
-#define SMB_VFS_OPAQUE_READLINK(conn, path, buf, bufsiz) ((conn)->vfs_opaque.ops.readlink((conn)->vfs_opaque.handles.readlink, (conn), (path), (buf), (bufsiz)))
-#define SMB_VFS_OPAQUE_LINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.link((conn)->vfs_opaque.handles.link, (conn), (oldpath), (newpath)))
-#define SMB_VFS_OPAQUE_MKNOD(conn, path, mode, dev) ((conn)->vfs_opaque.ops.mknod((conn)->vfs_opaque.handles.mknod, (conn), (path), (mode), (dev)))
-#define SMB_VFS_OPAQUE_REALPATH(conn, path, resolved_path) ((conn)->vfs_opaque.ops.realpath((conn)->vfs_opaque.handles.realpath, (conn), (path), (resolved_path)))
+#define SMB_VFS_OPAQUE_SYMLINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.symlink((conn)->vfs_opaque.handles.symlink, (oldpath), (newpath)))
+#define SMB_VFS_OPAQUE_READLINK(conn, path, buf, bufsiz) ((conn)->vfs_opaque.ops.readlink((conn)->vfs_opaque.handles.readlink, (path), (buf), (bufsiz)))
+#define SMB_VFS_OPAQUE_LINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.link((conn)->vfs_opaque.handles.link, (oldpath), (newpath)))
+#define SMB_VFS_OPAQUE_MKNOD(conn, path, mode, dev) ((conn)->vfs_opaque.ops.mknod((conn)->vfs_opaque.handles.mknod, (path), (mode), (dev)))
+#define SMB_VFS_OPAQUE_REALPATH(conn, path, resolved_path) ((conn)->vfs_opaque.ops.realpath((conn)->vfs_opaque.handles.realpath, (path), (resolved_path)))
 
 /* NT ACL operations. */
 #define SMB_VFS_OPAQUE_FGET_NT_ACL(fsp, fd, security_info, ppdesc) ((fsp)->conn->vfs_opaque.ops.fget_nt_acl((fsp)->conn->vfs_opaque.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc)))
 #define SMB_VFS_OPAQUE_SET_NT_ACL(fsp, name, security_info_sent, psd) ((fsp)->conn->vfs_opaque.ops.set_nt_acl((fsp)->conn->vfs_opaque.handles.set_nt_acl, (fsp), (name), (security_info_sent), (psd)))
 
 /* POSIX ACL operations. */
-#define SMB_VFS_OPAQUE_CHMOD_ACL(conn, name, mode) ((conn)->vfs_opaque.ops.chmod_acl((conn)->vfs_opaque.handles.chmod_acl, (conn), (name), (mode)))
+#define SMB_VFS_OPAQUE_CHMOD_ACL(conn, name, mode) ((conn)->vfs_opaque.ops.chmod_acl((conn)->vfs_opaque.handles.chmod_acl, (name), (mode)))
 #define SMB_VFS_OPAQUE_FCHMOD_ACL(fsp, fd, mode) ((fsp)->conn->vfs_opaque.ops.fchmod_acl((fsp)->conn->vfs_opaque.handles.chmod_acl, (fsp), (fd), (mode)))
 
-#define SMB_VFS_OPAQUE_SYS_ACL_GET_ENTRY(conn, theacl, entry_id, entry_p) ((conn)->vfs_opaque.ops.sys_acl_get_entry((conn)->vfs_opaque.handles.sys_acl_get_entry, (conn), (theacl), (entry_id), (entry_p)))
-#define SMB_VFS_OPAQUE_SYS_ACL_GET_TAG_TYPE(conn, entry_d, tag_type_p) ((conn)->vfs_opaque.ops.sys_acl_get_tag_type((conn)->vfs_opaque.handles.sys_acl_get_tag_type, (conn), (entry_d), (tag_type_p)))
-#define SMB_VFS_OPAQUE_SYS_ACL_GET_PERMSET(conn, entry_d, permset_p) ((conn)->vfs_opaque.ops.sys_acl_get_permset((conn)->vfs_opaque.handles.sys_acl_get_permset, (conn), (entry_d), (permset_p)))
-#define SMB_VFS_OPAQUE_SYS_ACL_GET_QUALIFIER(conn, entry_d) ((conn)->vfs_opaque.ops.sys_acl_get_qualifier((conn)->vfs_opaque.handles.sys_acl_get_qualifier, (conn), (entry_d)))
-#define SMB_VFS_OPAQUE_SYS_ACL_GET_FILE(conn, path_p, type) ((conn)->vfs_opaque.ops.sys_acl_get_file((conn)->vfs_opaque.handles.sys_acl_get_file, (conn), (path_p), (type)))
+#define SMB_VFS_OPAQUE_SYS_ACL_GET_ENTRY(conn, theacl, entry_id, entry_p) ((conn)->vfs_opaque.ops.sys_acl_get_entry((conn)->vfs_opaque.handles.sys_acl_get_entry, (theacl), (entry_id), (entry_p)))
+#define SMB_VFS_OPAQUE_SYS_ACL_GET_TAG_TYPE(conn, entry_d, tag_type_p) ((conn)->vfs_opaque.ops.sys_acl_get_tag_type((conn)->vfs_opaque.handles.sys_acl_get_tag_type, (entry_d), (tag_type_p)))
+#define SMB_VFS_OPAQUE_SYS_ACL_GET_PERMSET(conn, entry_d, permset_p) ((conn)->vfs_opaque.ops.sys_acl_get_permset((conn)->vfs_opaque.handles.sys_acl_get_permset, (entry_d), (permset_p)))
+#define SMB_VFS_OPAQUE_SYS_ACL_GET_QUALIFIER(conn, entry_d) ((conn)->vfs_opaque.ops.sys_acl_get_qualifier((conn)->vfs_opaque.handles.sys_acl_get_qualifier, (entry_d)))
+#define SMB_VFS_OPAQUE_SYS_ACL_GET_FILE(conn, path_p, type) ((conn)->vfs_opaque.ops.sys_acl_get_file((conn)->vfs_opaque.handles.sys_acl_get_file, (path_p), (type)))
 #define SMB_VFS_OPAQUE_SYS_ACL_GET_FD(fsp, fd) ((fsp)->conn->vfs_opaque.ops.sys_acl_get_fd((fsp)->conn->vfs_opaque.handles.sys_acl_get_fd, (fsp), (fd)))
-#define SMB_VFS_OPAQUE_SYS_ACL_CLEAR_PERMS(conn, permset) ((conn)->vfs_opaque.ops.sys_acl_clear_perms((conn)->vfs_opaque.handles.sys_acl_clear_perms, (conn), (permset)))
-#define SMB_VFS_OPAQUE_SYS_ACL_ADD_PERM(conn, permset, perm) ((conn)->vfs_opaque.ops.sys_acl_add_perm((conn)->vfs_opaque.handles.sys_acl_add_perm, (conn), (permset), (perm)))
-#define SMB_VFS_OPAQUE_SYS_ACL_TO_TEXT(conn, theacl, plen) ((conn)->vfs_opaque.ops.sys_acl_to_text((conn)->vfs_opaque.handles.sys_acl_to_text, (conn), (theacl), (plen)))
-#define SMB_VFS_OPAQUE_SYS_ACL_INIT(conn, count) ((conn)->vfs_opaque.ops.sys_acl_init((conn)->vfs_opaque.handles.sys_acl_init, (conn), (count)))
-#define SMB_VFS_OPAQUE_SYS_ACL_CREATE_ENTRY(conn, pacl, pentry) ((conn)->vfs_opaque.ops.sys_acl_create_entry((conn)->vfs_opaque.handles.sys_acl_create_entry, (conn), (pacl), (pentry)))
-#define SMB_VFS_OPAQUE_SYS_ACL_SET_TAG_TYPE(conn, entry, tagtype) ((conn)->vfs_opaque.ops.sys_acl_set_tag_type((conn)->vfs_opaque.handles.sys_acl_set_tag_type, (conn), (entry), (tagtype)))
-#define SMB_VFS_OPAQUE_SYS_ACL_SET_QUALIFIER(conn, entry, qual) ((conn)->vfs_opaque.ops.sys_acl_set_qualifier((conn)->vfs_opaque.handles.sys_acl_set_qualifier, (conn), (entry), (qual)))
-#define SMB_VFS_OPAQUE_SYS_ACL_SET_PERMSET(conn, entry, permset) ((conn)->vfs_opaque.ops.sys_acl_set_permset((conn)->vfs_opaque.handles.sys_acl_set_permset, (conn), (entry), (permset)))
-#define SMB_VFS_OPAQUE_SYS_ACL_VALID(conn, theacl) ((conn)->vfs_opaque.ops.sys_acl_valid((conn)->vfs_opaque.handles.sys_acl_valid, (conn), (theacl)))
-#define SMB_VFS_OPAQUE_SYS_ACL_SET_FILE(conn, name, acltype, theacl) ((conn)->vfs_opaque.ops.sys_acl_set_file((conn)->vfs_opaque.handles.sys_acl_set_file, (conn), (name), (acltype), (theacl)))
+#define SMB_VFS_OPAQUE_SYS_ACL_CLEAR_PERMS(conn, permset) ((conn)->vfs_opaque.ops.sys_acl_clear_perms((conn)->vfs_opaque.handles.sys_acl_clear_perms, (permset)))
+#define SMB_VFS_OPAQUE_SYS_ACL_ADD_PERM(conn, permset, perm) ((conn)->vfs_opaque.ops.sys_acl_add_perm((conn)->vfs_opaque.handles.sys_acl_add_perm, (permset), (perm)))
+#define SMB_VFS_OPAQUE_SYS_ACL_TO_TEXT(conn, theacl, plen) ((conn)->vfs_opaque.ops.sys_acl_to_text((conn)->vfs_opaque.handles.sys_acl_to_text, (theacl), (plen)))
+#define SMB_VFS_OPAQUE_SYS_ACL_INIT(conn, count) ((conn)->vfs_opaque.ops.sys_acl_init((conn)->vfs_opaque.handles.sys_acl_init, (count)))
+#define SMB_VFS_OPAQUE_SYS_ACL_CREATE_ENTRY(conn, pacl, pentry) ((conn)->vfs_opaque.ops.sys_acl_create_entry((conn)->vfs_opaque.handles.sys_acl_create_entry, (pacl), (pentry)))
+#define SMB_VFS_OPAQUE_SYS_ACL_SET_TAG_TYPE(conn, entry, tagtype) ((conn)->vfs_opaque.ops.sys_acl_set_tag_type((conn)->vfs_opaque.handles.sys_acl_set_tag_type, (entry), (tagtype)))
+#define SMB_VFS_OPAQUE_SYS_ACL_SET_QUALIFIER(conn, entry, qual) ((conn)->vfs_opaque.ops.sys_acl_set_qualifier((conn)->vfs_opaque.handles.sys_acl_set_qualifier, (entry), (qual)))
+#define SMB_VFS_OPAQUE_SYS_ACL_SET_PERMSET(conn, entry, permset) ((conn)->vfs_opaque.ops.sys_acl_set_permset((conn)->vfs_opaque.handles.sys_acl_set_permset, (entry), (permset)))
+#define SMB_VFS_OPAQUE_SYS_ACL_VALID(conn, theacl) ((conn)->vfs_opaque.ops.sys_acl_valid((conn)->vfs_opaque.handles.sys_acl_valid, (theacl)))
+#define SMB_VFS_OPAQUE_SYS_ACL_SET_FILE(conn, name, acltype, theacl) ((conn)->vfs_opaque.ops.sys_acl_set_file((conn)->vfs_opaque.handles.sys_acl_set_file, (name), (acltype), (theacl)))
 #define SMB_VFS_OPAQUE_SYS_ACL_SET_FD(fsp, fd, theacl) ((fsp)->conn->vfs_opaque.ops.sys_acl_set_fd((fsp)->conn->vfs_opaque.handles.sys_acl_set_fd, (fsp), (fd), (theacl)))
-#define SMB_VFS_OPAQUE_SYS_ACL_DELETE_DEF_FILE(conn, path) ((conn)->vfs_opaque.ops.sys_acl_delete_def_file((conn)->vfs_opaque.handles.sys_acl_delete_def_file, (conn), (path)))
-#define SMB_VFS_OPAQUE_SYS_ACL_GET_PERM(conn, permset, perm) ((conn)->vfs_opaque.ops.sys_acl_get_perm((conn)->vfs_opaque.handles.sys_acl_get_perm, (conn), (permset), (perm)))
-#define SMB_VFS_OPAQUE_SYS_ACL_FREE_TEXT(conn, text) ((conn)->vfs_opaque.ops.sys_acl_free_text((conn)->vfs_opaque.handles.sys_acl_free_text, (conn), (text)))
-#define SMB_VFS_OPAQUE_SYS_ACL_FREE_ACL(conn, posix_acl) ((conn)->vfs_opaque.ops.sys_acl_free_acl((conn)->vfs_opaque.handles.sys_acl_free_acl, (conn), (posix_acl)))
-#define SMB_VFS_OPAQUE_SYS_ACL_FREE_QUALIFIER(conn, qualifier, tagtype) ((conn)->vfs_opaque.ops.sys_acl_free_qualifier((conn)->vfs_opaque.handles.sys_acl_free_qualifier, (conn), (qualifier), (tagtype)))
+#define SMB_VFS_OPAQUE_SYS_ACL_DELETE_DEF_FILE(conn, path) ((conn)->vfs_opaque.ops.sys_acl_delete_def_file((conn)->vfs_opaque.handles.sys_acl_delete_def_file, (path)))
+#define SMB_VFS_OPAQUE_SYS_ACL_GET_PERM(conn, permset, perm) ((conn)->vfs_opaque.ops.sys_acl_get_perm((conn)->vfs_opaque.handles.sys_acl_get_perm, (permset), (perm)))
+#define SMB_VFS_OPAQUE_SYS_ACL_FREE_TEXT(conn, text) ((conn)->vfs_opaque.ops.sys_acl_free_text((conn)->vfs_opaque.handles.sys_acl_free_text, (text)))
+#define SMB_VFS_OPAQUE_SYS_ACL_FREE_ACL(conn, posix_acl) ((conn)->vfs_opaque.ops.sys_acl_free_acl((conn)->vfs_opaque.handles.sys_acl_free_acl, (posix_acl)))
+#define SMB_VFS_OPAQUE_SYS_ACL_FREE_QUALIFIER(conn, qualifier, tagtype) ((conn)->vfs_opaque.ops.sys_acl_free_qualifier((conn)->vfs_opaque.handles.sys_acl_free_qualifier, (qualifier), (tagtype)))
 
 /* EA operations. */
-#define SMB_VFS_OPAQUE_GETXATTR(conn,path,name,value,size) ((conn)->vfs_opaque.ops.getxattr((conn)->vfs_opaque.handles.getxattr,(conn),(path),(name),(value),(size)))
-#define SMB_VFS_OPAQUE_LGETXATTR(conn,path,name,value,size) ((conn)->vfs_opaque.ops.lgetxattr((conn)->vfs_opaque.handles.lgetxattr,(conn),(path),(name),(value),(size)))
+#define SMB_VFS_OPAQUE_GETXATTR(conn,path,name,value,size) ((conn)->vfs_opaque.ops.getxattr((conn)->vfs_opaque.handles.getxattr,(path),(name),(value),(size)))
+#define SMB_VFS_OPAQUE_LGETXATTR(conn,path,name,value,size) ((conn)->vfs_opaque.ops.lgetxattr((conn)->vfs_opaque.handles.lgetxattr,(path),(name),(value),(size)))
 #define SMB_VFS_OPAQUE_FGETXATTR(fsp,fd,name,value,size) ((fsp)->conn->vfs_opaque.ops.fgetxattr((fsp)->conn->vfs_opaque.handles.fgetxattr,(fsp),(fd),(name),(value),(size)))
-#define SMB_VFS_OPAQUE_LISTXATTR(conn,path,list,size) ((conn)->vfs_opaque.ops.listxattr((conn)->vfs_opaque.handles.listxattr,(conn),(path),(list),(size)))
-#define SMB_VFS_OPAQUE_LLISTXATTR(conn,path,list,size) ((conn)->vfs_opaque.ops.llistxattr((conn)->vfs_opaque.handles.llistxattr,(conn),(path),(list),(size)))
+#define SMB_VFS_OPAQUE_LISTXATTR(conn,path,list,size) ((conn)->vfs_opaque.ops.listxattr((conn)->vfs_opaque.handles.listxattr,(path),(list),(size)))
+#define SMB_VFS_OPAQUE_LLISTXATTR(conn,path,list,size) ((conn)->vfs_opaque.ops.llistxattr((conn)->vfs_opaque.handles.llistxattr,(path),(list),(size)))
 #define SMB_VFS_OPAQUE_FLISTXATTR(fsp,fd,list,size) ((fsp)->conn->vfs_opaque.ops.flistxattr((fsp)->conn->vfs_opaque.handles.flistxattr,(fsp),(fd),(list),(size)))
-#define SMB_VFS_OPAQUE_REMOVEXATTR(conn,path,name) ((conn)->vfs_opaque.ops.removexattr((conn)->vfs_opaque.handles.removexattr,(conn),(path),(name)))
-#define SMB_VFS_OPAQUE_LREMOVEXATTR(conn,path,name) ((conn)->vfs_opaque.ops.lremovexattr((conn)->vfs_opaque.handles.lremovexattr,(conn),(path),(name)))
+#define SMB_VFS_OPAQUE_REMOVEXATTR(conn,path,name) ((conn)->vfs_opaque.ops.removexattr((conn)->vfs_opaque.handles.removexattr,(path),(name)))
+#define SMB_VFS_OPAQUE_LREMOVEXATTR(conn,path,name) ((conn)->vfs_opaque.ops.lremovexattr((conn)->vfs_opaque.handles.lremovexattr,(path),(name)))
 #define SMB_VFS_OPAQUE_FREMOVEXATTR(fsp,fd,name) ((fsp)->conn->vfs_opaque.ops.fremovexattr((fsp)->conn->vfs_opaque.handles.fremovexattr,(fsp),(fd),(name)))
-#define SMB_VFS_OPAQUE_SETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.setxattr((conn)->vfs_opaque.handles.setxattr,(conn),(path),(name),(value),(size),(flags)))
-#define SMB_VFS_OPAQUE_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.lsetxattr((conn)->vfs_opaque.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags)))
+#define SMB_VFS_OPAQUE_SETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.setxattr((conn)->vfs_opaque.handles.setxattr,(path),(name),(value),(size),(flags)))
+#define SMB_VFS_OPAQUE_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.lsetxattr((conn)->vfs_opaque.handles.lsetxattr,(path),(name),(value),(size),(flags)))
 #define SMB_VFS_OPAQUE_FSETXATTR(fsp,fd,name,value,size,flags) ((fsp)->conn->vfs_opaque.ops.fsetxattr((fsp)->conn->vfs_opaque.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags)))
 
 /* AIO operations. */
 ********************************************************************/
 
 /* Disk operations */    
-#define SMB_VFS_NEXT_CONNECT(handle, conn, service, user) ((handle)->vfs_next.ops.connect_fn((handle)->vfs_next.handles.connect_hnd, (conn), (service), (user)))
-#define SMB_VFS_NEXT_DISCONNECT(handle, conn) ((handle)->vfs_next.ops.disconnect((handle)->vfs_next.handles.disconnect, (conn)))
-#define SMB_VFS_NEXT_DISK_FREE(handle, conn, path, small_query, bsize, dfree ,dsize) ((handle)->vfs_next.ops.disk_free((handle)->vfs_next.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize)))
-#define SMB_VFS_NEXT_GET_QUOTA(handle, conn, qtype, id, qt) ((handle)->vfs_next.ops.get_quota((handle)->vfs_next.handles.get_quota, (conn), (qtype), (id), (qt)))
-#define SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, qt) ((handle)->vfs_next.ops.set_quota((handle)->vfs_next.handles.set_quota, (conn), (qtype), (id), (qt)))
+#define SMB_VFS_NEXT_CONNECT(handle, service, user) ((handle)->vfs_next.ops.connect_fn((handle)->vfs_next.handles.connect_hnd, (service), (user)))
+#define SMB_VFS_NEXT_DISCONNECT(handle) ((handle)->vfs_next.ops.disconnect((handle)->vfs_next.handles.disconnect))
+#define SMB_VFS_NEXT_DISK_FREE(handle, path, small_query, bsize, dfree ,dsize) ((handle)->vfs_next.ops.disk_free((handle)->vfs_next.handles.disk_free, (path), (small_query), (bsize), (dfree), (dsize)))
+#define SMB_VFS_NEXT_GET_QUOTA(handle, qtype, id, qt) ((handle)->vfs_next.ops.get_quota((handle)->vfs_next.handles.get_quota, (qtype), (id), (qt)))
+#define SMB_VFS_NEXT_SET_QUOTA(handle, qtype, id, qt) ((handle)->vfs_next.ops.set_quota((handle)->vfs_next.handles.set_quota, (qtype), (id), (qt)))
 #define SMB_VFS_NEXT_GET_SHADOW_COPY_DATA(handle, fsp, shadow_copy_data ,labels) ((handle)->vfs_next.ops.get_shadow_copy_data((handle)->vfs_next.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels)))
-#define SMB_VFS_NEXT_STATVFS(handle, conn, path, statbuf) ((handle)->vfs_next.ops.statvfs((handle)->vfs_next.handles.statvfs, (conn), (path), (statbuf)))
+#define SMB_VFS_NEXT_STATVFS(handle, path, statbuf) ((handle)->vfs_next.ops.statvfs((handle)->vfs_next.handles.statvfs, (path), (statbuf)))
 
 /* Directory operations */
-#define SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr) ((handle)->vfs_next.ops.opendir((handle)->vfs_next.handles.opendir, (conn), (fname), (mask), (attr)))
-#define SMB_VFS_NEXT_READDIR(handle, conn, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (conn), (dirp))) 
-#define SMB_VFS_NEXT_SEEKDIR(handle, conn, dirp, offset) ((handle)->vfs_next.ops.seekdir((handle)->vfs_next.handles.seekdir, (conn), (dirp), (offset))) 
-#define SMB_VFS_NEXT_TELLDIR(handle, conn, dirp) ((handle)->vfs_next.ops.telldir((handle)->vfs_next.handles.telldir, (conn), (dirp))) 
-#define SMB_VFS_NEXT_REWINDDIR(handle, conn, dirp) ((handle)->vfs_next.ops.rewind_dir((handle)->vfs_next.handles.rewind_dir, (conn), (dirp))) 
-#define SMB_VFS_NEXT_DIR(handle, conn, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (conn), (dirp))) 
-#define SMB_VFS_NEXT_MKDIR(handle, conn, path, mode) ((handle)->vfs_next.ops.mkdir((handle)->vfs_next.handles.mkdir,(conn), (path), (mode)))
-#define SMB_VFS_NEXT_RMDIR(handle, conn, path) ((handle)->vfs_next.ops.rmdir((handle)->vfs_next.handles.rmdir, (conn), (path)))
-#define SMB_VFS_NEXT_CLOSEDIR(handle, conn, dir) ((handle)->vfs_next.ops.closedir((handle)->vfs_next.handles.closedir, (conn), dir))
+#define SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr) ((handle)->vfs_next.ops.opendir((handle)->vfs_next.handles.opendir, (fname), (mask), (attr)))
+#define SMB_VFS_NEXT_READDIR(handle, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (dirp)))
+#define SMB_VFS_NEXT_SEEKDIR(handle, dirp, offset) ((handle)->vfs_next.ops.seekdir((handle)->vfs_next.handles.seekdir, (dirp), (offset)))
+#define SMB_VFS_NEXT_TELLDIR(handle, dirp) ((handle)->vfs_next.ops.telldir((handle)->vfs_next.handles.telldir, (dirp)))
+#define SMB_VFS_NEXT_REWINDDIR(handle, dirp) ((handle)->vfs_next.ops.rewind_dir((handle)->vfs_next.handles.rewind_dir, (dirp)))
+#define SMB_VFS_NEXT_DIR(handle, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (dirp)))
+#define SMB_VFS_NEXT_MKDIR(handle, path, mode) ((handle)->vfs_next.ops.mkdir((handle)->vfs_next.handles.mkdir,(path), (mode)))
+#define SMB_VFS_NEXT_RMDIR(handle, path) ((handle)->vfs_next.ops.rmdir((handle)->vfs_next.handles.rmdir, (path)))
+#define SMB_VFS_NEXT_CLOSEDIR(handle, dir) ((handle)->vfs_next.ops.closedir((handle)->vfs_next.handles.closedir, dir))
     
 /* File operations */
-#define SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode) ((handle)->vfs_next.ops.open((handle)->vfs_next.handles.open, (conn), (fname), (flags), (mode)))
+#define SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode) ((handle)->vfs_next.ops.open((handle)->vfs_next.handles.open, (fname), (fsp), (flags), (mode)))
 #define SMB_VFS_NEXT_CLOSE(handle, fsp, fd) ((handle)->vfs_next.ops.close_fn((handle)->vfs_next.handles.close_hnd, (fsp), (fd)))
 #define SMB_VFS_NEXT_READ(handle, fsp, fd, data, n) ((handle)->vfs_next.ops.read((handle)->vfs_next.handles.read, (fsp), (fd), (data), (n)))
 #define SMB_VFS_NEXT_PREAD(handle, fsp, fd, data, n, off) ((handle)->vfs_next.ops.pread((handle)->vfs_next.handles.pread, (fsp), (fd), (data), (n), (off)))
 #define SMB_VFS_NEXT_PWRITE(handle, fsp, fd, data, n, off) ((handle)->vfs_next.ops.pwrite((handle)->vfs_next.handles.pwrite, (fsp), (fd), (data), (n), (off)))
 #define SMB_VFS_NEXT_LSEEK(handle, fsp, fd, offset, whence) ((handle)->vfs_next.ops.lseek((handle)->vfs_next.handles.lseek, (fsp), (fd), (offset), (whence)))
 #define SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd, header, offset, count) ((handle)->vfs_next.ops.sendfile((handle)->vfs_next.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count)))
-#define SMB_VFS_NEXT_RENAME(handle, conn, old, new) ((handle)->vfs_next.ops.rename((handle)->vfs_next.handles.rename, (conn), (old), (new)))
+#define SMB_VFS_NEXT_RENAME(handle, old, new) ((handle)->vfs_next.ops.rename((handle)->vfs_next.handles.rename, (old), (new)))
 #define SMB_VFS_NEXT_FSYNC(handle, fsp, fd) ((handle)->vfs_next.ops.fsync((handle)->vfs_next.handles.fsync, (fsp), (fd)))
-#define SMB_VFS_NEXT_STAT(handle, conn, fname, sbuf) ((handle)->vfs_next.ops.stat((handle)->vfs_next.handles.stat, (conn), (fname), (sbuf)))
+#define SMB_VFS_NEXT_STAT(handle, fname, sbuf) ((handle)->vfs_next.ops.stat((handle)->vfs_next.handles.stat, (fname), (sbuf)))
 #define SMB_VFS_NEXT_FSTAT(handle, fsp, fd, sbuf) ((handle)->vfs_next.ops.fstat((handle)->vfs_next.handles.fstat, (fsp) ,(fd) ,(sbuf)))
-#define SMB_VFS_NEXT_LSTAT(handle, conn, path, sbuf) ((handle)->vfs_next.ops.lstat((handle)->vfs_next.handles.lstat, (conn), (path), (sbuf)))
-#define SMB_VFS_NEXT_UNLINK(handle, conn, path) ((handle)->vfs_next.ops.unlink((handle)->vfs_next.handles.unlink, (conn), (path)))
-#define SMB_VFS_NEXT_CHMOD(handle, conn, path, mode) ((handle)->vfs_next.ops.chmod((handle)->vfs_next.handles.chmod, (conn), (path), (mode)))
+#define SMB_VFS_NEXT_LSTAT(handle, path, sbuf) ((handle)->vfs_next.ops.lstat((handle)->vfs_next.handles.lstat, (path), (sbuf)))
+#define SMB_VFS_NEXT_UNLINK(handle, path) ((handle)->vfs_next.ops.unlink((handle)->vfs_next.handles.unlink, (path)))
+#define SMB_VFS_NEXT_CHMOD(handle, path, mode) ((handle)->vfs_next.ops.chmod((handle)->vfs_next.handles.chmod, (path), (mode)))
 #define SMB_VFS_NEXT_FCHMOD(handle, fsp, fd, mode) ((handle)->vfs_next.ops.fchmod((handle)->vfs_next.handles.fchmod, (fsp), (fd), (mode)))
-#define SMB_VFS_NEXT_CHOWN(handle, conn, path, uid, gid) ((handle)->vfs_next.ops.chown((handle)->vfs_next.handles.chown, (conn), (path), (uid), (gid)))
+#define SMB_VFS_NEXT_CHOWN(handle, path, uid, gid) ((handle)->vfs_next.ops.chown((handle)->vfs_next.handles.chown, (path), (uid), (gid)))
 #define SMB_VFS_NEXT_FCHOWN(handle, fsp, fd, uid, gid) ((handle)->vfs_next.ops.fchown((handle)->vfs_next.handles.fchown, (fsp), (fd), (uid), (gid)))
-#define SMB_VFS_NEXT_CHDIR(handle, conn, path) ((handle)->vfs_next.ops.chdir((handle)->vfs_next.handles.chdir, (conn), (path)))
-#define SMB_VFS_NEXT_GETWD(handle, conn, buf) ((handle)->vfs_next.ops.getwd((handle)->vfs_next.handles.getwd, (conn), (buf)))
-#define SMB_VFS_NEXT_UTIME(handle, conn, path, times) ((handle)->vfs_next.ops.utime((handle)->vfs_next.handles.utime, (conn), (path), (times)))
+#define SMB_VFS_NEXT_CHDIR(handle, path) ((handle)->vfs_next.ops.chdir((handle)->vfs_next.handles.chdir, (path)))
+#define SMB_VFS_NEXT_GETWD(handle, buf) ((handle)->vfs_next.ops.getwd((handle)->vfs_next.handles.getwd, (buf)))
+#define SMB_VFS_NEXT_UTIME(handle, path, times) ((handle)->vfs_next.ops.utime((handle)->vfs_next.handles.utime, (path), (times)))
 #define SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset) ((handle)->vfs_next.ops.ftruncate((handle)->vfs_next.handles.ftruncate, (fsp), (fd), (offset)))
 #define SMB_VFS_NEXT_LOCK(handle, fsp, fd, op, offset, count, type) ((handle)->vfs_next.ops.lock((handle)->vfs_next.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
 #define SMB_VFS_NEXT_GETLOCK(handle, fsp, fd, poffset, pcount, ptype, ppid) ((handle)->vfs_next.ops.getlock((handle)->vfs_next.handles.getlock, (fsp), (fd), (poffset), (pcount), (ptype), (ppid)))
-#define SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath) ((handle)->vfs_next.ops.symlink((handle)->vfs_next.handles.symlink, (conn), (oldpath), (newpath)))
-#define SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz) ((handle)->vfs_next.ops.readlink((handle)->vfs_next.handles.readlink, (conn), (path), (buf), (bufsiz)))
-#define SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath) ((handle)->vfs_next.ops.link((handle)->vfs_next.handles.link, (conn), (oldpath), (newpath)))
-#define SMB_VFS_NEXT_MKNOD(handle, conn, path, mode, dev) ((handle)->vfs_next.ops.mknod((handle)->vfs_next.handles.mknod, (conn), (path), (mode), (dev)))
-#define SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path) ((handle)->vfs_next.ops.realpath((handle)->vfs_next.handles.realpath, (conn), (path), (resolved_path)))
+#define SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath) ((handle)->vfs_next.ops.symlink((handle)->vfs_next.handles.symlink, (oldpath), (newpath)))
+#define SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz) ((handle)->vfs_next.ops.readlink((handle)->vfs_next.handles.readlink, (path), (buf), (bufsiz)))
+#define SMB_VFS_NEXT_LINK(handle, oldpath, newpath) ((handle)->vfs_next.ops.link((handle)->vfs_next.handles.link, (oldpath), (newpath)))
+#define SMB_VFS_NEXT_MKNOD(handle, path, mode, dev) ((handle)->vfs_next.ops.mknod((handle)->vfs_next.handles.mknod, (path), (mode), (dev)))
+#define SMB_VFS_NEXT_REALPATH(handle, path, resolved_path) ((handle)->vfs_next.ops.realpath((handle)->vfs_next.handles.realpath, (path), (resolved_path)))
 
 /* NT ACL operations. */
 #define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, fd, security_info, ppdesc) ((handle)->vfs_next.ops.fget_nt_acl((handle)->vfs_next.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc)))
 #define SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, name, security_info_sent, psd) ((handle)->vfs_next.ops.set_nt_acl((handle)->vfs_next.handles.set_nt_acl, (fsp), (name), (security_info_sent), (psd)))
 
 /* POSIX ACL operations. */
-#define SMB_VFS_NEXT_CHMOD_ACL(handle, conn, name, mode) ((handle)->vfs_next.ops.chmod_acl((handle)->vfs_next.handles.chmod_acl, (conn), (name), (mode)))
+#define SMB_VFS_NEXT_CHMOD_ACL(handle, name, mode) ((handle)->vfs_next.ops.chmod_acl((handle)->vfs_next.handles.chmod_acl, (name), (mode)))
 #define SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, fd, mode) ((handle)->vfs_next.ops.fchmod_acl((handle)->vfs_next.handles.chmod_acl, (fsp), (fd), (mode)))
 
-#define SMB_VFS_NEXT_SYS_ACL_GET_ENTRY(handle, conn, theacl, entry_id, entry_p) ((handle)->vfs_next.ops.sys_acl_get_entry((handle)->vfs_next.handles.sys_acl_get_entry, (conn), (theacl), (entry_id), (entry_p)))
-#define SMB_VFS_NEXT_SYS_ACL_GET_TAG_TYPE(handle, conn, entry_d, tag_type_p) ((handle)->vfs_next.ops.sys_acl_get_tag_type((handle)->vfs_next.handles.sys_acl_get_tag_type, (conn), (entry_d), (tag_type_p)))
-#define SMB_VFS_NEXT_SYS_ACL_GET_PERMSET(handle, conn, entry_d, permset_p) ((handle)->vfs_next.ops.sys_acl_get_permset((handle)->vfs_next.handles.sys_acl_get_permset, (conn), (entry_d), (permset_p)))
-#define SMB_VFS_NEXT_SYS_ACL_GET_QUALIFIER(handle, conn, entry_d) ((handle)->vfs_next.ops.sys_acl_get_qualifier((handle)->vfs_next.handles.sys_acl_get_qualifier, (conn), (entry_d)))
-#define SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, path_p, type) ((handle)->vfs_next.ops.sys_acl_get_file((handle)->vfs_next.handles.sys_acl_get_file, (conn), (path_p), (type)))
+#define SMB_VFS_NEXT_SYS_ACL_GET_ENTRY(handle, theacl, entry_id, entry_p) ((handle)->vfs_next.ops.sys_acl_get_entry((handle)->vfs_next.handles.sys_acl_get_entry, (theacl), (entry_id), (entry_p)))
+#define SMB_VFS_NEXT_SYS_ACL_GET_TAG_TYPE(handle, entry_d, tag_type_p) ((handle)->vfs_next.ops.sys_acl_get_tag_type((handle)->vfs_next.handles.sys_acl_get_tag_type, (entry_d), (tag_type_p)))
+#define SMB_VFS_NEXT_SYS_ACL_GET_PERMSET(handle, entry_d, permset_p) ((handle)->vfs_next.ops.sys_acl_get_permset((handle)->vfs_next.handles.sys_acl_get_permset, (entry_d), (permset_p)))
+#define SMB_VFS_NEXT_SYS_ACL_GET_QUALIFIER(handle, entry_d) ((handle)->vfs_next.ops.sys_acl_get_qualifier((handle)->vfs_next.handles.sys_acl_get_qualifier, (entry_d)))
+#define SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, path_p, type) ((handle)->vfs_next.ops.sys_acl_get_file((handle)->vfs_next.handles.sys_acl_get_file, (path_p), (type)))
 #define SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, fd) ((handle)->vfs_next.ops.sys_acl_get_fd((handle)->vfs_next.handles.sys_acl_get_fd, (fsp), (fd)))
-#define SMB_VFS_NEXT_SYS_ACL_CLEAR_PERMS(handle, conn, permset) ((handle)->vfs_next.ops.sys_acl_clear_perms((handle)->vfs_next.handles.sys_acl_clear_perms, (conn), (permset)))
-#define SMB_VFS_NEXT_SYS_ACL_ADD_PERM(handle, conn, permset, perm) ((handle)->vfs_next.ops.sys_acl_add_perm((handle)->vfs_next.handles.sys_acl_add_perm, (conn), (permset), (perm)))
-#define SMB_VFS_NEXT_SYS_ACL_TO_TEXT(handle, conn, theacl, plen) ((handle)->vfs_next.ops.sys_acl_to_text((handle)->vfs_next.handles.sys_acl_to_text, (conn), (theacl), (plen)))
-#define SMB_VFS_NEXT_SYS_ACL_INIT(handle, conn, count) ((handle)->vfs_next.ops.sys_acl_init((handle)->vfs_next.handles.sys_acl_init, (conn), (count)))
-#define SMB_VFS_NEXT_SYS_ACL_CREATE_ENTRY(handle, conn, pacl, pentry) ((handle)->vfs_next.ops.sys_acl_create_entry((handle)->vfs_next.handles.sys_acl_create_entry, (conn), (pacl), (pentry)))
-#define SMB_VFS_NEXT_SYS_ACL_SET_TAG_TYPE(handle, conn, entry, tagtype) ((handle)->vfs_next.ops.sys_acl_set_tag_type((handle)->vfs_next.handles.sys_acl_set_tag_type, (conn), (entry), (tagtype)))
-#define SMB_VFS_NEXT_SYS_ACL_SET_QUALIFIER(handle, conn, entry, qual) ((handle)->vfs_next.ops.sys_acl_set_qualifier((handle)->vfs_next.handles.sys_acl_set_qualifier, (conn), (entry), (qual)))
-#define SMB_VFS_NEXT_SYS_ACL_SET_PERMSET(handle, conn, entry, permset) ((handle)->vfs_next.ops.sys_acl_set_permset((handle)->vfs_next.handles.sys_acl_set_permset, (conn), (entry), (permset)))
-#define SMB_VFS_NEXT_SYS_ACL_VALID(handle, conn, theacl) ((handle)->vfs_next.ops.sys_acl_valid((handle)->vfs_next.handles.sys_acl_valid, (conn), (theacl)))
-#define SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, name, acltype, theacl) ((handle)->vfs_next.ops.sys_acl_set_file((handle)->vfs_next.handles.sys_acl_set_file, (conn), (name), (acltype), (theacl)))
+#define SMB_VFS_NEXT_SYS_ACL_CLEAR_PERMS(handle, permset) ((handle)->vfs_next.ops.sys_acl_clear_perms((handle)->vfs_next.handles.sys_acl_clear_perms, (permset)))
+#define SMB_VFS_NEXT_SYS_ACL_ADD_PERM(handle, permset, perm) ((handle)->vfs_next.ops.sys_acl_add_perm((handle)->vfs_next.handles.sys_acl_add_perm, (permset), (perm)))
+#define SMB_VFS_NEXT_SYS_ACL_TO_TEXT(handle, theacl, plen) ((handle)->vfs_next.ops.sys_acl_to_text((handle)->vfs_next.handles.sys_acl_to_text, (theacl), (plen)))
+#define SMB_VFS_NEXT_SYS_ACL_INIT(handle, count) ((handle)->vfs_next.ops.sys_acl_init((handle)->vfs_next.handles.sys_acl_init, (count)))
+#define SMB_VFS_NEXT_SYS_ACL_CREATE_ENTRY(handle, pacl, pentry) ((handle)->vfs_next.ops.sys_acl_create_entry((handle)->vfs_next.handles.sys_acl_create_entry, (pacl), (pentry)))
+#define SMB_VFS_NEXT_SYS_ACL_SET_TAG_TYPE(handle, entry, tagtype) ((handle)->vfs_next.ops.sys_acl_set_tag_type((handle)->vfs_next.handles.sys_acl_set_tag_type, (entry), (tagtype)))
+#define SMB_VFS_NEXT_SYS_ACL_SET_QUALIFIER(handle, entry, qual) ((handle)->vfs_next.ops.sys_acl_set_qualifier((handle)->vfs_next.handles.sys_acl_set_qualifier, (entry), (qual)))
+#define SMB_VFS_NEXT_SYS_ACL_SET_PERMSET(handle, entry, permset) ((handle)->vfs_next.ops.sys_acl_set_permset((handle)->vfs_next.handles.sys_acl_set_permset, (entry), (permset)))
+#define SMB_VFS_NEXT_SYS_ACL_VALID(handle, theacl) ((handle)->vfs_next.ops.sys_acl_valid((handle)->vfs_next.handles.sys_acl_valid, (theacl)))
+#define SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, name, acltype, theacl) ((handle)->vfs_next.ops.sys_acl_set_file((handle)->vfs_next.handles.sys_acl_set_file, (name), (acltype), (theacl)))
 #define SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, fd, theacl) ((handle)->vfs_next.ops.sys_acl_set_fd((handle)->vfs_next.handles.sys_acl_set_fd, (fsp), (fd), (theacl)))
-#define SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, path) ((handle)->vfs_next.ops.sys_acl_delete_def_file((handle)->vfs_next.handles.sys_acl_delete_def_file, (conn), (path)))
-#define SMB_VFS_NEXT_SYS_ACL_GET_PERM(handle, conn, permset, perm) ((handle)->vfs_next.ops.sys_acl_get_perm((handle)->vfs_next.handles.sys_acl_get_perm, (conn), (permset), (perm)))
-#define SMB_VFS_NEXT_SYS_ACL_FREE_TEXT(handle, conn, text) ((handle)->vfs_next.ops.sys_acl_free_text((handle)->vfs_next.handles.sys_acl_free_text, (conn), (text)))
-#define SMB_VFS_NEXT_SYS_ACL_FREE_ACL(handle, conn, posix_acl) ((handle)->vfs_next.ops.sys_acl_free_acl((handle)->vfs_next.handles.sys_acl_free_acl, (conn), (posix_acl)))
-#define SMB_VFS_NEXT_SYS_ACL_FREE_QUALIFIER(handle, conn, qualifier, tagtype) ((handle)->vfs_next.ops.sys_acl_free_qualifier((handle)->vfs_next.handles.sys_acl_free_qualifier, (conn), (qualifier), (tagtype)))
+#define SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, path) ((handle)->vfs_next.ops.sys_acl_delete_def_file((handle)->vfs_next.handles.sys_acl_delete_def_file, (path)))
+#define SMB_VFS_NEXT_SYS_ACL_GET_PERM(handle, permset, perm) ((handle)->vfs_next.ops.sys_acl_get_perm((handle)->vfs_next.handles.sys_acl_get_perm, (permset), (perm)))
+#define SMB_VFS_NEXT_SYS_ACL_FREE_TEXT(handle, text) ((handle)->vfs_next.ops.sys_acl_free_text((handle)->vfs_next.handles.sys_acl_free_text, (text)))
+#define SMB_VFS_NEXT_SYS_ACL_FREE_ACL(handle, posix_acl) ((handle)->vfs_next.ops.sys_acl_free_acl((handle)->vfs_next.handles.sys_acl_free_acl, (posix_acl)))
+#define SMB_VFS_NEXT_SYS_ACL_FREE_QUALIFIER(handle, qualifier, tagtype) ((handle)->vfs_next.ops.sys_acl_free_qualifier((handle)->vfs_next.handles.sys_acl_free_qualifier, (qualifier), (tagtype)))
 
 /* EA operations. */
-#define SMB_VFS_NEXT_GETXATTR(handle,conn,path,name,value,size) ((handle)->vfs_next.ops.getxattr((handle)->vfs_next.handles.getxattr,(conn),(path),(name),(value),(size)))
-#define SMB_VFS_NEXT_LGETXATTR(handle,conn,path,name,value,size) ((handle)->vfs_next.ops.lgetxattr((handle)->vfs_next.handles.lgetxattr,(conn),(path),(name),(value),(size)))
+#define SMB_VFS_NEXT_GETXATTR(handle,path,name,value,size) ((handle)->vfs_next.ops.getxattr((handle)->vfs_next.handles.getxattr,(path),(name),(value),(size)))
+#define SMB_VFS_NEXT_LGETXATTR(handle,path,name,value,size) ((handle)->vfs_next.ops.lgetxattr((handle)->vfs_next.handles.lgetxattr,(path),(name),(value),(size)))
 #define SMB_VFS_NEXT_FGETXATTR(handle,fsp,fd,name,value,size) ((handle)->vfs_next.ops.fgetxattr((handle)->vfs_next.handles.fgetxattr,(fsp),(fd),(name),(value),(size)))
-#define SMB_VFS_NEXT_LISTXATTR(handle,conn,path,list,size) ((handle)->vfs_next.ops.listxattr((handle)->vfs_next.handles.listxattr,(conn),(path),(list),(size)))
-#define SMB_VFS_NEXT_LLISTXATTR(handle,conn,path,list,size) ((handle)->vfs_next.ops.llistxattr((handle)->vfs_next.handles.llistxattr,(conn),(path),(list),(size)))
+#define SMB_VFS_NEXT_LISTXATTR(handle,path,list,size) ((handle)->vfs_next.ops.listxattr((handle)->vfs_next.handles.listxattr,(path),(list),(size)))
+#define SMB_VFS_NEXT_LLISTXATTR(handle,path,list,size) ((handle)->vfs_next.ops.llistxattr((handle)->vfs_next.handles.llistxattr,(path),(list),(size)))
 #define SMB_VFS_NEXT_FLISTXATTR(handle,fsp,fd,list,size) ((handle)->vfs_next.ops.flistxattr((handle)->vfs_next.handles.flistxattr,(fsp),(fd),(list),(size)))
-#define SMB_VFS_NEXT_REMOVEXATTR(handle,conn,path,name) ((handle)->vfs_next.ops.removexattr((handle)->vfs_next.handles.removexattr,(conn),(path),(name)))
-#define SMB_VFS_NEXT_LREMOVEXATTR(handle,conn,path,name) ((handle)->vfs_next.ops.lremovexattr((handle)->vfs_next.handles.lremovexattr,(conn),(path),(name)))
+#define SMB_VFS_NEXT_REMOVEXATTR(handle,path,name) ((handle)->vfs_next.ops.removexattr((handle)->vfs_next.handles.removexattr,(path),(name)))
+#define SMB_VFS_NEXT_LREMOVEXATTR(handle,path,name) ((handle)->vfs_next.ops.lremovexattr((handle)->vfs_next.handles.lremovexattr,(path),(name)))
 #define SMB_VFS_NEXT_FREMOVEXATTR(handle,fsp,fd,name) ((handle)->vfs_next.ops.fremovexattr((handle)->vfs_next.handles.fremovexattr,(fsp),(fd),(name)))
-#define SMB_VFS_NEXT_SETXATTR(handle,conn,path,name,value,size,flags) ((handle)->vfs_next.ops.setxattr((handle)->vfs_next.handles.setxattr,(conn),(path),(name),(value),(size),(flags)))
-#define SMB_VFS_NEXT_LSETXATTR(handle,conn,path,name,value,size,flags) ((handle)->vfs_next.ops.lsetxattr((handle)->vfs_next.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags)))
+#define SMB_VFS_NEXT_SETXATTR(handle,path,name,value,size,flags) ((handle)->vfs_next.ops.setxattr((handle)->vfs_next.handles.setxattr,(path),(name),(value),(size),(flags)))
+#define SMB_VFS_NEXT_LSETXATTR(handle,path,name,value,size,flags) ((handle)->vfs_next.ops.lsetxattr((handle)->vfs_next.handles.lsetxattr,(path),(name),(value),(size),(flags)))
 #define SMB_VFS_NEXT_FSETXATTR(handle,fsp,fd,name,value,size,flags) ((handle)->vfs_next.ops.fsetxattr((handle)->vfs_next.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags)))
 
 /* AIO operations. */
index 6bf7346fe7f0763e441da70118e4e39c5a8947e0..8d844741f5d7b21ec9ad36f51309dda50a010a88 100644 (file)
@@ -262,10 +262,18 @@ BOOL init_account_policy(void)
                return True;
        }
 
-       tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
-       if (!tdb) {
-               DEBUG(0,("Failed to open account policy database\n"));
-               return False;
+       tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
+       if (!tdb) { /* the account policies files does not exist or open failed, try to create a new one */
+               tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
+               if (!tdb) {
+                       DEBUG(0,("Failed to open account policy database\n"));
+                       return False;
+               }
+               /* creation was successful */
+               /* add AP_MIGRATED_TO_PASSDB speacial key */
+               /* so that you do not need to migrate policies */
+               /* on brand new servers as it does not make sense */
+               account_policy_migrated(True);
        }
 
        /* handle a Samba upgrade */
index 8a304adcf0c80ade7851dc111112e86940cd1781..ea83fdebc254a163282ea183806e4336e18d02e5 100644 (file)
@@ -211,6 +211,7 @@ char *afs_createtoken_str(const char *username, const char *cell)
 
 BOOL afs_login(connection_struct *conn)
 {
+       extern userdom_struct current_user_info;
        extern struct current_user current_user;
        DATA_BLOB ticket;
        pstring afs_username;
@@ -222,7 +223,11 @@ BOOL afs_login(connection_struct *conn)
        struct ClearToken ct;
 
        pstrcpy(afs_username, lp_afs_username_map());
-       standard_sub_conn(conn, afs_username, sizeof(afs_username));
+       standard_sub_advanced(SNUM(conn), conn->user,
+                             conn->connectpath, conn->gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             afs_username, sizeof(afs_username));
 
        user_sid = &current_user.nt_user_token->user_sids[0];
        pstring_sub(afs_username, "%s", sid_string_static(user_sid));
index 097d746a638817d5b012d9fb607089f59757e560..fffdf010a058c65e5005cf5ada51c9aab8411970 100644 (file)
@@ -516,13 +516,14 @@ size_t convert_string(charset_t from, charset_t to,
  **/
 
 size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
-                              void const *src, size_t srclen, void **dest, BOOL allow_bad_conv)
+                              void const *src, size_t srclen, void *dst, BOOL allow_bad_conv)
 {
        size_t i_len, o_len, destlen = MAX(srclen, 512);
        size_t retval;
        const char *inbuf = (const char *)src;
        char *outbuf = NULL, *ob = NULL;
        smb_iconv_t descriptor;
+       void **dest = (void **)dst;
 
        *dest = NULL;
 
@@ -702,9 +703,11 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
  *
  * @returns Size in bytes of the converted string; or -1 in case of error.
  **/
-static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
-                               void const *src, size_t srclen, void **dest, BOOL allow_bad_conv)
+size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
+                            void const *src, size_t srclen, void *dst,
+                            BOOL allow_bad_conv)
 {
+       void **dest = (void **)dst;
        size_t dest_len;
 
        *dest = NULL;
@@ -944,9 +947,9 @@ size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len,
 
        if (flags & STR_TERMINATE) {
                if (src_len == (size_t)-1) {
-                       src_len = strlen(src) + 1;
+                       src_len = strlen((const char *)src) + 1;
                } else {
-                       size_t len = strnlen(src, src_len);
+                       size_t len = strnlen((const char *)src, src_len);
                        if (len < src_len)
                                len++;
                        src_len = len;
@@ -1034,7 +1037,7 @@ size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_
        len += ret;
 
        if (flags & STR_UPPER) {
-               smb_ucs2_t *dest_ucs2 = dest;
+               smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
                size_t i;
                for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) {
                        smb_ucs2_t v = toupper_w(dest_ucs2[i]);
@@ -1178,7 +1181,8 @@ size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_
        if (flags & STR_TERMINATE) {
                /* src_len -1 is the default for null terminated strings. */
                if (src_len != (size_t)-1) {
-                       size_t len = strnlen_w(src, src_len/2);
+                       size_t len = strnlen_w((const smb_ucs2_t *)src,
+                                               src_len/2);
                        if (len < src_len/2)
                                len++;
                        src_len = len*2;
index ccd0d27f47b61a68e13ded9759df9e2b13fb36d1..860ef5ad10f845ff2a6cd441f0407afb9cb2071d 100644 (file)
@@ -102,7 +102,7 @@ void data_blob_free(DATA_BLOB *d)
  Clear a DATA_BLOB's contents
 *******************************************************************/
 
-static void data_blob_clear(DATA_BLOB *d)
+void data_blob_clear(DATA_BLOB *d)
 {
        if (d->data) {
                memset(d->data, 0, d->length);
index 2b6c42b8eb04484c52d78df3fccbb684a31b608c..bf75bdf3d3f516d3c03f397bc02183c602975e13 100644 (file)
@@ -981,7 +981,7 @@ BOOL dbghdr( int level, const char *file, const char *func, int line )
   
                /* Print it all out at once to prevent split syslog output. */
                (void)Debug1( "[%s, %d%s] %s:%s(%d)\n",
-                       timestring(lp_debug_hires_timestamp()), level,
+                       current_timestring(lp_debug_hires_timestamp()), level,
                        header_str, file, func, line );
        }
 
index d29e171be0827e4a6dbcf2ba9533b8618d485080..0c0ed86dd1f8d18a5f3261331f0b8ba42107c4eb 100644 (file)
@@ -123,7 +123,7 @@ static void popt_common_callback(poptContext con,
 }
 
 struct poptOption popt_common_connection[] = {
-       { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback },
+       { NULL, 0, POPT_ARG_CALLBACK, (void *)popt_common_callback },
        { "socket-options", 'O', POPT_ARG_STRING, NULL, 'O', "socket options to use",
          "SOCKETOPTIONS" },
        { "netbiosname", 'n', POPT_ARG_STRING, NULL, 'n', "Primary netbios name", "NETBIOSNAME" },
@@ -134,7 +134,7 @@ struct poptOption popt_common_connection[] = {
 };
 
 struct poptOption popt_common_samba[] = {
-       { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_callback },
+       { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, (void *)popt_common_callback },
        { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" },
        { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternate configuration file", "CONFIGFILE" },
        { "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Base name for log files", "LOGFILEBASE" },
@@ -143,7 +143,7 @@ struct poptOption popt_common_samba[] = {
 };
 
 struct poptOption popt_common_version[] = {
-       { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback },
+       { NULL, 0, POPT_ARG_CALLBACK, (void *)popt_common_callback },
        { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version" },
        POPT_TABLEEND
 };
@@ -248,7 +248,7 @@ static void popt_dynconfig_callback(poptContext con,
 
 const struct poptOption popt_common_dynconfig[] = {
 
-       { NULL, '\0', POPT_ARG_CALLBACK, popt_dynconfig_callback },
+       { NULL, '\0', POPT_ARG_CALLBACK, (void *)popt_dynconfig_callback },
 
        { "sbindir", '\0' , POPT_ARG_STRING, NULL, DYN_SBINDIR,
            "Path to sbin directory", "SBINDIR" },
@@ -515,7 +515,7 @@ static void popt_common_credentials_callback(poptContext con,
 
 
 struct poptOption popt_common_credentials[] = {
-       { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_credentials_callback },
+       { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, (void *)popt_common_credentials_callback },
        { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "USERNAME" },
        { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, 0, "Don't ask for a password" },
        { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" },
index e9c1404d1131976636214842252438e25adc6d74..04c337267fddaeba6b03f80163a8d6cfe8b9e12e 100644 (file)
@@ -411,12 +411,16 @@ _PUBLIC_ int swrap_socket(int domain, int type, int protocol)
                return real_socket(domain, type, protocol);
        }
        
+       si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
+       if (si == NULL) {
+               errno = ENOMEM;
+               return -1;
+       }
+
        fd = real_socket(AF_UNIX, type, 0);
 
        if (fd == -1) return -1;
 
-       si = calloc(1, sizeof(struct socket_info));
-
        si->domain = domain;
        si->type = type;
        si->protocol = protocol;
@@ -457,7 +461,12 @@ _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
                                       parent_si->domain, addr, addrlen);
        if (ret == -1) return ret;
 
-       child_si = malloc(sizeof(struct socket_info));
+       child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
+       if (child_si == NULL) {
+               close(fd);
+               errno = ENOMEM;
+               return -1;
+       }
        memset(child_si, 0, sizeof(*child_si));
 
        child_si->fd = fd;
@@ -466,7 +475,7 @@ _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
        child_si->protocol = parent_si->protocol;
        child_si->bound = 1;
 
-       ret = real_getsockname(fd, &un_my_addr, &un_my_addrlen);
+       ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
        if (ret == -1) return ret;
 
        ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
index ff9deb8a5f0a8d5a150341918c69fe89bba3db2f..430c8029b8f812b669f64631956534d4355061d0 100644 (file)
@@ -415,11 +415,12 @@ static const char *automount_server(const char *user_name)
  don't allow expansions.
 ****************************************************************************/
 
-void standard_sub_basic(const char *smb_name, char *str, size_t len)
+void standard_sub_basic(const char *smb_name, const char *domain_name,
+                       char *str, size_t len)
 {
        char *s;
        
-       if ( (s = alloc_sub_basic( smb_name, str )) != NULL ) {
+       if ( (s = alloc_sub_basic( smb_name, domain_name, str )) != NULL ) {
                strncpy( str, s, len );
        }
        
@@ -432,11 +433,12 @@ void standard_sub_basic(const char *smb_name, char *str, size_t len)
  This function will return an allocated string that have to be freed.
 ****************************************************************************/
 
-char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *str)
+char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name,
+                      const char *domain_name, const char *str)
 {
        char *a, *t;
        
-       if ( (a = alloc_sub_basic(smb_name, str)) == NULL ) {
+       if ( (a = alloc_sub_basic(smb_name, domain_name, str)) == NULL ) {
                return NULL;
        }
        t = talloc_strdup(mem_ctx, a);
@@ -447,7 +449,8 @@ char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *st
 /****************************************************************************
 ****************************************************************************/
 
-char *alloc_sub_basic(const char *smb_name, const char *str)
+char *alloc_sub_basic(const char *smb_name, const char *domain_name,
+                     const char *str)
 {
        char *b, *p, *s, *r, *a_string;
        fstring pidstr;
@@ -463,7 +466,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str)
        
        a_string = SMB_STRDUP(str);
        if (a_string == NULL) {
-               DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
+               DEBUG(0, ("alloc_sub_basic: Out of memory!\n"));
                return NULL;
        }
        
@@ -490,7 +493,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str)
                        } 
                        break;
                case 'D' :
-                       r = strdup_upper(current_user_info.domain);
+                       r = strdup_upper(domain_name);
                        if (r == NULL) {
                                goto error;
                        }
@@ -522,7 +525,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str)
                        a_string = realloc_string_sub(a_string, "%R", remote_proto);
                        break;
                case 'T' :
-                       a_string = realloc_string_sub(a_string, "%T", timestring(False));
+                       a_string = realloc_string_sub(a_string, "%T", current_timestring(False));
                        break;
                case 'a' :
                        a_string = realloc_string_sub(a_string, "%a", remote_arch);
@@ -580,32 +583,20 @@ char *talloc_sub_specified(TALLOC_CTX *mem_ctx,
                        uid_t uid,
                        gid_t gid)
 {
-       char *a, *t;
-               a = alloc_sub_specified(input_string, username, domain, uid, gid);
-       if (!a) {
+       char *a_string;
+       char *ret_string = NULL;
+       char *b, *p, *s;
+       TALLOC_CTX *tmp_ctx;
+
+       if (!(tmp_ctx = talloc_new(mem_ctx))) {
+               DEBUG(0, ("talloc_new failed\n"));
                return NULL;
        }
-       t = talloc_strdup(mem_ctx, a);
-       SAFE_FREE(a);
-       return t;
-}
 
-/****************************************************************************
-****************************************************************************/
-
-char *alloc_sub_specified(const char *input_string,
-                       const char *username,
-                       const char *domain,
-                       uid_t uid,
-                       gid_t gid)
-{
-       char *a_string, *ret_string;
-       char *b, *p, *s;
-
-       a_string = SMB_STRDUP(input_string);
+       a_string = talloc_strdup(tmp_ctx, input_string);
        if (a_string == NULL) {
-               DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
-               return NULL;
+               DEBUG(0, ("talloc_sub_specified: Out of memory!\n"));
+               goto done;
        }
        
        for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
@@ -614,30 +605,42 @@ char *alloc_sub_specified(const char *input_string,
                
                switch (*(p+1)) {
                case 'U' : 
-                       a_string = realloc_string_sub(a_string, "%U", username);
+                       a_string = talloc_string_sub(
+                               tmp_ctx, a_string, "%U", username);
                        break;
                case 'u' : 
-                       a_string = realloc_string_sub(a_string, "%u", username);
+                       a_string = talloc_string_sub(
+                               tmp_ctx, a_string, "%u", username);
                        break;
                case 'G' :
                        if (gid != -1) {
-                               a_string = realloc_string_sub(a_string, "%G", gidtoname(gid));
+                               a_string = talloc_string_sub(
+                                       tmp_ctx, a_string, "%G",
+                                       gidtoname(gid));
                        } else {
-                               a_string = realloc_string_sub(a_string, "%G", "NO_GROUP");
+                               a_string = talloc_string_sub(
+                                       tmp_ctx, a_string,
+                                       "%G", "NO_GROUP");
                        }
                        break;
                case 'g' :
                        if (gid != -1) {
-                               a_string = realloc_string_sub(a_string, "%g", gidtoname(gid));
+                               a_string = talloc_string_sub(
+                                       tmp_ctx, a_string, "%g",
+                                       gidtoname(gid));
                        } else {
-                               a_string = realloc_string_sub(a_string, "%g", "NO_GROUP");
+                               a_string = talloc_string_sub(
+                                       tmp_ctx, a_string, "%g", "NO_GROUP");
                        }
                        break;
                case 'D' :
-                       a_string = realloc_string_sub(a_string, "%D", domain);
+                       a_string = talloc_string_sub(tmp_ctx, a_string,
+                                                    "%D", domain);
                        break;
                case 'N' : 
-                       a_string = realloc_string_sub(a_string, "%N", automount_server(username)); 
+                       a_string = talloc_string_sub(
+                               tmp_ctx, a_string, "%N",
+                               automount_server(username)); 
                        break;
                default: 
                        break;
@@ -645,42 +648,27 @@ char *alloc_sub_specified(const char *input_string,
 
                p++;
                if (a_string == NULL) {
-                       return NULL;
+                       goto done;
                }
        }
 
-       ret_string = alloc_sub_basic(username, a_string);
-       SAFE_FREE(a_string);
-       return ret_string;
-}
+       /* Watch out, using "mem_ctx" here, so all intermediate stuff goes
+        * away with the TALLOC_FREE(tmp_ctx) further down. */
 
-/****************************************************************************
-****************************************************************************/
+       ret_string = talloc_sub_basic(mem_ctx, username, domain, a_string);
 
-char *talloc_sub_advanced(TALLOC_CTX *mem_ctx,
-                       int snum,
-                       const char *user,
-                       const char *connectpath,
-                       gid_t gid,
-                       const char *smb_name,
-                       const char *str)
-{
-       char *a, *t;
-               a = alloc_sub_advanced(snum, user, connectpath, gid, smb_name, str);
-       if (!a) {
-               return NULL;
-       }
-       t = talloc_strdup(mem_ctx, a);
-       SAFE_FREE(a);
-       return t;
+ done:
+       TALLOC_FREE(tmp_ctx);
+       return ret_string;
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-char *alloc_sub_advanced(int snum, const char *user, 
-                                 const char *connectpath, gid_t gid, 
-                                 const char *smb_name, const char *str)
+char *alloc_sub_advanced(const char *servicename, const char *user, 
+                        const char *connectpath, gid_t gid, 
+                        const char *smb_name, const char *domain_name,
+                        const char *str)
 {
        char *a_string, *ret_string;
        char *b, *p, *s, *h;
@@ -707,7 +695,7 @@ char *alloc_sub_advanced(int snum, const char *user,
                        a_string = realloc_string_sub(a_string, "%P", connectpath); 
                        break;
                case 'S': 
-                       a_string = realloc_string_sub(a_string, "%S", lp_servicename(snum)); 
+                       a_string = realloc_string_sub(a_string, "%S", servicename);
                        break;
                case 'g': 
                        a_string = realloc_string_sub(a_string, "%g", gidtoname(gid)); 
@@ -724,7 +712,8 @@ char *alloc_sub_advanced(int snum, const char *user,
                         * "path =" string in [homes] and so needs the
                         * service name, not the username.  */
                case 'p': 
-                       a_string = realloc_string_sub(a_string, "%p", automount_path(lp_servicename(snum))); 
+                       a_string = realloc_string_sub(a_string, "%p",
+                                                     automount_path(servicename)); 
                        break;
                        
                default: 
@@ -737,67 +726,20 @@ char *alloc_sub_advanced(int snum, const char *user,
                }
        }
 
-       ret_string = alloc_sub_basic(smb_name, a_string);
+       ret_string = alloc_sub_basic(smb_name, domain_name, a_string);
        SAFE_FREE(a_string);
        return ret_string;
 }
 
-/****************************************************************************
- Do some standard substitutions in a string.
-****************************************************************************/
-
-void standard_sub_conn(connection_struct *conn, char *str, size_t len)
-{
-       char *s;
-       
-       s = alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath,
-                       conn->gid, smb_user_name, str);
-
-       if ( s ) {
-               strncpy( str, s, len );
-               SAFE_FREE( s );
-       }
-}
-
-/****************************************************************************
-****************************************************************************/
-
-char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *str)
-{
-       return talloc_sub_advanced(mem_ctx, SNUM(conn), conn->user,
-                       conn->connectpath, conn->gid,
-                       smb_user_name, str);
-}
-
-/****************************************************************************
-****************************************************************************/
-
-char *alloc_sub_conn(connection_struct *conn, const char *str)
-{
-       return alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath,
-                       conn->gid, smb_user_name, str);
-}
-
-/****************************************************************************
- Like standard_sub but by snum.
-****************************************************************************/
-
-void standard_sub_snum(int snum, char *str, size_t len)
+void standard_sub_advanced(const char *servicename, const char *user, 
+                          const char *connectpath, gid_t gid, 
+                          const char *smb_name, const char *domain_name,
+                          char *str, size_t len)
 {
-       static uid_t cached_uid = -1;
-       static fstring cached_user;
        char *s;
        
-       /* calling uidtoname() on every substitute would be too expensive, so
-          we cache the result here as nearly every call is for the same uid */
-
-       if (cached_uid != current_user.ut.uid) {
-               fstrcpy(cached_user, uidtoname(current_user.ut.uid));
-               cached_uid = current_user.ut.uid;
-       }
-
-       s = alloc_sub_advanced(snum, cached_user, "", current_user.ut.gid,
-                             smb_user_name, str);
+       s = alloc_sub_advanced(servicename, user, connectpath,
+                              gid, smb_name, domain_name, str);
 
        if ( s ) {
                strncpy( str, s, len );
index 2e5f42307bdf3e09114ef12999ef3e729935d673..24c726b8f75ec6155822c9b430cbd7762437d2d0 100644 (file)
@@ -922,16 +922,94 @@ void sys_endpwent(void)
  Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
 ****************************************************************************/
 
+#ifdef ENABLE_BUILD_FARM_HACKS
+
+/*
+ * In the build farm we want to be able to join machines to the domain. As we
+ * don't have root access, we need to bypass direct access to /etc/passwd
+ * after a user has been created via samr. Fake those users.
+ */
+
+static struct passwd *fake_pwd;
+static int num_fake_pwd;
+
 struct passwd *sys_getpwnam(const char *name)
 {
+       int i;
+
+       for (i=0; i<num_fake_pwd; i++) {
+               if (strcmp(fake_pwd[i].pw_name, name) == 0) {
+                       DEBUG(10, ("Returning fake user %s\n", name));
+                       return &fake_pwd[i];
+               }
+       }
+
        return getpwnam(name);
 }
 
 struct passwd *sys_getpwuid(uid_t uid)
 {
+       int i;
+
+       for (i=0; i<num_fake_pwd; i++) {
+               if (fake_pwd[i].pw_uid == uid) {
+                       DEBUG(10, ("Returning fake user %s\n",
+                                  fake_pwd[i].pw_name));
+                       return &fake_pwd[i];
+               }
+       }
+
        return getpwuid(uid);
 }
 
+void faked_create_user(const char *name)
+{
+       int i;
+       uid_t uid;
+       struct passwd new_pwd;
+
+       for (i=0; i<10; i++) {
+               generate_random_buffer((unsigned char *)&uid,
+                                      sizeof(uid));
+               if (getpwuid(uid) == NULL) {
+                       break;
+               }
+       }
+
+       if (i==10) {
+               /* Weird. No free uid found... */
+               return;
+       }
+
+       new_pwd.pw_name = SMB_STRDUP(name);
+       new_pwd.pw_passwd = SMB_STRDUP("x");
+       new_pwd.pw_uid = uid;
+       new_pwd.pw_gid = 100;
+       new_pwd.pw_gecos = SMB_STRDUP("faked user");
+       new_pwd.pw_dir = SMB_STRDUP("/nodir");
+       new_pwd.pw_shell = SMB_STRDUP("/bin/false");
+
+       ADD_TO_ARRAY(NULL, struct passwd, new_pwd, &fake_pwd,
+                    &num_fake_pwd);
+
+       DEBUG(10, ("Added fake user %s, have %d fake users\n",
+                  name, num_fake_pwd));
+}
+
+#else
+
+struct passwd *sys_getpwnam(const char *name)
+{
+       return getpwnam(name);
+}
+
+struct passwd *sys_getpwuid(uid_t uid)
+{
+       return getpwuid(uid);
+}
+
+#endif
+
 struct group *sys_getgrnam(const char *name)
 {
        return getgrnam(name);
index 51087ef9791ddff39867b9bf896acb7dda4cc45a..9d82441137917eb3270912a25bbfc378d9a4b868 100644 (file)
@@ -85,6 +85,7 @@
 static const void *null_context;
 static void *cleanup_context;
 
+static void *talloc_steal(const void *new_ctx, const void *ptr);
 
 struct talloc_reference_handle {
        struct talloc_reference_handle *next, *prev;
@@ -665,7 +666,7 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n
    ptr on success, or NULL if it could not be transferred.
    passing NULL as ptr will always return NULL with no side effects.
 */
-void *talloc_steal(const void *new_ctx, const void *ptr)
+static void *talloc_steal(const void *new_ctx, const void *ptr)
 {
        struct talloc_chunk *tc, *new_tc;
 
@@ -1138,9 +1139,7 @@ char *talloc_asprintf(const void *t, const char *fmt, ...)
  * accumulating output into a string buffer.
  **/
 
-static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
-
-static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
+char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
 {      
        struct talloc_chunk *tc;
        int len, s_len;
index 6504203a7ad5216de5092f438f99f4100f025adf..3ce45e20714ab9f663500f1cd7c98a4587325d26 100644 (file)
@@ -656,6 +656,7 @@ static BOOL test_type(void)
        return True;
 }
 
+#if 0
 /*
   test steal
 */
@@ -709,6 +710,7 @@ static BOOL test_steal(void)
 
        return True;
 }
+#endif
 
 /*
   test talloc_realloc_fn
@@ -819,7 +821,7 @@ BOOL torture_local_talloc(void)
        ret &= test_misc();
        ret &= test_realloc();
        ret &= test_realloc_child();
-       ret &= test_steal();
+/*     ret &= test_steal(); */
        ret &= test_unref_reparent();
        ret &= test_realloc_fn();
        ret &= test_type();
index 9a539d415e880414c2991b86234d2facc61c77ff..0bfdfac856bca89b605136e00a2e8840c65711f7 100644 (file)
@@ -635,7 +635,7 @@ char *http_timestring(time_t t)
  Return the date and time as a string
 ****************************************************************************/
 
-char *timestring(BOOL hires)
+char *current_timestring(BOOL hires)
 {
        static fstring TimeBuf;
        struct timeval tp;
@@ -1056,6 +1056,51 @@ struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs)
 }
 #endif
 
+
+/**
+ Return the date and time as a string
+**/
+char *timestring(TALLOC_CTX *mem_ctx, time_t t)
+{
+       char *TimeBuf;
+       char tempTime[80];
+       struct tm *tm;
+
+       tm = localtime(&t);
+       if (!tm) {
+               return talloc_asprintf(mem_ctx,
+                                      "%ld seconds since the Epoch",
+                                      (long)t);
+       }
+
+#ifdef HAVE_STRFTIME
+       /* some versions of gcc complain about using %c. This is a bug
+          in the gcc warning, not a bug in this code. See a recent
+          strftime() manual page for details.
+        */
+       strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm);
+       TimeBuf = talloc_strdup(mem_ctx, tempTime);
+#else
+       TimeBuf = talloc_strdup(mem_ctx, asctime(tm));
+#endif
+
+       return TimeBuf;
+}
+
+
+/**
+  return a talloced string representing a NTTIME for human consumption
+*/
+const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt)
+{
+       time_t t;
+       if (nt.low == 0 && nt.high == 0) {
+               return "NTTIME(0)";
+       }
+       t = nt_time_to_unix(&nt);
+       return timestring(mem_ctx, t);
+}
+
 /****************************************************************************
  Utility function that always returns a const string even if localtime
  and asctime fail.
index a1efecfbbbaac04681474e49731cf1f51b62bb5a..96263bf39475ad6e9422e78463bbfce48597ca63 100644 (file)
@@ -753,7 +753,7 @@ ssize_t transfer_file_internal(int infd, int outfd, size_t n, ssize_t (*read_fn)
        size_t num_to_read_thistime;
        size_t num_written = 0;
 
-       if ((buf = SMB_MALLOC(TRANSFER_BUF_SIZE)) == NULL)
+       if ((buf = SMB_MALLOC_ARRAY(char, TRANSFER_BUF_SIZE)) == NULL)
                return -1;
 
        while (total < n) {
@@ -1052,9 +1052,11 @@ void *realloc_array(void *p, size_t el_size, unsigned int count, BOOL free_old_o
 ****************************************************************************/
 
 void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
-                       void *element, void **array, uint32 *num_elements,
+                       void *element, void *_array, uint32 *num_elements,
                        ssize_t *array_size)
 {
+       void **array = (void **)_array;
+
        if (*array_size < 0) {
                return;
        }
diff --git a/source/lib/util_reg.c b/source/lib/util_reg.c
new file mode 100644 (file)
index 0000000..3f0b2d6
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Registry helper routines
+ * Copyright (C) Volker Lendecke 2006
+ * 
+ * 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"
+
+const char *reg_type_lookup(uint32 type)
+{
+       const char *result;
+
+       switch(type) {
+       case REG_NONE:
+               result = "REG_NONE";
+               break;
+       case REG_SZ:
+               result = "REG_SZ";
+               break;
+       case REG_EXPAND_SZ:
+               result = "REG_EXPAND_SZ";
+               break;
+       case REG_BINARY:
+               result = "REG_BINARY";
+               break;
+       case REG_DWORD:
+               result = "REG_DWORD";
+               break;
+       case REG_DWORD_BE:
+               result = "REG_DWORD_BE";
+               break;
+       case REG_LINK:
+               result = "REG_LINK";
+               break;
+       case REG_MULTI_SZ:
+               result = "REG_MULTI_SZ";
+               break;
+       case REG_RESOURCE_LIST:
+               result = "REG_RESOURCE_LIST";
+               break;
+       case REG_FULL_RESOURCE_DESCRIPTOR:
+               result = "REG_FULL_RESOURCE_DESCRIPTOR";
+               break;
+       case REG_RESOURCE_REQUIREMENTS_LIST:
+               result = "REG_RESOURCE_REQUIREMENTS_LIST";
+               break;
+       case REG_QWORD:
+               result = "REG_QWORD";
+               break;
+       default:
+               result = "REG TYPE IS UNKNOWN";
+               break;
+       }
+       return result;
+}
+
+NTSTATUS reg_pull_multi_sz(TALLOC_CTX *mem_ctx, const void *buf, size_t len,
+                          int *num_values, char ***values)
+{
+       const smb_ucs2_t *p = (const smb_ucs2_t *)buf;
+       *num_values = 0;
+
+       /*
+        * Make sure that a talloc context for the strings retrieved exists
+        */
+
+       if (!(*values = TALLOC_ARRAY(mem_ctx, char *, 1))) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       len /= 2;               /* buf is a set of UCS2 strings */
+
+       while (len > 0) {
+               char *val;
+               size_t dstlen, thislen;
+
+               thislen = strnlen_w(p, len) + 1;
+               dstlen = convert_string_allocate(*values, CH_UCS2, CH_UNIX,
+                                                p, thislen*2, (void *)&val,
+                                                True);
+               if (dstlen == (size_t)-1) {
+                       TALLOC_FREE(*values);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               ADD_TO_ARRAY(*values, char *, val, values, num_values);
+               if (*values == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               p += thislen;
+               len -= thislen;
+       }
+
+       return NT_STATUS_OK;
+}
index 938fb0f47b02121decdc696f23972768383bd792..2580521c3b9f97b10929251a955245c202f11a40 100644 (file)
@@ -5,6 +5,7 @@
    Copyright (C) Andrew Tridgell 1992-2001
    Copyright (C) Simo Sorce      2001-2002
    Copyright (C) Martin Pool     2003
+   Copyright (C) James Peach    2006
    
    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
@@ -1914,13 +1915,14 @@ int str_list_count( const char **list )
  for the work
  *****************************************************************************/
  
-BOOL str_list_sub_basic( char **list, const char *smb_name )
+BOOL str_list_sub_basic( char **list, const char *smb_name,
+                        const char *domain_name )
 {
        char *s, *tmpstr;
        
        while ( *list ) {
                s = *list;
-               tmpstr = alloc_sub_basic(smb_name, s);
+               tmpstr = alloc_sub_basic(smb_name, domain_name, s);
                if ( !tmpstr ) {
                        DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n"));
                        return False;
@@ -2302,6 +2304,73 @@ SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
        return val;
 }
 
+/* Convert a size specification to a count of bytes. We accept the following
+ * suffixes:
+ *         bytes if there is no suffix
+ *     kK  kibibytes
+ *     mM  mebibytes
+ *     gG  gibibytes
+ *     tT  tibibytes
+ *     pP  whatever the ISO name for petabytes is
+ *
+ *  Returns 0 if the string can't be converted.
+ */
+SMB_OFF_T conv_str_size(const char * str)
+{
+        SMB_OFF_T lval;
+       char * end;
+
+        if (str == NULL || *str == '\0') {
+                return 0;
+        }
+
+#ifdef HAVE_STRTOULL
+       if (sizeof(SMB_OFF_T) == 8) {
+           lval = strtoull(str, &end, 10 /* base */);
+       } else {
+           lval = strtoul(str, &end, 10 /* base */);
+       }
+#else
+       lval = strtoul(str, &end, 10 /* base */);
+#endif
+
+        if (end == NULL || end == str) {
+                return 0;
+        }
+
+        if (*end) {
+               SMB_OFF_T lval_orig = lval;
+
+                if (strwicmp(end, "K") == 0) {
+                        lval *= (SMB_OFF_T)1024;
+                } else if (strwicmp(end, "M") == 0) {
+                        lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024);
+                } else if (strwicmp(end, "G") == 0) {
+                        lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
+                               (SMB_OFF_T)1024);
+                } else if (strwicmp(end, "T") == 0) {
+                        lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
+                               (SMB_OFF_T)1024 * (SMB_OFF_T)1024);
+                } else if (strwicmp(end, "P") == 0) {
+                        lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
+                               (SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
+                               (SMB_OFF_T)1024);
+                } else {
+                        return 0;
+                }
+
+               /* Primitive attempt to detect wrapping on platforms with
+                * 4-byte SMB_OFF_T. It's better to let the caller handle
+                * a failure than some random number.
+                */
+               if (lval_orig <= lval) {
+                       return 0;
+               }
+        }
+
+       return lval;
+}
+
 void string_append(char **left, const char *right)
 {
        int new_len = strlen(right) + 1;
@@ -2454,3 +2523,52 @@ BOOL validate_net_name( const char *name, const char *invalid_chars, int max_len
        return True;
 }
 
+
+/**
+return the number of bytes occupied by a buffer in ASCII format
+the result includes the null termination
+limited by 'n' bytes
+**/
+size_t ascii_len_n(const char *src, size_t n)
+{
+       size_t len;
+
+       len = strnlen(src, n);
+       if (len+1 <= n) {
+               len += 1;
+       }
+
+       return len;
+}
+
+/**
+return the number of bytes occupied by a buffer in CH_UTF16 format
+the result includes the null termination
+**/
+size_t utf16_len(const void *buf)
+{
+       size_t len;
+
+       for (len = 0; SVAL(buf,len); len += 2) ;
+
+       return len + 2;
+}
+
+/**
+return the number of bytes occupied by a buffer in CH_UTF16 format
+the result includes the null termination
+limited by 'n' bytes
+**/
+size_t utf16_len_n(const void *src, size_t n)
+{
+       size_t len;
+
+       for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;
+
+       if (len+2 <= n) {
+               len += 2;
+       }
+
+       return len;
+}
+
index d2e263a9d1bd06c6469f6a4c07fd2319e0b23494..321b43552777501ff75976e937ab8b0303924b58 100644 (file)
 #define MAX_DNS_PACKET_SIZE 0xffff
 
 #ifdef NS_HFIXEDSZ     /* Bind 8/9 interface */
+#if !defined(C_IN)     /* AIX 5.3 already defines C_IN */
 #  define C_IN         ns_c_in
+#endif
+#if !defined(T_A)      /* AIX 5.3 already defines T_A */
 #  define T_A          ns_t_a
+#endif
 #  define T_SRV        ns_t_srv
 #else
 #  ifdef HFIXEDSZ
index b017ff941b9d2e42aa922318f361ac3b678b726c..58eca99f9e116edbd6e505dd21a531055a745c05 100644 (file)
@@ -831,10 +831,11 @@ ADS_STATUS ads_search(ADS_STRUCT *ads, void **res,
  * @param attrs Attributes to retrieve
  * @return status of search
  **/
-ADS_STATUS ads_search_dn(ADS_STRUCT *ads, void **res, 
+ADS_STATUS ads_search_dn(ADS_STRUCT *ads, void *_res, 
                         const char *dn, 
                         const char **attrs)
 {
+       void **res = (void **)_res;
        return ads_do_search(ads, dn, LDAP_SCOPE_BASE, "(objectclass=*)", attrs, res);
 }
 
@@ -973,8 +974,9 @@ ADS_MODLIST ads_init_mods(TALLOC_CTX *ctx)
 */
 static ADS_STATUS ads_modlist_add(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
                                  int mod_op, const char *name, 
-                                 const void **invals)
+                                 const void *_invals)
 {
+       const void **invals = (const void **)_invals;
        int curmod;
        LDAPMod **modlist = (LDAPMod **) *mods;
        struct berval **ber_values = NULL;
@@ -1037,8 +1039,7 @@ ADS_STATUS ads_mod_str(TALLOC_CTX *ctx, ADS_MODLIST *mods,
 
        if (!val)
                return ads_modlist_add(ctx, mods, LDAP_MOD_DELETE, name, NULL);
-       return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE, name, 
-                              (const void **) values);
+       return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE, name, values);
 }
 
 /**
index a12af43eb37d18dfb1f1e41bb6bb32086e2d3355..3c0bea93d6c8e77e14ef53493c6b59d5df18aef4 100644 (file)
@@ -278,7 +278,6 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
        uint8 *p;
        uint32 max_msg_size;
        char *sname;
-       unsigned sec_layer;
        ADS_STATUS status;
        krb5_principal principal;
        krb5_context ctx = NULL;
@@ -391,7 +390,6 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
        file_save("sasl_gssapi.dat", output_token.value, output_token.length);
 #endif
        max_msg_size = (p[1]<<16) | (p[2]<<8) | p[3];
-       sec_layer = *p;
 
        gss_release_buffer(&minor_status, &output_token);
 
index 7b62b4d4627a6e5607919d6e48cd53e13c2ed5ee..72c429e724791215b085792321aa43324d4ccc87 100644 (file)
@@ -49,7 +49,7 @@ int cac_LsaOpenPolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenP
 
    /*see if there is already an active session on this pipe, if not then open one*/
    if(!hnd->_internal.pipes[PI_LSARPC]) {
-      pipe_hnd = cli_rpc_pipe_open_noauth(&(srv->cli), PI_LSARPC, &(hnd->status));
+      pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_LSARPC, &hnd->status);
 
       if(!pipe_hnd) {
          hnd->status = NT_STATUS_UNSUCCESSFUL;
index 60c6562988e43ad28d20d2e92d437dc97cf05e42..a29ee7a41ebb0016860a48e4c4e69ba8bce8119d 100644 (file)
@@ -55,7 +55,7 @@ int cac_SamConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamConnect
 
    /*initialize for samr pipe if we have to*/
    if(!hnd->_internal.pipes[PI_SAMR]) {
-      if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SAMR, &(hnd->status)))) {
+      if(!(pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_SAMR, &hnd->status))) {
          return CAC_FAILURE;
       }
 
@@ -1507,7 +1507,7 @@ int cac_SamUserChangePasswd(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Sa
 
    /*open a session on SAMR if we don't have one*/
    if(!hnd->_internal.pipes[PI_SAMR]) {
-      if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SAMR, &(hnd->status)))) {
+      if(!(pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_SAMR, &hnd->status))) {
          return CAC_FAILURE;
       }
 
@@ -1576,7 +1576,7 @@ int cac_SamEnableUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *use
    }
 
    /*now set the userinfo*/
-   hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10, &(srv->cli.user_session_key), ctr);
+   hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10, &srv->cli->user_session_key, ctr);
 
    /*this will only work properly if we use set_userinfo2 - fail if it is not supported*/
    if(!NT_STATUS_IS_OK(hnd->status))
@@ -1630,7 +1630,7 @@ int cac_SamDisableUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *us
    ctr->info.id16->acb_info ^= ACB_DISABLED;
 
    /*this will only work properly if we use set_userinfo2*/
-   hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10, &(srv->cli.user_session_key), ctr);
+   hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10, &srv->cli->user_session_key, ctr);
 
    /*this will only work properly if we use set_userinfo2 fail if it is not supported*/
    if(!NT_STATUS_IS_OK(hnd->status))
@@ -1682,7 +1682,7 @@ int cac_SamSetPassword(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetP
    ctr.switch_value = 24;
    ctr.info.id24 = &info24;
 
-   hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 24, &(srv->cli.user_session_key), &ctr);
+   hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 24, &srv->cli->user_session_key, &ctr);
 
    if(!NT_STATUS_IS_OK(hnd->status))
       return CAC_FAILURE;
@@ -1767,11 +1767,11 @@ int cac_SamSetUserInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetU
    }
 
    if(hnd->_internal.srv_level >= SRV_WIN_NT4) {
-      hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, op->in.user_hnd, 21, &(srv->cli.user_session_key), ctr);
+      hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, op->in.user_hnd, 21, &srv->cli->user_session_key, ctr);
    }
 
    if(hnd->_internal.srv_level < SRV_WIN_NT4 || !NT_STATUS_IS_OK(hnd->status)) {
-      hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 21, &(srv->cli.user_session_key), ctr);
+      hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 21, &srv->cli->user_session_key, ctr);
 
       if(NT_STATUS_IS_OK(hnd->status) && hnd->_internal.srv_level > SRV_WIN_NT4) {
          hnd->_internal.srv_level = SRV_WIN_NT4;
@@ -1850,7 +1850,7 @@ int cac_SamSetUserInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamS
    }
 
 
-   hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, op->in.ctr->switch_value, &(srv->cli.user_session_key), op->in.ctr);
+   hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, op->in.ctr->switch_value, &srv->cli->user_session_key, op->in.ctr);
 
    if(!NT_STATUS_IS_OK(hnd->status))
       return CAC_FAILURE;
@@ -1899,7 +1899,7 @@ int cac_SamRenameUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRenam
    ctr.switch_value = 7;
    ctr.info.id7 = &info7;
 
-   hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 7, &(srv->cli.user_session_key), &ctr);
+   hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 7, &srv->cli->user_session_key, &ctr);
 
    if(!NT_STATUS_IS_OK(hnd->status))
       return CAC_FAILURE;
index 83dc0364930219ad049f7d2fde9109a1e5af4424..51a5b5d2dd9da9fe84235af0bd4a6c30694a68fa 100644 (file)
@@ -51,7 +51,7 @@ int cac_SvcOpenScm(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenScm
 
    /*initialize for samr pipe if we have to*/
    if(!hnd->_internal.pipes[PI_SVCCTL]) {
-      if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SVCCTL, &(hnd->status)))) {
+      if(!(pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_SVCCTL, &(hnd->status)))) {
          hnd->status = NT_STATUS_UNSUCCESSFUL;
          return CAC_FAILURE;
       }
index 6ef898eb16de956cfa7caaa347cdff1b47e0eef7..91db33d2953fb3344e80d38d1a9354d2e971cff2 100644 (file)
@@ -49,7 +49,7 @@ int cac_RegConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegConnect
 
    /*initialize for winreg pipe if we have to*/
    if(!hnd->_internal.pipes[PI_WINREG]) {
-      if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_WINREG, &(hnd->status)))) {
+      if(!(pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_WINREG, &hnd->status))) {
          return CAC_FAILURE;
       }
 
@@ -966,7 +966,7 @@ int cac_Shutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Shutdown *op)
 
    /*initialize for winreg pipe if we have to*/
    if(!hnd->_internal.pipes[PI_SHUTDOWN]) {
-      if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SHUTDOWN, &(hnd->status)))) {
+      if(!(pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_SHUTDOWN, &(hnd->status)))) {
          return CAC_FAILURE;
       }
 
index 3a47361db29dc442ac6c971e559662a8df2e5362..a097bc181ce649cdd2eb1d755aa04949545ddf38 100644 (file)
 #include "libmsrpc_internal.h"
 
 /*used to get a struct rpc_pipe_client* to be passed into rpccli* calls*/
-struct rpc_pipe_client *cac_GetPipe(CacServerHandle *hnd, int pi_idx) {
-   SMBCSRV *srv = NULL;
-   struct rpc_pipe_client *pipe_hnd = NULL;
+struct rpc_pipe_client *cac_GetPipe(CacServerHandle *hnd, int pi_idx)
+{
+       SMBCSRV *srv = NULL;
+       struct rpc_pipe_client *pipe_hnd = NULL;
 
-   if(!hnd)
-      return NULL;
+       if(!hnd) {
+               return NULL;
+       }
 
-   if(hnd->_internal.pipes[pi_idx] == False) {
-      hnd->status = NT_STATUS_INVALID_HANDLE;
-      return NULL;
-   }
+       if(hnd->_internal.pipes[pi_idx] == False) {
+               hnd->status = NT_STATUS_INVALID_HANDLE;
+               return NULL;
+       }
 
-   srv = cac_GetServer(hnd);
-   if(!srv) {
-      hnd->status = NT_STATUS_INVALID_CONNECTION;
-      return NULL;
-   }
+       srv = cac_GetServer(hnd);
+       if(!srv) {
+               hnd->status = NT_STATUS_INVALID_CONNECTION;
+               return NULL;
+       }
 
-   pipe_hnd = srv->cli.pipe_list;
+       pipe_hnd = srv->cli->pipe_list;
 
-   while(pipe_hnd != NULL && pipe_hnd->pipe_idx != pi_idx)
-      pipe_hnd = pipe_hnd->next;
+       while(pipe_hnd != NULL && pipe_hnd->pipe_idx != pi_idx) {
+               pipe_hnd = pipe_hnd->next;
+       }
 
-   return pipe_hnd;
+       return pipe_hnd;
 }
 
 /*takes a string like HKEY_LOCAL_MACHINE\HARDWARE\ACPI and returns the reg_type code and then a pointer to the start of the path (HARDWARE)*/
@@ -324,7 +327,7 @@ SAM_USERINFO_CTR *cac_MakeUserInfoCtr(TALLOC_CTX *mem_ctx, CacUserInfo *info) {
    SAM_USERINFO_CTR *ctr = NULL;
 
    /*the flags we are 'setting'- include/passdb.h*/
-   uint32 flags = ACCT_USERNAME | ACCT_FULL_NAME | ACCT_PRIMARY_GID | ACCT_ADMIN_DESC | ACCT_DESCRIPTION |
+   uint32 flags = ACCT_USERNAME | ACCT_FULL_NAME | ACCT_PRIMARY_GID | ACCT_DESCRIPTION | ACCT_COMMENT |
                      ACCT_HOME_DIR | ACCT_HOME_DRIVE | ACCT_LOGON_SCRIPT | ACCT_PROFILE | ACCT_WORKSTATIONS |
                       ACCT_FLAGS;
 
diff --git a/source/libndr/libndr.h b/source/libndr/libndr.h
new file mode 100644 (file)
index 0000000..817c461
--- /dev/null
@@ -0,0 +1,296 @@
+/* 
+   Unix SMB/CIFS implementation.
+   rpc interface definitions
+   Copyright (C) Andrew Tridgell 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
+   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.
+*/
+
+#ifndef __LIBNDR_H__
+#define __LIBNDR_H__
+
+#define _PRINTF_ATTRIBUTE(a,b) 
+
+#include "libndr/misc.h"
+#include "libndr/security.h"
+
+struct dcerpc_syntax_id {
+       struct GUID uuid;
+       uint32_t if_version;
+}/* [public] */;
+
+/*
+  this provides definitions for the libcli/rpc/ MSRPC library
+*/
+
+
+/*
+  this is used by the token store/retrieve code
+*/
+struct ndr_token_list {
+       struct ndr_token_list *next, *prev;
+       const void *key;
+       uint32_t value;
+};
+
+/* this is the base structure passed to routines that 
+   parse MSRPC formatted data 
+
+   note that in Samba4 we use separate routines and structures for
+   MSRPC marshalling and unmarshalling. Also note that these routines
+   are being kept deliberately very simple, and are not tied to a
+   particular transport
+*/
+struct ndr_pull {
+       uint32_t flags; /* LIBNDR_FLAG_* */
+       uint8_t *data;
+       uint32_t data_size;
+       uint32_t offset;
+
+       uint32_t relative_base_offset;
+       struct ndr_token_list *relative_base_list;
+
+       struct ndr_token_list *relative_list;
+       struct ndr_token_list *array_size_list;
+       struct ndr_token_list *array_length_list;
+       struct ndr_token_list *switch_list;
+
+       TALLOC_CTX *current_mem_ctx;
+
+       /* this is used to ensure we generate unique reference IDs
+          between request and reply */
+       uint32_t ptr_count;
+};
+
+struct ndr_pull_save {
+       uint32_t data_size;
+       uint32_t offset;
+       struct ndr_pull_save *next;
+};
+
+/* structure passed to functions that generate NDR formatted data */
+struct ndr_push {
+       uint32_t flags; /* LIBNDR_FLAG_* */
+       uint8_t *data;
+       uint32_t alloc_size;
+       uint32_t offset;
+
+       uint32_t relative_base_offset;
+       struct ndr_token_list *relative_base_list;
+
+       struct ndr_token_list *switch_list;
+       struct ndr_token_list *relative_list;
+       struct ndr_token_list *nbt_string_list;
+
+       /* this is used to ensure we generate unique reference IDs */
+       uint32_t ptr_count;
+};
+
+struct ndr_push_save {
+       uint32_t offset;
+       struct ndr_push_save *next;
+};
+
+
+/* structure passed to functions that print IDL structures */
+struct ndr_print {
+       uint32_t flags; /* LIBNDR_FLAG_* */
+       uint32_t depth;
+       struct ndr_token_list *switch_list;
+       void (*print)(struct ndr_print *, const char *, ...);
+       void *private_data;
+};
+
+#define LIBNDR_FLAG_BIGENDIAN  (1<<0)
+#define LIBNDR_FLAG_NOALIGN    (1<<1)
+
+#define LIBNDR_FLAG_STR_ASCII          (1<<2)
+#define LIBNDR_FLAG_STR_LEN4           (1<<3)
+#define LIBNDR_FLAG_STR_SIZE4          (1<<4)
+#define LIBNDR_FLAG_STR_NOTERM         (1<<5)
+#define LIBNDR_FLAG_STR_NULLTERM       (1<<6)
+#define LIBNDR_FLAG_STR_SIZE2          (1<<7)
+#define LIBNDR_FLAG_STR_BYTESIZE       (1<<8)
+#define LIBNDR_FLAG_STR_FIXLEN32       (1<<9)
+#define LIBNDR_FLAG_STR_CONFORMANT     (1<<10)
+#define LIBNDR_FLAG_STR_CHARLEN                (1<<11)
+#define LIBNDR_FLAG_STR_UTF8           (1<<12)
+#define LIBNDR_FLAG_STR_FIXLEN15       (1<<13)
+#define LIBNDR_STRING_FLAGS            (0x7FFC)
+
+
+#define LIBNDR_FLAG_REF_ALLOC    (1<<20)
+#define LIBNDR_FLAG_REMAINING    (1<<21)
+#define LIBNDR_FLAG_ALIGN2       (1<<22)
+#define LIBNDR_FLAG_ALIGN4       (1<<23)
+#define LIBNDR_FLAG_ALIGN8       (1<<24)
+
+#define LIBNDR_ALIGN_FLAGS (LIBNDR_FLAG_ALIGN2|LIBNDR_FLAG_ALIGN4|LIBNDR_FLAG_ALIGN8)
+
+#define LIBNDR_PRINT_ARRAY_HEX   (1<<25)
+#define LIBNDR_PRINT_SET_VALUES  (1<<26)
+
+/* used to force a section of IDL to be little-endian */
+#define LIBNDR_FLAG_LITTLE_ENDIAN (1<<27)
+
+/* used to check if alignment padding is zero */
+#define LIBNDR_FLAG_PAD_CHECK     (1<<28)
+
+/* set if an object uuid will be present */
+#define LIBNDR_FLAG_OBJECT_PRESENT    (1<<30)
+
+/* set to avoid recursion in ndr_size_*() calculation */
+#define LIBNDR_FLAG_NO_NDR_SIZE                (1<<31)
+
+/* useful macro for debugging */
+#define NDR_PRINT_DEBUG(type, p) ndr_print_debug((ndr_print_fn_t)ndr_print_ ##type, #p, p)
+#define NDR_PRINT_UNION_DEBUG(type, level, p) ndr_print_union_debug((ndr_print_fn_t)ndr_print_ ##type, #p, level, p)
+#define NDR_PRINT_FUNCTION_DEBUG(type, flags, p) ndr_print_function_debug((ndr_print_function_t)ndr_print_ ##type, #type, flags, p)
+#define NDR_PRINT_BOTH_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_BOTH, p)
+#define NDR_PRINT_OUT_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_OUT, p)
+#define NDR_PRINT_IN_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_IN | NDR_SET_VALUES, p)
+
+#define NDR_BE(ndr) (((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == LIBNDR_FLAG_BIGENDIAN)
+
+enum ndr_err_code {
+       NDR_ERR_ARRAY_SIZE,
+       NDR_ERR_BAD_SWITCH,
+       NDR_ERR_OFFSET,
+       NDR_ERR_RELATIVE,
+       NDR_ERR_CHARCNV,
+       NDR_ERR_LENGTH,
+       NDR_ERR_SUBCONTEXT,
+       NDR_ERR_COMPRESSION,
+       NDR_ERR_STRING,
+       NDR_ERR_VALIDATE,
+       NDR_ERR_BUFSIZE,
+       NDR_ERR_ALLOC,
+       NDR_ERR_RANGE,
+       NDR_ERR_TOKEN,
+       NDR_ERR_IPV4ADDRESS
+};
+
+enum ndr_compression_alg {
+       NDR_COMPRESSION_MSZIP   = 2,
+       NDR_COMPRESSION_XPRESS  = 3
+};
+
+/*
+  flags passed to control parse flow
+*/
+#define NDR_SCALARS 1
+#define NDR_BUFFERS 2
+
+/*
+  flags passed to ndr_print_*()
+*/
+#define NDR_IN 1
+#define NDR_OUT 2
+#define NDR_BOTH 3
+#define NDR_SET_VALUES 4
+
+#define NDR_PULL_NEED_BYTES(ndr, n) do { \
+       if ((n) > ndr->data_size || ndr->offset + (n) > ndr->data_size) { \
+               return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "Pull bytes %u", (unsigned)n); \
+       } \
+} while(0)
+
+#define NDR_ALIGN(ndr, n) ndr_align_size(ndr->offset, n)
+
+#define NDR_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
+
+#define NDR_PULL_ALIGN(ndr, n) do { \
+       if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \
+               if (ndr->flags & LIBNDR_FLAG_PAD_CHECK) { \
+                       ndr_check_padding(ndr, n); \
+               } \
+               ndr->offset = (ndr->offset + (n-1)) & ~(n-1); \
+       } \
+       if (ndr->offset > ndr->data_size) { \
+               return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "Pull align %u", (unsigned)n); \
+       } \
+} while(0)
+
+#define NDR_PUSH_NEED_BYTES(ndr, n) NDR_CHECK(ndr_push_expand(ndr, ndr->offset+(n)))
+
+#define NDR_PUSH_ALIGN(ndr, n) do { \
+       if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \
+               uint32_t _pad = ((ndr->offset + (n-1)) & ~(n-1)) - ndr->offset; \
+               while (_pad--) NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 0)); \
+       } \
+} while(0)
+
+/* these are used to make the error checking on each element in libndr
+   less tedious, hopefully making the code more readable */
+#define NDR_CHECK(call) do { NTSTATUS _status; \
+                             _status = call; \
+                             if (!NT_STATUS_IS_OK(_status)) \
+                                return _status; \
+                        } while (0)
+
+#define NDR_PULL_GET_MEM_CTX(ndr) (ndr->current_mem_ctx)
+
+#define NDR_PULL_SET_MEM_CTX(ndr, mem_ctx, flgs) do {\
+       if ( !(flgs) || (ndr->flags & flgs) ) {\
+               if (!(mem_ctx)) {\
+                       return ndr_pull_error(ndr, NDR_ERR_ALLOC, "NDR_PULL_SET_MEM_CTX(NULL): %s\n", __location__); \
+               }\
+               ndr->current_mem_ctx = mem_ctx;\
+       }\
+} while(0)
+
+#define _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr) do {\
+       if (!ndr->current_mem_ctx) {\
+               ndr->current_mem_ctx = talloc_new(ndr);\
+               if (!ndr->current_mem_ctx) {\
+                       return ndr_pull_error(ndr, NDR_ERR_ALLOC, "_NDR_PULL_FIX_CURRENT_MEM_CTX() failed: %s\n", __location__); \
+               }\
+       }\
+} while(0)
+
+#define NDR_PULL_ALLOC_SIZE(ndr, s, size) do { \
+       _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\
+       (s) = talloc_size(ndr->current_mem_ctx, size); \
+       if (!(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %u failed: %s\n",(unsigned)size, __location__); \
+} while (0)
+
+#define NDR_PULL_ALLOC(ndr, s) NDR_PULL_ALLOC_SIZE(ndr, s, sizeof(*(s)))
+
+#define NDR_PULL_ALLOC_N_SIZE(ndr, s, n, elsize) do { \
+       _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\
+       (s) = talloc_array_size(ndr->current_mem_ctx, elsize, n); \
+       if (!(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %u * %u failed: %s\n", (unsigned)n, (unsigned)elsize, __location__); \
+} while (0)
+
+#define NDR_PULL_ALLOC_N(ndr, s, n) NDR_PULL_ALLOC_N_SIZE(ndr, s, n, sizeof(*(s)))
+
+
+#define NDR_PUSH_ALLOC_SIZE(ndr, s, size) do { \
+       (s) = talloc_size(ndr, size); \
+       if (!(s)) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %u failed: %s\n", (unsigned)size, __location__); \
+} while (0)
+
+#define NDR_PUSH_ALLOC(ndr, s) NDR_PUSH_ALLOC_SIZE(ndr, s, sizeof(*(s)))
+
+/* these are used when generic fn pointers are needed for ndr push/pull fns */
+typedef NTSTATUS (*ndr_push_flags_fn_t)(struct ndr_push *, int ndr_flags, const void *);
+typedef NTSTATUS (*ndr_pull_flags_fn_t)(struct ndr_pull *, int ndr_flags, void *);
+typedef void (*ndr_print_fn_t)(struct ndr_print *, const char *, const void *);
+typedef void (*ndr_print_function_t)(struct ndr_print *, const char *, int, const void *);
+
+extern const struct dcerpc_syntax_id ndr_transfer_syntax;
+extern const struct dcerpc_syntax_id ndr64_transfer_syntax;
+
+#endif /* __LIBNDR_H__ */
diff --git a/source/libndr/misc.h b/source/libndr/misc.h
new file mode 100644 (file)
index 0000000..d929379
--- /dev/null
@@ -0,0 +1,37 @@
+/* header auto-generated by pidl */
+
+#ifndef _HEADER_misc
+#define _HEADER_misc
+
+struct GUID {
+       uint32_t time_low;
+       uint16_t time_mid;
+       uint16_t time_hi_and_version;
+       uint8_t clock_seq[2];
+       uint8_t node[6];
+}/* [noprint,gensize,public,noejs] */;
+
+struct policy_handle {
+       uint32_t handle_type;
+       struct GUID uuid;
+}/* [public] */;
+
+enum netr_SchannelType {
+       SEC_CHAN_WKSTA=2,
+       SEC_CHAN_DOMAIN=4,
+       SEC_CHAN_BDC=6
+};
+
+enum netr_SamDatabaseID {
+       SAM_DATABASE_DOMAIN=0,
+       SAM_DATABASE_BUILTIN=1,
+       SAM_DATABASE_PRIVS=2
+};
+
+enum samr_RejectReason {
+       SAMR_REJECT_OTHER=0,
+       SAMR_REJECT_TOO_SHORT=1,
+       SAMR_REJECT_COMPLEXITY=2
+};
+
+#endif /* _HEADER_misc */
diff --git a/source/libndr/ndr.c b/source/libndr/ndr.c
new file mode 100644 (file)
index 0000000..2aff7a8
--- /dev/null
@@ -0,0 +1,961 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   libndr interface
+
+   Copyright (C) Andrew Tridgell 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
+   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.
+*/
+
+/*
+  this provides the core routines for NDR parsing functions
+
+  see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details
+  of NDR encoding rules
+*/
+
+#include "includes.h"
+
+#define NDR_BASE_MARSHALL_SIZE 1024
+
+/* this guid indicates NDR encoding in a protocol tower */
+const struct dcerpc_syntax_id ndr_transfer_syntax = {
+  { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} },
+  2
+};
+
+const struct dcerpc_syntax_id ndr64_transfer_syntax = {
+  { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },
+  1
+};
+
+/*
+  work out the number of bytes needed to align on a n byte boundary
+*/
+size_t ndr_align_size(uint32_t offset, size_t n)
+{
+       if ((offset & (n-1)) == 0) return 0;
+       return n - (offset & (n-1));
+}
+
+/*
+  initialise a ndr parse structure from a data blob
+*/
+struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
+{
+       struct ndr_pull *ndr;
+
+       ndr = talloc_zero(mem_ctx, struct ndr_pull);
+       if (!ndr) return NULL;
+       ndr->current_mem_ctx = mem_ctx;
+
+       ndr->data = blob->data;
+       ndr->data_size = blob->length;
+
+       return ndr;
+}
+
+/*
+  advance by 'size' bytes
+*/
+NTSTATUS ndr_pull_advance(struct ndr_pull *ndr, uint32_t size)
+{
+       ndr->offset += size;
+       if (ndr->offset > ndr->data_size) {
+               return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, 
+                                     "ndr_pull_advance by %u failed",
+                                     size);
+       }
+       return NT_STATUS_OK;
+}
+
+/*
+  set the parse offset to 'ofs'
+*/
+static NTSTATUS ndr_pull_set_offset(struct ndr_pull *ndr, uint32_t ofs)
+{
+       ndr->offset = ofs;
+       if (ndr->offset > ndr->data_size) {
+               return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, 
+                                     "ndr_pull_set_offset %u failed",
+                                     ofs);
+       }
+       return NT_STATUS_OK;
+}
+
+/* save the offset/size of the current ndr state */
+void ndr_pull_save(struct ndr_pull *ndr, struct ndr_pull_save *save)
+{
+       save->offset = ndr->offset;
+       save->data_size = ndr->data_size;
+}
+
+/* restore the size/offset of a ndr structure */
+void ndr_pull_restore(struct ndr_pull *ndr, struct ndr_pull_save *save)
+{
+       ndr->offset = save->offset;
+       ndr->data_size = save->data_size;
+}
+
+
+/* create a ndr_push structure, ready for some marshalling */
+struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx)
+{
+       struct ndr_push *ndr;
+
+       ndr = talloc_zero(mem_ctx, struct ndr_push);
+       if (!ndr) {
+               return NULL;
+       }
+
+       ndr->flags = 0;
+       ndr->alloc_size = NDR_BASE_MARSHALL_SIZE;
+       ndr->data = talloc_array(ndr, uint8_t, ndr->alloc_size);
+       if (!ndr->data) {
+               return NULL;
+       }
+
+       return ndr;
+}
+
+
+/* create a ndr_push structure, ready for some marshalling */
+struct ndr_push *ndr_push_init(void)
+{
+       return ndr_push_init_ctx(NULL);
+}
+
+/* free a ndr_push structure */
+void ndr_push_free(struct ndr_push *ndr)
+{
+       talloc_free(ndr);
+}
+
+
+/* return a DATA_BLOB structure for the current ndr_push marshalled data */
+DATA_BLOB ndr_push_blob(struct ndr_push *ndr)
+{
+       DATA_BLOB blob;
+       blob.data = ndr->data;
+       blob.length = ndr->offset;
+       blob.free = NULL;
+       if (ndr->alloc_size > ndr->offset) {
+               ndr->data[ndr->offset] = 0;
+       }
+       return blob;
+}
+
+
+/*
+  expand the available space in the buffer to 'size'
+*/
+NTSTATUS ndr_push_expand(struct ndr_push *ndr, uint32_t size)
+{
+       if (ndr->alloc_size > size) {
+               return NT_STATUS_OK;
+       }
+
+       ndr->alloc_size += NDR_BASE_MARSHALL_SIZE;
+       if (size+1 > ndr->alloc_size) {
+               ndr->alloc_size = size+1;
+       }
+       ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->alloc_size);
+       if (!ndr->data) {
+               return ndr_push_error(ndr, NDR_ERR_ALLOC, "Failed to push_expand to %u",
+                                     ndr->alloc_size);
+       }
+
+       return NT_STATUS_OK;
+}
+
+void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3)
+{
+       va_list ap;
+       char *s = NULL;
+       int i;
+
+       va_start(ap, format);
+       vasprintf(&s, format, ap);
+       va_end(ap);
+
+       for (i=0;i<ndr->depth;i++) {
+               DEBUG(0,("    "));
+       }
+
+       DEBUG(0,("%s\n", s));
+       free(s);
+}
+
+static void ndr_print_string_helper(struct ndr_print *ndr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3)
+{
+       va_list ap;
+       int i;
+
+       for (i=0;i<ndr->depth;i++) {
+               ndr->private_data = talloc_asprintf_append(ndr->private_data, "    ");
+       }
+
+       va_start(ap, format);
+       ndr->private_data = talloc_vasprintf_append(ndr->private_data, format, ap);
+       va_end(ap);
+       ndr->private_data = talloc_asprintf_append(ndr->private_data, "\n");
+}
+
+/*
+  a useful helper function for printing idl structures via DEBUG()
+*/
+void ndr_print_debug(ndr_print_fn_t fn, const char *name, void *ptr)
+{
+       struct ndr_print *ndr;
+
+       ndr = talloc_zero(NULL, struct ndr_print);
+       if (!ndr) return;
+       ndr->print = ndr_print_debug_helper;
+       ndr->depth = 1;
+       ndr->flags = 0;
+       fn(ndr, name, ptr);
+       talloc_free(ndr);
+}
+
+/*
+  a useful helper function for printing idl unions via DEBUG()
+*/
+void ndr_print_union_debug(ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr)
+{
+       struct ndr_print *ndr;
+
+       ndr = talloc_zero(NULL, struct ndr_print);
+       if (!ndr) return;
+       ndr->print = ndr_print_debug_helper;
+       ndr->depth = 1;
+       ndr->flags = 0;
+       ndr_print_set_switch_value(ndr, ptr, level);
+       fn(ndr, name, ptr);
+       talloc_free(ndr);
+}
+
+/*
+  a useful helper function for printing idl function calls via DEBUG()
+*/
+void ndr_print_function_debug(ndr_print_function_t fn, const char *name, int flags, void *ptr)
+{
+       struct ndr_print *ndr;
+
+       ndr = talloc_zero(NULL, struct ndr_print);
+       if (!ndr) return;
+       ndr->print = ndr_print_debug_helper;
+       ndr->depth = 1;
+       ndr->flags = 0;
+       fn(ndr, name, flags, ptr);
+       talloc_free(ndr);
+}
+
+
+/*
+  a useful helper function for printing idl function calls to a string
+*/
+char *ndr_print_function_string(TALLOC_CTX *mem_ctx,
+                               ndr_print_function_t fn, const char *name, 
+                               int flags, void *ptr)
+{
+       struct ndr_print *ndr;
+       char *ret = NULL;
+
+       ndr = talloc_zero(mem_ctx, struct ndr_print);
+       if (!ndr) return NULL;
+       if (!(ndr->private_data = talloc_strdup(mem_ctx, ""))) {
+               TALLOC_FREE(ndr);
+               return NULL;
+       }
+       ndr->print = ndr_print_string_helper;
+       ndr->depth = 1;
+       ndr->flags = 0;
+       fn(ndr, name, flags, ptr);
+       ret = ndr->private_data;
+       talloc_free(ndr);
+       return ret;
+}
+
+void ndr_set_flags(uint32_t *pflags, uint32_t new_flags)
+{
+       /* the big/little endian flags are inter-dependent */
+       if (new_flags & LIBNDR_FLAG_LITTLE_ENDIAN) {
+               (*pflags) &= ~LIBNDR_FLAG_BIGENDIAN;
+       }
+       if (new_flags & LIBNDR_FLAG_BIGENDIAN) {
+               (*pflags) &= ~LIBNDR_FLAG_LITTLE_ENDIAN;
+       }
+       if (new_flags & LIBNDR_FLAG_REMAINING) {
+               (*pflags) &= ~LIBNDR_ALIGN_FLAGS;
+       }
+       if (new_flags & LIBNDR_ALIGN_FLAGS) {
+               (*pflags) &= ~LIBNDR_FLAG_REMAINING;
+       }
+       (*pflags) |= new_flags;
+}
+
+static NTSTATUS ndr_map_error(enum ndr_err_code ndr_err)
+{
+       switch (ndr_err) {
+       case NDR_ERR_BUFSIZE:
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       case NDR_ERR_TOKEN:
+               return NT_STATUS_INTERNAL_ERROR;
+       case NDR_ERR_ALLOC:
+               return NT_STATUS_NO_MEMORY;
+       case NDR_ERR_ARRAY_SIZE:
+               return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
+       default:
+               break;
+       }
+
+       /* we should map all error codes to different status codes */
+       return NT_STATUS_INVALID_PARAMETER;
+}
+
+/*
+  return and possibly log an NDR error
+*/
+NTSTATUS ndr_pull_error(struct ndr_pull *ndr,
+                                enum ndr_err_code ndr_err,
+                                const char *format, ...) _PRINTF_ATTRIBUTE(3,4)
+{
+       char *s=NULL;
+       va_list ap;
+
+       va_start(ap, format);
+       vasprintf(&s, format, ap);
+       va_end(ap);
+
+       DEBUG(3,("ndr_pull_error(%u): %s\n", ndr_err, s));
+
+       free(s);
+
+       return ndr_map_error(ndr_err);
+}
+
+/*
+  return and possibly log an NDR error
+*/
+NTSTATUS ndr_push_error(struct ndr_push *ndr,
+                                enum ndr_err_code ndr_err,
+                                const char *format, ...)  _PRINTF_ATTRIBUTE(3,4)
+{
+       char *s=NULL;
+       va_list ap;
+
+       va_start(ap, format);
+       vasprintf(&s, format, ap);
+       va_end(ap);
+
+       DEBUG(3,("ndr_push_error(%u): %s\n", ndr_err, s));
+
+       free(s);
+
+       return ndr_map_error(ndr_err);
+}
+
+/*
+  handle subcontext buffers, which in midl land are user-marshalled, but
+  we use magic in pidl to make them easier to cope with
+*/
+NTSTATUS ndr_pull_subcontext_start(struct ndr_pull *ndr, 
+                                  struct ndr_pull **_subndr,
+                                  size_t header_size,
+                                  ssize_t size_is)
+{
+       struct ndr_pull *subndr;
+       uint32_t r_content_size;
+
+       switch (header_size) {
+       case 0: {
+               uint32_t content_size = ndr->data_size - ndr->offset;
+               if (size_is >= 0) {
+                       content_size = size_is;
+               }
+               r_content_size = content_size;
+               break;
+       }
+
+       case 2: {
+               uint16_t content_size;
+               NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &content_size));
+               if (size_is >= 0 && size_is != content_size) {
+                       return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d", 
+                                               (int)size_is, (int)content_size);
+               }
+               r_content_size = content_size;
+               break;
+       }
+
+       case 4: {
+               uint32_t content_size;
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &content_size));
+               if (size_is >= 0 && size_is != content_size) {
+                       return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d", 
+                                               (int)size_is, (int)content_size);
+               }
+               r_content_size = content_size;
+               break;
+       }
+       default:
+               return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %d", 
+                                     (int)header_size);
+       }
+
+       NDR_PULL_NEED_BYTES(ndr, r_content_size);
+
+       subndr = talloc_zero(ndr, struct ndr_pull);
+       NT_STATUS_HAVE_NO_MEMORY(subndr);
+       subndr->flags           = ndr->flags;
+       subndr->current_mem_ctx = ndr->current_mem_ctx;
+
+       subndr->data = ndr->data + ndr->offset;
+       subndr->offset = 0;
+       subndr->data_size = r_content_size;
+
+       *_subndr = subndr;
+       return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_subcontext_end(struct ndr_pull *ndr, 
+                                struct ndr_pull *subndr,
+                                size_t header_size,
+                                ssize_t size_is)
+{
+       uint32_t advance;
+       if (size_is >= 0) {
+               advance = size_is;
+       } else if (header_size > 0) {
+               advance = subndr->data_size;
+       } else {
+               advance = subndr->offset;
+       }
+       NDR_CHECK(ndr_pull_advance(ndr, advance));
+       return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_push_subcontext_start(struct ndr_push *ndr,
+                                  struct ndr_push **_subndr,
+                                  size_t header_size,
+                                  ssize_t size_is)
+{
+       struct ndr_push *subndr;
+
+       subndr = ndr_push_init_ctx(ndr);
+       NT_STATUS_HAVE_NO_MEMORY(subndr);
+       subndr->flags   = ndr->flags;
+
+       *_subndr = subndr;
+       return NT_STATUS_OK;
+}
+
+/*
+  push a subcontext header 
+*/
+NTSTATUS ndr_push_subcontext_end(struct ndr_push *ndr,
+                                struct ndr_push *subndr,
+                                size_t header_size,
+                                ssize_t size_is)
+{
+       if (size_is >= 0) {
+               ssize_t padding_len = size_is - subndr->offset;
+               if (padding_len > 0) {
+                       NDR_CHECK(ndr_push_zero(subndr, padding_len));
+               } else if (padding_len < 0) {
+                       return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
+                                             (int)subndr->offset, (int)size_is);
+               }
+       }
+
+       switch (header_size) {
+       case 0: 
+               break;
+
+       case 2: 
+               NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, subndr->offset));
+               break;
+
+       case 4: 
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset));
+               break;
+
+       default:
+               return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %d", 
+                                     (int)header_size);
+       }
+
+       NDR_CHECK(ndr_push_bytes(ndr, subndr->data, subndr->offset));
+       return NT_STATUS_OK;
+}
+
+/*
+  store a token in the ndr context, for later retrieval
+*/
+NTSTATUS ndr_token_store(TALLOC_CTX *mem_ctx, 
+                        struct ndr_token_list **list, 
+                        const void *key, 
+                        uint32_t value)
+{
+       struct ndr_token_list *tok;
+       tok = talloc(mem_ctx, struct ndr_token_list);
+       if (tok == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       tok->key = key;
+       tok->value = value;
+       DLIST_ADD((*list), tok);
+       return NT_STATUS_OK;
+}
+
+/*
+  retrieve a token from a ndr context, using cmp_fn to match the tokens
+*/
+NTSTATUS ndr_token_retrieve_cmp_fn(struct ndr_token_list **list, const void *key, uint32_t *v,
+                                  comparison_fn_t _cmp_fn, BOOL _remove_tok)
+{
+       struct ndr_token_list *tok;
+       for (tok=*list;tok;tok=tok->next) {
+               if (_cmp_fn && _cmp_fn(tok->key,key)==0) goto found;
+               else if (!_cmp_fn && tok->key == key) goto found;
+       }
+       return ndr_map_error(NDR_ERR_TOKEN);
+found:
+       *v = tok->value;
+       if (_remove_tok) {
+               DLIST_REMOVE((*list), tok);
+               talloc_free(tok);
+       }
+       return NT_STATUS_OK;            
+}
+
+/*
+  retrieve a token from a ndr context
+*/
+NTSTATUS ndr_token_retrieve(struct ndr_token_list **list, const void *key, uint32_t *v)
+{
+       return ndr_token_retrieve_cmp_fn(list, key, v, NULL, True);
+}
+
+/*
+  peek at but don't removed a token from a ndr context
+*/
+uint32_t ndr_token_peek(struct ndr_token_list **list, const void *key)
+{
+       NTSTATUS status;
+       uint32_t v;
+       status = ndr_token_retrieve_cmp_fn(list, key, &v, NULL, False);
+       if (NT_STATUS_IS_OK(status)) return v;
+       return 0;
+}
+
+/*
+  pull an array size field and add it to the array_size_list token list
+*/
+NTSTATUS ndr_pull_array_size(struct ndr_pull *ndr, const void *p)
+{
+       uint32_t size;
+       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &size));
+       return ndr_token_store(ndr, &ndr->array_size_list, p, size);
+}
+
+/*
+  get the stored array size field
+*/
+uint32_t ndr_get_array_size(struct ndr_pull *ndr, const void *p)
+{
+       return ndr_token_peek(&ndr->array_size_list, p);
+}
+
+/*
+  check the stored array size field
+*/
+NTSTATUS ndr_check_array_size(struct ndr_pull *ndr, void *p, uint32_t size)
+{
+       uint32_t stored;
+       stored = ndr_token_peek(&ndr->array_size_list, p);
+       if (stored != size) {
+               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, 
+                                     "Bad array size - got %u expected %u\n",
+                                     stored, size);
+       }
+       return NT_STATUS_OK;
+}
+
+/*
+  pull an array length field and add it to the array_length_list token list
+*/
+NTSTATUS ndr_pull_array_length(struct ndr_pull *ndr, const void *p)
+{
+       uint32_t length, offset;
+       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &offset));
+       if (offset != 0) {
+               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, 
+                                     "non-zero array offset %u\n", offset);
+       }
+       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
+       return ndr_token_store(ndr, &ndr->array_length_list, p, length);
+}
+
+/*
+  get the stored array length field
+*/
+uint32_t ndr_get_array_length(struct ndr_pull *ndr, const void *p)
+{
+       return ndr_token_peek(&ndr->array_length_list, p);
+}
+
+/*
+  check the stored array length field
+*/
+NTSTATUS ndr_check_array_length(struct ndr_pull *ndr, void *p, uint32_t length)
+{
+       uint32_t stored;
+       stored = ndr_token_peek(&ndr->array_length_list, p);
+       if (stored != length) {
+               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, 
+                                     "Bad array length - got %u expected %u\n",
+                                     stored, length);
+       }
+       return NT_STATUS_OK;
+}
+
+/*
+  store a switch value
+ */
+NTSTATUS ndr_push_set_switch_value(struct ndr_push *ndr, const void *p, uint32_t val)
+{
+       return ndr_token_store(ndr, &ndr->switch_list, p, val);
+}
+
+NTSTATUS ndr_pull_set_switch_value(struct ndr_pull *ndr, const void *p, uint32_t val)
+{
+       return ndr_token_store(ndr, &ndr->switch_list, p, val);
+}
+
+NTSTATUS ndr_print_set_switch_value(struct ndr_print *ndr, const void *p, uint32_t val)
+{
+       return ndr_token_store(ndr, &ndr->switch_list, p, val);
+}
+
+/*
+  retrieve a switch value
+ */
+uint32_t ndr_push_get_switch_value(struct ndr_push *ndr, const void *p)
+{
+       return ndr_token_peek(&ndr->switch_list, p);
+}
+
+uint32_t ndr_pull_get_switch_value(struct ndr_pull *ndr, const void *p)
+{
+       return ndr_token_peek(&ndr->switch_list, p);
+}
+
+uint32_t ndr_print_get_switch_value(struct ndr_print *ndr, const void *p)
+{
+       return ndr_token_peek(&ndr->switch_list, p);
+}
+
+/*
+  pull a struct from a blob using NDR
+*/
+NTSTATUS ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
+                             ndr_pull_flags_fn_t fn)
+{
+       struct ndr_pull *ndr;
+       ndr = ndr_pull_init_blob(blob, mem_ctx);
+       if (!ndr) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       return fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+}
+
+/*
+  pull a struct from a blob using NDR - failing if all bytes are not consumed
+*/
+NTSTATUS ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
+                                 ndr_pull_flags_fn_t fn)
+{
+       struct ndr_pull *ndr;
+       NTSTATUS status;
+
+       ndr = ndr_pull_init_blob(blob, mem_ctx);
+       if (!ndr) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+       if (!NT_STATUS_IS_OK(status)) return status;
+       if (ndr->offset != ndr->data_size) {
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
+       return status;
+}
+
+/*
+  pull a union from a blob using NDR, given the union discriminator
+*/
+NTSTATUS ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
+                            uint32_t level, ndr_pull_flags_fn_t fn)
+{
+       struct ndr_pull *ndr;
+       NTSTATUS status;
+
+       ndr = ndr_pull_init_blob(blob, mem_ctx);
+       if (!ndr) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       ndr_pull_set_switch_value(ndr, p, level);
+       status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+       if (!NT_STATUS_IS_OK(status)) return status;
+       if (ndr->offset != ndr->data_size) {
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
+       return status;
+}
+
+/*
+  push a struct to a blob using NDR
+*/
+NTSTATUS ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, const void *p,
+                             ndr_push_flags_fn_t fn)
+{
+       NTSTATUS status;
+       struct ndr_push *ndr;
+       ndr = ndr_push_init_ctx(mem_ctx);
+       if (!ndr) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       *blob = ndr_push_blob(ndr);
+
+       return NT_STATUS_OK;
+}
+
+/*
+  push a union to a blob using NDR
+*/
+NTSTATUS ndr_push_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
+                            uint32_t level, ndr_push_flags_fn_t fn)
+{
+       NTSTATUS status;
+       struct ndr_push *ndr;
+       ndr = ndr_push_init_ctx(mem_ctx);
+       if (!ndr) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       ndr_push_set_switch_value(ndr, p, level);
+       status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       *blob = ndr_push_blob(ndr);
+
+       return NT_STATUS_OK;
+}
+
+/*
+  generic ndr_size_*() handler for structures
+*/
+size_t ndr_size_struct(const void *p, int flags, ndr_push_flags_fn_t push)
+{
+       struct ndr_push *ndr;
+       NTSTATUS status;
+       size_t ret;
+
+       /* avoid recursion */
+       if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
+
+       ndr = ndr_push_init_ctx(NULL);
+       if (!ndr) return 0;
+       ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
+       status = push(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+       if (!NT_STATUS_IS_OK(status)) {
+               return 0;
+       }
+       ret = ndr->offset;
+       talloc_free(ndr);
+       return ret;
+}
+
+/*
+  generic ndr_size_*() handler for unions
+*/
+size_t ndr_size_union(const void *p, int flags, uint32_t level, ndr_push_flags_fn_t push)
+{
+       struct ndr_push *ndr;
+       NTSTATUS status;
+       size_t ret;
+
+       /* avoid recursion */
+       if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
+
+       ndr = ndr_push_init_ctx(NULL);
+       if (!ndr) return 0;
+       ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
+       ndr_push_set_switch_value(ndr, p, level);
+       status = push(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+       if (!NT_STATUS_IS_OK(status)) {
+               return 0;
+       }
+       ret = ndr->offset;
+       talloc_free(ndr);
+       return ret;
+}
+
+/*
+  get the current base for relative pointers for the push
+*/
+uint32_t ndr_push_get_relative_base_offset(struct ndr_push *ndr)
+{
+       return ndr->relative_base_offset;
+}
+
+/*
+  restore the old base for relative pointers for the push
+*/
+void ndr_push_restore_relative_base_offset(struct ndr_push *ndr, uint32_t offset)
+{
+       ndr->relative_base_offset = offset;
+}
+
+/*
+  setup the current base for relative pointers for the push
+  called in the NDR_SCALAR stage
+*/
+NTSTATUS ndr_push_setup_relative_base_offset1(struct ndr_push *ndr, const void *p, uint32_t offset)
+{
+       ndr->relative_base_offset = offset;
+       return ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
+}
+
+/*
+  setup the current base for relative pointers for the push
+  called in the NDR_BUFFERS stage
+*/
+NTSTATUS ndr_push_setup_relative_base_offset2(struct ndr_push *ndr, const void *p)
+{
+       return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
+}
+
+/*
+  push a relative object - stage1
+  this is called during SCALARS processing
+*/
+NTSTATUS ndr_push_relative_ptr1(struct ndr_push *ndr, const void *p)
+{
+       if (p == NULL) {
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+               return NT_STATUS_OK;
+       }
+       NDR_CHECK(ndr_push_align(ndr, 4));
+       NDR_CHECK(ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset));
+       return ndr_push_uint32(ndr, NDR_SCALARS, 0xFFFFFFFF);
+}
+
+/*
+  push a relative object - stage2
+  this is called during buffers processing
+*/
+NTSTATUS ndr_push_relative_ptr2(struct ndr_push *ndr, const void *p)
+{
+       struct ndr_push_save save;
+       uint32_t ptr_offset = 0xFFFFFFFF;
+       if (p == NULL) {
+               return NT_STATUS_OK;
+       }
+       ndr_push_save(ndr, &save);
+       NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
+       if (ptr_offset > ndr->offset) {
+               return ndr_push_error(ndr, NDR_ERR_BUFSIZE, 
+                                     "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
+                                     ptr_offset, ndr->offset);
+       }
+       ndr->offset = ptr_offset;
+       if (save.offset < ndr->relative_base_offset) {
+               return ndr_push_error(ndr, NDR_ERR_BUFSIZE, 
+                                     "ndr_push_relative_ptr2 save.offset(%u) < ndr->relative_base_offset(%u)",
+                                     save.offset, ndr->relative_base_offset);
+       }       
+       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, save.offset - ndr->relative_base_offset));
+       ndr_push_restore(ndr, &save);
+       return NT_STATUS_OK;
+}
+
+/*
+  get the current base for relative pointers for the pull
+*/
+uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull *ndr)
+{
+       return ndr->relative_base_offset;
+}
+
+/*
+  restore the old base for relative pointers for the pull
+*/
+void ndr_pull_restore_relative_base_offset(struct ndr_pull *ndr, uint32_t offset)
+{
+       ndr->relative_base_offset = offset;
+}
+
+/*
+  setup the current base for relative pointers for the pull
+  called in the NDR_SCALAR stage
+*/
+NTSTATUS ndr_pull_setup_relative_base_offset1(struct ndr_pull *ndr, const void *p, uint32_t offset)
+{
+       ndr->relative_base_offset = offset;
+       return ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
+}
+
+/*
+  setup the current base for relative pointers for the pull
+  called in the NDR_BUFFERS stage
+*/
+NTSTATUS ndr_pull_setup_relative_base_offset2(struct ndr_pull *ndr, const void *p)
+{
+       return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
+}
+
+/*
+  pull a relative object - stage1
+  called during SCALARS processing
+*/
+NTSTATUS ndr_pull_relative_ptr1(struct ndr_pull *ndr, const void *p, uint32_t rel_offset)
+{
+       rel_offset += ndr->relative_base_offset;
+       if (rel_offset > ndr->data_size) {
+               return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, 
+                                     "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)",
+                                     rel_offset, ndr->data_size);
+       }
+       return ndr_token_store(ndr, &ndr->relative_list, p, rel_offset);
+}
+
+/*
+  pull a relative object - stage2
+  called during BUFFERS processing
+*/
+NTSTATUS ndr_pull_relative_ptr2(struct ndr_pull *ndr, const void *p)
+{
+       uint32_t rel_offset;
+       NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &rel_offset));
+       return ndr_pull_set_offset(ndr, rel_offset);
+}
diff --git a/source/libndr/ndr_basic.c b/source/libndr/ndr_basic.c
new file mode 100644 (file)
index 0000000..31a48f6
--- /dev/null
@@ -0,0 +1,826 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   routines for marshalling/unmarshalling basic types
+
+   Copyright (C) Andrew Tridgell 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
+   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"
+
+/* Evil hack to convert Samba3 NTTIME's to Samba4 NTTIME's */
+
+union NTTIME_big {
+       NTTIME s3;
+       uint64_t s4;
+};
+
+
+
+#define NDR_SVAL(ndr, ofs) (NDR_BE(ndr)?RSVAL(ndr->data,ofs):SVAL(ndr->data,ofs))
+#define NDR_IVAL(ndr, ofs) (NDR_BE(ndr)?RIVAL(ndr->data,ofs):IVAL(ndr->data,ofs))
+#define NDR_IVALS(ndr, ofs) (NDR_BE(ndr)?RIVALS(ndr->data,ofs):IVALS(ndr->data,ofs))
+#define NDR_SSVAL(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSSVAL(ndr->data,ofs,v); } else SSVAL(ndr->data,ofs,v); } while (0)
+#define NDR_SIVAL(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSIVAL(ndr->data,ofs,v); } else SIVAL(ndr->data,ofs,v); } while (0)
+#define NDR_SIVALS(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSIVALS(ndr->data,ofs,v); } else SIVALS(ndr->data,ofs,v); } while (0)
+
+
+/*
+  check for data leaks from the server by looking for non-zero pad bytes
+  these could also indicate that real structure elements have been
+  mistaken for padding in the IDL
+*/
+void ndr_check_padding(struct ndr_pull *ndr, size_t n)
+{
+       size_t ofs2 = (ndr->offset + (n-1)) & ~(n-1);
+       int i;
+       for (i=ndr->offset;i<ofs2;i++) {
+               if (ndr->data[i] != 0) {
+                       break;
+               }
+       }
+       if (i<ofs2) {
+               DEBUG(0,("WARNING: Non-zero padding to %d: ", (int)n));
+               for (i=ndr->offset;i<ofs2;i++) {
+                       DEBUG(0,("%02x ", ndr->data[i]));
+               }
+               DEBUG(0,("\n"));
+       }
+
+}
+
+/*
+  parse a int8_t
+*/
+NTSTATUS ndr_pull_int8(struct ndr_pull *ndr, int ndr_flags, int8_t *v)
+{
+       NDR_PULL_NEED_BYTES(ndr, 1);
+       *v = (int8_t)CVAL(ndr->data, ndr->offset);
+       ndr->offset += 1;
+       return NT_STATUS_OK;
+}
+
+/*
+  parse a uint8_t
+*/
+NTSTATUS ndr_pull_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
+{
+       NDR_PULL_NEED_BYTES(ndr, 1);
+       *v = CVAL(ndr->data, ndr->offset);
+       ndr->offset += 1;
+       return NT_STATUS_OK;
+}
+
+/*
+  parse a int16_t
+*/
+NTSTATUS ndr_pull_int16(struct ndr_pull *ndr, int ndr_flags, int16_t *v)
+{
+       NDR_PULL_ALIGN(ndr, 2);
+       NDR_PULL_NEED_BYTES(ndr, 2);
+       *v = (uint16_t)NDR_SVAL(ndr, ndr->offset);
+       ndr->offset += 2;
+       return NT_STATUS_OK;
+}
+
+/*
+  parse a uint16_t
+*/
+NTSTATUS ndr_pull_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
+{
+       NDR_PULL_ALIGN(ndr, 2);
+       NDR_PULL_NEED_BYTES(ndr, 2);
+       *v = NDR_SVAL(ndr, ndr->offset);
+       ndr->offset += 2;
+       return NT_STATUS_OK;
+}
+
+/*
+  parse a int32_t
+*/
+NTSTATUS ndr_pull_int32(struct ndr_pull *ndr, int ndr_flags, int32_t *v)
+{
+       NDR_PULL_ALIGN(ndr, 4);
+       NDR_PULL_NEED_BYTES(ndr, 4);
+       *v = NDR_IVALS(ndr, ndr->offset);
+       ndr->offset += 4;
+       return NT_STATUS_OK;
+}
+
+/*
+  parse a uint32_t
+*/
+NTSTATUS ndr_pull_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
+{
+       NDR_PULL_ALIGN(ndr, 4);
+       NDR_PULL_NEED_BYTES(ndr, 4);
+       *v = NDR_IVAL(ndr, ndr->offset);
+       ndr->offset += 4;
+       return NT_STATUS_OK;
+}
+
+/*
+  parse a pointer referent identifier
+*/
+NTSTATUS ndr_pull_generic_ptr(struct ndr_pull *ndr, uint32_t *v)
+{
+       NTSTATUS status;
+       status = ndr_pull_uint32(ndr, NDR_SCALARS, v);
+       if (NT_STATUS_IS_OK(status) && *v != 0) {
+               ndr->ptr_count++;
+       }
+       return status;
+}
+
+/*
+  parse a ref pointer referent identifier
+*/
+NTSTATUS ndr_pull_ref_ptr(struct ndr_pull *ndr, uint32_t *v)
+{
+       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, v));
+       /* ref pointers always point to data */
+       *v = 1;
+       return NT_STATUS_OK;
+}
+
+/*
+  parse a udlong
+*/
+NTSTATUS ndr_pull_udlong(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
+{
+       NDR_PULL_ALIGN(ndr, 4);
+       NDR_PULL_NEED_BYTES(ndr, 8);
+       *v = NDR_IVAL(ndr, ndr->offset);
+       *v |= (uint64_t)(NDR_IVAL(ndr, ndr->offset+4)) << 32;
+       ndr->offset += 8;
+       return NT_STATUS_OK;
+}
+
+/*
+  parse a udlongr
+*/
+NTSTATUS ndr_pull_udlongr(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
+{
+       NDR_PULL_ALIGN(ndr, 4);
+       NDR_PULL_NEED_BYTES(ndr, 8);
+       *v = ((uint64_t)NDR_IVAL(ndr, ndr->offset)) << 32;
+       *v |= NDR_IVAL(ndr, ndr->offset+4);
+       ndr->offset += 8;
+       return NT_STATUS_OK;
+}
+
+/*
+  parse a dlong
+*/
+NTSTATUS ndr_pull_dlong(struct ndr_pull *ndr, int ndr_flags, int64_t *v)
+{
+       return ndr_pull_udlong(ndr, ndr_flags, (uint64_t *)v);
+}
+
+/*
+  parse a hyper
+*/
+NTSTATUS ndr_pull_hyper(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
+{
+       NDR_PULL_ALIGN(ndr, 8);
+       return ndr_pull_udlong(ndr, ndr_flags, v);
+}
+
+/*
+  parse a pointer
+*/
+NTSTATUS ndr_pull_pointer(struct ndr_pull *ndr, int ndr_flags, void* *v)
+{
+       intptr_t h;
+       NDR_PULL_ALIGN(ndr, sizeof(h));
+       NDR_PULL_NEED_BYTES(ndr, sizeof(h));
+       memcpy(&h, ndr->data+ndr->offset, sizeof(h));
+       ndr->offset += sizeof(h);
+       *v = (void *)h;
+       return NT_STATUS_OK;    
+}
+
+/*
+  pull a NTSTATUS
+*/
+NTSTATUS ndr_pull_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, NTSTATUS *status)
+{
+       uint32_t v;
+       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+       *status = NT_STATUS(v);
+       return NT_STATUS_OK;
+}
+
+/*
+  push a NTSTATUS
+*/
+NTSTATUS ndr_push_NTSTATUS(struct ndr_push *ndr, int ndr_flags, NTSTATUS status)
+{
+       return ndr_push_uint32(ndr, ndr_flags, NT_STATUS_V(status));
+}
+
+void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTATUS r)
+{
+       ndr->print(ndr, "%-25s: %s", name, nt_errstr(r));
+}
+
+/*
+  pull a WERROR
+*/
+NTSTATUS ndr_pull_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *status)
+{
+       uint32_t v;
+       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+       *status = W_ERROR(v);
+       return NT_STATUS_OK;
+}
+
+/*
+  push a WERROR
+*/
+NTSTATUS ndr_push_WERROR(struct ndr_push *ndr, int ndr_flags, WERROR status)
+{
+       return ndr_push_uint32(ndr, NDR_SCALARS, W_ERROR_V(status));
+}
+
+void ndr_print_WERROR(struct ndr_print *ndr, const char *name, WERROR r)
+{
+       ndr->print(ndr, "%-25s: %d", name, W_ERROR_V(r));
+}
+
+/*
+  parse a set of bytes
+*/
+NTSTATUS ndr_pull_bytes(struct ndr_pull *ndr, uint8_t *data, uint32_t n)
+{
+       NDR_PULL_NEED_BYTES(ndr, n);
+       memcpy(data, ndr->data + ndr->offset, n);
+       ndr->offset += n;
+       return NT_STATUS_OK;
+}
+
+/*
+  pull an array of uint8
+*/
+NTSTATUS ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *data, uint32_t n)
+{
+       if (!(ndr_flags & NDR_SCALARS)) {
+               return NT_STATUS_OK;
+       }
+       return ndr_pull_bytes(ndr, data, n);
+}
+
+/*
+  push a int8_t
+*/
+NTSTATUS ndr_push_int8(struct ndr_push *ndr, int ndr_flags, int8_t v)
+{
+       NDR_PUSH_NEED_BYTES(ndr, 1);
+       SCVAL(ndr->data, ndr->offset, (uint8_t)v);
+       ndr->offset += 1;
+       return NT_STATUS_OK;
+}
+
+/*
+  push a uint8_t
+*/
+NTSTATUS ndr_push_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
+{
+       NDR_PUSH_NEED_BYTES(ndr, 1);
+       SCVAL(ndr->data, ndr->offset, v);
+       ndr->offset += 1;
+       return NT_STATUS_OK;
+}
+
+/*
+  push a int16_t
+*/
+NTSTATUS ndr_push_int16(struct ndr_push *ndr, int ndr_flags, int16_t v)
+{
+       NDR_PUSH_ALIGN(ndr, 2);
+       NDR_PUSH_NEED_BYTES(ndr, 2);
+       NDR_SSVAL(ndr, ndr->offset, (uint16_t)v);
+       ndr->offset += 2;
+       return NT_STATUS_OK;
+}
+
+/*
+  push a uint16_t
+*/
+NTSTATUS ndr_push_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
+{
+       NDR_PUSH_ALIGN(ndr, 2);
+       NDR_PUSH_NEED_BYTES(ndr, 2);
+       NDR_SSVAL(ndr, ndr->offset, v);
+       ndr->offset += 2;
+       return NT_STATUS_OK;
+}
+
+/*
+  push a int32_t
+*/
+NTSTATUS ndr_push_int32(struct ndr_push *ndr, int ndr_flags, int32_t v)
+{
+       NDR_PUSH_ALIGN(ndr, 4);
+       NDR_PUSH_NEED_BYTES(ndr, 4);
+       NDR_SIVALS(ndr, ndr->offset, v);
+       ndr->offset += 4;
+       return NT_STATUS_OK;
+}
+
+/*
+  push a uint32_t
+*/
+NTSTATUS ndr_push_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
+{
+       NDR_PUSH_ALIGN(ndr, 4);
+       NDR_PUSH_NEED_BYTES(ndr, 4);
+       NDR_SIVAL(ndr, ndr->offset, v);
+       ndr->offset += 4;
+       return NT_STATUS_OK;
+}
+
+/*
+  push a udlong
+*/
+NTSTATUS ndr_push_udlong(struct ndr_push *ndr, int ndr_flags, uint64_t v)
+{
+       NDR_PUSH_ALIGN(ndr, 4);
+       NDR_PUSH_NEED_BYTES(ndr, 8);
+       NDR_SIVAL(ndr, ndr->offset, (v & 0xFFFFFFFF));
+       NDR_SIVAL(ndr, ndr->offset+4, (v>>32));
+       ndr->offset += 8;
+       return NT_STATUS_OK;
+}
+
+/*
+  push a udlongr
+*/
+NTSTATUS ndr_push_udlongr(struct ndr_push *ndr, int ndr_flags, uint64_t v)
+{
+       NDR_PUSH_ALIGN(ndr, 4);
+       NDR_PUSH_NEED_BYTES(ndr, 8);
+       NDR_SIVAL(ndr, ndr->offset, (v>>32));
+       NDR_SIVAL(ndr, ndr->offset+4, (v & 0xFFFFFFFF));
+       ndr->offset += 8;
+       return NT_STATUS_OK;
+}
+
+/*
+  push a dlong
+*/
+NTSTATUS ndr_push_dlong(struct ndr_push *ndr, int ndr_flags, int64_t v)
+{
+       return ndr_push_udlong(ndr, NDR_SCALARS, (uint64_t)v);
+}
+
+/*
+  push a hyper
+*/
+NTSTATUS ndr_push_hyper(struct ndr_push *ndr, int ndr_flags, uint64_t v)
+{
+       NDR_PUSH_ALIGN(ndr, 8);
+       return ndr_push_udlong(ndr, NDR_SCALARS, v);
+}
+
+/*
+  push a pointer
+*/
+NTSTATUS ndr_push_pointer(struct ndr_push *ndr, int ndr_flags, void* v)
+{
+       intptr_t h = (intptr_t)v;
+       NDR_PUSH_ALIGN(ndr, sizeof(h));
+       NDR_PUSH_NEED_BYTES(ndr, sizeof(h));
+       memcpy(ndr->data+ndr->offset, &h, sizeof(h));
+       ndr->offset += sizeof(h);
+       return NT_STATUS_OK;    
+}
+
+NTSTATUS ndr_push_align(struct ndr_push *ndr, size_t size)
+{
+       NDR_PUSH_ALIGN(ndr, size);
+       return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_align(struct ndr_pull *ndr, size_t size)
+{
+       NDR_PULL_ALIGN(ndr, size);
+       return NT_STATUS_OK;
+}
+
+/*
+  push some bytes
+*/
+NTSTATUS ndr_push_bytes(struct ndr_push *ndr, const uint8_t *data, uint32_t n)
+{
+       NDR_PUSH_NEED_BYTES(ndr, n);
+       memcpy(ndr->data + ndr->offset, data, n);
+       ndr->offset += n;
+       return NT_STATUS_OK;
+}
+
+/*
+  push some zero bytes
+*/
+NTSTATUS ndr_push_zero(struct ndr_push *ndr, uint32_t n)
+{
+       NDR_PUSH_NEED_BYTES(ndr, n);
+       memset(ndr->data + ndr->offset, 0, n);
+       ndr->offset += n;
+       return NT_STATUS_OK;
+}
+
+/*
+  push an array of uint8
+*/
+NTSTATUS ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n)
+{
+       if (!(ndr_flags & NDR_SCALARS)) {
+               return NT_STATUS_OK;
+       }
+       return ndr_push_bytes(ndr, data, n);
+}
+
+/*
+  save the current position
+ */
+void ndr_push_save(struct ndr_push *ndr, struct ndr_push_save *save)
+{
+       save->offset = ndr->offset;
+}
+
+/*
+  restore the position
+ */
+void ndr_push_restore(struct ndr_push *ndr, struct ndr_push_save *save)
+{
+       ndr->offset = save->offset;
+}
+
+/*
+  push a unique non-zero value if a pointer is non-NULL, otherwise 0
+*/
+NTSTATUS ndr_push_unique_ptr(struct ndr_push *ndr, const void *p)
+{
+       uint32_t ptr = 0;
+       if (p) {
+               ptr = ndr->ptr_count * 4;
+               ptr |= 0x00020000;
+               ndr->ptr_count++;
+       }
+       return ndr_push_uint32(ndr, NDR_SCALARS, ptr);
+}
+
+/*
+  push a 'simple' full non-zero value if a pointer is non-NULL, otherwise 0
+*/
+NTSTATUS ndr_push_sptr_ptr(struct ndr_push *ndr, const void *p)
+{
+       uint32_t ptr = 0;
+       if (p) {
+               ndr->ptr_count++;
+               ptr = ndr->ptr_count;
+       }
+       return ndr_push_uint32(ndr, NDR_SCALARS, ptr);
+}
+
+/*
+  push always a 0, if a pointer is NULL it's a fatal error
+*/
+NTSTATUS ndr_push_ref_ptr(struct ndr_push *ndr, const void *p)
+{
+       if (p == NULL) {
+               return NT_STATUS_INVALID_PARAMETER_MIX;
+       }
+       return ndr_push_uint32(ndr, NDR_SCALARS, 0xAEF1AEF1);
+}
+
+/*
+  push a NTTIME
+*/
+NTSTATUS ndr_push_NTTIME(struct ndr_push *ndr, int ndr_flags, NTTIME t)
+{
+       union NTTIME_big b; b.s3 = t;
+       NDR_CHECK(ndr_push_udlong(ndr, ndr_flags, b.s4));
+       return NT_STATUS_OK;
+}
+
+/*
+  pull a NTTIME
+*/
+NTSTATUS ndr_pull_NTTIME(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
+{
+       union NTTIME_big b; 
+       NDR_CHECK(ndr_pull_udlong(ndr, ndr_flags, &b.s4));
+
+       *t = b.s3;
+       return NT_STATUS_OK;
+}
+
+/*
+  push a NTTIME
+*/
+NTSTATUS ndr_push_NTTIME_1sec(struct ndr_push *ndr, int ndr_flags, NTTIME t)
+{
+       union NTTIME_big b; b.s3 = t;
+
+       b.s4 /= 10000000;
+       NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, b.s4));
+       return NT_STATUS_OK;
+}
+
+/*
+  pull a NTTIME_1sec
+*/
+NTSTATUS ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
+{
+       union NTTIME_big b;
+       NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &b.s4));
+       b.s4 *= 10000000;
+       *t = b.s3;
+       return NT_STATUS_OK;
+}
+
+/*
+  pull a NTTIME_hyper
+*/
+NTSTATUS ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
+{
+       union NTTIME_big b;
+       NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &b.s4));
+       *t = b.s3;
+       return NT_STATUS_OK;
+}
+
+/*
+  push a NTTIME_hyper
+*/
+NTSTATUS ndr_push_NTTIME_hyper(struct ndr_push *ndr, int ndr_flags, NTTIME t)
+{
+       union NTTIME_big b; b.s3 = t;
+       NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, b.s4));
+       return NT_STATUS_OK;
+}
+
+/*
+  push a time_t
+*/
+NTSTATUS ndr_push_time_t(struct ndr_push *ndr, int ndr_flags, time_t t)
+{
+       return ndr_push_uint32(ndr, ndr_flags, t);
+}
+
+/*
+  pull a time_t
+*/
+NTSTATUS ndr_pull_time_t(struct ndr_pull *ndr, int ndr_flags, time_t *t)
+{
+       uint32_t tt;
+       NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &tt));
+       *t = tt;
+       return NT_STATUS_OK;
+}
+
+
+void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
+{
+       ndr->print(ndr, "%s: struct %s", name, type);
+}
+
+void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type, 
+                   const char *val, uint32_t value)
+{
+       if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
+               ndr->print(ndr, "%-25s: %s (0x%X)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
+       } else {
+               ndr->print(ndr, "%-25s: %s (%d)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
+       }
+}
+
+void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint32_t flag, uint32_t value)
+{
+       /* this is an attempt to support multi-bit bitmap masks */
+       value &= flag;
+
+       while (!(flag & 1)) {
+               flag >>= 1;
+               value >>= 1;
+       }       
+       if (flag == 1) {
+               ndr->print(ndr, "   %d: %-25s", value, flag_name);
+       } else {
+               ndr->print(ndr, "0x%02x: %-25s (%d)", value, flag_name, value);
+       }
+}
+
+void ndr_print_int8(struct ndr_print *ndr, const char *name, int8_t v)
+{
+       ndr->print(ndr, "%-25s: %d", name, v);
+}
+
+void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v)
+{
+       ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
+}
+
+void ndr_print_int16(struct ndr_print *ndr, const char *name, int16_t v)
+{
+       ndr->print(ndr, "%-25s: %d", name, v);
+}
+
+void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16_t v)
+{
+       ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
+}
+
+void ndr_print_int32(struct ndr_print *ndr, const char *name, int32_t v)
+{
+       ndr->print(ndr, "%-25s: %d", name, v);
+}
+
+void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t v)
+{
+       ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
+}
+
+void ndr_print_udlong(struct ndr_print *ndr, const char *name, uint64_t v)
+{
+       ndr->print(ndr, "%-25s: 0x%016llx (%llu)", name, v, v);
+}
+
+void ndr_print_udlongr(struct ndr_print *ndr, const char *name, uint64_t v)
+{
+       ndr_print_udlong(ndr, name, v);
+}
+
+void ndr_print_dlong(struct ndr_print *ndr, const char *name, int64_t v)
+{
+       ndr->print(ndr, "%-25s: 0x%016llx (%lld)", name, v, v);
+}
+
+void ndr_print_hyper(struct ndr_print *ndr, const char *name, uint64_t v)
+{
+       ndr_print_dlong(ndr, name, v);
+}
+
+void ndr_print_pointer(struct ndr_print *ndr, const char *name, void *v)
+{
+       ndr->print(ndr, "%-25s: %p", name, v);
+}
+
+void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
+{
+       if (p) {
+               ndr->print(ndr, "%-25s: *", name);
+       } else {
+               ndr->print(ndr, "%-25s: NULL", name);
+       }
+}
+
+void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
+{
+       ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr, t));
+}
+
+void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME t)
+{
+       /* this is a standard NTTIME here
+        * as it's already converted in the pull/push code
+        */
+       ndr_print_NTTIME(ndr, name, t);
+}
+
+void ndr_print_NTTIME_hyper(struct ndr_print *ndr, const char *name, NTTIME t)
+{
+       ndr_print_NTTIME(ndr, name, t);
+}
+
+void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t)
+{
+       if (t == (time_t)-1 || t == 0) {
+               ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t);
+       } else {
+               ndr->print(ndr, "%-25s: %s", name, timestring(ndr, t));
+       }
+}
+
+void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type)
+{
+       if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
+               ndr->print(ndr, "%-25s: union %s(case 0x%X)", name, type, level);
+       } else {
+               ndr->print(ndr, "%-25s: union %s(case %d)", name, type, level);
+       }
+}
+
+void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16_t level)
+{
+       ndr->print(ndr, "UNKNOWN LEVEL %u", level);
+}
+
+void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, 
+                          const uint8_t *data, uint32_t count)
+{
+       int i;
+
+       if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
+               char s[1202];
+               for (i=0;i<count;i++) {
+                       snprintf(&s[i*2], 3, "%02x", data[i]);
+               }
+               s[i*2] = 0;
+               ndr->print(ndr, "%-25s: %s", name, s);
+               return;
+       }
+
+       ndr->print(ndr, "%s: ARRAY(%d)", name, count);
+       ndr->depth++;
+       for (i=0;i<count;i++) {
+               char *idx=NULL;
+               asprintf(&idx, "[%d]", i);
+               if (idx) {
+                       ndr_print_uint8(ndr, idx, data[i]);
+                       free(idx);
+               }
+       }
+       ndr->depth--;   
+}
+
+void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
+{
+       ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, r.length);
+       if (r.length) {
+               dump_data(10, (const char *)r.data, r.length);
+       }
+}
+
+
+/*
+  push a DATA_BLOB onto the wire. 
+*/
+NTSTATUS ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flags, DATA_BLOB blob)
+{
+       if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
+               if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
+                       blob.length = NDR_ALIGN(ndr, 2);
+               } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
+                       blob.length = NDR_ALIGN(ndr, 4);
+               } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
+                       blob.length = NDR_ALIGN(ndr, 8);
+               }
+               NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
+               data_blob_clear(&blob);
+       } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, blob.length));
+       }
+       NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
+       return NT_STATUS_OK;
+}
+
+/*
+  pull a DATA_BLOB from the wire. 
+*/
+NTSTATUS ndr_pull_DATA_BLOB(struct ndr_pull *ndr, int ndr_flags, DATA_BLOB *blob)
+{
+       uint32_t length = 0;
+
+       if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
+               if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
+                       length = NDR_ALIGN(ndr, 2);
+               } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
+                       length = NDR_ALIGN(ndr, 4);
+               } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
+                       length = NDR_ALIGN(ndr, 8);
+               }
+               if (ndr->data_size - ndr->offset < length) {
+                       length = ndr->data_size - ndr->offset;
+               }
+       } else if (ndr->flags & LIBNDR_FLAG_REMAINING) {
+               length = ndr->data_size - ndr->offset;
+       } else {
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
+       }
+       NDR_PULL_NEED_BYTES(ndr, length);
+       *blob = data_blob_talloc(ndr->current_mem_ctx, ndr->data+ndr->offset, length);
+       ndr->offset += length;
+       return NT_STATUS_OK;
+}
+
+uint32_t ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags)
+{
+       return ret + data->length;
+}
diff --git a/source/libndr/ndr_misc.c b/source/libndr/ndr_misc.c
new file mode 100644 (file)
index 0000000..2f9004a
--- /dev/null
@@ -0,0 +1,171 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   UUID/GUID/policy_handle functions
+
+   Copyright (C) Theodore Ts'o               1996, 1997,
+   Copyright (C) Jim McDonough                     2002.
+   Copyright (C) Andrew Tridgell                   2003.
+   Copyright (C) Stefan (metze) Metzmacher         2004.
+   
+   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"
+
+/**
+  build a GUID from a string
+*/
+NTSTATUS GUID_from_string(const char *s, struct GUID *guid)
+{
+       NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
+       uint32_t time_low;
+       uint32_t time_mid, time_hi_and_version;
+       uint32_t clock_seq[2];
+       uint32_t node[6];
+       int i;
+
+       if (s == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (11 == sscanf(s, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+                        &time_low, &time_mid, &time_hi_and_version, 
+                        &clock_seq[0], &clock_seq[1],
+                        &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) {
+               status = NT_STATUS_OK;
+       } else if (11 == sscanf(s, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+                               &time_low, &time_mid, &time_hi_and_version, 
+                               &clock_seq[0], &clock_seq[1],
+                               &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) {
+               status = NT_STATUS_OK;
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       guid->time_low = time_low;
+       guid->time_mid = time_mid;
+       guid->time_hi_and_version = time_hi_and_version;
+       guid->clock_seq[0] = clock_seq[0];
+       guid->clock_seq[1] = clock_seq[1];
+       for (i=0;i<6;i++) {
+               guid->node[i] = node[i];
+       }
+
+       return NT_STATUS_OK;
+}
+
+/**
+ * generate a random GUID
+ */
+struct GUID GUID_random(void)
+{
+       struct GUID guid;
+
+       generate_random_buffer((uint8_t *)&guid, sizeof(guid));
+       guid.clock_seq[0] = (guid.clock_seq[0] & 0x3F) | 0x80;
+       guid.time_hi_and_version = (guid.time_hi_and_version & 0x0FFF) | 0x4000;
+
+       return guid;
+}
+
+/**
+ * generate an empty GUID 
+ */
+struct GUID GUID_zero(void)
+{
+       struct GUID guid;
+
+       ZERO_STRUCT(guid);
+
+       return guid;
+}
+
+/**
+ * see if a range of memory is all zero. A NULL pointer is considered
+ * to be all zero 
+ */
+BOOL all_zero(const uint8_t *ptr, size_t size)
+{
+       int i;
+       if (!ptr) return True;
+       for (i=0;i<size;i++) {
+               if (ptr[i]) return False;
+       }
+       return True;
+}
+
+
+BOOL GUID_all_zero(const struct GUID *u)
+{
+       if (u->time_low != 0 ||
+           u->time_mid != 0 ||
+           u->time_hi_and_version != 0 ||
+           u->clock_seq[0] != 0 ||
+           u->clock_seq[1] != 0 ||
+           !all_zero(u->node, 6)) {
+               return False;
+       }
+       return True;
+}
+
+BOOL GUID_equal(const struct GUID *u1, const struct GUID *u2)
+{
+       if (u1->time_low != u2->time_low ||
+           u1->time_mid != u2->time_mid ||
+           u1->time_hi_and_version != u2->time_hi_and_version ||
+           u1->clock_seq[0] != u2->clock_seq[0] ||
+           u1->clock_seq[1] != u2->clock_seq[1] ||
+           memcmp(u1->node, u2->node, 6) != 0) {
+               return False;
+       }
+       return True;
+}
+
+/**
+  its useful to be able to display these in debugging messages
+*/
+char *GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid)
+{
+       return talloc_asprintf(mem_ctx, 
+                              "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+                              guid->time_low, guid->time_mid,
+                              guid->time_hi_and_version,
+                              guid->clock_seq[0],
+                              guid->clock_seq[1],
+                              guid->node[0], guid->node[1],
+                              guid->node[2], guid->node[3],
+                              guid->node[4], guid->node[5]);
+}
+
+char *GUID_string2(TALLOC_CTX *mem_ctx, const struct GUID *guid)
+{
+       char *ret, *s = GUID_string(mem_ctx, guid);
+       ret = talloc_asprintf(mem_ctx, "{%s}", s);
+       talloc_free(s);
+       return ret;
+}
+
+void ndr_print_GUID(struct ndr_print *ndr, const char *name, const struct GUID *guid)
+{
+       ndr->print(ndr, "%-25s: %s", name, GUID_string(ndr, guid));
+}
+
+BOOL policy_handle_empty(struct policy_handle *h) 
+{
+       return (h->handle_type == 0 && GUID_all_zero(&h->uuid));
+}
diff --git a/source/libndr/ndr_sec.h b/source/libndr/ndr_sec.h
new file mode 100644 (file)
index 0000000..0858eac
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef __LIBRPC_NDR_NDR_SEC_H__
+#define __LIBRPC_NDR_NDR_SEC_H__
+
+#undef _PRINTF_ATTRIBUTE
+#define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2)
+/* This file was automatically generated by mkproto.pl. DO NOT EDIT */
+
+#ifndef _PUBLIC_
+#define _PUBLIC_
+#endif
+
+
+/* The following definitions come from librpc/ndr/ndr_sec_helper.c  */
+
+size_t ndr_size_dom_sid(const struct dom_sid *sid);
+size_t ndr_length_dom_sid(const struct dom_sid *sid);
+size_t ndr_size_security_ace(const struct security_ace *ace);
+size_t ndr_size_security_acl(const struct security_acl *acl);
+size_t ndr_size_security_descriptor(const struct security_descriptor *sd);
+void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, const struct dom_sid *sid);
+void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, const struct dom_sid *sid);
+void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct dom_sid *sid);
+char *dom_sid_string(TALLOC_CTX *mem_ctx, const struct dom_sid *sid);
+
+/* The following definitions come from librpc/ndr/ndr_sec.c  */
+
+NTSTATUS ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid);
+NTSTATUS ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid);
+NTSTATUS ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid);
+NTSTATUS ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid);
+#undef _PRINTF_ATTRIBUTE
+#define _PRINTF_ATTRIBUTE(a1, a2)
+
+#endif /* __LIBRPC_NDR_NDR_SEC_H__ */
+
diff --git a/source/libndr/ndr_sec_helper.c b/source/libndr/ndr_sec_helper.c
new file mode 100644 (file)
index 0000000..edbdd9a
--- /dev/null
@@ -0,0 +1,187 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   fast routines for getting the wire size of security objects
+
+   Copyright (C) Andrew Tridgell 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
+   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"
+
+/*
+  return the wire size of a dom_sid
+*/
+size_t ndr_size_dom_sid(const struct dom_sid *sid, int flags)
+{
+       if (!sid) return 0;
+       return 8 + 4*sid->num_auths;
+}
+
+/*
+  return the wire size of a security_ace
+*/
+size_t ndr_size_security_ace(const struct security_ace *ace, int flags)
+{
+       if (!ace) return 0;
+       return 8 + ndr_size_dom_sid(&ace->trustee, flags);
+}
+
+
+/*
+  return the wire size of a security_acl
+*/
+size_t ndr_size_security_acl(const struct security_acl *acl, int flags)
+{
+       size_t ret;
+       int i;
+       if (!acl) return 0;
+       ret = 8;
+       for (i=0;i<acl->num_aces;i++) {
+               ret += ndr_size_security_ace(&acl->aces[i], flags);
+       }
+       return ret;
+}
+
+/*
+  return the wire size of a security descriptor
+*/
+size_t ndr_size_security_descriptor(const struct security_descriptor *sd, int flags)
+{
+       size_t ret;
+       if (!sd) return 0;
+       
+       ret = 20;
+       ret += ndr_size_dom_sid(sd->owner_sid, flags);
+       ret += ndr_size_dom_sid(sd->group_sid, flags);
+       ret += ndr_size_security_acl(sd->dacl, flags);
+       ret += ndr_size_security_acl(sd->sacl, flags);
+       return ret;
+}
+
+/*
+  print a dom_sid
+*/
+void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
+{
+       ndr->print(ndr, "%-25s: %s", name, dom_sid_string(ndr, sid));
+}
+
+void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
+{
+       ndr_print_dom_sid(ndr, name, sid);
+}
+
+void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
+{
+       ndr_print_dom_sid(ndr, name, sid);
+}
+
+
+/*
+  parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
+*/
+NTSTATUS ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
+{
+       uint32_t num_auths;
+       if (!(ndr_flags & NDR_SCALARS)) {
+               return NT_STATUS_OK;
+       }
+       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &num_auths));
+       NDR_CHECK(ndr_pull_dom_sid(ndr, ndr_flags, sid));
+       if (sid->num_auths != num_auths) {
+               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, 
+                                     "Bad array size %u should exceed %u", 
+                                     num_auths, sid->num_auths);
+       }
+       return NT_STATUS_OK;
+}
+
+/*
+  parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
+*/
+NTSTATUS ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
+{
+       if (!(ndr_flags & NDR_SCALARS)) {
+               return NT_STATUS_OK;
+       }
+       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, sid->num_auths));
+       return ndr_push_dom_sid(ndr, ndr_flags, sid);
+}
+
+/*
+  parse a dom_sid28 - this is a dom_sid in a fixed 28 byte buffer, so we need to ensure there are only upto 5 sub_auth
+*/
+NTSTATUS ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
+{
+       NTSTATUS status;
+       struct ndr_pull *subndr;
+
+       if (!(ndr_flags & NDR_SCALARS)) {
+               return NT_STATUS_OK;
+       }
+
+       subndr = talloc_zero(ndr, struct ndr_pull);
+       NT_STATUS_HAVE_NO_MEMORY(subndr);
+       subndr->flags           = ndr->flags;
+       subndr->current_mem_ctx = ndr->current_mem_ctx;
+
+       subndr->data            = ndr->data + ndr->offset;
+       subndr->data_size       = 28;
+       subndr->offset          = 0;
+
+       NDR_CHECK(ndr_pull_advance(ndr, 28));
+
+       status = ndr_pull_dom_sid(subndr, ndr_flags, sid);
+       if (!NT_STATUS_IS_OK(status)) {
+               /* handle a w2k bug which send random data in the buffer */
+               ZERO_STRUCTP(sid);
+       }
+
+       return NT_STATUS_OK;
+}
+
+/*
+  push a dom_sid28 - this is a dom_sid in a 28 byte fixed buffer
+*/
+NTSTATUS ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
+{
+       uint32_t old_offset;
+       uint32_t padding;
+
+       if (!(ndr_flags & NDR_SCALARS)) {
+               return NT_STATUS_OK;
+       }
+
+       if (sid->num_auths > 5) {
+               return ndr_push_error(ndr, NDR_ERR_RANGE, 
+                                     "dom_sid28 allows only upto 5 sub auth [%u]", 
+                                     sid->num_auths);
+       }
+
+       old_offset = ndr->offset;
+       NDR_CHECK(ndr_push_dom_sid(ndr, ndr_flags, sid));
+
+       padding = 28 - (ndr->offset - old_offset);
+
+       if (padding > 0) {
+               NDR_CHECK(ndr_push_zero(ndr, padding));
+       }
+
+       return NT_STATUS_OK;
+}
+
diff --git a/source/libndr/ndr_string.c b/source/libndr/ndr_string.c
new file mode 100644 (file)
index 0000000..d6c842a
--- /dev/null
@@ -0,0 +1,612 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   routines for marshalling/unmarshalling string types
+
+   Copyright (C) Andrew Tridgell 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
+   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"
+
+/**
+  pull a general string from the wire
+*/
+NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
+{
+       char *as=NULL;
+       uint32_t len1, ofs, len2;
+       uint16_t len3;
+       int ret;
+       charset_t chset = CH_UCS2;
+       unsigned byte_mul = 2;
+       unsigned flags = ndr->flags;
+       unsigned c_len_term = 0;
+
+       if (!(ndr_flags & NDR_SCALARS)) {
+               return NT_STATUS_OK;
+       }
+
+       SMB_ASSERT(!NDR_BE(ndr));
+
+       if (flags & LIBNDR_FLAG_STR_ASCII) {
+               chset = CH_DOS;
+               byte_mul = 1;
+               flags &= ~LIBNDR_FLAG_STR_ASCII;
+       }
+
+       if (flags & LIBNDR_FLAG_STR_UTF8) {
+               chset = CH_UTF8;
+               byte_mul = 1;
+               flags &= ~LIBNDR_FLAG_STR_UTF8;
+       }
+
+       flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
+       if (flags & LIBNDR_FLAG_STR_CHARLEN) {
+               c_len_term = 1;
+               flags &= ~LIBNDR_FLAG_STR_CHARLEN;
+       }
+
+       switch (flags & LIBNDR_STRING_FLAGS) {
+       case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
+       case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
+               if (ofs != 0) {
+                       return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
+                                             ndr->flags & LIBNDR_STRING_FLAGS);
+               }
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2));
+               if (len2 > len1) {
+                       return ndr_pull_error(ndr, NDR_ERR_STRING, 
+                                             "Bad string lengths len1=%u ofs=%u len2=%u\n", 
+                                             len1, ofs, len2);
+               }
+               NDR_PULL_NEED_BYTES(ndr, (len2 + c_len_term)*byte_mul);
+               if (len2 == 0) {
+                       as = talloc_strdup(ndr->current_mem_ctx, "");
+               } else {
+                       ret = convert_string_talloc(ndr->current_mem_ctx,
+                                                   chset, CH_UNIX, 
+                                                   ndr->data+ndr->offset, 
+                                                   (len2 + c_len_term)*byte_mul,
+                                                   &as, True);
+                       if (ret == -1) {
+                               return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
+                                                     "Bad character conversion");
+                       }
+               }
+               NDR_CHECK(ndr_pull_advance(ndr, (len2 + c_len_term)*byte_mul));
+
+               if (len1 != len2) {
+                       DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1, len2, as));
+               }
+
+               /* this is a way of detecting if a string is sent with the wrong
+                  termination */
+               if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
+                       if (strlen(as) < (len2 + c_len_term)) {
+                               DEBUG(6,("short string '%s'\n", as));
+                       }
+               } else {
+                       if (strlen(as) == (len2 + c_len_term)) {
+                               DEBUG(6,("long string '%s'\n", as));
+                       }
+               }
+               *s = as;
+               break;
+
+       case LIBNDR_FLAG_STR_SIZE4:
+       case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
+               NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
+               if (len1 == 0) {
+                       as = talloc_strdup(ndr->current_mem_ctx, "");
+               } else {
+                       ret = convert_string_talloc(ndr->current_mem_ctx,
+                                                   chset, CH_UNIX, 
+                                                   ndr->data+ndr->offset, 
+                                                   (len1 + c_len_term)*byte_mul,
+                                                   &as, False);
+                       if (ret == -1) {
+                               return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
+                                                     "Bad character conversion");
+                       }
+               }
+               NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
+
+               /* this is a way of detecting if a string is sent with the wrong
+                  termination */
+               if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
+                       if (strlen(as) < (len1 + c_len_term)) {
+                               DEBUG(6,("short string '%s'\n", as));
+                       }
+               } else {
+                       if (strlen(as) == (len1 + c_len_term)) {
+                               DEBUG(6,("long string '%s'\n", as));
+                       }
+               }
+               *s = as;
+               break;
+
+       case LIBNDR_FLAG_STR_LEN4:
+       case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
+               if (ofs != 0) {
+                       return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
+                                             ndr->flags & LIBNDR_STRING_FLAGS);
+               }
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
+               NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
+               if (len1 == 0) {
+                       as = talloc_strdup(ndr->current_mem_ctx, "");
+               } else {
+                       ret = convert_string_talloc(ndr->current_mem_ctx,
+                                                   chset, CH_UNIX, 
+                                                   ndr->data+ndr->offset, 
+                                                   (len1 + c_len_term)*byte_mul,
+                                                   &as, False);
+                       if (ret == -1) {
+                               return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
+                                                     "Bad character conversion");
+                       }
+               }
+               NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
+
+               /* this is a way of detecting if a string is sent with the wrong
+                  termination */
+               if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
+                       if (strlen(as) < (len1 + c_len_term)) {
+                               DEBUG(6,("short string '%s'\n", as));
+                       }
+               } else {
+                       if (strlen(as) == (len1 + c_len_term)) {
+                               DEBUG(6,("long string '%s'\n", as));
+                       }
+               }
+               *s = as;
+               break;
+
+
+       case LIBNDR_FLAG_STR_SIZE2:
+       case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
+               NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
+               NDR_PULL_NEED_BYTES(ndr, (len3 + c_len_term)*byte_mul);
+               if (len3 == 0) {
+                       as = talloc_strdup(ndr->current_mem_ctx, "");
+               } else {
+                       ret = convert_string_talloc(ndr->current_mem_ctx,
+                                                   chset, CH_UNIX, 
+                                                   ndr->data+ndr->offset, 
+                                                   (len3 + c_len_term)*byte_mul,
+                                                   &as, False);
+                       if (ret == -1) {
+                               return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
+                                                     "Bad character conversion");
+                       }
+               }
+               NDR_CHECK(ndr_pull_advance(ndr, (len3 + c_len_term)*byte_mul));
+
+               /* this is a way of detecting if a string is sent with the wrong
+                  termination */
+               if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
+                       if (strlen(as) < (len3 + c_len_term)) {
+                               DEBUG(6,("short string '%s'\n", as));
+                       }
+               } else {
+                       if (strlen(as) == (len3 + c_len_term)) {
+                               DEBUG(6,("long string '%s'\n", as));
+                       }
+               }
+               *s = as;
+               break;
+
+       case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
+               NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
+               NDR_PULL_NEED_BYTES(ndr, len3);
+               if (len3 == 0) {
+                       as = talloc_strdup(ndr->current_mem_ctx, "");
+               } else {
+                       ret = convert_string_talloc(ndr->current_mem_ctx,
+                                                   chset, CH_UNIX, 
+                                                   ndr->data+ndr->offset, 
+                                                   len3, &as, False);
+                       if (ret == -1) {
+                               return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
+                                                     "Bad character conversion");
+                       }
+               }
+               NDR_CHECK(ndr_pull_advance(ndr, len3));
+               *s = as;
+               break;
+
+       case LIBNDR_FLAG_STR_NULLTERM:
+               if (byte_mul == 1) {
+                       len1 = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
+               } else {
+                       len1 = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
+               }
+               ret = convert_string_talloc(ndr->current_mem_ctx,
+                                           chset, CH_UNIX, 
+                                           ndr->data+ndr->offset, 
+                                           len1, &as, False);
+               if (ret == -1) {
+                       return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
+                                             "Bad character conversion");
+               }
+               NDR_CHECK(ndr_pull_advance(ndr, len1));
+               *s = as;
+               break;
+
+       case LIBNDR_FLAG_STR_FIXLEN15:
+       case LIBNDR_FLAG_STR_FIXLEN32:
+               len1 = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
+               NDR_PULL_NEED_BYTES(ndr, len1*byte_mul);
+               ret = convert_string_talloc(ndr->current_mem_ctx,
+                                           chset, CH_UNIX, 
+                                           ndr->data+ndr->offset, 
+                                           len1*byte_mul, &as, False);
+               if (ret == -1) {
+                       return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
+                                             "Bad character conversion");
+               }
+               NDR_CHECK(ndr_pull_advance(ndr, len1*byte_mul));
+               *s = as;
+               break;
+
+       default:
+               return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
+                                     ndr->flags & LIBNDR_STRING_FLAGS);
+       }
+
+       return NT_STATUS_OK;
+}
+
+
+/**
+  push a general string onto the wire
+*/
+NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
+{
+       ssize_t s_len, c_len, d_len;
+       charset_t chset = CH_UCS2;
+       unsigned flags = ndr->flags;
+       unsigned byte_mul = 2;
+       uint8_t *dest = NULL;
+
+       if (!(ndr_flags & NDR_SCALARS)) {
+               return NT_STATUS_OK;
+       }
+
+       SMB_ASSERT(!NDR_BE(ndr));
+       
+       s_len = s?strlen(s):0;
+
+       if (flags & LIBNDR_FLAG_STR_ASCII) {
+               chset = CH_DOS;
+               byte_mul = 1;
+               flags &= ~LIBNDR_FLAG_STR_ASCII;
+       }
+
+       if (flags & LIBNDR_FLAG_STR_UTF8) {
+               chset = CH_UTF8;
+               byte_mul = 1;
+               flags &= ~LIBNDR_FLAG_STR_UTF8;
+       }
+
+       flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
+
+       if (!(flags & 
+             (LIBNDR_FLAG_STR_NOTERM |
+              LIBNDR_FLAG_STR_FIXLEN15 |
+              LIBNDR_FLAG_STR_FIXLEN32))) {
+               s_len++;
+       }
+       d_len = convert_string_talloc(ndr, CH_UNIX, chset, s, s_len, &dest,
+                                     False);
+       if (d_len == -1) {
+               return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
+                                     "Bad character conversion");
+       }
+
+       if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
+               c_len = d_len;
+               flags &= ~LIBNDR_FLAG_STR_BYTESIZE;
+       } else if (flags & LIBNDR_FLAG_STR_CHARLEN) {
+               c_len = (d_len / byte_mul)-1;
+               flags &= ~LIBNDR_FLAG_STR_CHARLEN;
+       } else {
+               c_len = d_len / byte_mul;
+       }
+
+       switch ((flags & LIBNDR_STRING_FLAGS) & ~LIBNDR_FLAG_STR_NOTERM) {
+       case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
+               NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+               break;
+
+       case LIBNDR_FLAG_STR_LEN4:
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
+               NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+               break;
+
+       case LIBNDR_FLAG_STR_SIZE4:
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
+               NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+               break;
+
+       case LIBNDR_FLAG_STR_SIZE2:
+               NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len));
+               NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+               break;
+
+       case LIBNDR_FLAG_STR_NULLTERM:
+               NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+               break;
+
+       case LIBNDR_FLAG_STR_FIXLEN15:
+       case LIBNDR_FLAG_STR_FIXLEN32: {
+               ssize_t fix_len = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
+               uint32_t pad_len = fix_len - d_len;
+               if (d_len > fix_len) {
+                       return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
+                                             "Bad character conversion");
+               }
+               NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+               if (pad_len != 0) {
+                       NDR_CHECK(ndr_push_zero(ndr, pad_len));
+               }
+               break;
+       }
+
+       default:
+               return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
+                                     ndr->flags & LIBNDR_STRING_FLAGS);
+       }
+
+       talloc_free(dest);
+
+       return NT_STATUS_OK;
+}
+
+/**
+  push a general string onto the wire
+*/
+size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
+{
+       size_t c_len;
+       unsigned flags = ndr->flags;
+       unsigned byte_mul = 2;
+       unsigned c_len_term = 1;
+
+       if (flags & LIBNDR_FLAG_STR_FIXLEN32) {
+               return 32;
+       }
+       if (flags & LIBNDR_FLAG_STR_FIXLEN15) {
+               return 15;
+       }
+       
+       c_len = s?strlen(s):0;
+
+       if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) {
+               byte_mul = 1;
+       }
+
+       if (flags & LIBNDR_FLAG_STR_NOTERM) {
+               c_len_term = 0;
+       }
+
+       c_len = c_len + c_len_term;
+
+       if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
+               c_len = c_len * byte_mul;
+       }
+
+       return c_len;
+}
+
+void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
+{
+       if (s) {
+               ndr->print(ndr, "%-25s: '%s'", name, s);
+       } else {
+               ndr->print(ndr, "%-25s: NULL", name);
+       }
+}
+
+uint32_t ndr_size_string(int ret, const char * const* string, int flags) 
+{
+       /* FIXME: Is this correct for all strings ? */
+       if(!(*string)) return ret;
+       return ret+strlen(*string)+1;
+}
+
+/**
+  pull a general string array from the wire
+*/
+NTSTATUS ndr_pull_string_array(struct ndr_pull *ndr, int ndr_flags, const char ***_a)
+{
+       const char **a = *_a;
+       uint32_t count;
+
+       if (!(ndr_flags & NDR_SCALARS)) {
+               return NT_STATUS_OK;
+       }
+
+       for (count = 0;; count++) {
+               TALLOC_CTX *tmp_ctx;
+               const char *s = NULL;
+               a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2);
+               NT_STATUS_HAVE_NO_MEMORY(a);
+               a[count]   = NULL;
+               a[count+1]   = NULL;
+
+               tmp_ctx = ndr->current_mem_ctx;
+               ndr->current_mem_ctx = a;
+               NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
+               ndr->current_mem_ctx = tmp_ctx;
+               if (strcmp("", s)==0) {
+                       a[count] = NULL;
+                       break;
+               } else {
+                       a[count] = s;
+               }
+       }
+
+       *_a =a;
+       return NT_STATUS_OK;
+}
+
+/**
+  push a general string array onto the wire
+*/
+NTSTATUS ndr_push_string_array(struct ndr_push *ndr, int ndr_flags, const char **a)
+{
+       uint32_t count;
+
+       if (!(ndr_flags & NDR_SCALARS)) {
+               return NT_STATUS_OK;
+       }
+
+       for (count = 0; a && a[count]; count++) {
+               NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
+       }
+
+       NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
+
+       return NT_STATUS_OK;
+}
+
+void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a)
+{
+       uint32_t count;
+       uint32_t i;
+
+       for (count = 0; a && a[count]; count++) {}
+
+       ndr->print(ndr, "%s: ARRAY(%d)", name, count);
+       ndr->depth++;
+       for (i=0;i<count;i++) {
+               char *idx=NULL;
+               asprintf(&idx, "[%d]", i);
+               if (idx) {
+                       ndr_print_string(ndr, idx, a[i]);
+                       free(idx);
+               }
+       }
+       ndr->depth--;
+}
+
+/**
+ * Return number of elements in a string including the last (zeroed) element 
+ */
+uint32_t ndr_string_length(const void *_var, uint32_t element_size)
+{
+       uint32_t i;
+       uint8_t zero[4] = {0,0,0,0};
+       const char *var = (const char *)_var;
+
+       for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++);
+
+       return i+1;
+}
+
+NTSTATUS ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
+{
+       uint32_t i;
+       struct ndr_pull_save save_offset;
+
+       ndr_pull_save(ndr, &save_offset);
+       ndr_pull_advance(ndr, (count - 1) * element_size);
+       NDR_PULL_NEED_BYTES(ndr, element_size);
+
+       for (i = 0; i < element_size; i++) {
+                if (ndr->data[ndr->offset+i] != 0) {
+                       ndr_pull_restore(ndr, &save_offset);
+
+                       return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries");
+                }
+       }
+
+       ndr_pull_restore(ndr, &save_offset);
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_charset(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, int chset)
+{
+       int ret;
+       if (length == 0) {
+               *var = talloc_strdup(ndr->current_mem_ctx, "");
+               return NT_STATUS_OK;
+       }
+
+       SMB_ASSERT (!NDR_BE(ndr) || chset != CH_UCS2);
+
+       NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
+
+       ret = convert_string_talloc(ndr->current_mem_ctx,
+                                   chset, CH_UNIX, 
+                                   ndr->data+ndr->offset, 
+                                   length*byte_mul,
+                                   var, False);
+       if (ret == -1) {
+               return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
+                                     "Bad character conversion");
+       }
+       NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_push_charset(struct ndr_push *ndr, int ndr_flags, const char *var,
+                         uint32_t length, uint8_t byte_mul, charset_t chset)
+{
+       ssize_t ret, required;
+
+       SMB_ASSERT(!NDR_BE(ndr) || chset != CH_UCS2);
+
+       required = byte_mul * length;
+       
+       NDR_PUSH_NEED_BYTES(ndr, required);
+       ret = convert_string(CH_UNIX, chset, 
+                            var, strlen(var),
+                            ndr->data+ndr->offset, required, False);
+       if (ret == -1) {
+               return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
+                                     "Bad character conversion");
+       }
+
+       /* Make sure the remaining part of the string is filled with zeroes */
+       if (ret < required) {
+               memset(ndr->data+ndr->offset+ret, 0, required-ret);
+       }
+
+       ndr->offset += required;
+
+       return NT_STATUS_OK;
+}
+
+/* Return number of elements in a string in the specified charset */
+uint32_t ndr_charset_length(const void *var, int chset)
+{
+       /* FIXME: Treat special chars special here, taking chset into account */
+       /* Also include 0 byte */
+       return strlen((const char *)var)+1;
+}
diff --git a/source/libndr/security.h b/source/libndr/security.h
new file mode 100644 (file)
index 0000000..8f790f3
--- /dev/null
@@ -0,0 +1,260 @@
+/* header auto-generated by pidl */
+
+#ifndef _HEADER_security
+#define _HEADER_security
+
+#define SEC_MASK_GENERIC       ( 0xF0000000 )
+#define SEC_MASK_FLAGS ( 0x0F000000 )
+#define SEC_MASK_STANDARD      ( 0x00FF0000 )
+#define SEC_MASK_SPECIFIC      ( 0x0000FFFF )
+#define SEC_GENERIC_ALL        ( 0x10000000 )
+#define SEC_GENERIC_EXECUTE    ( 0x20000000 )
+#define SEC_GENERIC_WRITE      ( 0x40000000 )
+#define SEC_GENERIC_READ       ( 0x80000000 )
+#define SEC_FLAG_SYSTEM_SECURITY       ( 0x01000000 )
+#define SEC_FLAG_MAXIMUM_ALLOWED       ( 0x02000000 )
+#define SEC_STD_DELETE ( 0x00010000 )
+#define SEC_STD_READ_CONTROL   ( 0x00020000 )
+#define SEC_STD_WRITE_DAC      ( 0x00040000 )
+#define SEC_STD_WRITE_OWNER    ( 0x00080000 )
+#define SEC_STD_SYNCHRONIZE    ( 0x00100000 )
+#define SEC_STD_REQUIRED       ( 0x000F0000 )
+#define SEC_STD_ALL    ( 0x001F0000 )
+#define SEC_FILE_READ_DATA     ( 0x00000001 )
+#define SEC_FILE_WRITE_DATA    ( 0x00000002 )
+#define SEC_FILE_APPEND_DATA   ( 0x00000004 )
+#define SEC_FILE_READ_EA       ( 0x00000008 )
+#define SEC_FILE_WRITE_EA      ( 0x00000010 )
+#define SEC_FILE_EXECUTE       ( 0x00000020 )
+#define SEC_FILE_READ_ATTRIBUTE        ( 0x00000080 )
+#define SEC_FILE_WRITE_ATTRIBUTE       ( 0x00000100 )
+#define SEC_FILE_ALL   ( 0x000001ff )
+#define SEC_DIR_LIST   ( 0x00000001 )
+#define SEC_DIR_ADD_FILE       ( 0x00000002 )
+#define SEC_DIR_ADD_SUBDIR     ( 0x00000004 )
+#define SEC_DIR_READ_EA        ( 0x00000008 )
+#define SEC_DIR_WRITE_EA       ( 0x00000010 )
+#define SEC_DIR_TRAVERSE       ( 0x00000020 )
+#define SEC_DIR_DELETE_CHILD   ( 0x00000040 )
+#define SEC_DIR_READ_ATTRIBUTE ( 0x00000080 )
+#define SEC_DIR_WRITE_ATTRIBUTE        ( 0x00000100 )
+#define SEC_REG_QUERY_VALUE    ( 0x00000001 )
+#define SEC_REG_SET_VALUE      ( 0x00000002 )
+#define SEC_REG_CREATE_SUBKEY  ( 0x00000004 )
+#define SEC_REG_ENUM_SUBKEYS   ( 0x00000008 )
+#define SEC_REG_NOTIFY ( 0x00000010 )
+#define SEC_REG_CREATE_LINK    ( 0x00000020 )
+#define SEC_ADS_CREATE_CHILD   ( 0x00000001 )
+#define SEC_ADS_DELETE_CHILD   ( 0x00000002 )
+#define SEC_ADS_LIST   ( 0x00000004 )
+#define SEC_ADS_SELF_WRITE     ( 0x00000008 )
+#define SEC_ADS_READ_PROP      ( 0x00000010 )
+#define SEC_ADS_WRITE_PROP     ( 0x00000020 )
+#define SEC_ADS_DELETE_TREE    ( 0x00000040 )
+#define SEC_ADS_LIST_OBJECT    ( 0x00000080 )
+#define SEC_ADS_CONTROL_ACCESS ( 0x00000100 )
+#define SEC_RIGHTS_FILE_READ   ( SEC_STD_READ_CONTROL|SEC_STD_SYNCHRONIZE|SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_READ_EA )
+#define SEC_RIGHTS_FILE_WRITE  ( SEC_STD_READ_CONTROL|SEC_STD_SYNCHRONIZE|SEC_FILE_WRITE_DATA|SEC_FILE_WRITE_ATTRIBUTE|SEC_FILE_WRITE_EA|SEC_FILE_APPEND_DATA )
+#define SEC_RIGHTS_FILE_EXECUTE        ( SEC_STD_SYNCHRONIZE|SEC_STD_READ_CONTROL|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_EXECUTE )
+#define SEC_RIGHTS_FILE_ALL    ( SEC_STD_ALL|SEC_FILE_ALL )
+#define SEC_RIGHTS_DIR_READ    ( SEC_RIGHTS_FILE_READ )
+#define SEC_RIGHTS_DIR_WRITE   ( SEC_RIGHTS_FILE_WRITE )
+#define SEC_RIGHTS_DIR_EXECUTE ( SEC_RIGHTS_FILE_EXECUTE )
+#define SEC_RIGHTS_DIR_ALL     ( SEC_RIGHTS_FILE_ALL )
+#define SID_NULL       ( "S-1-0-0" )
+#define SID_WORLD_DOMAIN       ( "S-1-1" )
+#define SID_WORLD      ( "S-1-1-0" )
+#define SID_CREATOR_OWNER_DOMAIN       ( "S-1-3" )
+#define SID_CREATOR_OWNER      ( "S-1-3-0" )
+#define SID_CREATOR_GROUP      ( "S-1-3-1" )
+#define SID_NT_AUTHORITY       ( "S-1-5" )
+#define SID_NT_DIALUP  ( "S-1-5-1" )
+#define SID_NT_NETWORK ( "S-1-5-2" )
+#define SID_NT_BATCH   ( "S-1-5-3" )
+#define SID_NT_INTERACTIVE     ( "S-1-5-4" )
+#define SID_NT_SERVICE ( "S-1-5-6" )
+#define SID_NT_ANONYMOUS       ( "S-1-5-7" )
+#define SID_NT_PROXY   ( "S-1-5-8" )
+#define SID_NT_ENTERPRISE_DCS  ( "S-1-5-9" )
+#define SID_NT_SELF    ( "S-1-5-10" )
+#define SID_NT_AUTHENTICATED_USERS     ( "S-1-5-11" )
+#define SID_NT_RESTRICTED      ( "S-1-5-12" )
+#define SID_NT_TERMINAL_SERVER_USERS   ( "S-1-5-13" )
+#define SID_NT_REMOTE_INTERACTIVE      ( "S-1-5-14" )
+#define SID_NT_THIS_ORGANISATION       ( "S-1-5-15" )
+#define SID_NT_SYSTEM  ( "S-1-5-18" )
+#define SID_NT_LOCAL_SERVICE   ( "S-1-5-19" )
+#define SID_NT_NETWORK_SERVICE ( "S-1-5-20" )
+#define SID_BUILTIN    ( "S-1-5-32" )
+#define SID_BUILTIN_ADMINISTRATORS     ( "S-1-5-32-544" )
+#define SID_BUILTIN_USERS      ( "S-1-5-32-545" )
+#define SID_BUILTIN_GUESTS     ( "S-1-5-32-546" )
+#define SID_BUILTIN_POWER_USERS        ( "S-1-5-32-547" )
+#define SID_BUILTIN_ACCOUNT_OPERATORS  ( "S-1-5-32-548" )
+#define SID_BUILTIN_SERVER_OPERATORS   ( "S-1-5-32-549" )
+#define SID_BUILTIN_PRINT_OPERATORS    ( "S-1-5-32-550" )
+#define SID_BUILTIN_BACKUP_OPERATORS   ( "S-1-5-32-551" )
+#define SID_BUILTIN_REPLICATOR ( "S-1-5-32-552" )
+#define SID_BUILTIN_RAS_SERVERS        ( "S-1-5-32-553" )
+#define SID_BUILTIN_PREW2K     ( "S-1-5-32-554" )
+#define DOMAIN_RID_LOGON       ( 9 )
+#define DOMAIN_RID_ADMINISTRATOR       ( 500 )
+#define DOMAIN_RID_GUEST       ( 501 )
+#define DOMAIN_RID_ADMINS      ( 512 )
+#define DOMAIN_RID_USERS       ( 513 )
+#define DOMAIN_RID_DCS ( 516 )
+#define DOMAIN_RID_CERT_ADMINS ( 517 )
+#define DOMAIN_RID_SCHEMA_ADMINS       ( 518 )
+#define DOMAIN_RID_ENTERPRISE_ADMINS   ( 519 )
+#define NT4_ACL_REVISION       ( SECURITY_ACL_REVISION_NT4 )
+#define SD_REVISION    ( SECURITY_DESCRIPTOR_REVISION_1 )
+enum sec_privilege {
+       SEC_PRIV_SECURITY=1,
+       SEC_PRIV_BACKUP=2,
+       SEC_PRIV_RESTORE=3,
+       SEC_PRIV_SYSTEMTIME=4,
+       SEC_PRIV_SHUTDOWN=5,
+       SEC_PRIV_REMOTE_SHUTDOWN=6,
+       SEC_PRIV_TAKE_OWNERSHIP=7,
+       SEC_PRIV_DEBUG=8,
+       SEC_PRIV_SYSTEM_ENVIRONMENT=9,
+       SEC_PRIV_SYSTEM_PROFILE=10,
+       SEC_PRIV_PROFILE_SINGLE_PROCESS=11,
+       SEC_PRIV_INCREASE_BASE_PRIORITY=12,
+       SEC_PRIV_LOAD_DRIVER=13,
+       SEC_PRIV_CREATE_PAGEFILE=14,
+       SEC_PRIV_INCREASE_QUOTA=15,
+       SEC_PRIV_CHANGE_NOTIFY=16,
+       SEC_PRIV_UNDOCK=17,
+       SEC_PRIV_MANAGE_VOLUME=18,
+       SEC_PRIV_IMPERSONATE=19,
+       SEC_PRIV_CREATE_GLOBAL=20,
+       SEC_PRIV_ENABLE_DELEGATION=21,
+       SEC_PRIV_INTERACTIVE_LOGON=22,
+       SEC_PRIV_NETWORK_LOGON=23,
+       SEC_PRIV_REMOTE_INTERACTIVE_LOGON=24
+};
+
+struct dom_sid {
+       uint8_t sid_rev_num;
+       int8_t num_auths;/* [range(0 15)] */
+       uint8_t id_auth[6];
+       uint32_t *sub_auths;
+}/* [noprint,gensize,noejs,public,nosize] */;
+
+/* bitmap security_ace_flags */
+#define SEC_ACE_FLAG_OBJECT_INHERIT ( 0x01 )
+#define SEC_ACE_FLAG_CONTAINER_INHERIT ( 0x02 )
+#define SEC_ACE_FLAG_NO_PROPAGATE_INHERIT ( 0x04 )
+#define SEC_ACE_FLAG_INHERIT_ONLY ( 0x08 )
+#define SEC_ACE_FLAG_INHERITED_ACE ( 0x10 )
+#define SEC_ACE_FLAG_VALID_INHERIT ( 0x0f )
+#define SEC_ACE_FLAG_SUCCESSFUL_ACCESS ( 0x40 )
+#define SEC_ACE_FLAG_FAILED_ACCESS ( 0x80 )
+
+enum security_ace_type {
+       SEC_ACE_TYPE_ACCESS_ALLOWED=0,
+       SEC_ACE_TYPE_ACCESS_DENIED=1,
+       SEC_ACE_TYPE_SYSTEM_AUDIT=2,
+       SEC_ACE_TYPE_SYSTEM_ALARM=3,
+       SEC_ACE_TYPE_ALLOWED_COMPOUND=4,
+       SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT=5,
+       SEC_ACE_TYPE_ACCESS_DENIED_OBJECT=6,
+       SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT=7,
+       SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT=8
+};
+
+/* bitmap security_ace_object_flags */
+#define SEC_ACE_OBJECT_TYPE_PRESENT ( 0x00000001 )
+#define SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT ( 0x00000002 )
+
+union security_ace_object_type {
+       struct GUID type;/* [case(SEC_ACE_OBJECT_TYPE_PRESENT)] */
+}/* [nodiscriminant] */;
+
+union security_ace_object_inherited_type {
+       struct GUID inherited_type;/* [case(SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)] */
+}/* [nodiscriminant] */;
+
+struct security_ace_object {
+       uint32_t flags;
+       union security_ace_object_type type;/* [switch_is(flags&SEC_ACE_OBJECT_TYPE_PRESENT)] */
+       union security_ace_object_inherited_type inherited_type;/* [switch_is(flags&SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)] */
+};
+
+union security_ace_object_ctr {
+       struct security_ace_object object;/* [case(SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT)] */
+}/* [nodiscriminant] */;
+
+struct security_ace {
+       enum security_ace_type type;
+       uint8_t flags;
+       uint16_t size;/* [value(ndr_size_security_ace(r,ndr->flags))] */
+       uint32_t access_mask;
+       union security_ace_object_ctr object;/* [switch_is(type)] */
+       struct dom_sid trustee;
+}/* [gensize,public,nosize] */;
+
+enum security_acl_revision {
+       SECURITY_ACL_REVISION_NT4=2,
+       SECURITY_ACL_REVISION_ADS=4
+};
+
+struct security_acl {
+       enum security_acl_revision revision;
+       uint16_t size;/* [value(ndr_size_security_acl(r,ndr->flags))] */
+       uint32_t num_aces;/* [range(0 1000)] */
+       struct security_ace *aces;
+}/* [gensize,public,nosize] */;
+
+enum security_descriptor_revision {
+       SECURITY_DESCRIPTOR_REVISION_1=1
+};
+
+/* bitmap security_descriptor_type */
+#define SEC_DESC_OWNER_DEFAULTED ( 0x0001 )
+#define SEC_DESC_GROUP_DEFAULTED ( 0x0002 )
+#define SEC_DESC_DACL_PRESENT ( 0x0004 )
+#define SEC_DESC_DACL_DEFAULTED ( 0x0008 )
+#define SEC_DESC_SACL_PRESENT ( 0x0010 )
+#define SEC_DESC_SACL_DEFAULTED ( 0x0020 )
+#define SEC_DESC_DACL_TRUSTED ( 0x0040 )
+#define SEC_DESC_SERVER_SECURITY ( 0x0080 )
+#define SEC_DESC_DACL_AUTO_INHERIT_REQ ( 0x0100 )
+#define SEC_DESC_SACL_AUTO_INHERIT_REQ ( 0x0200 )
+#define SEC_DESC_DACL_AUTO_INHERITED ( 0x0400 )
+#define SEC_DESC_SACL_AUTO_INHERITED ( 0x0800 )
+#define SEC_DESC_DACL_PROTECTED ( 0x1000 )
+#define SEC_DESC_SACL_PROTECTED ( 0x2000 )
+#define SEC_DESC_RM_CONTROL_VALID ( 0x4000 )
+#define SEC_DESC_SELF_RELATIVE ( 0x8000 )
+
+struct security_descriptor {
+       enum security_descriptor_revision revision;
+       uint16_t type;
+       struct dom_sid *owner_sid;/* [relative] */
+       struct dom_sid *group_sid;/* [relative] */
+       struct security_acl *sacl;/* [relative] */
+       struct security_acl *dacl;/* [relative] */
+}/* [gensize,public,flag(LIBNDR_FLAG_LITTLE_ENDIAN),nosize] */;
+
+struct sec_desc_buf {
+       uint32_t sd_size;/* [value(ndr_size_security_descriptor(sd,ndr->flags)),range(0 0x40000)] */
+       struct security_descriptor *sd;/* [unique,subcontext(4)] */
+}/* [public] */;
+
+struct security_token {
+       struct dom_sid *user_sid;/* [unique] */
+       struct dom_sid *group_sid;/* [unique] */
+       uint32_t num_sids;
+       struct dom_sid **sids;/* [unique,size_is(num_sids)] */
+       uint64_t privilege_mask;
+}/* [public] */;
+
+/* bitmap security_secinfo */
+#define SECINFO_OWNER ( 0x00000001 )
+#define SECINFO_GROUP ( 0x00000002 )
+#define SECINFO_DACL ( 0x00000004 )
+#define SECINFO_SACL ( 0x00000008 )
+
+#endif /* _HEADER_security */
diff --git a/source/libndr/sid.c b/source/libndr/sid.c
new file mode 100644 (file)
index 0000000..0bb42a3
--- /dev/null
@@ -0,0 +1,97 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   libndr interface
+
+   Copyright (C) Andrew Tridgell 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
+   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"
+
+NTSTATUS ndr_push_dom_sid(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *r)
+{
+       uint32_t cntr_sub_auths_0;
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->sid_rev_num));
+               NDR_CHECK(ndr_push_int8(ndr, NDR_SCALARS, r->num_auths));
+               NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
+               for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->sub_auths[cntr_sub_auths_0]));
+               }
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+       }
+       return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_dom_sid(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *r)
+{
+       uint32_t cntr_sub_auths_0;
+       TALLOC_CTX *_mem_save_sub_auths_0;
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->sid_rev_num));
+               NDR_CHECK(ndr_pull_int8(ndr, NDR_SCALARS, &r->num_auths));
+               if (r->num_auths < 0 || r->num_auths > 15) {
+                       return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range");
+               }
+               NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
+               NDR_PULL_ALLOC_N(ndr, r->sub_auths, r->num_auths);
+               _mem_save_sub_auths_0 = NDR_PULL_GET_MEM_CTX(ndr);
+               NDR_PULL_SET_MEM_CTX(ndr, r->sub_auths, 0);
+               for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
+                       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sub_auths[cntr_sub_auths_0]));
+               }
+               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sub_auths_0, 0);
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+       }
+       return NT_STATUS_OK;
+}
+
+/*
+  convert a dom_sid to a string
+*/
+char *dom_sid_string(TALLOC_CTX *mem_ctx, const struct dom_sid *sid)
+{
+       int i, ofs, maxlen;
+       uint32_t ia;
+       char *ret;
+       
+       if (!sid) {
+               return talloc_strdup(mem_ctx, "(NULL SID)");
+       }
+
+       maxlen = sid->num_auths * 11 + 25;
+       ret = talloc_size(mem_ctx, maxlen);
+       if (!ret) return talloc_strdup(mem_ctx, "(SID ERR)");
+
+       ia = (sid->id_auth[5]) +
+               (sid->id_auth[4] << 8 ) +
+               (sid->id_auth[3] << 16) +
+               (sid->id_auth[2] << 24);
+
+       ofs = snprintf(ret, maxlen, "S-%u-%lu", 
+                      (unsigned int)sid->sid_rev_num, (unsigned long)ia);
+
+       for (i = 0; i < sid->num_auths; i++) {
+               ofs += snprintf(ret + ofs, maxlen - ofs, "-%lu", (unsigned long)sid->sub_auths[i]);
+       }
+       
+       return ret;
+}
index 7f5b5d7fa57ba97c9c314064ccadecdb8d9da5b2..4c3c4f456508c054127920c2eedcb8249a70e37e 100644 (file)
@@ -1394,8 +1394,9 @@ NTSTATUS cli_start_connection(struct cli_state **output_cli,
        if (!my_name) 
                my_name = global_myname();
        
-       if (!(cli = cli_initialise(NULL)))
+       if (!(cli = cli_initialise())) {
                return NT_STATUS_NO_MEMORY;
+       }
        
        make_nmb_name(&calling, my_name, 0x0);
        make_nmb_name(&called , dest_host, 0x20);
@@ -1495,6 +1496,8 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
        struct cli_state *cli = NULL;
        int pw_len = password ? strlen(password)+1 : 0;
 
+       *output_cli = NULL;
+
        if (password == NULL) {
                password = "";
        }
@@ -1513,8 +1516,9 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
                        nt_status = cli_nt_error(cli);
                        DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status)));
                        cli_shutdown(cli);
-                       if (NT_STATUS_IS_OK(nt_status)) 
+                       if (NT_STATUS_IS_OK(nt_status)) {
                                nt_status = NT_STATUS_UNSUCCESSFUL;
+                       }
                        return nt_status;
                }
        } 
@@ -1541,7 +1545,7 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
 ****************************************************************************/
 
-BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost,
+BOOL attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
                                      struct in_addr *pdest_ip)
 {
        struct nmb_name calling, called;
@@ -1553,12 +1557,13 @@ BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost,
         * then use *SMBSERVER immediately.
         */
 
-       if(is_ipaddress(desthost))
+       if(is_ipaddress(desthost)) {
                make_nmb_name(&called, "*SMBSERVER", 0x20);
-       else
+       } else {
                make_nmb_name(&called, desthost, 0x20);
+       }
 
-       if (!cli_session_request(cli, &calling, &called)) {
+       if (!cli_session_request(*ppcli, &calling, &called)) {
                struct nmb_name smbservername;
 
                make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
@@ -1575,23 +1580,23 @@ BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost,
                         */
 
                        DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
-with error %s.\n", desthost, cli_errstr(cli) ));
+with error %s.\n", desthost, cli_errstr(*ppcli) ));
                        return False;
                }
 
-               /*
-                * We need to close the connection here but can't call cli_shutdown as
-                * will free an allocated cli struct. cli_close_connection was invented
-                * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>.
-                */
+               /* Try again... */
+               cli_shutdown(*ppcli);
 
-               cli_close_connection(cli);
+               *ppcli = cli_initialise();
+               if (!*ppcli) {
+                       /* Out of memory... */
+                       return False;
+               }
 
-               if (!cli_initialise(cli) ||
-                               !cli_connect(cli, desthost, pdest_ip) ||
-                               !cli_session_request(cli, &calling, &smbservername)) {
+               if (!cli_connect(*ppcli, desthost, pdest_ip) ||
+                               !cli_session_request(*ppcli, &calling, &smbservername)) {
                        DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
-name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
+name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
                        return False;
                }
        }
index e564bc429573f57059e4db334eadedf95e6d62d3..4280b0628eb4cd0a79f0d7b0507719ec9c4bd618 100644 (file)
@@ -51,7 +51,7 @@ static struct client_connection *connections;
 static struct cli_state *do_connect( const char *server, const char *share,
                                      BOOL show_sessetup )
 {
-       struct cli_state *c;
+       struct cli_state *c = NULL;
        struct nmb_name called, calling;
        const char *server_n;
        struct in_addr ip;
@@ -83,7 +83,7 @@ static struct cli_state *do_connect( const char *server, const char *share,
                ip = dest_ip;
 
        /* have to open a new connection */
-       if (!(c=cli_initialise(NULL)) || (cli_set_port(c, port) != port) ||
+       if (!(c=cli_initialise()) || (cli_set_port(c, port) != port) ||
            !cli_connect(c, server_n, &ip)) {
                d_printf("Connection to %s failed\n", server_n);
                return NULL;
@@ -99,6 +99,7 @@ static struct cli_state *do_connect( const char *server, const char *share,
                d_printf("session request to %s failed (%s)\n", 
                         called.name, cli_errstr(c));
                cli_shutdown(c);
+               c = NULL;
                if ((p=strchr_m(called.name, '.'))) {
                        *p = 0;
                        goto again;
index 8342df0f1d14e35bd54e9bc7d3cc4ca13552a9f2..4608d40d4629190a0197aaa82070a7c6f7154d56 100644 (file)
@@ -255,12 +255,12 @@ void cli_setup_signing_state(struct cli_state *cli, int signing_state)
 }
 
 /****************************************************************************
- Initialise a client structure.
+ Initialise a client structure. Always returns a malloc'ed struct.
 ****************************************************************************/
 
-struct cli_state *cli_initialise(struct cli_state *cli)
+struct cli_state *cli_initialise(void)
 {
-        BOOL alloced_cli = False;
+       struct cli_state *cli = NULL;
 
        /* Check the effective uid - make sure we are not setuid */
        if (is_setuid_root()) {
@@ -268,17 +268,11 @@ struct cli_state *cli_initialise(struct cli_state *cli)
                return NULL;
        }
 
+       cli = SMB_MALLOC_P(struct cli_state);
        if (!cli) {
-               cli = SMB_MALLOC_P(struct cli_state);
-               if (!cli)
-                       return NULL;
-               ZERO_STRUCTP(cli);
-                alloced_cli = True;
+               return NULL;
        }
 
-       if (cli->initialised)
-               cli_close_connection(cli);
-
        ZERO_STRUCTP(cli);
 
        cli->port = 0;
@@ -333,7 +327,6 @@ struct cli_state *cli_initialise(struct cli_state *cli)
        cli_null_set_signing(cli);
 
        cli->initialised = 1;
-       cli->allocated = alloced_cli;
 
        return cli;
 
@@ -343,10 +336,7 @@ struct cli_state *cli_initialise(struct cli_state *cli)
 
         SAFE_FREE(cli->inbuf);
         SAFE_FREE(cli->outbuf);
-
-        if (alloced_cli)
-                SAFE_FREE(cli);
-
+       SAFE_FREE(cli);
         return NULL;
 }
 
@@ -403,10 +393,10 @@ void cli_nt_pipes_close(struct cli_state *cli)
 }
 
 /****************************************************************************
Close a client connection and free the memory without destroying cli itself.
Shutdown a client structure.
 ****************************************************************************/
 
-void cli_close_connection(struct cli_state *cli)
+void cli_shutdown(struct cli_state *cli)
 {
        cli_nt_pipes_close(cli);
 
@@ -443,20 +433,8 @@ void cli_close_connection(struct cli_state *cli)
        }
        cli->fd = -1;
        cli->smb_rw_error = 0;
-}
 
-/****************************************************************************
- Shutdown a client structure.
-****************************************************************************/
-
-void cli_shutdown(struct cli_state *cli)
-{
-       BOOL allocated = cli->allocated;
-       cli_close_connection(cli);
-       ZERO_STRUCTP(cli);
-       if (allocated) {
-               free(cli);
-       }
+       SAFE_FREE(cli);
 }
 
 /****************************************************************************
index abb3843bacbe3724b3e37f0d27e064b5cd85fe4f..d40fc31dc441d435da4a48670966f57a2dfdc2c6 100644 (file)
@@ -112,7 +112,7 @@ static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context,
 
 #ifndef HAVE_KRB5_SET_REAL_TIME
 /*
- * This function is not in the Heimdal mainline.
+ * Thir function is not in the Heimdal mainline.
  */
  krb5_error_code krb5_set_real_time(krb5_context context, int32_t seconds, int32_t microseconds)
 {
index 147683689d62eda269ed68bff7646bb1202db809..3c23310f66ce8837fd12867b4b9159ce82a03aba 100644 (file)
@@ -220,7 +220,7 @@ int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 * grinfo )
   /* Allocate data. */
   data_size = MAX(soffset + strlen(grinfo->comment) + 1, 1024);
 
-  data = SMB_MALLOC(data_size);
+  data = SMB_MALLOC_ARRAY(char, data_size);
   if (!data) {
     DEBUG (1, ("Malloc fail\n"));
     return -1;
index 5d948ea5e25dd77512e349fc69e317c308e7a467..8c4fd7c89f72e96764dc1a9a880a81ba245805f8 100644 (file)
@@ -150,9 +150,10 @@ static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, const char * server,
                                  * doesn't match the requested share, so
                                  * disconnect from the current share.
                                  */
-                                if (! cli_tdis(&srv->server->cli)) {
+                                if (! cli_tdis(srv->server->cli)) {
                                         /* Sigh. Couldn't disconnect. */
-                                        cli_shutdown(&srv->server->cli);
+                                        cli_shutdown(srv->server->cli);
+                                       srv->server->cli = NULL;
                                         context->callbacks.remove_cached_srv_fn(context, srv->server);
                                         continue;
                                 }
@@ -166,7 +167,8 @@ static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, const char * server,
                                 srv->share_name = SMB_STRDUP(share);
                                 if (!srv->share_name) {
                                         /* Out of memory. */
-                                        cli_shutdown(&srv->server->cli);
+                                        cli_shutdown(srv->server->cli);
+                                       srv->server->cli = NULL;
                                         context->callbacks.remove_cached_srv_fn(context, srv->server);
                                         continue;
                                 }
index ca2624305e6295876122c54588ac984dcf33f90f..db788f46e9bb7de73e06f4d071ef7000665e883c 100644 (file)
@@ -487,7 +487,7 @@ static int
 smbc_check_server(SMBCCTX * context,
                   SMBCSRV * server) 
 {
-       if ( send_keepalive(server->cli.fd) == False )
+       if ( send_keepalive(server->cli->fd) == False )
                return 1;
 
        /* connection is ok */
@@ -524,7 +524,8 @@ smbc_remove_unused_server(SMBCCTX * context,
 
        DLIST_REMOVE(context->internal->_servers, srv);
 
-       cli_shutdown(&srv->cli);
+       cli_shutdown(srv->cli);
+       srv->cli = NULL;
 
        DEBUG(3, ("smbc_remove_usused_server: %p removed.\n", srv));
 
@@ -630,7 +631,7 @@ smbc_server(SMBCCTX *context,
             fstring password)
 {
        SMBCSRV *srv=NULL;
-       struct cli_state c;
+       struct cli_state *c;
        struct nmb_name called, calling;
        const char *server_n = server;
        pstring ipenv;
@@ -666,7 +667,7 @@ smbc_server(SMBCCTX *context,
                  * disconnect if the requested share is not the same as the
                  * one that was already connected.
                  */
-                if (srv->cli.cnum == (uint16) -1) {
+                if (srv->cli->cnum == (uint16) -1) {
                         /* Ensure we have accurate auth info */
                         if (context->internal->_auth_fn_with_context != NULL) {
                                 context->internal->_auth_fn_with_context(
@@ -683,11 +684,12 @@ smbc_server(SMBCCTX *context,
                                         password, sizeof(fstring));
                         }
 
-                        if (! cli_send_tconX(&srv->cli, share, "?????",
+                        if (! cli_send_tconX(srv->cli, share, "?????",
                                              password, strlen(password)+1)) {
                         
-                                errno = smbc_errno(context, &srv->cli);
-                                cli_shutdown(&srv->cli);
+                                errno = smbc_errno(context, srv->cli);
+                                cli_shutdown(srv->cli);
+                               srv->cli = NULL;
                                 context->callbacks.remove_cached_srv_fn(context,
                                                                         srv);
                                 srv = NULL;
@@ -730,19 +732,19 @@ smbc_server(SMBCCTX *context,
        zero_ip(&ip);
 
        /* have to open a new connection */
-       if (!cli_initialise(&c)) {
+       if ((c = cli_initialise()) == NULL) {
                errno = ENOMEM;
                return NULL;
        }
 
        if (context->flags & SMB_CTX_FLAG_USE_KERBEROS) {
-               c.use_kerberos = True;
+               c->use_kerberos = True;
        }
        if (context->flags & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS) {
-               c.fallback_after_kerberos = True;
+               c->fallback_after_kerberos = True;
        }
 
-       c.timeout = context->timeout;
+       c->timeout = context->timeout;
 
         /*
          * Force use of port 139 for first try if share is $IPC, empty, or
@@ -756,49 +758,47 @@ smbc_server(SMBCCTX *context,
                 port_try_next = 139;
         }
 
-        c.port = port_try_first;
+        c->port = port_try_first;
 
-       if (!cli_connect(&c, server_n, &ip)) {
+       if (!cli_connect(c, server_n, &ip)) {
 
                 /* First connection attempt failed.  Try alternate port. */
-                c.port = port_try_next;
+                c->port = port_try_next;
 
-                if (!cli_connect(&c, server_n, &ip)) {
-                        cli_shutdown(&c);
+                if (!cli_connect(c, server_n, &ip)) {
+                        cli_shutdown(c);
                         errno = ETIMEDOUT;
                         return NULL;
                 }
        }
 
-       if (!cli_session_request(&c, &calling, &called)) {
-               cli_shutdown(&c);
+       if (!cli_session_request(c, &calling, &called)) {
+               cli_shutdown(c);
                if (strcmp(called.name, "*SMBSERVER")) {
                        make_nmb_name(&called , "*SMBSERVER", 0x20);
                        goto again;
-               }
-               else {  /* Try one more time, but ensure we don't loop */
-
-                 /* Only try this if server is an IP address ... */
-
-                 if (is_ipaddress(server) && !tried_reverse) {
-                   fstring remote_name;
-                   struct in_addr rem_ip;
+               } else {  /* Try one more time, but ensure we don't loop */
 
-                   if ((rem_ip.s_addr=inet_addr(server)) == INADDR_NONE) {
-                     DEBUG(4, ("Could not convert IP address %s to struct in_addr\n", server));
-                     errno = ETIMEDOUT;
-                     return NULL;
-                   }
+                       /* Only try this if server is an IP address ... */
 
-                   tried_reverse++; /* Yuck */
+                       if (is_ipaddress(server) && !tried_reverse) {
+                               fstring remote_name;
+                               struct in_addr rem_ip;
 
-                   if (name_status_find("*", 0, 0, rem_ip, remote_name)) {
-                     make_nmb_name(&called, remote_name, 0x20);
-                     goto again;
-                   }
+                               if ((rem_ip.s_addr=inet_addr(server)) == INADDR_NONE) {
+                                       DEBUG(4, ("Could not convert IP address "
+                                               "%s to struct in_addr\n", server));
+                                       errno = ETIMEDOUT;
+                                       return NULL;
+                               }
 
+                               tried_reverse++; /* Yuck */
 
-                 }
+                               if (name_status_find("*", 0, 0, rem_ip, remote_name)) {
+                                       make_nmb_name(&called, remote_name, 0x20);
+                                       goto again;
+                               }
+                       }
                }
                errno = ETIMEDOUT;
                return NULL;
@@ -806,15 +806,15 @@ smbc_server(SMBCCTX *context,
   
        DEBUG(4,(" session request ok\n"));
   
-       if (!cli_negprot(&c)) {
-               cli_shutdown(&c);
+       if (!cli_negprot(c)) {
+               cli_shutdown(c);
                errno = ETIMEDOUT;
                return NULL;
        }
 
         username_used = username;
 
-       if (!cli_session_setup(&c, username_used, 
+       if (!cli_session_setup(c, username_used, 
                               password, strlen(password),
                               password, strlen(password),
                               workgroup)) {
@@ -823,12 +823,12 @@ smbc_server(SMBCCTX *context,
                 username_used = "";
 
                 if ((context->flags & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON) ||
-                     !cli_session_setup(&c, username_used,
+                     !cli_session_setup(c, username_used,
                                         password, 1,
                                         password, 0,
                                         workgroup)) {
 
-                        cli_shutdown(&c);
+                        cli_shutdown(c);
                         errno = EPERM;
                         return NULL;
                 }
@@ -836,10 +836,10 @@ smbc_server(SMBCCTX *context,
 
        DEBUG(4,(" session setup ok\n"));
 
-       if (!cli_send_tconX(&c, share, "?????",
+       if (!cli_send_tconX(c, share, "?????",
                            password, strlen(password)+1)) {
-               errno = smbc_errno(context, &c);
-               cli_shutdown(&c);
+               errno = smbc_errno(context, c);
+               cli_shutdown(c);
                return NULL;
        }
   
@@ -858,7 +858,6 @@ smbc_server(SMBCCTX *context,
 
        ZERO_STRUCTP(srv);
        srv->cli = c;
-        srv->cli.allocated = False;
        srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
         srv->no_pathinfo = False;
         srv->no_pathinfo2 = False;
@@ -884,8 +883,10 @@ smbc_server(SMBCCTX *context,
        return srv;
 
  failed:
-       cli_shutdown(&c);
-       if (!srv) return NULL;
+       cli_shutdown(c);
+       if (!srv) {
+               return NULL;
+       }
   
        SAFE_FREE(srv);
        return NULL;
@@ -960,19 +961,16 @@ smbc_attr_server(SMBCCTX *context,
                 }
 
                 ZERO_STRUCTP(ipc_srv);
-                ipc_srv->cli = *ipc_cli;
-                ipc_srv->cli.allocated = False;
-
-                free(ipc_cli);
+                ipc_srv->cli = ipc_cli;
 
                 if (pol) {
-                        pipe_hnd = cli_rpc_pipe_open_noauth(&ipc_srv->cli,
+                        pipe_hnd = cli_rpc_pipe_open_noauth(ipc_srv->cli,
                                                             PI_LSARPC,
                                                             &nt_status);
                         if (!pipe_hnd) {
                                 DEBUG(1, ("cli_nt_session_open fail!\n"));
                                 errno = ENOTSUP;
-                                cli_shutdown(&ipc_srv->cli);
+                                cli_shutdown(ipc_srv->cli);
                                 free(ipc_srv);
                                 return NULL;
                         }
@@ -985,14 +983,14 @@ smbc_attr_server(SMBCCTX *context,
         
                         nt_status = rpccli_lsa_open_policy(
                                 pipe_hnd,
-                                ipc_srv->cli.mem_ctx,
+                                ipc_srv->cli->mem_ctx,
                                 True, 
                                 GENERIC_EXECUTE_ACCESS,
                                 pol);
         
                         if (!NT_STATUS_IS_OK(nt_status)) {
-                                errno = smbc_errno(context, &ipc_srv->cli);
-                                cli_shutdown(&ipc_srv->cli);
+                                errno = smbc_errno(context, ipc_srv->cli);
+                                cli_shutdown(ipc_srv->cli);
                                 return NULL;
                         }
                 }
@@ -1009,7 +1007,7 @@ smbc_attr_server(SMBCCTX *context,
                         if (errno == 0) {
                                 errno = ENOMEM;
                         }
-                        cli_shutdown(&ipc_srv->cli);
+                        cli_shutdown(ipc_srv->cli);
                         free(ipc_srv);
                         return NULL;
                 }
@@ -1098,7 +1096,7 @@ smbc_open_ctx(SMBCCTX *context,
                ZERO_STRUCTP(file);
 
                /*d_printf(">>>open: resolving %s\n", 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);
                        SAFE_FREE(file);
@@ -1172,7 +1170,7 @@ smbc_open_ctx(SMBCCTX *context,
        if (fd == -1) {
                int eno = 0;
 
-               eno = smbc_errno(context, &srv->cli);
+               eno = smbc_errno(context, srv->cli);
                file = context->opendir(context, fname);
                if (!file) errno = eno;
                return file;
@@ -1275,7 +1273,7 @@ smbc_read_ctx(SMBCCTX *context,
         }
        
        /*d_printf(">>>read: resolving %s\n", path);*/
-       if (!cli_resolve_path("", &file->srv->cli, path,
+       if (!cli_resolve_path("", file->srv->cli, path,
                               &targetcli, targetpath))
        {
                d_printf("Could not resolve %s\n", path);
@@ -1358,7 +1356,7 @@ smbc_write_ctx(SMBCCTX *context,
         }
        
        /*d_printf(">>>write: resolving %s\n", path);*/
-       if (!cli_resolve_path("", &file->srv->cli, path,
+       if (!cli_resolve_path("", file->srv->cli, path,
                               &targetcli, targetpath))
        {
                d_printf("Could not resolve %s\n", path);
@@ -1430,7 +1428,7 @@ smbc_close_ctx(SMBCCTX *context,
         }
        
        /*d_printf(">>>close: resolving %s\n", path);*/
-       if (!cli_resolve_path("", &file->srv->cli, path,
+       if (!cli_resolve_path("", file->srv->cli, path,
                               &targetcli, targetpath))
        {
                d_printf("Could not resolve %s\n", path);
@@ -1500,7 +1498,7 @@ smbc_getatr(SMBCCTX * context,
        }
        DEBUG(4,("smbc_getatr: sending qpathinfo\n"));
   
-       if (!cli_resolve_path( "", &srv->cli, fixedpath, &targetcli, targetpath))
+       if (!cli_resolve_path( "", srv->cli, fixedpath, &targetcli, targetpath))
        {
                d_printf("Couldn't resolve %s\n", path);
                return False;
@@ -1565,7 +1563,7 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
          * attributes manipulated.
          */
         if (srv->no_pathinfo ||
-            ! cli_setpathinfo(&srv->cli, path, c_time, a_time, m_time, mode)) {
+            ! cli_setpathinfo(srv->cli, path, c_time, a_time, m_time, mode)) {
 
                 /*
                  * setpathinfo is not supported; go to plan B. 
@@ -1581,9 +1579,9 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
                 srv->no_pathinfo = True;
 
                 /* Open the file */
-                if ((fd = cli_open(&srv->cli, path, O_RDWR, DENY_NONE)) < 0) {
+                if ((fd = cli_open(srv->cli, path, O_RDWR, DENY_NONE)) < 0) {
 
-                        errno = smbc_errno(context, &srv->cli);
+                        errno = smbc_errno(context, srv->cli);
                         return -1;
                 }
 
@@ -1592,7 +1590,7 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
                  * We'll need it in the set call
                  */
                 if (c_time == 0) {
-                        ret = cli_getattrE(&srv->cli, fd,
+                        ret = cli_getattrE(srv->cli, fd,
                                            NULL, NULL,
                                            &c_time, NULL, NULL);
                 } else {
@@ -1619,9 +1617,9 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
                         if (c_time > m_time) c_time = m_time;
                         
                         /* Set the new attributes */
-                        ret = cli_setattrE(&srv->cli, fd,
+                        ret = cli_setattrE(srv->cli, fd,
                                            c_time, a_time, m_time);
-                        cli_close(&srv->cli, fd);
+                        cli_close(srv->cli, fd);
                 }
 
                 /*
@@ -1631,11 +1629,11 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
                  * seems to work on win98.
                  */
                 if (ret && mode != (uint16) -1) {
-                        ret = cli_setatr(&srv->cli, path, mode, 0);
+                        ret = cli_setatr(srv->cli, path, mode, 0);
                 }
 
                 if (! ret) {
-                        errno = smbc_errno(context, &srv->cli);
+                        errno = smbc_errno(context, srv->cli);
                         return False;
                 }
         }
@@ -1695,7 +1693,7 @@ smbc_unlink_ctx(SMBCCTX *context,
        }
 
        /*d_printf(">>>unlink: resolving %s\n", 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 -1;
@@ -1828,14 +1826,14 @@ smbc_rename_ctx(SMBCCTX *ocontext,
        }
 
        /*d_printf(">>>rename: resolving %s\n", path1);*/
-       if (!cli_resolve_path( "", &srv->cli, path1, &targetcli1, targetpath1))
+       if (!cli_resolve_path( "", srv->cli, path1, &targetcli1, targetpath1))
        {
                d_printf("Could not resolve %s\n", path1);
                return -1;
        }
        /*d_printf(">>>rename: resolved path as %s\n", targetpath1);*/
        /*d_printf(">>>rename: resolving %s\n", path2);*/
-       if (!cli_resolve_path( "", &srv->cli, path2, &targetcli2, targetpath2))
+       if (!cli_resolve_path( "", srv->cli, path2, &targetcli2, targetpath2))
        {
                d_printf("Could not resolve %s\n", path2);
                return -1;
@@ -1930,7 +1928,7 @@ smbc_lseek_ctx(SMBCCTX *context,
                        }
                
                /*d_printf(">>>lseek: resolving %s\n", path);*/
-               if (!cli_resolve_path("", &file->srv->cli, path,
+               if (!cli_resolve_path("", file->srv->cli, path,
                                       &targetcli, targetpath))
                {
                        d_printf("Could not resolve %s\n", path);
@@ -2099,7 +2097,7 @@ smbc_stat_ctx(SMBCCTX *context,
        if (!smbc_getatr(context, srv, path, &mode, &size, 
                         &c_time, &a_time, &m_time, &ino)) {
 
-               errno = smbc_errno(context, &srv->cli);
+               errno = smbc_errno(context, srv->cli);
                return -1;
                
        }
@@ -2175,7 +2173,7 @@ smbc_fstat_ctx(SMBCCTX *context,
         }
        
        /*d_printf(">>>fstat: resolving %s\n", path);*/
-       if (!cli_resolve_path("", &file->srv->cli, path,
+       if (!cli_resolve_path("", file->srv->cli, path,
                               &targetcli, targetpath))
        {
                d_printf("Could not resolve %s\n", path);
@@ -2676,7 +2674,7 @@ smbc_opendir_ctx(SMBCCTX *context,
 
                         /* Now, list the stuff ... */
                         
-                        if (!cli_NetServerEnum(&srv->cli,
+                        if (!cli_NetServerEnum(srv->cli,
                                                workgroup,
                                                SV_TYPE_DOMAIN_ENUM,
                                                list_unique_wg_fn,
@@ -2772,7 +2770,7 @@ smbc_opendir_ctx(SMBCCTX *context,
                                dir->srv = srv;
 
                                /* Now, list the servers ... */
-                               if (!cli_NetServerEnum(&srv->cli, server,
+                               if (!cli_NetServerEnum(srv->cli, server,
                                                        0x0000FFFE, list_fn,
                                                       (void *)dir)) {
 
@@ -2808,15 +2806,15 @@ smbc_opendir_ctx(SMBCCTX *context,
                                 /* List the shares ... */
 
                                 if (net_share_enum_rpc(
-                                            &srv->cli,
+                                            srv->cli,
                                             list_fn,
                                             (void *) dir) < 0 &&
                                     cli_RNetShareEnum(
-                                            &srv->cli,
+                                            srv->cli,
                                             list_fn, 
                                             (void *)dir) < 0) {
                                                 
-                                        errno = cli_errno(&srv->cli);
+                                        errno = cli_errno(srv->cli);
                                         if (dir) {
                                                 SAFE_FREE(dir->fname);
                                                 SAFE_FREE(dir);
@@ -2866,7 +2864,7 @@ smbc_opendir_ctx(SMBCCTX *context,
                         p = path + strlen(path);
                        pstrcat(path, "\\*");
 
-                       if (!cli_resolve_path("", &srv->cli, path,
+                       if (!cli_resolve_path("", srv->cli, path,
                                               &targetcli, targetpath))
                        {
                                d_printf("Could not resolve %s\n", path);
@@ -3215,7 +3213,7 @@ smbc_mkdir_ctx(SMBCCTX *context,
        }
 
        /*d_printf(">>>mkdir: resolving %s\n", 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 -1;
@@ -3312,7 +3310,7 @@ smbc_rmdir_ctx(SMBCCTX *context,
        }
 
        /*d_printf(">>>rmdir: resolving %s\n", 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 -1;
@@ -3568,8 +3566,8 @@ smbc_chmod_ctx(SMBCCTX *context,
        if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM;
        if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN;
 
-       if (!cli_setatr(&srv->cli, path, mode, 0)) {
-               errno = smbc_errno(context, &srv->cli);
+       if (!cli_setatr(srv->cli, path, mode, 0)) {
+               errno = smbc_errno(context, srv->cli);
                return -1;
        }
        
@@ -4098,7 +4096,7 @@ dos_attr_query(SMBCCTX *context,
                          &mode, &size, 
                          &c_time, &a_time, &m_time, &inode)) {
         
-                errno = smbc_errno(context, &srv->cli);
+                errno = smbc_errno(context, srv->cli);
                 DEBUG(5, ("dos_attr_query Failed to query old attributes\n"));
                 return NULL;
         
@@ -4206,7 +4204,7 @@ cacl_get(SMBCCTX *context,
        SMB_OFF_T size = 0;
        uint16 mode = 0;
        SMB_INO_T ino = 0;
-        struct cli_state *cli = &srv->cli;
+        struct cli_state *cli = srv->cli;
 
         /* Copy name so we can strip off exclusions (if any are specified) */
         strncpy(name_sandbox, attr_name, sizeof(name_sandbox) - 1);
@@ -4551,7 +4549,7 @@ cacl_get(SMBCCTX *context,
                 if (!smbc_getatr(context, srv, filename, &mode, &size, 
                                  &c_time, &a_time, &m_time, &ino)) {
                         
-                        errno = smbc_errno(context, &srv->cli);
+                        errno = smbc_errno(context, srv->cli);
                         return -1;
                         
                 }
@@ -5108,8 +5106,8 @@ smbc_setxattr_ctx(SMBCCTX *context,
                 }
 
                 if (ipc_srv) {
-                        ret = cacl_set(ctx, &srv->cli,
-                                       &ipc_srv->cli, &pol, path,
+                        ret = cacl_set(ctx, srv->cli,
+                                       ipc_srv->cli, &pol, path,
                                        namevalue,
                                        (*namevalue == '*'
                                         ? SMBC_XATTR_MODE_SET
@@ -5171,8 +5169,8 @@ smbc_setxattr_ctx(SMBCCTX *context,
                         errno = ENOMEM;
                         ret = -1;
                 } else {
-                        ret = cacl_set(ctx, &srv->cli,
-                                       &ipc_srv->cli, &pol, path,
+                        ret = cacl_set(ctx, srv->cli,
+                                       ipc_srv->cli, &pol, path,
                                        namevalue,
                                        (*namevalue == '*'
                                         ? SMBC_XATTR_MODE_SET
@@ -5202,8 +5200,8 @@ smbc_setxattr_ctx(SMBCCTX *context,
                         errno = ENOMEM;
                         ret = -1;
                 } else {
-                        ret = cacl_set(ctx, &srv->cli,
-                                       &ipc_srv->cli, &pol, path,
+                        ret = cacl_set(ctx, srv->cli,
+                                       ipc_srv->cli, &pol, path,
                                        namevalue, SMBC_XATTR_MODE_CHOWN, 0);
                 }
                 talloc_destroy(ctx);
@@ -5229,8 +5227,8 @@ smbc_setxattr_ctx(SMBCCTX *context,
                         errno = ENOMEM;
                         ret = -1;
                 } else {
-                        ret = cacl_set(ctx, &srv->cli,
-                                       &ipc_srv->cli, &pol, path,
+                        ret = cacl_set(ctx, srv->cli,
+                                       ipc_srv->cli, &pol, path,
                                        namevalue, SMBC_XATTR_MODE_CHOWN, 0);
                 }
                 talloc_destroy(ctx);
@@ -5388,12 +5386,12 @@ smbc_getxattr_ctx(SMBCCTX *context,
 
                 /* Yup. */
                 ret = cacl_get(context, ctx, srv,
-                               ipc_srv == NULL ? NULL : &ipc_srv->cli, 
+                               ipc_srv == NULL ? NULL : ipc_srv->cli, 
                                &pol, path,
                                CONST_DISCARD(char *, name),
                                CONST_DISCARD(char *, value), size);
                 if (ret < 0 && errno == 0) {
-                        errno = smbc_errno(context, &srv->cli);
+                        errno = smbc_errno(context, srv->cli);
                 }
                 talloc_destroy(ctx);
                 return ret;
@@ -5484,8 +5482,8 @@ smbc_removexattr_ctx(SMBCCTX *context,
             StrCaseCmp(name, "system.nt_sec_desc.*+") == 0) {
 
                 /* Yup. */
-                ret = cacl_set(ctx, &srv->cli,
-                               &ipc_srv->cli, &pol, path,
+                ret = cacl_set(ctx, srv->cli,
+                               ipc_srv->cli, &pol, path,
                                NULL, SMBC_XATTR_MODE_REMOVE_ALL, 0);
                 talloc_destroy(ctx);
                 return ret;
@@ -5504,8 +5502,8 @@ smbc_removexattr_ctx(SMBCCTX *context,
             StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) {
 
                 /* Yup. */
-                ret = cacl_set(ctx, &srv->cli,
-                               &ipc_srv->cli, &pol, path,
+                ret = cacl_set(ctx, srv->cli,
+                               ipc_srv->cli, &pol, path,
                                name + 19, SMBC_XATTR_MODE_REMOVE, 0);
                 talloc_destroy(ctx);
                 return ret;
@@ -5755,10 +5753,10 @@ smbc_list_print_jobs_ctx(SMBCCTX *context,
 
         }
 
-        if (cli_print_queue(&srv->cli,
+        if (cli_print_queue(srv->cli,
                             (void (*)(struct print_job_info *))fn) < 0) {
 
-                errno = smbc_errno(context, &srv->cli);
+                errno = smbc_errno(context, srv->cli);
                 return -1;
 
         }
@@ -5825,10 +5823,10 @@ smbc_unlink_print_job_ctx(SMBCCTX *context,
 
         }
 
-        if ((err = cli_printjob_del(&srv->cli, id)) != 0) {
+        if ((err = cli_printjob_del(srv->cli, id)) != 0) {
 
                 if (err < 0)
-                        errno = smbc_errno(context, &srv->cli);
+                        errno = smbc_errno(context, srv->cli);
                 else if (err == ERRnosuchprintjob)
                         errno = EINVAL;
                 return -1;
@@ -5947,8 +5945,8 @@ smbc_free_context(SMBCCTX *context,
                         s = context->internal->_servers;
                         while (s) {
                                 DEBUG(1, ("Forced shutdown: %p (fd=%d)\n",
-                                          s, s->cli.fd));
-                                cli_shutdown(&s->cli);
+                                          s, s->cli->fd));
+                                cli_shutdown(s->cli);
                                 context->callbacks.remove_cached_srv_fn(context,
                                                                         s);
                                 next = s->next;
@@ -6074,9 +6072,9 @@ smbc_option_get(SMBCCTX *context,
                  * Log to standard error instead of standard output.
                  */
 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
-                return (void *) (intptr_t) context->internal->_debug_stderr;
+               return (void *) (intptr_t) context->internal->_debug_stderr;
 #else
-                return (void *) context->internal->_debug_stderr;
+               return (void *) context->internal->_debug_stderr;
 #endif
         } else if (strcmp(option_name, "auth_function") == 0) {
                 /*
index 673671d28db05ba02621562f54e38205d61d50c7..0d3dcf4d75517ab4386ece05aa46a61c9f6bf4b6 100644 (file)
@@ -29,7 +29,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
                            char *err_str, size_t err_str_len)
 {
        struct nmb_name calling, called;
-       struct cli_state cli;
+       struct cli_state *cli;
        struct rpc_pipe_client *pipe_hnd;
        struct in_addr ip;
 
@@ -44,39 +44,45 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
                return NT_STATUS_UNSUCCESSFUL;
        }
  
-       ZERO_STRUCT(cli);
-       if (!cli_initialise(&cli) || !cli_connect(&cli, remote_machine, &ip)) {
+       cli = cli_initialise();
+       if (!cli) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (!cli_connect(cli, remote_machine, &ip)) {
                slprintf(err_str, err_str_len-1, "unable to connect to SMB server on machine %s. Error was : %s.\n",
-                       remote_machine, cli_errstr(&cli) );
-               return NT_STATUS_UNSUCCESSFUL;
+                       remote_machine, cli_errstr(cli) );
+               result = cli_nt_error(cli);
+               cli_shutdown(cli);
+               return result;
        }
   
        make_nmb_name(&calling, global_myname() , 0x0);
        make_nmb_name(&called , remote_machine, 0x20);
        
-       if (!cli_session_request(&cli, &calling, &called)) {
+       if (!cli_session_request(cli, &calling, &called)) {
                slprintf(err_str, err_str_len-1, "machine %s rejected the session setup. Error was : %s.\n",
-                       remote_machine, cli_errstr(&cli) );
-               cli_shutdown(&cli);
-               return NT_STATUS_UNSUCCESSFUL;
+                       remote_machine, cli_errstr(cli) );
+               result = cli_nt_error(cli);
+               cli_shutdown(cli);
+               return result;
        }
   
-       cli.protocol = PROTOCOL_NT1;
+       cli->protocol = PROTOCOL_NT1;
 
-       if (!cli_negprot(&cli)) {
+       if (!cli_negprot(cli)) {
                slprintf(err_str, err_str_len-1, "machine %s rejected the negotiate protocol. Error was : %s.\n",        
-                       remote_machine, cli_errstr(&cli) );
-               result = cli_nt_error(&cli);
-               cli_shutdown(&cli);
+                       remote_machine, cli_errstr(cli) );
+               result = cli_nt_error(cli);
+               cli_shutdown(cli);
                return result;
        }
   
        /* Given things like SMB signing, restrict anonymous and the like, 
           try an authenticated connection first */
-       if (!cli_session_setup(&cli, user_name, old_passwd, strlen(old_passwd)+1, old_passwd, strlen(old_passwd)+1, "")) {
+       if (!cli_session_setup(cli, user_name, old_passwd, strlen(old_passwd)+1, old_passwd, strlen(old_passwd)+1, "")) {
 
-               result = cli_nt_error(&cli);
+               result = cli_nt_error(cli);
 
                if (!NT_STATUS_IS_OK(result)) {
 
@@ -89,8 +95,8 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
                                             NT_STATUS_PASSWORD_MUST_CHANGE)) {
                                slprintf(err_str, err_str_len-1, "Could not "
                                         "connect to machine %s: %s\n",
-                                        remote_machine, cli_errstr(&cli));
-                               cli_shutdown(&cli);
+                                        remote_machine, cli_errstr(cli));
+                               cli_shutdown(cli);
                                return result;
                        }
 
@@ -103,31 +109,31 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
                 * Thanks to <Nicholas.S.Jenkins@cdc.com> for this fix.
                 */
 
-               if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) {
+               if (!cli_session_setup(cli, "", "", 0, "", 0, "")) {
                        slprintf(err_str, err_str_len-1, "machine %s rejected the session setup. Error was : %s.\n",        
-                                remote_machine, cli_errstr(&cli) );
-                       result = cli_nt_error(&cli);
-                       cli_shutdown(&cli);
+                                remote_machine, cli_errstr(cli) );
+                       result = cli_nt_error(cli);
+                       cli_shutdown(cli);
                        return result;
                }
 
-               cli_init_creds(&cli, "", "", NULL);
+               cli_init_creds(cli, "", "", NULL);
        } else {
-               cli_init_creds(&cli, user_name, "", old_passwd);
+               cli_init_creds(cli, user_name, "", old_passwd);
        }
 
-       if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
+       if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
                slprintf(err_str, err_str_len-1, "machine %s rejected the tconX on the IPC$ share. Error was : %s.\n",
-                       remote_machine, cli_errstr(&cli) );
-               result = cli_nt_error(&cli);
-               cli_shutdown(&cli);
+                       remote_machine, cli_errstr(cli) );
+               result = cli_nt_error(cli);
+               cli_shutdown(cli);
                return result;
        }
 
        /* Try not to give the password away too easily */
 
        if (!pass_must_change) {
-               pipe_hnd = cli_rpc_pipe_open_ntlmssp(&cli,
+               pipe_hnd = cli_rpc_pipe_open_ntlmssp(cli,
                                                PI_SAMR,
                                                PIPE_AUTH_LEVEL_PRIVACY,
                                                "", /* what domain... ? */
@@ -143,17 +149,17 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
                 * will just fail. So we do it anonymously, there's no other
                 * way.
                 */
-               pipe_hnd = cli_rpc_pipe_open_noauth(&cli, PI_SAMR, &result);
+               pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result);
        }
 
        if (!pipe_hnd) {
                if (lp_client_lanman_auth()) {
                        /* Use the old RAP method. */
-                       if (!cli_oem_change_password(&cli, user_name, new_passwd, old_passwd)) {
+                       if (!cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) {
                                slprintf(err_str, err_str_len-1, "machine %s rejected the password change: Error was : %s.\n",
-                                        remote_machine, cli_errstr(&cli) );
-                               result = cli_nt_error(&cli);
-                               cli_shutdown(&cli);
+                                        remote_machine, cli_errstr(cli) );
+                               result = cli_nt_error(cli);
+                               cli_shutdown(cli);
                                return result;
                        }
                } else {
@@ -161,16 +167,16 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
                                "SAMR connection to machine %s failed. Error was %s, "
                                "but LANMAN password changed are disabled\n",
                                nt_errstr(result), remote_machine);
-                       result = cli_nt_error(&cli);
-                       cli_shutdown(&cli);
+                       result = cli_nt_error(cli);
+                       cli_shutdown(cli);
                        return result;
                }
        }
 
-       if (NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd, cli.mem_ctx, user_name, 
+       if (NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd, cli->mem_ctx, user_name, 
                                                             new_passwd, old_passwd))) {
                /* Great - it all worked! */
-               cli_shutdown(&cli);
+               cli_shutdown(cli);
                return NT_STATUS_OK;
 
        } else if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) 
@@ -179,7 +185,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
                
                slprintf(err_str, err_str_len-1, "machine %s rejected the password change: Error was : %s.\n",
                         remote_machine, get_friendly_nt_error_msg(result));
-               cli_shutdown(&cli);
+               cli_shutdown(cli);
                return result;
        }
 
@@ -187,21 +193,21 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
        cli_rpc_pipe_close(pipe_hnd);
        
        /* Try anonymous NTLMSSP... */
-       cli_init_creds(&cli, "", "", NULL);
+       cli_init_creds(cli, "", "", NULL);
        
        result = NT_STATUS_UNSUCCESSFUL;
        
        /* OK, this is ugly, but... try an anonymous pipe. */
-       pipe_hnd = cli_rpc_pipe_open_noauth(&cli, PI_SAMR, &result);
+       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result);
 
        if ( pipe_hnd &&
                (NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd,
-                                               cli.mem_ctx,
+                                               cli->mem_ctx,
                                                user_name, 
                                                new_passwd,
                                                old_passwd)))) {
                /* Great - it all worked! */
-               cli_shutdown(&cli);
+               cli_shutdown(cli);
                return NT_STATUS_OK;
        } else {
                if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) 
@@ -211,7 +217,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
                        slprintf(err_str, err_str_len-1, 
                                 "machine %s rejected the (anonymous) password change: Error was : %s.\n",
                                 remote_machine, get_friendly_nt_error_msg(result));
-                       cli_shutdown(&cli);
+                       cli_shutdown(cli);
                        return result;
                }
                
@@ -220,24 +226,24 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
                
                if (lp_client_lanman_auth()) {
                        /* Use the old RAP method. */
-                       if (cli_oem_change_password(&cli, user_name, new_passwd, old_passwd)) {
+                       if (cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) {
                                /* SAMR failed, but the old LanMan protocol worked! */
 
-                               cli_shutdown(&cli);
+                               cli_shutdown(cli);
                                return NT_STATUS_OK;
                        }
                        slprintf(err_str, err_str_len-1, 
                                 "machine %s rejected the password change: Error was : %s.\n",
-                                remote_machine, cli_errstr(&cli) );
-                       result = cli_nt_error(&cli);
-                       cli_shutdown(&cli);
+                                remote_machine, cli_errstr(cli) );
+                       result = cli_nt_error(cli);
+                       cli_shutdown(cli);
                        return result;
                } else {
                        slprintf(err_str, err_str_len-1,
                                "SAMR connection to machine %s failed. Error was %s, "
                                "but LANMAN password changed are disabled\n",
                                nt_errstr(result), remote_machine);
-                       cli_shutdown(&cli);
+                       cli_shutdown(cli);
                        return NT_STATUS_UNSUCCESSFUL;
                }
        }
index 55108bf72f2c0fa6827654cbd96060aed966e3e5..e4061883eb1f96c3064040e8e4412298b11a37ff 100644 (file)
@@ -99,7 +99,7 @@ NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *m
        
        if (NT_STATUS_IS_OK(nt_status)) {
                DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n", 
-                        timestring(False)));
+                        current_timestring(False)));
                /*
                 * Return the result of trying to write the new password
                 * back into the trust account file.
index 574552e9e2198751de0e4369e6e5b687426b919a..9c8a7a17ee6d96e807ac4f0e300bd224693ebd38 100644 (file)
 
 #define ZERO_ZERO 0
 
-/* This contains elements that differentiate locks. The smbpid is a
-   client supplied pid, and is essentially the locking context for
-   this client */
-
-struct lock_context {
-       uint16 smbpid;
-       uint16 tid;
-       struct process_id pid;
-};
-
-/* The data in brlock records is an unsorted linear array of these
-   records.  It is unnecessary to store the count as tdb provides the
-   size of the record */
-
-struct lock_struct {
-       struct lock_context context;
-       br_off start;
-       br_off size;
-       int fnum;
-       enum brl_type lock_type;
-       enum brl_flavour lock_flav;
-};
-
 /* The open brlock.tdb database. */
 
 static TDB_CONTEXT *tdb;
@@ -83,7 +60,7 @@ static void print_lock_struct(unsigned int i, struct lock_struct *pls)
  See if two locking contexts are equal.
 ****************************************************************************/
 
-static BOOL brl_same_context(const struct lock_context *ctx1, 
+BOOL brl_same_context(const struct lock_context *ctx1, 
                             const struct lock_context *ctx2)
 {
        return (procid_equal(&ctx1->pid, &ctx2->pid) &&
@@ -343,13 +320,19 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck,
 
        /* We can get the Windows lock, now see if it needs to
           be mapped into a lower level POSIX one, and if so can
-          we get it ? We tell the lower lock layer about the
-          lock type so it can cope with the difference between
-          Windows "stacking" locks and POSIX "flat" ones. */
+          we get it ? */
 
        if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) {
-               if (!set_posix_lock(fsp, plock->start, plock->size, plock->lock_type, WINDOWS_LOCK)) {
-                       if (errno == EACCES || errno == EAGAIN) {
+               int errno_ret;
+               if (!set_posix_lock_windows_flavour(fsp,
+                               plock->start,
+                               plock->size,
+                               plock->lock_type,
+                               &plock->context,
+                               locks,
+                               br_lck->num_locks,
+                               &errno_ret)) {
+                       if (errno_ret == EACCES || errno_ret == EAGAIN) {
                                return NT_STATUS_FILE_LOCK_CONFLICT;
                        } else {
                                return map_nt_error_from_unix(errno);
@@ -375,9 +358,9 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck,
  Cope with POSIX range splits and merges.
 ****************************************************************************/
 
-static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr,
-                                               const struct lock_struct *ex,
-                                               const struct lock_struct *plock,
+static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr,              /* Output array. */
+                                               const struct lock_struct *ex,           /* existing lock. */
+                                               const struct lock_struct *plock,        /* proposed lock. */
                                                BOOL *lock_was_added)
 {
        BOOL lock_types_differ = (ex->lock_type != plock->lock_type);
@@ -398,26 +381,26 @@ static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr,
                                              +---------+
                                              | ex      |
                                              +---------+
-                                +-------+
-                                | plock |
-                                +-------+
+                              +-------+
+                              | plock |
+                              +-------+
 OR....
              +---------+
              |  ex     |
              +---------+
 **********************************************/
 
-       if ( (ex->start >= (plock->start + plock->size)) ||
-                       (plock->start >= (ex->start + ex->size))) {
+       if ( (ex->start > (plock->start + plock->size)) ||
+                       (plock->start > (ex->start + ex->size))) {
                /* No overlap with this lock - copy existing. */
                memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
                return 1;
        }
 
 /*********************************************
-                +---------+
-                |  ex     |
-                +---------+
+        +---------------------------+
+        |          ex               |
+        +---------------------------+
         +---------------------------+
         |       plock               | -> replace with plock.
         +---------------------------+
@@ -431,24 +414,32 @@ OR....
        }
 
 /*********************************************
-                +---------------+
-                |  ex           |
-                +---------------+
+        +-----------------------+
+        |          ex           |
+        +-----------------------+
         +---------------+
         |   plock       |
         +---------------+
+OR....
+                        +-------+
+                        |  ex   |
+                        +-------+
+        +---------------+
+        |   plock       |
+        +---------------+
+
 BECOMES....
         +---------------+-------+
         |   plock       | ex    | - different lock types.
         +---------------+-------+
-OR....
+OR.... (merge)
         +-----------------------+
         |   ex                  | - same lock type.
         +-----------------------+
 **********************************************/
 
        if ( (ex->start >= plock->start) &&
-                               (ex->start < plock->start + plock->size) &&
+                               (ex->start <= plock->start + plock->size) &&
                                (ex->start + ex->size > plock->start + plock->size) ) {
 
                *lock_was_added = True;
@@ -475,9 +466,16 @@ OR....
        }
 
 /*********************************************
-   +---------------+
-   |  ex           |
-   +---------------+
+   +-----------------------+
+   |  ex                   |
+   +-----------------------+
+           +---------------+
+           |   plock       |
+           +---------------+
+OR....
+   +-------+        
+   |  ex   |
+   +-------+
            +---------------+
            |   plock       |
            +---------------+
@@ -486,7 +484,7 @@ BECOMES....
    | ex    |   plock       | - different lock types
    +-------+---------------+
 
-OR
+OR.... (merge)
    +-----------------------+
    | ex                    | - same lock type.
    +-----------------------+
@@ -494,7 +492,7 @@ OR
 **********************************************/
 
        if ( (ex->start < plock->start) &&
-                       (ex->start + ex->size > plock->start) &&
+                       (ex->start + ex->size >= plock->start) &&
                        (ex->start + ex->size <= plock->start + plock->size) ) {
 
                *lock_was_added = True;
@@ -631,20 +629,28 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
                }
        }
 
+       if (!lock_was_added) {
+               memcpy(&tp[count], plock, sizeof(struct lock_struct));
+               count++;
+       }
+
        /* We can get the POSIX lock, now see if it needs to
           be mapped into a lower level POSIX one, and if so can
-          we get it ? We well the lower lock layer about the
-          lock type so it can cope with the difference between
-          Windows "stacking" locks and POSIX "flat" ones. */
+          we get it ? */
 
-#if 0
-       /* FIXME - this call doesn't work correctly yet for POSIX locks... */
+       if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(br_lck->fsp->conn))) {
+               int errno_ret;
 
-       if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) {
-               files_struct *fsp = br_lck->fsp;
+               /* The lower layer just needs to attempt to
+                  get the system POSIX lock. We've weeded out
+                  any conflicts above. */
 
-               if (!set_posix_lock(fsp, plock->start, plock->size, plock->lock_type, POSIX_LOCK)) {
-                       if (errno == EACCES || errno == EAGAIN) {
+               if (!set_posix_lock_posix_flavour(br_lck->fsp,
+                               plock->start,
+                               plock->size,
+                               plock->lock_type,
+                               &errno_ret)) {
+                       if (errno_ret == EACCES || errno_ret == EAGAIN) {
                                SAFE_FREE(tp);
                                return NT_STATUS_FILE_LOCK_CONFLICT;
                        } else {
@@ -653,12 +659,6 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
                        }
                }
        }
-#endif
-
-       if (!lock_was_added) {
-               memcpy(&tp[count], plock, sizeof(struct lock_struct));
-               count++;
-       }
 
        /* Realloc so we don't leak entries per lock call. */
        tp = (struct lock_struct *)SMB_REALLOC(tp, count * sizeof(*locks));
@@ -676,7 +676,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
 ****************************************************************************/
 
 NTSTATUS brl_lock(struct byte_range_lock *br_lck,
-               uint16 smbpid,
+               uint32 smbpid,
                struct process_id pid,
                br_off start,
                br_off size, 
@@ -740,8 +740,12 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock
        unsigned int i, j;
        struct lock_struct *lock = NULL;
        struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
+       enum brl_type deleted_lock_type = READ_LOCK; /* shut the compiler up.... */
 
 #if ZERO_ZERO
+       /* Delete write locks by preference... The lock list
+          is sorted in the zero zero case. */
+
        for (i = 0; i < br_lck->num_locks; i++) {
                lock = &locks[i];
 
@@ -753,16 +757,15 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock
                    lock->size == plock->size) {
 
                        /* found it - delete it */
-                       if (i < br_lck->num_locks - 1) {
-                               memmove(&locks[i], &locks[i+1], 
-                                       sizeof(*locks)*((br_lck->num_locks-1) - i));
-                       }
-
-                       br_lck->num_locks -= 1;
-                       br_lck->modified = True;
-                       return True;
+                       deleted_lock_type = lock->lock_type;
+                       break;
                }
        }
+
+       if (i != br_lck->num_locks) {
+               /* We found it - don't search again. */
+               goto unlock_continue;
+       }
 #endif
 
        for (i = 0; i < br_lck->num_locks; i++) {
@@ -774,6 +777,7 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock
                                        lock->lock_flav == WINDOWS_LOCK &&
                                        lock->start == plock->start &&
                                        lock->size == plock->size ) {
+                       deleted_lock_type = lock->lock_type;
                        break;
                }
        }
@@ -783,9 +787,28 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock
                return False;
        }
 
-       /* Unlock any POSIX regions. */
+#if ZERO_ZERO
+  unlock_continue:
+#endif
+
+       /* Actually delete the lock. */
+       if (i < br_lck->num_locks - 1) {
+               memmove(&locks[i], &locks[i+1], 
+                       sizeof(*locks)*((br_lck->num_locks-1) - i));
+       }
+
+       br_lck->num_locks -= 1;
+       br_lck->modified = True;
+
+       /* Unlock the underlying POSIX regions. */
        if(lp_posix_locking(br_lck->fsp->conn->cnum)) {
-               release_posix_lock(br_lck->fsp, plock->start, plock->size);
+               release_posix_lock_windows_flavour(br_lck->fsp,
+                               plock->start,
+                               plock->size,
+                               deleted_lock_type,
+                               &plock->context,
+                               locks,
+                               br_lck->num_locks);
        }
 
        /* Send unlock messages to any pending waiters that overlap. */
@@ -810,14 +833,6 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock
                }
        }
 
-       /* Actually delete the lock. */
-       if (i < br_lck->num_locks - 1) {
-               memmove(&locks[i], &locks[i+1], 
-                       sizeof(*locks)*((br_lck->num_locks-1) - i));
-       }
-
-       br_lck->num_locks -= 1;
-       br_lck->modified = True;
        return True;
 }
 
@@ -895,13 +910,18 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s
                                SMB_ASSERT(tmp_lock[0].lock_type == locks[i].lock_type);
                                SMB_ASSERT(tmp_lock[1].lock_type == UNLOCK_LOCK);
                                memcpy(&tp[count], &tmp_lock[0], sizeof(struct lock_struct));
+                               if (tmp_lock[0].size != locks[i].size) {
+                                       overlap_found = True;
+                               }
                        } else {
                                SMB_ASSERT(tmp_lock[0].lock_type == UNLOCK_LOCK);
                                SMB_ASSERT(tmp_lock[1].lock_type == locks[i].lock_type);
                                memcpy(&tp[count], &tmp_lock[1], sizeof(struct lock_struct));
+                               if (tmp_lock[1].start != locks[i].start) {
+                                       overlap_found = True;
+                               }
                        }
                        count++;
-                       overlap_found = True;
                        continue;
                } else {
                        /* tmp_count == 3 - (we split a lock range in two). */
@@ -933,14 +953,15 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s
                return True;
        }
 
-#if 0
-       /* FIXME - this call doesn't work correctly yet for POSIX locks... */
-
        /* Unlock any POSIX regions. */
        if(lp_posix_locking(br_lck->fsp->conn->cnum)) {
-               release_posix_lock(br_lck->fsp, plock->start, plock->size);
+               release_posix_lock_posix_flavour(br_lck->fsp,
+                                               plock->start,
+                                               plock->size,
+                                               &plock->context,
+                                               tp,
+                                               count);
        }
-#endif
 
        /* Realloc so we don't leak entries per unlock call. */
        if (count) {
@@ -991,7 +1012,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s
 ****************************************************************************/
 
 BOOL brl_unlock(struct byte_range_lock *br_lck,
-               uint16 smbpid,
+               uint32 smbpid,
                struct process_id pid,
                br_off start,
                br_off size,
@@ -1021,7 +1042,7 @@ BOOL brl_unlock(struct byte_range_lock *br_lck,
 ****************************************************************************/
 
 BOOL brl_locktest(struct byte_range_lock *br_lck,
-               uint16 smbpid,
+               uint32 smbpid,
                struct process_id pid,
                br_off start,
                br_off size, 
@@ -1079,7 +1100,7 @@ BOOL brl_locktest(struct byte_range_lock *br_lck,
 ****************************************************************************/
 
 NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
-               uint16 *psmbpid,
+               uint32 *psmbpid,
                struct process_id pid,
                br_off *pstart,
                br_off *psize, 
@@ -1148,7 +1169,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
 ****************************************************************************/
 
 BOOL brl_remove_pending_lock(struct byte_range_lock *br_lck,
-               uint16 smbpid,
+               uint32 smbpid,
                struct process_id pid,
                br_off start,
                br_off size,
@@ -1192,18 +1213,75 @@ BOOL brl_remove_pending_lock(struct byte_range_lock *br_lck,
        return True;
 }
 
-
 /****************************************************************************
  Remove any locks associated with a open file.
+ We return True if this process owns any other Windows locks on this
+ fd and so we should not immediately close the fd.
 ****************************************************************************/
 
-void brl_close_fnum(struct byte_range_lock *br_lck, struct process_id pid)
+void brl_close_fnum(struct byte_range_lock *br_lck)
 {
        files_struct *fsp = br_lck->fsp;
        uint16 tid = fsp->conn->cnum;
        int fnum = fsp->fnum;
        unsigned int i, j, dcount=0;
        struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
+       struct process_id pid = procid_self();
+       BOOL unlock_individually = False;
+
+       if(lp_posix_locking(fsp->conn->cnum) && !lp_posix_cifsu_locktype()) {
+
+               /* Check if there are any Windows locks associated with this dev/ino
+                  pair that are not this fnum. If so we need to call unlock on each
+                  one in order to release the system POSIX locks correctly. */
+
+               for (i=0; i < br_lck->num_locks; i++) {
+                       struct lock_struct *lock = &locks[i];
+
+                       if (!procid_equal(&lock->context.pid, &pid)) {
+                               continue;
+                       }
+
+                       if (lock->lock_type != READ_LOCK && lock->lock_type != WRITE_LOCK) {
+                               continue; /* Ignore pending. */
+                       }
+
+                       if (lock->context.tid != tid || lock->fnum != fnum) {
+                               unlock_individually = True;
+                               break;
+                       }
+               }
+
+               if (unlock_individually) {
+                       struct lock_struct *locks_copy;
+
+                       /* Copy the current lock array. */
+                       locks_copy = TALLOC_MEMDUP(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct));
+                       if (!locks_copy) {
+                               DEBUG(0,("brl_close_fnum: talloc fail.\n"));
+                       }
+
+                       for (i=0; i < br_lck->num_locks; i++) {
+                               struct lock_struct *lock = &locks_copy[i];
+
+                               if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid) &&
+                                               (lock->fnum == fnum)) {
+                                       brl_unlock(br_lck,
+                                               lock->context.smbpid,
+                                               pid,
+                                               lock->start,
+                                               lock->size,
+                                               lock->lock_flav);
+                               }
+                       }
+                       return;
+               }
+       }
+
+       /* We can bulk delete - any POSIX locks will be removed when the fd closes. */
+
+       /* Zero any lock reference count on this dev/ino pair. */
+       zero_windows_lock_ref_count(fsp);
 
        /* Remove any existing locks for this fnum (or any fnum if they're POSIX). */
 
@@ -1346,7 +1424,7 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st
        }
 
        if (orig_num_locks != num_locks) {
-               dbuf.dptr = (void *)locks;
+               dbuf.dptr = (char *)locks;
                dbuf.dsize = num_locks * sizeof(*locks);
 
                if (dbuf.dsize) {
@@ -1388,8 +1466,10 @@ int brl_forall(BRLOCK_FN(fn))
  Unlock the record.
 ********************************************************************/
 
-int byte_range_lock_destructor(struct byte_range_lock *br_lck)
+static int byte_range_lock_destructor(void *p)
 {
+       struct byte_range_lock *br_lck =
+               talloc_get_type_abort(p, struct byte_range_lock);
        TDB_DATA key;
 
        key.dptr = (char *)&br_lck->key;
@@ -1406,7 +1486,7 @@ int byte_range_lock_destructor(struct byte_range_lock *br_lck)
                }
        } else {
                TDB_DATA data;
-               data.dptr = br_lck->lock_data;
+               data.dptr = (char *)br_lck->lock_data;
                data.dsize = br_lck->num_locks * sizeof(struct lock_struct);
 
                if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) {
@@ -1418,20 +1498,21 @@ int byte_range_lock_destructor(struct byte_range_lock *br_lck)
 
        tdb_chainunlock(tdb, key);
        SAFE_FREE(br_lck->lock_data);
-       SAFE_FREE(br_lck);
        return 0;
 }
 
 /*******************************************************************
  Fetch a set of byte range lock data from the database.
  Leave the record locked.
+ TALLOC_FREE(brl) will release the lock in the destructor.
 ********************************************************************/
 
-struct byte_range_lock *brl_get_locks(files_struct *fsp)
+struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx,
+                                       files_struct *fsp)
 {
        TDB_DATA key;
        TDB_DATA data;
-       struct byte_range_lock *br_lck = SMB_MALLOC_P(struct byte_range_lock);
+       struct byte_range_lock *br_lck = TALLOC_P(mem_ctx, struct byte_range_lock);
 
        if (br_lck == NULL) {
                return NULL;
@@ -1449,10 +1530,12 @@ struct byte_range_lock *brl_get_locks(files_struct *fsp)
 
        if (tdb_chainlock(tdb, key) != 0) {
                DEBUG(3, ("Could not lock byte range lock entry\n"));
-               SAFE_FREE(br_lck);
+               TALLOC_FREE(br_lck);
                return NULL;
        }
 
+       talloc_set_destructor(br_lck, byte_range_lock_destructor);
+
        data = tdb_fetch(tdb, key);
        br_lck->lock_data = (void *)data.dptr;
        br_lck->num_locks = data.dsize / sizeof(struct lock_struct);
@@ -1463,13 +1546,22 @@ struct byte_range_lock *brl_get_locks(files_struct *fsp)
                /* Go through and ensure all entries exist - remove any that don't. */
                /* Makes the lockdb self cleaning at low cost. */
 
-               if (!validate_lock_entries(&br_lck->num_locks, (struct lock_struct **)&br_lck->lock_data)) {
-                       tdb_chainunlock(tdb, key);
+               struct lock_struct *locks =
+                       (struct lock_struct *)br_lck->lock_data;
+
+               if (!validate_lock_entries(&br_lck->num_locks, &locks)) {
                        SAFE_FREE(br_lck->lock_data);
-                       SAFE_FREE(br_lck);
+                       TALLOC_FREE(br_lck);
                        return NULL;
                }
 
+               /*
+                * validate_lock_entries might have changed locks. We can't
+                * use a direct pointer here because otherwise gcc warnes
+                * about strict aliasing rules being violated.
+                */
+               br_lck->lock_data = locks;
+
                /* Mark the lockdb as "clean" as seen from this open file. */
                fsp->lockdb_clean = True;
        }
index 9d3ca956014561817a721f723a00aed4da311856..ac50c9b648fdb7be9eb938ae82a9c5d38c5176f8 100644 (file)
@@ -37,7 +37,6 @@
 */
 
 #include "includes.h"
-uint16 global_smbpid;
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_LOCKING
@@ -74,6 +73,7 @@ const char *lock_flav_name(enum brl_flavour lock_flav)
 ****************************************************************************/
 
 BOOL is_locked(files_struct *fsp,
+               uint32 smbpid,
                SMB_BIG_UINT count,
                SMB_BIG_UINT offset, 
                enum brl_type lock_type)
@@ -100,32 +100,32 @@ BOOL is_locked(files_struct *fsp,
                        DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name ));
                        ret = False;
                } else {
-                       struct byte_range_lock *br_lck = brl_get_locks(fsp);
+                       struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
                        if (!br_lck) {
                                return False;
                        }
                        ret = !brl_locktest(br_lck,
-                                       global_smbpid,
+                                       smbpid,
                                        procid_self(),
                                        offset,
                                        count,
                                        lock_type,
                                        lock_flav);
-                       byte_range_lock_destructor(br_lck);
+                       TALLOC_FREE(br_lck);
                }
        } else {
-               struct byte_range_lock *br_lck = brl_get_locks(fsp);
+               struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
                if (!br_lck) {
                        return False;
                }
                ret = !brl_locktest(br_lck,
-                               global_smbpid,
+                               smbpid,
                                procid_self(),
                                offset,
                                count,
                                lock_type,
                                lock_flav);
-               byte_range_lock_destructor(br_lck);
+               TALLOC_FREE(br_lck);
        }
 
        DEBUG(10,("is_locked: flavour = %s brl start=%.0f len=%.0f %s for fnum %d file %s\n",
@@ -141,7 +141,7 @@ BOOL is_locked(files_struct *fsp,
 ****************************************************************************/
 
 NTSTATUS query_lock(files_struct *fsp,
-                       uint16 *psmbpid,
+                       uint32 *psmbpid,
                        SMB_BIG_UINT *pcount,
                        SMB_BIG_UINT *poffset,
                        enum brl_type *plock_type,
@@ -150,15 +150,15 @@ NTSTATUS query_lock(files_struct *fsp,
        struct byte_range_lock *br_lck = NULL;
        NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;
 
-       if (!OPEN_FSP(fsp) || !fsp->can_lock) {
-               return NT_STATUS_INVALID_HANDLE;
+       if (!fsp->can_lock) {
+               return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
        }
 
        if (!lp_locking(SNUM(fsp->conn))) {
                return NT_STATUS_OK;
        }
 
-       br_lck = brl_get_locks(fsp);
+       br_lck = brl_get_locks(NULL, fsp);
        if (!br_lck) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -171,7 +171,7 @@ NTSTATUS query_lock(files_struct *fsp,
                        plock_type,
                        lock_flav);
 
-       byte_range_lock_destructor(br_lck);
+       TALLOC_FREE(br_lck);
        return status;
 }
 
@@ -180,7 +180,7 @@ NTSTATUS query_lock(files_struct *fsp,
 ****************************************************************************/
 
 NTSTATUS do_lock(files_struct *fsp,
-                       uint16 lock_pid,
+                       uint32 lock_pid,
                        SMB_BIG_UINT count,
                        SMB_BIG_UINT offset,
                        enum brl_type lock_type,
@@ -190,8 +190,8 @@ NTSTATUS do_lock(files_struct *fsp,
        struct byte_range_lock *br_lck = NULL;
        NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;
 
-       if (!OPEN_FSP(fsp) || !fsp->can_lock) {
-               return NT_STATUS_INVALID_HANDLE;
+       if (!fsp->can_lock) {
+               return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
        }
 
        if (!lp_locking(SNUM(fsp->conn))) {
@@ -204,7 +204,7 @@ NTSTATUS do_lock(files_struct *fsp,
                lock_flav_name(lock_flav), lock_type_name(lock_type),
                (double)offset, (double)count, fsp->fnum, fsp->fsp_name ));
 
-       br_lck = brl_get_locks(fsp);
+       br_lck = brl_get_locks(NULL, fsp);
        if (!br_lck) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -218,7 +218,7 @@ NTSTATUS do_lock(files_struct *fsp,
                        lock_flav,
                        my_lock_ctx);
 
-       byte_range_lock_destructor(br_lck);
+       TALLOC_FREE(br_lck);
        return status;
 }
 
@@ -230,7 +230,7 @@ NTSTATUS do_lock(files_struct *fsp,
 ****************************************************************************/
 
 NTSTATUS do_lock_spin(files_struct *fsp,
-                       uint16 lock_pid,
+                       uint32 lock_pid,
                        SMB_BIG_UINT count,
                        SMB_BIG_UINT offset,
                        enum brl_type lock_type,
@@ -286,7 +286,7 @@ NTSTATUS do_lock_spin(files_struct *fsp,
 ****************************************************************************/
 
 NTSTATUS do_unlock(files_struct *fsp,
-                       uint16 lock_pid,
+                       uint32 lock_pid,
                        SMB_BIG_UINT count,
                        SMB_BIG_UINT offset,
                        enum brl_flavour lock_flav)
@@ -294,18 +294,18 @@ NTSTATUS do_unlock(files_struct *fsp,
        BOOL ok = False;
        struct byte_range_lock *br_lck = NULL;
        
-       if (!lp_locking(SNUM(fsp->conn))) {
-               return NT_STATUS_OK;
+       if (!fsp->can_lock) {
+               return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
        }
        
-       if (!OPEN_FSP(fsp) || !fsp->can_lock) {
-               return NT_STATUS_INVALID_HANDLE;
+       if (!lp_locking(SNUM(fsp->conn))) {
+               return NT_STATUS_OK;
        }
        
        DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n",
                  (double)offset, (double)count, fsp->fnum, fsp->fsp_name ));
 
-       br_lck = brl_get_locks(fsp);
+       br_lck = brl_get_locks(NULL, fsp);
        if (!br_lck) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -317,7 +317,7 @@ NTSTATUS do_unlock(files_struct *fsp,
                        count,
                        lock_flav);
    
-       byte_range_lock_destructor(br_lck);
+       TALLOC_FREE(br_lck);
 
        if (!ok) {
                DEBUG(10,("do_unlock: returning ERRlock.\n" ));
@@ -334,25 +334,15 @@ NTSTATUS do_unlock(files_struct *fsp,
 void locking_close_file(files_struct *fsp)
 {
        struct byte_range_lock *br_lck;
-       struct process_id pid = procid_self();
 
-       if (!lp_locking(SNUM(fsp->conn)))
+       if (!lp_locking(SNUM(fsp->conn))) {
                return;
-
-       /*
-        * Just release all the brl locks, no need to release individually.
-        */
-
-       br_lck = brl_get_locks(fsp);
-       if (br_lck) {
-               brl_close_fnum(br_lck, pid);
-               byte_range_lock_destructor(br_lck);
        }
 
-       if(lp_posix_locking(SNUM(fsp->conn))) {
-               /* Release all the POSIX locks.*/
-               posix_locking_close_file(fsp);
-
+       br_lck = brl_get_locks(NULL,fsp);
+       if (br_lck) {
+               brl_close_fnum(br_lck);
+               TALLOC_FREE(br_lck);
        }
 }
 
@@ -516,9 +506,10 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck)
                        smb_panic("PANIC: parse_share_modes: buffer too short.\n");
                }
                                  
-               lck->share_modes = talloc_memdup(lck, dbuf.dptr+sizeof(*data),
-                                                lck->num_share_modes *
-                                                sizeof(struct share_mode_entry));
+               lck->share_modes = (struct share_mode_entry *)
+                       talloc_memdup(lck, dbuf.dptr+sizeof(*data),
+                                     lck->num_share_modes *
+                                     sizeof(struct share_mode_entry));
 
                if (lck->share_modes == NULL) {
                        smb_panic("talloc failed\n");
@@ -635,7 +626,7 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck)
                delete_token_size +
                sp_len + 1 +
                strlen(lck->filename) + 1;
-       result.dptr = talloc_size(lck, result.dsize);
+       result.dptr = TALLOC_ARRAY(lck, char, result.dsize);
 
        if (result.dptr == NULL) {
                smb_panic("talloc failed\n");
@@ -838,7 +829,7 @@ BOOL rename_share_filename(struct share_mode_lock *lck,
        msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + fn_len + 1;
 
        /* Set up the name changed message. */
-       frm = TALLOC(lck, msg_len);
+       frm = TALLOC_ARRAY(lck, char, msg_len);
        if (!frm) {
                return False;
        }
@@ -862,9 +853,9 @@ BOOL rename_share_filename(struct share_mode_lock *lck,
                        continue;
                }
 
-               DEBUG(10,("rename_share_filename: sending rename message to pid %u "
+               DEBUG(10,("rename_share_filename: sending rename message to pid %s "
                        "dev %x, inode  %.0f sharepath %s newname %s\n",
-                       (unsigned int)procid_to_pid(&se->pid),
+                       procid_str_static(&se->pid),
                        (unsigned int)lck->dev, (double)lck->ino,
                        lck->servicepath, lck->filename ));
 
@@ -1305,5 +1296,5 @@ int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *,
 {
        if (tdb == NULL)
                return 0;
-       return tdb_traverse(tdb, traverse_fn, fn);
+       return tdb_traverse(tdb, traverse_fn, (void *)fn);
 }
index 4a5f59b622d5f2b8b60c8ddd0ae2bad4bec77ea0..59b62170e828e9451ace632f43f13f30dd93e604 100644 (file)
@@ -1,7 +1,7 @@
 /* 
    Unix SMB/CIFS implementation.
    Locking functions
-   Copyright (C) Jeremy Allison 1992-2000
+   Copyright (C) Jeremy Allison 1992-2006
    
    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
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_LOCKING
 
-/*
- * The POSIX locking database handle.
- */
-
-static TDB_CONTEXT *posix_lock_tdb;
-
 /*
  * The pending close database handle.
  */
 
 static TDB_CONTEXT *posix_pending_close_tdb;
 
-/*
- * The data in POSIX lock records is an unsorted linear array of these
- * records.  It is unnecessary to store the count as tdb provides the
- * size of the record.
- */
-
-struct posix_lock {
-       int fd;
-       SMB_OFF_T start;
-       SMB_OFF_T size;
-       int lock_type;
-};
-
-/*
- * The data in POSIX pending close records is an unsorted linear array of int
- * records.  It is unnecessary to store the count as tdb provides the
- * size of the record.
- */
-
-/* The key used in both the POSIX databases. */
-
-struct posix_lock_key {
-       SMB_DEV_T device;
-       SMB_INO_T inode;
-}; 
+/****************************************************************************
+ First - the functions that deal with the underlying system locks - these
+ functions are used no matter if we're mapping CIFS Windows locks or CIFS
+ POSIX locks onto POSIX.
+****************************************************************************/
 
-/*******************************************************************
- Form a static locking key for a dev/inode pair.
-******************************************************************/
+/****************************************************************************
+ Utility function to map a lock type correctly depending on the open
+ mode of a file.
+****************************************************************************/
 
-static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
+static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type)
 {
-       static struct posix_lock_key key;
-       TDB_DATA kbuf;
+       if((lock_type == WRITE_LOCK) && !fsp->can_write) {
+               /*
+                * Many UNIX's cannot get a write lock on a file opened read-only.
+                * Win32 locking semantics allow this.
+                * Do the best we can and attempt a read-only lock.
+                */
+               DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n"));
+               return F_RDLCK;
+       }
 
-       memset(&key, '\0', sizeof(key));
-       key.device = dev;
-       key.inode = inode;
-       kbuf.dptr = (char *)&key;
-       kbuf.dsize = sizeof(key);
-       return kbuf;
+       /*
+        * This return should be the most normal, as we attempt
+        * to always open files read/write.
+        */
+
+       return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK;
 }
 
-/*******************************************************************
Convenience function to get a key from an fsp.
-******************************************************************/
+/****************************************************************************
Debugging aid :-).
+****************************************************************************/
 
-static TDB_DATA locking_key_fsp(files_struct *fsp)
+static const char *posix_lock_type_name(int lock_type)
 {
-       return locking_key(fsp->dev, fsp->inode);
+       return (lock_type == F_RDLCK) ? "READ" : "WRITE";
 }
 
 /****************************************************************************
- Add an fd to the pending close tdb.
+ Check to see if the given unsigned lock range is within the possible POSIX
+ range. Modifies the given args to be in range if possible, just returns
+ False if not.
 ****************************************************************************/
 
-static BOOL add_fd_to_close_entry(files_struct *fsp)
+static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
+                               SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count)
 {
-       TDB_DATA kbuf = locking_key_fsp(fsp);
-       TDB_DATA dbuf;
+       SMB_OFF_T offset = (SMB_OFF_T)u_offset;
+       SMB_OFF_T count = (SMB_OFF_T)u_count;
 
-       dbuf.dptr = NULL;
-       dbuf.dsize = 0;
+       /*
+        * For the type of system we are, attempt to
+        * find the maximum positive lock offset as an SMB_OFF_T.
+        */
 
-       dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+#if defined(MAX_POSITIVE_LOCK_OFFSET) /* Some systems have arbitrary limits. */
 
-       dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int));
-       if (!dbuf.dptr) {
-               DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n"));
+       SMB_OFF_T max_positive_lock_offset = (MAX_POSITIVE_LOCK_OFFSET);
+
+#elif defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS)
+
+       /*
+        * In this case SMB_OFF_T is 64 bits,
+        * and the underlying system can handle 64 bit signed locks.
+        */
+
+       SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
+       SMB_OFF_T mask = (mask2<<1);
+       SMB_OFF_T max_positive_lock_offset = ~mask;
+
+#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
+
+       /*
+        * In this case either SMB_OFF_T is 32 bits,
+        * or the underlying system cannot handle 64 bit signed locks.
+        * All offsets & counts must be 2^31 or less.
+        */
+
+       SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF;
+
+#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
+
+       /*
+        * POSIX locks of length zero mean lock to end-of-file.
+        * Win32 locks of length zero are point probes. Ignore
+        * any Win32 locks of length zero. JRA.
+        */
+
+       if (count == (SMB_OFF_T)0) {
+               DEBUG(10,("posix_lock_in_range: count = 0, ignoring.\n"));
                return False;
        }
 
-       memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int));
-       dbuf.dsize += sizeof(int);
+       /*
+        * If the given offset was > max_positive_lock_offset then we cannot map this at all
+        * ignore this lock.
+        */
 
-       if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
-               DEBUG(0,("add_fd_to_close_entry: tdb_store fail !\n"));
+       if (u_offset & ~((SMB_BIG_UINT)max_positive_lock_offset)) {
+               DEBUG(10,("posix_lock_in_range: (offset = %.0f) offset > %.0f and we cannot handle this. Ignoring lock.\n",
+                               (double)u_offset, (double)((SMB_BIG_UINT)max_positive_lock_offset) ));
+               return False;
        }
 
-       SAFE_FREE(dbuf.dptr);
+       /*
+        * We must truncate the count to less than max_positive_lock_offset.
+        */
+
+       if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset)) {
+               count = max_positive_lock_offset;
+       }
+
+       /*
+        * Truncate count to end at max lock offset.
+        */
+
+       if (offset + count < 0 || offset + count > max_positive_lock_offset) {
+               count = max_positive_lock_offset - offset;
+       }
+
+       /*
+        * If we ate all the count, ignore this lock.
+        */
+
+       if (count == 0) {
+               DEBUG(10,("posix_lock_in_range: Count = 0. Ignoring lock u_offset = %.0f, u_count = %.0f\n",
+                               (double)u_offset, (double)u_count ));
+               return False;
+       }
+
+       /*
+        * The mapping was successful.
+        */
+
+       DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n",
+                       (double)offset, (double)count ));
+
+       *offset_out = offset;
+       *count_out = count;
+       
        return True;
 }
 
 /****************************************************************************
- Remove all fd entries for a specific dev/inode pair from the tdb.
+ Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and
+ broken NFS implementations.
 ****************************************************************************/
 
-static void delete_close_entries(files_struct *fsp)
+static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
 {
-       TDB_DATA kbuf = locking_key_fsp(fsp);
+       BOOL ret;
 
-       if (tdb_delete(posix_pending_close_tdb, kbuf) == -1)
-               DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));
-}
+       DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type));
 
-/****************************************************************************
- Get the array of POSIX pending close records for an open fsp. Caller must
- free. Returns number of entries.
-****************************************************************************/
+       ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
 
-static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries)
-{
-       TDB_DATA kbuf = locking_key_fsp(fsp);
-       TDB_DATA dbuf;
-       size_t count = 0;
+       if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  EINVAL))) {
 
-       *entries = NULL;
-       dbuf.dptr = NULL;
+               DEBUG(0,("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n",
+                                       (double)offset,(double)count));
+               DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));
+               DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
 
-       dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+               /*
+                * If the offset is > 0x7FFFFFFF then this will cause problems on
+                * 32 bit NFS mounted filesystems. Just ignore it.
+                */
 
-       if (!dbuf.dptr) {
-               return 0;
-       }
+               if (offset & ~((SMB_OFF_T)0x7fffffff)) {
+                       DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
+                       return True;
+               }
 
-       *entries = (int *)dbuf.dptr;
-       count = (size_t)(dbuf.dsize / sizeof(int));
+               if (count & ~((SMB_OFF_T)0x7fffffff)) {
+                       /* 32 bit NFS file system, retry with smaller offset */
+                       DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
+                       errno = 0;
+                       count &= 0x7fffffff;
+                       ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
+               }
+       }
 
-       return count;
+       DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed"));
+       return ret;
 }
 
 /****************************************************************************
- Get the array of POSIX locks for an fsp. Caller must free. Returns
number of entries.
+ Actual function that gets POSIX locks. Copes with 64 -> 32 bit cruft and
broken NFS implementations.
 ****************************************************************************/
 
-static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entries)
+static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype)
 {
-       TDB_DATA kbuf = locking_key_fsp(fsp);
-       TDB_DATA dbuf;
-       size_t count = 0;
+       pid_t pid;
+       BOOL ret;
 
-       *entries = NULL;
+       DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n",
+               fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype));
 
-       dbuf.dptr = NULL;
+       ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
 
-       dbuf = tdb_fetch(posix_lock_tdb, kbuf);
+       if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  EINVAL))) {
 
-       if (!dbuf.dptr) {
-               return 0;
-       }
+               DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset %.0f, length %.0f returned\n",
+                                       (double)*poffset,(double)*pcount));
+               DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));
+               DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
 
-       *entries = (struct posix_lock *)dbuf.dptr;
-       count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
+               /*
+                * If the offset is > 0x7FFFFFFF then this will cause problems on
+                * 32 bit NFS mounted filesystems. Just ignore it.
+                */
 
-       return count;
+               if (*poffset & ~((SMB_OFF_T)0x7fffffff)) {
+                       DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
+                       return True;
+               }
+
+               if (*pcount & ~((SMB_OFF_T)0x7fffffff)) {
+                       /* 32 bit NFS file system, retry with smaller offset */
+                       DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
+                       errno = 0;
+                       *pcount &= 0x7fffffff;
+                       ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
+               }
+       }
+
+       DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? "successful" : "failed"));
+       return ret;
 }
 
 /****************************************************************************
- Deal with pending closes needed by POSIX locking support.
- Note that posix_locking_close_file() is expected to have been called
- to delete all locks on this fsp before this function is called.
+ POSIX function to see if a file region is locked. Returns True if the
+ region is locked, False otherwise.
 ****************************************************************************/
 
-int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
+BOOL is_posix_locked(files_struct *fsp,
+                       SMB_BIG_UINT *pu_offset,
+                       SMB_BIG_UINT *pu_count,
+                       enum brl_type *plock_type,
+                       enum brl_flavour lock_flav)
 {
-       int saved_errno = 0;
-       int ret;
-       size_t count, i;
-       struct posix_lock *entries = NULL;
-       int *fd_array = NULL;
-       BOOL locks_on_other_fds = False;
-
-       if (!lp_posix_locking(SNUM(conn))) {
-               /*
-                * No POSIX to worry about, just close.
-                */
-               ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
-               fsp->fh->fd = -1;
-               return ret;
-       }
-
-       /*
-        * Get the number of outstanding POSIX locks on this dev/inode pair.
-        */
+       SMB_OFF_T offset;
+       SMB_OFF_T count;
+       int posix_lock_type = map_posix_lock_type(fsp,*plock_type);
 
-       count = get_posix_lock_entries(fsp, &entries);
+       DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n",
+               fsp->fsp_name, (double)*pu_offset, (double)*pu_count, posix_lock_type_name(*plock_type) ));
 
        /*
-        * Check if there are any outstanding locks belonging to
-        * other fd's. This should never be the case if posix_locking_close_file()
-        * has been called first, but it never hurts to be *sure*.
+        * If the requested lock won't fit in the POSIX range, we will
+        * never set it, so presume it is not locked.
         */
 
-       for (i = 0; i < count; i++) {
-               if (entries[i].fd != fsp->fh->fd) {
-                       locks_on_other_fds = True;
-                       break;
-               }
+       if(!posix_lock_in_range(&offset, &count, *pu_offset, *pu_count)) {
+               return False;
        }
 
-       if (locks_on_other_fds) {
-
-               /*
-                * There are outstanding locks on this dev/inode pair on other fds.
-                * Add our fd to the pending close tdb and set fsp->fh->fd to -1.
-                */
-
-               if (!add_fd_to_close_entry(fsp)) {
-                       SAFE_FREE(entries);
-                       return -1;
-               }
+       if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) {
+               return False;
+       }
 
-               SAFE_FREE(entries);
-               fsp->fh->fd = -1;
-               return 0;
+       if (posix_lock_type == F_UNLCK) {
+               return False;
        }
 
-       SAFE_FREE(entries);
+       if (lock_flav == POSIX_LOCK) {
+               /* Only POSIX lock queries need to know the details. */
+               *pu_offset = (SMB_BIG_UINT)offset;
+               *pu_count = (SMB_BIG_UINT)count;
+               *plock_type = (posix_lock_type == F_RDLCK) ? READ_LOCK : WRITE_LOCK;
+       }
+       return True;
+}
 
-       /*
       * No outstanding POSIX locks. Get the pending close fd's
       * from the tdb and close them all.
-        */
+/****************************************************************************
Next - the functions that deal with in memory database storing representations
of either Windows CIFS locks or POSIX CIFS locks.
+****************************************************************************/
 
-       count = get_posix_pending_close_entries(fsp, &fd_array);
+/* The key used in the in-memory POSIX databases. */
 
-       if (count) {
-               DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count ));
+struct lock_ref_count_key {
+       SMB_DEV_T device;
+       SMB_INO_T inode;
+       char r;
+}; 
 
-               for(i = 0; i < count; i++) {
-                       if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) {
-                               saved_errno = errno;
-                       }
-               }
+struct fd_key {
+       SMB_DEV_T device;
+       SMB_INO_T inode;
+}; 
 
-               /*
-                * Delete all fd's stored in the tdb
-                * for this dev/inode pair.
-                */
+/*******************************************************************
+ Form a static locking key for a dev/inode pair for the fd array.
+******************************************************************/
 
-               delete_close_entries(fsp);
-       }
+static TDB_DATA fd_array_key(SMB_DEV_T dev, SMB_INO_T inode)
+{
+       static struct fd_key key;
+       TDB_DATA kbuf;
 
-       SAFE_FREE(fd_array);
+       memset(&key, '\0', sizeof(key));
+       key.device = dev;
+       key.inode = inode;
+       kbuf.dptr = (char *)&key;
+       kbuf.dsize = sizeof(key);
+       return kbuf;
+}
 
-       /*
-        * Finally close the fd associated with this fsp.
-        */
+/*******************************************************************
+ Form a static locking key for a dev/inode pair for the lock ref count
+******************************************************************/
 
-       ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
+static TDB_DATA locking_ref_count_key(SMB_DEV_T dev, SMB_INO_T inode)
+{
+       static struct lock_ref_count_key key;
+       TDB_DATA kbuf;
 
-       if (saved_errno != 0) {
-               errno = saved_errno;
-               ret = -1;
-       } 
+       memset(&key, '\0', sizeof(key));
+       key.device = dev;
+       key.inode = inode;
+       key.r = 'r';
+       kbuf.dptr = (char *)&key;
+       kbuf.dsize = sizeof(key);
+       return kbuf;
+}
 
-       fsp->fh->fd = -1;
+/*******************************************************************
+ Convenience function to get an fd_array key from an fsp.
+******************************************************************/
 
-       return ret;
+static TDB_DATA fd_array_key_fsp(files_struct *fsp)
+{
+       return fd_array_key(fsp->dev, fsp->inode);
 }
 
-/****************************************************************************
Debugging aid :-).
-****************************************************************************/
+/*******************************************************************
Convenience function to get a lock ref count key from an fsp.
+******************************************************************/
 
-static const char *posix_lock_type_name(int lock_type)
+static TDB_DATA locking_ref_count_key_fsp(files_struct *fsp)
 {
-       return (lock_type == F_RDLCK) ? "READ" : "WRITE";
+       return locking_ref_count_key(fsp->dev, fsp->inode);
 }
 
-/****************************************************************************
- Delete a POSIX lock entry by index number. Used if the tdb add succeeds, but
- then the POSIX fcntl lock fails.
-****************************************************************************/
+/*******************************************************************
+ Create the in-memory POSIX lock databases.
+********************************************************************/
 
-static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry)
+BOOL posix_locking_init(int read_only)
 {
-       TDB_DATA kbuf = locking_key_fsp(fsp);
-       TDB_DATA dbuf;
-       struct posix_lock *locks;
-       size_t count;
-
-       dbuf.dptr = NULL;
+       if (posix_pending_close_tdb) {
+               return True;
+       }
        
-       dbuf = tdb_fetch(posix_lock_tdb, kbuf);
-
-       if (!dbuf.dptr) {
-               DEBUG(10,("delete_posix_lock_entry_by_index: tdb_fetch failed !\n"));
-               goto fail;
+       if (!posix_pending_close_tdb) {
+               posix_pending_close_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL,
+                                                  read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644);
        }
-
-       count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
-       locks = (struct posix_lock *)dbuf.dptr;
-
-       if (count == 1) {
-               tdb_delete(posix_lock_tdb, kbuf);
-       } else {
-               if (entry < count-1) {
-                       memmove(&locks[entry], &locks[entry+1], sizeof(struct posix_lock)*((count-1) - entry));
-               }
-               dbuf.dsize -= sizeof(struct posix_lock);
-               tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE);
+       if (!posix_pending_close_tdb) {
+               DEBUG(0,("Failed to open POSIX pending close database.\n"));
+               return False;
        }
 
-       SAFE_FREE(dbuf.dptr);
+       return True;
+}
+
+/*******************************************************************
+ Delete the in-memory POSIX lock databases.
+********************************************************************/
 
+BOOL posix_locking_end(void)
+{
+       if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0) {
+               return False;
+       }
        return True;
+}
 
- fail:
+/****************************************************************************
+ Next - the functions that deal with storing fd's that have outstanding
+ POSIX locks when closed.
+****************************************************************************/
 
-       SAFE_FREE(dbuf.dptr);
-       return False;
-}
+/****************************************************************************
+ The records in posix_pending_close_tdb are composed of an array of ints
+ keyed by dev/ino pair.
+ The first int is a reference count of the number of outstanding locks on
+ all open fd's on this dev/ino pair. Any subsequent ints are the fd's that
+ were open on this dev/ino pair that should have been closed, but can't as
+ the lock ref count is non zero.
+****************************************************************************/
 
 /****************************************************************************
- Add an entry into the POSIX locking tdb. We return the index number of the
- added lock (used in case we need to delete *exactly* this entry). Returns
- False on fail, True on success.
+ Keep a reference count of the number of Windows locks open on this dev/ino
+ pair. Creates entry if it doesn't exist.
 ****************************************************************************/
 
-static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type, size_t *pentry_num)
+static void increment_windows_lock_ref_count(files_struct *fsp)
 {
-       TDB_DATA kbuf = locking_key_fsp(fsp);
+       TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
        TDB_DATA dbuf;
-       struct posix_lock pl;
-
-       dbuf.dptr = NULL;
-       dbuf.dsize = 0;
+       int lock_ref_count;
 
-       dbuf = tdb_fetch(posix_lock_tdb, kbuf);
+       dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+       if (dbuf.dptr == NULL) {
+               dbuf.dptr = (char *)SMB_MALLOC_P(int);
+               if (!dbuf.dptr) {
+                       smb_panic("increment_windows_lock_ref_count: malloc fail.\n");
+               }
+               memset(dbuf.dptr, '\0', sizeof(int));
+               dbuf.dsize = sizeof(int);
+       }
 
-       *pentry_num = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
+       memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
+       lock_ref_count++;
+       memcpy(dbuf.dptr, &lock_ref_count, sizeof(int));
+       
+       if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
+               smb_panic("increment_windows_lock_ref_count: tdb_store_fail.\n");
+       }
+       SAFE_FREE(dbuf.dptr);
 
-       /*
-        * Add new record.
-        */
+       DEBUG(10,("increment_windows_lock_ref_count for file now %s = %d\n",
+               fsp->fsp_name, lock_ref_count ));
+}
 
-       pl.fd = fsp->fh->fd;
-       pl.start = start;
-       pl.size = size;
-       pl.lock_type = lock_type;
+static void decrement_windows_lock_ref_count(files_struct *fsp)
+{
+       TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
+       TDB_DATA dbuf;
+       int lock_ref_count;
 
-       dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(struct posix_lock));
+       dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
        if (!dbuf.dptr) {
-               DEBUG(0,("add_posix_lock_entry: Realloc fail !\n"));
-               goto fail;
+               smb_panic("decrement_windows_lock_ref_count: logic error.\n");
        }
 
-       memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(struct posix_lock));
-       dbuf.dsize += sizeof(struct posix_lock);
+       memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
+       lock_ref_count--;
+       memcpy(dbuf.dptr, &lock_ref_count, sizeof(int));
 
-       if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
-               DEBUG(0,("add_posix_lock: Failed to add lock entry on file %s\n", fsp->fsp_name));
-               goto fail;
+       if (lock_ref_count < 0) {
+               smb_panic("decrement_windows_lock_ref_count: lock_count logic error.\n");
        }
 
+       if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
+               smb_panic("decrement_windows_lock_ref_count: tdb_store_fail.\n");
+       }
        SAFE_FREE(dbuf.dptr);
 
-       DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: dev=%.0f inode=%.0f\n",
-                       fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size,
-                       (double)fsp->dev, (double)fsp->inode ));
-
-       return True;
-
- fail:
-
-       SAFE_FREE(dbuf.dptr);
-       return False;
-}
-
-/****************************************************************************
- Calculate if locks have any overlap at all.
-****************************************************************************/
-
-static BOOL does_lock_overlap(SMB_OFF_T start1, SMB_OFF_T size1, SMB_OFF_T start2, SMB_OFF_T size2)
-{
-       if (start1 >= start2 && start1 <= start2 + size2)
-               return True;
-
-       if (start1 < start2 && start1 + size1 > start2)
-               return True;
-
-       return False;
+       DEBUG(10,("decrement_windows_lock_ref_count for file now %s = %d\n",
+               fsp->fsp_name, lock_ref_count ));
 }
 
 /****************************************************************************
- Delete an entry from the POSIX locking tdb. Returns a copy of the entry being
- deleted and the number of records that are overlapped by this one, or -1 on error.
+ Ensure the lock ref count is zero.
 ****************************************************************************/
 
-static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, struct posix_lock *pl)
+void zero_windows_lock_ref_count(files_struct *fsp)
 {
-       TDB_DATA kbuf = locking_key_fsp(fsp);
+       TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
        TDB_DATA dbuf;
-       struct posix_lock *locks;
-       size_t i, count;
-       BOOL found = False;
-       int num_overlapping_records = 0;
-
-       dbuf.dptr = NULL;
-       
-       dbuf = tdb_fetch(posix_lock_tdb, kbuf);
+       int lock_ref_count;
 
+       dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
        if (!dbuf.dptr) {
-               DEBUG(10,("delete_posix_lock_entry: tdb_fetch failed !\n"));
-               goto fail;
+               return;
        }
 
-       /* There are existing locks - find a match. */
-       locks = (struct posix_lock *)dbuf.dptr;
-       count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
-
-       /*
-        * Search for and delete the first record that matches the
-        * unlock criteria.
-        */
-
-       for (i=0; i<count; i++) { 
-               struct posix_lock *entry = &locks[i];
-
-               if (entry->fd == fsp->fh->fd &&
-                       entry->start == start &&
-                       entry->size == size) {
-
-                       /* Make a copy */
-                       *pl = *entry;
-
-                       /* Found it - delete it. */
-                       if (count == 1) {
-                               tdb_delete(posix_lock_tdb, kbuf);
-                       } else {
-                               if (i < count-1) {
-                                       memmove(&locks[i], &locks[i+1], sizeof(struct posix_lock)*((count-1) - i));
-                               }
-                               dbuf.dsize -= sizeof(struct posix_lock);
-                               tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE);
-                       }
-                       count--;
-                       found = True;
-                       break;
-               }
+       memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
+       if (lock_ref_count < 0) {
+               smb_panic("zero_windows_lock_ref_count: lock_count logic error.\n");
        }
 
-       if (!found)
-               goto fail;
-
-       /*
-        * Count the number of entries that are
-        * overlapped by this unlock request.
-        */
-
-       for (i = 0; i < count; i++) {
-               struct posix_lock *entry = &locks[i];
-
-               if (fsp->fh->fd == entry->fd &&
-                       does_lock_overlap( start, size, entry->start, entry->size))
-                               num_overlapping_records++;
+       lock_ref_count = 0;
+       memcpy(dbuf.dptr, &lock_ref_count, sizeof(int));
+       
+       if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
+               smb_panic("zero_windows_lock_ref_count: tdb_store_fail.\n");
        }
-
-       DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n",
-                       posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size,
-                               (unsigned int)num_overlapping_records ));
-
        SAFE_FREE(dbuf.dptr);
 
-       return num_overlapping_records;
-
- fail:
-
-       SAFE_FREE(dbuf.dptr);
-       return -1;
+       DEBUG(10,("zero_windows_lock_ref_count for file now %s = %d\n",
+               fsp->fsp_name, lock_ref_count ));
 }
 
 /****************************************************************************
- Utility function to map a lock type correctly depending on the open
- mode of a file.
+ Fetch the lock ref count.
 ****************************************************************************/
 
-static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type)
+static int get_windows_lock_ref_count(files_struct *fsp)
 {
-       if((lock_type == WRITE_LOCK) && !fsp->can_write) {
-               /*
-                * Many UNIX's cannot get a write lock on a file opened read-only.
-                * Win32 locking semantics allow this.
-                * Do the best we can and attempt a read-only lock.
-                */
-               DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n"));
-               return F_RDLCK;
-       }
-#if 0
-       /* We no longer open files write-only. */
-        else if((lock_type == READ_LOCK) && !fsp->can_read) {
-               /*
-                * Ditto for read locks on write only files.
-                */
-               DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n"));
-               return F_WRLCK;
-       }
-#endif
+       TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
+       TDB_DATA dbuf;
+       int lock_ref_count;
 
-       /*
-        * This return should be the most normal, as we attempt
-        * to always open files read/write.
-        */
+       dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+       if (!dbuf.dptr) {
+               lock_ref_count = 0;
+       } else {
+               memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
+       }
 
-       return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK;
+       DEBUG(10,("get_windows_lock_count for file %s = %d\n",
+               fsp->fsp_name, lock_ref_count ));
+       return lock_ref_count;
 }
 
 /****************************************************************************
- Check to see if the given unsigned lock range is within the possible POSIX
- range. Modifies the given args to be in range if possible, just returns
- False if not.
+ Delete a lock_ref_count entry.
 ****************************************************************************/
 
-static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
-                               SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count)
+static void delete_windows_lock_ref_count(files_struct *fsp)
 {
-       SMB_OFF_T offset = (SMB_OFF_T)u_offset;
-       SMB_OFF_T count = (SMB_OFF_T)u_count;
-
-       /*
-        * For the type of system we are, attempt to
-        * find the maximum positive lock offset as an SMB_OFF_T.
-        */
-
-#if defined(MAX_POSITIVE_LOCK_OFFSET) /* Some systems have arbitrary limits. */
-
-       SMB_OFF_T max_positive_lock_offset = (MAX_POSITIVE_LOCK_OFFSET);
-
-#elif defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS)
+       TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
 
-       /*
-        * In this case SMB_OFF_T is 64 bits,
-        * and the underlying system can handle 64 bit signed locks.
-        */
-
-       SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
-       SMB_OFF_T mask = (mask2<<1);
-       SMB_OFF_T max_positive_lock_offset = ~mask;
-
-#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
+       /* Not a bug if it doesn't exist - no locks were ever granted. */
+       tdb_delete(posix_pending_close_tdb, kbuf);
+       DEBUG(10,("delete_windows_lock_ref_count for file %s\n", fsp->fsp_name));
+}
 
-       /*
-        * In this case either SMB_OFF_T is 32 bits,
-        * or the underlying system cannot handle 64 bit signed locks.
-        * All offsets & counts must be 2^31 or less.
-        */
+/****************************************************************************
+ Add an fd to the pending close tdb.
+****************************************************************************/
 
-       SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF;
+static void add_fd_to_close_entry(files_struct *fsp)
+{
+       TDB_DATA kbuf = fd_array_key_fsp(fsp);
+       TDB_DATA dbuf;
 
-#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
+       dbuf.dptr = NULL;
+       dbuf.dsize = 0;
 
-       /*
-        * POSIX locks of length zero mean lock to end-of-file.
-        * Win32 locks of length zero are point probes. Ignore
-        * any Win32 locks of length zero. JRA.
-        */
+       dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
 
-       if (count == (SMB_OFF_T)0) {
-               DEBUG(10,("posix_lock_in_range: count = 0, ignoring.\n"));
-               return False;
+       dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int));
+       if (!dbuf.dptr) {
+               smb_panic("add_fd_to_close_entry: Realloc fail !\n");
        }
 
-       /*
-        * If the given offset was > max_positive_lock_offset then we cannot map this at all
-        * ignore this lock.
-        */
+       memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int));
+       dbuf.dsize += sizeof(int);
 
-       if (u_offset & ~((SMB_BIG_UINT)max_positive_lock_offset)) {
-               DEBUG(10,("posix_lock_in_range: (offset = %.0f) offset > %.0f and we cannot handle this. Ignoring lock.\n",
-                               (double)u_offset, (double)((SMB_BIG_UINT)max_positive_lock_offset) ));
-               return False;
+       if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
+               smb_panic("add_fd_to_close_entry: tdb_store_fail.\n");
        }
 
-       /*
-        * We must truncate the count to less than max_positive_lock_offset.
-        */
-
-       if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset))
-               count = max_positive_lock_offset;
+       DEBUG(10,("add_fd_to_close_entry: added fd %d file %s\n",
+               fsp->fh->fd, fsp->fsp_name ));
 
-       /*
-        * Truncate count to end at max lock offset.
-        */
+       SAFE_FREE(dbuf.dptr);
+}
 
-       if (offset + count < 0 || offset + count > max_positive_lock_offset)
-               count = max_positive_lock_offset - offset;
+/****************************************************************************
+ Remove all fd entries for a specific dev/inode pair from the tdb.
+****************************************************************************/
 
-       /*
-        * If we ate all the count, ignore this lock.
-        */
+static void delete_close_entries(files_struct *fsp)
+{
+       TDB_DATA kbuf = fd_array_key_fsp(fsp);
 
-       if (count == 0) {
-               DEBUG(10,("posix_lock_in_range: Count = 0. Ignoring lock u_offset = %.0f, u_count = %.0f\n",
-                               (double)u_offset, (double)u_count ));
-               return False;
+       if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) {
+               smb_panic("delete_close_entries: tdb_delete fail !\n");
        }
-
-       /*
-        * The mapping was successful.
-        */
-
-       DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n",
-                       (double)offset, (double)count ));
-
-       *offset_out = offset;
-       *count_out = count;
-       
-       return True;
 }
 
 /****************************************************************************
- Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and
broken NFS implementations.
+ Get the array of POSIX pending close records for an open fsp. Caller must
free. Returns number of entries.
 ****************************************************************************/
 
-static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
+static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries)
 {
-       BOOL ret;
-
-       DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type));
-
-       ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
-
-       if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  EINVAL))) {
-
-               DEBUG(0,("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n",
-                                       (double)offset,(double)count));
-               DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));
-               DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
+       TDB_DATA kbuf = fd_array_key_fsp(fsp);
+       TDB_DATA dbuf;
+       size_t count = 0;
 
-               /*
-                * If the offset is > 0x7FFFFFFF then this will cause problems on
-                * 32 bit NFS mounted filesystems. Just ignore it.
-                */
+       *entries = NULL;
+       dbuf.dptr = NULL;
 
-               if (offset & ~((SMB_OFF_T)0x7fffffff)) {
-                       DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
-                       return True;
-               }
+       dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
 
-               if (count & ~((SMB_OFF_T)0x7fffffff)) {
-                       /* 32 bit NFS file system, retry with smaller offset */
-                       DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
-                       errno = 0;
-                       count &= 0x7fffffff;
-                       ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
-               }
+       if (!dbuf.dptr) {
+               return 0;
        }
 
-       DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed"));
-       return ret;
+       *entries = (int *)dbuf.dptr;
+       count = (size_t)(dbuf.dsize / sizeof(int));
+
+       return count;
 }
 
 /****************************************************************************
- Actual function that gets POSIX locks. Copes with 64 -> 32 bit cruft and
- broken NFS implementations.
+ Deal with pending closes needed by POSIX locking support.
+ Note that posix_locking_close_file() is expected to have been called
+ to delete all locks on this fsp before this function is called.
 ****************************************************************************/
 
-static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype)
+int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
 {
-       pid_t pid;
-       BOOL ret;
-
-       DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n",
-               fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype));
-
-       ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
+       int saved_errno = 0;
+       int ret;
+       int *fd_array = NULL;
+       size_t count, i;
 
-       if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  EINVAL))) {
+       if (!lp_locking(SNUM(fsp->conn)) || !lp_posix_locking(SNUM(conn)) || lp_posix_cifsu_locktype()) {
+               /*
+                * No locking or POSIX to worry about or we want POSIX semantics
+                * which will lose all locks on all fd's open on this dev/inode,
+                * just close.
+                */
+               ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
+               fsp->fh->fd = -1;
+               return ret;
+       }
 
-               DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset %.0f, length %.0f returned\n",
-                                       (double)*poffset,(double)*pcount));
-               DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));
-               DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
+       if (get_windows_lock_ref_count(fsp)) {
 
                /*
-                * If the offset is > 0x7FFFFFFF then this will cause problems on
-                * 32 bit NFS mounted filesystems. Just ignore it.
+                * There are outstanding locks on this dev/inode pair on other fds.
+                * Add our fd to the pending close tdb and set fsp->fh->fd to -1.
                 */
 
-               if (*poffset & ~((SMB_OFF_T)0x7fffffff)) {
-                       DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
-                       return True;
-               }
-
-               if (*pcount & ~((SMB_OFF_T)0x7fffffff)) {
-                       /* 32 bit NFS file system, retry with smaller offset */
-                       DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
-                       errno = 0;
-                       *pcount &= 0x7fffffff;
-                       ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
-               }
+               add_fd_to_close_entry(fsp);
+               fsp->fh->fd = -1;
+               return 0;
        }
 
-       DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? "successful" : "failed"));
-       return ret;
-}
+       /*
+        * No outstanding locks. Get the pending close fd's
+        * from the tdb and close them all.
+        */
 
+       count = get_posix_pending_close_entries(fsp, &fd_array);
 
-/****************************************************************************
- POSIX function to see if a file region is locked. Returns True if the
- region is locked, False otherwise.
-****************************************************************************/
+       if (count) {
+               DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count ));
 
-BOOL is_posix_locked(files_struct *fsp,
-                       SMB_BIG_UINT *pu_offset,
-                       SMB_BIG_UINT *pu_count,
-                       enum brl_type *plock_type,
-                       enum brl_flavour lock_flav)
-{
-       SMB_OFF_T offset;
-       SMB_OFF_T count;
-       int posix_lock_type = map_posix_lock_type(fsp,*plock_type);
+               for(i = 0; i < count; i++) {
+                       if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) {
+                               saved_errno = errno;
+                       }
+               }
 
-       DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n",
-               fsp->fsp_name, (double)*pu_offset, (double)*pu_count, posix_lock_type_name(*plock_type) ));
+               /*
+                * Delete all fd's stored in the tdb
+                * for this dev/inode pair.
+                */
+
+               delete_close_entries(fsp);
+       }
+
+       SAFE_FREE(fd_array);
+
+       /* Don't need a lock ref count on this dev/ino anymore. */
+       delete_windows_lock_ref_count(fsp);
 
        /*
-        * If the requested lock won't fit in the POSIX range, we will
-        * never set it, so presume it is not locked.
+        * Finally close the fd associated with this fsp.
         */
 
-       if(!posix_lock_in_range(&offset, &count, *pu_offset, *pu_count)) {
-               return False;
-       }
+       ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
 
-       if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) {
-               return False;
-       }
+       if (saved_errno != 0) {
+               errno = saved_errno;
+               ret = -1;
+       } 
 
-       if (posix_lock_type == F_UNLCK) {
-               return False;
-       }
+       fsp->fh->fd = -1;
 
-       if (lock_flav == POSIX_LOCK) {
-               /* Only POSIX lock queries need to know the details. */
-               *pu_offset = (SMB_BIG_UINT)offset;
-               *pu_count = (SMB_BIG_UINT)count;
-               *plock_type = (posix_lock_type == F_RDLCK) ? READ_LOCK : WRITE_LOCK;
-       }
-       return True;
+       return ret;
 }
 
+/****************************************************************************
+ Next - the functions that deal with the mapping CIFS Windows locks onto
+ the underlying system POSIX locks.
+****************************************************************************/
+
 /*
  * Structure used when splitting a lock range
  * into a POSIX lock range. Doubly linked list.
@@ -792,22 +733,14 @@ struct lock_list {
  understand it :-).
 ****************************************************************************/
 
-static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhead, files_struct *fsp)
+static struct lock_list *posix_lock_list(TALLOC_CTX *ctx,
+                                               struct lock_list *lhead,
+                                               const struct lock_context *lock_ctx, /* Lock context lhead belongs to. */
+                                               files_struct *fsp,
+                                               const struct lock_struct *plocks,
+                                               int num_locks)
 {
-       TDB_DATA kbuf = locking_key_fsp(fsp);
-       TDB_DATA dbuf;
-       struct posix_lock *locks;
-       size_t num_locks, i;
-
-       dbuf.dptr = NULL;
-
-       dbuf = tdb_fetch(posix_lock_tdb, kbuf);
-
-       if (!dbuf.dptr)
-               return lhead;
-       
-       locks = (struct posix_lock *)dbuf.dptr;
-       num_locks = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
+       int i;
 
        /*
         * Check the current lock list on this dev/inode pair.
@@ -818,10 +751,19 @@ static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhea
                (double)lhead->start, (double)lhead->size ));
 
        for (i=0; i<num_locks && lhead; i++) {
-
-               struct posix_lock *lock = &locks[i];
+               const struct lock_struct *lock = &plocks[i];
                struct lock_list *l_curr;
 
+               /* Ignore all but read/write locks. */
+               if (lock->lock_type != READ_LOCK && lock->lock_type != WRITE_LOCK) {
+                       continue;
+               }
+
+               /* Ignore locks not owned by this process. */
+               if (!procid_equal(&lock->context.pid, &lock_ctx->pid)) {
+                       continue;
+               }
+
                /*
                 * Walk the lock list, checking for overlaps. Note that
                 * the lock list can expand within this loop if the current
@@ -830,13 +772,13 @@ static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhea
 
                for (l_curr = lhead; l_curr;) {
 
-                       DEBUG(10,("posix_lock_list: lock: fd=%d: start=%.0f,size=%.0f:type=%s", lock->fd,
+                       DEBUG(10,("posix_lock_list: lock: fnum=%d: start=%.0f,size=%.0f:type=%s", lock->fnum,
                                (double)lock->start, (double)lock->size, posix_lock_type_name(lock->lock_type) ));
 
                        if ( (l_curr->start >= (lock->start + lock->size)) ||
                                 (lock->start >= (l_curr->start + l_curr->size))) {
 
-                               /* No overlap with this lock - leave this range alone. */
+                               /* No overlap with existing lock - leave this range alone. */
 /*********************************************
                                              +---------+
                                              | l_curr  |
@@ -850,7 +792,7 @@ OR....
              +---------+
 **********************************************/
 
-                               DEBUG(10,("no overlap case.\n" ));
+                               DEBUG(10,(" no overlap case.\n" ));
 
                                l_curr = l_curr->next;
 
@@ -858,8 +800,8 @@ OR....
                                                (l_curr->start + l_curr->size <= lock->start + lock->size) ) {
 
                                /*
-                                * This unlock is completely overlapped by this existing lock range
-                                * and thus should have no effect (not be unlocked). Delete it from the list.
+                                * This range is completely overlapped by this existing lock range
+                                * and thus should have no effect. Delete it from the list.
                                 */
 /*********************************************
                 +---------+
@@ -872,11 +814,12 @@ OR....
                                /* Save the next pointer */
                                struct lock_list *ul_next = l_curr->next;
 
-                               DEBUG(10,("delete case.\n" ));
+                               DEBUG(10,(" delete case.\n" ));
 
                                DLIST_REMOVE(lhead, l_curr);
-                               if(lhead == NULL)
+                               if(lhead == NULL) {
                                        break; /* No more list... */
+                               }
 
                                l_curr = ul_next;
                                
@@ -885,7 +828,7 @@ OR....
                                                (l_curr->start + l_curr->size > lock->start + lock->size) ) {
 
                                /*
-                                * This unlock overlaps the existing lock range at the high end.
+                                * This range overlaps the existing lock range at the high end.
                                 * Truncate by moving start to existing range end and reducing size.
                                 */
 /*********************************************
@@ -904,7 +847,7 @@ BECOMES....
                                l_curr->size = (l_curr->start + l_curr->size) - (lock->start + lock->size);
                                l_curr->start = lock->start + lock->size;
 
-                               DEBUG(10,("truncate high case: start=%.0f,size=%.0f\n",
+                               DEBUG(10,(" truncate high case: start=%.0f,size=%.0f\n",
                                                                (double)l_curr->start, (double)l_curr->size ));
 
                                l_curr = l_curr->next;
@@ -914,7 +857,7 @@ BECOMES....
                                                (l_curr->start + l_curr->size <= lock->start + lock->size) ) {
 
                                /*
-                                * This unlock overlaps the existing lock range at the low end.
+                                * This range overlaps the existing lock range at the low end.
                                 * Truncate by reducing size.
                                 */
 /*********************************************
@@ -932,7 +875,7 @@ BECOMES....
 
                                l_curr->size = lock->start - l_curr->start;
 
-                               DEBUG(10,("truncate low case: start=%.0f,size=%.0f\n",
+                               DEBUG(10,(" truncate low case: start=%.0f,size=%.0f\n",
                                                                (double)l_curr->start, (double)l_curr->size ));
 
                                l_curr = l_curr->next;
@@ -940,10 +883,10 @@ BECOMES....
                        } else if ( (l_curr->start < lock->start) &&
                                                (l_curr->start + l_curr->size > lock->start + lock->size) ) {
                                /*
-                                * Worst case scenario. Unlock request completely overlaps an existing
+                                * Worst case scenario. Range completely overlaps an existing
                                 * lock range. Split the request into two, push the new (upper) request
-                                * into the dlink list, and continue with the entry after ul_new (as we
-                                * know that ul_new will not overlap with this lock).
+                                * into the dlink list, and continue with the entry after l_new (as we
+                                * know that l_new will not overlap with this lock).
                                 */
 /*********************************************
         +---------------------------+
@@ -971,7 +914,7 @@ BECOMES.....
                                /* Truncate the l_curr. */
                                l_curr->size = lock->start - l_curr->start;
 
-                               DEBUG(10,("split case: curr: start=%.0f,size=%.0f \
+                               DEBUG(10,(" split case: curr: start=%.0f,size=%.0f \
 new: start=%.0f,size=%.0f\n", (double)l_curr->start, (double)l_curr->size,
                                                                (double)l_new->start, (double)l_new->size ));
 
@@ -1003,34 +946,33 @@ lock: start = %.0f, size = %.0f\n", (double)l_curr->start, (double)l_curr->size,
                } /* end for ( l_curr = lhead; l_curr;) */
        } /* end for (i=0; i<num_locks && ul_head; i++) */
 
-       SAFE_FREE(dbuf.dptr);
-       
        return lhead;
 }
 
 /****************************************************************************
  POSIX function to acquire a lock. Returns True if the
  lock could be granted, False if not.
- TODO -- Fix POSIX lock flavour semantics.
 ****************************************************************************/
 
-BOOL set_posix_lock(files_struct *fsp,
+BOOL set_posix_lock_windows_flavour(files_struct *fsp,
                        SMB_BIG_UINT u_offset,
                        SMB_BIG_UINT u_count,
                        enum brl_type lock_type,
-                       enum brl_flavour lock_flav)
+                       const struct lock_context *lock_ctx,
+                       const struct lock_struct *plocks,
+                       int num_locks,
+                       int *errno_ret)
 {
        SMB_OFF_T offset;
        SMB_OFF_T count;
+       int posix_lock_type = map_posix_lock_type(fsp,lock_type);
        BOOL ret = True;
-       size_t entry_num = 0;
        size_t lock_count;
        TALLOC_CTX *l_ctx = NULL;
        struct lock_list *llist = NULL;
        struct lock_list *ll = NULL;
-       int posix_lock_type = map_posix_lock_type(fsp,lock_type);
 
-       DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n",
+       DEBUG(5,("set_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f, type = %s\n",
                        fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
 
        /*
@@ -1038,8 +980,9 @@ BOOL set_posix_lock(files_struct *fsp,
         * pretend it was successful.
         */
 
-       if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
+       if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
                return True;
+       }
 
        /*
         * Windows is very strange. It allows read locks to be overlayed
@@ -1056,19 +999,16 @@ BOOL set_posix_lock(files_struct *fsp,
         *                                            READ LOCK: start =0, len = 10 - OK
         *
         * Under POSIX, the same sequence in steps 1 and 2 would not be reference counted, but
-        * would leave a single read lock over the 0-14 region. In order to
-        * re-create Windows semantics mapped to POSIX locks, we create multiple TDB
-        * entries, one for each overlayed lock request. We are guarenteed by the brlock
-        * semantics that if a write lock is added, then it will be first in the array.
+        * would leave a single read lock over the 0-14 region.
         */
        
        if ((l_ctx = talloc_init("set_posix_lock")) == NULL) {
-               DEBUG(0,("set_posix_lock: unable to init talloc context.\n"));
+               DEBUG(0,("set_posix_lock_windows_flavour: unable to init talloc context.\n"));
                return True; /* Not a fatal error. */
        }
 
        if ((ll = TALLOC_P(l_ctx, struct lock_list)) == NULL) {
-               DEBUG(0,("set_posix_lock: unable to talloc unlock list.\n"));
+               DEBUG(0,("set_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
                talloc_destroy(l_ctx);
                return True; /* Not a fatal error. */
        }
@@ -1092,19 +1032,12 @@ BOOL set_posix_lock(files_struct *fsp,
         * POSIX locks.
         */
 
-       llist = posix_lock_list(l_ctx, llist, fsp);
-
-       /*
-        * Now we have the list of ranges to lock it is safe to add the
-        * entry into the POSIX lock tdb. We take note of the entry we
-        * added here in case we have to remove it on POSIX lock fail.
-        */
-
-       if (!add_posix_lock_entry(fsp,offset,count,posix_lock_type,&entry_num)) {
-               DEBUG(0,("set_posix_lock: Unable to create posix lock entry !\n"));
-               talloc_destroy(l_ctx);
-               return False;
-       }
+       llist = posix_lock_list(l_ctx,
+                               llist,
+                               lock_ctx, /* Lock context llist belongs to. */
+                               fsp,
+                               plocks,
+                               num_locks);
 
        /*
         * Add the POSIX locks on the list of ranges returned.
@@ -1116,11 +1049,12 @@ BOOL set_posix_lock(files_struct *fsp,
                offset = ll->start;
                count = ll->size;
 
-               DEBUG(5,("set_posix_lock: Real lock: Type = %s: offset = %.0f, count = %.0f\n",
+               DEBUG(5,("set_posix_lock_windows_flavour: Real lock: Type = %s: offset = %.0f, count = %.0f\n",
                        posix_lock_type_name(posix_lock_type), (double)offset, (double)count ));
 
                if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) {
-                       DEBUG(5,("set_posix_lock: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n",
+                       *errno_ret = errno;
+                       DEBUG(5,("set_posix_lock_windows_flavour: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n",
                                posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) ));
                        ret = False;
                        break;
@@ -1137,17 +1071,14 @@ BOOL set_posix_lock(files_struct *fsp,
                        offset = ll->start;
                        count = ll->size;
 
-                       DEBUG(5,("set_posix_lock: Backing out locks: Type = %s: offset = %.0f, count = %.0f\n",
+                       DEBUG(5,("set_posix_lock_windows_flavour: Backing out locks: Type = %s: offset = %.0f, count = %.0f\n",
                                posix_lock_type_name(posix_lock_type), (double)offset, (double)count ));
 
                        posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK);
                }
-
-               /*
-                * Remove the tdb entry for this lock.
-                */
-
-               delete_posix_lock_entry_by_index(fsp,entry_num);
+       } else {
+               /* Remember the number of Windows locks we have on this dev/ino pair. */
+               increment_windows_lock_ref_count(fsp);
        }
 
        talloc_destroy(l_ctx);
@@ -1159,7 +1090,13 @@ BOOL set_posix_lock(files_struct *fsp,
  lock could be released, False if not.
 ****************************************************************************/
 
-BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count)
+BOOL release_posix_lock_windows_flavour(files_struct *fsp,
+                               SMB_BIG_UINT u_offset,
+                               SMB_BIG_UINT u_count,
+                               enum brl_type deleted_lock_type,
+                               const struct lock_context *lock_ctx,
+                               const struct lock_struct *plocks,
+                               int num_locks)
 {
        SMB_OFF_T offset;
        SMB_OFF_T count;
@@ -1167,10 +1104,8 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
        TALLOC_CTX *ul_ctx = NULL;
        struct lock_list *ulist = NULL;
        struct lock_list *ul = NULL;
-       struct posix_lock deleted_lock;
-       int num_overlapped_entries;
 
-       DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n",
+       DEBUG(5,("release_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f\n",
                fsp->fsp_name, (double)u_offset, (double)u_count ));
 
        /*
@@ -1178,43 +1113,20 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
         * pretend it was successful.
         */
 
-       if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
+       if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
                return True;
-
-       /*
-        * We treat this as one unlock request for POSIX accounting purposes even
-        * if it may later be split into multiple smaller POSIX unlock ranges.
-        * num_overlapped_entries is the number of existing locks that have any
-        * overlap with this unlock request.
-        */ 
-
-       num_overlapped_entries = delete_posix_lock_entry(fsp, offset, count, &deleted_lock);
-
-       if (num_overlapped_entries == -1) {
-               smb_panic("release_posix_lock: unable find entry to delete !\n");
        }
 
-       /*
-        * If num_overlapped_entries is > 0, and the lock_type we just deleted from the tdb was
-        * a POSIX write lock, then before doing the unlock we need to downgrade
-        * the POSIX lock to a read lock. This allows any overlapping read locks
-        * to be atomically maintained.
-        */
-
-       if (num_overlapped_entries > 0 && deleted_lock.lock_type == F_WRLCK) {
-               if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK)) {
-                       DEBUG(0,("release_posix_lock: downgrade of lock failed with error %s !\n", strerror(errno) ));
-                       return False;
-               }
-       }
+       /* Remember the number of Windows locks we have on this dev/ino pair. */
+       decrement_windows_lock_ref_count(fsp);
 
        if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) {
-               DEBUG(0,("release_posix_lock: unable to init talloc context.\n"));
+               DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n"));
                return True; /* Not a fatal error. */
        }
 
        if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) {
-               DEBUG(0,("release_posix_lock: unable to talloc unlock list.\n"));
+               DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
                talloc_destroy(ul_ctx);
                return True; /* Not a fatal error. */
        }
@@ -1239,7 +1151,33 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
         * unlocks are performed.
         */
 
-       ulist = posix_lock_list(ul_ctx, ulist, fsp);
+       ulist = posix_lock_list(ul_ctx,
+                               ulist,
+                               lock_ctx, /* Lock context ulist belongs to. */
+                               fsp,
+                               plocks,
+                               num_locks);
+
+       /*
+        * If there were any overlapped entries (list is > 1 or size or start have changed),
+        * and the lock_type we just deleted from
+        * the upper layer tdb was a write lock, then before doing the unlock we need to downgrade
+        * the POSIX lock to a read lock. This allows any overlapping read locks
+        * to be atomically maintained.
+        */
+
+       if (deleted_lock_type == WRITE_LOCK &&
+                       (!ulist || ulist->next != NULL || ulist->start != offset || ulist->size != count)) {
+
+               DEBUG(5,("release_posix_lock_windows_flavour: downgrading lock to READ: offset = %.0f, count = %.0f\n",
+                       (double)offset, (double)count ));
+
+               if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK)) {
+                       DEBUG(0,("release_posix_lock_windows_flavour: downgrade of lock failed with error %s !\n", strerror(errno) ));
+                       talloc_destroy(ul_ctx);
+                       return False;
+               }
+       }
 
        /*
         * Release the POSIX locks on the list of ranges returned.
@@ -1249,129 +1187,148 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
                offset = ulist->start;
                count = ulist->size;
 
-               DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n",
+               DEBUG(5,("release_posix_lock_windows_flavour: Real unlock: offset = %.0f, count = %.0f\n",
                        (double)offset, (double)count ));
 
-               if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK))
+               if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) {
                        ret = False;
+               }
        }
 
        talloc_destroy(ul_ctx);
-
        return ret;
 }
 
 /****************************************************************************
- Remove all lock entries for a specific dev/inode pair from the tdb.
+ Next - the functions that deal with mapping CIFS POSIX locks onto
+ the underlying system POSIX locks.
 ****************************************************************************/
 
-static void delete_posix_lock_entries(files_struct *fsp)
-{
-       TDB_DATA kbuf = locking_key_fsp(fsp);
-
-       if (tdb_delete(posix_lock_tdb, kbuf) == -1)
-               DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));
-}
-
 /****************************************************************************
- Debug function.
+ POSIX function to acquire a lock. Returns True if the
+ lock could be granted, False if not.
+ As POSIX locks don't stack or conflict (they just overwrite)
+ we can map the requested lock directly onto a system one. We
+ know it doesn't conflict with locks on other contexts as the
+ upper layer would have refused it.
 ****************************************************************************/
 
-static void dump_entry(struct posix_lock *pl)
+BOOL set_posix_lock_posix_flavour(files_struct *fsp,
+                       SMB_BIG_UINT u_offset,
+                       SMB_BIG_UINT u_count,
+                       enum brl_type lock_type,
+                       int *errno_ret)
 {
-       DEBUG(10,("entry: start=%.0f, size=%.0f, type=%d, fd=%i\n",
-               (double)pl->start, (double)pl->size, (int)pl->lock_type, pl->fd ));
+       SMB_OFF_T offset;
+       SMB_OFF_T count;
+       int posix_lock_type = map_posix_lock_type(fsp,lock_type);
+
+       DEBUG(5,("set_posix_lock_posix_flavour: File %s, offset = %.0f, count = %.0f, type = %s\n",
+                       fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
+
+       /*
+        * If the requested lock won't fit in the POSIX range, we will
+        * pretend it was successful.
+        */
+
+       if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
+               return True;
+       }
+
+       if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) {
+               *errno_ret = errno;
+               DEBUG(5,("set_posix_lock_posix_flavour: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n",
+                       posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) ));
+               return False;
+       }
+       return True;
 }
 
 /****************************************************************************
- Remove any locks on this fd. Called from file_close().
+ POSIX function to release a lock. Returns True if the
+ lock could be released, False if not.
+ We are given a complete lock state from the upper layer which is what the lock
+ state should be after the unlock has already been done, so what
+ we do is punch out holes in the unlock range where locks owned by this process
+ have a different lock context.
 ****************************************************************************/
 
-void posix_locking_close_file(files_struct *fsp)
+BOOL release_posix_lock_posix_flavour(files_struct *fsp,
+                               SMB_BIG_UINT u_offset,
+                               SMB_BIG_UINT u_count,
+                               const struct lock_context *lock_ctx,
+                               const struct lock_struct *plocks,
+                               int num_locks)
 {
-       struct posix_lock *entries = NULL;
-       size_t count, i;
+       BOOL ret = True;
+       SMB_OFF_T offset;
+       SMB_OFF_T count;
+       TALLOC_CTX *ul_ctx = NULL;
+       struct lock_list *ulist = NULL;
+       struct lock_list *ul = NULL;
+
+       DEBUG(5,("release_posix_lock_posix_flavour: File %s, offset = %.0f, count = %.0f\n",
+               fsp->fsp_name, (double)u_offset, (double)u_count ));
 
        /*
-        * Optimization for the common case where we are the only
-        * opener of a file. If all fd entries are our own, we don't
-        * need to explicitly release all the locks via the POSIX functions,
-        * we can just remove all the entries in the tdb and allow the
-        * close to remove the real locks.
+        * If the requested lock won't fit in the POSIX range, we will
+        * pretend it was successful.
         */
 
-       count = get_posix_lock_entries(fsp, &entries);
-
-       if (count == 0) {
-               DEBUG(10,("posix_locking_close_file: file %s has no outstanding locks.\n", fsp->fsp_name ));
-               return;
+       if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
+               return True;
        }
 
-       for (i = 0; i < count; i++) {
-               if (entries[i].fd != fsp->fh->fd )
-                       break;
-
-               dump_entry(&entries[i]);
+       if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) {
+               DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n"));
+               return False;
        }
 
-       if (i == count) {
-               /* All locks are ours. */
-               DEBUG(10,("posix_locking_close_file: file %s has %u outstanding locks, but all on one fd.\n", 
-                       fsp->fsp_name, (unsigned int)count ));
-               SAFE_FREE(entries);
-               delete_posix_lock_entries(fsp);
-               return;
+       if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) {
+               DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
+               talloc_destroy(ul_ctx);
+               return False;
        }
 
        /*
-        * Difficult case. We need to delete all our locks, whilst leaving
-        * all other POSIX locks in place.
+        * Create the initial list entry containing the
+        * lock we want to remove.
         */
 
-       for (i = 0; i < count; i++) {
-               struct posix_lock *pl = &entries[i];
-               if (pl->fd == fsp->fh->fd)
-                       release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size );
-       }
-       SAFE_FREE(entries);
-}
+       ZERO_STRUCTP(ul);
+       ul->start = offset;
+       ul->size = count;
 
-/*******************************************************************
- Create the in-memory POSIX lock databases.
-********************************************************************/
+       DLIST_ADD(ulist, ul);
 
-BOOL posix_locking_init(int read_only)
-{
-       if (posix_lock_tdb && posix_pending_close_tdb)
-               return True;
-       
-       if (!posix_lock_tdb)
-               posix_lock_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL,
-                                         read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644);
-       if (!posix_lock_tdb) {
-               DEBUG(0,("Failed to open POSIX byte range locking database.\n"));
-               return False;
-       }
-       if (!posix_pending_close_tdb)
-               posix_pending_close_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL,
-                                                  read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644);
-       if (!posix_pending_close_tdb) {
-               DEBUG(0,("Failed to open POSIX pending close database.\n"));
-               return False;
-       }
+       /*
+        * Walk the given array creating a linked list
+        * of unlock requests.
+        */
 
-       return True;
-}
+       ulist = posix_lock_list(ul_ctx,
+                               ulist,
+                               lock_ctx, /* Lock context ulist belongs to. */
+                               fsp,
+                               plocks,
+                               num_locks);
 
-/*******************************************************************
Delete the in-memory POSIX lock databases.
-********************************************************************/
+       /*
       * Release the POSIX locks on the list of ranges returned.
+        */
 
-BOOL posix_locking_end(void)
-{
-    if (posix_lock_tdb && tdb_close(posix_lock_tdb) != 0)
-               return False;
-    if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0)
-               return False;
+       for(; ulist; ulist = ulist->next) {
+               offset = ulist->start;
+               count = ulist->size;
+
+               DEBUG(5,("release_posix_lock_posix_flavour: Real unlock: offset = %.0f, count = %.0f\n",
+                       (double)offset, (double)count ));
+
+               if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) {
+                       ret = False;
+               }
+       }
+
+       talloc_destroy(ul_ctx);
        return True;
 }
index 6f50d879ba4bd1d6b3f5d76e87b9a3545549c6fe..a9003c7a826b868b34c9dbc624977e876a18e9c3 100644 (file)
@@ -594,7 +594,7 @@ static struct charset_functions macosxfs_encoding_functions = {
        "MACOSXFS", macosxfs_encoding_pull, macosxfs_encoding_push
 };
 
-NTSTATUS init_module(void)
+NTSTATUS charset_macosxfs_init(void)
 {
        return smb_register_charset(&macosxfs_encoding_functions);
 }
index 53272ca06fe374fa7fa6b2901a6fa4c1afd6f05c..11498fccf9e156d76b6d2e73c7d69f55915d930a 100644 (file)
@@ -1011,7 +1011,6 @@ BOOL afsacl_set_nt_acl(vfs_handle_struct *handle,
 }
 
 static int afsacl_connect(vfs_handle_struct *handle, 
-                         connection_struct *conn, 
                          const char *service, 
                          const char *user)
 {
@@ -1022,7 +1021,7 @@ static int afsacl_connect(vfs_handle_struct *handle,
        if (spc != NULL)
                space_replacement = spc[0];
        
-       return SMB_VFS_NEXT_CONNECT(handle, conn, service, user);
+       return SMB_VFS_NEXT_CONNECT(handle, service, user);
 }
 
 /* VFS operations structure */
index 9f5179a47ce9caa9535c6ea0e0b40112877b9f2f..b240cafd29fa94d512d92ced6789789269478d83 100644 (file)
 
 /* Function prototypes */
 
-static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user);
-static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn);
-static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr);
-static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode);
-static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path);
-static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode);
+static int audit_connect(vfs_handle_struct *handle, const char *svc, const char *user);
+static void audit_disconnect(vfs_handle_struct *handle);
+static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr);
+static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode);
+static int audit_rmdir(vfs_handle_struct *handle, const char *path);
+static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode);
 static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd);
-static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname);
-static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path);
-static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode);
-static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode);
+static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname);
+static int audit_unlink(vfs_handle_struct *handle, const char *path);
+static int audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode);
+static int audit_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode);
 static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode);
 static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode);
 
@@ -120,7 +120,7 @@ static int audit_syslog_priority(vfs_handle_struct *handle)
 /* Implementation of vfs_ops.  Pass everything on to the default
    operation but log event first. */
 
-static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user)
+static int audit_connect(vfs_handle_struct *handle, const char *svc, const char *user)
 {
        int result;
        
@@ -129,24 +129,24 @@ static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, con
        syslog(audit_syslog_priority(handle), "connect to service %s by user %s\n", 
               svc, user);
 
-       result = SMB_VFS_NEXT_CONNECT(handle, conn, svc, user);
+       result = SMB_VFS_NEXT_CONNECT(handle, svc, user);
 
        return result;
 }
 
-static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn)
+static void audit_disconnect(vfs_handle_struct *handle)
 {
        syslog(audit_syslog_priority(handle), "disconnected\n");
-       SMB_VFS_NEXT_DISCONNECT(handle, conn);
+       SMB_VFS_NEXT_DISCONNECT(handle);
 
        return;
 }
 
-static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr)
+static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
 {
        SMB_STRUCT_DIR *result;
        
-       result = SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr);
+       result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
 
        syslog(audit_syslog_priority(handle), "opendir %s %s%s\n",
               fname,
@@ -156,11 +156,11 @@ static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struc
        return result;
 }
 
-static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
 {
        int result;
        
-       result = SMB_VFS_NEXT_MKDIR(handle, conn, path, mode);
+       result = SMB_VFS_NEXT_MKDIR(handle, path, mode);
        
        syslog(audit_syslog_priority(handle), "mkdir %s %s%s\n", 
               path,
@@ -170,11 +170,11 @@ static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const
        return result;
 }
 
-static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int audit_rmdir(vfs_handle_struct *handle, const char *path)
 {
        int result;
 
-       result = SMB_VFS_NEXT_RMDIR(handle, conn, path);
+       result = SMB_VFS_NEXT_RMDIR(handle, path);
 
        syslog(audit_syslog_priority(handle), "rmdir %s %s%s\n", 
               path, 
@@ -184,11 +184,11 @@ static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const
        return result;
 }
 
-static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
+static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode)
 {
        int result;
 
-       result = SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
+       result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
 
        syslog(audit_syslog_priority(handle), "open %s (fd %d) %s%s%s\n", 
               fname, result,
@@ -213,11 +213,11 @@ static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
        return result;
 }
 
-static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname)
+static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname)
 {
        int result;
 
-       result = SMB_VFS_NEXT_RENAME(handle, conn, oldname, newname);
+       result = SMB_VFS_NEXT_RENAME(handle, oldname, newname);
 
        syslog(audit_syslog_priority(handle), "rename %s -> %s %s%s\n",
               oldname, newname,
@@ -227,11 +227,11 @@ static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, cons
        return result;    
 }
 
-static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int audit_unlink(vfs_handle_struct *handle, const char *path)
 {
        int result;
 
-       result = SMB_VFS_NEXT_UNLINK(handle, conn, path);
+       result = SMB_VFS_NEXT_UNLINK(handle, path);
 
        syslog(audit_syslog_priority(handle), "unlink %s %s%s\n",
               path,
@@ -241,11 +241,11 @@ static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, cons
        return result;
 }
 
-static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
 {
        int result;
 
-       result = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode);
+       result = SMB_VFS_NEXT_CHMOD(handle, path, mode);
 
        syslog(audit_syslog_priority(handle), "chmod %s mode 0x%x %s%s\n",
               path, mode,
@@ -255,11 +255,11 @@ static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const
        return result;
 }
 
-static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int audit_chmod_acl(vfs_handle_struct *handle, const char *path, mode_t mode)
 {
        int result;
 
-       result = SMB_VFS_NEXT_CHMOD_ACL(handle, conn, path, mode);
+       result = SMB_VFS_NEXT_CHMOD_ACL(handle, path, mode);
 
        syslog(audit_syslog_priority(handle), "chmod_acl %s mode 0x%x %s%s\n",
               path, mode,
diff --git a/source/modules/vfs_cacheprime.c b/source/modules/vfs_cacheprime.c
new file mode 100644 (file)
index 0000000..196441c
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) James Peach 2005-2006
+ *
+ * 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"
+
+/* Cache priming module.
+ *
+ * The purpose of this module is to do RAID stripe width reads to prime the
+ * buffer cache to do zero-copy I/O for subsequent sendfile calls. The idea is
+ * to do a single large read at the start of the file to make sure that most or
+ * all of the file is pulled into the buffer cache. Subsequent I/Os have
+ * reduced latency.
+ *
+ * Tunables.
+ *
+ *      cacheprime:rsize    Amount of readahead in bytes. This should be a
+ *                          multiple of the RAID stripe width.
+ *      cacheprime:debug    Debug level at which to emit messages.
+ */
+
+#define READAHEAD_MIN       (128 * 1024)        /* min is 128 KiB */
+#define READAHEAD_MAX       (100 * 1024 * 1024) /* max is 100 MiB */
+
+#define MODULE "cacheprime"
+
+static int module_debug;
+static ssize_t g_readsz = 0;
+static void * g_readbuf = NULL;
+
+/* Prime the kernel buffer cache with data from the specified file. We use
+ * per-fsp data to make sure we only ever do this once. If pread is being
+ * emulated by seek/read/seek, when this will suck quite a lot.
+ */
+static BOOL prime_cache(
+            struct vfs_handle_struct *  handle,
+                       files_struct *                  fsp,
+                       int                                     fd,
+                       SMB_OFF_T                           offset,
+                       size_t                              count)
+{
+        SMB_OFF_T * last;
+        ssize_t nread;
+
+        last = VFS_ADD_FSP_EXTENSION(handle, fsp, SMB_OFF_T);
+        if (!last) {
+                return False;
+        }
+
+        if (*last == -1) {
+            /* Readahead disabled. */
+            return False;
+        }
+
+        if ((*last + g_readsz) > (offset + count)) {
+            /* Skip readahead ... we've already been here. */
+            return False;
+        }
+
+        DEBUG(module_debug,
+            ("%s: doing readahead of %lld bytes at %lld for %s\n",
+            MODULE, (long long)g_readsz, (long long)*last,
+            fsp->fsp_name));
+
+        nread = sys_pread(fd, g_readbuf, g_readsz, *last);
+        if (nread < 0) {
+            *last = -1;
+            return False;
+        }
+
+        *last += nread;
+        return True;
+}
+
+static int cprime_connect(
+                struct vfs_handle_struct *  handle,
+                const char *                service,
+                const char *                user)
+{
+        module_debug = lp_parm_int(SNUM(handle->conn), MODULE, "debug", 100);
+        if (g_readbuf) {
+                /* Only allocate g_readbuf once. If the config changes and
+                 * another client multiplexes onto this smbd, we don't want
+                 * to risk memory corruption.
+                 */
+                return SMB_VFS_NEXT_CONNECT(handle, service, user);
+        }
+
+        g_readsz = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
+                                        MODULE, "rsize", NULL));
+
+        if (g_readsz < READAHEAD_MIN) {
+                DEBUG(module_debug, ("%s: %ld bytes of readahead "
+                            "requested, using minimum of %u\n",
+                            MODULE, (long)g_readsz, READAHEAD_MIN));
+                g_readsz = READAHEAD_MIN;
+        } else if (g_readsz > READAHEAD_MAX) {
+                DEBUG(module_debug, ("%s: %ld bytes of readahead "
+                            "requested, using maximum of %u\n",
+                            MODULE, (long)g_readsz, READAHEAD_MAX));
+                g_readsz = READAHEAD_MAX;
+        }
+
+        if ((g_readbuf = SMB_MALLOC(g_readsz)) == NULL) {
+                /* Turn off readahead if we can't get a buffer. */
+                g_readsz = 0;
+        }
+
+        return SMB_VFS_NEXT_CONNECT(handle, service, user);
+}
+
+static ssize_t cprime_sendfile(
+                struct vfs_handle_struct *  handle,
+                int                         tofd,
+                files_struct *              fsp,
+                int                         fromfd,
+                const DATA_BLOB *           header,
+                SMB_OFF_T                   offset,
+                size_t                      count)
+{
+        if (g_readbuf && offset == 0) {
+                prime_cache(handle, fsp, fromfd, offset, count);
+        }
+
+        return SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd,
+                                     header, offset, count);
+}
+
+static ssize_t cprime_read(
+                vfs_handle_struct * handle,
+                files_struct *      fsp,
+                int                 fd,
+                void *              data,
+                size_t              count)
+{
+        SMB_OFF_T offset;
+
+        offset = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
+        if (offset >= 0 && g_readbuf)  {
+                prime_cache(handle, fsp, fd, offset, count);
+                SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET);
+        }
+
+        return SMB_VFS_NEXT_READ(handle, fsp, fd, data, count);
+}
+
+static ssize_t cprime_pread(
+                vfs_handle_struct * handle,
+                files_struct *      fsp,
+                int                 fd,
+                void *              data,
+                       size_t              count,
+                SMB_OFF_T           offset)
+{
+        if (g_readbuf) {
+                prime_cache(handle, fsp, fd, offset, count);
+        }
+
+        return SMB_VFS_NEXT_PREAD(handle, fsp, fd, data, count, offset);
+}
+
+static vfs_op_tuple cprime_ops [] =
+{
+        {SMB_VFS_OP(cprime_sendfile),
+                SMB_VFS_OP_SENDFILE, SMB_VFS_LAYER_TRANSPARENT},
+        {SMB_VFS_OP(cprime_pread),
+                SMB_VFS_OP_PREAD, SMB_VFS_LAYER_TRANSPARENT},
+        {SMB_VFS_OP(cprime_read),
+                SMB_VFS_OP_READ, SMB_VFS_LAYER_TRANSPARENT},
+        {SMB_VFS_OP(cprime_connect),
+                SMB_VFS_OP_CONNECT,  SMB_VFS_LAYER_TRANSPARENT},
+
+        {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
+};
+
+/* -------------------------------------------------------------------------
+ * Samba module initialisation entry point.
+ * -------------------------------------------------------------------------
+ */
+
+NTSTATUS vfs_cacheprime_init(void)
+{
+    return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE, cprime_ops);
+}
+
+/* vim: set sw=4 ts=4 tw=79 et: */
index b1bfcd75f2fafc6caebb1ad31627c9ac6763418f..54f74dde678ddb48a8ef36df6990790ced0f7aed 100644 (file)
 static char *capencode(char *to, const char *from);
 static char *capdecode(char *to, const char *from);
 
-static SMB_BIG_UINT cap_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path,
+static SMB_BIG_UINT cap_disk_free(vfs_handle_struct *handle, const char *path,
        BOOL small_query, SMB_BIG_UINT *bsize,
        SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
 {
         pstring cappath;
         capencode(cappath, path);
-       return SMB_VFS_NEXT_DISK_FREE(handle, conn, cappath, small_query, bsize, 
+       return SMB_VFS_NEXT_DISK_FREE(handle, cappath, small_query, bsize,
                                         dfree, dsize);
 }
 
-static SMB_STRUCT_DIR *cap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr)
+static SMB_STRUCT_DIR *cap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
 {
         pstring capname;
         capencode(capname, fname);
-       return SMB_VFS_NEXT_OPENDIR(handle, conn, capname, mask, attr);
+       return SMB_VFS_NEXT_OPENDIR(handle, capname, mask, attr);
 }
 
-static SMB_STRUCT_DIRENT *cap_readdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp)
+static SMB_STRUCT_DIRENT *cap_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp)
 {
         SMB_STRUCT_DIRENT *result;
        DEBUG(3,("cap: cap_readdir\n"));
-       result = SMB_VFS_NEXT_READDIR(handle, conn, dirp);
+       result = SMB_VFS_NEXT_READDIR(handle, dirp);
        if (result) {
          DEBUG(3,("cap: cap_readdir: %s\n", result->d_name));
          capdecode(result->d_name, result->d_name);
@@ -57,124 +57,124 @@ static SMB_STRUCT_DIRENT *cap_readdir(vfs_handle_struct *handle, connection_stru
         return result;
 }
 
-static int cap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int cap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
 {
        pstring cappath;
        capencode(cappath, path);
-       return SMB_VFS_NEXT_MKDIR(handle, conn, cappath, mode);
+       return SMB_VFS_NEXT_MKDIR(handle, cappath, mode);
 }
 
-static int cap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int cap_rmdir(vfs_handle_struct *handle, const char *path)
 {
         pstring cappath;
         capencode(cappath, path);
-       return SMB_VFS_NEXT_RMDIR(handle, conn, cappath);
+       return SMB_VFS_NEXT_RMDIR(handle, cappath);
 }
 
-static int cap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
+static int cap_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode)
 {
         pstring capname;
        DEBUG(3,("cap: cap_open for %s\n", fname));
        capencode(capname, fname);
-       return SMB_VFS_NEXT_OPEN(handle, conn, capname, flags, mode);
+       return SMB_VFS_NEXT_OPEN(handle, capname, fsp, flags, mode);
 }
 
-static int cap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname)
+static int cap_rename(vfs_handle_struct *handle, const char *oldname, const char *newname)
 {
        pstring capold, capnew;
        capencode(capold, oldname);
        capencode(capnew, newname);
 
-       return SMB_VFS_NEXT_RENAME(handle, conn, capold, capnew);
+       return SMB_VFS_NEXT_RENAME(handle, capold, capnew);
 }
 
-static int cap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
+static int cap_stat(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf)
 {
         pstring capname;
        capencode(capname, fname);
-       return SMB_VFS_NEXT_STAT(handle, conn, capname, sbuf);
+       return SMB_VFS_NEXT_STAT(handle, capname, sbuf);
 }
 
-static int cap_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
+static int cap_lstat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf)
 {
        pstring cappath;
        capencode(cappath, path);
-       return SMB_VFS_NEXT_LSTAT(handle, conn, cappath, sbuf);
+       return SMB_VFS_NEXT_LSTAT(handle, cappath, sbuf);
 }
 
-static int cap_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int cap_unlink(vfs_handle_struct *handle, const char *path)
 {
        pstring cappath;
        capencode(cappath, path);
-       return SMB_VFS_NEXT_UNLINK(handle, conn, cappath);
+       return SMB_VFS_NEXT_UNLINK(handle, cappath);
 }
 
-static int cap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int cap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
 {
         pstring cappath;
        capencode(cappath, path);
-       return SMB_VFS_NEXT_CHMOD(handle, conn, cappath, mode);
+       return SMB_VFS_NEXT_CHMOD(handle, cappath, mode);
 }
 
-static int cap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid)
+static int cap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
 {
         pstring cappath;
        capencode(cappath, path);
-       return SMB_VFS_NEXT_CHOWN(handle, conn, cappath, uid, gid);
+       return SMB_VFS_NEXT_CHOWN(handle, cappath, uid, gid);
 }
 
-static int cap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int cap_chdir(vfs_handle_struct *handle, const char *path)
 {
         pstring cappath;
        DEBUG(3,("cap: cap_chdir for %s\n", path));
        capencode(cappath, path);
-       return SMB_VFS_NEXT_CHDIR(handle, conn, cappath);
+       return SMB_VFS_NEXT_CHDIR(handle, cappath);
 }
 
-static int cap_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times)
+static int cap_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times)
 {
         pstring cappath;
        capencode(cappath, path);
-       return SMB_VFS_NEXT_UTIME(handle, conn, cappath, times);
+       return SMB_VFS_NEXT_UTIME(handle, cappath, times);
 }
 
 
-static BOOL cap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
+static BOOL cap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
 {
         pstring capoldpath, capnewpath;
         capencode(capoldpath, oldpath);
         capencode(capnewpath, newpath);
-       return SMB_VFS_NEXT_SYMLINK(handle, conn, capoldpath, capnewpath);
+       return SMB_VFS_NEXT_SYMLINK(handle, capoldpath, capnewpath);
 }
 
-static BOOL cap_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz)
+static BOOL cap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
 {
         pstring cappath;
        capencode(cappath, path);
-       return SMB_VFS_NEXT_READLINK(handle, conn, cappath, buf, bufsiz);
+       return SMB_VFS_NEXT_READLINK(handle, cappath, buf, bufsiz);
 }
 
-static int cap_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
+static int cap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
 {
         pstring capoldpath, capnewpath;
         capencode(capoldpath, oldpath);
         capencode(capnewpath, newpath);
-       return SMB_VFS_NEXT_LINK(handle, conn, capoldpath, capnewpath);
+       return SMB_VFS_NEXT_LINK(handle, capoldpath, capnewpath);
 }
 
-static int cap_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev)
+static int cap_mknod(vfs_handle_struct *handle, const char *path, mode_t mode, SMB_DEV_T dev)
 {
         pstring cappath;
        capencode(cappath, path);
-       return SMB_VFS_NEXT_MKNOD(handle, conn, cappath, mode, dev);
+       return SMB_VFS_NEXT_MKNOD(handle, cappath, mode, dev);
 }
 
-static char *cap_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path)
+static char *cap_realpath(vfs_handle_struct *handle, const char *path, char *resolved_path)
 {
         /* monyo need capencode'ed and capdecode'ed? */
         pstring cappath;
        capencode(cappath, path);
-       return SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path);
+       return SMB_VFS_NEXT_REALPATH(handle, path, resolved_path);
 }
 
 static BOOL cap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd)
@@ -184,7 +184,7 @@ static BOOL cap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const c
        return SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, capname, security_info_sent, psd);
 }
 
-static int cap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode)
+static int cap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
 {
         pstring capname;
        capencode(capname, name);
@@ -194,45 +194,45 @@ static int cap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, con
                errno = ENOSYS;
                return -1;
        }
-       return SMB_VFS_NEXT_CHMOD_ACL(handle, conn, capname, mode);
+       return SMB_VFS_NEXT_CHMOD_ACL(handle, capname, mode);
 }
 
-static SMB_ACL_T cap_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
+static SMB_ACL_T cap_sys_acl_get_file(vfs_handle_struct *handle, const char *path_p, SMB_ACL_TYPE_T type)
 {
         pstring cappath_p;
        capencode(cappath_p, path_p);
-       return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, cappath_p, type);
+       return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, cappath_p, type);
 }
 
-static int cap_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
+static int cap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
 {
         pstring capname;
        capencode(capname, name);
-       return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, capname, acltype, theacl);
+       return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, capname, acltype, theacl);
 }
 
-static int cap_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int cap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
 {
         pstring cappath;
        capencode(cappath, path);
-       return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, cappath);
+       return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, cappath);
 }
 
-static ssize_t cap_getxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t size)
+static ssize_t cap_getxattr(vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t size)
 {
         pstring cappath, capname;
        capencode(cappath, path);
        capencode(capname, name);
-        return SMB_VFS_NEXT_GETXATTR(handle, conn, cappath, capname, value, size);
+        return SMB_VFS_NEXT_GETXATTR(handle, cappath, capname, value, size);
 }
 
-static ssize_t cap_lgetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t
+static ssize_t cap_lgetxattr(vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t
 size)
 {
         pstring cappath, capname;
        capencode(cappath, path);
        capencode(capname, name);
-        return SMB_VFS_NEXT_LGETXATTR(handle, conn, cappath, capname, value, size);
+        return SMB_VFS_NEXT_LGETXATTR(handle, cappath, capname, value, size);
 }
 
 static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size)
@@ -242,34 +242,34 @@ static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp
         return SMB_VFS_NEXT_FGETXATTR(handle, fsp, fd, capname, value, size);
 }
 
-static ssize_t cap_listxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
+static ssize_t cap_listxattr(vfs_handle_struct *handle, const char *path, char *list, size_t size)
 {
         pstring cappath;
        capencode(cappath, path);
-        return SMB_VFS_NEXT_LISTXATTR(handle, conn, cappath, list, size);
+        return SMB_VFS_NEXT_LISTXATTR(handle, cappath, list, size);
 }
 
-static ssize_t cap_llistxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
+static ssize_t cap_llistxattr(vfs_handle_struct *handle, const char *path, char *list, size_t size)
 {
         pstring cappath;
        capencode(cappath, path);
-        return SMB_VFS_NEXT_LLISTXATTR(handle, conn, cappath, list, size);
+        return SMB_VFS_NEXT_LLISTXATTR(handle, cappath, list, size);
 }
 
-static int cap_removexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
+static int cap_removexattr(vfs_handle_struct *handle, const char *path, const char *name)
 {
         pstring cappath, capname;
        capencode(cappath, path);
        capencode(capname, name);
-        return SMB_VFS_NEXT_REMOVEXATTR(handle, conn, cappath, capname);
+        return SMB_VFS_NEXT_REMOVEXATTR(handle, cappath, capname);
 }
 
-static int cap_lremovexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
+static int cap_lremovexattr(vfs_handle_struct *handle, const char *path, const char *name)
 {
         pstring cappath, capname;
        capencode(cappath, path);
        capencode(capname, name);
-        return SMB_VFS_NEXT_LREMOVEXATTR(handle, conn, cappath, capname);
+        return SMB_VFS_NEXT_LREMOVEXATTR(handle, cappath, capname);
 }
 
 static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name)
@@ -279,20 +279,20 @@ static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp,
         return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, fd, capname);
 }
 
-static int cap_setxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
+static int cap_setxattr(vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
 {
         pstring cappath, capname;
        capencode(cappath, path);
        capencode(capname, name);
-        return SMB_VFS_NEXT_SETXATTR(handle, conn, cappath, capname, value, size, flags);
+        return SMB_VFS_NEXT_SETXATTR(handle, cappath, capname, value, size, flags);
 }
 
-static int cap_lsetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
+static int cap_lsetxattr(vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
 {
         pstring cappath, capname;
        capencode(cappath, path);
        capencode(capname, name);
-        return SMB_VFS_NEXT_LSETXATTR(handle, conn, cappath, capname, value, size, flags);
+        return SMB_VFS_NEXT_LSETXATTR(handle, cappath, capname, value, size, flags);
 }
 
 static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags)
index 69735de3f43ca3b15137e65aadf7541b552caa9b..f5c7e95794fa12a166c3581051ffad4b0e06a351 100644 (file)
@@ -71,20 +71,20 @@ static void to_unix(char *s)
         catia_string_replace(s, '\xb1', ' ');
 }
 
-static SMB_STRUCT_DIR *catia_opendir(vfs_handle_struct *handle, connection_struct 
-                         *conn, const char *fname, const char *mask, uint32 attr)
+static SMB_STRUCT_DIR *catia_opendir(vfs_handle_struct *handle,
+                         const char *fname, const char *mask, uint32 attr)
 {
         pstring name;
         pstrcpy(name, fname);
         to_unix(name);
 
-        return SMB_VFS_NEXT_OPENDIR(handle, conn, name, mask, attr);
+        return SMB_VFS_NEXT_OPENDIR(handle, name, mask, attr);
 }
 
 static SMB_STRUCT_DIRENT *catia_readdir(vfs_handle_struct *handle, 
-                                       connection_struct *conn, SMB_STRUCT_DIR *dirp)
+                                       SMB_STRUCT_DIR *dirp)
 {
-        SMB_STRUCT_DIRENT *result = SMB_VFS_NEXT_READDIR(handle, conn, dirp);
+        SMB_STRUCT_DIRENT *result = SMB_VFS_NEXT_READDIR(handle, dirp);
 
         if (result == NULL)
                 return result;
@@ -93,18 +93,18 @@ static SMB_STRUCT_DIRENT *catia_readdir(vfs_handle_struct *handle,
         return result;
 }
 
-static int catia_open(vfs_handle_struct *handle, connection_struct *conn, 
-                     const char *fname, int flags, mode_t mode)
+static int catia_open(vfs_handle_struct *handle,
+                     const char *fname, files_struct *fsp, int flags, mode_t mode)
 {
         pstring name;
 
         pstrcpy(name, fname);
         to_unix(name);
  
-        return SMB_VFS_NEXT_OPEN(handle, conn, name, flags, mode);
+        return SMB_VFS_NEXT_OPEN(handle, name, fsp, flags, mode);
 }
 
-static int catia_rename(vfs_handle_struct *handle, connection_struct *conn,
+static int catia_rename(vfs_handle_struct *handle,
                        const char *oldname, const char *newname)
 {
         pstring oname, nname;
@@ -117,109 +117,107 @@ static int catia_rename(vfs_handle_struct *handle, connection_struct *conn,
         DEBUG(10, ("converted old name: %s\n", oname));
         DEBUG(10, ("converted new name: %s\n", nname));
  
-        return SMB_VFS_NEXT_RENAME(handle, conn, oname, nname);
+        return SMB_VFS_NEXT_RENAME(handle, oname, nname);
 }
 
-static int catia_stat(vfs_handle_struct *handle, connection_struct *conn, 
+static int catia_stat(vfs_handle_struct *handle,
                      const char *fname, SMB_STRUCT_STAT *sbuf)
 {
         pstring name;
         pstrcpy(name, fname);
         to_unix(name);
 
-        return SMB_VFS_NEXT_STAT(handle, conn, name, sbuf);
+        return SMB_VFS_NEXT_STAT(handle, name, sbuf);
 }
 
-static int catia_lstat(vfs_handle_struct *handle, connection_struct *conn, 
+static int catia_lstat(vfs_handle_struct *handle,
                       const char *path, SMB_STRUCT_STAT *sbuf)
 {
         pstring name;
         pstrcpy(name, path);
         to_unix(name);
 
-        return SMB_VFS_NEXT_LSTAT(handle, conn, name, sbuf);
+        return SMB_VFS_NEXT_LSTAT(handle, name, sbuf);
 }
 
-static int catia_unlink(vfs_handle_struct *handle, connection_struct *conn,
-                       const char *path)
+static int catia_unlink(vfs_handle_struct *handle, const char *path)
 {
         pstring name;
         pstrcpy(name, path);
         to_unix(name);
 
-        return SMB_VFS_NEXT_UNLINK(handle, conn, name);
+        return SMB_VFS_NEXT_UNLINK(handle, name);
 }
 
-static int catia_chmod(vfs_handle_struct *handle, connection_struct *conn, 
+static int catia_chmod(vfs_handle_struct *handle,
                       const char *path, mode_t mode)
 {
         pstring name;
         pstrcpy(name, path);
         to_unix(name);
 
-        return SMB_VFS_NEXT_CHMOD(handle, conn, name, mode);
+        return SMB_VFS_NEXT_CHMOD(handle, name, mode);
 }
 
-static int catia_chown(vfs_handle_struct *handle, connection_struct *conn, 
+static int catia_chown(vfs_handle_struct *handle,
                       const char *path, uid_t uid, gid_t gid)
 {
         pstring name;
         pstrcpy(name, path);
         to_unix(name);
 
-        return SMB_VFS_NEXT_CHOWN(handle, conn, name, uid, gid);
+        return SMB_VFS_NEXT_CHOWN(handle, name, uid, gid);
 }
 
-static int catia_chdir(vfs_handle_struct *handle, connection_struct *conn, 
+static int catia_chdir(vfs_handle_struct *handle,
                       const char *path)
 {
         pstring name;
         pstrcpy(name, path);
         to_unix(name);
 
-        return SMB_VFS_NEXT_CHDIR(handle, conn, name);
+        return SMB_VFS_NEXT_CHDIR(handle, name);
 }
 
-static char *catia_getwd(vfs_handle_struct *handle, connection_struct *conn,
-                        char *buf)
+static char *catia_getwd(vfs_handle_struct *handle, char *buf)
 {
-        return SMB_VFS_NEXT_GETWD(handle, conn, buf);
+        return SMB_VFS_NEXT_GETWD(handle, buf);
 }
 
-static int catia_utime(vfs_handle_struct *handle, connection_struct *conn, 
+static int catia_utime(vfs_handle_struct *handle,
                       const char *path, struct utimbuf *times)
 {
-        return SMB_VFS_NEXT_UTIME(handle, conn, path, times);
+        return SMB_VFS_NEXT_UTIME(handle, path, times);
 }
 
-static BOOL catia_symlink(vfs_handle_struct *handle, connection_struct *conn,
+static BOOL catia_symlink(vfs_handle_struct *handle,
                          const char *oldpath, const char *newpath)
 {
-        return SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath);
+        return SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath);
 }
 
-static BOOL catia_readlink(vfs_handle_struct *handle, connection_struct *conn,
+static BOOL catia_readlink(vfs_handle_struct *handle,
                           const char *path, char *buf, size_t bufsiz)
 {
-        return SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz);
+        return SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz);
 }
 
-static int catia_link(vfs_handle_struct *handle, connection_struct *conn, 
+static int catia_link(vfs_handle_struct *handle,
                      const char *oldpath, const char *newpath)
 {
-        return SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath);
+        return SMB_VFS_NEXT_LINK(handle, oldpath, newpath);
 }
 
-static int catia_mknod(vfs_handle_struct *handle, connection_struct *conn, 
+static int catia_mknod(vfs_handle_struct *handle,
                       const char *path, mode_t mode, SMB_DEV_T dev)
 {
-        return SMB_VFS_NEXT_MKNOD(handle, conn, path, mode, dev);
+        return SMB_VFS_NEXT_MKNOD(handle, path, mode, dev);
 }
 
-static char *catia_realpath(vfs_handle_struct *handle, connection_struct *conn,
+static char *catia_realpath(vfs_handle_struct *handle,
                            const char *path, char *resolved_path)
 {
-        return SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path);
+        return SMB_VFS_NEXT_REALPATH(handle, path, resolved_path);
 }
 
 static size_t catia_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
@@ -238,7 +236,7 @@ static BOOL catia_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
                                       psd);
 }
 
-static int catia_chmod_acl(vfs_handle_struct *handle, connection_struct *conn,
+static int catia_chmod_acl(vfs_handle_struct *handle,
                           const char *name, mode_t mode)
 {
         /* If the underlying VFS doesn't have ACL support... */
@@ -246,7 +244,7 @@ static int catia_chmod_acl(vfs_handle_struct *handle, connection_struct *conn,
                 errno = ENOSYS;
                 return -1;
         }
-        return SMB_VFS_NEXT_CHMOD_ACL(handle, conn, name, mode);
+        return SMB_VFS_NEXT_CHMOD_ACL(handle, name, mode);
 }
 
 /* VFS operations structure */
@@ -310,7 +308,7 @@ SMB_VFS_LAYER_TRANSPARENT},
 SMB_VFS_LAYER_NOOP}
 };
 
-NTSTATUS init_module(void)
+NTSTATUS vfs_catia_init(void)
 {
         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "catia", 
 catia_op_tuples);
diff --git a/source/modules/vfs_commit.c b/source/modules/vfs_commit.c
new file mode 100644 (file)
index 0000000..9d817c0
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) James Peach 2006
+ *
+ * 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"
+
+/* Commit data module.
+ *
+ * The purpose of this module is to flush data to disk at regular intervals,
+ * just like the NFS commit operation. There's two rationales for this. First,
+ * it minimises the data loss in case of a power outage without incurring
+ * the poor performance of synchronous I/O. Second, a steady flush rate
+ * can produce better throughput than suddenly dumping massive amounts of
+ * writes onto a disk.
+ *
+ * Tunables:
+ *
+ *  commit: dthresh         Amount of dirty data that can accumulate
+ *                                     before we commit (sync) it.
+ *
+ *  commit: debug           Debug level at which to emit messages.
+ *
+ */
+
+#define MODULE "commit"
+
+static int module_debug;
+
+struct commit_info
+{
+        SMB_OFF_T dbytes;      /* Dirty (uncommitted) bytes */
+        SMB_OFF_T dthresh;     /* Dirty data threshold */
+};
+
+static void commit_all(
+        struct vfs_handle_struct *     handle,
+        files_struct *                 fsp)
+{
+        struct commit_info *c;
+
+        if ((c = VFS_FETCH_FSP_EXTENSION(handle, fsp))) {
+                if (c->dbytes) {
+                        DEBUG(module_debug,
+                                ("%s: flushing %lu dirty bytes\n",
+                                 MODULE, (unsigned long)c->dbytes));
+
+                        fdatasync(fsp->fh->fd);
+                        c->dbytes = 0;
+                }
+        }
+}
+
+static void commit(
+        struct vfs_handle_struct *     handle,
+        files_struct *                 fsp,
+        ssize_t                                last_write)
+{
+        struct commit_info *c;
+
+        if ((c = VFS_FETCH_FSP_EXTENSION(handle, fsp))) {
+
+                if (last_write > 0) {
+                        c->dbytes += last_write;
+                }
+
+                if (c->dbytes > c->dthresh) {
+                        DEBUG(module_debug,
+                                ("%s: flushing %lu dirty bytes\n",
+                                 MODULE, (unsigned long)c->dbytes));
+
+                        fdatasync(fsp->fh->fd);
+                        c->dbytes = 0;
+                }
+        }
+}
+
+static int commit_connect(
+        struct vfs_handle_struct *  handle,
+        const char *                service,
+        const char *                user)
+{
+        module_debug = lp_parm_int(SNUM(handle->conn), MODULE, "debug", 100);
+        return SMB_VFS_NEXT_CONNECT(handle, service, user);
+}
+
+static int commit_open(
+       vfs_handle_struct * handle,
+       const char *        fname,
+       files_struct *      fsp,
+       int                 flags,
+       mode_t              mode)
+{
+        SMB_OFF_T dthresh;
+
+        /* Don't bother with read-only files. */
+        if ((flags & O_ACCMODE) == O_RDONLY) {
+                return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+        }
+
+        dthresh = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
+                                        MODULE, "dthresh", NULL));
+
+        if (dthresh > 0) {
+                struct commit_info * c;
+                c = VFS_ADD_FSP_EXTENSION(handle, fsp, struct commit_info);
+                if (c) {
+                        c->dthresh = dthresh;
+                        c->dbytes = 0;
+                }
+        }
+
+        return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+}
+
+static ssize_t commit_write(
+        vfs_handle_struct * handle,
+        files_struct *      fsp,
+        int                 fd,
+        void *              data,
+        size_t              count)
+{
+        ssize_t ret;
+
+        ret = SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, count);
+        commit(handle, fsp, ret);
+
+        return ret;
+}
+
+static ssize_t commit_pwrite(
+        vfs_handle_struct * handle,
+        files_struct *      fsp,
+        int                 fd,
+        void *              data,
+        size_t              count,
+       SMB_OFF_T           offset)
+{
+        ssize_t ret;
+
+        ret = SMB_VFS_NEXT_PWRITE(handle, fsp, fd, data, count, offset);
+        commit(handle, fsp, ret);
+
+        return ret;
+}
+
+static ssize_t commit_close(
+        vfs_handle_struct * handle,
+        files_struct *      fsp,
+        int                 fd)
+{
+        commit_all(handle, fsp);
+        return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
+}
+
+static vfs_op_tuple commit_ops [] =
+{
+        {SMB_VFS_OP(commit_open),
+                SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT},
+        {SMB_VFS_OP(commit_close),
+                SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_TRANSPARENT},
+        {SMB_VFS_OP(commit_write),
+                SMB_VFS_OP_WRITE, SMB_VFS_LAYER_TRANSPARENT},
+        {SMB_VFS_OP(commit_pwrite),
+                SMB_VFS_OP_PWRITE, SMB_VFS_LAYER_TRANSPARENT},
+        {SMB_VFS_OP(commit_connect),
+                SMB_VFS_OP_CONNECT,  SMB_VFS_LAYER_TRANSPARENT},
+
+        {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_commit_init(void)
+{
+       return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE, commit_ops);
+}
+
diff --git a/source/modules/vfs_default.c b/source/modules/vfs_default.c
new file mode 100644 (file)
index 0000000..82eec46
--- /dev/null
@@ -0,0 +1,1327 @@
+/*
+   Unix SMB/CIFS implementation.
+   Wrap disk only vfs functions to sidestep dodgy compilers.
+   Copyright (C) Tim Potter 1998
+
+   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"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_VFS
+
+/* Check for NULL pointer parameters in vfswrap_* functions */
+
+/* We don't want to have NULL function pointers lying around.  Someone
+   is sure to try and execute them.  These stubs are used to prevent
+   this possibility. */
+
+static int vfswrap_connect(vfs_handle_struct *handle,  const char *service, const char *user)
+{
+    return 0;    /* Return >= 0 for success */
+}
+
+static void vfswrap_disconnect(vfs_handle_struct *handle)
+{
+}
+
+/* Disk operations */
+
+static SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle,  const char *path, BOOL small_query, SMB_BIG_UINT *bsize,
+                              SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
+{
+       SMB_BIG_UINT result;
+
+       result = sys_disk_free(handle->conn, path, small_query, bsize, dfree, dsize);
+       return result;
+}
+
+static int vfswrap_get_quota(struct vfs_handle_struct *handle,  enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
+{
+#ifdef HAVE_SYS_QUOTAS
+       int result;
+
+       START_PROFILE(syscall_get_quota);
+       result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
+       END_PROFILE(syscall_get_quota);
+       return result;
+#else
+       errno = ENOSYS;
+       return -1;
+#endif
+}
+
+static int vfswrap_set_quota(struct vfs_handle_struct *handle,  enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
+{
+#ifdef HAVE_SYS_QUOTAS
+       int result;
+
+       START_PROFILE(syscall_set_quota);
+       result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
+       END_PROFILE(syscall_set_quota);
+       return result;
+#else
+       errno = ENOSYS;
+       return -1;
+#endif
+}
+
+static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
+{
+       errno = ENOSYS;
+       return -1;  /* Not implemented. */
+}
+
+static int vfswrap_statvfs(struct vfs_handle_struct *handle,  const char *path, vfs_statvfs_struct *statbuf)
+{
+       return sys_statvfs(path, statbuf);
+}
+
+/* Directory operations */
+
+static SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle,  const char *fname, const char *mask, uint32 attr)
+{
+       SMB_STRUCT_DIR *result;
+
+       START_PROFILE(syscall_opendir);
+       result = sys_opendir(fname);
+       END_PROFILE(syscall_opendir);
+       return result;
+}
+
+static SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
+{
+       SMB_STRUCT_DIRENT *result;
+
+       START_PROFILE(syscall_readdir);
+       result = sys_readdir(dirp);
+       END_PROFILE(syscall_readdir);
+       return result;
+}
+
+static void vfswrap_seekdir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp, long offset)
+{
+       START_PROFILE(syscall_seekdir);
+       sys_seekdir(dirp, offset);
+       END_PROFILE(syscall_seekdir);
+}
+
+static long vfswrap_telldir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
+{
+       long result;
+       START_PROFILE(syscall_telldir);
+       result = sys_telldir(dirp);
+       END_PROFILE(syscall_telldir);
+       return result;
+}
+
+static void vfswrap_rewinddir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
+{
+       START_PROFILE(syscall_rewinddir);
+       sys_rewinddir(dirp);
+       END_PROFILE(syscall_rewinddir);
+}
+
+static int vfswrap_mkdir(vfs_handle_struct *handle,  const char *path, mode_t mode)
+{
+       int result;
+       BOOL has_dacl = False;
+
+       START_PROFILE(syscall_mkdir);
+
+       if (lp_inherit_acls(SNUM(handle->conn)) && (has_dacl = directory_has_default_acl(handle->conn, parent_dirname(path))))
+               mode = 0777;
+
+       result = mkdir(path, mode);
+
+       if (result == 0 && !has_dacl) {
+               /*
+                * We need to do this as the default behavior of POSIX ACLs
+                * is to set the mask to be the requested group permission
+                * bits, not the group permission bits to be the requested
+                * group permission bits. This is not what we want, as it will
+                * mess up any inherited ACL bits that were set. JRA.
+                */
+               int saved_errno = errno; /* We may get ENOSYS */
+               if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
+                       errno = saved_errno;
+       }
+
+       END_PROFILE(syscall_mkdir);
+       return result;
+}
+
+static int vfswrap_rmdir(vfs_handle_struct *handle,  const char *path)
+{
+       int result;
+
+       START_PROFILE(syscall_rmdir);
+       result = rmdir(path);
+       END_PROFILE(syscall_rmdir);
+       return result;
+}
+
+static int vfswrap_closedir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
+{
+       int result;
+
+       START_PROFILE(syscall_closedir);
+       result = sys_closedir(dirp);
+       END_PROFILE(syscall_closedir);
+       return result;
+}
+
+/* File operations */
+
+static int vfswrap_open(vfs_handle_struct *handle,  const char *fname,
+       files_struct *fsp, int flags, mode_t mode)
+{
+       int result;
+
+       START_PROFILE(syscall_open);
+       result = sys_open(fname, flags, mode);
+       END_PROFILE(syscall_open);
+       return result;
+}
+
+static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
+{
+       int result;
+
+       START_PROFILE(syscall_close);
+
+       result = close(fd);
+       END_PROFILE(syscall_close);
+       return result;
+}
+
+static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n)
+{
+       ssize_t result;
+
+       START_PROFILE_BYTES(syscall_read, n);
+       result = sys_read(fd, data, n);
+       END_PROFILE(syscall_read);
+       return result;
+}
+
+static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data,
+                       size_t n, SMB_OFF_T offset)
+{
+       ssize_t result;
+
+#if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
+       START_PROFILE_BYTES(syscall_pread, n);
+       result = sys_pread(fd, data, n, offset);
+       END_PROFILE(syscall_pread);
+
+       if (result == -1 && errno == ESPIPE) {
+               /* Maintain the fiction that pipes can be seeked (sought?) on. */
+               result = SMB_VFS_READ(fsp, fd, data, n);
+               fsp->fh->pos = 0;
+       }
+
+#else /* HAVE_PREAD */
+       SMB_OFF_T   curr;
+       int lerrno;
+
+       curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
+       if (curr == -1 && errno == ESPIPE) {
+               /* Maintain the fiction that pipes can be seeked (sought?) on. */
+               result = SMB_VFS_READ(fsp, fd, data, n);
+               fsp->fh->pos = 0;
+               return result;
+       }
+
+       if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) {
+               return -1;
+       }
+
+       errno = 0;
+       result = SMB_VFS_READ(fsp, fd, data, n);
+       lerrno = errno;
+
+       SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET);
+       errno = lerrno;
+
+#endif /* HAVE_PREAD */
+
+       return result;
+}
+
+static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n)
+{
+       ssize_t result;
+
+       START_PROFILE_BYTES(syscall_write, n);
+       result = sys_write(fd, data, n);
+       END_PROFILE(syscall_write);
+       return result;
+}
+
+static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data,
+                       size_t n, SMB_OFF_T offset)
+{
+       ssize_t result;
+
+#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
+       START_PROFILE_BYTES(syscall_pwrite, n);
+       result = sys_pwrite(fd, data, n, offset);
+       END_PROFILE(syscall_pwrite);
+
+       if (result == -1 && errno == ESPIPE) {
+               /* Maintain the fiction that pipes can be sought on. */
+               result = SMB_VFS_WRITE(fsp, fd, data, n);
+       }
+
+#else /* HAVE_PWRITE */
+       SMB_OFF_T   curr;
+       int         lerrno;
+
+       curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
+       if (curr == -1) {
+               return -1;
+       }
+
+       if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) {
+               return -1;
+       }
+
+       result = SMB_VFS_WRITE(fsp, fd, data, n);
+       lerrno = errno;
+
+       SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET);
+       errno = lerrno;
+
+#endif /* HAVE_PWRITE */
+
+       return result;
+}
+
+static SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence)
+{
+       SMB_OFF_T result = 0;
+
+       START_PROFILE(syscall_lseek);
+
+       /* Cope with 'stat' file opens. */
+       if (filedes != -1)
+               result = sys_lseek(filedes, offset, whence);
+
+       /*
+        * We want to maintain the fiction that we can seek
+        * on a fifo for file system purposes. This allows
+        * people to set up UNIX fifo's that feed data to Windows
+        * applications. JRA.
+        */
+
+       if((result == -1) && (errno == ESPIPE)) {
+               result = 0;
+               errno = 0;
+       }
+
+       END_PROFILE(syscall_lseek);
+       return result;
+}
+
+static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *hdr,
+                       SMB_OFF_T offset, size_t n)
+{
+       ssize_t result;
+
+       START_PROFILE_BYTES(syscall_sendfile, n);
+       result = sys_sendfile(tofd, fromfd, hdr, offset, n);
+       END_PROFILE(syscall_sendfile);
+       return result;
+}
+
+/*********************************************************
+ For rename across filesystems Patch from Warren Birnbaum
+ <warrenb@hpcvscdp.cv.hp.com>
+**********************************************************/
+
+static int copy_reg(const char *source, const char *dest)
+{
+       SMB_STRUCT_STAT source_stats;
+       int saved_errno;
+       int ifd = -1;
+       int ofd = -1;
+
+       if (sys_lstat (source, &source_stats) == -1)
+               return -1;
+
+       if (!S_ISREG (source_stats.st_mode))
+               return -1;
+
+       if((ifd = sys_open (source, O_RDONLY, 0)) < 0)
+               return -1;
+
+       if (unlink (dest) && errno != ENOENT)
+               return -1;
+
+#ifdef O_NOFOLLOW
+       if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 )
+#else
+       if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 )
+#endif
+               goto err;
+
+       if (transfer_file(ifd, ofd, (size_t)-1) == -1)
+               goto err;
+
+       /*
+        * Try to preserve ownership.  For non-root it might fail, but that's ok.
+        * But root probably wants to know, e.g. if NFS disallows it.
+        */
+
+#ifdef HAVE_FCHOWN
+       if ((fchown(ofd, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
+#else
+       if ((chown(dest, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
+#endif
+               goto err;
+
+       /*
+        * fchown turns off set[ug]id bits for non-root,
+        * so do the chmod last.
+        */
+
+#if defined(HAVE_FCHMOD)
+       if (fchmod (ofd, source_stats.st_mode & 07777))
+#else
+       if (chmod (dest, source_stats.st_mode & 07777))
+#endif
+               goto err;
+
+       if (close (ifd) == -1)
+               goto err;
+
+       if (close (ofd) == -1)
+               return -1;
+
+       /* Try to copy the old file's modtime and access time.  */
+       {
+               struct utimbuf tv;
+
+               tv.actime = source_stats.st_atime;
+               tv.modtime = source_stats.st_mtime;
+               utime(dest, &tv);
+       }
+
+       if (unlink (source) == -1)
+               return -1;
+
+       return 0;
+
+  err:
+
+       saved_errno = errno;
+       if (ifd != -1)
+               close(ifd);
+       if (ofd != -1)
+               close(ofd);
+       errno = saved_errno;
+       return -1;
+}
+
+static int vfswrap_rename(vfs_handle_struct *handle,  const char *oldname, const char *newname)
+{
+       int result;
+
+       START_PROFILE(syscall_rename);
+       result = rename(oldname, newname);
+       if (errno == EXDEV) {
+               /* Rename across filesystems needed. */
+               result = copy_reg(oldname, newname);
+       }
+
+       END_PROFILE(syscall_rename);
+       return result;
+}
+
+static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd)
+{
+#ifdef HAVE_FSYNC
+       int result;
+
+       START_PROFILE(syscall_fsync);
+       result = fsync(fd);
+       END_PROFILE(syscall_fsync);
+       return result;
+#else
+       return 0;
+#endif
+}
+
+static int vfswrap_stat(vfs_handle_struct *handle,  const char *fname, SMB_STRUCT_STAT *sbuf)
+{
+       int result;
+
+       START_PROFILE(syscall_stat);
+       result = sys_stat(fname, sbuf);
+       END_PROFILE(syscall_stat);
+       return result;
+}
+
+static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
+{
+       int result;
+
+       START_PROFILE(syscall_fstat);
+       result = sys_fstat(fd, sbuf);
+       END_PROFILE(syscall_fstat);
+       return result;
+}
+
+int vfswrap_lstat(vfs_handle_struct *handle,  const char *path, SMB_STRUCT_STAT *sbuf)
+{
+       int result;
+
+       START_PROFILE(syscall_lstat);
+       result = sys_lstat(path, sbuf);
+       END_PROFILE(syscall_lstat);
+       return result;
+}
+
+static int vfswrap_unlink(vfs_handle_struct *handle,  const char *path)
+{
+       int result;
+
+       START_PROFILE(syscall_unlink);
+       result = unlink(path);
+       END_PROFILE(syscall_unlink);
+       return result;
+}
+
+static int vfswrap_chmod(vfs_handle_struct *handle,  const char *path, mode_t mode)
+{
+       int result;
+
+       START_PROFILE(syscall_chmod);
+
+       /*
+        * We need to do this due to the fact that the default POSIX ACL
+        * chmod modifies the ACL *mask* for the group owner, not the
+        * group owner bits directly. JRA.
+        */
+
+
+       {
+               int saved_errno = errno; /* We might get ENOSYS */
+               if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
+                       END_PROFILE(syscall_chmod);
+                       return result;
+               }
+               /* Error - return the old errno. */
+               errno = saved_errno;
+       }
+
+       result = chmod(path, mode);
+       END_PROFILE(syscall_chmod);
+       return result;
+}
+
+static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
+{
+       int result;
+
+       START_PROFILE(syscall_fchmod);
+
+       /*
+        * We need to do this due to the fact that the default POSIX ACL
+        * chmod modifies the ACL *mask* for the group owner, not the
+        * group owner bits directly. JRA.
+        */
+
+       {
+               int saved_errno = errno; /* We might get ENOSYS */
+               if ((result = SMB_VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) {
+                       END_PROFILE(syscall_fchmod);
+                       return result;
+               }
+               /* Error - return the old errno. */
+               errno = saved_errno;
+       }
+
+#if defined(HAVE_FCHMOD)
+       result = fchmod(fd, mode);
+#else
+       result = -1;
+       errno = ENOSYS;
+#endif
+
+       END_PROFILE(syscall_fchmod);
+       return result;
+}
+
+static int vfswrap_chown(vfs_handle_struct *handle,  const char *path, uid_t uid, gid_t gid)
+{
+       int result;
+
+       START_PROFILE(syscall_chown);
+       result = sys_chown(path, uid, gid);
+       END_PROFILE(syscall_chown);
+       return result;
+}
+
+static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid)
+{
+#ifdef HAVE_FCHOWN
+       int result;
+
+       START_PROFILE(syscall_fchown);
+       result = fchown(fd, uid, gid);
+       END_PROFILE(syscall_fchown);
+       return result;
+#else
+       errno = ENOSYS;
+       return -1;
+#endif
+}
+
+static int vfswrap_chdir(vfs_handle_struct *handle,  const char *path)
+{
+       int result;
+
+       START_PROFILE(syscall_chdir);
+       result = chdir(path);
+       END_PROFILE(syscall_chdir);
+       return result;
+}
+
+static char *vfswrap_getwd(vfs_handle_struct *handle,  char *path)
+{
+       char *result;
+
+       START_PROFILE(syscall_getwd);
+       result = sys_getwd(path);
+       END_PROFILE(syscall_getwd);
+       return result;
+}
+
+static int vfswrap_utime(vfs_handle_struct *handle,  const char *path, struct utimbuf *times)
+{
+       int result;
+
+       START_PROFILE(syscall_utime);
+       result = utime(path, times);
+       END_PROFILE(syscall_utime);
+       return result;
+}
+
+/*********************************************************************
+ A version of ftruncate that will write the space on disk if strict
+ allocate is set.
+**********************************************************************/
+
+static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len)
+{
+       SMB_STRUCT_STAT st;
+       SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
+       unsigned char zero_space[4096];
+       SMB_OFF_T space_to_write;
+
+       if (currpos == -1)
+               return -1;
+
+       if (SMB_VFS_FSTAT(fsp, fd, &st) == -1)
+               return -1;
+
+       space_to_write = len - st.st_size;
+
+#ifdef S_ISFIFO
+       if (S_ISFIFO(st.st_mode))
+               return 0;
+#endif
+
+       if (st.st_size == len)
+               return 0;
+
+       /* Shrink - just ftruncate. */
+       if (st.st_size > len)
+               return sys_ftruncate(fd, len);
+
+       /* Write out the real space on disk. */
+       if (SMB_VFS_LSEEK(fsp, fd, st.st_size, SEEK_SET) != st.st_size)
+               return -1;
+
+       space_to_write = len - st.st_size;
+
+       memset(zero_space, '\0', sizeof(zero_space));
+       while ( space_to_write > 0) {
+               SMB_OFF_T retlen;
+               SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
+
+               retlen = SMB_VFS_WRITE(fsp,fsp->fh->fd,(char *)zero_space,current_len_to_write);
+               if (retlen <= 0)
+                       return -1;
+
+               space_to_write -= retlen;
+       }
+
+       /* Seek to where we were */
+       if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos)
+               return -1;
+
+       return 0;
+}
+
+static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len)
+{
+       int result = -1;
+       SMB_STRUCT_STAT st;
+       char c = 0;
+       SMB_OFF_T currpos;
+
+       START_PROFILE(syscall_ftruncate);
+
+       if (lp_strict_allocate(SNUM(fsp->conn))) {
+               result = strict_allocate_ftruncate(handle, fsp, fd, len);
+               END_PROFILE(syscall_ftruncate);
+               return result;
+       }
+
+       /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
+          sys_ftruncate if the system supports it. Then I discovered that
+          you can have some filesystems that support ftruncate
+          expansion and some that don't! On Linux fat can't do
+          ftruncate extend but ext2 can. */
+
+       result = sys_ftruncate(fd, len);
+       if (result == 0)
+               goto done;
+
+       /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
+          extend a file with ftruncate. Provide alternate implementation
+          for this */
+       currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
+       if (currpos == -1) {
+               goto done;
+       }
+
+       /* Do an fstat to see if the file is longer than the requested
+          size in which case the ftruncate above should have
+          succeeded or shorter, in which case seek to len - 1 and
+          write 1 byte of zero */
+       if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) {
+               goto done;
+       }
+
+#ifdef S_ISFIFO
+       if (S_ISFIFO(st.st_mode)) {
+               result = 0;
+               goto done;
+       }
+#endif
+
+       if (st.st_size == len) {
+               result = 0;
+               goto done;
+       }
+
+       if (st.st_size > len) {
+               /* the sys_ftruncate should have worked */
+               goto done;
+       }
+
+       if (SMB_VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1)
+               goto done;
+
+       if (SMB_VFS_WRITE(fsp, fd, &c, 1)!=1)
+               goto done;
+
+       /* Seek to where we were */
+       if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos)
+               goto done;
+       result = 0;
+
+  done:
+
+       END_PROFILE(syscall_ftruncate);
+       return result;
+}
+
+static BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
+{
+       BOOL result;
+
+       START_PROFILE(syscall_fcntl_lock);
+       result =  fcntl_lock(fd, op, offset, count, type);
+       END_PROFILE(syscall_fcntl_lock);
+       return result;
+}
+
+static BOOL vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
+{
+       BOOL result;
+
+       START_PROFILE(syscall_fcntl_getlock);
+       result =  fcntl_getlock(fd, poffset, pcount, ptype, ppid);
+       END_PROFILE(syscall_fcntl_getlock);
+       return result;
+}
+
+static int vfswrap_symlink(vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
+{
+       int result;
+
+       START_PROFILE(syscall_symlink);
+       result = sys_symlink(oldpath, newpath);
+       END_PROFILE(syscall_symlink);
+       return result;
+}
+
+static int vfswrap_readlink(vfs_handle_struct *handle,  const char *path, char *buf, size_t bufsiz)
+{
+       int result;
+
+       START_PROFILE(syscall_readlink);
+       result = sys_readlink(path, buf, bufsiz);
+       END_PROFILE(syscall_readlink);
+       return result;
+}
+
+static int vfswrap_link(vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
+{
+       int result;
+
+       START_PROFILE(syscall_link);
+       result = sys_link(oldpath, newpath);
+       END_PROFILE(syscall_link);
+       return result;
+}
+
+static int vfswrap_mknod(vfs_handle_struct *handle,  const char *pathname, mode_t mode, SMB_DEV_T dev)
+{
+       int result;
+
+       START_PROFILE(syscall_mknod);
+       result = sys_mknod(pathname, mode, dev);
+       END_PROFILE(syscall_mknod);
+       return result;
+}
+
+static char *vfswrap_realpath(vfs_handle_struct *handle,  const char *path, char *resolved_path)
+{
+       char *result;
+
+       START_PROFILE(syscall_realpath);
+       result = sys_realpath(path, resolved_path);
+       END_PROFILE(syscall_realpath);
+       return result;
+}
+
+static size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, SEC_DESC **ppdesc)
+{
+       size_t result;
+
+       START_PROFILE(fget_nt_acl);
+       result = get_nt_acl(fsp, security_info, ppdesc);
+       END_PROFILE(fget_nt_acl);
+       return result;
+}
+
+static size_t vfswrap_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, SEC_DESC **ppdesc)
+{
+       size_t result;
+
+       START_PROFILE(get_nt_acl);
+       result = get_nt_acl(fsp, security_info, ppdesc);
+       END_PROFILE(get_nt_acl);
+       return result;
+}
+
+static BOOL vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
+{
+       BOOL result;
+
+       START_PROFILE(fset_nt_acl);
+       result = set_nt_acl(fsp, security_info_sent, psd);
+       END_PROFILE(fset_nt_acl);
+       return result;
+}
+
+static BOOL vfswrap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
+{
+       BOOL result;
+
+       START_PROFILE(set_nt_acl);
+       result = set_nt_acl(fsp, security_info_sent, psd);
+       END_PROFILE(set_nt_acl);
+       return result;
+}
+
+static int vfswrap_chmod_acl(vfs_handle_struct *handle,  const char *name, mode_t mode)
+{
+#ifdef HAVE_NO_ACL
+       errno = ENOSYS;
+       return -1;
+#else
+       int result;
+
+       START_PROFILE(chmod_acl);
+       result = chmod_acl(handle->conn, name, mode);
+       END_PROFILE(chmod_acl);
+       return result;
+#endif
+}
+
+static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
+{
+#ifdef HAVE_NO_ACL
+       errno = ENOSYS;
+       return -1;
+#else
+       int result;
+
+       START_PROFILE(fchmod_acl);
+       result = fchmod_acl(fsp, fd, mode);
+       END_PROFILE(fchmod_acl);
+       return result;
+#endif
+}
+
+static int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle,  SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
+{
+       return sys_acl_get_entry(theacl, entry_id, entry_p);
+}
+
+static int vfswrap_sys_acl_get_tag_type(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
+{
+       return sys_acl_get_tag_type(entry_d, tag_type_p);
+}
+
+static int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
+{
+       return sys_acl_get_permset(entry_d, permset_p);
+}
+
+static void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d)
+{
+       return sys_acl_get_qualifier(entry_d);
+}
+
+static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,  const char *path_p, SMB_ACL_TYPE_T type)
+{
+       return sys_acl_get_file(path_p, type);
+}
+
+static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
+{
+       return sys_acl_get_fd(fd);
+}
+
+static int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset)
+{
+       return sys_acl_clear_perms(permset);
+}
+
+static int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
+{
+       return sys_acl_add_perm(permset, perm);
+}
+
+static char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle,  SMB_ACL_T theacl, ssize_t *plen)
+{
+       return sys_acl_to_text(theacl, plen);
+}
+
+static SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle,  int count)
+{
+       return sys_acl_init(count);
+}
+
+static int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle,  SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
+{
+       return sys_acl_create_entry(pacl, pentry);
+}
+
+static int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
+{
+       return sys_acl_set_tag_type(entry, tagtype);
+}
+
+static int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, void *qual)
+{
+       return sys_acl_set_qualifier(entry, qual);
+}
+
+static int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
+{
+       return sys_acl_set_permset(entry, permset);
+}
+
+static int vfswrap_sys_acl_valid(vfs_handle_struct *handle,  SMB_ACL_T theacl )
+{
+       return sys_acl_valid(theacl );
+}
+
+static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,  const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
+{
+       return sys_acl_set_file(name, acltype, theacl);
+}
+
+static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl)
+{
+       return sys_acl_set_fd(fd, theacl);
+}
+
+static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,  const char *path)
+{
+       return sys_acl_delete_def_file(path);
+}
+
+static int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
+{
+       return sys_acl_get_perm(permset, perm);
+}
+
+static int vfswrap_sys_acl_free_text(vfs_handle_struct *handle,  char *text)
+{
+       return sys_acl_free_text(text);
+}
+
+static int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle,  SMB_ACL_T posix_acl)
+{
+       return sys_acl_free_acl(posix_acl);
+}
+
+static int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle,  void *qualifier, SMB_ACL_TAG_T tagtype)
+{
+       return sys_acl_free_qualifier(qualifier, tagtype);
+}
+
+/****************************************************************
+ Extended attribute operations.
+*****************************************************************/
+
+static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
+{
+       return sys_getxattr(path, name, value, size);
+}
+
+static ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
+{
+       return sys_lgetxattr(path, name, value, size);
+}
+
+static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size)
+{
+       return sys_fgetxattr(fd, name, value, size);
+}
+
+static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
+{
+       return sys_listxattr(path, list, size);
+}
+
+ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
+{
+       return sys_llistxattr(path, list, size);
+}
+
+ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size)
+{
+       return sys_flistxattr(fd, list, size);
+}
+
+static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
+{
+       return sys_removexattr(path, name);
+}
+
+static int vfswrap_lremovexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
+{
+       return sys_lremovexattr(path, name);
+}
+
+static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name)
+{
+       return sys_fremovexattr(fd, name);
+}
+
+static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
+{
+       return sys_setxattr(path, name, value, size, flags);
+}
+
+static int vfswrap_lsetxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
+{
+       return sys_lsetxattr(path, name, value, size, flags);
+}
+
+static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags)
+{
+       return sys_fsetxattr(fd, name, value, size, flags);
+}
+
+static int vfswrap_aio_read(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
+{
+       return sys_aio_read(aiocb);
+}
+
+static int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
+{
+       return sys_aio_write(aiocb);
+}
+
+static ssize_t vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
+{
+       return sys_aio_return(aiocb);
+}
+
+static int vfswrap_aio_cancel(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_STRUCT_AIOCB *aiocb)
+{
+       return sys_aio_cancel(fd, aiocb);
+}
+
+static int vfswrap_aio_error(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
+{
+       return sys_aio_error(aiocb);
+}
+
+static int vfswrap_aio_fsync(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb)
+{
+       return sys_aio_fsync(op, aiocb);
+}
+
+static int vfswrap_aio_suspend(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_AIOCB * const aiocb[], int n, const struct timespec *timeout)
+{
+       return sys_aio_suspend(aiocb, n, timeout);
+}
+
+static vfs_op_tuple vfs_default_ops[] = {
+
+       /* Disk operations */
+
+       {SMB_VFS_OP(vfswrap_connect),   SMB_VFS_OP_CONNECT,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_disconnect),        SMB_VFS_OP_DISCONNECT,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_disk_free), SMB_VFS_OP_DISK_FREE,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_get_quota), SMB_VFS_OP_GET_QUOTA,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_set_quota), SMB_VFS_OP_SET_QUOTA,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_get_shadow_copy_data), SMB_VFS_OP_GET_SHADOW_COPY_DATA,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_statvfs),   SMB_VFS_OP_STATVFS,
+        SMB_VFS_LAYER_OPAQUE},
+
+       /* Directory operations */
+
+       {SMB_VFS_OP(vfswrap_opendir),   SMB_VFS_OP_OPENDIR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_readdir),   SMB_VFS_OP_READDIR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_seekdir),   SMB_VFS_OP_SEEKDIR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_telldir),   SMB_VFS_OP_TELLDIR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_rewinddir), SMB_VFS_OP_REWINDDIR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_mkdir),     SMB_VFS_OP_MKDIR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_rmdir),     SMB_VFS_OP_RMDIR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_closedir),  SMB_VFS_OP_CLOSEDIR,
+        SMB_VFS_LAYER_OPAQUE},
+
+       /* File operations */
+
+       {SMB_VFS_OP(vfswrap_open),      SMB_VFS_OP_OPEN,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_close),     SMB_VFS_OP_CLOSE,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_read),      SMB_VFS_OP_READ,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_pread),     SMB_VFS_OP_PREAD,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_write),     SMB_VFS_OP_WRITE,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_pwrite),    SMB_VFS_OP_PWRITE,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_lseek),     SMB_VFS_OP_LSEEK,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sendfile),  SMB_VFS_OP_SENDFILE,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_rename),    SMB_VFS_OP_RENAME,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_fsync),     SMB_VFS_OP_FSYNC,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_stat),      SMB_VFS_OP_STAT,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_fstat),     SMB_VFS_OP_FSTAT,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_lstat),     SMB_VFS_OP_LSTAT,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_unlink),    SMB_VFS_OP_UNLINK,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_chmod),     SMB_VFS_OP_CHMOD,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_fchmod),    SMB_VFS_OP_FCHMOD,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_chown),     SMB_VFS_OP_CHOWN,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_fchown),    SMB_VFS_OP_FCHOWN,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_chdir),     SMB_VFS_OP_CHDIR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_getwd),     SMB_VFS_OP_GETWD,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_utime),     SMB_VFS_OP_UTIME,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_ftruncate), SMB_VFS_OP_FTRUNCATE,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_lock),      SMB_VFS_OP_LOCK,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_getlock),   SMB_VFS_OP_GETLOCK,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_symlink),   SMB_VFS_OP_SYMLINK,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_readlink),  SMB_VFS_OP_READLINK,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_link),      SMB_VFS_OP_LINK,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_mknod),     SMB_VFS_OP_MKNOD,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_realpath),  SMB_VFS_OP_REALPATH,
+        SMB_VFS_LAYER_OPAQUE},
+
+       /* NT ACL operations. */
+
+       {SMB_VFS_OP(vfswrap_fget_nt_acl),       SMB_VFS_OP_FGET_NT_ACL,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_get_nt_acl),        SMB_VFS_OP_GET_NT_ACL,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_fset_nt_acl),       SMB_VFS_OP_FSET_NT_ACL,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_set_nt_acl),        SMB_VFS_OP_SET_NT_ACL,
+        SMB_VFS_LAYER_OPAQUE},
+
+       /* POSIX ACL operations. */
+
+       {SMB_VFS_OP(vfswrap_chmod_acl), SMB_VFS_OP_CHMOD_ACL,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_fchmod_acl),        SMB_VFS_OP_FCHMOD_ACL,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_get_entry), SMB_VFS_OP_SYS_ACL_GET_ENTRY,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_get_tag_type),      SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_get_permset),       SMB_VFS_OP_SYS_ACL_GET_PERMSET,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_get_qualifier),     SMB_VFS_OP_SYS_ACL_GET_QUALIFIER,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_get_file),  SMB_VFS_OP_SYS_ACL_GET_FILE,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_get_fd),    SMB_VFS_OP_SYS_ACL_GET_FD,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_clear_perms),       SMB_VFS_OP_SYS_ACL_CLEAR_PERMS,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_add_perm),  SMB_VFS_OP_SYS_ACL_ADD_PERM,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_to_text),   SMB_VFS_OP_SYS_ACL_TO_TEXT,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_init),      SMB_VFS_OP_SYS_ACL_INIT,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_create_entry),      SMB_VFS_OP_SYS_ACL_CREATE_ENTRY,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_set_tag_type),      SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_set_qualifier),     SMB_VFS_OP_SYS_ACL_SET_QUALIFIER,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_set_permset),       SMB_VFS_OP_SYS_ACL_SET_PERMSET,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_valid),     SMB_VFS_OP_SYS_ACL_VALID,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_set_file),  SMB_VFS_OP_SYS_ACL_SET_FILE,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_set_fd),    SMB_VFS_OP_SYS_ACL_SET_FD,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_delete_def_file),   SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_get_perm),  SMB_VFS_OP_SYS_ACL_GET_PERM,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_free_text), SMB_VFS_OP_SYS_ACL_FREE_TEXT,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_free_acl),  SMB_VFS_OP_SYS_ACL_FREE_ACL,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_sys_acl_free_qualifier),    SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER,
+        SMB_VFS_LAYER_OPAQUE},
+
+       /* EA operations. */
+
+       {SMB_VFS_OP(vfswrap_getxattr),  SMB_VFS_OP_GETXATTR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_lgetxattr), SMB_VFS_OP_LGETXATTR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_fgetxattr), SMB_VFS_OP_FGETXATTR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_listxattr), SMB_VFS_OP_LISTXATTR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_llistxattr),        SMB_VFS_OP_LLISTXATTR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_flistxattr),        SMB_VFS_OP_FLISTXATTR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_removexattr),       SMB_VFS_OP_REMOVEXATTR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_lremovexattr),      SMB_VFS_OP_LREMOVEXATTR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_fremovexattr),      SMB_VFS_OP_FREMOVEXATTR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_setxattr),  SMB_VFS_OP_SETXATTR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_lsetxattr), SMB_VFS_OP_LSETXATTR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_fsetxattr), SMB_VFS_OP_FSETXATTR,
+        SMB_VFS_LAYER_OPAQUE},
+
+       {SMB_VFS_OP(vfswrap_aio_read),  SMB_VFS_OP_AIO_READ,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_aio_write), SMB_VFS_OP_AIO_WRITE,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_aio_return),        SMB_VFS_OP_AIO_RETURN,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_aio_cancel), SMB_VFS_OP_AIO_CANCEL,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_aio_error), SMB_VFS_OP_AIO_ERROR,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_aio_fsync), SMB_VFS_OP_AIO_FSYNC,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_aio_suspend),SMB_VFS_OP_AIO_SUSPEND,
+        SMB_VFS_LAYER_OPAQUE},
+
+       /* Finish VFS operations definition */
+
+       {SMB_VFS_OP(NULL),              SMB_VFS_OP_NOOP,
+        SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_default_init(void)
+{
+       unsigned int needed = SMB_VFS_OP_LAST + 1; /* convert from index to count */
+
+       if (ARRAY_SIZE(vfs_default_ops) != needed) {
+               DEBUG(0, ("%s: %u ops registered, but %u ops are required\n",
+                       DEFAULT_VFS_MODULE_NAME, (unsigned int)ARRAY_SIZE(vfs_default_ops), needed));
+               smb_panic("operation(s) missing from default VFS module");
+       }
+
+       return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
+                               DEFAULT_VFS_MODULE_NAME, vfs_default_ops);
+}
index 9922a30315d4804c243503ec6db85559f143b2db..55dc287b88a126cc834b7725f766193dbfcfaae9 100644 (file)
 #define DEFAULT_QUOTA_GID_NOLIMIT(handle) \
        lp_parm_bool(SNUM((handle)->conn),DEFAULT_QUOTA_NAME,"gid nolimit",DEFAULT_QUOTA_GID_NOLIMIT_DEFAULT)
 
-static int default_quota_get_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq)
+static int default_quota_get_quota(vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq)
 {
        int ret = -1;
 
-       if ((ret=SMB_VFS_NEXT_GET_QUOTA(handle, conn, qtype, id, dq))!=0) {
+       if ((ret=SMB_VFS_NEXT_GET_QUOTA(handle, qtype, id, dq))!=0) {
                return ret;
        }
 
@@ -122,7 +122,7 @@ static int default_quota_get_quota(vfs_handle_struct *handle, connection_struct
                                unid_t qid;
                                uint32 qflags = dq->qflags;
                                qid.uid = DEFAULT_QUOTA_UID(handle);
-                               SMB_VFS_NEXT_GET_QUOTA(handle, conn, SMB_USER_QUOTA_TYPE, qid, dq);
+                               SMB_VFS_NEXT_GET_QUOTA(handle, SMB_USER_QUOTA_TYPE, qid, dq);
                                dq->qflags = qflags;
                        }
                        break;
@@ -132,7 +132,7 @@ static int default_quota_get_quota(vfs_handle_struct *handle, connection_struct
                                unid_t qid;
                                uint32 qflags = dq->qflags;
                                qid.gid = DEFAULT_QUOTA_GID(handle);
-                               SMB_VFS_NEXT_GET_QUOTA(handle, conn, SMB_GROUP_QUOTA_TYPE, qid, dq);
+                               SMB_VFS_NEXT_GET_QUOTA(handle, SMB_GROUP_QUOTA_TYPE, qid, dq);
                                dq->qflags = qflags;
                        }
                        break;
@@ -146,7 +146,7 @@ static int default_quota_get_quota(vfs_handle_struct *handle, connection_struct
        return ret;
 }
 
-static int default_quota_set_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq)
+static int default_quota_set_quota(vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq)
 {
        int ret = -1;
 
@@ -179,7 +179,7 @@ static int default_quota_set_quota(vfs_handle_struct *handle, connection_struct
                        break;
        }
 
-       if ((ret=SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, dq))!=0) {
+       if ((ret=SMB_VFS_NEXT_SET_QUOTA(handle, qtype, id, dq))!=0) {
                return ret;
        }
 
@@ -194,7 +194,7 @@ static int default_quota_set_quota(vfs_handle_struct *handle, connection_struct
                        {
                                unid_t qid;
                                qid.uid = DEFAULT_QUOTA_UID(handle);
-                               ret = SMB_VFS_NEXT_SET_QUOTA(handle, conn, SMB_USER_QUOTA_TYPE, qid, dq);
+                               ret = SMB_VFS_NEXT_SET_QUOTA(handle, SMB_USER_QUOTA_TYPE, qid, dq);
                        }
                        break;
 #ifdef HAVE_GROUP_QUOTA
@@ -202,7 +202,7 @@ static int default_quota_set_quota(vfs_handle_struct *handle, connection_struct
                        {
                                unid_t qid;
                                qid.gid = DEFAULT_QUOTA_GID(handle);
-                               ret = SMB_VFS_NEXT_SET_QUOTA(handle, conn, SMB_GROUP_QUOTA_TYPE, qid, dq);
+                               ret = SMB_VFS_NEXT_SET_QUOTA(handle, SMB_GROUP_QUOTA_TYPE, qid, dq);
                        }
                        break;
 #endif /* HAVE_GROUP_QUOTA */
index d22f6a7f98e45f88d4b4c735cec7d55d55c2f7e2..fdd9ac6fbd80c5784d7e53ad588bb3fb0f63525b 100644 (file)
@@ -110,6 +110,7 @@ static BOOL expand_msdfs_target(connection_struct* conn, pstring target)
        int filename_len;
        pstring targethost;
        pstring new_target;
+       extern userdom_struct current_user_info;
 
        if (filename_start == NULL) {
                DEBUG(10, ("No filename start in %s\n", target));
@@ -135,7 +136,11 @@ static BOOL expand_msdfs_target(connection_struct* conn, pstring target)
                return False;
        }
 
-       standard_sub_conn(conn, mapfilename, sizeof(mapfilename));
+       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                             conn->connectpath, conn->gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             mapfilename, sizeof(mapfilename));
 
        DEBUG(10, ("Expanded targethost to %s\n", targethost));
 
@@ -150,13 +155,12 @@ static BOOL expand_msdfs_target(connection_struct* conn, pstring target)
 }
 
 static int expand_msdfs_readlink(struct vfs_handle_struct *handle,
-                                struct connection_struct *conn,
                                 const char *path, char *buf, size_t bufsiz)
 {
        pstring target;
        int result;
 
-       result = SMB_VFS_NEXT_READLINK(handle, conn, path, target,
+       result = SMB_VFS_NEXT_READLINK(handle, path, target,
                                       sizeof(target));
 
        if (result < 0)
@@ -166,7 +170,7 @@ static int expand_msdfs_readlink(struct vfs_handle_struct *handle,
 
        if ((strncmp(target, "msdfs:", strlen("msdfs:")) == 0) &&
            (strchr_m(target, '@') != NULL)) {
-               if (!expand_msdfs_target(conn, target)) {
+               if (!expand_msdfs_target(handle->conn, target)) {
                        errno = ENOENT;
                        return -1;
                }
index cb8c3ffd6ab60624369fcbb4746ef48fa32d8cf3..1c3b25103c8c2d0e3017a098a700310c435a0cb3 100644 (file)
@@ -32,17 +32,17 @@ static int vfs_extd_audit_debug_level = DBGC_VFS;
 
 /* Function prototypes */
 
-static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user);
-static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn);
-static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr);
-static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode);
-static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path);
-static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode);
+static int audit_connect(vfs_handle_struct *handle, const char *svc, const char *user);
+static void audit_disconnect(vfs_handle_struct *handle);
+static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr);
+static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode);
+static int audit_rmdir(vfs_handle_struct *handle, const char *path);
+static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode);
 static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd);
-static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname);
-static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path);
-static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode);
-static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode);
+static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname);
+static int audit_unlink(vfs_handle_struct *handle, const char *path);
+static int audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode);
+static int audit_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode);
 static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode);
 static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode);
 
@@ -123,7 +123,7 @@ static int audit_syslog_priority(vfs_handle_struct *handle)
 /* Implementation of vfs_ops.  Pass everything on to the default
    operation but log event first. */
 
-static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user)
+static int audit_connect(vfs_handle_struct *handle, const char *svc, const char *user)
 {
        int result;
 
@@ -134,25 +134,25 @@ static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, con
        DEBUG(10, ("Connected to service %s as user %s\n",
               svc, user));
 
-       result = SMB_VFS_NEXT_CONNECT(handle, conn, svc, user);
+       result = SMB_VFS_NEXT_CONNECT(handle, svc, user);
 
        return result;
 }
 
-static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn)
+static void audit_disconnect(vfs_handle_struct *handle)
 {
        syslog(audit_syslog_priority(handle), "disconnected\n");
        DEBUG(10, ("Disconnected from VFS module extd_audit\n"));
-       SMB_VFS_NEXT_DISCONNECT(handle, conn);
+       SMB_VFS_NEXT_DISCONNECT(handle);
 
        return;
 }
 
-static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr)
+static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
 {
        SMB_STRUCT_DIR *result;
 
-       result = SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr);
+       result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
 
        syslog(audit_syslog_priority(handle), "opendir %s %s%s\n",
               fname,
@@ -166,11 +166,11 @@ static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struc
        return result;
 }
 
-static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
 {
        int result;
        
-       result = SMB_VFS_NEXT_MKDIR(handle, conn, path, mode);
+       result = SMB_VFS_NEXT_MKDIR(handle, path, mode);
        
        syslog(audit_syslog_priority(handle), "mkdir %s %s%s\n", 
               path,
@@ -184,11 +184,11 @@ static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const
        return result;
 }
 
-static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int audit_rmdir(vfs_handle_struct *handle, const char *path)
 {
        int result;
        
-       result = SMB_VFS_NEXT_RMDIR(handle, conn, path);
+       result = SMB_VFS_NEXT_RMDIR(handle, path);
 
        syslog(audit_syslog_priority(handle), "rmdir %s %s%s\n", 
               path, 
@@ -202,11 +202,11 @@ static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const
        return result;
 }
 
-static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
+static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode)
 {
        int result;
        
-       result = SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
+       result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
 
        syslog(audit_syslog_priority(handle), "open %s (fd %d) %s%s%s\n", 
               fname, result,
@@ -239,11 +239,11 @@ static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
        return result;
 }
 
-static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname)
+static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname)
 {
        int result;
        
-       result = SMB_VFS_NEXT_RENAME(handle, conn, oldname, newname);
+       result = SMB_VFS_NEXT_RENAME(handle, oldname, newname);
 
        syslog(audit_syslog_priority(handle), "rename %s -> %s %s%s\n",
               oldname, newname,
@@ -257,11 +257,11 @@ static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, cons
        return result;    
 }
 
-static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int audit_unlink(vfs_handle_struct *handle, const char *path)
 {
        int result;
        
-       result = SMB_VFS_NEXT_UNLINK(handle, conn, path);
+       result = SMB_VFS_NEXT_UNLINK(handle, path);
 
        syslog(audit_syslog_priority(handle), "unlink %s %s%s\n",
               path,
@@ -275,11 +275,11 @@ static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, cons
        return result;
 }
 
-static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
 {
        int result;
 
-       result = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode);
+       result = SMB_VFS_NEXT_CHMOD(handle, path, mode);
 
        syslog(audit_syslog_priority(handle), "chmod %s mode 0x%x %s%s\n",
               path, mode,
@@ -293,11 +293,11 @@ static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const
        return result;
 }
 
-static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int audit_chmod_acl(vfs_handle_struct *handle, const char *path, mode_t mode)
 {
        int result;
        
-       result = SMB_VFS_NEXT_CHMOD_ACL(handle, conn, path, mode);
+       result = SMB_VFS_NEXT_CHMOD_ACL(handle, path, mode);
 
        syslog(audit_syslog_priority(handle), "chmod_acl %s mode 0x%x %s%s\n",
               path, mode,
index decbe01d3cacf8de22f421369b87ed0eaaf6196d..8bd8bbf532115c7d213e26ac12ddddd4d92e4ce8 100644 (file)
@@ -29,11 +29,11 @@ extern struct current_user current_user;
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_VFS
 
-static int fake_perms_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
+static int fake_perms_stat(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf)
 {
        int ret = -1;
 
-       ret = SMB_VFS_NEXT_STAT(handle, conn, fname, sbuf);
+       ret = SMB_VFS_NEXT_STAT(handle, fname, sbuf);
        if (ret == 0) {
                if (S_ISDIR(sbuf->st_mode)) {
                        sbuf->st_mode = S_IFDIR | S_IRWXU;
index b9ffd6fc05fb9e653fbe9437c77314743da9b04e..fd15c5c35851c3948f594c659b5d22b6ee9f94ec 100644 (file)
@@ -72,48 +72,44 @@ struct vfs_full_audit_private_data {
 
 /* Function prototypes */
 
-static int smb_full_audit_connect(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_connect(vfs_handle_struct *handle,
                         const char *svc, const char *user);
-static void smb_full_audit_disconnect(vfs_handle_struct *handle,
-                            connection_struct *conn);
+static void smb_full_audit_disconnect(vfs_handle_struct *handle);
 static SMB_BIG_UINT smb_full_audit_disk_free(vfs_handle_struct *handle,
-                                   connection_struct *conn, const char *path,
+                                   const char *path,
                                    BOOL small_query, SMB_BIG_UINT *bsize, 
                                    SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
 static int smb_full_audit_get_quota(struct vfs_handle_struct *handle,
-                          struct connection_struct *conn,
                           enum SMB_QUOTA_TYPE qtype, unid_t id,
                           SMB_DISK_QUOTA *qt);
 static int smb_full_audit_set_quota(struct vfs_handle_struct *handle,
-                          struct connection_struct *conn,
                           enum SMB_QUOTA_TYPE qtype, unid_t id,
                           SMB_DISK_QUOTA *qt);
 static int smb_full_audit_get_shadow_copy_data(struct vfs_handle_struct *handle,
                                 struct files_struct *fsp,
                                 SHADOW_COPY_DATA *shadow_copy_data, BOOL labels);
 static int smb_full_audit_statvfs(struct vfs_handle_struct *handle,
-                               struct connection_struct *conn,
                                const char *path,
                                struct vfs_statvfs_struct *statbuf);
 
-static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle, connection_struct *conn,
+static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle,
                          const char *fname, const char *mask, uint32 attr);
 static SMB_STRUCT_DIRENT *smb_full_audit_readdir(vfs_handle_struct *handle,
-                                   connection_struct *conn, SMB_STRUCT_DIR *dirp);
-static void smb_full_audit_seekdir(vfs_handle_struct *handle, connection_struct *conn,
+                                   SMB_STRUCT_DIR *dirp);
+static void smb_full_audit_seekdir(vfs_handle_struct *handle,
                        SMB_STRUCT_DIR *dirp, long offset);
-static long smb_full_audit_telldir(vfs_handle_struct *handle, connection_struct *conn,
+static long smb_full_audit_telldir(vfs_handle_struct *handle,
                        SMB_STRUCT_DIR *dirp);
-static void smb_full_audit_rewinddir(vfs_handle_struct *handle, connection_struct *conn,
+static void smb_full_audit_rewinddir(vfs_handle_struct *handle,
                        SMB_STRUCT_DIR *dirp);
-static int smb_full_audit_mkdir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_mkdir(vfs_handle_struct *handle,
                       const char *path, mode_t mode);
-static int smb_full_audit_rmdir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_rmdir(vfs_handle_struct *handle,
                       const char *path);
-static int smb_full_audit_closedir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_closedir(vfs_handle_struct *handle,
                          SMB_STRUCT_DIR *dirp);
-static int smb_full_audit_open(vfs_handle_struct *handle, connection_struct *conn,
-                     const char *fname, int flags, mode_t mode);
+static int smb_full_audit_open(vfs_handle_struct *handle,
+                     const char *fname, files_struct *fsp, int flags, mode_t mode);
 static int smb_full_audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd);
 static ssize_t smb_full_audit_read(vfs_handle_struct *handle, files_struct *fsp,
                          int fd, void *data, size_t n);
@@ -130,30 +126,30 @@ static ssize_t smb_full_audit_sendfile(vfs_handle_struct *handle, int tofd,
                              files_struct *fsp, int fromfd,
                              const DATA_BLOB *hdr, SMB_OFF_T offset,
                              size_t n);
-static int smb_full_audit_rename(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_rename(vfs_handle_struct *handle,
                        const char *oldname, const char *newname);
 static int smb_full_audit_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd);
-static int smb_full_audit_stat(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_stat(vfs_handle_struct *handle,
                      const char *fname, SMB_STRUCT_STAT *sbuf);
 static int smb_full_audit_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd,
                       SMB_STRUCT_STAT *sbuf);
-static int smb_full_audit_lstat(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_lstat(vfs_handle_struct *handle,
                       const char *path, SMB_STRUCT_STAT *sbuf);
-static int smb_full_audit_unlink(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_unlink(vfs_handle_struct *handle,
                        const char *path);
-static int smb_full_audit_chmod(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chmod(vfs_handle_struct *handle,
                       const char *path, mode_t mode);
 static int smb_full_audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd,
                        mode_t mode);
-static int smb_full_audit_chown(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chown(vfs_handle_struct *handle,
                       const char *path, uid_t uid, gid_t gid);
 static int smb_full_audit_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd,
                        uid_t uid, gid_t gid);
-static int smb_full_audit_chdir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chdir(vfs_handle_struct *handle,
                       const char *path);
-static char *smb_full_audit_getwd(vfs_handle_struct *handle, connection_struct *conn,
+static char *smb_full_audit_getwd(vfs_handle_struct *handle,
                         char *path);
-static int smb_full_audit_utime(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_utime(vfs_handle_struct *handle,
                       const char *path, struct utimbuf *times);
 static int smb_full_audit_ftruncate(vfs_handle_struct *handle, files_struct *fsp,
                           int fd, SMB_OFF_T len);
@@ -161,15 +157,15 @@ static BOOL smb_full_audit_lock(vfs_handle_struct *handle, files_struct *fsp, in
                       int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
 static BOOL smb_full_audit_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd,
                       SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid);
-static int smb_full_audit_symlink(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_symlink(vfs_handle_struct *handle,
                         const char *oldpath, const char *newpath);
-static int smb_full_audit_readlink(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_readlink(vfs_handle_struct *handle,
                          const char *path, char *buf, size_t bufsiz);
-static int smb_full_audit_link(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_link(vfs_handle_struct *handle,
                      const char *oldpath, const char *newpath);
-static int smb_full_audit_mknod(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_mknod(vfs_handle_struct *handle,
                       const char *pathname, mode_t mode, SMB_DEV_T dev);
-static char *smb_full_audit_realpath(vfs_handle_struct *handle, connection_struct *conn,
+static char *smb_full_audit_realpath(vfs_handle_struct *handle,
                            const char *path, char *resolved_path);
 static size_t smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
                                int fd, uint32 security_info,
@@ -183,120 +179,99 @@ static BOOL smb_full_audit_fset_nt_acl(vfs_handle_struct *handle, files_struct *
 static BOOL smb_full_audit_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
                             const char *name, uint32 security_info_sent,
                             SEC_DESC *psd);
-static int smb_full_audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chmod_acl(vfs_handle_struct *handle,
                           const char *path, mode_t mode);
 static int smb_full_audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp,
                            int fd, mode_t mode);
 static int smb_full_audit_sys_acl_get_entry(vfs_handle_struct *handle,
-                                  connection_struct *conn,
                                   SMB_ACL_T theacl, int entry_id,
                                   SMB_ACL_ENTRY_T *entry_p);
 static int smb_full_audit_sys_acl_get_tag_type(vfs_handle_struct *handle,
-                                     connection_struct *conn,
                                      SMB_ACL_ENTRY_T entry_d,
                                      SMB_ACL_TAG_T *tag_type_p);
 static int smb_full_audit_sys_acl_get_permset(vfs_handle_struct *handle,
-                                    connection_struct *conn,
                                     SMB_ACL_ENTRY_T entry_d,
                                     SMB_ACL_PERMSET_T *permset_p);
 static void * smb_full_audit_sys_acl_get_qualifier(vfs_handle_struct *handle,
-                                         connection_struct *conn,
                                          SMB_ACL_ENTRY_T entry_d);
 static SMB_ACL_T smb_full_audit_sys_acl_get_file(vfs_handle_struct *handle,
-                                       connection_struct *conn,
                                        const char *path_p,
                                        SMB_ACL_TYPE_T type);
 static SMB_ACL_T smb_full_audit_sys_acl_get_fd(vfs_handle_struct *handle,
                                      files_struct *fsp,
                                      int fd);
 static int smb_full_audit_sys_acl_clear_perms(vfs_handle_struct *handle,
-                                    connection_struct *conn,
                                     SMB_ACL_PERMSET_T permset);
 static int smb_full_audit_sys_acl_add_perm(vfs_handle_struct *handle,
-                                 connection_struct *conn,
                                  SMB_ACL_PERMSET_T permset,
                                  SMB_ACL_PERM_T perm);
 static char * smb_full_audit_sys_acl_to_text(vfs_handle_struct *handle,
-                                   connection_struct *conn, SMB_ACL_T theacl,
+                                   SMB_ACL_T theacl,
                                    ssize_t *plen);
 static SMB_ACL_T smb_full_audit_sys_acl_init(vfs_handle_struct *handle,
-                                   connection_struct *conn,
                                    int count);
 static int smb_full_audit_sys_acl_create_entry(vfs_handle_struct *handle,
-                                     connection_struct *conn, SMB_ACL_T *pacl,
+                                     SMB_ACL_T *pacl,
                                      SMB_ACL_ENTRY_T *pentry);
 static int smb_full_audit_sys_acl_set_tag_type(vfs_handle_struct *handle,
-                                     connection_struct *conn,
                                      SMB_ACL_ENTRY_T entry,
                                      SMB_ACL_TAG_T tagtype);
 static int smb_full_audit_sys_acl_set_qualifier(vfs_handle_struct *handle,
-                                      connection_struct *conn,
                                       SMB_ACL_ENTRY_T entry,
                                       void *qual);
 static int smb_full_audit_sys_acl_set_permset(vfs_handle_struct *handle,
-                                    connection_struct *conn,
                                     SMB_ACL_ENTRY_T entry,
                                     SMB_ACL_PERMSET_T permset);
 static int smb_full_audit_sys_acl_valid(vfs_handle_struct *handle,
-                              connection_struct *conn,
                               SMB_ACL_T theacl );
 static int smb_full_audit_sys_acl_set_file(vfs_handle_struct *handle,
-                                 connection_struct *conn,
                                  const char *name, SMB_ACL_TYPE_T acltype,
                                  SMB_ACL_T theacl);
 static int smb_full_audit_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
                                int fd, SMB_ACL_T theacl);
 static int smb_full_audit_sys_acl_delete_def_file(vfs_handle_struct *handle,
-                                        connection_struct *conn,
                                         const char *path);
 static int smb_full_audit_sys_acl_get_perm(vfs_handle_struct *handle,
-                                 connection_struct *conn,
                                  SMB_ACL_PERMSET_T permset,
                                  SMB_ACL_PERM_T perm);
 static int smb_full_audit_sys_acl_free_text(vfs_handle_struct *handle,
-                                  connection_struct *conn,
                                   char *text);
 static int smb_full_audit_sys_acl_free_acl(vfs_handle_struct *handle,
-                                 connection_struct *conn,
                                  SMB_ACL_T posix_acl);
 static int smb_full_audit_sys_acl_free_qualifier(vfs_handle_struct *handle,
-                                       connection_struct *conn,
                                        void *qualifier,
                                        SMB_ACL_TAG_T tagtype);
 static ssize_t smb_full_audit_getxattr(struct vfs_handle_struct *handle,
-                             struct connection_struct *conn, const char *path,
+                             const char *path,
                              const char *name, void *value, size_t size);
 static ssize_t smb_full_audit_lgetxattr(struct vfs_handle_struct *handle,
-                              struct connection_struct *conn,
                               const char *path, const char *name,
                               void *value, size_t size);
 static ssize_t smb_full_audit_fgetxattr(struct vfs_handle_struct *handle,
                               struct files_struct *fsp, int fd,
                               const char *name, void *value, size_t size);
 static ssize_t smb_full_audit_listxattr(struct vfs_handle_struct *handle,
-                              struct connection_struct *conn,
                               const char *path, char *list, size_t size);
 static ssize_t smb_full_audit_llistxattr(struct vfs_handle_struct *handle,
-                               struct connection_struct *conn,
                                const char *path, char *list, size_t size);
 static ssize_t smb_full_audit_flistxattr(struct vfs_handle_struct *handle,
                                struct files_struct *fsp, int fd, char *list,
                                size_t size);
 static int smb_full_audit_removexattr(struct vfs_handle_struct *handle,
-                            struct connection_struct *conn, const char *path,
+                            const char *path,
                             const char *name);
 static int smb_full_audit_lremovexattr(struct vfs_handle_struct *handle,
-                             struct connection_struct *conn, const char *path,
+                             const char *path,
                              const char *name);
 static int smb_full_audit_fremovexattr(struct vfs_handle_struct *handle,
                              struct files_struct *fsp, int fd,
                              const char *name);
 static int smb_full_audit_setxattr(struct vfs_handle_struct *handle,
-                         struct connection_struct *conn, const char *path,
+                         const char *path,
                          const char *name, const void *value, size_t size,
                          int flags);
 static int smb_full_audit_lsetxattr(struct vfs_handle_struct *handle,
-                          struct connection_struct *conn, const char *path,
+                          const char *path,
                           const char *name, const void *value, size_t size,
                           int flags);
 static int smb_full_audit_fsetxattr(struct vfs_handle_struct *handle,
@@ -666,10 +641,15 @@ static int audit_syslog_priority(vfs_handle_struct *handle)
 static char *audit_prefix(connection_struct *conn)
 {
        static pstring prefix;
+       extern userdom_struct current_user_info;
 
        pstrcpy(prefix, lp_parm_const_string(SNUM(conn), "full_audit",
                                             "prefix", "%u|%I"));
-       standard_sub_snum(SNUM(conn), prefix, sizeof(prefix)-1);
+       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                             conn->connectpath, conn->gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             prefix, sizeof(prefix));
        return prefix;
 }
 
@@ -811,7 +791,7 @@ static void free_private_data(void **p_data)
 /* Implementation of vfs_ops.  Pass everything on to the default
    operation but log event first. */
 
-static int smb_full_audit_connect(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_connect(vfs_handle_struct *handle,
                         const char *svc, const char *user)
 {
        int result;
@@ -832,17 +812,17 @@ static int smb_full_audit_connect(vfs_handle_struct *handle, connection_struct *
        openlog("smbd_audit", 0, audit_syslog_facility(handle));
 
        init_bitmap(&pd->success_ops,
-                   lp_parm_string_list(SNUM(conn), "full_audit", "success",
+                   lp_parm_string_list(SNUM(handle->conn), "full_audit", "success",
                                        none));
        init_bitmap(&pd->failure_ops,
-                   lp_parm_string_list(SNUM(conn), "full_audit", "failure",
+                   lp_parm_string_list(SNUM(handle->conn), "full_audit", "failure",
                                        all));
 
        /* Store the private data. */
        SMB_VFS_HANDLE_SET_DATA(handle, pd, free_private_data,
                                struct vfs_full_audit_private_data, return -1);
 
-       result = SMB_VFS_NEXT_CONNECT(handle, conn, svc, user);
+       result = SMB_VFS_NEXT_CONNECT(handle, svc, user);
 
        do_log(SMB_VFS_OP_CONNECT, True, handle,
               "%s", svc);
@@ -850,13 +830,12 @@ static int smb_full_audit_connect(vfs_handle_struct *handle, connection_struct *
        return result;
 }
 
-static void smb_full_audit_disconnect(vfs_handle_struct *handle,
-                            connection_struct *conn)
+static void smb_full_audit_disconnect(vfs_handle_struct *handle)
 {
-       SMB_VFS_NEXT_DISCONNECT(handle, conn);
+       SMB_VFS_NEXT_DISCONNECT(handle);
 
        do_log(SMB_VFS_OP_DISCONNECT, True, handle,
-              "%s", lp_servicename(SNUM(conn)));
+              "%s", lp_servicename(SNUM(handle->conn)));
 
        /* The bitmaps will be disconnected when the private
           data is deleted. */
@@ -865,13 +844,13 @@ static void smb_full_audit_disconnect(vfs_handle_struct *handle,
 }
 
 static SMB_BIG_UINT smb_full_audit_disk_free(vfs_handle_struct *handle,
-                                   connection_struct *conn, const char *path,
+                                   const char *path,
                                    BOOL small_query, SMB_BIG_UINT *bsize, 
                                    SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
 {
        SMB_BIG_UINT result;
 
-       result = SMB_VFS_NEXT_DISK_FREE(handle, conn, path, small_query, bsize,
+       result = SMB_VFS_NEXT_DISK_FREE(handle, path, small_query, bsize,
                                        dfree, dsize);
 
        /* Don't have a reasonable notion of failure here */
@@ -882,13 +861,12 @@ static SMB_BIG_UINT smb_full_audit_disk_free(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_get_quota(struct vfs_handle_struct *handle,
-                          struct connection_struct *conn,
                           enum SMB_QUOTA_TYPE qtype, unid_t id,
                           SMB_DISK_QUOTA *qt)
 {
        int result;
 
-       result = SMB_VFS_NEXT_GET_QUOTA(handle, conn, qtype, id, qt);
+       result = SMB_VFS_NEXT_GET_QUOTA(handle, qtype, id, qt);
 
        do_log(SMB_VFS_OP_GET_QUOTA, (result >= 0), handle, "");
 
@@ -897,13 +875,12 @@ static int smb_full_audit_get_quota(struct vfs_handle_struct *handle,
 
        
 static int smb_full_audit_set_quota(struct vfs_handle_struct *handle,
-                          struct connection_struct *conn,
                           enum SMB_QUOTA_TYPE qtype, unid_t id,
                           SMB_DISK_QUOTA *qt)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, qt);
+       result = SMB_VFS_NEXT_SET_QUOTA(handle, qtype, id, qt);
 
        do_log(SMB_VFS_OP_SET_QUOTA, (result >= 0), handle, "");
 
@@ -924,25 +901,24 @@ static int smb_full_audit_get_shadow_copy_data(struct vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_statvfs(struct vfs_handle_struct *handle,
-                               struct connection_struct *conn,
                                const char *path,
                                struct vfs_statvfs_struct *statbuf)
 {
        int result;
 
-       result = SMB_VFS_NEXT_STATVFS(handle, conn, path, statbuf);
+       result = SMB_VFS_NEXT_STATVFS(handle, path, statbuf);
 
        do_log(SMB_VFS_OP_STATVFS, (result >= 0), handle, "");
 
        return result;
 }
 
-static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle, connection_struct *conn,
+static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle,
                          const char *fname, const char *mask, uint32 attr)
 {
        SMB_STRUCT_DIR *result;
 
-       result = SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr);
+       result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
 
        do_log(SMB_VFS_OP_OPENDIR, (result != NULL), handle, "%s", fname);
 
@@ -950,11 +926,11 @@ static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle, connect
 }
 
 static SMB_STRUCT_DIRENT *smb_full_audit_readdir(vfs_handle_struct *handle,
-                                   connection_struct *conn, SMB_STRUCT_DIR *dirp)
+                                   SMB_STRUCT_DIR *dirp)
 {
        SMB_STRUCT_DIRENT *result;
 
-       result = SMB_VFS_NEXT_READDIR(handle, conn, dirp);
+       result = SMB_VFS_NEXT_READDIR(handle, dirp);
 
        /* This operation has no reasonable error condition
         * (End of dir is also failure), so always succeed.
@@ -964,78 +940,78 @@ static SMB_STRUCT_DIRENT *smb_full_audit_readdir(vfs_handle_struct *handle,
        return result;
 }
 
-static void smb_full_audit_seekdir(vfs_handle_struct *handle, connection_struct *conn,
+static void smb_full_audit_seekdir(vfs_handle_struct *handle,
                        SMB_STRUCT_DIR *dirp, long offset)
 {
-       SMB_VFS_NEXT_SEEKDIR(handle, conn, dirp, offset);
+       SMB_VFS_NEXT_SEEKDIR(handle, dirp, offset);
 
        do_log(SMB_VFS_OP_SEEKDIR, True, handle, "");
        return;
 }
 
-static long smb_full_audit_telldir(vfs_handle_struct *handle, connection_struct *conn,
+static long smb_full_audit_telldir(vfs_handle_struct *handle,
                        SMB_STRUCT_DIR *dirp)
 {
        long result;
 
-       result = SMB_VFS_NEXT_TELLDIR(handle, conn, dirp);
+       result = SMB_VFS_NEXT_TELLDIR(handle, dirp);
 
        do_log(SMB_VFS_OP_TELLDIR, True, handle, "");
 
        return result;
 }
 
-static void smb_full_audit_rewinddir(vfs_handle_struct *handle, connection_struct *conn,
+static void smb_full_audit_rewinddir(vfs_handle_struct *handle,
                        SMB_STRUCT_DIR *dirp)
 {
-       SMB_VFS_NEXT_REWINDDIR(handle, conn, dirp);
+       SMB_VFS_NEXT_REWINDDIR(handle, dirp);
 
        do_log(SMB_VFS_OP_REWINDDIR, True, handle, "");
        return;
 }
 
-static int smb_full_audit_mkdir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_mkdir(vfs_handle_struct *handle,
                       const char *path, mode_t mode)
 {
        int result;
        
-       result = SMB_VFS_NEXT_MKDIR(handle, conn, path, mode);
+       result = SMB_VFS_NEXT_MKDIR(handle, path, mode);
        
        do_log(SMB_VFS_OP_MKDIR, (result >= 0), handle, "%s", path);
 
        return result;
 }
 
-static int smb_full_audit_rmdir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_rmdir(vfs_handle_struct *handle,
                       const char *path)
 {
        int result;
        
-       result = SMB_VFS_NEXT_RMDIR(handle, conn, path);
+       result = SMB_VFS_NEXT_RMDIR(handle, path);
 
        do_log(SMB_VFS_OP_RMDIR, (result >= 0), handle, "%s", path);
 
        return result;
 }
 
-static int smb_full_audit_closedir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_closedir(vfs_handle_struct *handle,
                          SMB_STRUCT_DIR *dirp)
 {
        int result;
 
-       result = SMB_VFS_NEXT_CLOSEDIR(handle, conn, dirp);
+       result = SMB_VFS_NEXT_CLOSEDIR(handle, dirp);
        
        do_log(SMB_VFS_OP_CLOSEDIR, (result >= 0), handle, "");
 
        return result;
 }
 
-static int smb_full_audit_open(vfs_handle_struct *handle, connection_struct *conn,
-                     const char *fname, int flags, mode_t mode)
+static int smb_full_audit_open(vfs_handle_struct *handle,
+                     const char *fname, files_struct *fsp, int flags, mode_t mode)
 {
        int result;
        
-       result = SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
+       result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
 
        do_log(SMB_VFS_OP_OPEN, (result >= 0), handle, "%s|%s",
               ((flags & O_WRONLY) || (flags & O_RDWR))?"w":"r",
@@ -1133,12 +1109,12 @@ static ssize_t smb_full_audit_sendfile(vfs_handle_struct *handle, int tofd,
        return result;
 }
 
-static int smb_full_audit_rename(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_rename(vfs_handle_struct *handle,
                        const char *oldname, const char *newname)
 {
        int result;
        
-       result = SMB_VFS_NEXT_RENAME(handle, conn, oldname, newname);
+       result = SMB_VFS_NEXT_RENAME(handle, oldname, newname);
 
        do_log(SMB_VFS_OP_RENAME, (result >= 0), handle, "%s|%s", oldname, newname);
 
@@ -1156,12 +1132,12 @@ static int smb_full_audit_fsync(vfs_handle_struct *handle, files_struct *fsp, in
        return result;    
 }
 
-static int smb_full_audit_stat(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_stat(vfs_handle_struct *handle,
                      const char *fname, SMB_STRUCT_STAT *sbuf)
 {
        int result;
        
-       result = SMB_VFS_NEXT_STAT(handle, conn, fname, sbuf);
+       result = SMB_VFS_NEXT_STAT(handle, fname, sbuf);
 
        do_log(SMB_VFS_OP_STAT, (result >= 0), handle, "%s", fname);
 
@@ -1180,36 +1156,36 @@ static int smb_full_audit_fstat(vfs_handle_struct *handle, files_struct *fsp, in
        return result;
 }
 
-static int smb_full_audit_lstat(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_lstat(vfs_handle_struct *handle,
                       const char *path, SMB_STRUCT_STAT *sbuf)
 {
        int result;
        
-       result = SMB_VFS_NEXT_LSTAT(handle, conn, path, sbuf);
+       result = SMB_VFS_NEXT_LSTAT(handle, path, sbuf);
 
        do_log(SMB_VFS_OP_LSTAT, (result >= 0), handle, "%s", path);
 
        return result;    
 }
 
-static int smb_full_audit_unlink(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_unlink(vfs_handle_struct *handle,
                        const char *path)
 {
        int result;
        
-       result = SMB_VFS_NEXT_UNLINK(handle, conn, path);
+       result = SMB_VFS_NEXT_UNLINK(handle, path);
 
        do_log(SMB_VFS_OP_UNLINK, (result >= 0), handle, "%s", path);
 
        return result;
 }
 
-static int smb_full_audit_chmod(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chmod(vfs_handle_struct *handle,
                       const char *path, mode_t mode)
 {
        int result;
 
-       result = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode);
+       result = SMB_VFS_NEXT_CHMOD(handle, path, mode);
 
        do_log(SMB_VFS_OP_CHMOD, (result >= 0), handle, "%s|%o", path, mode);
 
@@ -1229,12 +1205,12 @@ static int smb_full_audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, i
        return result;
 }
 
-static int smb_full_audit_chown(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chown(vfs_handle_struct *handle,
                       const char *path, uid_t uid, gid_t gid)
 {
        int result;
 
-       result = SMB_VFS_NEXT_CHOWN(handle, conn, path, uid, gid);
+       result = SMB_VFS_NEXT_CHOWN(handle, path, uid, gid);
 
        do_log(SMB_VFS_OP_CHOWN, (result >= 0), handle, "%s|%ld|%ld",
               path, (long int)uid, (long int)gid);
@@ -1255,36 +1231,36 @@ static int smb_full_audit_fchown(vfs_handle_struct *handle, files_struct *fsp, i
        return result;
 }
 
-static int smb_full_audit_chdir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chdir(vfs_handle_struct *handle,
                       const char *path)
 {
        int result;
 
-       result = SMB_VFS_NEXT_CHDIR(handle, conn, path);
+       result = SMB_VFS_NEXT_CHDIR(handle, path);
 
        do_log(SMB_VFS_OP_CHDIR, (result >= 0), handle, "chdir|%s", path);
 
        return result;
 }
 
-static char *smb_full_audit_getwd(vfs_handle_struct *handle, connection_struct *conn,
+static char *smb_full_audit_getwd(vfs_handle_struct *handle,
                         char *path)
 {
        char *result;
 
-       result = SMB_VFS_NEXT_GETWD(handle, conn, path);
+       result = SMB_VFS_NEXT_GETWD(handle, path);
        
        do_log(SMB_VFS_OP_GETWD, (result != NULL), handle, "%s", path);
 
        return result;
 }
 
-static int smb_full_audit_utime(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_utime(vfs_handle_struct *handle,
                       const char *path, struct utimbuf *times)
 {
        int result;
 
-       result = SMB_VFS_NEXT_UTIME(handle, conn, path, times);
+       result = SMB_VFS_NEXT_UTIME(handle, path, times);
 
        do_log(SMB_VFS_OP_UTIME, (result >= 0), handle, "%s", path);
 
@@ -1328,12 +1304,12 @@ static BOOL smb_full_audit_getlock(vfs_handle_struct *handle, files_struct *fsp,
        return result;
 }
 
-static int smb_full_audit_symlink(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_symlink(vfs_handle_struct *handle,
                         const char *oldpath, const char *newpath)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath);
+       result = SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath);
 
        do_log(SMB_VFS_OP_SYMLINK, (result >= 0), handle,
               "%s|%s", oldpath, newpath);
@@ -1341,24 +1317,24 @@ static int smb_full_audit_symlink(vfs_handle_struct *handle, connection_struct *
        return result;
 }
 
-static int smb_full_audit_readlink(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_readlink(vfs_handle_struct *handle,
                          const char *path, char *buf, size_t bufsiz)
 {
        int result;
 
-       result = SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz);
+       result = SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz);
 
        do_log(SMB_VFS_OP_READLINK, (result >= 0), handle, "%s", path);
 
        return result;
 }
 
-static int smb_full_audit_link(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_link(vfs_handle_struct *handle,
                      const char *oldpath, const char *newpath)
 {
        int result;
 
-       result = SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath);
+       result = SMB_VFS_NEXT_LINK(handle, oldpath, newpath);
 
        do_log(SMB_VFS_OP_LINK, (result >= 0), handle,
               "%s|%s", oldpath, newpath);
@@ -1366,24 +1342,24 @@ static int smb_full_audit_link(vfs_handle_struct *handle, connection_struct *con
        return result;
 }
 
-static int smb_full_audit_mknod(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_mknod(vfs_handle_struct *handle,
                       const char *pathname, mode_t mode, SMB_DEV_T dev)
 {
        int result;
 
-       result = SMB_VFS_NEXT_MKNOD(handle, conn, pathname, mode, dev);
+       result = SMB_VFS_NEXT_MKNOD(handle, pathname, mode, dev);
 
        do_log(SMB_VFS_OP_MKNOD, (result >= 0), handle, "%s", pathname);
 
        return result;
 }
 
-static char *smb_full_audit_realpath(vfs_handle_struct *handle, connection_struct *conn,
+static char *smb_full_audit_realpath(vfs_handle_struct *handle,
                            const char *path, char *resolved_path)
 {
        char *result;
 
-       result = SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path);
+       result = SMB_VFS_NEXT_REALPATH(handle, path, resolved_path);
 
        do_log(SMB_VFS_OP_REALPATH, (result != NULL), handle, "%s", path);
 
@@ -1448,12 +1424,12 @@ static BOOL smb_full_audit_set_nt_acl(vfs_handle_struct *handle, files_struct *f
        return result;
 }
 
-static int smb_full_audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chmod_acl(vfs_handle_struct *handle,
                           const char *path, mode_t mode)
 {
        int result;
        
-       result = SMB_VFS_NEXT_CHMOD_ACL(handle, conn, path, mode);
+       result = SMB_VFS_NEXT_CHMOD_ACL(handle, path, mode);
 
        do_log(SMB_VFS_OP_CHMOD_ACL, (result >= 0), handle,
               "%s|%o", path, mode);
@@ -1475,13 +1451,13 @@ static int smb_full_audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fs
 }
 
 static int smb_full_audit_sys_acl_get_entry(vfs_handle_struct *handle,
-                                  connection_struct *conn,
+
                                   SMB_ACL_T theacl, int entry_id,
                                   SMB_ACL_ENTRY_T *entry_p)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_GET_ENTRY(handle, conn, theacl, entry_id,
+       result = SMB_VFS_NEXT_SYS_ACL_GET_ENTRY(handle, theacl, entry_id,
                                                entry_p);
 
        do_log(SMB_VFS_OP_SYS_ACL_GET_ENTRY, (result >= 0), handle,
@@ -1491,13 +1467,13 @@ static int smb_full_audit_sys_acl_get_entry(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_sys_acl_get_tag_type(vfs_handle_struct *handle,
-                                     connection_struct *conn,
+
                                      SMB_ACL_ENTRY_T entry_d,
                                      SMB_ACL_TAG_T *tag_type_p)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_GET_TAG_TYPE(handle, conn, entry_d,
+       result = SMB_VFS_NEXT_SYS_ACL_GET_TAG_TYPE(handle, entry_d,
                                                   tag_type_p);
 
        do_log(SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE, (result >= 0), handle,
@@ -1507,13 +1483,13 @@ static int smb_full_audit_sys_acl_get_tag_type(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_sys_acl_get_permset(vfs_handle_struct *handle,
-                                    connection_struct *conn,
+
                                     SMB_ACL_ENTRY_T entry_d,
                                     SMB_ACL_PERMSET_T *permset_p)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_GET_PERMSET(handle, conn, entry_d,
+       result = SMB_VFS_NEXT_SYS_ACL_GET_PERMSET(handle, entry_d,
                                                  permset_p);
 
        do_log(SMB_VFS_OP_SYS_ACL_GET_PERMSET, (result >= 0), handle,
@@ -1523,12 +1499,12 @@ static int smb_full_audit_sys_acl_get_permset(vfs_handle_struct *handle,
 }
 
 static void * smb_full_audit_sys_acl_get_qualifier(vfs_handle_struct *handle,
-                                         connection_struct *conn,
+
                                          SMB_ACL_ENTRY_T entry_d)
 {
        void *result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_GET_QUALIFIER(handle, conn, entry_d);
+       result = SMB_VFS_NEXT_SYS_ACL_GET_QUALIFIER(handle, entry_d);
 
        do_log(SMB_VFS_OP_SYS_ACL_GET_QUALIFIER, (result != NULL), handle,
               "");
@@ -1537,13 +1513,12 @@ static void * smb_full_audit_sys_acl_get_qualifier(vfs_handle_struct *handle,
 }
 
 static SMB_ACL_T smb_full_audit_sys_acl_get_file(vfs_handle_struct *handle,
-                                       connection_struct *conn,
                                        const char *path_p,
                                        SMB_ACL_TYPE_T type)
 {
        SMB_ACL_T result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, path_p, type);
+       result = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, path_p, type);
 
        do_log(SMB_VFS_OP_SYS_ACL_GET_FILE, (result != NULL), handle,
               "%s", path_p);
@@ -1565,12 +1540,12 @@ static SMB_ACL_T smb_full_audit_sys_acl_get_fd(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_sys_acl_clear_perms(vfs_handle_struct *handle,
-                                    connection_struct *conn,
+
                                     SMB_ACL_PERMSET_T permset)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_CLEAR_PERMS(handle, conn, permset);
+       result = SMB_VFS_NEXT_SYS_ACL_CLEAR_PERMS(handle, permset);
 
        do_log(SMB_VFS_OP_SYS_ACL_CLEAR_PERMS, (result >= 0), handle,
               "");
@@ -1579,13 +1554,13 @@ static int smb_full_audit_sys_acl_clear_perms(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_sys_acl_add_perm(vfs_handle_struct *handle,
-                                 connection_struct *conn,
+
                                  SMB_ACL_PERMSET_T permset,
                                  SMB_ACL_PERM_T perm)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_ADD_PERM(handle, conn, permset, perm);
+       result = SMB_VFS_NEXT_SYS_ACL_ADD_PERM(handle, permset, perm);
 
        do_log(SMB_VFS_OP_SYS_ACL_ADD_PERM, (result >= 0), handle,
               "");
@@ -1594,12 +1569,12 @@ static int smb_full_audit_sys_acl_add_perm(vfs_handle_struct *handle,
 }
 
 static char * smb_full_audit_sys_acl_to_text(vfs_handle_struct *handle,
-                                   connection_struct *conn, SMB_ACL_T theacl,
+                                   SMB_ACL_T theacl,
                                    ssize_t *plen)
 {
        char * result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_TO_TEXT(handle, conn, theacl, plen);
+       result = SMB_VFS_NEXT_SYS_ACL_TO_TEXT(handle, theacl, plen);
 
        do_log(SMB_VFS_OP_SYS_ACL_TO_TEXT, (result != NULL), handle,
               "");
@@ -1608,12 +1583,12 @@ static char * smb_full_audit_sys_acl_to_text(vfs_handle_struct *handle,
 }
 
 static SMB_ACL_T smb_full_audit_sys_acl_init(vfs_handle_struct *handle,
-                                   connection_struct *conn,
+
                                    int count)
 {
        SMB_ACL_T result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_INIT(handle, conn, count);
+       result = SMB_VFS_NEXT_SYS_ACL_INIT(handle, count);
 
        do_log(SMB_VFS_OP_SYS_ACL_INIT, (result != NULL), handle,
               "");
@@ -1622,12 +1597,12 @@ static SMB_ACL_T smb_full_audit_sys_acl_init(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_sys_acl_create_entry(vfs_handle_struct *handle,
-                                     connection_struct *conn, SMB_ACL_T *pacl,
+                                     SMB_ACL_T *pacl,
                                      SMB_ACL_ENTRY_T *pentry)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_CREATE_ENTRY(handle, conn, pacl, pentry);
+       result = SMB_VFS_NEXT_SYS_ACL_CREATE_ENTRY(handle, pacl, pentry);
 
        do_log(SMB_VFS_OP_SYS_ACL_CREATE_ENTRY, (result >= 0), handle,
               "");
@@ -1636,13 +1611,13 @@ static int smb_full_audit_sys_acl_create_entry(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_sys_acl_set_tag_type(vfs_handle_struct *handle,
-                                     connection_struct *conn,
+
                                      SMB_ACL_ENTRY_T entry,
                                      SMB_ACL_TAG_T tagtype)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_SET_TAG_TYPE(handle, conn, entry,
+       result = SMB_VFS_NEXT_SYS_ACL_SET_TAG_TYPE(handle, entry,
                                                   tagtype);
 
        do_log(SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE, (result >= 0), handle,
@@ -1652,13 +1627,13 @@ static int smb_full_audit_sys_acl_set_tag_type(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_sys_acl_set_qualifier(vfs_handle_struct *handle,
-                                      connection_struct *conn,
+
                                       SMB_ACL_ENTRY_T entry,
                                       void *qual)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_SET_QUALIFIER(handle, conn, entry, qual);
+       result = SMB_VFS_NEXT_SYS_ACL_SET_QUALIFIER(handle, entry, qual);
 
        do_log(SMB_VFS_OP_SYS_ACL_SET_QUALIFIER, (result >= 0), handle,
               "");
@@ -1667,13 +1642,13 @@ static int smb_full_audit_sys_acl_set_qualifier(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_sys_acl_set_permset(vfs_handle_struct *handle,
-                                    connection_struct *conn,
+
                                     SMB_ACL_ENTRY_T entry,
                                     SMB_ACL_PERMSET_T permset)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_SET_PERMSET(handle, conn, entry, permset);
+       result = SMB_VFS_NEXT_SYS_ACL_SET_PERMSET(handle, entry, permset);
 
        do_log(SMB_VFS_OP_SYS_ACL_SET_PERMSET, (result >= 0), handle,
               "");
@@ -1682,12 +1657,12 @@ static int smb_full_audit_sys_acl_set_permset(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_sys_acl_valid(vfs_handle_struct *handle,
-                              connection_struct *conn,
+
                               SMB_ACL_T theacl )
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_VALID(handle, conn, theacl);
+       result = SMB_VFS_NEXT_SYS_ACL_VALID(handle, theacl);
 
        do_log(SMB_VFS_OP_SYS_ACL_VALID, (result >= 0), handle,
               "");
@@ -1696,13 +1671,13 @@ static int smb_full_audit_sys_acl_valid(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_sys_acl_set_file(vfs_handle_struct *handle,
-                                 connection_struct *conn,
+
                                  const char *name, SMB_ACL_TYPE_T acltype,
                                  SMB_ACL_T theacl)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, name, acltype,
+       result = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, name, acltype,
                                               theacl);
 
        do_log(SMB_VFS_OP_SYS_ACL_SET_FILE, (result >= 0), handle,
@@ -1725,12 +1700,12 @@ static int smb_full_audit_sys_acl_set_fd(vfs_handle_struct *handle, files_struct
 }
 
 static int smb_full_audit_sys_acl_delete_def_file(vfs_handle_struct *handle,
-                                        connection_struct *conn,
+
                                         const char *path)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, path);
+       result = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, path);
 
        do_log(SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, (result >= 0), handle,
               "%s", path);
@@ -1739,13 +1714,13 @@ static int smb_full_audit_sys_acl_delete_def_file(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_sys_acl_get_perm(vfs_handle_struct *handle,
-                                 connection_struct *conn,
+
                                  SMB_ACL_PERMSET_T permset,
                                  SMB_ACL_PERM_T perm)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_GET_PERM(handle, conn, permset, perm);
+       result = SMB_VFS_NEXT_SYS_ACL_GET_PERM(handle, permset, perm);
 
        do_log(SMB_VFS_OP_SYS_ACL_GET_PERM, (result >= 0), handle,
               "");
@@ -1754,12 +1729,12 @@ static int smb_full_audit_sys_acl_get_perm(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_sys_acl_free_text(vfs_handle_struct *handle,
-                                  connection_struct *conn,
+
                                   char *text)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_FREE_TEXT(handle, conn, text);
+       result = SMB_VFS_NEXT_SYS_ACL_FREE_TEXT(handle, text);
 
        do_log(SMB_VFS_OP_SYS_ACL_FREE_TEXT, (result >= 0), handle,
               "");
@@ -1768,12 +1743,12 @@ static int smb_full_audit_sys_acl_free_text(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_sys_acl_free_acl(vfs_handle_struct *handle,
-                                 connection_struct *conn,
+
                                  SMB_ACL_T posix_acl)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_FREE_ACL(handle, conn, posix_acl);
+       result = SMB_VFS_NEXT_SYS_ACL_FREE_ACL(handle, posix_acl);
 
        do_log(SMB_VFS_OP_SYS_ACL_FREE_ACL, (result >= 0), handle,
               "");
@@ -1782,13 +1757,12 @@ static int smb_full_audit_sys_acl_free_acl(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_sys_acl_free_qualifier(vfs_handle_struct *handle,
-                                       connection_struct *conn,
                                        void *qualifier,
                                        SMB_ACL_TAG_T tagtype)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYS_ACL_FREE_QUALIFIER(handle, conn, qualifier,
+       result = SMB_VFS_NEXT_SYS_ACL_FREE_QUALIFIER(handle, qualifier,
                                                     tagtype);
 
        do_log(SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER, (result >= 0), handle,
@@ -1798,12 +1772,12 @@ static int smb_full_audit_sys_acl_free_qualifier(vfs_handle_struct *handle,
 }
 
 static ssize_t smb_full_audit_getxattr(struct vfs_handle_struct *handle,
-                             struct connection_struct *conn, const char *path,
+                             const char *path,
                              const char *name, void *value, size_t size)
 {
        ssize_t result;
 
-       result = SMB_VFS_NEXT_GETXATTR(handle, conn, path, name, value, size);
+       result = SMB_VFS_NEXT_GETXATTR(handle, path, name, value, size);
 
        do_log(SMB_VFS_OP_GETXATTR, (result >= 0), handle,
               "%s|%s", path, name);
@@ -1812,13 +1786,12 @@ static ssize_t smb_full_audit_getxattr(struct vfs_handle_struct *handle,
 }
 
 static ssize_t smb_full_audit_lgetxattr(struct vfs_handle_struct *handle,
-                              struct connection_struct *conn,
                               const char *path, const char *name,
                               void *value, size_t size)
 {
        ssize_t result;
 
-       result = SMB_VFS_NEXT_LGETXATTR(handle, conn, path, name, value, size);
+       result = SMB_VFS_NEXT_LGETXATTR(handle, path, name, value, size);
 
        do_log(SMB_VFS_OP_LGETXATTR, (result >= 0), handle,
               "%s|%s", path, name);
@@ -1841,12 +1814,11 @@ static ssize_t smb_full_audit_fgetxattr(struct vfs_handle_struct *handle,
 }
 
 static ssize_t smb_full_audit_listxattr(struct vfs_handle_struct *handle,
-                              struct connection_struct *conn,
                               const char *path, char *list, size_t size)
 {
        ssize_t result;
 
-       result = SMB_VFS_NEXT_LISTXATTR(handle, conn, path, list, size);
+       result = SMB_VFS_NEXT_LISTXATTR(handle, path, list, size);
 
        do_log(SMB_VFS_OP_LISTXATTR, (result >= 0), handle, "%s", path);
 
@@ -1854,12 +1826,11 @@ static ssize_t smb_full_audit_listxattr(struct vfs_handle_struct *handle,
 }
 
 static ssize_t smb_full_audit_llistxattr(struct vfs_handle_struct *handle,
-                               struct connection_struct *conn,
                                const char *path, char *list, size_t size)
 {
        ssize_t result;
 
-       result = SMB_VFS_NEXT_LLISTXATTR(handle, conn, path, list, size);
+       result = SMB_VFS_NEXT_LLISTXATTR(handle, path, list, size);
 
        do_log(SMB_VFS_OP_LLISTXATTR, (result >= 0), handle, "%s", path);
 
@@ -1881,12 +1852,12 @@ static ssize_t smb_full_audit_flistxattr(struct vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_removexattr(struct vfs_handle_struct *handle,
-                            struct connection_struct *conn, const char *path,
+                            const char *path,
                             const char *name)
 {
        int result;
 
-       result = SMB_VFS_NEXT_REMOVEXATTR(handle, conn, path, name);
+       result = SMB_VFS_NEXT_REMOVEXATTR(handle, path, name);
 
        do_log(SMB_VFS_OP_REMOVEXATTR, (result >= 0), handle,
               "%s|%s", path, name);
@@ -1895,12 +1866,12 @@ static int smb_full_audit_removexattr(struct vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_lremovexattr(struct vfs_handle_struct *handle,
-                             struct connection_struct *conn, const char *path,
+                             const char *path,
                              const char *name)
 {
        int result;
 
-       result = SMB_VFS_NEXT_LREMOVEXATTR(handle, conn, path, name);
+       result = SMB_VFS_NEXT_LREMOVEXATTR(handle, path, name);
 
        do_log(SMB_VFS_OP_LREMOVEXATTR, (result >= 0), handle,
               "%s|%s", path, name);
@@ -1923,13 +1894,13 @@ static int smb_full_audit_fremovexattr(struct vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_setxattr(struct vfs_handle_struct *handle,
-                         struct connection_struct *conn, const char *path,
+                         const char *path,
                          const char *name, const void *value, size_t size,
                          int flags)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SETXATTR(handle, conn, path, name, value, size,
+       result = SMB_VFS_NEXT_SETXATTR(handle, path, name, value, size,
                                       flags);
 
        do_log(SMB_VFS_OP_SETXATTR, (result >= 0), handle,
@@ -1939,13 +1910,13 @@ static int smb_full_audit_setxattr(struct vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_lsetxattr(struct vfs_handle_struct *handle,
-                          struct connection_struct *conn, const char *path,
+                          const char *path,
                           const char *name, const void *value, size_t size,
                           int flags)
 {
        int result;
 
-       result = SMB_VFS_NEXT_LSETXATTR(handle, conn, path, name, value, size,
+       result = SMB_VFS_NEXT_LSETXATTR(handle, path, name, value, size,
                                        flags);
 
        do_log(SMB_VFS_OP_LSETXATTR, (result >= 0), handle,
index e9d4360cd8028f79b6b43acd84164e8d31faa26f..279160d966587a2b0353003e59a15d53cbf2d6f5 100644 (file)
@@ -172,11 +172,11 @@ static void atalk_rrmdir(TALLOC_CTX *ctx, char *path)
 
 /* Directory operations */
 
-SMB_STRUCT_DIR *atalk_opendir(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, const char *mask, uint32 attr)
+SMB_STRUCT_DIR *atalk_opendir(struct vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
 {
        SMB_STRUCT_DIR *ret = 0;
 
-       ret = SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr);
+       ret = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
 
        /*
         * when we try to perform delete operation upon file which has fork
@@ -187,19 +187,19 @@ SMB_STRUCT_DIR *atalk_opendir(struct vfs_handle_struct *handle, struct connectio
         * list then it would be nice to add one.
         */
 
-       atalk_add_to_list(&conn->hide_list);
-       atalk_add_to_list(&conn->veto_list);
+       atalk_add_to_list(&handle->conn->hide_list);
+       atalk_add_to_list(&handle->conn->veto_list);
 
        return ret;
 }
 
-static int atalk_rmdir(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path)
+static int atalk_rmdir(struct vfs_handle_struct *handle, const char *path)
 {
        BOOL add = False;
        TALLOC_CTX *ctx = 0;
        char *dpath;
 
-       if (!conn || !conn->origpath || !path) goto exit_rmdir;
+       if (!handle->conn->origpath || !path) goto exit_rmdir;
 
        /* due to there is no way to change bDeleteVetoFiles variable
         * from this module, gotta use talloc stuff..
@@ -211,19 +211,19 @@ static int atalk_rmdir(struct vfs_handle_struct *handle, struct connection_struc
                goto exit_rmdir;
 
        if (!(dpath = talloc_asprintf(ctx, "%s/%s%s", 
-         conn->origpath, path, add ? "/"APPLEDOUBLE : "")))
+         handle->conn->origpath, path, add ? "/"APPLEDOUBLE : "")))
                goto exit_rmdir;
 
        atalk_rrmdir(ctx, dpath);
 
 exit_rmdir:
        talloc_destroy(ctx);
-       return SMB_VFS_NEXT_RMDIR(handle, conn, path);
+       return SMB_VFS_NEXT_RMDIR(handle, path);
 }
 
 /* File operations */
 
-static int atalk_rename(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldname, const char *newname)
+static int atalk_rename(struct vfs_handle_struct *handle, const char *oldname, const char *newname)
 {
        int ret = 0;
        char *adbl_path = 0;
@@ -232,14 +232,14 @@ static int atalk_rename(struct vfs_handle_struct *handle, struct connection_stru
        SMB_STRUCT_STAT orig_info;
        TALLOC_CTX *ctx;
 
-       ret = SMB_VFS_NEXT_RENAME(handle, conn, oldname, newname);
+       ret = SMB_VFS_NEXT_RENAME(handle, oldname, newname);
 
-       if (!conn || !oldname) return ret;
+       if (!oldname) return ret;
 
        if (!(ctx = talloc_init("rename_file")))
                return ret;
 
-       if (atalk_build_paths(ctx, conn->origpath, oldname, &adbl_path, &orig_path, 
+       if (atalk_build_paths(ctx, handle->conn->origpath, oldname, &adbl_path, &orig_path,
          &adbl_info, &orig_info) != 0)
                return ret;
 
@@ -255,7 +255,7 @@ exit_rename:
        return ret;
 }
 
-static int atalk_unlink(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path)
+static int atalk_unlink(struct vfs_handle_struct *handle, const char *path)
 {
        int ret = 0, i;
        char *adbl_path = 0;
@@ -264,25 +264,25 @@ static int atalk_unlink(struct vfs_handle_struct *handle, struct connection_stru
        SMB_STRUCT_STAT orig_info;
        TALLOC_CTX *ctx;
 
-       ret = SMB_VFS_NEXT_UNLINK(handle, conn, path);
+       ret = SMB_VFS_NEXT_UNLINK(handle, path);
 
-       if (!conn || !path) return ret;
+       if (!path) return ret;
 
        /* no .AppleDouble sync if veto or hide list is empty,
         * otherwise "Cannot find the specified file" error will be caused
         */
 
-       if (!conn->veto_list) return ret;
-       if (!conn->hide_list) return ret;
+       if (!handle->conn->veto_list) return ret;
+       if (!handle->conn->hide_list) return ret;
 
-       for (i = 0; conn->veto_list[i].name; i ++) {
-               if (strstr(conn->veto_list[i].name, APPLEDOUBLE))
+       for (i = 0; handle->conn->veto_list[i].name; i ++) {
+               if (strstr(handle->conn->veto_list[i].name, APPLEDOUBLE))
                        break;
        }
 
-       if (!conn->veto_list[i].name) {
-               for (i = 0; conn->hide_list[i].name; i ++) {
-                       if (strstr(conn->hide_list[i].name, APPLEDOUBLE))
+       if (!handle->conn->veto_list[i].name) {
+               for (i = 0; handle->conn->hide_list[i].name; i ++) {
+                       if (strstr(handle->conn->hide_list[i].name, APPLEDOUBLE))
                                break;
                        else {
                                DEBUG(3, ("ATALK: %s is not hidden, skipped..\n",
@@ -295,7 +295,7 @@ static int atalk_unlink(struct vfs_handle_struct *handle, struct connection_stru
        if (!(ctx = talloc_init("unlink_file")))
                return ret;
 
-       if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, 
+       if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path,
          &adbl_info, &orig_info) != 0)
                return ret;
 
@@ -311,7 +311,7 @@ exit_unlink:
        return ret;
 }
 
-static int atalk_chmod(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode)
+static int atalk_chmod(struct vfs_handle_struct *handle, const char *path, mode_t mode)
 {
        int ret = 0;
        char *adbl_path = 0;
@@ -320,14 +320,14 @@ static int atalk_chmod(struct vfs_handle_struct *handle, struct connection_struc
        SMB_STRUCT_STAT orig_info;
        TALLOC_CTX *ctx;
 
-       ret = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode);
+       ret = SMB_VFS_NEXT_CHMOD(handle, path, mode);
 
-       if (!conn || !path) return ret;
+       if (!path) return ret;
 
        if (!(ctx = talloc_init("chmod_file")))
                return ret;
 
-       if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path,
+       if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path,
          &adbl_info, &orig_info) != 0)
                return ret;
 
@@ -343,7 +343,7 @@ exit_chmod:
        return ret;
 }
 
-static int atalk_chown(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, uid_t uid, gid_t gid)
+static int atalk_chown(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
 {
        int ret = 0;
        char *adbl_path = 0;
@@ -352,14 +352,14 @@ static int atalk_chown(struct vfs_handle_struct *handle, struct connection_struc
        SMB_STRUCT_STAT orig_info;
        TALLOC_CTX *ctx;
 
-       ret = SMB_VFS_NEXT_CHOWN(handle, conn, path, uid, gid);
+       ret = SMB_VFS_NEXT_CHOWN(handle, path, uid, gid);
 
-       if (!conn || !path) return ret;
+       if (!path) return ret;
 
        if (!(ctx = talloc_init("chown_file")))
                return ret;
 
-       if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path,
+       if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path,
          &adbl_info, &orig_info) != 0)
                return ret;
 
diff --git a/source/modules/vfs_prealloc.c b/source/modules/vfs_prealloc.c
new file mode 100644 (file)
index 0000000..94db642
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * XFS preallocation support module.
+ *
+ * Copyright (c) James Peach 2006
+ *
+ * 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"
+
+/* Extent preallocation module.
+ *
+ * The purpose of this module is to preallocate space on the filesystem when
+ * we have a good idea of how large files are supposed to be. This lets writes
+ * proceed without having to allocate new extents and results in better file
+ * layouts on disk.
+ *
+ * Currently only implemented for XFS. This module is based on an original idea
+ * and implementation by Sebastian Brings.
+ *
+ * Tunables.
+ *
+ *      prealloc: <ext>            Number of bytes to preallocate for a file with
+ *                         the matching extension.
+ *      prealloc:debug     Debug level at which to emit messages.
+ *
+ * Example.
+ *
+ *     prealloc:mpeg = 500M  # Preallocate *.mpeg to 500 MiB.
+ */
+
+#ifdef HAVE_XFS_LIBXFS_H
+#include <xfs/libxfs.h>
+#define lock_type xfs_flock64_t
+#else
+#define lock_type struct flock64
+#endif
+
+#define MODULE "prealloc"
+static int module_debug;
+
+static int preallocate_space(int fd, SMB_OFF_T size)
+{
+       lock_type fl = {0};
+       int err;
+
+       if (size <= 0) {
+               return 0;
+       }
+
+       fl.l_whence = SEEK_SET;
+       fl.l_start = 0;
+       fl.l_len = size;
+
+       /* IMPORTANT: We use RESVSP because we want the extents to be
+        * allocated, but we don't want the allocation to show up in
+        * st_size or persist after the close(2).
+        */
+
+#if defined(XFS_IOC_RESVSP64)
+       /* On Linux this comes in via libxfs.h. */
+       err = xfsctl(NULL, fd, XFS_IOC_RESVSP64, &fl);
+#elif defined(F_RESVSP64)
+       /* On IRIX, this comes from fcntl.h. */
+       err = fcntl(fd, F_RESVSP64, &fl);
+#else
+       err = -1;
+       errno = ENOSYS;
+#endif
+
+       if (err) {
+               DEBUG(module_debug,
+                       ("%s: preallocate failed on fd=%d size=%lld: %s\n",
+                       MODULE, fd, (long long)size, strerror(errno)));
+       }
+
+       return err;
+}
+
+static int prealloc_connect(
+                struct vfs_handle_struct *  handle,
+                const char *                service,
+                const char *                user)
+{
+           module_debug = lp_parm_int(SNUM(handle->conn),
+                                       MODULE, "debug", 100);
+
+           return SMB_VFS_NEXT_CONNECT(handle, service, user);
+}
+
+static int prealloc_open(vfs_handle_struct* handle,
+                       const char *        fname,
+                       files_struct *      fsp,
+                       int                 flags,
+                       mode_t              mode)
+{
+       int fd;
+       off64_t size = 0;
+
+       const char * dot;
+       char fext[10];
+
+       if (!(flags & (O_CREAT|O_TRUNC))) {
+               /* Caller is not intending to rewrite the file. Let's not mess
+                * with the allocation in this case.
+                */
+               goto normal_open;
+       }
+
+       *fext = '\0';
+       dot = strrchr(fname, '.');
+       if (dot && *++dot) {
+               if (strlen(dot) < sizeof(fext)) {
+                       strncpy(fext, dot, sizeof(fext));
+                       strnorm(fext, CASE_LOWER);
+               }
+       }
+
+       if (*fext == '\0') {
+               goto normal_open;
+       }
+
+       /* Syntax for specifying preallocation size is:
+        *      MODULE: <extension> = <size>
+        * where
+        *      <extension> is the file extension in lower case
+        *      <size> is a size like 10, 10K, 10M
+        */
+       size = conv_str_size(lp_parm_const_string(SNUM(handle->conn), MODULE,
+                                                   fext, NULL));
+       if (size <= 0) {
+               /* No need to preallocate this file. */
+               goto normal_open;
+       }
+
+       fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       if (fd < 0) {
+               return fd;
+       }
+
+       /* Prellocate only if the file is being created or replaced. Note that
+        * Samba won't ever pass down O_TRUNC, which is why we have to handle
+        * truncate calls specially.
+        */
+       if ((flags & O_CREAT) || (flags & O_TRUNC)) {
+               SMB_OFF_T * psize;
+
+               psize = VFS_ADD_FSP_EXTENSION(handle, fsp, SMB_OFF_T);
+               if (psize == NULL || *psize == -1) {
+                       return fd;
+               }
+
+               DEBUG(module_debug,
+                       ("%s: preallocating %s (fd=%d) to %lld bytes\n",
+                       MODULE, fname, fd, (long long)size));
+
+               *psize = size;
+               if (preallocate_space(fd, *psize) < 0) {
+                       VFS_REMOVE_FSP_EXTENSION(handle, fsp);
+               }
+       }
+
+       return fd;
+
+normal_open:
+       /* We are not creating or replacing a file. Skip the
+        * preallocation.
+        */
+       DEBUG(module_debug, ("%s: skipping preallocation for %s\n",
+                   MODULE, fname));
+       return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+}
+
+static int prealloc_ftruncate(vfs_handle_struct * handle,
+                       files_struct *  fsp,
+                       int             fd,
+                       SMB_OFF_T       offset)
+{
+       SMB_OFF_T *psize;
+       int ret = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset);
+
+       /* Maintain the allocated space even in the face of truncates. */
+       if ((psize = VFS_FETCH_FSP_EXTENSION(handle, fsp))) {
+               preallocate_space(fd, *psize);
+       }
+
+       return ret;
+}
+
+static vfs_op_tuple prealloc_op_tuples[] = {
+       {SMB_VFS_OP(prealloc_open), SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(prealloc_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(prealloc_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT},
+       {NULL,  SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_prealloc_init(void)
+{
+       return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
+               MODULE, prealloc_op_tuples);
+}
+
index ee9e40c2fcaa7b51a6caab0af6161750d6eba993..e69f7dac0162cc67265f02c82b7ee42415c94aa7 100644 (file)
@@ -55,7 +55,6 @@
 
 #define MODULE_NAME "readonly"
 static int readonly_connect(vfs_handle_struct *handle, 
-                           connection_struct *conn, 
                            const char *service, 
                            const char *user)    
 {
@@ -71,10 +70,10 @@ static int readonly_connect(vfs_handle_struct *handle,
     time_t end_period   = get_date(period[1], &current_time);
 
     if ((current_time >= begin_period) && (current_time <= end_period)) {
-      conn->read_only = True;
+      handle->conn->read_only = True;
     }
 
-    return SMB_VFS_NEXT_CONNECT(handle, conn, service, user);
+    return SMB_VFS_NEXT_CONNECT(handle, service, user);
 
   } else {
     
index 42f2f51416ee3f57c85d36ec489dc069c7ee4031..cb5eaffa54d21b53aaa4e7539f6e6aefa29808ed 100644 (file)
@@ -32,9 +32,9 @@ static int vfs_recycle_debug_level = DBGC_VFS;
 #undef DBGC_CLASS
 #define DBGC_CLASS vfs_recycle_debug_level
  
-static int recycle_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user);
-static void recycle_disconnect(vfs_handle_struct *handle, connection_struct *conn);
-static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *name);
+static int recycle_connect(vfs_handle_struct *handle, const char *service, const char *user);
+static void recycle_disconnect(vfs_handle_struct *handle);
+static int recycle_unlink(vfs_handle_struct *handle, const char *name);
 
 static vfs_op_tuple recycle_ops[] = {
 
@@ -48,20 +48,20 @@ static vfs_op_tuple recycle_ops[] = {
        {SMB_VFS_OP(NULL),              SMB_VFS_OP_NOOP,        SMB_VFS_LAYER_NOOP}
 };
 
-static int recycle_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user)
+static int recycle_connect(vfs_handle_struct *handle, const char *service, const char *user)
 {
        DEBUG(10,("recycle_connect() connect to service[%s] as user[%s].\n",
                service,user));
 
-       return SMB_VFS_NEXT_CONNECT(handle, conn, service, user);               
+       return SMB_VFS_NEXT_CONNECT(handle, service, user);
 }
 
-static void recycle_disconnect(vfs_handle_struct *handle, connection_struct *conn)
+static void recycle_disconnect(vfs_handle_struct *handle)
 {
        DEBUG(10,("recycle_disconnect() connect to service[%s].\n",
-               lp_servicename(SNUM(conn))));
+               lp_servicename(SNUM(handle->conn))));
 
-       SMB_VFS_NEXT_DISCONNECT(handle, conn);  
+       SMB_VFS_NEXT_DISCONNECT(handle);
 }
 
 static const char *recycle_repository(vfs_handle_struct *handle)
@@ -202,7 +202,7 @@ static BOOL recycle_directory_exist(vfs_handle_struct *handle, const char *dname
 {
        SMB_STRUCT_STAT st;
 
-       if (SMB_VFS_NEXT_STAT(handle, handle->conn, dname, &st) == 0) {
+       if (SMB_VFS_NEXT_STAT(handle, dname, &st) == 0) {
                if (S_ISDIR(st.st_mode)) {
                        return True;
                }
@@ -215,7 +215,7 @@ static BOOL recycle_file_exist(vfs_handle_struct *handle, const char *fname)
 {
        SMB_STRUCT_STAT st;
 
-       if (SMB_VFS_NEXT_STAT(handle, handle->conn, fname, &st) == 0) {
+       if (SMB_VFS_NEXT_STAT(handle, fname, &st) == 0) {
                if (S_ISREG(st.st_mode)) {
                        return True;
                }
@@ -234,7 +234,7 @@ static SMB_OFF_T recycle_get_file_size(vfs_handle_struct *handle, const char *fn
 {
        SMB_STRUCT_STAT st;
 
-       if (SMB_VFS_NEXT_STAT(handle, handle->conn, fname, &st) != 0) {
+       if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) {
                DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno)));
                return (SMB_OFF_T)0;
        }
@@ -280,7 +280,7 @@ static BOOL recycle_create_dir(vfs_handle_struct *handle, const char *dname)
                        DEBUG(10, ("recycle: dir %s already exists\n", new_dir));
                else {
                        DEBUG(5, ("recycle: creating new dir %s\n", new_dir));
-                       if (SMB_VFS_NEXT_MKDIR(handle, handle->conn, new_dir, mode) != 0) {
+                       if (SMB_VFS_NEXT_MKDIR(handle, new_dir, mode) != 0) {
                                DEBUG(1,("recycle: mkdir failed for %s with error: %s\n", new_dir, strerror(errno)));
                                ret = False;
                                goto done;
@@ -354,7 +354,7 @@ static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, BOOL
        struct utimbuf tb;
        time_t currtime;
        
-       if (SMB_VFS_NEXT_STAT(handle, handle->conn, fname, &st) != 0) {
+       if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) {
                DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno)));
                return;
        }
@@ -362,16 +362,19 @@ static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, BOOL
        tb.actime = currtime;
        tb.modtime = touch_mtime ? currtime : st.st_mtime;
 
-       if (SMB_VFS_NEXT_UTIME(handle, handle->conn, fname, &tb) == -1 ) {
+       if (SMB_VFS_NEXT_UTIME(handle, fname, &tb) == -1 ) {
                DEBUG(0, ("recycle: touching %s failed, reason = %s\n", fname, strerror(errno)));
        }
 }
 
+extern userdom_struct current_user_info;
+
 /**
  * Check if file should be recycled
  **/
-static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *file_name)
+static int recycle_unlink(vfs_handle_struct *handle, const char *file_name)
 {
+       connection_struct *conn = handle->conn;
        char *path_name = NULL;
                char *temp_name = NULL;
        char *final_name = NULL;
@@ -383,7 +386,12 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
        BOOL exist;
        int rc = -1;
 
-       repository = alloc_sub_conn(conn, recycle_repository(handle));
+       repository = alloc_sub_advanced(lp_servicename(SNUM(conn)),
+                                       conn->user,
+                                       conn->connectpath, conn->gid,
+                                       get_current_username(),
+                                       current_user_info.domain,
+                                       recycle_repository(handle));
        ALLOC_CHECK(repository, done);
        /* shouldn't we allow absolute path names here? --metze */
        /* Yes :-). JRA. */
@@ -391,14 +399,14 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
        
        if(!repository || *(repository) == '\0') {
                DEBUG(3, ("recycle: repository path not set, purging %s...\n", file_name));
-               rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+               rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
                goto done;
        }
 
        /* we don't recycle the recycle bin... */
        if (strncmp(file_name, repository, strlen(repository)) == 0) {
                DEBUG(3, ("recycle: File is within recycling bin, unlinking ...\n"));
-               rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+               rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
                goto done;
        }
 
@@ -408,7 +416,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
         *
        if(fsize == 0) {
                DEBUG(3, ("recycle: File %s is empty, purging...\n", file_name));
-               rc = SMB_VFS_NEXT_UNLINK(handle,conn,file_name);
+               rc = SMB_VFS_NEXT_UNLINK(handle,file_name);
                goto done;
        }
         */
@@ -420,18 +428,18 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
        maxsize = recycle_maxsize(handle);
        if(maxsize > 0 && file_size > maxsize) {
                DEBUG(3, ("recycle: File %s exceeds maximum recycle size, purging... \n", file_name));
-               rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+               rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
                goto done;
        }
 
        /* FIXME: this is wrong: moving files with rename does not change the disk space
         * allocation
         *
-       space_avail = SMB_VFS_NEXT_DISK_FREE(handle, conn, ".", True, &bsize, &dfree, &dsize) * 1024L;
+       space_avail = SMB_VFS_NEXT_DISK_FREE(handle, ".", True, &bsize, &dfree, &dsize) * 1024L;
        DEBUG(5, ("space_avail = %Lu, file_size = %Lu\n", space_avail, file_size));
        if(space_avail < file_size) {
                DEBUG(3, ("recycle: Not enough diskspace, purging file %s\n", file_name));
-               rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+               rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
                goto done;
        }
         */
@@ -456,7 +464,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
 
        if (matchparam(recycle_exclude(handle), base)) {
                DEBUG(3, ("recycle: file %s is excluded \n", base));
-               rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+               rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
                goto done;
        }
 
@@ -466,7 +474,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
         */
        if (checkparam(recycle_exclude_dir(handle), path_name)) {
                DEBUG(3, ("recycle: directory %s is excluded \n", path_name));
-               rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+               rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
                goto done;
        }
 
@@ -484,7 +492,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
                DEBUG(10, ("recycle: Creating directory %s\n", temp_name));
                if (recycle_create_dir(handle, temp_name) == False) {
                        DEBUG(3, ("recycle: Could not create directory, purging %s...\n", file_name));
-                       rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+                       rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
                        goto done;
                }
        }
@@ -497,7 +505,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
        if (recycle_file_exist(handle, final_name)) {
                if (recycle_versions(handle) == False || matchparam(recycle_noversions(handle), base) == True) {
                        DEBUG(3, ("recycle: Removing old file %s from recycle bin\n", final_name));
-                       if (SMB_VFS_NEXT_UNLINK(handle, conn, final_name) != 0) {
+                       if (SMB_VFS_NEXT_UNLINK(handle, final_name) != 0) {
                                DEBUG(1, ("recycle: Error deleting old file: %s\n", strerror(errno)));
                        }
                }
@@ -511,10 +519,10 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
        }
 
        DEBUG(10, ("recycle: Moving %s to %s\n", file_name, final_name));
-       rc = SMB_VFS_NEXT_RENAME(handle, conn, file_name, final_name);
+       rc = SMB_VFS_NEXT_RENAME(handle, file_name, final_name);
        if (rc != 0) {
                DEBUG(3, ("recycle: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name));
-               rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+               rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
                goto done;
        }
 
index db1c8d007dc64aee88133ec7d22cd469db338732..447c53d773a41e20f0c8d4b119429c1151353cd4 100644 (file)
@@ -72,10 +72,10 @@ static BOOL shadow_copy_match_name(const char *name)
        return False;
 }
 
-static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr)
+static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
 {
        shadow_copy_Dir *dirp;
-       SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,conn,fname,mask,attr);
+       SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fname,mask,attr);
 
        if (!p) {
                DEBUG(0,("shadow_copy_opendir: SMB_VFS_NEXT_OPENDIR() failed for [%s]\n",fname));
@@ -85,7 +85,7 @@ static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection
        dirp = SMB_MALLOC_P(shadow_copy_Dir);
        if (!dirp) {
                DEBUG(0,("shadow_copy_opendir: Out of memory\n"));
-               SMB_VFS_NEXT_CLOSEDIR(handle,conn,p);
+               SMB_VFS_NEXT_CLOSEDIR(handle,p);
                return NULL;
        }
 
@@ -94,7 +94,7 @@ static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection
        while (True) {
                SMB_STRUCT_DIRENT *d;
 
-               d = SMB_VFS_NEXT_READDIR(handle, conn, p);
+               d = SMB_VFS_NEXT_READDIR(handle, p);
                if (d == NULL) {
                        break;
                }
@@ -115,11 +115,11 @@ static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection
                dirp->dirs[dirp->num++] = *d;
        }
 
-       SMB_VFS_NEXT_CLOSEDIR(handle,conn,p);
+       SMB_VFS_NEXT_CLOSEDIR(handle,p);
        return((SMB_STRUCT_DIR *)dirp);
 }
 
-SMB_STRUCT_DIRENT *shadow_copy_readdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *_dirp)
+SMB_STRUCT_DIRENT *shadow_copy_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
 {
        shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
 
@@ -130,7 +130,7 @@ SMB_STRUCT_DIRENT *shadow_copy_readdir(vfs_handle_struct *handle, connection_str
        return NULL;
 }
 
-static void shadow_copy_seekdir(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *_dirp, long offset)
+static void shadow_copy_seekdir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp, long offset)
 {
        shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
 
@@ -139,19 +139,19 @@ static void shadow_copy_seekdir(struct vfs_handle_struct *handle, struct connect
        }
 }
 
-static long shadow_copy_telldir(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *_dirp)
+static long shadow_copy_telldir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
 {
        shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
        return( dirp->pos ) ;
 }
 
-static void shadow_copy_rewinddir(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *_dirp)
+static void shadow_copy_rewinddir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
 {
        shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
        dirp->pos = 0 ;
 }
 
-int shadow_copy_closedir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *_dirp)
+int shadow_copy_closedir(vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
 {
        shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
 
@@ -163,7 +163,7 @@ int shadow_copy_closedir(vfs_handle_struct *handle, connection_struct *conn, SMB
 
 static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
 {
-       SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fsp->conn,fsp->conn->connectpath,NULL,0);
+       SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fsp->conn->connectpath,NULL,0);
 
        shadow_copy_data->num_volumes = 0;
        shadow_copy_data->labels = NULL;
@@ -177,7 +177,7 @@ static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_str
                SHADOW_COPY_LABEL *tlabels;
                SMB_STRUCT_DIRENT *d;
 
-               d = SMB_VFS_NEXT_READDIR(handle, fsp->conn, p);
+               d = SMB_VFS_NEXT_READDIR(handle, p);
                if (d == NULL) {
                        break;
                }
@@ -200,7 +200,7 @@ static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_str
                                                                        (shadow_copy_data->num_volumes+1)*sizeof(SHADOW_COPY_LABEL));
                if (tlabels == NULL) {
                        DEBUG(0,("shadow_copy_get_shadow_copy_data: Out of memory\n"));
-                       SMB_VFS_NEXT_CLOSEDIR(handle,fsp->conn,p);
+                       SMB_VFS_NEXT_CLOSEDIR(handle,p);
                        return -1;
                }
 
@@ -209,7 +209,7 @@ static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_str
                shadow_copy_data->labels = tlabels;
        }
 
-       SMB_VFS_NEXT_CLOSEDIR(handle,fsp->conn,p);
+       SMB_VFS_NEXT_CLOSEDIR(handle,p);
        return 0;
 }
 
index 28ad92ed108022ac277e51cd7d7c175c349f868b..0e67c3f69c0bf94fbcaa6c780ea13f2009463eb8 100644 (file)
@@ -68,7 +68,7 @@ static void sync_child(char *name, int nm_type,
                       char *fname)
 {
        fstring unix_workgroup;
-       static struct cli_state cli;
+       struct cli_state *cli;
        uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0;
        struct nmb_name called, calling;
 
@@ -76,50 +76,55 @@ static void sync_child(char *name, int nm_type,
         * Patch from Andy Levine andyl@epicrealm.com.
         */
 
-       if (!cli_initialise(&cli) || !cli_set_port(&cli, 139) || !cli_connect(&cli, name, &ip)) {
+       cli = cli_initialise();
+       if (!cli) {
+               return;
+       }
+
+       if (!cli_set_port(cli, 139) || !cli_connect(cli, name, &ip)) {
                return;
        }
 
        make_nmb_name(&calling, local_machine, 0x0);
        make_nmb_name(&called , name, nm_type);
 
-       if (!cli_session_request(&cli, &calling, &called)) {
-               cli_shutdown(&cli);
+       if (!cli_session_request(cli, &calling, &called)) {
+               cli_shutdown(cli);
                return;
        }
 
-       if (!cli_negprot(&cli)) {
-               cli_shutdown(&cli);
+       if (!cli_negprot(cli)) {
+               cli_shutdown(cli);
                return;
        }
 
-       if (!cli_session_setup(&cli, "", "", 1, "", 0, workgroup)) {
-               cli_shutdown(&cli);
+       if (!cli_session_setup(cli, "", "", 1, "", 0, workgroup)) {
+               cli_shutdown(cli);
                return;
        }
 
-       if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
-               cli_shutdown(&cli);
+       if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
+               cli_shutdown(cli);
                return;
        }
 
        /* All the cli_XX functions take UNIX character set. */
-       fstrcpy(unix_workgroup, cli.server_domain?cli.server_domain:workgroup);
+       fstrcpy(unix_workgroup, cli->server_domain ? cli->server_domain : workgroup);
 
        /* Fetch a workgroup list. */
-       cli_NetServerEnum(&cli, unix_workgroup,
+       cli_NetServerEnum(cli, unix_workgroup,
                          local_type|SV_TYPE_DOMAIN_ENUM, 
                          callback, NULL);
        
        /* Now fetch a server list. */
        if (servers) {
                fstrcpy(unix_workgroup, workgroup);
-               cli_NetServerEnum(&cli, unix_workgroup, 
+               cli_NetServerEnum(cli, unix_workgroup, 
                                  local?SV_TYPE_LOCAL_LIST_ONLY:SV_TYPE_ALL,
                                  callback, NULL);
        }
        
-       cli_shutdown(&cli);
+       cli_shutdown(cli);
 }
 
 /*******************************************************************
index 78776256e99767a383c10a6e1e904ca6be625fe2..118ba358e1693eb539d16de00ff783a8c32d1044 100644 (file)
@@ -128,6 +128,24 @@ static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int error_
        SAFE_FREE(data);
 }
 
+/*
+ * Work around the pam API that has functions with void ** as parameters.
+ * These lead to strict aliasing warnings with gcc.
+ */
+static int _pam_get_item(const pam_handle_t *pamh, int item_type,
+                        const void *_item)
+{
+       const void **item = (const void **)_item;
+       return pam_get_item(pamh, item_type, item);
+}
+static int _pam_get_data(const pam_handle_t *pamh,
+                        const char *module_data_name, const void *_data)
+{
+       const void **data = (const void **)_data;
+       return pam_get_data(pamh, module_data_name, data);
+}
+
+
 static const struct ntstatus_errors {
        const char *ntstatus_string;
        const char *error_string;
@@ -173,7 +191,7 @@ static int converse(pam_handle_t *pamh, int nargs,
        int retval;
        struct pam_conv *conv;
 
-       retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv );
+       retval = _pam_get_item(pamh, PAM_CONV, &conv );
        if (retval == PAM_SUCCESS) {
                retval = conv->conv(nargs, (const struct pam_message **)message,
                                    response, conv->appdata_ptr);
@@ -676,7 +694,7 @@ static int _winbind_read_password(pam_handle_t * pamh,
         */
 
        if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) {
-               retval = pam_get_item(pamh, authtok_flag, (const void **) &item);
+               retval = _pam_get_item(pamh, authtok_flag, &item);
                if (retval != PAM_SUCCESS) {
                        /* very strange. */
                        _pam_log(LOG_ALERT, 
@@ -778,7 +796,7 @@ static int _winbind_read_password(pam_handle_t * pamh,
        retval = pam_set_item(pamh, authtok_flag, token);
        _pam_delete(token);     /* clean it up */
        if (retval != PAM_SUCCESS || 
-           (retval = pam_get_item(pamh, authtok_flag, (const void **) &item)) != PAM_SUCCESS) {
+           (retval = _pam_get_item(pamh, authtok_flag, &item)) != PAM_SUCCESS) {
                
                _pam_log(LOG_CRIT, "error manipulating password");
                return retval;
@@ -1251,8 +1269,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
                 * get the old token back. 
                 */
                
-               retval = pam_get_item(pamh, PAM_OLDAUTHTOK,
-                                     (const void **) &pass_old);
+               retval = _pam_get_item(pamh, PAM_OLDAUTHTOK, &pass_old);
                
                if (retval != PAM_SUCCESS) {
                        _pam_log(LOG_NOTICE, "user not authenticated");
@@ -1300,7 +1317,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
                 * By reaching here we have approved the passwords and must now
                 * rebuild the password database file.
                 */
-               pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET, (const void **)&pwdlastset_update);
+               _pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET,
+                              &pwdlastset_update);
 
                retval = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new, pwdlastset_update);
                if (retval) {
index de1edf054d117e9a4cf38b3b9e049802993db1df..b1a7947137560506f9395b1ddb478c586c2969e6 100644 (file)
@@ -113,6 +113,116 @@ BOOL winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
        return True;
 }
 
+BOOL winbind_lookup_rids(TALLOC_CTX *mem_ctx,
+                        const DOM_SID *domain_sid,
+                        int num_rids, uint32 *rids,
+                        const char **domain_name,
+                        const char ***names, enum SID_NAME_USE **types)
+{
+       size_t i, buflen;
+       ssize_t len;
+       char *ridlist;
+       char *p;
+       struct winbindd_request request;
+       struct winbindd_response response;
+       NSS_STATUS result;
+
+       if (num_rids == 0) {
+               return False;
+       }
+
+       /* Initialise request */
+
+       ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
+
+       fstrcpy(request.data.sid, sid_string_static(domain_sid));
+       
+       len = 0;
+       buflen = 0;
+       ridlist = NULL;
+
+       for (i=0; i<num_rids; i++) {
+               sprintf_append(mem_ctx, &ridlist, &len, &buflen,
+                              "%ld\n", rids[i]);
+       }
+
+       if ((num_rids != 0) && (ridlist == NULL)) {
+               return False;
+       }
+
+       request.extra_data.data = ridlist;
+       request.extra_len = strlen(ridlist)+1;
+
+       result = winbindd_request_response(WINBINDD_LOOKUPRIDS,
+                                          &request, &response);
+
+       TALLOC_FREE(ridlist);
+
+       if (result != NSS_STATUS_SUCCESS) {
+               return False;
+       }
+
+       *domain_name = talloc_strdup(mem_ctx, response.data.domain_name);
+
+       *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
+       *types = TALLOC_ARRAY(mem_ctx, enum SID_NAME_USE, num_rids);
+
+       if ((*names == NULL) || (*types == NULL)) {
+               goto fail;
+       }
+
+       p = response.extra_data.data;
+
+       for (i=0; i<num_rids; i++) {
+               char *q;
+
+               if (*p == '\0') {
+                       DEBUG(10, ("Got invalid reply: %s\n",
+                                  (char *)response.extra_data.data));
+                       goto fail;
+               }
+                       
+               (*types)[i] = (enum SID_NAME_USE)strtoul(p, &q, 10);
+
+               if (*q != ' ') {
+                       DEBUG(10, ("Got invalid reply: %s\n",
+                                  (char *)response.extra_data.data));
+                       goto fail;
+               }
+
+               p = q+1;
+
+               q = strchr(p, '\n');
+               if (q == NULL) {
+                       DEBUG(10, ("Got invalid reply: %s\n",
+                                  (char *)response.extra_data.data));
+                       goto fail;
+               }
+
+               *q = '\0';
+
+               (*names)[i] = talloc_strdup(*names, p);
+
+               p = q+1;
+       }
+
+       if (*p != '\0') {
+               DEBUG(10, ("Got invalid reply: %s\n",
+                          (char *)response.extra_data.data));
+               goto fail;
+       }
+
+       SAFE_FREE(response.extra_data.data);
+
+       return True;
+
+ fail:
+       TALLOC_FREE(*names);
+       TALLOC_FREE(*types);
+       return False;
+}
+
 /* Call winbindd to convert SID to uid */
 
 BOOL winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
index 27ec27d0be522f728867e18cd173ebb6f01472e0..a393855f026370d36a6500e1331e147bf6ad9edc 100644 (file)
@@ -151,6 +151,34 @@ static BOOL wbinfo_get_userinfo(char *user)
        return True;
 }
 
+/* pull grent for a given group */
+static BOOL wbinfo_get_groupinfo(char *group)
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+       NSS_STATUS result;
+
+       ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
+
+       /* Send request */
+
+       fstrcpy(request.data.groupname, group);
+
+       result = winbindd_request_response(WINBINDD_GETGRNAM, &request,
+                                          &response);
+
+       if ( result != NSS_STATUS_SUCCESS)
+               return False;
+
+       d_printf( "%s:%s:%d\n",
+                 response.data.gr.gr_name,
+                 response.data.gr.gr_passwd,
+                 response.data.gr.gr_gid );
+       
+       return True;
+}
+
 /* List groups a user is a member of */
 
 static BOOL wbinfo_get_usergroups(char *user)
@@ -201,7 +229,7 @@ static BOOL wbinfo_get_usersids(char *user_sid)
        if (result != NSS_STATUS_SUCCESS)
                return False;
 
-       s = response.extra_data.data;
+       s = (const char *)response.extra_data.data;
        for (i = 0; i < response.data.num_entries; i++) {
                d_printf("%s\n", s);
                s += strlen(s) + 1;
@@ -608,6 +636,64 @@ static BOOL wbinfo_lookupsid(char *sid)
        return True;
 }
 
+/* Lookup a list of RIDs */
+
+static BOOL wbinfo_lookuprids(char *domain_sid, char *arg)
+{
+       size_t i;
+       DOM_SID sid;
+       int num_rids;
+       uint32 *rids;
+       const char *p;
+       char ridstr[32];
+       const char **names;
+       enum SID_NAME_USE *types;
+       const char *domain_name;
+       TALLOC_CTX *mem_ctx;
+
+       if (!string_to_sid(&sid, domain_sid)) {
+               d_printf("Could not convert %s to sid\n", domain_sid);
+               return False;
+       }
+
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               d_printf("talloc_new failed\n");
+               return False;
+       }
+
+       num_rids = 0;
+       rids = NULL;
+       p = arg;
+
+       while (next_token(&p, ridstr, " ,\n", sizeof(ridstr))) {
+               uint32 rid = strtoul(ridstr, NULL, 10);
+               ADD_TO_ARRAY(mem_ctx, uint32, rid, &rids, &num_rids);
+       }
+
+       if (rids == NULL) {
+               TALLOC_FREE(mem_ctx);
+               return False;
+       }
+
+       if (!winbind_lookup_rids(mem_ctx, &sid, num_rids, rids,
+                                &domain_name, &names, &types)) {
+               d_printf("winbind_lookup_rids failed\n");
+               TALLOC_FREE(mem_ctx);
+               return False;
+       }
+
+       d_printf("Domain: %s\n", domain_name);
+
+       for (i=0; i<num_rids; i++) {
+               d_printf("%8d: %s (%s)\n", rids[i], names[i],
+                        sid_type_lookup(types[i]));
+       }
+
+       TALLOC_FREE(mem_ctx);
+       return True;
+}
+
 /* Convert string to sid */
 
 static BOOL wbinfo_lookupname(char *name)
@@ -1092,7 +1178,8 @@ enum {
        OPT_ALLOCATE_GID,
        OPT_SEPARATOR,
        OPT_LIST_ALL_DOMAINS,
-       OPT_LIST_OWN_DOMAIN
+       OPT_LIST_OWN_DOMAIN,
+       OPT_GROUP_INFO,
 };
 
 int main(int argc, char **argv)
@@ -1117,6 +1204,7 @@ int main(int argc, char **argv)
                { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name", "IP" },
                { "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n', "Converts name to sid", "NAME" },
                { "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's', "Converts sid to name", "SID" },
+               { "lookup-rids", 'R', POPT_ARG_STRING, &string_arg, 'R', "Converts RIDs to names", "RIDs" },
                { "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U', "Converts uid to sid" , "UID" },
                { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" },
                { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" },
@@ -1132,6 +1220,7 @@ int main(int argc, char **argv)
                { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" },
                { "domain-info", 'D', POPT_ARG_STRING, &string_arg, 'D', "Show most of the info we have about the domain" },
                { "user-info", 'i', POPT_ARG_STRING, &string_arg, 'i', "Get user info", "USER" },
+               { "group-info", 0, POPT_ARG_STRING, &string_arg, OPT_GROUP_INFO, "Get group info", "GROUP" },
                { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" },
                { "user-domgroups", 0, POPT_ARG_STRING, &string_arg,
                  OPT_USERDOMGROUPS, "Get user domain groups", "SID" },
@@ -1210,6 +1299,12 @@ int main(int argc, char **argv)
                                goto done;
                        }
                        break;
+               case 'R':
+                       if (!wbinfo_lookuprids(opt_domain_name, string_arg)) {
+                               d_fprintf(stderr, "Could not lookup RIDs %s\n", string_arg);
+                               goto done;
+                       }
+                       break;
                case 'n':
                        if (!wbinfo_lookupname(string_arg)) {
                                d_fprintf(stderr, "Could not lookup name %s\n", string_arg);
@@ -1298,6 +1393,13 @@ int main(int argc, char **argv)
                                goto done;
                        }
                        break;
+               case OPT_GROUP_INFO:
+                       if ( !wbinfo_get_groupinfo(string_arg)) {
+                               d_fprintf(stderr, "Could not get info for "
+                                         "group %s\n", string_arg);
+                               goto done;
+                       }
+            break;
                case 'r':
                        if (!wbinfo_get_usergroups(string_arg)) {
                                d_fprintf(stderr, "Could not get groups for user %s\n", 
index 046ea40f59a964995a78a75cbf014e8b984c6389..e5582915b2f63b83e7d0c0fc080a4955694251cc 100644 (file)
@@ -227,6 +227,7 @@ static struct winbindd_dispatch_table {
 
        { WINBINDD_LOOKUPSID, winbindd_lookupsid, "LOOKUPSID" },
        { WINBINDD_LOOKUPNAME, winbindd_lookupname, "LOOKUPNAME" },
+       { WINBINDD_LOOKUPRIDS, winbindd_lookuprids, "LOOKUPRIDS" },
 
        /* Lookup related functions */
 
index 7d5330dccb21208b0ffe70df5046c96ddb4eb06c..a16613258b1039426fea160fcf1bfc572a5bc65a 100644 (file)
@@ -245,6 +245,15 @@ struct winbindd_methods {
                                char **name,
                                enum SID_NAME_USE *type);
 
+       NTSTATUS (*rids_to_names)(struct winbindd_domain *domain,
+                                 TALLOC_CTX *mem_ctx,
+                                 const DOM_SID *domain_sid,
+                                 uint32 *rids,
+                                 size_t num_rids,
+                                 char **domain_name,
+                                 char ***names,
+                                 enum SID_NAME_USE **types);
+
        /* lookup user info for a given SID */
        NTSTATUS (*query_user)(struct winbindd_domain *domain, 
                               TALLOC_CTX *mem_ctx, 
index 250b5f3b8c2784bdb462e39e886b408e6f0d7968..07127a63166dd887e475a3f2b5559d41a0d2d45f 100644 (file)
@@ -1119,6 +1119,7 @@ struct winbindd_methods ads_methods = {
        enum_local_groups,
        msrpc_name_to_sid,
        msrpc_sid_to_name,
+       msrpc_rids_to_names,
        query_user,
        lookup_usergroups,
        msrpc_lookup_useraliases,
index 7f282df929d50749290048a1f1d744aaf273b97b..6169b8299ec1cd9cdbe32e6b89ad39ab4049c7af 100644 (file)
@@ -116,7 +116,7 @@ static void idmap_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success,
                                   struct winbindd_response *response,
                                   void *c, void *private_data)
 {
-       void (*cont)(void *priv, BOOL succ) = c;
+       void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c;
 
        if (!success) {
                DEBUG(5, ("Could not trigger idmap_set_mapping\n"));
@@ -149,7 +149,7 @@ void idmap_set_mapping_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
        sid_to_string(request.data.dual_idmapset.sid, sid);
 
        do_async(mem_ctx, idmap_child(), &request, idmap_set_mapping_recv,
-                cont, private_data);
+                (void *)cont, private_data);
 }
 
 enum winbindd_result winbindd_dual_idmapset(struct winbindd_domain *domain,
@@ -188,7 +188,7 @@ void idmap_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc,
        sid_to_string(request.data.dual_sid2id.sid, sid);
        request.data.dual_sid2id.alloc = alloc;
        do_async(mem_ctx, idmap_child(), &request, idmap_sid2uid_recv,
-                cont, private_data);
+                (void *)cont, private_data);
 }
 
 enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain,
@@ -211,7 +211,7 @@ enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain,
 
        result = idmap_sid_to_uid(&sid, &(state->response.data.uid),
                                  state->request.data.dual_sid2id.alloc ?
-                                 0 : ID_QUERY_ONLY);
+                                 0 : IDMAP_FLAG_QUERY_ONLY);
 
        return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
 }
@@ -220,7 +220,8 @@ static void idmap_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
                               struct winbindd_response *response,
                               void *c, void *private_data)
 {
-       void (*cont)(void *priv, BOOL succ, uid_t uid) = c;
+       void (*cont)(void *priv, BOOL succ, uid_t uid) =
+               (void (*)(void *, BOOL, uid_t))c;
 
        if (!success) {
                DEBUG(5, ("Could not trigger sid2uid\n"));
@@ -251,7 +252,7 @@ void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid,
        request.cmd = WINBINDD_DUAL_UID2NAME;
        request.data.uid = uid;
        do_async(mem_ctx, idmap_child(), &request, uid2name_recv,
-                cont, private_data);
+                (void *)cont, private_data);
 }
 
 enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain,
@@ -277,7 +278,8 @@ static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
                          struct winbindd_response *response,
                          void *c, void *private_data)
 {
-       void (*cont)(void *priv, BOOL succ, const char *name) = c;
+       void (*cont)(void *priv, BOOL succ, const char *name) =
+               (void (*)(void *, BOOL, const char *))c;
 
        if (!success) {
                DEBUG(5, ("Could not trigger uid2name\n"));
@@ -308,7 +310,7 @@ static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name,
        request.cmd = WINBINDD_DUAL_NAME2UID;
        fstrcpy(request.data.username, name);
        do_async(mem_ctx, idmap_child(), &request, name2uid_recv,
-                cont, private_data);
+                (void *)cont, private_data);
 }
 
 enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain,
@@ -336,7 +338,8 @@ static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
                          struct winbindd_response *response,
                          void *c, void *private_data)
 {
-       void (*cont)(void *priv, BOOL succ, uid_t uid) = c;
+       void (*cont)(void *priv, BOOL succ, uid_t uid) =
+               (void (*)(void *, BOOL, uid_t))c;
 
        if (!success) {
                DEBUG(5, ("Could not trigger name2uid\n"));
@@ -371,7 +374,7 @@ void idmap_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc,
 
        request.data.dual_sid2id.alloc = alloc;
        do_async(mem_ctx, idmap_child(), &request, idmap_sid2gid_recv,
-                cont, private_data);
+                (void *)cont, private_data);
 }
 
 enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain,
@@ -392,9 +395,9 @@ enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain,
        /* Find gid for this sid and return it, possibly ask the slow remote
         * idmap */
 
-       result = idmap_sid_to_gid(&sid, &(state->response.data.gid),
+       result = idmap_sid_to_gid(&sid, &state->response.data.gid,
                                  state->request.data.dual_sid2id.alloc ?
-                                 0 : ID_QUERY_ONLY);
+                                 0 : IDMAP_FLAG_QUERY_ONLY);
 
        /* If the lookup failed, the perhaps we need to look 
           at the passdb for local groups */
@@ -412,7 +415,8 @@ static void idmap_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
                               struct winbindd_response *response,
                               void *c, void *private_data)
 {
-       void (*cont)(void *priv, BOOL succ, gid_t gid) = c;
+       void (*cont)(void *priv, BOOL succ, gid_t gid) =
+               (void (*)(void *, BOOL, gid_t))c;
 
        if (!success) {
                DEBUG(5, ("Could not trigger sid2gid\n"));
@@ -433,7 +437,8 @@ static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
                          struct winbindd_response *response,
                          void *c, void *private_data)
 {
-       void (*cont)(void *priv, BOOL succ, const char *name) = c;
+       void (*cont)(void *priv, BOOL succ, const char *name) =
+               (void (*)(void *, BOOL, const char *))c;
 
        if (!success) {
                DEBUG(5, ("Could not trigger gid2name\n"));
@@ -460,7 +465,7 @@ void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid,
        request.cmd = WINBINDD_DUAL_GID2NAME;
        request.data.gid = gid;
        do_async(mem_ctx, idmap_child(), &request, gid2name_recv,
-                cont, private_data);
+                (void *)cont, private_data);
 }
 
 enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain,
@@ -493,7 +498,7 @@ static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name,
        request.cmd = WINBINDD_DUAL_NAME2GID;
        fstrcpy(request.data.groupname, name);
        do_async(mem_ctx, idmap_child(), &request, name2gid_recv,
-                cont, private_data);
+                (void *)cont, private_data);
 }
 
 enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain,
@@ -521,7 +526,8 @@ static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
                          struct winbindd_response *response,
                          void *c, void *private_data)
 {
-       void (*cont)(void *priv, BOOL succ, gid_t gid) = c;
+       void (*cont)(void *priv, BOOL succ, gid_t gid) =
+               (void (*)(void *, BOOL, gid_t))c;
 
        if (!success) {
                DEBUG(5, ("Could not trigger name2gid\n"));
@@ -544,7 +550,9 @@ static void lookupsid_recv(TALLOC_CTX *mem_ctx, BOOL success,
                           void *c, void *private_data)
 {
        void (*cont)(void *priv, BOOL succ, const char *dom_name,
-                    const char *name, enum SID_NAME_USE type) = c;
+                    const char *name, enum SID_NAME_USE type) =
+               (void (*)(void *, BOOL, const char *, const char *,
+                         enum SID_NAME_USE))c;
 
        if (!success) {
                DEBUG(5, ("Could not trigger lookupsid\n"));
@@ -559,7 +567,8 @@ static void lookupsid_recv(TALLOC_CTX *mem_ctx, BOOL success,
        }
 
        cont(private_data, True, response->data.name.dom_name,
-            response->data.name.name, response->data.name.type);
+            response->data.name.name,
+            (enum SID_NAME_USE)response->data.name.type);
 }
 
 void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
@@ -585,7 +594,7 @@ void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
        fstrcpy(request.data.sid, sid_string_static(sid));
 
        do_async_domain(mem_ctx, domain, &request, lookupsid_recv,
-                       cont, private_data);
+                       (void *)cont, private_data);
 }
 
 enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain,
@@ -628,7 +637,8 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success,
                            void *c, void *private_data)
 {
        void (*cont)(void *priv, BOOL succ, const DOM_SID *sid,
-                    enum SID_NAME_USE type) = c;
+                    enum SID_NAME_USE type) =
+               (void (*)(void *, BOOL, const DOM_SID *, enum SID_NAME_USE))c;
        DOM_SID sid;
 
        if (!success) {
@@ -650,7 +660,8 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success,
                return;
        }
 
-       cont(private_data, True, &sid, response->data.sid.type);
+       cont(private_data, True, &sid,
+            (enum SID_NAME_USE)response->data.sid.type);
 }
 
 void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, const char *dom_name,
@@ -677,7 +688,7 @@ void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, const char *dom_name,
        fstrcpy(request.data.name.name, name);
 
        do_async_domain(mem_ctx, domain, &request, lookupname_recv,
-                       cont, private_data);
+                       (void *)cont, private_data);
 }
 
 enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain,
@@ -740,8 +751,8 @@ BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
        return True;
 }
 
-BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
-                  DOM_SID **sids, size_t *num_sids)
+static BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
+                         DOM_SID **sids, size_t *num_sids)
 {
        char *p, *q;
 
@@ -768,28 +779,8 @@ BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
        return True;
 }
 
-BOOL print_ridlist(TALLOC_CTX *mem_ctx, uint32 *rids, size_t num_rids,
-                  char **result, ssize_t *len)
-{
-       size_t i;
-       size_t buflen = 0;
-
-       *len = 0;
-       *result = NULL;
-       for (i=0; i<num_rids; i++) {
-               sprintf_append(mem_ctx, result, len, &buflen,
-                              "%ld\n", rids[i]);
-       }
-
-       if ((num_rids != 0) && (*result == NULL)) {
-               return False;
-       }
-
-       return True;
-}
-
-BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
-                  uint32 **sids, size_t *num_rids)
+static BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
+                         uint32 **rids, size_t *num_rids)
 {
        char *p;
 
@@ -806,17 +797,76 @@ BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
                        return False;
                }
                p = q+1;
-               ADD_TO_ARRAY(mem_ctx, uint32, rid, sids, num_rids);
+               ADD_TO_ARRAY(mem_ctx, uint32, rid, rids, num_rids);
        }
        return True;
 }
 
+enum winbindd_result winbindd_dual_lookuprids(struct winbindd_domain *domain,
+                                             struct winbindd_cli_state *state)
+{
+       uint32 *rids = NULL;
+       size_t i, buflen, num_rids = 0;
+       ssize_t len;
+       DOM_SID domain_sid;
+       char *domain_name;
+       char **names;
+       enum SID_NAME_USE *types;
+       NTSTATUS status;
+       char *result;
+
+       DEBUG(10, ("Looking up RIDs for domain %s (%s)\n",
+                  state->request.domain_name,
+                  state->request.data.sid));
+
+       if (!parse_ridlist(state->mem_ctx, state->request.extra_data.data,
+                          &rids, &num_rids)) {
+               DEBUG(5, ("Could not parse ridlist\n"));
+               return WINBINDD_ERROR;
+       }
+
+       if (!string_to_sid(&domain_sid, state->request.data.sid)) {
+               DEBUG(5, ("Could not parse domain sid %s\n",
+                         state->request.data.sid));
+               return WINBINDD_ERROR;
+       }
+
+       status = domain->methods->rids_to_names(domain, state->mem_ctx,
+                                               &domain_sid, rids, num_rids,
+                                               &domain_name,
+                                               &names, &types);
+
+       if (!NT_STATUS_IS_OK(status) &&
+           !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
+               return WINBINDD_ERROR;
+       }
+
+       len = 0;
+       buflen = 0;
+       result = NULL;
+
+       for (i=0; i<num_rids; i++) {
+               sprintf_append(state->mem_ctx, &result, &len, &buflen,
+                              "%d %s\n", types[i], names[i]);
+       }
+
+       fstrcpy(state->response.data.domain_name, domain_name);
+
+       if (result != NULL) {
+               state->response.extra_data.data = SMB_STRDUP(result);
+               state->response.length += len+1;
+       }
+
+       return WINBINDD_OK;
+}
+
 static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success,
                               struct winbindd_response *response,
                               void *c, void *private_data)
 {
        void (*cont)(void *priv, BOOL succ,
-                    DOM_SID *aliases, size_t num_aliases) = c;
+                    DOM_SID *aliases, size_t num_aliases) =
+               (void (*)(void *, BOOL, DOM_SID *, size_t))c;
        char *aliases_str;
        DOM_SID *sids = NULL;
        size_t num_sids = 0;
@@ -833,7 +883,7 @@ static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success,
                return;
        }
 
-       aliases_str = response->extra_data.data;
+       aliases_str = (char *)response->extra_data.data;
 
        if (aliases_str == NULL) {
                DEBUG(10, ("getsidaliases return 0 SIDs\n"));
@@ -881,7 +931,7 @@ void winbindd_getsidaliases_async(struct winbindd_domain *domain,
        request.extra_data.data = sidstr;
 
        do_async_domain(mem_ctx, domain, &request, getsidaliases_recv,
-                       cont, private_data);
+                       (void *)cont, private_data);
 }
 
 enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
@@ -937,12 +987,15 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
                add_sid_to_array(state->mem_ctx, &sid, &sids, &num_sids);
        }
 
-       if (!print_sidlist(NULL, sids, num_sids,
-                          (char **)&state->response.extra_data.data, &len)) {
+
+       if (!print_sidlist(NULL, sids, num_sids, &sidstr, &len)) {
                DEBUG(0, ("Could not print_sidlist\n"));
+               state->response.extra_data.data = NULL;
                return WINBINDD_ERROR;
        }
 
+       state->response.extra_data.data = sidstr;
+
        if (state->response.extra_data.data != NULL) {
                DEBUG(10, ("aliases_list: %s\n",
                           (char *)state->response.extra_data.data));
@@ -1026,7 +1079,7 @@ static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
                return;
        }
 
-       sids_str = response->extra_data.data;
+       sids_str = (char *)response->extra_data.data;
 
        if (sids_str == NULL) {
                /* This could be normal if we are dealing with a
@@ -1070,7 +1123,7 @@ static void gettoken_recvaliases(void *private_data, BOOL success,
                                 const DOM_SID *aliases,
                                 size_t num_aliases)
 {
-       struct gettoken_state *state = private_data;
+       struct gettoken_state *state = (struct gettoken_state *)private_data;
        size_t i;
 
        if (!success) {
@@ -1140,7 +1193,7 @@ void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
 
        /* Query only the local tdb, everything else might possibly block */
 
-       result = idmap_sid_to_uid(sid, &uid, ID_QUERY_ONLY|ID_CACHE_ONLY);
+       result = idmap_sid_to_uid(sid, &uid, IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY);
 
        if (NT_STATUS_IS_OK(result)) {
                cont(private_data, True, uid);
@@ -1302,7 +1355,7 @@ void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
 
        /* Query only the local tdb, everything else might possibly block */
 
-       result = idmap_sid_to_gid(sid, &gid, ID_QUERY_ONLY|ID_CACHE_ONLY);
+       result = idmap_sid_to_gid(sid, &gid, IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY);
 
        if (NT_STATUS_IS_OK(result)) {
                cont(private_data, True, gid);
@@ -1437,7 +1490,9 @@ static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success,
 {
        void (*cont)(void *priv, BOOL succ, const char *acct_name,
                     const char *full_name, const char *homedir, 
-                    const char *shell, uint32 group_rid) = c;
+                    const char *shell, uint32 group_rid) =
+               (void (*)(void *, BOOL, const char *, const char *,
+                         const char *, const char *, uint32))c;
 
        if (!success) {
                DEBUG(5, ("Could not trigger query_user\n"));
@@ -1467,5 +1522,5 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
        request.cmd = WINBINDD_DUAL_USERINFO;
        sid_to_string(request.data.sid, sid);
        do_async_domain(mem_ctx, domain, &request, query_user_recv,
-                       cont, private_data);
+                       (void *)cont, private_data);
 }
index b267a3f770517425e3e2fe8ae73824038b1de58f..95a66420c5918609d402e5c41a961839a7d9cede 100644 (file)
@@ -66,7 +66,7 @@ void winbindd_check_cache_size(time_t t)
                return;
        }
 
-       if (fstat(wcache->tdb->fd, &st) == -1) {
+       if (fstat(tdb_fd(wcache->tdb), &st) == -1) {
                DEBUG(0, ("Unable to check size of tdb cache %s!\n", strerror(errno) ));
                return;
        }
@@ -259,7 +259,7 @@ static char *centry_string(struct cache_entry *centry, TALLOC_CTX *mem_ctx)
                smb_panic("centry_string");
        }
 
-       ret = TALLOC(mem_ctx, len+1);
+       ret = TALLOC_ARRAY(mem_ctx, char, len+1);
        if (!ret) {
                smb_panic("centry_string out of memory\n");
        }
@@ -567,7 +567,8 @@ static void centry_expand(struct cache_entry *centry, uint32 len)
        if (centry->len - centry->ofs >= len)
                return;
        centry->len *= 2;
-       centry->data = SMB_REALLOC(centry->data, centry->len);
+       centry->data = SMB_REALLOC_ARRAY(centry->data, unsigned char,
+                                        centry->len);
        if (!centry->data) {
                DEBUG(0,("out of memory: needed %d bytes in centry_expand\n", centry->len));
                smb_panic("out of memory in centry_expand");
@@ -1316,6 +1317,128 @@ do_query:
        return status;
 }
 
+static NTSTATUS rids_to_names(struct winbindd_domain *domain,
+                             TALLOC_CTX *mem_ctx,
+                             const DOM_SID *domain_sid,
+                             uint32 *rids,
+                             size_t num_rids,
+                             char **domain_name,
+                             char ***names,
+                             enum SID_NAME_USE **types)
+{
+       struct winbind_cache *cache = get_cache(domain);
+       size_t i;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       BOOL have_mapped;
+       BOOL have_unmapped;
+
+       *domain_name = NULL;
+       *names = NULL;
+       *types = NULL;
+
+       if (!cache->tdb) {
+               goto do_query;
+       }
+
+       if (num_rids == 0) {
+               return NT_STATUS_OK;
+       }
+
+       *names = TALLOC_ARRAY(mem_ctx, char *, num_rids);
+       *types = TALLOC_ARRAY(mem_ctx, enum SID_NAME_USE, num_rids);
+
+       if ((*names == NULL) || (*types == NULL)) {
+               result = NT_STATUS_NO_MEMORY;
+               goto error;
+       }
+
+       have_mapped = have_unmapped = False;
+
+       for (i=0; i<num_rids; i++) {
+               DOM_SID sid;
+               struct cache_entry *centry;
+
+               if (!sid_compose(&sid, domain_sid, rids[i])) {
+                       result = NT_STATUS_INTERNAL_ERROR;
+                       goto error;
+               }
+
+               centry = wcache_fetch(cache, domain, "SN/%s",
+                                     sid_string_static(&sid));
+               if (!centry) {
+                       goto do_query;
+               }
+
+               (*types)[i] = SID_NAME_UNKNOWN;
+               (*names)[i] = talloc_strdup(*names, "");
+
+               if (NT_STATUS_IS_OK(centry->status)) {
+                       char *dom;
+                       have_mapped = True;
+                       (*types)[i] = (enum SID_NAME_USE)centry_uint32(centry);
+                       dom = centry_string(centry, mem_ctx);
+                       if (*domain_name == NULL) {
+                               *domain_name = dom;
+                       } else {
+                               talloc_free(dom);
+                       }
+                       (*names)[i] = centry_string(centry, *names);
+               } else {
+                       have_unmapped = True;
+               }
+
+               centry_free(centry);
+       }
+
+       if (!have_mapped) {
+               return NT_STATUS_NONE_MAPPED;
+       }
+       if (!have_unmapped) {
+               return NT_STATUS_OK;
+       }
+       return STATUS_SOME_UNMAPPED;
+
+ do_query:
+
+       TALLOC_FREE(*names);
+       TALLOC_FREE(*types);
+
+       result = domain->backend->rids_to_names(domain, mem_ctx, domain_sid,
+                                               rids, num_rids, domain_name,
+                                               names, types);
+
+       if (!NT_STATUS_IS_OK(result) &&
+           !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
+               return result;
+       }
+
+       refresh_sequence_number(domain, False);
+
+       for (i=0; i<num_rids; i++) {
+               DOM_SID sid;
+               NTSTATUS status;
+
+               if (!sid_compose(&sid, domain_sid, rids[i])) {
+                       result = NT_STATUS_INTERNAL_ERROR;
+                       goto error;
+               }
+
+               status = (*types)[i] == SID_NAME_UNKNOWN ?
+                       NT_STATUS_NONE_MAPPED : NT_STATUS_OK;
+
+               wcache_save_sid_to_name(domain, status, &sid, *domain_name,
+                                       (*names)[i], (*types)[i]);
+       }
+
+       return result;
+
+ error:
+       
+       TALLOC_FREE(*names);
+       TALLOC_FREE(*types);
+       return result;
+}
+
 /* Lookup user information from a rid */
 static NTSTATUS query_user(struct winbindd_domain *domain, 
                           TALLOC_CTX *mem_ctx, 
@@ -1914,7 +2037,7 @@ void cache_store_response(pid_t pid, struct winbindd_response *response)
 
        fstr_sprintf(key_str, "DR/%d", pid);
        if (tdb_store(wcache->tdb, string_tdb_data(key_str), 
-                     make_tdb_data((void *)response, sizeof(*response)),
+                     make_tdb_data((const char *)response, sizeof(*response)),
                      TDB_REPLACE) == -1)
                return;
 
@@ -1928,7 +2051,7 @@ void cache_store_response(pid_t pid, struct winbindd_response *response)
 
        fstr_sprintf(key_str, "DE/%d", pid);
        if (tdb_store(wcache->tdb, string_tdb_data(key_str),
-                     make_tdb_data(response->extra_data.data,
+                     make_tdb_data((const char *)response->extra_data.data,
                                    response->length - sizeof(*response)),
                      TDB_REPLACE) == 0)
                return;
@@ -2313,7 +2436,7 @@ BOOL set_global_winbindd_state_offline(void)
                return True;
        }
 
-       wcache->tdb->ecode = 0;
+/*     wcache->tdb->ecode = 0; */
 
        data = tdb_fetch_bystring( wcache->tdb, "WINBINDD_OFFLINE" );
 
@@ -2368,6 +2491,7 @@ struct winbindd_methods cache_methods = {
        enum_local_groups,
        name_to_sid,
        sid_to_name,
+       rids_to_names,
        query_user,
        lookup_usergroups,
        lookup_useraliases,
index c1276bd9612dd7b9885ed6f46c6491a44d134c72..2b8a8898ac694dd6b0e7fe850c76a08ba434e628 100644 (file)
@@ -214,7 +214,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
                goto done;
        }
 
-       if ((*cli = cli_initialise(NULL)) == NULL) {
+       if ((*cli = cli_initialise()) == NULL) {
                DEBUG(1, ("Could not cli_initialize\n"));
                result = NT_STATUS_NO_MEMORY;
                goto done;
index 0cc35277b0550f425d8d7473b81fc3538074ce15..5908c78d9a8a180801b3cff3dedbde9ef6808fa1 100644 (file)
@@ -345,6 +345,7 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = {
        
        { WINBINDD_LOOKUPSID,            winbindd_dual_lookupsid,             "LOOKUPSID" },
        { WINBINDD_LOOKUPNAME,           winbindd_dual_lookupname,            "LOOKUPNAME" },
+       { WINBINDD_LOOKUPRIDS,           winbindd_dual_lookuprids,            "LOOKUPRIDS" },
        { WINBINDD_LIST_TRUSTDOM,        winbindd_dual_list_trusted_domains,  "LIST_TRUSTDOM" },
        { WINBINDD_INIT_CONNECTION,      winbindd_dual_init_connection,       "INIT_CONNECTION" },
        { WINBINDD_GETDCNAME,            winbindd_dual_getdcname,             "GETDCNAME" },
index 2afefcc12caa1f37343962c63b12f2b05ef153f2..6167a10c46466ceda0414c96bec0fc5c938febe3 100644 (file)
@@ -34,7 +34,7 @@
 
 /* Update this when you change the interface.  */
 
-#define WINBIND_INTERFACE_VERSION 14
+#define WINBIND_INTERFACE_VERSION 15
 
 /* Socket commands */
 
@@ -76,6 +76,7 @@ enum winbindd_cmd {
 
        WINBINDD_LOOKUPSID,
        WINBINDD_LOOKUPNAME,
+       WINBINDD_LOOKUPRIDS,
 
        /* Lookup functions */
 
index b949ea080851eef8a8b4e87a4108e4ab93e9bd8e..d73917ef830c05039c0aa3d6b197d47330bd6a58 100644 (file)
@@ -286,6 +286,18 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
        return NT_STATUS_OK;
 }
 
+static NTSTATUS rids_to_names(struct winbindd_domain *domain,
+                             TALLOC_CTX *mem_ctx,
+                             const DOM_SID *sid,
+                             uint32 *rids,
+                             size_t num_rids,
+                             char **domain_name,
+                             char ***names,
+                             enum SID_NAME_USE **types)
+{
+       return NT_STATUS_UNSUCCESSFUL;
+}
+
 /* Lookup user information from a rid or username. */
 static NTSTATUS query_user(struct winbindd_domain *domain, 
                           TALLOC_CTX *mem_ctx, 
@@ -353,15 +365,21 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
        const DOM_SID **sids;
        struct lsa_dom_info *lsa_domains;
        struct lsa_name_info *lsa_names;
+       TALLOC_CTX *tmp_ctx;
 
        if (!sid_check_is_in_our_domain(group_sid)) {
                /* There's no groups, only aliases in BUILTIN */
                return NT_STATUS_NO_SUCH_GROUP;
        }
 
-       result = pdb_enum_group_members(mem_ctx, group_sid, &rids,
+       if (!(tmp_ctx = talloc_init("lookup_groupmem"))) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       result = pdb_enum_group_members(tmp_ctx, group_sid, &rids,
                                        &num_members);
        if (!NT_STATUS_IS_OK(result)) {
+               TALLOC_FREE(tmp_ctx);
                return result;
        }
 
@@ -370,29 +388,39 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
                *sid_mem = NULL;
                *names = NULL;
                *name_types = NULL;
+               TALLOC_FREE(tmp_ctx);
                return NT_STATUS_OK;
        }
 
        *sid_mem = TALLOC_ARRAY(mem_ctx, DOM_SID, num_members);
        *names = TALLOC_ARRAY(mem_ctx, char *, num_members);
        *name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members);
-       sids = TALLOC_ARRAY(mem_ctx, const DOM_SID *, num_members);
+       sids = TALLOC_ARRAY(tmp_ctx, const DOM_SID *, num_members);
 
        if (((*sid_mem) == NULL) || ((*names) == NULL) ||
            ((*name_types) == NULL) || (sids == NULL)) {
+               TALLOC_FREE(tmp_ctx);
                return NT_STATUS_NO_MEMORY;
        }
 
+       /*
+        * Prepare an array of sid pointers for the lookup_sids calling
+        * convention.
+        */
+
        for (i=0; i<num_members; i++) {
                DOM_SID *sid = &((*sid_mem)[i]);
-               sid_copy(sid, &domain->sid);
-               sid_append_rid(sid, rids[i]);
+               if (!sid_compose(sid, &domain->sid, rids[i])) {
+                       TALLOC_FREE(tmp_ctx);
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
                sids[i] = sid;
        }
 
-       result = lookup_sids(mem_ctx, num_members, sids, 1,
+       result = lookup_sids(tmp_ctx, num_members, sids, 1,
                             &lsa_domains, &lsa_names);
        if (!NT_STATUS_IS_OK(result)) {
+               TALLOC_FREE(tmp_ctx);
                return result;
        }
 
@@ -403,8 +431,12 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
                                  sid_type_lookup(lsa_names[i].type)));
                        continue;
                }
-               (*names)[i] = talloc_steal((*names),
-                                          lsa_names[i].name);
+               if (!((*names)[i] = talloc_strdup((*names),
+                                                 lsa_names[i].name))) {
+                       TALLOC_FREE(tmp_ctx);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
                (*name_types)[i] = lsa_names[i].type;
 
                num_mapped += 1;
@@ -412,6 +444,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
 
        *num_names = num_mapped;
 
+       TALLOC_FREE(tmp_ctx);
        return NT_STATUS_OK;
 }
 
@@ -497,15 +530,21 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
        NTSTATUS nt_status;
        struct trustdom_info **domains;
        int i;
+       TALLOC_CTX *tmp_ctx;
 
        *num_domains = 0;
        *names = NULL;
        *alt_names = NULL;
        *dom_sids = NULL;
 
-       nt_status = secrets_trusted_domains(mem_ctx, num_domains,
+       if (!(tmp_ctx = talloc_init("trusted_domains"))) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       nt_status = secrets_trusted_domains(tmp_ctx, num_domains,
                                            &domains);
        if (!NT_STATUS_IS_OK(nt_status)) {
+               TALLOC_FREE(tmp_ctx);
                return nt_status;
        }
 
@@ -514,15 +553,21 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
        *dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
 
        if ((*alt_names == NULL) || (*names == NULL) || (*dom_sids == NULL)) {
+               TALLOC_FREE(tmp_ctx);
                return NT_STATUS_NO_MEMORY;
        }
 
        for (i=0; i<*num_domains; i++) {
                (*alt_names)[i] = NULL;
-               (*names)[i] = talloc_steal((*names), domains[i]->name);
+               if (!((*names)[i] = talloc_strdup((*names),
+                                                 domains[i]->name))) {
+                       TALLOC_FREE(tmp_ctx);
+                       return NT_STATUS_NO_MEMORY;
+               }
                sid_copy(&(*dom_sids)[i], &domains[i]->sid);
        }
 
+       TALLOC_FREE(tmp_ctx);
        return NT_STATUS_OK;
 }
 
@@ -534,6 +579,7 @@ struct winbindd_methods passdb_methods = {
        enum_local_groups,
        name_to_sid,
        sid_to_name,
+       rids_to_names,
        query_user,
        lookup_usergroups,
        lookup_useraliases,
index 7bc8be121317f97bfd759b283007daa055eff459..8c5d59f9af0c77090cc0a7c1b342f3d464bc5ea2 100644 (file)
@@ -125,6 +125,30 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
        return result;
 }
 
+static NTSTATUS rids_to_names(struct winbindd_domain *domain,
+                             TALLOC_CTX *mem_ctx,
+                             const DOM_SID *sid,
+                             uint32 *rids,
+                             size_t num_rids,
+                             char **domain_name,
+                             char ***names,
+                             enum SID_NAME_USE **types)
+{
+       NTSTATUS result;
+
+       result = msrpc_methods.rids_to_names(domain, mem_ctx, sid,
+                                            rids, num_rids,
+                                            domain_name, names, types);
+       if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) {
+               result = msrpc_methods.rids_to_names(domain, mem_ctx, sid,
+                                                    rids, num_rids,
+                                                    domain_name, names,
+                                                    types);
+       }
+
+       return result;
+}
+
 /* Lookup user information from a rid or username. */
 static NTSTATUS query_user(struct winbindd_domain *domain, 
                           TALLOC_CTX *mem_ctx, 
@@ -280,6 +304,7 @@ struct winbindd_methods reconnect_methods = {
        enum_local_groups,
        name_to_sid,
        sid_to_name,
+       rids_to_names,
        query_user,
        lookup_usergroups,
        lookup_useraliases,
index 27feea2f6715d84c83d3dde6998ddb62a74bbc03..d8797ee2bc6e15d6c2cec49525b6fb637c06bda4 100644 (file)
@@ -318,6 +318,58 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
        return NT_STATUS_OK;
 }
 
+NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
+                            TALLOC_CTX *mem_ctx,
+                            const DOM_SID *sid,
+                            uint32 *rids,
+                            size_t num_rids,
+                            char **domain_name,
+                            char ***names,
+                            enum SID_NAME_USE **types)
+{
+       char **domains;
+       NTSTATUS result;
+       struct rpc_pipe_client *cli;
+       POLICY_HND lsa_policy;
+       DOM_SID *sids;
+       size_t i;
+
+       DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
+
+       sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
+       if (sids == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0; i<num_rids; i++) {
+               if (!sid_compose(&sids[i], sid, rids[i])) {
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
+       }
+
+       result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
+
+       result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
+                                       num_rids, sids, &domains,
+                                       names, types);
+       if (!NT_STATUS_IS_OK(result) &&
+           !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
+               return result;
+       }
+
+       for (i=0; i<num_rids; i++) {
+               if ((*types)[i] != SID_NAME_UNKNOWN) {
+                       *domain_name = domains[i];
+                       break;
+               }
+       }
+
+       return result;
+}
+
 /* Lookup user information from a rid or username. */
 static NTSTATUS query_user(struct winbindd_domain *domain, 
                           TALLOC_CTX *mem_ctx, 
@@ -772,7 +824,6 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
        NTSTATUS result;
        POLICY_HND dom_pol;
        BOOL got_seq_num = False;
-       int retry;
        struct rpc_pipe_client *cli;
 
        DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
@@ -782,8 +833,6 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
        if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
                return NT_STATUS_NO_MEMORY;
 
-       retry = 0;
-
 #ifdef HAVE_LDAP
        if ( domain->native_mode ) 
        {
@@ -985,6 +1034,7 @@ struct winbindd_methods msrpc_methods = {
        enum_local_groups,
        msrpc_name_to_sid,
        msrpc_sid_to_name,
+       msrpc_rids_to_names,
        query_user,
        lookup_usergroups,
        msrpc_lookup_useraliases,
index d489e267cb21ecd62c6734c352417be8f13f18cb..4a9e17e4c7089f5f1d03a28fd912d95c11fbc352 100644 (file)
@@ -124,6 +124,34 @@ static void lookupname_recv(void *private_data, BOOL success,
        return;
 }
 
+void winbindd_lookuprids(struct winbindd_cli_state *state)
+{
+       struct winbindd_domain *domain;
+       DOM_SID domain_sid;
+       
+       /* Ensure null termination */
+       state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
+
+       DEBUG(10, ("lookup_rids: %s\n", state->request.data.sid));
+
+       if (!string_to_sid(&domain_sid, state->request.data.sid)) {
+               DEBUG(5, ("Could not convert %s to SID\n",
+                         state->request.data.sid));
+               request_error(state);
+               return;
+       }
+
+       domain = find_lookup_domain_from_sid(&domain_sid);
+       if (domain == NULL) {
+               DEBUG(10, ("Could not find domain for name %s\n",
+                          state->request.domain_name));
+               request_error(state);
+               return;
+       }
+
+       sendto_domain(state, domain);
+}
+
 static struct winbindd_child static_idmap_child;
 
 void init_idmap_child(void)
@@ -167,8 +195,8 @@ void winbindd_sid_to_uid(struct winbindd_cli_state *state)
 
        /* Query only the local tdb, everything else might possibly block */
 
-       result = idmap_sid_to_uid(&sid, &(state->response.data.uid),
-                                 ID_QUERY_ONLY|ID_CACHE_ONLY);
+       result = idmap_sid_to_uid(&sid, &state->response.data.uid,
+                                 IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY);
 
        if (NT_STATUS_IS_OK(result)) {
                request_ok(state);
@@ -225,8 +253,8 @@ void winbindd_sid_to_gid(struct winbindd_cli_state *state)
 
        /* Query only the local tdb, everything else might possibly block */
 
-       result = idmap_sid_to_gid(&sid, &(state->response.data.gid),
-                                 ID_QUERY_ONLY|ID_CACHE_ONLY);
+       result = idmap_sid_to_gid(&sid, &state->response.data.gid,
+                                 IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY);
 
        if (NT_STATUS_IS_OK(result)) {
                request_ok(state);
@@ -285,7 +313,7 @@ void winbindd_uid_to_sid(struct winbindd_cli_state *state)
        }
 
        status = idmap_uid_to_sid(&sid, state->request.data.uid,
-                                 ID_QUERY_ONLY | ID_CACHE_ONLY);
+                                 IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY);
 
        if (NT_STATUS_IS_OK(status)) {
                sid_to_string(state->response.data.sid.sid, &sid);
@@ -412,7 +440,7 @@ void winbindd_gid_to_sid(struct winbindd_cli_state *state)
        }
 
        status = idmap_gid_to_sid(&sid, state->request.data.gid,
-                                 ID_QUERY_ONLY | ID_CACHE_ONLY);
+                                 IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY);
 
        if (NT_STATUS_IS_OK(status)) {
                sid_to_string(state->response.data.sid.sid, &sid);
index a73b5c394cd4524340bae37a9871d97b07c22fde..8a0ebbafa50ee414def303f804b6f92e8e767e98 100644 (file)
@@ -28,8 +28,6 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
-extern userdom_struct current_user_info;
-
 static BOOL fillup_pw_field(const char *lp_template, 
                            const char *username, 
                            const char *domname,
@@ -53,15 +51,16 @@ static BOOL fillup_pw_field(const char *lp_template,
           shell. */
        
        /* The substitution of %U and %D in the 'template homedir' is done
-          by alloc_sub_specified() below. */
+          by talloc_sub_specified() below. */
 
-       templ = alloc_sub_specified(lp_template, username, domname, uid, gid);
+       templ = talloc_sub_specified(NULL, lp_template, username, domname,
+                                    uid, gid);
                
        if (!templ)
                return False;
 
        safe_strcpy(out, templ, sizeof(fstring) - 1);
-       SAFE_FREE(templ);
+       TALLOC_FREE(templ);
                
        return True;
        
@@ -109,11 +108,6 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
           defaults are /tmp for the home directory and /bin/false for
           shell. */
        
-       /* The substitution of %U and %D in the 'template homedir' is done
-          by alloc_sub_specified() below. */
-
-       fstrcpy(current_user_info.domain, dom_name);
-
        if (!fillup_pw_field(lp_template_homedir(), user_name, dom_name, 
                             pw->pw_uid, pw->pw_gid, homedir, pw->pw_dir))
                return False;
@@ -293,8 +287,6 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid)
        safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1);
        safe_strcpy(pw->pw_gecos, s->fullname, sizeof(pw->pw_gecos) - 1);
 
-       fstrcpy(current_user_info.domain, s->domain->name);
-
        if (!fillup_pw_field(lp_template_homedir(), s->username, s->domain->name, 
                             pw->pw_uid, pw->pw_gid, s->homedir, pw->pw_dir)) {
                DEBUG(5, ("Could not compose homedir\n"));
@@ -407,7 +399,7 @@ void winbindd_getpwuid(struct winbindd_cli_state *state)
                  (unsigned long)state->request.data.uid));
 
        status = idmap_uid_to_sid(&user_sid, state->request.data.uid,
-                                 ID_QUERY_ONLY | ID_CACHE_ONLY);
+                                 IDMAP_FLAG_QUERY_ONLY | IDMAP_FLAG_CACHE_ONLY);
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(5, ("Could not find SID for uid %lu\n",
index 67b94817adb0fa7440a723b49474864a91609b3c..25ba20bb9f387fbdebcc8cb75bd78ce06c88d6df 100644 (file)
@@ -1096,7 +1096,7 @@ static BOOL idmap_convert(const char *idmap_name)
                return False;
        }
 
-       bigendianheader = (idmap_tdb->flags & TDB_BIGENDIAN) ? True : False;
+       bigendianheader = (tdb_get_flags(idmap_tdb) & TDB_BIGENDIAN) ? True : False;
 
        vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION");
 
index b6c027f8714143456a922ea4bd69834901cb3cc4..c308378a227f1fc9cbcbf6ca12863744a0c92958 100644 (file)
@@ -58,6 +58,7 @@ BOOL bLoaded = False;
 
 extern pstring user_socket_options;
 extern enum protocol_types Protocol;
+extern userdom_struct current_user_info;
 
 #ifndef GLOBAL_NAME
 #define GLOBAL_NAME "global"
@@ -1702,11 +1703,13 @@ static char *lp_string(const char *s)
        if (!lp_talloc)
                lp_talloc = talloc_init("lp_talloc");
 
-       tmpstr = alloc_sub_basic(get_current_username(), s);
+       tmpstr = alloc_sub_basic(get_current_username(),
+                                current_user_info.domain, s);
        if (trim_char(tmpstr, '\"', '\"')) {
                if (strchr(tmpstr,'\"') != NULL) {
                        SAFE_FREE(tmpstr);
-                       tmpstr = alloc_sub_basic(get_current_username(),s);
+                       tmpstr = alloc_sub_basic(get_current_username(),
+                                                current_user_info.domain, s);
                }
        }
        ret = talloc_strdup(lp_talloc, tmpstr);
@@ -1741,11 +1744,16 @@ static char *lp_string(const char *s)
  const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
 #define FN_LOCAL_BOOL(fn_name,val) \
  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
-#define FN_LOCAL_CHAR(fn_name,val) \
- char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
 #define FN_LOCAL_INTEGER(fn_name,val) \
  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
 
+#define FN_LOCAL_PARM_BOOL(fn_name,val) \
+ BOOL fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
+#define FN_LOCAL_PARM_STRING(fn_name,val) \
+ char *fn_name(const struct share_params *p) {return(lp_string((LP_SNUM_OK(p->service) && ServicePtrs[(p->service)]->val) ? ServicePtrs[(p->service)]->val : sDefault.val));}
+#define FN_LOCAL_CHAR(fn_name,val) \
+ char fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
+
 FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
@@ -1981,7 +1989,7 @@ FN_LOCAL_STRING(lp_fstype, fstype)
 FN_LOCAL_LIST(lp_vfs_objects, szVfsObjects)
 FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
 static FN_LOCAL_STRING(lp_volume, volume)
-FN_LOCAL_STRING(lp_mangled_map, szMangledMap)
+FN_LOCAL_PARM_STRING(lp_mangled_map, szMangledMap)
 FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
 FN_LOCAL_STRING(lp_hide_files, szHideFiles)
 FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles)
@@ -2015,7 +2023,7 @@ FN_LOCAL_BOOL(lp_share_modes, bShareModes)
 FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
 FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
 FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
-FN_LOCAL_BOOL(lp_manglednames, bMangledNames)
+FN_LOCAL_PARM_BOOL(lp_manglednames, bMangledNames)
 FN_LOCAL_BOOL(lp_widelinks, bWidelinks)
 FN_LOCAL_BOOL(lp_symlinks, bSymlinks)
 FN_LOCAL_BOOL(lp_syncalways, bSyncAlways)
@@ -3002,7 +3010,9 @@ BOOL lp_file_list_changed(void)
                time_t mod_time;
 
                pstrcpy(n2, f->name);
-               standard_sub_basic( get_current_username(), n2, sizeof(n2) );
+               standard_sub_basic( get_current_username(),
+                                   current_user_info.domain,
+                                   n2, sizeof(n2) );
 
                DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
                             f->name, n2, ctime(&f->modtime)));
@@ -3036,7 +3046,8 @@ static BOOL handle_netbios_name(int snum, const char *pszParmValue, char **ptr)
 
        pstrcpy(netbios_name, pszParmValue);
 
-       standard_sub_basic(get_current_username(), netbios_name,sizeof(netbios_name));
+       standard_sub_basic(get_current_username(), current_user_info.domain,
+                          netbios_name, sizeof(netbios_name));
 
        ret = set_global_myname(netbios_name);
        string_set(&Globals.szNetbiosName,global_myname());
@@ -3094,7 +3105,8 @@ static BOOL handle_include(int snum, const char *pszParmValue, char **ptr)
        pstring fname;
        pstrcpy(fname, pszParmValue);
 
-       standard_sub_basic(get_current_username(), fname,sizeof(fname));
+       standard_sub_basic(get_current_username(), current_user_info.domain,
+                          fname,sizeof(fname));
 
        add_to_file_list(pszParmValue, fname);
 
@@ -4936,7 +4948,8 @@ BOOL lp_load(const char *pszFname,
 
        pstrcpy(n2, pszFname);
        
-       standard_sub_basic( get_current_username(), n2,sizeof(n2) );
+       standard_sub_basic( get_current_username(), current_user_info.domain,
+                           n2,sizeof(n2) );
 
        add_to_file_list(pszFname, n2);
 
@@ -5080,7 +5093,9 @@ int lp_servicenumber(const char *pszServiceName)
                         * service names
                         */
                        fstrcpy(serviceName, ServicePtrs[iService]->szService);
-                       standard_sub_basic(get_current_username(), serviceName,sizeof(serviceName));
+                       standard_sub_basic(get_current_username(),
+                                          current_user_info.domain,
+                                          serviceName,sizeof(serviceName));
                        if (strequal(serviceName, pszServiceName)) {
                                break;
                        }
@@ -5116,6 +5131,11 @@ int lp_servicenumber(const char *pszServiceName)
        return (iService);
 }
 
+BOOL share_defined(const char *service_name)
+{
+       return (lp_servicenumber(service_name) != -1);
+}
+
 /*******************************************************************
  A useful volume label function. 
 ********************************************************************/
index 9a19dcf437ac250ee3624fccead5e28ac63a65aa..7fd3b47826f8d1c941cd342244b8714f05043aa4 100644 (file)
@@ -140,7 +140,7 @@ BOOL login_cache_write(const struct samu *sampass, LOGIN_CACHE entry)
                         entry.acct_ctrl,
                         entry.bad_password_count,
                         entry.bad_password_time);
-       databuf.dptr = SMB_MALLOC(databuf.dsize);
+       databuf.dptr = SMB_MALLOC_ARRAY(char, databuf.dsize);
        if (!databuf.dptr) {
                SAFE_FREE(keybuf.dptr);
                return False;
index dba43ed6c4fd2eb989c75908877033f2e16d38d3..a7a3fdc94d577431838f1bb5f049610a22221644 100644 (file)
@@ -63,6 +63,7 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
 
        if ((domain == NULL) || (name == NULL)) {
                DEBUG(0, ("talloc failed\n"));
+               TALLOC_FREE(tmp_ctx);
                return False;
        }
 
@@ -74,7 +75,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
                        sid_append_rid(&sid, rid);
                        goto ok;
                }
-               goto failed;
+               TALLOC_FREE(tmp_ctx);
+               return False;
        }
 
        if (strequal(domain, builtin_domain_name())) {
@@ -86,7 +88,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
                        type = SID_NAME_ALIAS;
                        goto ok;
                }
-               goto failed;
+               TALLOC_FREE(tmp_ctx);
+               return False;
        }
 
        /* Try the explicit winbind lookup first, don't let it guess the
@@ -102,7 +105,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
                        type = SID_NAME_USER;
                        goto ok;
                }
-               goto failed;
+               TALLOC_FREE(tmp_ctx);
+               return False;
        }
 
        if (strequal(domain, unix_groups_domain_name())) {
@@ -110,11 +114,13 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
                        type = SID_NAME_DOM_GRP;
                        goto ok;
                }
-               goto failed;
+               TALLOC_FREE(tmp_ctx);
+               return False;
        }
 
        if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
-               goto failed;
+               TALLOC_FREE(tmp_ctx);
+               return False;
        }
 
        /*
@@ -201,7 +207,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
        if (strequal(name, get_global_sam_name())) {
                if (!secrets_fetch_domain_sid(name, &sid)) {
                        DEBUG(3, ("Could not fetch my SID\n"));
-                       goto failed;
+                       TALLOC_FREE(tmp_ctx);
+                       return False;
                }
                /* Swap domain and name */
                tmp = name; name = domain; domain = tmp;
@@ -214,7 +221,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
        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;
+                       TALLOC_FREE(tmp_ctx);
+                       return False;
                }
                /* Swap domain and name */
                tmp = name; name = domain; domain = tmp;
@@ -258,7 +266,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
        /* Now our local possibilities are exhausted. */
 
        if (!(flags & LOOKUP_NAME_REMOTE)) {
-               goto failed;
+               TALLOC_FREE(tmp_ctx);
+               return False;
        }
 
        /* If we are not a DC, we have to ask in our primary domain. Let
@@ -298,7 +307,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
                    (domain_type != SID_NAME_DOMAIN)) {
                        DEBUG(2, ("winbind could not find the domain's name "
                                  "it just looked up for us\n"));
-                       goto failed;
+                       TALLOC_FREE(tmp_ctx);
+                       return False;
                }
                goto ok;
        }
@@ -320,7 +330,10 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
                goto ok;
        }
 
- failed:
+       /*
+        * Ok, all possibilities tried. Fail.
+        */
+
        TALLOC_FREE(tmp_ctx);
        return False;
 
@@ -331,14 +344,26 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
                return False;
        }
 
-       if (ret_name != NULL) {
-               *ret_name = talloc_steal(mem_ctx, name);
+       /*
+        * Hand over the results to the talloc context we've been given.
+        */
+
+       if ((ret_name != NULL) &&
+           !(*ret_name = talloc_strdup(mem_ctx, name))) {
+               DEBUG(0, ("talloc failed\n"));
+               TALLOC_FREE(tmp_ctx);
+               return False;
        }
 
        if (ret_domain != NULL) {
-               char *tmp_dom = talloc_strdup(tmp_ctx, domain);
+               char *tmp_dom;
+               if (!(tmp_dom = talloc_strdup(tmp_ctx, domain))) {
+                       DEBUG(0, ("talloc failed\n"));
+                       TALLOC_FREE(tmp_ctx);
+                       return False;
+               }
                strupper_m(tmp_dom);
-               *ret_domain = talloc_steal(mem_ctx, tmp_dom);
+               *ret_domain = tmp_dom;
        }
 
        if (ret_sid != NULL) {
@@ -353,34 +378,46 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
        return True;
 }
 
-static BOOL winbind_lookup_rids(TALLOC_CTX *mem_ctx,
-                               const DOM_SID *domain_sid,
-                               int num_rids, uint32 *rids,
-                               const char **domain_name,
-                               const char **names, enum SID_NAME_USE *types)
+static BOOL wb_lookup_rids(TALLOC_CTX *mem_ctx,
+                          const DOM_SID *domain_sid,
+                          int num_rids, uint32 *rids,
+                          const char **domain_name,
+                          const char **names, enum SID_NAME_USE *types)
 {
-       /* Unless the winbind interface is upgraded, fall back to ask for
-        * individual sids. I imagine introducing a lookuprids operation that
-        * directly proxies to lsa_lookupsids to the correct DC. -- vl */
-
        int i;
-       for (i=0; i<num_rids; i++) {
-               DOM_SID sid;
+       const char **my_names;
+       enum SID_NAME_USE *my_types;
+       TALLOC_CTX *tmp_ctx;
 
-               sid_copy(&sid, domain_sid);
-               sid_append_rid(&sid, rids[i]);
+       if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
+               return False;
+       }
 
-               if (winbind_lookup_sid(mem_ctx, &sid,
-                                      *domain_name == NULL ?
-                                      domain_name : NULL,
-                                      &names[i], &types[i])) {
-                       if ((names[i] == NULL) || ((*domain_name) == NULL)) {
-                               return False;
-                       }
-               } else {
+       if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
+                                domain_name, &my_names, &my_types)) {
+               for (i=0; i<num_rids; i++) {
                        types[i] = SID_NAME_UNKNOWN;
                }
+               return True;
        }
+
+       /*
+        * winbind_lookup_rids allocates its own array. We've been given the
+        * array, so copy it over
+        */
+
+       for (i=0; i<num_rids; i++) {
+               if (my_names[i] == NULL) {
+                       TALLOC_FREE(tmp_ctx);
+                       return False;
+               }
+               if (!(names[i] = talloc_strdup(names, my_names[i]))) {
+                       TALLOC_FREE(tmp_ctx);
+                       return False;
+               }
+               types[i] = my_types[i];
+       }
+       TALLOC_FREE(tmp_ctx);
        return True;
 }
 
@@ -489,8 +526,8 @@ static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
                return True;
        }
 
-       return winbind_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
-                                  domain_name, *names, *types);
+       return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
+                             domain_name, *names, *types);
 }
 
 /*
@@ -627,18 +664,17 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
 
        int i, j;
 
-       tmp_ctx = talloc_new(mem_ctx);
-       if (tmp_ctx == NULL) {
+       if (!(tmp_ctx = talloc_new(mem_ctx))) {
                DEBUG(0, ("talloc_new failed\n"));
                return NT_STATUS_NO_MEMORY;
        }
 
-       name_infos = TALLOC_ARRAY(tmp_ctx, struct lsa_name_info, num_sids);
-       dom_infos = TALLOC_ZERO_ARRAY(tmp_ctx, struct lsa_dom_info,
+       name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
+       dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
                                      MAX_REF_DOMAINS);
        if ((name_infos == NULL) || (dom_infos == NULL)) {
                result = NT_STATUS_NO_MEMORY;
-               goto done;
+               goto fail;
        }
 
        /* First build up the data structures:
@@ -673,7 +709,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
                         */
                        if (domain_name == NULL) {
                                result = NT_STATUS_NO_MEMORY;
-                               goto done;
+                               goto fail;
                        }
                                
                        name_infos[i].rid = 0;
@@ -687,14 +723,14 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
                                        name_infos, builtin_domain_name());
                                if (name_infos[i].name == NULL) {
                                        result = NT_STATUS_NO_MEMORY;
-                                       goto done;
+                                       goto fail;
                                }
                        }
                } else {
                        /* This is a normal SID with rid component */
                        if (!sid_split_rid(&sid, &rid)) {
                                result = NT_STATUS_INVALID_PARAMETER;
-                               goto done;
+                               goto fail;
                        }
                }
 
@@ -717,7 +753,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
                if (j == MAX_REF_DOMAINS) {
                        /* TODO: What's the right error message here? */
                        result = NT_STATUS_NONE_MAPPED;
-                       goto done;
+                       goto fail;
                }
 
                if (!dom_infos[j].valid) {
@@ -730,7 +766,11 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
                                /* This name was being found above in the case
                                 * when we found a domain SID */
                                dom_infos[j].name =
-                                       talloc_steal(dom_infos, domain_name);
+                                       talloc_strdup(dom_infos, domain_name);
+                               if (dom_infos[j].name == NULL) {
+                                       result = NT_STATUS_NO_MEMORY;
+                                       goto fail;
+                               }
                        } else {
                                /* lookup_rids will take care of this */
                                dom_infos[j].name = NULL;
@@ -747,7 +787,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
 
                        if (dom_infos[j].idxs == NULL) {
                                result = NT_STATUS_NO_MEMORY;
-                               goto done;
+                               goto fail;
                        }
                }
        }
@@ -756,6 +796,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
 
        for (i=0; i<MAX_REF_DOMAINS; i++) {
                uint32_t *rids;
+               const char *domain_name = NULL;
                const char **names;
                enum SID_NAME_USE *types;
                struct lsa_dom_info *dom = &dom_infos[i];
@@ -765,11 +806,9 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
                        break;
                }
 
-               rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs);
-
-               if (rids == NULL) {
+               if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
                        result = NT_STATUS_NO_MEMORY;
-                       goto done;
+                       goto fail;
                }
 
                for (j=0; j<dom->num_idxs; j++) {
@@ -777,31 +816,40 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
                }
 
                if (!lookup_rids(tmp_ctx, &dom->sid,
-                                dom->num_idxs, rids, &dom->name,
+                                dom->num_idxs, rids, &domain_name,
                                 &names, &types)) {
                        result = NT_STATUS_NO_MEMORY;
-                       goto done;
+                       goto fail;
                }
 
-               talloc_steal(dom_infos, dom->name);
-
+               if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
+                       result = NT_STATUS_NO_MEMORY;
+                       goto fail;
+               }
+                       
                for (j=0; j<dom->num_idxs; j++) {
                        int idx = dom->idxs[j];
                        name_infos[idx].type = types[j];
                        if (types[j] != SID_NAME_UNKNOWN) {
                                name_infos[idx].name =
-                                       talloc_steal(name_infos, names[j]);
+                                       talloc_strdup(name_infos, names[j]);
+                               if (name_infos[idx].name == NULL) {
+                                       result = NT_STATUS_NO_MEMORY;
+                                       goto fail;
+                               }
                        } else {
                                name_infos[idx].name = NULL;
                        }
                }
        }
 
-       *ret_domains = talloc_steal(mem_ctx, dom_infos);
-       *ret_names = talloc_steal(mem_ctx, name_infos);
-       result = NT_STATUS_OK;
+       *ret_domains = dom_infos;
+       *ret_names = name_infos;
+       return NT_STATUS_OK;
 
- done:
+ fail:
+       TALLOC_FREE(dom_infos);
+       TALLOC_FREE(name_infos);
        TALLOC_FREE(tmp_ctx);
        return result;
 }
@@ -819,9 +867,7 @@ BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
        TALLOC_CTX *tmp_ctx;
        BOOL ret = False;
 
-       tmp_ctx = talloc_new(mem_ctx);
-
-       if (tmp_ctx == NULL) {
+       if (!(tmp_ctx = talloc_new(mem_ctx))) {
                DEBUG(0, ("talloc_new failed\n"));
                return False;
        }
@@ -835,12 +881,14 @@ BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
                goto done;
        }
 
-       if (ret_domain != NULL) {
-               *ret_domain = talloc_steal(mem_ctx, domain->name);
+       if ((ret_domain != NULL) &&
+           !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
+               goto done;
        }
 
-       if (ret_name != NULL) {
-               *ret_name = talloc_steal(mem_ctx, name->name);
+       if ((ret_name != NULL) && 
+           !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
+               goto done;
        }
 
        if (ret_type != NULL) {
index cbb30ead023f9638f168f1b63c47bf9c29cc94a6..f74b1fbe3bab9fe2fdadd4ab8e0d789bfb1853ae 100644 (file)
@@ -52,7 +52,7 @@ const char *my_sam_name(void)
 
 static int samu_destroy(void *p) 
 {
-       struct samu *user = p;
+       struct samu *user = (struct samu *)p;
 
        data_blob_clear_free( &user->lm_pw );
        data_blob_clear_free( &user->nt_pw );
@@ -111,7 +111,7 @@ struct samu *samu_new( TALLOC_CTX *ctx )
        user->profile_path = "";
        user->acct_desc = "";
        user->workstations = "";
-       user->unknown_str = "";
+       user->comment = "";
        user->munged_dial = "";
 
        user->plaintext_pw = NULL;
@@ -926,14 +926,15 @@ BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
        if (homedir) {
                fstrcpy( tmpstring, homedir );
                if (expand_explicit) {
-                       standard_sub_basic( username, tmpstring,
+                       standard_sub_basic( username, domain, tmpstring,
                                            sizeof(tmpstring) );
                }
                pdb_set_homedir(sampass, tmpstring, PDB_SET);
        }
        else {
                pdb_set_homedir(sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_home()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_home()),
                        PDB_DEFAULT);
        }
 
@@ -945,28 +946,29 @@ BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
        if (logon_script) {
                fstrcpy( tmpstring, logon_script );
                if (expand_explicit) {
-                       standard_sub_basic( username, tmpstring,
+                       standard_sub_basic( username, domain, tmpstring,
                                            sizeof(tmpstring) );
                }
                pdb_set_logon_script(sampass, tmpstring, PDB_SET);
        }
        else {
                pdb_set_logon_script(sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_script()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_script()),
                        PDB_DEFAULT);
        }
        
        if (profile_path) {     
                fstrcpy( tmpstring, profile_path );
                if (expand_explicit) {
-                       standard_sub_basic( username, tmpstring,
+                       standard_sub_basic( username, domain, tmpstring,
                                            sizeof(tmpstring) );
                }
                pdb_set_profile_path(sampass, tmpstring, PDB_SET);
        } 
        else {
                pdb_set_profile_path(sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_path()),
+                       talloc_sub_basic(sampass, username, domain, lp_logon_path()),
                        PDB_DEFAULT);
        }
 
@@ -990,7 +992,7 @@ BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
 
        pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
        if (pwHistLen) {
-               uint8 *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
+               uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
                if (!pw_hist) {
                        ret = False;
                        goto done;
index 2e69240b1afbefd143982e4fedb17f50a6a37476..3b774b510b0247241da93b42dd61f3a3cbb2983b 100644 (file)
@@ -288,9 +288,9 @@ const char *pdb_get_workstations(const struct samu *sampass)
        return sampass->workstations;
 }
 
-const char *pdb_get_unknown_str(const struct samu *sampass)
+const char *pdb_get_comment(const struct samu *sampass)
 {
-       return sampass->unknown_str;
+       return sampass->comment;
 }
 
 const char *pdb_get_munged_dial(const struct samu *sampass)
@@ -752,23 +752,22 @@ BOOL pdb_set_workstations(struct samu *sampass, const char *workstations, enum p
 }
 
 /*********************************************************************
- Set the user's 'unknown_str', whatever the heck this actually is...
  ********************************************************************/
 
-BOOL pdb_set_unknown_str(struct samu *sampass, const char *unknown_str, enum pdb_value_state flag)
+BOOL pdb_set_comment(struct samu *sampass, const char *comment, enum pdb_value_state flag)
 {
-       if (unknown_str) { 
-               sampass->unknown_str = talloc_strdup(sampass, unknown_str);
+       if (comment) { 
+               sampass->comment = talloc_strdup(sampass, comment);
                
-               if (!sampass->unknown_str) {
-                       DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n"));
+               if (!sampass->comment) {
+                       DEBUG(0, ("pdb_set_comment: talloc_strdup() failed!\n"));
                        return False;
                }
        } else {
-               sampass->unknown_str = PDB_NOT_QUITE_NULL;
+               sampass->comment = PDB_NOT_QUITE_NULL;
        }
 
-       return pdb_set_init_flags(sampass, PDB_UNKNOWNSTR, flag);
+       return pdb_set_init_flags(sampass, PDB_COMMENT, flag);
 }
 
 /*********************************************************************
@@ -1021,7 +1020,7 @@ BOOL pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext)
 
                                if (current_history_len < pwHistLen) {
                                        /* Ensure we have space for the needed history. */
-                                       uchar *new_history = TALLOC(sampass,
+                                       uchar *new_history = (uchar *)TALLOC(sampass,
                                                                pwHistLen*PW_HISTORY_ENTRY_LEN);
                                        if (!new_history) {
                                                return False;
index a0310d0c71ffbdc927192feb66dc4fdab01b9cd4..20aa72d24ee37b2a34c9948c96c530736aa5d2d4 100644 (file)
@@ -361,6 +361,15 @@ static NTSTATUS pdb_default_create_user(struct pdb_methods *methods,
                add_ret = smbrun(add_script,NULL);
                DEBUG(add_ret ? 0 : 3, ("_samr_create_user: Running the command `%s' gave %d\n",
                                        add_script, add_ret));
+
+#ifdef ENABLE_BUILD_FARM_HACKS
+               if (add_ret != 0) {
+                       DEBUG(1, ("Creating a faked user %s for build farm "
+                                 "purposes", name));
+                       faked_create_user(name);
+               }
+#endif
+
                flush_pwnam_cache();
 
                pwd = Get_Pwnam_alloc(tmp_ctx, name);
@@ -1711,7 +1720,7 @@ struct user_search {
 static BOOL next_entry_users(struct pdb_search *s,
                             struct samr_displayentry *entry)
 {
-       struct user_search *state = s->private_data;
+       struct user_search *state = (struct user_search *)s->private_data;
        struct samu *user = NULL;
 
  next:
@@ -1786,7 +1795,7 @@ struct group_search {
 static BOOL next_entry_groups(struct pdb_search *s,
                              struct samr_displayentry *entry)
 {
-       struct group_search *state = s->private_data;
+       struct group_search *state = (struct group_search *)s->private_data;
        uint32 rid;
        GROUP_MAP *map = &state->groups[state->current_group];
 
@@ -1804,7 +1813,8 @@ static BOOL next_entry_groups(struct pdb_search *s,
 
 static void search_end_groups(struct pdb_search *search)
 {
-       struct group_search *state = search->private_data;
+       struct group_search *state =
+               (struct group_search *)search->private_data;
        SAFE_FREE(state->groups);
 }
 
index 4d0c84b5433bb25a2c6b577447dea5b004ad7bbe..83f8d7183ccf6fe66abdbfb1b7639ceb816334a4 100644 (file)
@@ -650,12 +650,13 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir)) 
        {
                pdb_set_homedir( sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_home()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_home()),
                        PDB_DEFAULT );
        } else {
                pstrcpy( tmpstring, homedir );
                if (expand_explicit) {
-                       standard_sub_basic( username, tmpstring,
+                       standard_sub_basic( username, domain, tmpstring,
                                            sizeof(tmpstring) );
                }
                pdb_set_homedir(sampass, tmpstring, PDB_SET);
@@ -665,12 +666,13 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script)) 
        {
                pdb_set_logon_script( sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_script()), 
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_script()), 
                        PDB_DEFAULT );
        } else {
                pstrcpy( tmpstring, logon_script );
                if (expand_explicit) {
-                       standard_sub_basic( username, tmpstring,
+                       standard_sub_basic( username, domain, tmpstring,
                                            sizeof(tmpstring) );
                }
                pdb_set_logon_script(sampass, tmpstring, PDB_SET);
@@ -680,12 +682,13 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path)) 
        {
                pdb_set_profile_path( sampass, 
-                       talloc_sub_basic( sampass, username, lp_logon_path()),
+                       talloc_sub_basic( sampass, username, domain,
+                                         lp_logon_path()),
                        PDB_DEFAULT );
        } else {
                pstrcpy( tmpstring, profile_path );
                if (expand_explicit) {
-                       standard_sub_basic( username, tmpstring,
+                       standard_sub_basic( username, domain, tmpstring,
                                            sizeof(tmpstring) );
                }
                pdb_set_profile_path(sampass, tmpstring, PDB_SET);
@@ -787,7 +790,7 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
 
                pwHistLen = MIN(pwHistLen, MAX_PW_HISTORY_LEN);
 
-               if ((pwhist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN)) == NULL){
+               if ((pwhist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN)) == NULL){
                        DEBUG(0, ("init_sam_from_ldap: malloc failed!\n"));
                        return False;
                }
@@ -967,15 +970,14 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
        /* only update the RID if we actually need to */
        if (need_update(sampass, PDB_USERSID)) {
                fstring sid_string;
-               fstring dom_sid_string;
                const DOM_SID *user_sid = pdb_get_user_sid(sampass);
                
                switch ( ldap_state->schema_ver ) {
                        case SCHEMAVER_SAMBAACCOUNT:
                                if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) {
                                        DEBUG(1, ("init_ldap_from_sam: User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n", 
-                                               sid_to_string(sid_string, user_sid), 
-                                               sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
+                                                 sid_string_static(user_sid), 
+                                                 sid_string_static(&ldap_state->domain_sid)));
                                        return False;
                                }
                                slprintf(temp, sizeof(temp) - 1, "%i", rid);
@@ -1001,15 +1003,14 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
 
        if (need_update(sampass, PDB_GROUPSID)) {
                fstring sid_string;
-               fstring dom_sid_string;
                const DOM_SID *group_sid = pdb_get_group_sid(sampass);
                
                switch ( ldap_state->schema_ver ) {
                        case SCHEMAVER_SAMBAACCOUNT:
                                if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) {
                                        DEBUG(1, ("init_ldap_from_sam: User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
-                                               sid_to_string(sid_string, group_sid),
-                                               sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
+                                                 sid_string_static(group_sid),
+                                                 sid_string_static(&ldap_state->domain_sid)));
                                        return False;
                                }
 
@@ -1747,7 +1748,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc
        LDAPMod **mods = NULL;
        const char **attr_list;
 
-       result = pdb_get_backend_private_data(newpwd, my_methods);
+       result = (LDAPMessage *)pdb_get_backend_private_data(newpwd, my_methods);
        if (!result) {
                attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
                if (pdb_get_username(newpwd) == NULL) {
@@ -3923,7 +3924,8 @@ struct ldap_search_state {
 
 static BOOL ldapsam_search_firstpage(struct pdb_search *search)
 {
-       struct ldap_search_state *state = search->private_data;
+       struct ldap_search_state *state =
+               (struct ldap_search_state *)search->private_data;
        LDAP *ld;
        int rc = LDAP_OPERATIONS_ERROR;
 
@@ -3975,7 +3977,8 @@ static BOOL ldapsam_search_firstpage(struct pdb_search *search)
 
 static BOOL ldapsam_search_nextpage(struct pdb_search *search)
 {
-       struct ldap_search_state *state = search->private_data;
+       struct ldap_search_state *state =
+               (struct ldap_search_state *)search->private_data;
        int rc;
 
        if (!state->connection->paged_results) {
@@ -4005,7 +4008,8 @@ static BOOL ldapsam_search_nextpage(struct pdb_search *search)
 static BOOL ldapsam_search_next_entry(struct pdb_search *search,
                                      struct samr_displayentry *entry)
 {
-       struct ldap_search_state *state = search->private_data;
+       struct ldap_search_state *state =
+               (struct ldap_search_state *)search->private_data;
        BOOL result;
 
  retry:
@@ -4040,7 +4044,8 @@ static BOOL ldapsam_search_next_entry(struct pdb_search *search,
 
 static void ldapsam_search_end(struct pdb_search *search)
 {
-       struct ldap_search_state *state = search->private_data;
+       struct ldap_search_state *state =
+               (struct ldap_search_state *)search->private_data;
        int rc;
 
        if (state->pagedresults_cookie == NULL)
@@ -4156,7 +4161,8 @@ static BOOL ldapsam_search_users(struct pdb_methods *methods,
                                 struct pdb_search *search,
                                 uint32 acct_flags)
 {
-       struct ldapsam_privates *ldap_state = methods->private_data;
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)methods->private_data;
        struct ldap_search_state *state;
 
        state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
@@ -4314,7 +4320,8 @@ static BOOL ldapsam_search_grouptype(struct pdb_methods *methods,
                                      const DOM_SID *sid,
                                     enum SID_NAME_USE type)
 {
-       struct ldapsam_privates *ldap_state = methods->private_data;
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)methods->private_data;
        struct ldap_search_state *state;
 
        state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
@@ -4473,8 +4480,8 @@ static NTSTATUS ldapsam_new_rid_internal(struct pdb_methods *methods, uint32 *ri
        int i;
 
        for (i=0; i<10; i++) {
-               NTSTATUS result = ldapsam_get_new_rid(methods->private_data,
-                                                     rid);
+               NTSTATUS result = ldapsam_get_new_rid(
+                       (struct ldapsam_privates *)methods->private_data, rid);
                if (NT_STATUS_IS_OK(result)) {
                        return result;
                }
@@ -4500,7 +4507,8 @@ static BOOL ldapsam_sid_to_id(struct pdb_methods *methods,
                              const DOM_SID *sid,
                              union unid_t *id, enum SID_NAME_USE *type)
 {
-       struct ldapsam_privates *priv = methods->private_data;
+       struct ldapsam_privates *priv =
+               (struct ldapsam_privates *)methods->private_data;
        char *filter;
        const char *attrs[] = { "sambaGroupType", "gidNumber", "uidNumber",
                                NULL };
@@ -5487,7 +5495,7 @@ NTSTATUS pdb_init_ldapsam_compat(struct pdb_methods **pdb_method, const char *lo
 
        (*pdb_method)->name = "ldapsam_compat";
 
-       ldap_state = (*pdb_method)->private_data;
+       ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
        ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
 
        sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
@@ -5545,7 +5553,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
                }
        }
 
-       ldap_state = (*pdb_method)->private_data;
+       ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
        ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
 
        /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
index 08ad96efa4b9fc459e2eaa25b00e3f38dc6ae1bd..ab4a1a7f208ab32017cc27b2d8e8f239ea4c58c1 100644 (file)
@@ -241,7 +241,7 @@ static int berDecodeLoginData(
        if(retData)
        {
                retOctStrLen = *retDataLen + 1;
-               retOctStr = SMB_MALLOC(retOctStrLen);
+               retOctStr = SMB_MALLOC_ARRAY(char, retOctStrLen);
                if(!retOctStr)
                {
                        err = LDAP_OPERATIONS_ERROR;
@@ -404,7 +404,7 @@ static int nmasldap_get_simple_pwd(
        size_t  pwdBufLen, bufferLen;
 
        bufferLen = pwdBufLen = pwdLen+2;
-       pwdBuf = SMB_MALLOC(pwdBufLen); /* digest and null */
+       pwdBuf = SMB_MALLOC_ARRAY(char, pwdBufLen); /* digest and null */
        if(pwdBuf == NULL)
        {
                return LDAP_NO_MEMORY;
@@ -568,7 +568,7 @@ static int nmasldap_get_password(
        }
 
        bufferLen = pwdBufLen = *pwdSize;
-       pwdBuf = SMB_MALLOC(pwdBufLen+2);
+       pwdBuf = SMB_MALLOC_ARRAY(char, pwdBufLen+2);
        if(pwdBuf == NULL)
        {
                return LDAP_NO_MEMORY;
@@ -769,7 +769,7 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
                DEBUG(5,("pdb_nds_update_login_attempts: %s login for %s\n",
                                success ? "Successful" : "Failed", username));
 
-               result = pdb_get_backend_private_data(sam_acct, methods);
+               result = (LDAPMessage *)pdb_get_backend_private_data(sam_acct, methods);
                if (!result) {
                        attr_list = get_userattr_list(NULL,
                                                      ldap_state->schema_ver);
@@ -854,7 +854,8 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
 
 static NTSTATUS pdb_init_NDS_ldapsam_common(struct pdb_methods **pdb_method, const char *location)
 {
-       struct ldapsam_privates *ldap_state = (*pdb_method)->private_data;
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)((*pdb_method)->private_data);
 
        /* Mark this as eDirectory ldap */
        ldap_state->is_nds_ldap = True;
index a8a42196d48ac331a71e8a7be1f003faa2a5db04..aec1db48b5dffb94b608978f8bbf17c37c651e77 100644 (file)
@@ -584,7 +584,8 @@ static char *format_new_smbpasswd_entry(const struct smb_passwd *newpwd)
  Routine to add an entry to the smbpasswd file.
 *************************************************************************/
 
-static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, struct smb_passwd *newpwd)
+static NTSTATUS add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state,
+                                    struct smb_passwd *newpwd)
 {
        const char *pfile = smbpasswd_state->smbpasswd_file;
        struct smb_passwd *pwd = NULL;
@@ -605,7 +606,7 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str
 
        if (fp == NULL) {
                DEBUG(0, ("add_smbfilepwd_entry: unable to open file.\n"));
-               return False;
+               return map_nt_error_from_unix(errno);
        }
 
        /*
@@ -616,7 +617,7 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str
                if (strequal(newpwd->smb_name, pwd->smb_name)) {
                        DEBUG(0, ("add_smbfilepwd_entry: entry with name %s already exists\n", pwd->smb_name));
                        endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
-                       return False;
+                       return NT_STATUS_USER_EXISTS;
                }
        }
 
@@ -630,17 +631,18 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str
        fd = fileno(fp);
 
        if((offpos = sys_lseek(fd, 0, SEEK_END)) == -1) {
+               NTSTATUS result = map_nt_error_from_unix(errno);
                DEBUG(0, ("add_smbfilepwd_entry(sys_lseek): Failed to add entry for user %s to file %s. \
 Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
                endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
-               return False;
+               return result;
        }
 
        if((new_entry = format_new_smbpasswd_entry(newpwd)) == NULL) {
                DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \
 Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
                endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
-               return False;
+               return NT_STATUS_NO_MEMORY;
        }
 
        new_entry_length = strlen(new_entry);
@@ -651,6 +653,7 @@ Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
 #endif
 
        if ((wr_len = write(fd, new_entry, new_entry_length)) != new_entry_length) {
+               NTSTATUS result = map_nt_error_from_unix(errno);
                DEBUG(0, ("add_smbfilepwd_entry(write): %d Failed to add entry for user %s to file %s. \
 Error was %s\n", wr_len, newpwd->smb_name, pfile, strerror(errno)));
 
@@ -663,12 +666,12 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n",
 
                endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
                free(new_entry);
-               return False;
+               return result;
        }
 
        free(new_entry);
        endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
-       return True;
+       return NT_STATUS_OK;
 }
 
 /************************************************************************
@@ -1308,7 +1311,7 @@ static NTSTATUS smbpasswd_getsampwnam(struct pdb_methods *my_methods,
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
        struct smb_passwd *smb_pw;
-       void *fp = NULL;
+       FILE *fp = NULL;
 
        DEBUG(10, ("getsampwnam (smbpasswd): search by name: %s\n", username));
 
@@ -1352,7 +1355,7 @@ static NTSTATUS smbpasswd_getsampwsid(struct pdb_methods *my_methods, struct sam
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
        struct smb_passwd *smb_pw;
-       void *fp = NULL;
+       FILE *fp = NULL;
        fstring sid_str;
        uint32 rid;
        
@@ -1423,11 +1426,7 @@ static NTSTATUS smbpasswd_add_sam_account(struct pdb_methods *my_methods, struct
        }
        
        /* add the entry */
-       if(!add_smbfilepwd_entry(smbpasswd_state, &smb_pw)) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-       
-       return NT_STATUS_OK;
+       return add_smbfilepwd_entry(smbpasswd_state, &smb_pw);
 }
 
 static NTSTATUS smbpasswd_update_sam_account(struct pdb_methods *my_methods, struct samu *sampass)
index f3ae4b7b02e2bbff217290036d09ec24bd5fd773..ac8cbbe91a3d98ab631eb8395a657657ddee88a5 100644 (file)
@@ -169,7 +169,8 @@ static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buf
        }
        else {
                pdb_set_homedir(sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_home()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_home()),
                        PDB_DEFAULT);
        }
 
@@ -177,7 +178,8 @@ static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buf
                pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
        else {
                pdb_set_dir_drive(sampass, 
-                       talloc_sub_basic(sampass,  username, lp_logon_drive()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_drive()),
                        PDB_DEFAULT);
        }
 
@@ -185,7 +187,8 @@ static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buf
                pdb_set_logon_script(sampass, logon_script, PDB_SET);
        else {
                pdb_set_logon_script(sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_script()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_script()),
                        PDB_DEFAULT);
        }
        
@@ -193,7 +196,8 @@ static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buf
                pdb_set_profile_path(sampass, profile_path, PDB_SET);
        } else {
                pdb_set_profile_path(sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_path()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_path()),
                        PDB_DEFAULT);
        }
 
@@ -356,7 +360,8 @@ static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buf
        }
        else {
                pdb_set_homedir(sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_home()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_home()),
                        PDB_DEFAULT);
        }
 
@@ -364,7 +369,8 @@ static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buf
                pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
        else {
                pdb_set_dir_drive(sampass, 
-                       talloc_sub_basic(sampass,  username, lp_logon_drive()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_drive()),
                        PDB_DEFAULT);
        }
 
@@ -372,7 +378,8 @@ static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buf
                pdb_set_logon_script(sampass, logon_script, PDB_SET);
        else {
                pdb_set_logon_script(sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_script()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_script()),
                        PDB_DEFAULT);
        }
        
@@ -380,7 +387,8 @@ static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buf
                pdb_set_profile_path(sampass, profile_path, PDB_SET);
        } else {
                pdb_set_profile_path(sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_path()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_path()),
                        PDB_DEFAULT);
        }
 
@@ -541,14 +549,15 @@ BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
        if (homedir) {
                fstrcpy( tmpstring, homedir );
                if (expand_explicit) {
-                       standard_sub_basic( username, tmpstring,
+                       standard_sub_basic( username, domain, tmpstring,
                                            sizeof(tmpstring) );
                }
                pdb_set_homedir(sampass, tmpstring, PDB_SET);
        }
        else {
                pdb_set_homedir(sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_home()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_home()),
                        PDB_DEFAULT);
        }
 
@@ -560,28 +569,30 @@ BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
        if (logon_script) {
                fstrcpy( tmpstring, logon_script );
                if (expand_explicit) {
-                       standard_sub_basic( username, tmpstring,
+                       standard_sub_basic( username, domain, tmpstring,
                                            sizeof(tmpstring) );
                }
                pdb_set_logon_script(sampass, tmpstring, PDB_SET);
        }
        else {
                pdb_set_logon_script(sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_script()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_script()),
                        PDB_DEFAULT);
        }
        
        if (profile_path) {     
                fstrcpy( tmpstring, profile_path );
                if (expand_explicit) {
-                       standard_sub_basic( username, tmpstring,
+                       standard_sub_basic( username, domain, tmpstring,
                                            sizeof(tmpstring) );
                }
                pdb_set_profile_path(sampass, tmpstring, PDB_SET);
        } 
        else {
                pdb_set_profile_path(sampass, 
-                       talloc_sub_basic(sampass, username, lp_logon_path()),
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_path()),
                        PDB_DEFAULT);
        }
 
@@ -606,7 +617,7 @@ BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
        /* Change from V1 is addition of password history field. */
        pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
        if (pwHistLen) {
-               uint8 *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
+               uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
                if (!pw_hist) {
                        ret = False;
                        goto done;
@@ -901,7 +912,7 @@ static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data,
                
                /* save a copy of the key */
                
-               ptr->key.dptr = memdup( key.dptr, key.dsize );
+               ptr->key.dptr = (char *)memdup( key.dptr, key.dsize );
                if (!ptr->key.dptr) {
                        DEBUG(0,("tdbsam_traverse_setpwent: memdup failed\n"));
                        /* just return 0 and let the traversal continue */
index 04d6da2814a995499dd469785eaeb773f8fa8c73..f72a7cb8d548886ba40c207a9cda96f33087c172 100644 (file)
@@ -104,8 +104,9 @@ BOOL secrets_store(const char *key, const void *data, size_t size)
        secrets_init();
        if (!tdb)
                return False;
-       return tdb_store(tdb, string_tdb_data(key), make_tdb_data(data, size),
-                        TDB_REPLACE) == 0;
+       return tdb_trans_store(tdb, string_tdb_data(key),
+                              make_tdb_data((const char *)data, size),
+                              TDB_REPLACE) == 0;
 }
 
 
@@ -288,7 +289,8 @@ BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
                return True;
        }
 
-       if (!(pass = secrets_fetch(trust_keystr(domain), &size))) {
+       if (!(pass = (struct machine_acct_pass *)secrets_fetch(
+                     trust_keystr(domain), &size))) {
                DEBUG(5, ("secrets_fetch failed!\n"));
                return False;
        }
@@ -319,6 +321,136 @@ BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
        return True;
 }
 
+/**
+ * Pack SID passed by pointer
+ *
+ * @param pack_buf pointer to buffer which is to be filled with packed data
+ * @param bufsize size of packing buffer
+ * @param sid pointer to sid to be packed
+ *
+ * @return length of the packed representation of the whole structure
+ **/
+static size_t tdb_sid_pack(char* pack_buf, int bufsize, DOM_SID* sid)
+{
+       int idx;
+       size_t len = 0;
+       
+       if (!sid || !pack_buf) return -1;
+       
+       len += tdb_pack(pack_buf + len, bufsize - len, "bb", sid->sid_rev_num,
+                       sid->num_auths);
+       
+       for (idx = 0; idx < 6; idx++) {
+               len += tdb_pack(pack_buf + len, bufsize - len, "b",
+                               sid->id_auth[idx]);
+       }
+       
+       for (idx = 0; idx < MAXSUBAUTHS; idx++) {
+               len += tdb_pack(pack_buf + len, bufsize - len, "d",
+                               sid->sub_auths[idx]);
+       }
+       
+       return len;
+}
+
+/**
+ * Unpack SID into a pointer
+ *
+ * @param pack_buf pointer to buffer with packed representation
+ * @param bufsize size of the buffer
+ * @param sid pointer to sid structure to be filled with unpacked data
+ *
+ * @return size of structure unpacked from buffer
+ **/
+static size_t tdb_sid_unpack(char* pack_buf, int bufsize, DOM_SID* sid)
+{
+       int idx, len = 0;
+       
+       if (!sid || !pack_buf) return -1;
+
+       len += tdb_unpack(pack_buf + len, bufsize - len, "bb",
+                         &sid->sid_rev_num, &sid->num_auths);
+                         
+       for (idx = 0; idx < 6; idx++) {
+               len += tdb_unpack(pack_buf + len, bufsize - len, "b",
+                                 &sid->id_auth[idx]);
+       }
+       
+       for (idx = 0; idx < MAXSUBAUTHS; idx++) {
+               len += tdb_unpack(pack_buf + len, bufsize - len, "d",
+                                 &sid->sub_auths[idx]);
+       }
+       
+       return len;
+}
+
+/**
+ * Pack TRUSTED_DOM_PASS passed by pointer
+ *
+ * @param pack_buf pointer to buffer which is to be filled with packed data
+ * @param bufsize size of the buffer
+ * @param pass pointer to trusted domain password to be packed
+ *
+ * @return length of the packed representation of the whole structure
+ **/
+static size_t tdb_trusted_dom_pass_pack(char* pack_buf, int bufsize,
+                                       TRUSTED_DOM_PASS* pass)
+{
+       int idx, len = 0;
+       
+       if (!pack_buf || !pass) return -1;
+       
+       /* packing unicode domain name and password */
+       len += tdb_pack(pack_buf + len, bufsize - len, "d",
+                       pass->uni_name_len);
+       
+       for (idx = 0; idx < 32; idx++)
+               len +=  tdb_pack(pack_buf + len, bufsize - len, "w",
+                                pass->uni_name[idx]);
+       
+       len += tdb_pack(pack_buf + len, bufsize - len, "dPd", pass->pass_len,
+                            pass->pass, pass->mod_time);
+
+       /* packing SID structure */
+       len += tdb_sid_pack(pack_buf + len, bufsize - len, &pass->domain_sid);
+
+       return len;
+}
+
+
+/**
+ * Unpack TRUSTED_DOM_PASS passed by pointer
+ *
+ * @param pack_buf pointer to buffer with packed representation
+ * @param bufsize size of the buffer
+ * @param pass pointer to trusted domain password to be filled with unpacked data
+ *
+ * @return size of structure unpacked from buffer
+ **/
+size_t tdb_trusted_dom_pass_unpack(char* pack_buf, int bufsize,
+                                  TRUSTED_DOM_PASS* pass)
+{
+       int idx, len = 0;
+       
+       if (!pack_buf || !pass) return -1;
+
+       /* unpack unicode domain name and plaintext password */
+       len += tdb_unpack(pack_buf, bufsize - len, "d", &pass->uni_name_len);
+       
+       for (idx = 0; idx < 32; idx++)
+               len +=  tdb_unpack(pack_buf + len, bufsize - len, "w",
+                                  &pass->uni_name[idx]);
+
+       len += tdb_unpack(pack_buf + len, bufsize - len, "dPd",
+                         &pass->pass_len, &pass->pass, &pass->mod_time);
+       
+       /* unpack domain sid */
+       len += tdb_sid_unpack(pack_buf + len, bufsize - len,
+                             &pass->domain_sid);
+       
+       return len;     
+}
+
 /************************************************************************
  Routine to get account password to trusted domain
 ************************************************************************/
@@ -336,7 +468,8 @@ BOOL secrets_fetch_trusted_domain_password(const char *domain, char** pwd,
        ZERO_STRUCT(pass);
 
        /* fetching trusted domain password structure */
-       if (!(pass_buf = secrets_fetch(trustdom_keystr(domain), &size))) {
+       if (!(pass_buf = (char *)secrets_fetch(trustdom_keystr(domain),
+                                              &size))) {
                DEBUG(5, ("secrets_fetch failed!\n"));
                return False;
        }
@@ -494,7 +627,7 @@ char *secrets_fetch_machine_password(const char *domain,
                uint32 *last_set_time;
                asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain);
                strupper_m(key);
-               last_set_time = secrets_fetch(key, &size);
+               last_set_time = (unsigned int *)secrets_fetch(key, &size);
                if (last_set_time) {
                        *pass_last_set_time = IVAL(last_set_time,0);
                        SAFE_FREE(last_set_time);
@@ -509,7 +642,7 @@ char *secrets_fetch_machine_password(const char *domain,
                uint32 *channel_type;
                asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain);
                strupper_m(key);
-               channel_type = secrets_fetch(key, &size);
+               channel_type = (unsigned int *)secrets_fetch(key, &size);
                if (channel_type) {
                        *channel = IVAL(channel_type,0);
                        SAFE_FREE(channel_type);
@@ -613,7 +746,7 @@ BOOL fetch_ldap_pw(char **dn, char** pw)
                DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
        }
        
-       *pw=secrets_fetch(key, &size);
+       *pw=(char *)secrets_fetch(key, &size);
        SAFE_FREE(key);
 
        if (!size) {
@@ -631,7 +764,7 @@ BOOL fetch_ldap_pw(char **dn, char** pw)
                for (p=old_style_key; *p; p++)
                        if (*p == ',') *p = '/';
        
-               data=secrets_fetch(old_style_key, &size);
+               data=(char *)secrets_fetch(old_style_key, &size);
                if (!size && size < sizeof(old_style_pw)) {
                        DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
                        SAFE_FREE(old_style_key);
@@ -672,20 +805,35 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
 {
        TDB_LIST_NODE *keys, *k;
        char *pattern;
+       TALLOC_CTX *tmp_ctx;
+
+       if (!(tmp_ctx = talloc_new(mem_ctx))) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
        if (!secrets_init()) return NT_STATUS_ACCESS_DENIED;
        
        /* generate searching pattern */
-       pattern = talloc_asprintf(mem_ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS);
+       pattern = talloc_asprintf(tmp_ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS);
        if (pattern == NULL) {
                DEBUG(0, ("secrets_trusted_domains: talloc_asprintf() "
                          "failed!\n"));
+               TALLOC_FREE(tmp_ctx);
                return NT_STATUS_NO_MEMORY;
        }
 
-       *domains = NULL;
        *num_domains = 0;
 
+       /*
+        * Make sure that a talloc context for the trustdom_info structs
+        * exists
+        */
+
+       if (!(*domains = TALLOC_ARRAY(mem_ctx, struct trustdom_info *, 1))) {
+               TALLOC_FREE(tmp_ctx);
+               return NT_STATUS_NO_MEMORY;
+       }
+
        /* fetching trusted domains' data and collecting them in a list */
        keys = tdb_search_keys(tdb, pattern);
 
@@ -698,16 +846,17 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
                struct trustdom_info *dom_info;
                
                /* important: ensure null-termination of the key string */
-               secrets_key = talloc_strndup(mem_ctx,
+               secrets_key = talloc_strndup(tmp_ctx,
                                             k->node_key.dptr,
                                             k->node_key.dsize);
                if (!secrets_key) {
                        DEBUG(0, ("strndup failed!\n"));
                        tdb_search_list_free(keys);
+                       TALLOC_FREE(tmp_ctx);
                        return NT_STATUS_NO_MEMORY;
                }
 
-               packed_pass = secrets_fetch(secrets_key, &size);
+               packed_pass = (char *)secrets_fetch(secrets_key, &size);
                packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size,
                                                          &pass);
                /* packed representation isn't needed anymore */
@@ -727,30 +876,31 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
                        continue;
                }
 
-               dom_info = TALLOC_P(mem_ctx, struct trustdom_info);
-               if (dom_info == NULL) {
+               if (!(dom_info = TALLOC_P(*domains, struct trustdom_info))) {
                        DEBUG(0, ("talloc failed\n"));
                        tdb_search_list_free(keys);
+                       TALLOC_FREE(tmp_ctx);
                        return NT_STATUS_NO_MEMORY;
                }
 
-               if (pull_ucs2_talloc(mem_ctx, &dom_info->name,
+               if (pull_ucs2_talloc(dom_info, &dom_info->name,
                                     pass.uni_name) == (size_t)-1) {
                        DEBUG(2, ("pull_ucs2_talloc failed\n"));
                        tdb_search_list_free(keys);
+                       TALLOC_FREE(tmp_ctx);
                        return NT_STATUS_NO_MEMORY;
                }
 
                sid_copy(&dom_info->sid, &pass.domain_sid);
 
-               ADD_TO_ARRAY(mem_ctx, struct trustdom_info *, dom_info,
+               ADD_TO_ARRAY(*domains, struct trustdom_info *, dom_info,
                             domains, num_domains);
 
                if (*domains == NULL) {
                        tdb_search_list_free(keys);
+                       TALLOC_FREE(tmp_ctx);
                        return NT_STATUS_NO_MEMORY;
                }
-               talloc_steal(*domains, dom_info);
        }
        
        DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n",
@@ -758,6 +908,7 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
 
        /* free the results of searching the keys */
        tdb_search_list_free(keys);
+       TALLOC_FREE(tmp_ctx);
 
        return NT_STATUS_OK;
 }
@@ -858,9 +1009,9 @@ BOOL secrets_fetch_afs_key(const char *cell, struct afs_key *result)
 *******************************************************************************/
 void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
 {
-       *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
-       *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
-       *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
+       *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
+       *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
+       *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
        
        if (*username && **username) {
 
@@ -965,7 +1116,7 @@ BOOL secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx,
                                pdc->remote_machine,
                                pdc->domain);
 
-       value.dptr = TALLOC(mem_ctx, value.dsize);
+       value.dptr = (char *)TALLOC(mem_ctx, value.dsize);
        if (!value.dptr) {
                TALLOC_FREE(keystr);
                return False;
index bcdf0e046257fa4e7b0d826fcc097180fafa7a11..4b71f6e0b6688f1173d814f18c7f6e5c8797effc 100644 (file)
@@ -1281,6 +1281,8 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
        SMB_STRUCT_STAT stat_buf;
        BOOL bad_path;
 
+       NTSTATUS status;
+
        SET_STAT_INVALID(st);
        SET_STAT_INVALID(stat_buf);
        new_create_time = (time_t)0;
@@ -1291,16 +1293,16 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
 
        driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
 
-       fsp = open_file_ntcreate(conn, filepath, &stat_buf,
+       status = open_file_ntcreate(conn, filepath, &stat_buf,
                                FILE_GENERIC_READ,
                                FILE_SHARE_READ|FILE_SHARE_WRITE,
                                FILE_OPEN,
                                0,
                                FILE_ATTRIBUTE_NORMAL,
                                INTERNAL_OPEN_ONLY,
-                               NULL);
+                               NULL, &fsp);
 
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                /* Old file not found, so by definition new file is in fact newer */
                DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
                                filepath, errno));
@@ -1327,16 +1329,16 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
        pstrcpy(filepath, new_file);
        driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
 
-       fsp = open_file_ntcreate(conn, filepath, &stat_buf,
+       status = open_file_ntcreate(conn, filepath, &stat_buf,
                                FILE_GENERIC_READ,
                                FILE_SHARE_READ|FILE_SHARE_WRITE,
                                FILE_OPEN,
                                0,
                                FILE_ATTRIBUTE_NORMAL,
                                INTERNAL_OPEN_ONLY,
-                               NULL);
+                               NULL, &fsp);
 
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                /* New file not found, this shouldn't occur if the caller did its job */
                DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
                                filepath, errno));
@@ -1405,6 +1407,7 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_
        BOOL              bad_path;
        SMB_STRUCT_STAT   st;
        connection_struct *conn;
+       NTSTATUS status;
 
        SET_STAT_INVALID(st);
 
@@ -1460,16 +1463,16 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_
                goto error_exit;
        }
 
-       fsp = open_file_ntcreate(conn, driverpath, &st,
+       status = open_file_ntcreate(conn, driverpath, &st,
                                FILE_GENERIC_READ,
                                FILE_SHARE_READ|FILE_SHARE_WRITE,
                                FILE_OPEN,
                                0,
                                FILE_ATTRIBUTE_NORMAL,
                                INTERNAL_OPEN_ONLY,
-                               NULL);
+                               NULL, &fsp);
 
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
                                driverpath, errno));
                *perr = WERR_ACCESS_DENIED;
@@ -4368,7 +4371,8 @@ WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_print
                                fstrcpy( servername, print_hnd->servername );
                        else {
                                fstrcpy( servername, "%L" );
-                               standard_sub_basic( "", servername, sizeof(servername)-1 );
+                               standard_sub_basic( "", "", servername,
+                                                   sizeof(servername)-1 );
                        }
 
                        result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
@@ -5441,7 +5445,7 @@ BOOL print_access_check(struct current_user *user, int snum, int access_type)
  Check the time parameters allow a print operation.
 *****************************************************************************/
 
-BOOL print_time_access_check(int snum)
+BOOL print_time_access_check(const char *servicename)
 {
        NT_PRINTER_INFO_LEVEL *printer = NULL;
        BOOL ok = False;
@@ -5449,7 +5453,7 @@ BOOL print_time_access_check(int snum)
        struct tm *t;
        uint32 mins;
 
-       if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
+       if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
                return False;
 
        if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
index 1ea762695b1707943c24eaacbf34deaf723f9d1e..aef4e50bfaac6b5503711cb959f9731b8c32cd21 100644 (file)
@@ -30,7 +30,9 @@ for local substitution strings
 static int print_run_command(int snum, const char* printername, BOOL do_sub,
                             const char *command, int *outfd, ...)
 {
-
+       extern struct current_user current_user;
+       extern userdom_struct current_user_info;
+       
        pstring syscmd;
        char *arg;
        int ret;
@@ -56,7 +58,12 @@ static int print_run_command(int snum, const char* printername, BOOL do_sub,
        pstring_sub( syscmd, "%p", printername );
 
        if ( do_sub && snum != -1 )
-               standard_sub_snum(snum,syscmd,sizeof(syscmd));
+               standard_sub_advanced(lp_servicename(snum),
+                                     current_user_info.unix_name, "",
+                                     current_user.ut.gid,
+                                     get_current_username(),
+                                     current_user_info.domain,
+                                     syscmd, sizeof(syscmd));
                
        ret = smbrun(syscmd,outfd);
 
index c248851822b8242d83ce98446b79da0f69e85009..5278c60f992edd28a7facb94bac9a03387e15ef5 100644 (file)
@@ -28,15 +28,19 @@ open a print file and setup a fsp for it. This is a wrapper around
 print_job_start().
 ***************************************************************************/
 
-files_struct *print_fsp_open(connection_struct *conn, const char *fname)
+NTSTATUS print_fsp_open(connection_struct *conn, const char *fname,
+                       files_struct **result)
 {
        int jobid;
        SMB_STRUCT_STAT sbuf;
-       files_struct *fsp = file_new(conn);
+       files_struct *fsp;
        fstring name;
+       NTSTATUS status;
 
-       if(!fsp)
-               return NULL;
+       status = file_new(conn, &fsp);
+       if(!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
        fstrcpy( name, "Remote Downlevel Document");
        if (fname) {
@@ -50,8 +54,9 @@ files_struct *print_fsp_open(connection_struct *conn, const char *fname)
 
        jobid = print_job_start(&current_user, SNUM(conn), name, NULL);
        if (jobid == -1) {
+               status = map_nt_error_from_unix(errno);
                file_free(fsp);
-               return NULL;
+               return status;
        }
 
        /* Convert to RAP id. */
@@ -60,7 +65,7 @@ files_struct *print_fsp_open(connection_struct *conn, const char *fname)
                /* We need to delete the entry in the tdb. */
                pjob_delete(lp_const_servicename(SNUM(conn)), jobid);
                file_free(fsp);
-               return NULL;
+               return NT_STATUS_ACCESS_DENIED; /* No errno around here */
        }
 
        /* setup a full fsp */
@@ -87,7 +92,8 @@ files_struct *print_fsp_open(connection_struct *conn, const char *fname)
 
        conn->num_files_open++;
 
-       return fsp;
+       *result = fsp;
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
index 9dd6bec0be447cfdc9f34b188e5e19dc9ee7f21a..bb756c8870734ee3d54665a776f5b2f6d11f8f67 100644 (file)
@@ -839,10 +839,9 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
  Check if the print queue has been updated recently enough.
 ****************************************************************************/
 
-static void print_cache_flush(int snum)
+static void print_cache_flush(const char *sharename)
 {
        fstring key;
-       const char *sharename = lp_const_servicename(snum);
        struct tdb_print_db *pdb = get_print_db_byname(sharename);
 
        if (!pdb)
@@ -1439,6 +1438,8 @@ update the internal database from the system print queue for a queue
 
 static void print_queue_update(int snum, BOOL force)
 {
+       extern struct current_user current_user;
+       extern userdom_struct current_user_info;
        fstring key;
        fstring sharename;
        pstring lpqcommand, lprmcommand;
@@ -1456,12 +1457,22 @@ static void print_queue_update(int snum, BOOL force)
        pstrcpy( lpqcommand, lp_lpqcommand(snum));
        string_sub2( lpqcommand, "%p", PRINTERNAME(snum), sizeof(lpqcommand), 
                     False, False, False );
-       standard_sub_snum( snum, lpqcommand, sizeof(lpqcommand) );
+       standard_sub_advanced(lp_servicename(snum),
+                             current_user_info.unix_name, "",
+                             current_user.ut.gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             lpqcommand, sizeof(lpqcommand) );
        
        pstrcpy( lprmcommand, lp_lprmcommand(snum));
        string_sub2( lprmcommand, "%p", PRINTERNAME(snum), sizeof(lprmcommand), 
                     False, False, False );
-       standard_sub_snum( snum, lprmcommand, sizeof(lprmcommand) );
+       standard_sub_advanced(lp_servicename(snum),
+                             current_user_info.unix_name, "",
+                             current_user.ut.gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             lprmcommand, sizeof(lprmcommand) );
        
        /* 
         * Make sure that the background queue process exists.  
@@ -1781,7 +1792,7 @@ NT_DEVICEMODE *print_job_devmode(const char* sharename, uint32 jobid)
  Set the place in the queue for a job.
 ****************************************************************************/
 
-BOOL print_job_set_place(int snum, uint32 jobid, int place)
+BOOL print_job_set_place(const char *sharename, uint32 jobid, int place)
 {
        DEBUG(2,("print_job_set_place not implemented yet\n"));
        return False;
@@ -1791,9 +1802,8 @@ BOOL print_job_set_place(int snum, uint32 jobid, int place)
  Set the name of a job. Only possible for owner.
 ****************************************************************************/
 
-BOOL print_job_set_name(int snum, uint32 jobid, char *name)
+BOOL print_job_set_name(const char *sharename, uint32 jobid, char *name)
 {
-       const char* sharename = lp_const_servicename(snum);
        struct printjob *pjob;
 
        pjob = print_job_find(sharename, jobid);
@@ -1930,9 +1940,10 @@ static BOOL print_job_delete1(int snum, uint32 jobid)
  Return true if the current user owns the print job.
 ****************************************************************************/
 
-static BOOL is_owner(struct current_user *user, int snum, uint32 jobid)
+static BOOL is_owner(struct current_user *user, const char *servicename,
+                    uint32 jobid)
 {
-       struct printjob *pjob = print_job_find(lp_const_servicename(snum), jobid);
+       struct printjob *pjob = print_job_find(servicename, jobid);
        user_struct *vuser;
 
        if (!pjob || !user)
@@ -1958,7 +1969,7 @@ BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR
 
        *errcode = WERR_OK;
                
-       owner = is_owner(user, snum, jobid);
+       owner = is_owner(user, lp_const_servicename(snum), jobid);
        
        /* Check access against security descriptor or whether the user
           owns their job. */
@@ -2037,7 +2048,7 @@ BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *
                return False;
        }
 
-       if (!is_owner(user, snum, jobid) &&
+       if (!is_owner(user, lp_const_servicename(snum), jobid) &&
            !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
                DEBUG(3, ("pause denied by security descriptor\n"));
 
@@ -2061,7 +2072,7 @@ pause, or resume print job. User name: %s. Printer name: %s.",
        }
 
        /* force update the database */
-       print_cache_flush(snum);
+       print_cache_flush(lp_const_servicename(snum));
 
        /* Send a printer notify message */
 
@@ -2097,7 +2108,7 @@ BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR
                return False;
        }
 
-       if (!is_owner(user, snum, jobid) &&
+       if (!is_owner(user, lp_const_servicename(snum), jobid) &&
            !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
                DEBUG(3, ("resume denied by security descriptor\n"));
                *errcode = WERR_ACCESS_DENIED;
@@ -2119,7 +2130,7 @@ pause, or resume print job. User name: %s. Printer name: %s.",
        }
 
        /* force update the database */
-       print_cache_flush(snum);
+       print_cache_flush(lp_const_servicename(snum));
 
        /* Send a printer notify message */
 
@@ -2325,7 +2336,7 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE
                return (uint32)-1;
        }
 
-       if (!print_time_access_check(snum)) {
+       if (!print_time_access_check(lp_servicename(snum))) {
                DEBUG(3, ("print_job_start: job start denied by time check\n"));
                release_print_db(pdb);
                return (uint32)-1;
@@ -2739,7 +2750,7 @@ BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode)
        }
 
        /* force update the database */
-       print_cache_flush(snum);
+       print_cache_flush(lp_const_servicename(snum));
 
        /* Send a printer notify message */
 
@@ -2805,7 +2816,7 @@ BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode)
                become_root();
 
        for (i=0;i<njobs;i++) {
-               BOOL owner = is_owner(user, snum, queue[i].job);
+               BOOL owner = is_owner(user, lp_const_servicename(snum), queue[i].job);
 
                if (owner || can_job_admin) {
                        print_job_delete1(snum, queue[i].job);
index c3512ec01d83eca19b232ffc8883354b3fc9ea5f..926cc508dd2c46c97b8406cdcb08b75456f7c88d 100644 (file)
@@ -2,7 +2,8 @@
    Unix SMB/CIFS implementation.
    store smbd profiling information in shared memory
    Copyright (C) Andrew Tridgell 1999
-   
+   Copyright (C) James Peach 2006
+
    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
@@ -249,4 +250,182 @@ BOOL profile_setup(BOOL rdonly)
        message_register(MSG_REQ_PROFILELEVEL, reqprofile_message);
        return True;
 }
+
+ const char * profile_value_name(enum profile_stats_values val)
+{
+       static const char * valnames[PR_VALUE_MAX + 1] =
+       {
+           "smbd_idle",                /* PR_VALUE_SMBD_IDLE */
+           "syscall_opendir",          /* PR_VALUE_SYSCALL_OPENDIR */
+           "syscall_readdir",          /* PR_VALUE_SYSCALL_READDIR */
+           "syscall_seekdir",          /* PR_VALUE_SYSCALL_SEEKDIR */
+           "syscall_telldir",          /* PR_VALUE_SYSCALL_TELLDIR */
+           "syscall_rewinddir",        /* PR_VALUE_SYSCALL_REWINDDIR */
+           "syscall_mkdir",            /* PR_VALUE_SYSCALL_MKDIR */
+           "syscall_rmdir",            /* PR_VALUE_SYSCALL_RMDIR */
+           "syscall_closedir",         /* PR_VALUE_SYSCALL_CLOSEDIR */
+           "syscall_open",             /* PR_VALUE_SYSCALL_OPEN */
+           "syscall_close",            /* PR_VALUE_SYSCALL_CLOSE */
+           "syscall_read",             /* PR_VALUE_SYSCALL_READ */
+           "syscall_pread",            /* PR_VALUE_SYSCALL_PREAD */
+           "syscall_write",            /* PR_VALUE_SYSCALL_WRITE */
+           "syscall_pwrite",           /* PR_VALUE_SYSCALL_PWRITE */
+           "syscall_lseek",            /* PR_VALUE_SYSCALL_LSEEK */
+           "syscall_sendfile",         /* PR_VALUE_SYSCALL_SENDFILE */
+           "syscall_rename",           /* PR_VALUE_SYSCALL_RENAME */
+           "syscall_fsync",            /* PR_VALUE_SYSCALL_FSYNC */
+           "syscall_stat",             /* PR_VALUE_SYSCALL_STAT */
+           "syscall_fstat",            /* PR_VALUE_SYSCALL_FSTAT */
+           "syscall_lstat",            /* PR_VALUE_SYSCALL_LSTAT */
+           "syscall_unlink",           /* PR_VALUE_SYSCALL_UNLINK */
+           "syscall_chmod",            /* PR_VALUE_SYSCALL_CHMOD */
+           "syscall_fchmod",           /* PR_VALUE_SYSCALL_FCHMOD */
+           "syscall_chown",            /* PR_VALUE_SYSCALL_CHOWN */
+           "syscall_fchown",           /* PR_VALUE_SYSCALL_FCHOWN */
+           "syscall_chdir",            /* PR_VALUE_SYSCALL_CHDIR */
+           "syscall_getwd",            /* PR_VALUE_SYSCALL_GETWD */
+           "syscall_utime",            /* PR_VALUE_SYSCALL_UTIME */
+           "syscall_ftruncate",        /* PR_VALUE_SYSCALL_FTRUNCATE */
+           "syscall_fcntl_lock",       /* PR_VALUE_SYSCALL_FCNTL_LOCK */
+           "syscall_fcntl_getlock",    /* PR_VALUE_SYSCALL_FCNTL_GETLOCK */
+           "syscall_readlink",         /* PR_VALUE_SYSCALL_READLINK */
+           "syscall_symlink",          /* PR_VALUE_SYSCALL_SYMLINK */
+           "syscall_link",             /* PR_VALUE_SYSCALL_LINK */
+           "syscall_mknod",            /* PR_VALUE_SYSCALL_MKNOD */
+           "syscall_realpath",         /* PR_VALUE_SYSCALL_REALPATH */
+           "syscall_get_quota",        /* PR_VALUE_SYSCALL_GET_QUOTA */
+           "syscall_set_quota",        /* PR_VALUE_SYSCALL_SET_QUOTA */
+           "SMBmkdir",         /* PR_VALUE_SMBMKDIR */
+           "SMBrmdir",         /* PR_VALUE_SMBRMDIR */
+           "SMBopen",          /* PR_VALUE_SMBOPEN */
+           "SMBcreate",        /* PR_VALUE_SMBCREATE */
+           "SMBclose",         /* PR_VALUE_SMBCLOSE */
+           "SMBflush",         /* PR_VALUE_SMBFLUSH */
+           "SMBunlink",        /* PR_VALUE_SMBUNLINK */
+           "SMBmv",            /* PR_VALUE_SMBMV */
+           "SMBgetatr",        /* PR_VALUE_SMBGETATR */
+           "SMBsetatr",        /* PR_VALUE_SMBSETATR */
+           "SMBread",          /* PR_VALUE_SMBREAD */
+           "SMBwrite",         /* PR_VALUE_SMBWRITE */
+           "SMBlock",          /* PR_VALUE_SMBLOCK */
+           "SMBunlock",        /* PR_VALUE_SMBUNLOCK */
+           "SMBctemp",         /* PR_VALUE_SMBCTEMP */
+           "SMBmknew",         /* PR_VALUE_SMBMKNEW */
+           "SMBchkpth",        /* PR_VALUE_SMBCHKPTH */
+           "SMBexit",          /* PR_VALUE_SMBEXIT */
+           "SMBlseek",         /* PR_VALUE_SMBLSEEK */
+           "SMBlockread",              /* PR_VALUE_SMBLOCKREAD */
+           "SMBwriteunlock",           /* PR_VALUE_SMBWRITEUNLOCK */
+           "SMBreadbraw",              /* PR_VALUE_SMBREADBRAW */
+           "SMBreadBmpx",              /* PR_VALUE_SMBREADBMPX */
+           "SMBreadBs",                /* PR_VALUE_SMBREADBS */
+           "SMBwritebraw",             /* PR_VALUE_SMBWRITEBRAW */
+           "SMBwriteBmpx",             /* PR_VALUE_SMBWRITEBMPX */
+           "SMBwriteBs",               /* PR_VALUE_SMBWRITEBS */
+           "SMBwritec",                /* PR_VALUE_SMBWRITEC */
+           "SMBsetattrE",              /* PR_VALUE_SMBSETATTRE */
+           "SMBgetattrE",              /* PR_VALUE_SMBGETATTRE */
+           "SMBlockingX",              /* PR_VALUE_SMBLOCKINGX */
+           "SMBtrans",         /* PR_VALUE_SMBTRANS */
+           "SMBtranss",        /* PR_VALUE_SMBTRANSS */
+           "SMBioctl",         /* PR_VALUE_SMBIOCTL */
+           "SMBioctls",        /* PR_VALUE_SMBIOCTLS */
+           "SMBcopy",          /* PR_VALUE_SMBCOPY */
+           "SMBmove",          /* PR_VALUE_SMBMOVE */
+           "SMBecho",          /* PR_VALUE_SMBECHO */
+           "SMBwriteclose",    /* PR_VALUE_SMBWRITECLOSE */
+           "SMBopenX",         /* PR_VALUE_SMBOPENX */
+           "SMBreadX",         /* PR_VALUE_SMBREADX */
+           "SMBwriteX",        /* PR_VALUE_SMBWRITEX */
+           "SMBtrans2",        /* PR_VALUE_SMBTRANS2 */
+           "SMBtranss2",       /* PR_VALUE_SMBTRANSS2 */
+           "SMBfindclose",     /* PR_VALUE_SMBFINDCLOSE */
+           "SMBfindnclose",    /* PR_VALUE_SMBFINDNCLOSE */
+           "SMBtcon",          /* PR_VALUE_SMBTCON */
+           "SMBtdis",          /* PR_VALUE_SMBTDIS */
+           "SMBnegprot",       /* PR_VALUE_SMBNEGPROT */
+           "SMBsesssetupX",    /* PR_VALUE_SMBSESSSETUPX */
+           "SMBulogoffX",      /* PR_VALUE_SMBULOGOFFX */
+           "SMBtconX",         /* PR_VALUE_SMBTCONX */
+           "SMBdskattr",               /* PR_VALUE_SMBDSKATTR */
+           "SMBsearch",                /* PR_VALUE_SMBSEARCH */
+           "SMBffirst",                /* PR_VALUE_SMBFFIRST */
+           "SMBfunique",               /* PR_VALUE_SMBFUNIQUE */
+           "SMBfclose",                /* PR_VALUE_SMBFCLOSE */
+           "SMBnttrans",               /* PR_VALUE_SMBNTTRANS */
+           "SMBnttranss",              /* PR_VALUE_SMBNTTRANSS */
+           "SMBntcreateX",             /* PR_VALUE_SMBNTCREATEX */
+           "SMBntcancel",              /* PR_VALUE_SMBNTCANCEL */
+           "SMBntrename",              /* PR_VALUE_SMBNTRENAME */
+           "SMBsplopen",               /* PR_VALUE_SMBSPLOPEN */
+           "SMBsplwr",                 /* PR_VALUE_SMBSPLWR */
+           "SMBsplclose",              /* PR_VALUE_SMBSPLCLOSE */
+           "SMBsplretq",               /* PR_VALUE_SMBSPLRETQ */
+           "SMBsends",                 /* PR_VALUE_SMBSENDS */
+           "SMBsendb",                 /* PR_VALUE_SMBSENDB */
+           "SMBfwdname",               /* PR_VALUE_SMBFWDNAME */
+           "SMBcancelf",               /* PR_VALUE_SMBCANCELF */
+           "SMBgetmac",                /* PR_VALUE_SMBGETMAC */
+           "SMBsendstrt",              /* PR_VALUE_SMBSENDSTRT */
+           "SMBsendend",               /* PR_VALUE_SMBSENDEND */
+           "SMBsendtxt",               /* PR_VALUE_SMBSENDTXT */
+           "SMBinvalid",               /* PR_VALUE_SMBINVALID */
+           "pathworks_setdir",         /* PR_VALUE_PATHWORKS_SETDIR */
+           "Trans2_open",              /* PR_VALUE_TRANS2_OPEN */
+           "Trans2_findfirst",         /* PR_VALUE_TRANS2_FINDFIRST */
+           "Trans2_findnext",          /* PR_VALUE_TRANS2_FINDNEXT */
+           "Trans2_qfsinfo",           /* PR_VALUE_TRANS2_QFSINFO */
+           "Trans2_setfsinfo",         /* PR_VALUE_TRANS2_SETFSINFO */
+           "Trans2_qpathinfo",         /* PR_VALUE_TRANS2_QPATHINFO */
+           "Trans2_setpathinfo",       /* PR_VALUE_TRANS2_SETPATHINFO */
+           "Trans2_qfileinfo",         /* PR_VALUE_TRANS2_QFILEINFO */
+           "Trans2_setfileinfo",       /* PR_VALUE_TRANS2_SETFILEINFO */
+           "Trans2_fsctl",             /* PR_VALUE_TRANS2_FSCTL */
+           "Trans2_ioctl",             /* PR_VALUE_TRANS2_IOCTL */
+           "Trans2_findnotifyfirst",   /* PR_VALUE_TRANS2_FINDNOTIFYFIRST */
+           "Trans2_findnotifynext",    /* PR_VALUE_TRANS2_FINDNOTIFYNEXT */
+           "Trans2_mkdir",             /* PR_VALUE_TRANS2_MKDIR */
+           "Trans2_session_setup",     /* PR_VALUE_TRANS2_SESSION_SETUP */
+           "Trans2_get_dfs_referral",  /* PR_VALUE_TRANS2_GET_DFS_REFERRAL */
+           "Trans2_report_dfs_inconsistancy",  /* PR_VALUE_TRANS2_REPORT_DFS_INCONSISTANCY */
+           "NT_transact_create",       /* PR_VALUE_NT_TRANSACT_CREATE */
+           "NT_transact_ioctl",        /* PR_VALUE_NT_TRANSACT_IOCTL */
+           "NT_transact_set_security_desc",    /* PR_VALUE_NT_TRANSACT_SET_SECURITY_DESC */
+           "NT_transact_notify_change",/* PR_VALUE_NT_TRANSACT_NOTIFY_CHANGE */
+           "NT_transact_rename",       /* PR_VALUE_NT_TRANSACT_RENAME */
+           "NT_transact_query_security_desc",  /* PR_VALUE_NT_TRANSACT_QUERY_SECURITY_DESC */
+           "NT_transact_get_user_quota",/* PR_VALUE_NT_TRANSACT_GET_USER_QUOTA */
+           "NT_transact_set_user_quota",/* PR_VALUE_NT_TRANSACT_SET_USER_QUOTA */
+           "get_nt_acl",               /* PR_VALUE_GET_NT_ACL */
+           "fget_nt_acl",              /* PR_VALUE_FGET_NT_ACL */
+           "set_nt_acl",               /* PR_VALUE_SET_NT_ACL */
+           "fset_nt_acl",              /* PR_VALUE_FSET_NT_ACL */
+           "chmod_acl",                /* PR_VALUE_CHMOD_ACL */
+           "fchmod_acl",               /* PR_VALUE_FCHMOD_ACL */
+           "name_release",             /* PR_VALUE_NAME_RELEASE */
+           "name_refresh",             /* PR_VALUE_NAME_REFRESH */
+           "name_registration",        /* PR_VALUE_NAME_REGISTRATION */
+           "node_status",              /* PR_VALUE_NODE_STATUS */
+           "name_query",               /* PR_VALUE_NAME_QUERY */
+           "host_announce",            /* PR_VALUE_HOST_ANNOUNCE */
+           "workgroup_announce",       /* PR_VALUE_WORKGROUP_ANNOUNCE */
+           "local_master_announce",    /* PR_VALUE_LOCAL_MASTER_ANNOUNCE */
+           "master_browser_announce",  /* PR_VALUE_MASTER_BROWSER_ANNOUNCE */
+           "lm_host_announce",         /* PR_VALUE_LM_HOST_ANNOUNCE */
+           "get_backup_list",          /* PR_VALUE_GET_BACKUP_LIST */
+           "reset_browser",            /* PR_VALUE_RESET_BROWSER */
+           "announce_request",         /* PR_VALUE_ANNOUNCE_REQUEST */
+           "lm_announce_request",      /* PR_VALUE_LM_ANNOUNCE_REQUEST */
+           "domain_logon",             /* PR_VALUE_DOMAIN_LOGON */
+           "sync_browse_lists",        /* PR_VALUE_SYNC_BROWSE_LISTS */
+           "run_elections",            /* PR_VALUE_RUN_ELECTIONS */
+           "election",                 /* PR_VALUE_ELECTION */
+           "" /* PR_VALUE_MAX */
+       };
+
+       SMB_ASSERT(val >= 0);
+       SMB_ASSERT(val < PR_VALUE_MAX);
+       return valnames[val];
+}
+
 #endif /* WITH_PROFILE */
index 679c113f397b2533ad511b0139adfce16d65fe29..f92a9e258dcac7237e70ac97498902c366aea520 100644 (file)
@@ -43,7 +43,7 @@ static PyObject *py_smb_connect(PyObject *self, PyObject *args, PyObject *kw)
        if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &server))
                return NULL;
 
-       if (!(cli = cli_initialise(NULL)))
+       if (!(cli = cli_initialise()))
                return NULL;
 
        ZERO_STRUCT(ip);
index 3ecff3d69641204181e3fd7b3a1817387f4cc1ac..338bc7af6a775d03656faab1d5852b899c239520 100644 (file)
@@ -382,7 +382,6 @@ static void fill_in_printer_values( NT_PRINTER_INFO_LEVEL_2 *info2, REGVAL_CTR *
        UNISTR2         data;
        char            *p;
        uint32 printer_status = PRINTER_STATUS_OK;
-       int snum;
        
        regval_ctr_addvalue( values, "Attributes",       REG_DWORD, (char*)&info2->attributes,       sizeof(info2->attributes) );
        regval_ctr_addvalue( values, "Priority",         REG_DWORD, (char*)&info2->priority,         sizeof(info2->attributes) );
@@ -438,8 +437,7 @@ static void fill_in_printer_values( NT_PRINTER_INFO_LEVEL_2 *info2, REGVAL_CTR *
 
        /* stream the device mode */
                
-       snum = lp_servicenumber(info2->sharename);
-       if ( (devmode = construct_dev_mode( snum )) != NULL ) {                 
+       if ( (devmode = construct_dev_mode( info2->sharename )) != NULL ) {
                if ( spoolss_io_devmode( "devmode", &prs, 0, devmode ) ) {
                        offset = prs_offset( &prs );
                        regval_ctr_addvalue( values, "Default Devmode", REG_BINARY, prs_data_p(&prs), offset );
index 97d8eb621be8cb95bc4ff7f57a4360dc3238d8d1..7e29332ef97439f77549457641293bdcc4c2038f 100644 (file)
@@ -1284,43 +1284,43 @@ done:
 BOOL fetch_domain_sid( char *domain, char *remote_machine, DOM_SID *psid)
 {
        extern pstring global_myname;
-       struct cli_state cli;
+       struct cli_state *cli;
        NTSTATUS result;
        POLICY_HND lsa_pol;
        BOOL ret = False;
  
        ZERO_STRUCT(cli);
-       if(cli_initialise(&cli) == False) {
+       if((cli = cli_initialise()) == NULL) {
                DEBUG(0,("fetch_domain_sid: unable to initialize client connection.\n"));
                return False;
        }
  
-       if(!resolve_name( remote_machine, &cli.dest_ip, 0x20)) {
+       if(!resolve_name( remote_machine, &cli->dest_ip, 0x20)) {
                DEBUG(0,("fetch_domain_sid: Can't resolve address for %s\n", remote_machine));
                goto done;
        }
  
-       if (!cli_connect(&cli, remote_machine, &cli.dest_ip)) {
+       if (!cli_connect(cli, remote_machine, &cli->dest_ip)) {
                DEBUG(0,("fetch_domain_sid: unable to connect to SMB server on \
-machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
+machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
                goto done;
        }
 
-       if (!attempt_netbios_session_request(&cli, global_myname, remote_machine, &cli.dest_ip)) {
+       if (!attempt_netbios_session_request(cli, global_myname, remote_machine, &cli->dest_ip)) {
                DEBUG(0,("fetch_domain_sid: machine %s rejected the NetBIOS session request.\n", 
                        remote_machine));
                goto done;
        }
  
-       cli.protocol = PROTOCOL_NT1;
+       cli->protocol = PROTOCOL_NT1;
  
-       if (!cli_negprot(&cli)) {
+       if (!cli_negprot(cli)) {
                DEBUG(0,("fetch_domain_sid: machine %s rejected the negotiate protocol. \
-Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
+Error was : %s.\n", remote_machine, cli_errstr(cli) ));
                goto done;
        }
  
-       if (cli.protocol != PROTOCOL_NT1) {
+       if (cli->protocol != PROTOCOL_NT1) {
                DEBUG(0,("fetch_domain_sid: machine %s didn't negotiate NT protocol.\n",
                        remote_machine));
                goto done;
@@ -1330,39 +1330,39 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
         * Do an anonymous session setup.
         */
  
-       if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) {
+       if (!cli_session_setup(cli, "", "", 0, "", 0, "")) {
                DEBUG(0,("fetch_domain_sid: machine %s rejected the session setup. \
-Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
+Error was : %s.\n", remote_machine, cli_errstr(cli) ));
                goto done;
        }
  
-       if (!(cli.sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
+       if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
                DEBUG(0,("fetch_domain_sid: machine %s isn't in user level security mode\n",
                        remote_machine));
                goto done;
        }
 
-       if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
+       if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
                DEBUG(0,("fetch_domain_sid: machine %s rejected the tconX on the IPC$ share. \
-Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
+Error was : %s.\n", remote_machine, cli_errstr(cli) ));
                goto done;
        }
 
        /* Fetch domain sid */
  
-       if (!cli_nt_session_open(&cli, PI_LSARPC)) {
+       if (!cli_nt_session_open(cli, PI_LSARPC)) {
                DEBUG(0, ("fetch_domain_sid: Error connecting to SAM pipe\n"));
                goto done;
        }
  
-       result = cli_lsa_open_policy(&cli, cli.mem_ctx, True, SEC_RIGHTS_QUERY_VALUE, &lsa_pol);
+       result = cli_lsa_open_policy(cli, cli->mem_ctx, True, SEC_RIGHTS_QUERY_VALUE, &lsa_pol);
        if (!NT_STATUS_IS_OK(result)) {
                DEBUG(0, ("fetch_domain_sid: Error opening lsa policy handle. %s\n",
                        nt_errstr(result) ));
                goto done;
        }
  
-       result = cli_lsa_query_info_policy(&cli, cli.mem_ctx, &lsa_pol, 5, domain, psid);
+       result = cli_lsa_query_info_policy(cli, cli->mem_ctx, &lsa_pol, 5, domain, psid);
        if (!NT_STATUS_IS_OK(result)) {
                DEBUG(0, ("fetch_domain_sid: Error querying lsa policy handle. %s\n",
                        nt_errstr(result) ));
@@ -1373,7 +1373,7 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
 
   done:
 
-       cli_shutdown(&cli);
+       cli_shutdown(cli);
        return ret;
 }
 
index 0d50e94d5777014c6635e9c0b58ca50a6ca9c1f1..7b4818b4b06363963afb10166a0943804e3d2176 100644 (file)
@@ -5,6 +5,8 @@
    Copyright (C) Tim Potter 2001
    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
    Copyright (C) Jeremy Allison  2005.
+   Copyright (C) Gerald (Jerry) Carter        2006.
+
 
    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
@@ -537,38 +539,37 @@ WERROR rpccli_srvsvc_net_file_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_
 
        ZERO_STRUCTP(ctr);
 
-       ctr->switch_value = file_level;
+       ctr->level = file_level;
 
        ctr->num_entries = ctr->num_entries2 = r.ctr.num_entries;
        
        switch(file_level) {
        case 3:
-               ctr->file.info3 = TALLOC_ARRAY(mem_ctx, SRV_FILE_INFO_3, ctr->num_entries);
-               if (ctr->file.info3 == NULL) {
+               if ( (ctr->file.info3 = TALLOC_ARRAY(mem_ctx, FILE_INFO_3, ctr->num_entries)) == NULL ) {
                        return WERR_NOMEM;
                }
 
-               memset(ctr->file.info3, 0, 
-                      sizeof(SRV_FILE_INFO_3) * ctr->num_entries);
+               memset(ctr->file.info3, 0, sizeof(FILE_INFO_3) * ctr->num_entries);
 
                for (i = 0; i < r.ctr.num_entries; i++) {
-                       SRV_FILE_INFO_3 *info3 = &ctr->file.info3[i];
+                       FILE_INFO_3 *info3 = &ctr->file.info3[i];
                        char *s;
                        
                        /* Copy pointer crap */
 
-                       memcpy(&info3->info_3, &r.ctr.file.info3[i].info_3, 
-                              sizeof(FILE_INFO_3));
+                       memcpy(info3, &r.ctr.file.info3[i], sizeof(FILE_INFO_3));
 
                        /* Duplicate strings */
 
-                       s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_path_name);
-                       if (s)
-                               init_unistr2(&info3->info_3_str.uni_path_name, s, UNI_STR_TERMINATE);
+                       if ( (s = unistr2_tdup(mem_ctx, r.ctr.file.info3[i].path)) != NULL ) {
+                               info3->path = TALLOC_P( mem_ctx, UNISTR2 );
+                               init_unistr2(info3->path, s, UNI_STR_TERMINATE);
+                       }
                
-                       s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_user_name);
-                       if (s)
-                               init_unistr2(&info3->info_3_str.uni_user_name, s, UNI_STR_TERMINATE);
+                       if ( (s = unistr2_tdup(mem_ctx, r.ctr.file.info3[i].user)) != NULL ) {
+                               info3->user = TALLOC_P( mem_ctx, UNISTR2 );
+                               init_unistr2(info3->user, s, UNI_STR_TERMINATE);
+                       }
 
                }               
 
diff --git a/source/rpc_client/cli_unixinfo.c b/source/rpc_client/cli_unixinfo.c
new file mode 100644 (file)
index 0000000..b9a960d
--- /dev/null
@@ -0,0 +1,226 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   RPC pipe client
+
+   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"
+
+NTSTATUS rpccli_unixinfo_uid2sid(struct rpc_pipe_client *cli,
+                                TALLOC_CTX *mem_ctx, uid_t uid, DOM_SID *sid)
+{
+       prs_struct qbuf, rbuf;
+       UNIXINFO_Q_UID_TO_SID q;
+       UNIXINFO_R_UID_TO_SID r;
+       NTSTATUS result = NT_STATUS_NET_WRITE_FAULT;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Marshall data and send request */
+       {
+               UINT64_S uid64;
+               uid64.high = 0;
+               uid64.low = uid;
+               init_q_unixinfo_uid_to_sid(&q, uid64);
+       }
+
+       CLI_DO_RPC(cli, mem_ctx, PI_UNIXINFO, UNIXINFO_UID_TO_SID,
+               q, r,
+               qbuf, rbuf,
+               unixinfo_io_q_unixinfo_uid_to_sid,
+               unixinfo_io_r_unixinfo_uid_to_sid,
+               NT_STATUS_NET_WRITE_FAULT);
+
+       if (NT_STATUS_IS_OK(r.status) && (sid != NULL)) {
+               sid_copy(sid, &r.sid);
+       }
+
+       result = r.status;
+       return result;
+}
+
+NTSTATUS rpccli_unixinfo_sid2uid(struct rpc_pipe_client *cli,
+                                TALLOC_CTX *mem_ctx,
+                                const DOM_SID *sid, uid_t *uid)
+{
+       prs_struct qbuf, rbuf;
+       UNIXINFO_Q_SID_TO_UID q;
+       UNIXINFO_R_SID_TO_UID r;
+       NTSTATUS result = NT_STATUS_NET_WRITE_FAULT;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Marshall data and send request */
+       init_q_unixinfo_sid_to_uid(&q, sid);
+
+       CLI_DO_RPC(cli, mem_ctx, PI_UNIXINFO, UNIXINFO_SID_TO_UID,
+               q, r,
+               qbuf, rbuf,
+               unixinfo_io_q_unixinfo_sid_to_uid,
+               unixinfo_io_r_unixinfo_sid_to_uid,
+               NT_STATUS_NET_WRITE_FAULT);
+
+       if (NT_STATUS_IS_OK(r.status)) {
+               if (r.uid.high != 0) {
+                       /* 64-Bit uid's not yet handled */
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               if (uid != NULL) {
+                       *uid = r.uid.low;
+               }
+       }
+
+       result = r.status;
+       return result;
+}
+
+NTSTATUS rpccli_unixinfo_gid2sid(struct rpc_pipe_client *cli,
+                                TALLOC_CTX *mem_ctx, gid_t gid, DOM_SID *sid)
+{
+       prs_struct qbuf, rbuf;
+       UNIXINFO_Q_GID_TO_SID q;
+       UNIXINFO_R_GID_TO_SID r;
+       NTSTATUS result = NT_STATUS_NET_WRITE_FAULT;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Marshall data and send request */
+       {
+               UINT64_S gid64;
+               gid64.high = 0;
+               gid64.low = gid;
+               init_q_unixinfo_gid_to_sid(&q, gid64);
+       }
+
+       CLI_DO_RPC(cli, mem_ctx, PI_UNIXINFO, UNIXINFO_GID_TO_SID,
+               q, r,
+               qbuf, rbuf,
+               unixinfo_io_q_unixinfo_gid_to_sid,
+               unixinfo_io_r_unixinfo_gid_to_sid,
+               NT_STATUS_NET_WRITE_FAULT);
+
+       if (NT_STATUS_IS_OK(r.status) && (sid != NULL)) {
+               sid_copy(sid, &r.sid);
+       }
+
+       result = r.status;
+       return result;
+}
+
+NTSTATUS rpccli_unixinfo_sid2gid(struct rpc_pipe_client *cli,
+                                TALLOC_CTX *mem_ctx,
+                                const DOM_SID *sid, gid_t *gid)
+{
+       prs_struct qbuf, rbuf;
+       UNIXINFO_Q_SID_TO_GID q;
+       UNIXINFO_R_SID_TO_GID r;
+       NTSTATUS result = NT_STATUS_NET_WRITE_FAULT;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Marshall data and send request */
+       init_q_unixinfo_sid_to_gid(&q, sid);
+
+       CLI_DO_RPC(cli, mem_ctx, PI_UNIXINFO, UNIXINFO_SID_TO_GID,
+               q, r,
+               qbuf, rbuf,
+               unixinfo_io_q_unixinfo_sid_to_gid,
+               unixinfo_io_r_unixinfo_sid_to_gid,
+               NT_STATUS_NET_WRITE_FAULT);
+
+       if (NT_STATUS_IS_OK(r.status)) {
+               if (r.gid.high != 0) {
+                       /* 64-Bit gid's not yet handled */
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               if (gid != NULL) {
+                       *gid = r.gid.low;
+               }
+       }
+
+       result = r.status;
+       return result;
+}
+
+NTSTATUS rpccli_unixinfo_getpwuid(struct rpc_pipe_client *cli,
+                                 TALLOC_CTX *mem_ctx,
+                                 int count, uid_t *uids,
+                                 struct unixinfo_getpwuid **info)
+{
+       prs_struct qbuf, rbuf;
+       UNIXINFO_Q_GETPWUID q;
+       UNIXINFO_R_GETPWUID r;
+       NTSTATUS result = NT_STATUS_NET_WRITE_FAULT;
+       int i;
+       UINT64_S *uids64;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Marshall data and send request */
+
+       uids64 = TALLOC_ARRAY(mem_ctx, UINT64_S, count);
+       if (uids64 == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0; i<count; i++) {
+               uids64[i].high = 0;
+               uids64[i].low = uids[i];
+       }
+
+       init_q_unixinfo_getpwuid(&q, count, uids64);
+
+       CLI_DO_RPC(cli, mem_ctx, PI_UNIXINFO, UNIXINFO_GETPWUID,
+               q, r,
+               qbuf, rbuf,
+               unixinfo_io_q_unixinfo_getpwuid,
+               unixinfo_io_r_unixinfo_getpwuid,
+               NT_STATUS_NET_WRITE_FAULT);
+
+       if (!NT_STATUS_IS_OK(r.status)) {
+               result = r.status;
+               *info = NULL;
+               return result;
+       }
+
+       if (r.count != count) {
+               DEBUG(0, ("Expected array size %d, got %d\n",
+                         count, r.count));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       *info = TALLOC_ARRAY(mem_ctx, struct unixinfo_getpwuid, count);
+       if (*info == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0; i<count; i++) {
+               (*info)[i].status = r.info[i].status;
+               (*info)[i].homedir = talloc_strdup(mem_ctx, r.info[i].homedir);
+               (*info)[i].shell = talloc_strdup(mem_ctx, r.info[i].shell);
+       }
+
+       result = r.status;
+       return result;
+}
diff --git a/source/rpc_client/ndr.c b/source/rpc_client/ndr.c
new file mode 100644 (file)
index 0000000..985490f
--- /dev/null
@@ -0,0 +1,90 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   libndr interface
+
+   Copyright (C) Jelmer Vernooij 2006
+   
+   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"
+
+
+NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
+                       int p_idx, int opnum, void *data, 
+                       ndr_pull_flags_fn_t pull_fn, ndr_push_flags_fn_t push_fn)
+{
+       prs_struct q_ps, r_ps;
+       struct ndr_pull *pull;
+       DATA_BLOB blob;
+       struct ndr_push *push;
+       NTSTATUS status;
+
+       SMB_ASSERT(cli->pipe_idx == p_idx);
+
+       push = ndr_push_init_ctx(mem_ctx);
+       if (!push) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = push_fn(push, NDR_IN, data);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       blob = ndr_push_blob(push);
+
+       if (!prs_init_data_blob(&q_ps, &blob, mem_ctx)) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       talloc_free(push);
+
+       if (!prs_init( &r_ps, 0, mem_ctx, UNMARSHALL )) {
+               prs_mem_free( &q_ps );
+               return NT_STATUS_NO_MEMORY;
+       }
+       
+       status = rpc_api_pipe_req(cli, opnum, &q_ps, &r_ps); 
+
+       prs_mem_free( &q_ps );
+
+       if (!NT_STATUS_IS_OK(status)) {
+               prs_mem_free( &r_ps );
+               return status;
+       }
+
+       if (!prs_data_blob(&r_ps, &blob, mem_ctx)) {
+               prs_mem_free( &r_ps );
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       prs_mem_free( &r_ps );
+
+       pull = ndr_pull_init_blob(&blob, mem_ctx);
+       if (pull == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = pull_fn(pull, NDR_OUT, data);
+       talloc_free(pull);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       return NT_STATUS_OK;
+}
index 4aff9734eed9a0230ebd4025c4dde1ac864836f6..addf433feb8c7e9b0c0d5e645c912471d1c83871 100644 (file)
@@ -54,7 +54,7 @@ BOOL eventlog_io_q_open_eventlog(const char *desc, EVENTLOG_Q_OPEN_EVENTLOG *q_u
        if(!prs_align(ps))
                return False;
 
-       if ( !prs_pointer("", ps, depth, (void**)&q_u->unknown0, sizeof(EVENTLOG_OPEN_UNKNOWN0), (PRS_POINTER_CAST)prs_ev_open_unknown0))
+       if ( !prs_pointer("", ps, depth, (void*)&q_u->unknown0, sizeof(EVENTLOG_OPEN_UNKNOWN0), (PRS_POINTER_CAST)prs_ev_open_unknown0))
                return False;
 
        if ( !prs_unistr4("logname", ps, depth, &q_u->logname) )
index ae4cff53e4ba17b29a2afb5a3db0acd94f3cf2d8..919b7c395524c510393970dd9811f321d97ddee9 100644 (file)
@@ -664,7 +664,7 @@ BOOL lsa_io_r_enum_trust_dom(const char *desc, LSA_R_ENUM_TRUST_DOM *out,
        if(!prs_uint32("count", ps, depth, &out->count))
                return False;
 
-       if ( !prs_pointer("trusted_domains", ps, depth, (void**)&out->domlist, sizeof(DOMAIN_LIST), (PRS_POINTER_CAST)lsa_io_domain_list))
+       if ( !prs_pointer("trusted_domains", ps, depth, (void*)&out->domlist, sizeof(DOMAIN_LIST), (PRS_POINTER_CAST)lsa_io_domain_list))
                return False;
                
        if(!prs_ntstatus("status", ps, depth, &out->status))
@@ -3250,7 +3250,7 @@ BOOL lsa_io_r_enum_acct_rights(const char *desc, LSA_R_ENUM_ACCT_RIGHTS *out, pr
        if(!prs_uint32("count   ", ps, depth, &out->count))
                return False;
 
-       if ( !prs_pointer("rights", ps, depth, (void**)&out->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
+       if ( !prs_pointer("rights", ps, depth, (void*)&out->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
                return False;
 
        if(!prs_align(ps))
@@ -3302,7 +3302,7 @@ BOOL lsa_io_q_add_acct_rights(const char *desc, LSA_Q_ADD_ACCT_RIGHTS *in, prs_s
        if(!prs_uint32("count", ps, depth, &in->count))
                return False;
 
-       if ( !prs_pointer("rights", ps, depth, (void**)&in->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
+       if ( !prs_pointer("rights", ps, depth, (void*)&in->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
                return False;
 
        return True;
@@ -3371,7 +3371,7 @@ BOOL lsa_io_q_remove_acct_rights(const char *desc, LSA_Q_REMOVE_ACCT_RIGHTS *in,
        if(!prs_uint32("count", ps, depth, &in->count))
                return False;
 
-       if ( !prs_pointer("rights", ps, depth, (void**)&in->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
+       if ( !prs_pointer("rights", ps, depth, (void*)&in->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
                return False;
 
        return True;
@@ -4056,7 +4056,7 @@ BOOL lsa_io_r_query_trusted_domain_info(const char *desc,
        prs_debug(ps, depth, desc, "lsa_io_r_query_trusted_domain_info");
        depth++;
 
-       if (!prs_pointer("trustdom", ps, depth, (void**)&r_q->info, 
+       if (!prs_pointer("trustdom", ps, depth, (void*)&r_q->info, 
                         sizeof(LSA_TRUSTED_DOMAIN_INFO), 
                         (PRS_POINTER_CAST)lsa_io_trustdom_query) )
                return False;
@@ -4185,7 +4185,7 @@ BOOL lsa_io_r_query_dom_info(const char *desc, LSA_R_QUERY_DOM_INFO_POLICY *out,
        prs_debug(ps, depth, desc, "lsa_io_r_query_dom_info");
        depth++;
 
-       if (!prs_pointer("dominfo", ps, depth, (void**)&out->info, 
+       if (!prs_pointer("dominfo", ps, depth, (void*)&out->info, 
                         sizeof(LSA_DOM_INFO_UNION), 
                         (PRS_POINTER_CAST)lsa_io_dom_info_query) )
                return False;
index 599257e8020ff7025e3c03f48fe7ee142949ddcb..ab5f3f75e87bc43bc059a799bb2e8c256496c6ae 100644 (file)
@@ -77,7 +77,7 @@ BOOL ntsvcs_io_q_get_device_list_size(const char *desc, NTSVCS_Q_GET_DEVICE_LIST
        if(!prs_align(ps))
                return False;
 
-       if ( !prs_pointer("devicename", ps, depth, (void**)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) )
+       if ( !prs_pointer("devicename", ps, depth, (void*)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) )
                return False;
        if ( !prs_align(ps) )
                return False;
@@ -127,7 +127,7 @@ BOOL ntsvcs_io_q_get_device_list(const char *desc, NTSVCS_Q_GET_DEVICE_LIST *q_u
        if(!prs_align(ps))
                return False;
 
-       if ( !prs_pointer("devicename", ps, depth, (void**)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) )
+       if ( !prs_pointer("devicename", ps, depth, (void*)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) )
                return False;
        if( !prs_align(ps) )
                return False;
index 14e190892d77bd76f6b5439b73077c7dc147f768..29a3e60aa909752184a7c0e26fc3fae1c0697ea2 100644 (file)
@@ -624,9 +624,10 @@ BOOL prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8)
  ********************************************************************/
 
 BOOL prs_pointer( const char *name, prs_struct *ps, int depth, 
-                 void **data, size_t data_size,
+                 void *dta, size_t data_size,
                  BOOL(*prs_fn)(const char*, prs_struct*, int, void*) )
 {
+       void ** data = (void **)dta;
        uint32 data_p;
 
        /* output f000baaa to stream if the pointer is non-zero. */
@@ -1793,3 +1794,32 @@ BOOL schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l
        return (memcmp(digest_final, verf->packet_digest, 
                       sizeof(verf->packet_digest)) == 0);
 }
+
+/*******************************************************************
+creates a new prs_struct containing a DATA_BLOB
+********************************************************************/
+BOOL prs_init_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
+{
+       if (!prs_init( prs, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL ))
+               return False;
+
+
+       if (!prs_copy_data_in(prs, (char *)blob->data, blob->length))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+return the contents of a prs_struct in a DATA_BLOB
+********************************************************************/
+BOOL prs_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
+{
+       blob->length = prs_offset(prs);
+       blob->data = talloc_zero_size(mem_ctx, blob->length);
+
+       if (!prs_copy_all_data_out((char *)blob->data, prs))
+               return False;
+       
+       return True;
+}
index fef1332e5c7734a39d2effac1829995237e1249e..1820a595eda589938aa34ae8739dd794f2e999e7 100644 (file)
@@ -76,7 +76,7 @@ BOOL reg_io_q_open_hive(const char *desc, REG_Q_OPEN_HIVE *q_u,
        if(!prs_align(ps))
                return False;
 
-       if(!prs_pointer("server", ps, depth, (void**)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16))
+       if(!prs_pointer("server", ps, depth, (void*)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16))
                return False;
 
        if(!prs_align(ps))
@@ -276,7 +276,7 @@ BOOL reg_io_q_create_key_ex(const char *desc,  REG_Q_CREATE_KEY_EX *q_u,
        if(!prs_uint32("access", ps, depth, &q_u->access))
                return False;
 
-       if(!prs_pointer("sec_info", ps, depth, (void**)&q_u->sec_info, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
+       if(!prs_pointer("sec_info", ps, depth, (void*)&q_u->sec_info, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
                return False;
 
        if ( q_u->sec_info ) {
@@ -286,7 +286,7 @@ BOOL reg_io_q_create_key_ex(const char *desc,  REG_Q_CREATE_KEY_EX *q_u,
                        return False;
        }
 
-       if(!prs_pointer("disposition", ps, depth, (void**)&q_u->disposition, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
+       if(!prs_pointer("disposition", ps, depth, (void*)&q_u->disposition, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
                return False;
 
        return True;
@@ -1060,17 +1060,17 @@ BOOL reg_io_r_query_value(const char *desc, REG_R_QUERY_VALUE *r_u, prs_struct *
        if(!prs_align(ps))
                return False;
        
-       if ( !prs_pointer("type", ps, depth, (void**)&r_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
+       if ( !prs_pointer("type", ps, depth, (void*)&r_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
                return False;
 
-       if ( !prs_pointer("value", ps, depth, (void**)&r_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer))
+       if ( !prs_pointer("value", ps, depth, (void*)&r_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer))
                return False;
        if(!prs_align(ps))
                return False;
 
-       if ( !prs_pointer("buf_max_len", ps, depth, (void**)&r_u->buf_max_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
+       if ( !prs_pointer("buf_max_len", ps, depth, (void*)&r_u->buf_max_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
                return False;
-       if ( !prs_pointer("buf_len", ps, depth, (void**)&r_u->buf_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
+       if ( !prs_pointer("buf_len", ps, depth, (void*)&r_u->buf_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
                return False;
 
        if(!prs_werror("status", ps, depth, &r_u->status))
@@ -1207,17 +1207,17 @@ BOOL reg_io_q_enum_val(const char *desc,  REG_Q_ENUM_VALUE *q_u, prs_struct *ps,
        if(!prs_align(ps))
                return False;
 
-       if(!prs_pointer("type", ps, depth, (void**)&q_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
+       if(!prs_pointer("type", ps, depth, (void*)&q_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
                return False;
 
-       if ( !prs_pointer("value", ps, depth, (void**)&q_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer))
+       if ( !prs_pointer("value", ps, depth, (void*)&q_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer))
                return False;
        if(!prs_align(ps))
                return False;
 
-       if(!prs_pointer("buffer_len", ps, depth, (void**)&q_u->buffer_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
+       if(!prs_pointer("buffer_len", ps, depth, (void*)&q_u->buffer_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
                return False;
-       if(!prs_pointer("name_len", ps, depth, (void**)&q_u->name_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
+       if(!prs_pointer("name_len", ps, depth, (void*)&q_u->name_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
                return False;
 
        return True;
@@ -1243,17 +1243,17 @@ BOOL reg_io_r_enum_val(const char *desc,  REG_R_ENUM_VALUE *r_u, prs_struct *ps,
        if(!prs_align(ps))
                return False;
 
-       if(!prs_pointer("type", ps, depth, (void**)&r_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
+       if(!prs_pointer("type", ps, depth, (void*)&r_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
                return False;
 
-       if ( !prs_pointer("value", ps, depth, (void**)&r_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer))
+       if ( !prs_pointer("value", ps, depth, (void*)&r_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer))
                return False;
        if(!prs_align(ps))
                return False;
 
-       if(!prs_pointer("buffer_len1", ps, depth, (void**)&r_u->buffer_len1, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
+       if(!prs_pointer("buffer_len1", ps, depth, (void*)&r_u->buffer_len1, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
                return False;
-       if(!prs_pointer("buffer_len2", ps, depth, (void**)&r_u->buffer_len2, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
+       if(!prs_pointer("buffer_len2", ps, depth, (void*)&r_u->buffer_len2, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
                return False;
 
        if(!prs_werror("status", ps, depth, &r_u->status))
@@ -1457,12 +1457,12 @@ BOOL reg_io_r_enum_key(const char *desc,  REG_R_ENUM_KEY *q_u, prs_struct *ps, i
        
        if(!prs_align(ps))
                return False;
-       if (!prs_pointer("class", ps, depth, (void**)&q_u->classname, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4))
+       if (!prs_pointer("class", ps, depth, (void*)&q_u->classname, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4))
                return False;
 
        if(!prs_align(ps))
                return False;
-       if (!prs_pointer("time", ps, depth, (void**)&q_u->time, sizeof(NTTIME), (PRS_POINTER_CAST)smb_io_nttime))
+       if (!prs_pointer("time", ps, depth, (void*)&q_u->time, sizeof(NTTIME), (PRS_POINTER_CAST)smb_io_nttime))
                return False;
 
        if(!prs_align(ps))
@@ -1620,12 +1620,12 @@ BOOL reg_io_q_shutdown(const char *desc, REG_Q_SHUTDOWN *q_u, prs_struct *ps,
        if (!prs_align(ps))
                return False;
 
-       if (!prs_pointer("server", ps, depth, (void**)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16))
+       if (!prs_pointer("server", ps, depth, (void*)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16))
                return False;
        if (!prs_align(ps))
                return False;
 
-       if (!prs_pointer("message", ps, depth, (void**)&q_u->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4))
+       if (!prs_pointer("message", ps, depth, (void*)&q_u->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4))
                return False;
 
        if (!prs_align(ps))
@@ -1680,12 +1680,12 @@ BOOL reg_io_q_shutdown_ex(const char *desc, REG_Q_SHUTDOWN_EX *q_u, prs_struct *
        if (!prs_align(ps))
                return False;
 
-       if (!prs_pointer("server", ps, depth, (void**)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16))
+       if (!prs_pointer("server", ps, depth, (void*)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16))
                return False;
        if (!prs_align(ps))
                return False;
 
-       if (!prs_pointer("message", ps, depth, (void**)&q_u->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4))
+       if (!prs_pointer("message", ps, depth, (void*)&q_u->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4))
                return False;
 
        if (!prs_align(ps))
@@ -1759,7 +1759,7 @@ BOOL reg_io_q_abort_shutdown(const char *desc, REG_Q_ABORT_SHUTDOWN *q_u,
        if (!prs_align(ps))
                return False;
 
-       if (!prs_pointer("server", ps, depth, (void**)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16))
+       if (!prs_pointer("server", ps, depth, (void*)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16))
                return False;
        if (!prs_align(ps))
                return False;
index 2d166c773b4d4cafa8221ca198dc5ac516d12ee1..240cac886cfaec6b1b353de369b708ebd300d46a 100644 (file)
@@ -191,6 +191,16 @@ interface/version dce/rpc pipe identification
        }, 0x00                             \
 }
 
+#define SYNT_UNIXINFO_V0                    \
+{                                           \
+       {                                   \
+               0x9c54e310, 0xa955, 0x4885, \
+               { 0xbd, 0x31 },             \
+                { 0x78, 0x78,               \
+                  0x71, 0x47, 0xdf, 0xa6 }  \
+       }, 0x00                             \
+}
+
 #define SYNT_NTSVCS_V1                      \
 {                                           \
        {                                   \
@@ -222,6 +232,7 @@ const struct pipe_id_info pipe_names [] =
        { PIPE_SHUTDOWN, SYNT_SHUTDOWN_V1      , PIPE_SHUTDOWN , TRANS_SYNT_V2 },
        { PIPE_SVCCTL  , SYNT_SVCCTL_V2        , PIPE_NTSVCS   , TRANS_SYNT_V2 },
        { PIPE_EVENTLOG, SYNT_EVENTLOG_V0      , PIPE_EVENTLOG , TRANS_SYNT_V2 },
+       { PIPE_UNIXINFO, SYNT_UNIXINFO_V0      , PIPE_UNIXINFO , TRANS_SYNT_V2 },
        { PIPE_NTSVCS  , SYNT_NTSVCS_V1        , PIPE_NTSVCS   , TRANS_SYNT_V2 },
        { NULL         , SYNT_NONE_V0          , NULL          , SYNT_NONE_V0  }
 };
index 9026d503c307b951fb69a1fbbe9b2ebf956414d4..26da7b426d7374e0be72564f3a4333846619413c 100644 (file)
@@ -3854,7 +3854,7 @@ BOOL samr_io_r_query_aliasinfo(const char *desc, SAMR_R_QUERY_ALIASINFO *out,
        if(!prs_align(ps))
                return False;
 
-       if ( !prs_pointer("alias", ps, depth, (void**)&out->ctr, sizeof(ALIAS_INFO_CTR), (PRS_POINTER_CAST)samr_alias_info_ctr))
+       if ( !prs_pointer("alias", ps, depth, (void*)&out->ctr, sizeof(ALIAS_INFO_CTR), (PRS_POINTER_CAST)samr_alias_info_ctr))
                return False;
        if(!prs_align(ps))
                return False;
@@ -4896,7 +4896,7 @@ inits a SAMR_R_LOOKUP_NAMES structure.
 
 NTSTATUS init_samr_r_lookup_names(TALLOC_CTX *ctx, SAMR_R_LOOKUP_NAMES * r_u,
                              uint32 num_rids,
-                             uint32 *rid, uint32 *type,
+                             uint32 *rid, enum SID_NAME_USE *type,
                              NTSTATUS status)
 {
        DEBUG(5, ("init_samr_r_lookup_names\n"));
@@ -5741,8 +5741,8 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time,   /* all z
        copy_unistr2(&usr->uni_workstations, wkstas);
        init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations);
 
-       copy_unistr2(&usr->uni_unknown_str, unk_str);
-       init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str);
+       copy_unistr2(&usr->uni_comment, unk_str);
+       init_uni_hdr(&usr->hdr_comment, &usr->uni_comment);
 
        copy_unistr2(&usr->uni_munged_dial, mung_dial);
        init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
@@ -5835,8 +5835,8 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time,   /* all z
        init_unistr2(&usr->uni_workstations, wkstas, UNI_FLAGS_NONE);
        init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations);
 
-       init_unistr2(&usr->uni_unknown_str, unk_str, UNI_FLAGS_NONE);
-       init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str);
+       init_unistr2(&usr->uni_comment, unk_str, UNI_FLAGS_NONE);
+       init_uni_hdr(&usr->hdr_comment, &usr->uni_comment);
 
        init_unistr2_from_datablob(&usr->uni_munged_dial, &blob);
        init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
@@ -5895,7 +5895,7 @@ static BOOL sam_io_user_info23(const char *desc, SAM_USER_INFO_23 * usr,
                return False;
        if(!smb_io_unihdr("hdr_workstations", &usr->hdr_workstations, ps, depth))       /* wkstas user can log on from */
                return False;
-       if(!smb_io_unihdr("hdr_unknown_str ", &usr->hdr_unknown_str, ps, depth))        /* unknown string */
+       if(!smb_io_unihdr("hdr_comment ", &usr->hdr_comment, ps, depth))        /* unknown string */
                return False;
        if(!smb_io_unihdr("hdr_munged_dial ", &usr->hdr_munged_dial, ps, depth))        /* wkstas user can log on from */
                return False;
@@ -5963,7 +5963,7 @@ static BOOL sam_io_user_info23(const char *desc, SAM_USER_INFO_23 * usr,
        if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth))        /* worksations user can log on from */
                return False;
 
-       if(!smb_io_unistr2("uni_unknown_str ", &usr->uni_unknown_str, usr->hdr_unknown_str.buffer, ps, depth))  /* unknown string */
+       if(!smb_io_unistr2("uni_comment ", &usr->uni_comment, usr->hdr_comment.buffer, ps, depth))      /* unknown string */
                return False;
 
        if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial, usr->hdr_munged_dial.buffer, ps, depth))
@@ -6025,7 +6025,7 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str
                return False;
        if(!smb_io_unihdr("hdr_workstations", &usr->hdr_workstations, ps, depth))       /* wkstas user can log on from */
                return False;
-       if(!smb_io_unihdr("hdr_unknown_str ", &usr->hdr_unknown_str, ps, depth))        /* unknown string */
+       if(!smb_io_unihdr("hdr_comment ", &usr->hdr_comment, ps, depth))        /* unknown string */
                return False;
        if(!smb_io_unihdr("hdr_munged_dial ", &usr->hdr_munged_dial, ps, depth))        /* wkstas user can log on from */
                return False;
@@ -6076,7 +6076,7 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str
        if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth))        /* worksations user can log on from */
                return False;
 
-       if(!smb_io_unistr2("uni_unknown_str ", &usr->uni_unknown_str, usr->hdr_unknown_str.buffer, ps, depth))  /* unknown string */
+       if(!smb_io_unistr2("uni_comment ", &usr->uni_comment, usr->hdr_comment.buffer, ps, depth))      /* unknown string */
                return False;
 
        if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial, usr->hdr_munged_dial.buffer, ps, depth))
@@ -6182,8 +6182,8 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr,
        copy_unistr2(&usr->uni_workstations, wkstas);
        init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations);
 
-       copy_unistr2(&usr->uni_unknown_str, unk_str);
-       init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str);
+       copy_unistr2(&usr->uni_comment, unk_str);
+       init_uni_hdr(&usr->hdr_comment, &usr->uni_comment);
 
        copy_unistr2(&usr->uni_munged_dial, mung_dial);
        init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
@@ -6331,8 +6331,8 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, struct samu *pw, DOM_SID *
        init_unistr2(&usr->uni_workstations, workstations, UNI_STR_TERMINATE);
        init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations);
 
-       init_unistr2(&usr->uni_unknown_str, NULL, UNI_STR_TERMINATE);
-       init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str);
+       init_unistr2(&usr->uni_comment, NULL, UNI_STR_TERMINATE);
+       init_uni_hdr(&usr->hdr_comment, &usr->uni_comment);
 
        init_unistr2_from_datablob(&usr->uni_munged_dial, &munged_dial_blob);
        init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
@@ -6398,7 +6398,7 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr,
                return False;
        if(!smb_io_unihdr("hdr_workstations", &usr->hdr_workstations, ps, depth))       /* wkstas user can log on from */
                return False;
-       if(!smb_io_unihdr("hdr_unknown_str ", &usr->hdr_unknown_str, ps, depth))        /* unknown string */
+       if(!smb_io_unihdr("hdr_comment ", &usr->hdr_comment, ps, depth))        /* unknown string */
                return False;
        if(!smb_io_unihdr("hdr_munged_dial ", &usr->hdr_munged_dial, ps, depth))        /* wkstas user can log on from */
                return False;
@@ -6438,25 +6438,25 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr,
 
        /* here begins pointed-to data */
 
-       if(!smb_io_unistr2("uni_user_name   ", &usr->uni_user_name,usr->hdr_user_name.buffer, ps, depth))       /* username unicode string */
+       if(!smb_io_unistr2("uni_user_name   ", &usr->uni_user_name,usr->hdr_user_name.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_full_name   ", &usr->uni_full_name, usr->hdr_full_name.buffer, ps, depth))      /* user's full name unicode string */
+       if(!smb_io_unistr2("uni_full_name   ", &usr->uni_full_name, usr->hdr_full_name.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_home_dir    ", &usr->uni_home_dir, usr->hdr_home_dir.buffer, ps, depth))        /* home directory unicode string */
+       if(!smb_io_unistr2("uni_home_dir    ", &usr->uni_home_dir, usr->hdr_home_dir.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_dir_drive   ", &usr->uni_dir_drive, usr->hdr_dir_drive.buffer, ps, depth))      /* home directory drive unicode string */
+       if(!smb_io_unistr2("uni_dir_drive   ", &usr->uni_dir_drive, usr->hdr_dir_drive.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_logon_script", &usr->uni_logon_script, usr->hdr_logon_script.buffer, ps, depth))        /* logon script unicode string */
+       if(!smb_io_unistr2("uni_logon_script", &usr->uni_logon_script, usr->hdr_logon_script.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_profile_path", &usr->uni_profile_path, usr->hdr_profile_path.buffer, ps, depth))        /* profile path unicode string */
+       if(!smb_io_unistr2("uni_profile_path", &usr->uni_profile_path, usr->hdr_profile_path.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_acct_desc   ", &usr->uni_acct_desc, usr->hdr_acct_desc.buffer, ps, depth))      /* user desc unicode string */
+       if(!smb_io_unistr2("uni_acct_desc   ", &usr->uni_acct_desc, usr->hdr_acct_desc.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth))        /* worksations user can log on from */
+       if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_unknown_str ", &usr->uni_unknown_str, usr->hdr_unknown_str.buffer, ps, depth))  /* unknown string */
+       if(!smb_io_unistr2("uni_comment", &usr->uni_comment, usr->hdr_comment.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial,usr->hdr_munged_dial.buffer, ps, depth))   /* worksations user can log on from */
+       if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial,usr->hdr_munged_dial.buffer, ps, depth))
                return False;
 
        /* ok, this is only guess-work (as usual) */
index da3380773337b4576d057d657557dafeb5f8a898..8c417c05dce64ed02ef1e49c0bdc47cf04a585ee 100644 (file)
@@ -100,12 +100,12 @@ BOOL shutdown_io_q_init(const char *desc, SHUTDOWN_Q_INIT *q_s, prs_struct *ps,
        if (!prs_align(ps))
                return False;
 
-       if (!prs_pointer("server", ps, depth, (void**)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16))
+       if (!prs_pointer("server", ps, depth, (void*)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16))
                return False;
        if (!prs_align(ps))
                return False;
 
-       if (!prs_pointer("message", ps, depth, (void**)&q_s->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4))
+       if (!prs_pointer("message", ps, depth, (void*)&q_s->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4))
                return False;
 
        if (!prs_align(ps))
@@ -159,12 +159,12 @@ BOOL shutdown_io_q_init_ex(const char *desc, SHUTDOWN_Q_INIT_EX * q_s, prs_struc
        if (!prs_align(ps))
                return False;
 
-       if (!prs_pointer("server", ps, depth, (void**)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16))
+       if (!prs_pointer("server", ps, depth, (void*)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16))
                return False;
        if (!prs_align(ps))
                return False;
 
-       if (!prs_pointer("message", ps, depth, (void**)&q_s->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4))
+       if (!prs_pointer("message", ps, depth, (void*)&q_s->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4))
                return False;
 
        if (!prs_align(ps))
@@ -238,7 +238,7 @@ BOOL shutdown_io_q_abort(const char *desc, SHUTDOWN_Q_ABORT *q_s,
        if (!prs_align(ps))
                return False;
 
-       if (!prs_pointer("server", ps, depth, (void**)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16))
+       if (!prs_pointer("server", ps, depth, (void*)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16))
                return False;
        if (!prs_align(ps))
                return False;
index 2884883e893763abc3bebd2a44f2e750333ed2a1..8d4a757a74aee8ebb37f19a3db76d8fab33c3b0e 100644 (file)
@@ -606,7 +606,7 @@ static BOOL spool_io_user_level(const char *desc, SPOOL_USER_CTR *q_u, prs_struc
        switch ( q_u->level ) 
        {       
                case 1:
-                       if ( !prs_pointer( "" , ps, depth, (void**)&q_u->user.user1, 
+                       if ( !prs_pointer( "" , ps, depth, (void*)&q_u->user.user1, 
                                sizeof(SPOOL_USER_1), (PRS_POINTER_CAST)spool_io_user_level_1 )) 
                        {
                                return False;
index 7d15eda630f908074d8e03717c5aa832215c21b3..5123d1c2ccacb5bc24f28d18d211e6295a93bc35 100644 (file)
@@ -7,6 +7,7 @@
  *  Copyright (C) Jeremy Allison                   1999,
  *  Copyright (C) Nigel Williams                   2001,
  *  Copyright (C) Jim McDonough (jmcd@us.ibm.com)   2002.
+ *  Copyright (C) Gerald (Jerry) Carter             2006.
  *  
  *  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
@@ -1588,64 +1589,17 @@ BOOL srv_io_r_net_share_del(const char *desc, SRV_R_NET_SHARE_DEL *q_n, prs_stru
  Inits a SESS_INFO_0_STR structure
 ********************************************************************/
 
-void init_srv_sess_info0_str(SESS_INFO_0_STR *ss0, const char *name)
+void init_srv_sess_info0( SESS_INFO_0 *ss0, const char *name )
 {
-       DEBUG(5,("init_srv_sess_info0_str\n"));
+       ZERO_STRUCTP( ss0 );
 
-       init_unistr2(&ss0->uni_name, name, UNI_STR_TERMINATE);
-}
-
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-
-static BOOL srv_io_sess_info0_str(const char *desc,  SESS_INFO_0_STR *ss0, prs_struct *ps, int depth)
-{
-       if (ss0 == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "srv_io_sess_info0_str");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!smb_io_unistr2("", &ss0->uni_name, True, ps, depth))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Inits a SESS_INFO_0 structure
-********************************************************************/
-
-void init_srv_sess_info0(SESS_INFO_0 *ss0, const char *name)
-{
-       DEBUG(5,("init_srv_sess_info0: %s\n", name));
-
-       ss0->ptr_name = (name != NULL) ? 1 : 0;
-}
-
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-
-static BOOL srv_io_sess_info0(const char *desc, SESS_INFO_0 *ss0, prs_struct *ps, int depth)
-{
-       if (ss0 == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "srv_io_sess_info0");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("ptr_name", ps, depth, &ss0->ptr_name))
-               return False;
-
-       return True;
+       if ( name ) {
+               if ( (ss0->sharename = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) {
+                       DEBUG(0,("init_srv_sess_info0: talloc failed!\n"));
+                       return;
+               }
+               init_unistr2( ss0->sharename, name, UNI_STR_TERMINATE );
+       }
 }
 
 /*******************************************************************
@@ -1681,13 +1635,15 @@ static BOOL srv_io_srv_sess_info_0(const char *desc, SRV_SESS_INFO_0 *ss0, prs_s
 
                SMB_ASSERT_ARRAY(ss0->info_0, num_entries);
 
+               /* first the pointers */
                for (i = 0; i < num_entries; i++) {
-                       if(!srv_io_sess_info0("", &ss0->info_0[i], ps, depth))
+                       if ( !prs_io_unistr2_p("", ps, depth, &ss0->info_0[i].sharename ) )
                                return False;
                }
 
+               /* now the strings */
                for (i = 0; i < num_entries; i++) {
-                       if(!srv_io_sess_info0_str("", &ss0->info_0_str[i], ps, depth))
+                       if ( !prs_io_unistr2("sharename", ps, depth, ss0->info_0[i].sharename ))
                                return False;
                }
 
@@ -1698,54 +1654,33 @@ static BOOL srv_io_srv_sess_info_0(const char *desc, SRV_SESS_INFO_0 *ss0, prs_s
        return True;
 }
 
-/*******************************************************************
- Inits a SESS_INFO_1_STR structure
-********************************************************************/
-
-void init_srv_sess_info1_str(SESS_INFO_1_STR *ss1, const char *name, const char *user)
-{
-       DEBUG(5,("init_srv_sess_info1_str\n"));
-
-       init_unistr2(&ss1->uni_name, name, UNI_STR_TERMINATE);
-       init_unistr2(&ss1->uni_user, user, UNI_STR_TERMINATE);
-}
-
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-
-static BOOL srv_io_sess_info1_str(const char *desc, SESS_INFO_1_STR *ss1, prs_struct *ps, int depth)
-{
-       if (ss1 == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "srv_io_sess_info1_str");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!smb_io_unistr2("", &ss1->uni_name, True, ps, depth))
-               return False;
-       if(!smb_io_unistr2("", &(ss1->uni_user), True, ps, depth))
-               return False;
-
-       return True;
-}
-
 /*******************************************************************
  Inits a SESS_INFO_1 structure
 ********************************************************************/
 
-void init_srv_sess_info1(SESS_INFO_1 *ss1, 
-                               const char *name, const char *user,
-                               uint32 num_opens, uint32 open_time, uint32 idle_time,
-                               uint32 user_flags)
+void init_srv_sess_info1( SESS_INFO_1 *ss1, const char *name, const char *user,
+                          uint32 num_opens, uint32 open_time, uint32 idle_time,
+                          uint32 user_flags)
 {
        DEBUG(5,("init_srv_sess_info1: %s\n", name));
 
-       ss1->ptr_name = (name != NULL) ? 1 : 0;
-       ss1->ptr_user = (user != NULL) ? 1 : 0;
+       ZERO_STRUCTP( ss1 );
+
+       if ( name ) {
+               if ( (ss1->sharename = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) {
+                       DEBUG(0,("init_srv_sess_info0: talloc failed!\n"));
+                       return;
+               }
+               init_unistr2( ss1->sharename, name, UNI_STR_TERMINATE );
+       }
+
+       if ( user ) {
+               if ( (ss1->username = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) {
+                       DEBUG(0,("init_srv_sess_info0: talloc failed!\n"));
+                       return;
+               }
+               init_unistr2( ss1->username, user, UNI_STR_TERMINATE );
+       }
 
        ss1->num_opens  = num_opens;
        ss1->open_time  = open_time;
@@ -1753,37 +1688,6 @@ void init_srv_sess_info1(SESS_INFO_1 *ss1,
        ss1->user_flags = user_flags;
 }
 
-/*******************************************************************
-reads or writes a structure.
-********************************************************************/
-
-static BOOL srv_io_sess_info1(const char *desc, SESS_INFO_1 *ss1, prs_struct *ps, int depth)
-{
-       if (ss1 == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "srv_io_sess_info1");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("ptr_name  ", ps, depth, &ss1->ptr_name))
-               return False;
-       if(!prs_uint32("ptr_user  ", ps, depth, &ss1->ptr_user))
-               return False;
-
-       if(!prs_uint32("num_opens ", ps, depth, &ss1->num_opens))
-               return False;
-       if(!prs_uint32("open_time ", ps, depth, &ss1->open_time))
-               return False;
-       if(!prs_uint32("idle_time ", ps, depth, &ss1->idle_time))
-               return False;
-       if(!prs_uint32("user_flags", ps, depth, &ss1->user_flags))
-               return False;
-
-       return True;
-}
 
 /*******************************************************************
  Reads or writes a structure.
@@ -1818,13 +1722,31 @@ static BOOL srv_io_srv_sess_info_1(const char *desc, SRV_SESS_INFO_1 *ss1, prs_s
 
                SMB_ASSERT_ARRAY(ss1->info_1, num_entries);
 
+               /* first the pointers and flags */
+
                for (i = 0; i < num_entries; i++) {
-                       if(!srv_io_sess_info1("", &ss1->info_1[i], ps, depth))
+
+                       if ( !prs_io_unistr2_p("", ps, depth, &ss1->info_1[i].sharename ))
+                               return False;
+                       if ( !prs_io_unistr2_p("", ps, depth, &ss1->info_1[i].username ))
+                               return False;
+
+                       if(!prs_uint32("num_opens ", ps, depth, &ss1->info_1[i].num_opens))
+                               return False;
+                       if(!prs_uint32("open_time ", ps, depth, &ss1->info_1[i].open_time))
+                               return False;
+                       if(!prs_uint32("idle_time ", ps, depth, &ss1->info_1[i].idle_time))
+                               return False;
+                       if(!prs_uint32("user_flags", ps, depth, &ss1->info_1[i].user_flags))
                                return False;
                }
 
+               /* now the strings */
+
                for (i = 0; i < num_entries; i++) {
-                       if(!srv_io_sess_info1_str("", &ss1->info_1_str[i], ps, depth))
+                       if ( !prs_io_unistr2("", ps, depth, ss1->info_1[i].sharename ))
+                               return False;
+                       if ( !prs_io_unistr2("", ps, depth, ss1->info_1[i].username ))
                                return False;
                }
 
@@ -1883,37 +1805,13 @@ static BOOL srv_io_srv_sess_ctr(const char *desc, SRV_SESS_INFO_CTR **pp_ctr, pr
        return True;
 }
 
-/*******************************************************************
- Inits a SRV_Q_NET_SESS_ENUM structure.
-********************************************************************/
-
-void init_srv_q_net_sess_enum(SRV_Q_NET_SESS_ENUM *q_n, 
-                             const char *srv_name, const char *qual_name,
-                             const char *user_name, uint32 sess_level, 
-                             SRV_SESS_INFO_CTR *ctr, uint32 preferred_len,
-                             ENUM_HND *hnd)
-{
-       q_n->ctr = ctr;
-
-       DEBUG(5,("init_q_net_sess_enum\n"));
-
-       init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name);
-       init_buf_unistr2(&q_n->uni_qual_name, &q_n->ptr_qual_name, qual_name);
-       init_buf_unistr2(&q_n->uni_user_name, &q_n->ptr_user_name, user_name);
-
-       q_n->sess_level    = sess_level;
-       q_n->preferred_len = preferred_len;
-
-       memcpy(&q_n->enum_hnd, hnd, sizeof(*hnd));
-}
-
 /*******************************************************************
  Reads or writes a structure.
 ********************************************************************/
 
-BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_n, prs_struct *ps, int depth)
+BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_u, prs_struct *ps, int depth)
 {
-       if (q_n == NULL)
+       if (q_u == NULL)
                return False;
 
        prs_debug(ps, depth, desc, "srv_io_q_net_sess_enum");
@@ -1922,41 +1820,36 @@ BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_n, prs_stru
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
-               return False;
-       if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
+       if(!prs_pointer("servername", ps, depth, (void*)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
 
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("ptr_qual_name", ps, depth, &q_n->ptr_qual_name))
-               return False;
-       if(!smb_io_unistr2("", &q_n->uni_qual_name, q_n->ptr_qual_name, ps, depth))
+       if(!prs_pointer("qualifier", ps, depth, (void*)&q_u->qualifier, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
 
        if(!prs_align(ps))
                return False;
-       if(!prs_uint32("ptr_user_name", ps, depth, &q_n->ptr_user_name))
-               return False;
-       if(!smb_io_unistr2("", &q_n->uni_user_name, q_n->ptr_user_name, ps, depth))
+
+       if(!prs_pointer("username", ps, depth, (void*)&q_u->username, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
 
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("sess_level", ps, depth, &q_n->sess_level))
+       if(!prs_uint32("sess_level", ps, depth, &q_u->sess_level))
                return False;
        
-       if (q_n->sess_level != (uint32)-1) {
-               if(!srv_io_srv_sess_ctr("sess_ctr", &q_n->ctr, ps, depth))
+       if (q_u->sess_level != (uint32)-1) {
+               if(!srv_io_srv_sess_ctr("sess_ctr", &q_u->ctr, ps, depth))
                        return False;
        }
 
-       if(!prs_uint32("preferred_len", ps, depth, &q_n->preferred_len))
+       if(!prs_uint32("preferred_len", ps, depth, &q_u->preferred_len))
                return False;
 
-       if(!smb_io_enum_hnd("enum_hnd", &q_n->enum_hnd, ps, depth))
+       if(!smb_io_enum_hnd("enum_hnd", &q_u->enum_hnd, ps, depth))
                return False;
 
        return True;
@@ -2433,23 +2326,11 @@ BOOL srv_io_r_net_conn_enum(const char *desc,  SRV_R_NET_CONN_ENUM *r_n, prs_str
        return True;
 }
 
-/*******************************************************************
- Inits a FILE_INFO_3_STR structure
-********************************************************************/
-
-void init_srv_file_info3_str(FILE_INFO_3_STR *fi3, const char *user_name, const char *path_name)
-{
-       DEBUG(5,("init_srv_file_info3_str\n"));
-
-       init_unistr2(&fi3->uni_path_name, path_name, UNI_STR_TERMINATE);
-       init_unistr2(&fi3->uni_user_name, user_name, UNI_STR_TERMINATE);
-}
-
 /*******************************************************************
  Reads or writes a structure.
 ********************************************************************/
 
-static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_struct *ps, int depth)
+static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3 *sh1, prs_struct *ps, int depth)
 {
        if (sh1 == NULL)
                return False;
@@ -2460,10 +2341,15 @@ static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_st
        if(!prs_align(ps))
                return False;
 
-       if(!smb_io_unistr2("", &sh1->uni_path_name, True, ps, depth))
-               return False;
-       if(!smb_io_unistr2("", &sh1->uni_user_name, True, ps, depth))
-               return False;
+       if ( sh1->path ) {
+               if(!smb_io_unistr2("", sh1->path, True, ps, depth))
+                       return False;
+       }
+
+       if ( sh1->user ) {
+               if(!smb_io_unistr2("", sh1->user, True, ps, depth))
+                       return False;
+       }
 
        return True;
 }
@@ -2472,18 +2358,26 @@ static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_st
  Inits a FILE_INFO_3 structure
 ********************************************************************/
 
-void init_srv_file_info3(FILE_INFO_3 *fl3,
-                        uint32 id, uint32 perms, uint32 num_locks,
-                        const char *path_name, const char *user_name)
+void init_srv_file_info3( FILE_INFO_3 *fl3, uint32 id, uint32 perms, uint32 num_locks,
+                          const char *user_name, const char *path_name )
 {
-       DEBUG(5,("init_srv_file_info3: %s %s\n", path_name, user_name));
-
        fl3->id        = id;    
        fl3->perms     = perms;
        fl3->num_locks = num_locks;
 
-       fl3->ptr_path_name = (path_name != NULL) ? 1 : 0;
-       fl3->ptr_user_name = (user_name != NULL) ? 1 : 0;
+        if ( path_name ) {
+                if ( (fl3->path = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+                        return;
+                init_unistr2(fl3->path, path_name, UNI_STR_TERMINATE);
+        }
+
+        if ( user_name ) {
+                if ( (fl3->user = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+                        return;
+                init_unistr2(fl3->user, user_name, UNI_STR_TERMINATE);
+        }
+
+       return;
 }
 
 /*******************************************************************
@@ -2492,6 +2386,8 @@ void init_srv_file_info3(FILE_INFO_3 *fl3,
 
 static BOOL srv_io_file_info3(const char *desc, FILE_INFO_3 *fl3, prs_struct *ps, int depth)
 {
+       uint32 uni_p;
+
        if (fl3 == NULL)
                return False;
 
@@ -2507,10 +2403,24 @@ static BOOL srv_io_file_info3(const char *desc, FILE_INFO_3 *fl3, prs_struct *ps
                return False;
        if(!prs_uint32("num_locks    ", ps, depth, &fl3->num_locks))
                return False;
-       if(!prs_uint32("ptr_path_name", ps, depth, &fl3->ptr_path_name))
+
+       uni_p = fl3->path ? 1 : 0;
+       if(!prs_uint32("ptr", ps, depth, &uni_p))
                return False;
-       if(!prs_uint32("ptr_user_name", ps, depth, &fl3->ptr_user_name))
+       if (UNMARSHALLING(ps)) {
+               if ( (fl3->path = PRS_ALLOC_MEM( ps, UNISTR2, 1)) == NULL ) {
+                       return False;
+               }
+       }
+
+       uni_p = fl3->user ? 1 : 0;
+       if(!prs_uint32("ptr", ps, depth, &uni_p))
                return False;
+       if (UNMARSHALLING(ps)) {
+               if ( (fl3->user = PRS_ALLOC_MEM( ps, UNISTR2, 1)) == NULL ) {
+                       return False;
+               }
+       }
 
        return True;
 }
@@ -2528,55 +2438,53 @@ static BOOL srv_io_srv_file_ctr(const char *desc, SRV_FILE_INFO_CTR *ctr, prs_st
        depth++;
 
        if (UNMARSHALLING(ps)) {
-               memset(ctr, '\0', sizeof(SRV_FILE_INFO_CTR));
+               ZERO_STRUCTP(ctr);
        }
 
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("switch_value", ps, depth, &ctr->switch_value))
+       if(!prs_uint32("level", ps, depth, &ctr->level))
                return False;
-       if (ctr->switch_value != 3) {
-               DEBUG(5,("%s File info %d level not supported\n",
-                        tab_depth(depth), ctr->switch_value));
-       }
+
        if(!prs_uint32("ptr_file_info", ps, depth, &ctr->ptr_file_info))
                return False;
        if(!prs_uint32("num_entries", ps, depth, &ctr->num_entries))
                return False;
        if(!prs_uint32("ptr_entries", ps, depth, &ctr->ptr_entries))
                return False;
+
        if (ctr->ptr_entries == 0)
                return True;
-       if(!prs_uint32("num_entries2", ps, depth, 
-                      &ctr->num_entries2))
+
+       if(!prs_uint32("num_entries2", ps, depth, &ctr->num_entries2))
                return False;
 
-       switch (ctr->switch_value) {
+       switch (ctr->level) {
        case 3: {
-               SRV_FILE_INFO_3 *info3 = ctr->file.info3;
+               FILE_INFO_3 *info3 = ctr->file.info3;
                int num_entries = ctr->num_entries;
                int i;
 
                if (UNMARSHALLING(ps)) {
-                       if (!(info3 = PRS_ALLOC_MEM(ps, SRV_FILE_INFO_3, num_entries)))
+                       if (!(info3 = PRS_ALLOC_MEM(ps, FILE_INFO_3, num_entries)))
                                return False;
                        ctr->file.info3 = info3;
                }
 
                for (i = 0; i < num_entries; i++) {
-                       if(!srv_io_file_info3("", &ctr->file.info3[i].info_3, ps, depth))
+                       if(!srv_io_file_info3("", &ctr->file.info3[i], ps, depth)) 
                                return False;
                }
+
                for (i = 0; i < num_entries; i++) {
-                       if(!srv_io_file_info3_str("", &ctr->file.info3[i].info_3_str, ps, depth))
+                       if(!srv_io_file_info3_str("", &ctr->file.info3[i], ps, depth))
                                return False;
                }
                break;
        }
        default:
-               DEBUG(5,("%s no file info at switch_value %d\n",
-                        tab_depth(depth), ctr->switch_value));
+               DEBUG(5,("%s no file info at switch_value %d\n", tab_depth(depth), ctr->level));
                break;
        }
                        
@@ -2594,13 +2502,28 @@ void init_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n,
                              uint32 preferred_len,
                              ENUM_HND *hnd)
 {
-       DEBUG(5,("init_q_net_file_enum\n"));
+       uint32 ptr;
 
-       init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name);
-       init_buf_unistr2(&q_n->uni_qual_name, &q_n->ptr_qual_name, qual_name);
-       init_buf_unistr2(&q_n->uni_user_name, &q_n->ptr_user_name, user_name);
+       if ( srv_name ) {
+               if ( (q_n->servername = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+                       return;
+               init_buf_unistr2(q_n->servername, &ptr, srv_name);
+       }
+
+       if ( qual_name ) {
+               if ( (q_n->qualifier = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+                       return;
+               init_buf_unistr2(q_n->qualifier,  &ptr, qual_name);
+       }
+
+       if ( user_name ) {
+               if ( (q_n->username = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+                       return;
+               init_buf_unistr2(q_n->username,   &ptr, user_name);
+       }
+
+       q_n->level = q_n->ctr.level = file_level;
 
-       q_n->file_level    = q_n->ctr.switch_value = file_level;
        q_n->preferred_len = preferred_len;
        q_n->ctr.ptr_file_info = 1;
        q_n->ctr.num_entries = 0;
@@ -2613,9 +2536,9 @@ void init_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n,
  Reads or writes a structure.
 ********************************************************************/
 
-BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_n, prs_struct *ps, int depth)
+BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_u, prs_struct *ps, int depth)
 {
-       if (q_n == NULL)
+       if (q_u == NULL)
                return False;
 
        prs_debug(ps, depth, desc, "srv_io_q_net_file_enum");
@@ -2624,41 +2547,33 @@ BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_n, prs_stru
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
+       if(!prs_pointer("servername", ps, depth, (void*)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
-       if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
-               return False;
-
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("ptr_qual_name", ps, depth, &q_n->ptr_qual_name))
-               return False;
-       if(!smb_io_unistr2("", &q_n->uni_qual_name, q_n->ptr_qual_name, ps, depth))
+       if(!prs_pointer("qualifier", ps, depth, (void*)&q_u->qualifier, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
-
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("ptr_user_name", ps, depth, &q_n->ptr_user_name))
-               return False;
-       if(!smb_io_unistr2("", &q_n->uni_user_name, q_n->ptr_user_name, ps, depth))
+       if(!prs_pointer("username", ps, depth, (void*)&q_u->username, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
-
        if(!prs_align(ps))
                return False;
-       if(!prs_uint32("file_level", ps, depth, &q_n->file_level))
+
+       if(!prs_uint32("level", ps, depth, &q_u->level))
                return False;
 
-       if (q_n->file_level != (uint32)-1) {
-               if(!srv_io_srv_file_ctr("file_ctr", &q_n->ctr, ps, depth))
+       if (q_u->level != (uint32)-1) {
+               if(!srv_io_srv_file_ctr("file_ctr", &q_u->ctr, ps, depth))
                        return False;
        }
 
-       if(!prs_uint32("preferred_len", ps, depth, &q_n->preferred_len))
+       if(!prs_uint32("preferred_len", ps, depth, &q_u->preferred_len))
                return False;
 
-       if(!smb_io_enum_hnd("enum_hnd", &q_n->enum_hnd, ps, depth))
+       if(!smb_io_enum_hnd("enum_hnd", &q_u->enum_hnd, ps, depth))
                return False;
 
        return True;
@@ -2679,10 +2594,10 @@ BOOL srv_io_r_net_file_enum(const char *desc, SRV_R_NET_FILE_ENUM *r_n, prs_stru
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("file_level", ps, depth, &r_n->file_level))
+       if(!prs_uint32("level", ps, depth, &r_n->level))
                return False;
 
-       if (r_n->file_level != 0) {
+       if (r_n->level != 0) {
                if(!srv_io_srv_file_ctr("file_ctr", &r_n->ctr, ps, depth))
                        return False;
        }
@@ -2703,62 +2618,16 @@ BOOL srv_io_r_net_file_enum(const char *desc, SRV_R_NET_FILE_ENUM *r_n, prs_stru
 void init_srv_q_net_file_close(SRV_Q_NET_FILE_CLOSE *q_n, const char *server,
                               uint32 file_id)
 {
-       q_n->ptr_srv_name = 1;
-       init_unistr2(&q_n->uni_srv_name, server, UNI_STR_TERMINATE);
-       q_n->file_id = file_id;
-}
-
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-BOOL srv_io_q_net_file_close(const char *desc, SRV_Q_NET_FILE_CLOSE *q_n,
-                            prs_struct *ps, int depth)
-{
-       if (q_n == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "srv_io_q_net_file_close");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
-               return False;
-       if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
-               return False;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("file_id", ps, depth, &q_n->file_id))
-               return False;
+       if ( server ) {
+               if ( (q_n->servername = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) {
+                       return;
+               }
+               init_unistr2(q_n->servername, server, UNI_STR_TERMINATE);
+       }
 
-       return True;
+       q_n->file_id = file_id;
 }
 
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-
-BOOL srv_io_r_net_file_close(const char *desc, SRV_R_NET_FILE_CLOSE *q_n, 
-                            prs_struct *ps, int depth)
-{
-       if (q_n == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "srv_io_r_net_file_close");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_werror("status", ps, depth, &q_n->status))
-               return False;
-
-       return True;
-}      
-
 /*******************************************************************
  Inits a SRV_INFO_100 structure.
  ********************************************************************/
@@ -3410,25 +3279,6 @@ BOOL srv_io_r_net_disk_enum(const char *desc, SRV_R_NET_DISK_ENUM *r_n, prs_stru
        return True;
 }
 
-/*******************************************************************
- initialises a structure.
- ********************************************************************/
-
-BOOL init_srv_q_net_name_validate(SRV_Q_NET_NAME_VALIDATE *q_n, const char *srv_name, const char *share_name, int type) 
-{
-       uint32 ptr_share_name;
-
-       DEBUG(5,("init_srv_q_net_name_validate\n"));
-  
-       init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name);
-       init_buf_unistr2(&q_n->uni_name,     &ptr_share_name,    share_name);
-
-       q_n->type  = type;
-       q_n->flags = 0;
-
-       return True;
-}
-
 /*******************************************************************
  Reads or writes a structure.
  ********************************************************************/
@@ -3444,16 +3294,13 @@ BOOL srv_io_q_net_name_validate(const char *desc, SRV_Q_NET_NAME_VALIDATE *q_n,
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
-               return False;
-
-       if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
+       if(!prs_pointer("servername", ps, depth, (void*)&q_n->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
 
        if(!prs_align(ps))
                return False;
 
-       if(!smb_io_unistr2("", &q_n->uni_name, True, ps, depth))
+       if(!smb_io_unistr2("", &q_n->sharename, True, ps, depth))
                return False;
 
        if(!prs_align(ps))
@@ -3663,3 +3510,48 @@ void init_srv_q_net_remote_tod(SRV_Q_NET_REMOTE_TOD *q_u, const char *server)
        q_u->ptr_srv_name = 1;
        init_unistr2(&q_u->uni_srv_name, server, UNI_STR_TERMINATE);
 }
+
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+BOOL srv_io_q_net_file_close(const char *desc, SRV_Q_NET_FILE_CLOSE *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "srv_io_q_net_file_close");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_pointer("servername", ps, depth, (void*)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
+               return False;
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("file_id", ps, depth, &q_u->file_id))
+               return False;
+               
+       return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+BOOL srv_io_r_net_file_close(const char *desc, SRV_R_NET_FILE_CLOSE *r_n, 
+                              prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "srv_io_r_net_file_close");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_werror("status", ps, depth, &r_n->status))
+               return False;
+
+       return True;
+}
index 2cb44c63195dfa3d1adca862b0241d0ab4ad870f..dc4ee3e6e99ed3e46725c17130c8b7545489f709 100644 (file)
@@ -257,12 +257,12 @@ BOOL svcctl_io_q_open_scmanager(const char *desc, SVCCTL_Q_OPEN_SCMANAGER *q_u,
        if(!prs_align(ps))
                return False;
 
-       if(!prs_pointer("servername", ps, depth, (void**)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
+       if(!prs_pointer("servername", ps, depth, (void*)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
        if(!prs_align(ps))
                return False;
 
-       if(!prs_pointer("database", ps, depth, (void**)&q_u->database, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
+       if(!prs_pointer("database", ps, depth, (void*)&q_u->database, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
        if(!prs_align(ps))
                return False;
@@ -486,7 +486,7 @@ BOOL svcctl_io_q_enum_services_status(const char *desc, SVCCTL_Q_ENUM_SERVICES_S
        if(!prs_uint32("buffer_size", ps, depth, &q_u->buffer_size))
                return False;
 
-       if(!prs_pointer("resume", ps, depth, (void**)&q_u->resume, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
+       if(!prs_pointer("resume", ps, depth, (void*)&q_u->resume, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
                return False;
        
        return True;
@@ -517,7 +517,7 @@ BOOL svcctl_io_r_enum_services_status(const char *desc, SVCCTL_R_ENUM_SERVICES_S
        if(!prs_uint32("returned", ps, depth, &r_u->returned))
                return False;
 
-       if(!prs_pointer("resume", ps, depth, (void**)&r_u->resume, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
+       if(!prs_pointer("resume", ps, depth, (void*)&r_u->resume, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
                return False;
 
        if(!prs_werror("status", ps, depth, &r_u->status))
@@ -546,7 +546,7 @@ BOOL svcctl_io_q_start_service(const char *desc, SVCCTL_Q_START_SERVICE *q_u, pr
        if(!prs_uint32("parmcount", ps, depth, &q_u->parmcount))
                return False;
 
-       if ( !prs_pointer("rights", ps, depth, (void**)&q_u->parameters, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
+       if ( !prs_pointer("rights", ps, depth, (void*)&q_u->parameters, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
                return False;
 
        return True;
@@ -821,9 +821,9 @@ BOOL svcctl_io_service_fa( const char *desc, SERVICE_FAILURE_ACTIONS *fa, RPC_BU
        if ( !prs_uint32("reset_period", ps, depth, &fa->reset_period) )
                return False;
 
-       if ( !prs_pointer( desc, ps, depth, (void**)&fa->rebootmsg, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) )
+       if ( !prs_pointer( desc, ps, depth, (void*)&fa->rebootmsg, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) )
                return False;
-       if ( !prs_pointer( desc, ps, depth, (void**)&fa->command, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) )
+       if ( !prs_pointer( desc, ps, depth, (void*)&fa->command, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) )
                return False;
 
        if ( !prs_uint32("num_actions", ps, depth, &fa->num_actions) )
diff --git a/source/rpc_parse/parse_unixinfo.c b/source/rpc_parse/parse_unixinfo.c
new file mode 100644 (file)
index 0000000..391713c
--- /dev/null
@@ -0,0 +1,266 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *
+ *  RPC Pipe client / server routines
+ *
+ *  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"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_PARSE
+
+void init_q_unixinfo_sid_to_uid(UNIXINFO_Q_SID_TO_UID *q_d, const DOM_SID *sid)
+{
+       sid_copy(&q_d->sid, sid);
+}
+
+BOOL unixinfo_io_q_unixinfo_sid_to_uid(const char *desc, UNIXINFO_Q_SID_TO_UID *q_d,
+                                prs_struct *ps, int depth)
+{
+       return smb_io_dom_sid(desc, &q_d->sid, ps, depth);
+}
+
+BOOL unixinfo_io_r_unixinfo_sid_to_uid(const char *desc, UNIXINFO_R_SID_TO_UID *r_d,
+                                prs_struct *ps, int depth)
+{
+       if (!prs_uint64(desc, ps, depth, &r_d->uid))
+               return False;
+
+       if (!prs_ntstatus(desc, ps, depth, &r_d->status))
+               return False;
+
+       return True;
+}
+
+void init_q_unixinfo_uid_to_sid(UNIXINFO_Q_UID_TO_SID *q_d, UINT64_S uid)
+{
+       q_d->uid = uid;
+}
+
+BOOL unixinfo_io_q_unixinfo_uid_to_sid(const char *desc, UNIXINFO_Q_UID_TO_SID *q_d,
+                                prs_struct *ps, int depth)
+{
+       return prs_uint64(desc, ps, depth, &q_d->uid);
+}
+
+void init_r_unixinfo_uid_to_sid(UNIXINFO_R_UID_TO_SID *r_d, DOM_SID *sid)
+{
+       if (sid == NULL) {
+               r_d->sidptr = 0;
+               return;
+       }
+       r_d->sidptr = 1;
+       sid_copy(&r_d->sid, sid);
+}
+
+BOOL unixinfo_io_r_unixinfo_uid_to_sid(const char *desc, UNIXINFO_R_UID_TO_SID *r_d,
+                                prs_struct *ps, int depth)
+{
+       if (!prs_uint32("sidptr", ps, depth, &r_d->sidptr))
+               return False;
+
+       if (r_d->sidptr != 0) {
+               if (!smb_io_dom_sid(desc, &r_d->sid, ps, depth))
+                       return False;
+       }
+
+       if (!prs_ntstatus(desc, ps, depth, &r_d->status))
+               return False;
+
+       return True;
+}
+
+void init_q_unixinfo_sid_to_gid(UNIXINFO_Q_SID_TO_GID *q_d, const DOM_SID *sid)
+{
+       sid_copy(&q_d->sid, sid);
+}
+
+BOOL unixinfo_io_q_unixinfo_sid_to_gid(const char *desc, UNIXINFO_Q_SID_TO_GID *q_d,
+                                prs_struct *ps, int depth)
+{
+       return smb_io_dom_sid(desc, &q_d->sid, ps, depth);
+}
+
+void init_r_unixinfo_sid_to_gid(UNIXINFO_R_SID_TO_GID *r_d, UINT64_S gid)
+{
+       r_d->gid = gid;
+       r_d->status = NT_STATUS_OK;
+}
+
+BOOL unixinfo_io_r_unixinfo_sid_to_gid(const char *desc, UNIXINFO_R_SID_TO_GID *r_d,
+                                prs_struct *ps, int depth)
+{
+       if (!prs_uint64(desc, ps, depth, &r_d->gid))
+               return False;
+
+       if (!prs_ntstatus(desc, ps, depth, &r_d->status))
+               return False;
+
+       return True;
+}
+
+void init_q_unixinfo_gid_to_sid(UNIXINFO_Q_GID_TO_SID *q_d, UINT64_S gid)
+{
+       q_d->gid = gid;
+}
+
+BOOL unixinfo_io_q_unixinfo_gid_to_sid(const char *desc, UNIXINFO_Q_GID_TO_SID *q_d,
+                                prs_struct *ps, int depth)
+{
+       return prs_uint64(desc, ps, depth, &q_d->gid);
+}
+
+void init_r_unixinfo_gid_to_sid(UNIXINFO_R_GID_TO_SID *r_d, DOM_SID *sid)
+{
+       if (sid == NULL) {
+               r_d->sidptr = 0;
+               return;
+       }
+       r_d->sidptr = 1;
+       sid_copy(&r_d->sid, sid);
+}
+
+BOOL unixinfo_io_r_unixinfo_gid_to_sid(const char *desc, UNIXINFO_R_GID_TO_SID *r_d,
+                                prs_struct *ps, int depth)
+{
+       if (!prs_uint32("sidptr", ps, depth, &r_d->sidptr))
+               return False;
+
+       if (r_d->sidptr != 0) {
+               if (!smb_io_dom_sid(desc, &r_d->sid, ps, depth))
+                       return False;
+       }
+
+       if (!prs_ntstatus(desc, ps, depth, &r_d->status))
+               return False;
+
+       return True;
+}
+
+void init_q_unixinfo_getpwuid(UNIXINFO_Q_GETPWUID *r_d, int count,
+                             UINT64_S *uids)
+{
+       r_d->count = count;
+       r_d->uid = uids;
+}
+
+BOOL unixinfo_io_q_unixinfo_getpwuid(const char *desc,
+                                    UNIXINFO_Q_GETPWUID *q_d,
+                                    prs_struct *ps, int depth)
+{
+       uint32 arraysize;
+       int i;
+
+       if (!prs_uint32("count", ps, depth, &q_d->count))
+               return False;
+
+       arraysize = q_d->count;
+
+       if (!prs_uint32("arraysize", ps, depth, &arraysize))
+               return False;
+
+       if (arraysize != q_d->count) {
+               DEBUG(10, ("count!=arraysize\n"));
+               return False;
+       }
+
+       if (q_d->count > 1023) {
+               DEBUG(10, ("Range exceeded\n"));
+               return False;
+       }
+
+       if (UNMARSHALLING(ps)) {
+               q_d->uid = PRS_ALLOC_MEM(ps, UINT64_S, q_d->count);
+               if (q_d->uid == NULL) {
+                       return False;
+               }
+       }
+
+       for (i=0; i<q_d->count; i++) {
+               if (!prs_uint64(desc, ps, depth+1, &q_d->uid[i]))
+                       return False;
+       }
+
+       return True;
+}
+
+void init_r_unixinfo_getpwuid(UNIXINFO_R_GETPWUID *r_d, uint32 count,
+                             struct unixinfo_getpwuid *info)
+{
+       r_d->count = count;
+       r_d->info = info;
+}
+
+BOOL unixinfo_io_r_unixinfo_getpwuid(const char *desc,
+                                    UNIXINFO_R_GETPWUID *r_d,
+                                    prs_struct *ps, int depth)
+{
+       uint32 arraysize;
+       int i;
+
+       if (!prs_uint32("count", ps, depth, &r_d->count))
+               return False;
+
+       arraysize = r_d->count;
+
+       if (!prs_uint32("arraysize", ps, depth, &arraysize))
+               return False;
+
+       if (arraysize != r_d->count) {
+               DEBUG(10, ("count!=arraysize\n"));
+               return False;
+       }
+
+       if (r_d->count > 1023) {
+               DEBUG(10, ("Range exceeded\n"));
+               return False;
+       }
+
+       if (UNMARSHALLING(ps)) {
+               r_d->info = PRS_ALLOC_MEM(ps, struct unixinfo_getpwuid,
+                                         r_d->count);
+               if (r_d->info == NULL) {
+                       return False;
+               }
+       }
+
+       for (i=0; i<r_d->count; i++) {
+               if (!prs_align(ps))
+                       return False;
+
+               if (!prs_ntstatus("status", ps, depth+1, &r_d->info[i].status))
+                       return False;
+
+               if (!prs_string_alloc("homedir", ps, depth+1,
+                                     &r_d->info[i].homedir))
+                       return False;
+
+               if (!prs_string_alloc("shell", ps, depth+1,
+                                     &r_d->info[i].shell))
+                       return False;
+       }
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!prs_ntstatus(desc, ps, depth, &r_d->status))
+               return False;
+
+       return True;
+}
index 8239584522a9d478b4a82e27e545eae6d85e01cd..c7f8e05d91cfebf0072ef68e1d75ed062658964c 100644 (file)
@@ -40,7 +40,6 @@ uint32 _dfs_GetManagerVersion(pipes_struct *p, NETDFS_Q_DFS_GETMANAGERVERSION *q
 
 WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u)
 {
-       struct current_user user;
        struct junction_map jn;
        struct referral* old_referral_list = NULL;
        BOOL exists = False;
@@ -48,9 +47,7 @@ WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u)
        pstring dfspath, servername, sharename;
        pstring altpath;
 
-       get_current_user(&user,p);
-
-       if (user.ut.uid != 0) {
+       if (p->pipe_user.ut.uid != 0) {
                DEBUG(10,("_dfs_add: uid != 0. Access denied.\n"));
                return WERR_ACCESS_DENIED;
        }
@@ -104,16 +101,13 @@ WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u)
 WERROR _dfs_Remove(pipes_struct *p, NETDFS_Q_DFS_REMOVE *q_u, 
                    NETDFS_R_DFS_REMOVE *r_u)
 {
-       struct current_user user;
        struct junction_map jn;
        BOOL found = False;
 
        pstring dfspath, servername, sharename;
        pstring altpath;
 
-       get_current_user(&user,p);
-
-       if (user.ut.uid != 0) {
+       if (p->pipe_user.ut.uid != 0) {
                DEBUG(10,("_dfs_remove: uid != 0. Access denied.\n"));
                return WERR_ACCESS_DENIED;
        }
index efa7156eea6f20913dd08228b42d5f33499733bc..2cc5ef6110492ed592d1c0cf42ae3f89b0c4a4f0 100644 (file)
@@ -1557,17 +1557,23 @@ NTSTATUS _lsa_create_account(pipes_struct *p, LSA_Q_CREATEACCOUNT *q_u, LSA_R_CR
         * I don't know if it's the right one. not documented.
         * but guessed with rpcclient.
         */
-       if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION))
+       if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION)) {
+               DEBUG(10, ("_lsa_create_account: No POLICY_GET_PRIVATE_INFORMATION access right!\n"));
                return NT_STATUS_ACCESS_DENIED;
+       }
 
        /* check to see if the pipe_user is a Domain Admin since 
           account_pol.tdb was already opened as root, this is all we have */
           
-       if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
+       if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) {
+               DEBUG(10, ("_lsa_create_account: The use is not a Domain Admin, deny access!\n"));
                return NT_STATUS_ACCESS_DENIED;
+       }
                
-       if ( is_privileged_sid( &q_u->sid.sid ) )
+       if ( is_privileged_sid( &q_u->sid.sid ) ) {
+               DEBUG(10, ("_lsa_create_account: Policy account already exists!\n"));
                return NT_STATUS_OBJECT_NAME_COLLISION;
+       }
 
        /* associate the user/group SID with the (unique) handle. */
        
@@ -1582,6 +1588,7 @@ NTSTATUS _lsa_create_account(pipes_struct *p, LSA_Q_CREATEACCOUNT *q_u, LSA_R_CR
        if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
+       DEBUG(10, ("_lsa_create_account: call privileges code to create an account\n"));
        return privilege_create_account( &info->sid );
 }
 
@@ -1676,7 +1683,7 @@ NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA
                return NT_STATUS_INVALID_HANDLE;
 
        if (!lookup_sid(p->mem_ctx, &info->sid, NULL, NULL, NULL))
-               return NT_STATUS_ACCESS_DENIED;
+               return NT_STATUS_OK;
 
        /*
          0x01 -> Log on locally
@@ -1727,7 +1734,6 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u
        struct lsa_info *info = NULL;
        SE_PRIV mask;
        PRIVILEGE_SET *set = NULL;
-       struct current_user user;
 
        /* find the connection policy handle. */
        if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
@@ -1736,8 +1742,7 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u
        /* check to see if the pipe_user is root or a Domain Admin since 
           account_pol.tdb was already opened as root, this is all we have */
           
-       get_current_user( &user, p );
-       if ( user.ut.uid != sec_initial_uid() 
+       if ( p->pipe_user.ut.uid != sec_initial_uid() 
                && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
        {
                return NT_STATUS_ACCESS_DENIED;
@@ -1768,7 +1773,6 @@ NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEP
        struct lsa_info *info = NULL;
        SE_PRIV mask;
        PRIVILEGE_SET *set = NULL;
-       struct current_user user;
 
        /* find the connection policy handle. */
        if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
@@ -1777,8 +1781,7 @@ NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEP
        /* check to see if the pipe_user is root or a Domain Admin since 
           account_pol.tdb was already opened as root, this is all we have */
           
-       get_current_user( &user, p );
-       if ( user.ut.uid != sec_initial_uid()
+       if ( p->pipe_user.ut.uid != sec_initial_uid()
                && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) 
        {
                return NT_STATUS_ACCESS_DENIED;
@@ -1929,7 +1932,6 @@ NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R
        DOM_SID sid;
        fstring privname;
        UNISTR4_ARRAY *uni_privnames = q_u->rights;
-       struct current_user user;
        
 
        /* find the connection policy handle. */
@@ -1939,8 +1941,7 @@ NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R
        /* check to see if the pipe_user is a Domain Admin since 
           account_pol.tdb was already opened as root, this is all we have */
           
-       get_current_user( &user, p );
-       if ( user.ut.uid != sec_initial_uid()
+       if ( p->pipe_user.ut.uid != sec_initial_uid()
                && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) 
        {
                return NT_STATUS_ACCESS_DENIED;
@@ -1987,7 +1988,6 @@ NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u,
        DOM_SID sid;
        fstring privname;
        UNISTR4_ARRAY *uni_privnames = q_u->rights;
-       struct current_user user;
        
 
        /* find the connection policy handle. */
@@ -1997,8 +1997,7 @@ NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u,
        /* check to see if the pipe_user is a Domain Admin since 
           account_pol.tdb was already opened as root, this is all we have */
           
-       get_current_user( &user, p );
-       if ( user.ut.uid != sec_initial_uid()
+       if ( p->pipe_user.ut.uid != sec_initial_uid()
                && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
        {
                return NT_STATUS_ACCESS_DENIED;
index 812a720d9059f2408d3af9ca7de6ed4a5966cd73..e2c5e865ed183cd34fb3df5c5ac51418fd8502bf 100644 (file)
@@ -46,6 +46,11 @@ static void free_pipe_ntlmssp_auth_data(struct pipe_auth_data *auth)
        auth->a_u.auth_ntlmssp_state = NULL;
 }
 
+static DATA_BLOB generic_session_key(void)
+{
+       return data_blob("SystemLibraryDTC", 16);
+}
+
 /*******************************************************************
  Generate the next PDU to be returned from the data in p->rdata. 
  Handle NTLMSSP.
@@ -610,16 +615,6 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
 
        ZERO_STRUCT(reply);
 
-       memset(p->user_name, '\0', sizeof(p->user_name));
-       memset(p->pipe_user_name, '\0', sizeof(p->pipe_user_name));
-       memset(p->domain, '\0', sizeof(p->domain));
-       memset(p->wks, '\0', sizeof(p->wks));
-
-       /* Set up for non-authenticated user. */
-       TALLOC_FREE(p->pipe_user.nt_user_token);
-       p->pipe_user.ut.ngroups = 0;
-       SAFE_FREE( p->pipe_user.ut.groups);
-
        /* this has to be done as root in order to verify the password */
        become_root();
        status = auth_ntlmssp_update(a, *p_resp_blob, &reply);
@@ -632,6 +627,12 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
                return False;
        }
 
+       if (a->server_info->ptok == NULL) {
+               DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n"));
+               p->pipe_user.nt_user_token = NULL;
+               return False;
+       }
+
        /* Finally - if the pipe negotiated integrity (sign) or privacy (seal)
           ensure the underlying NTLMSSP flags are also set. If not we should
           refuse the bind. */
@@ -653,13 +654,9 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
                }
        }
        
-       fstrcpy(p->user_name, a->ntlmssp_state->user);
-       fstrcpy(p->pipe_user_name, a->server_info->unix_name);
-       fstrcpy(p->domain, a->ntlmssp_state->domain);
-       fstrcpy(p->wks, a->ntlmssp_state->workstation);
-
        DEBUG(5,("pipe_ntlmssp_verify_final: OK: user: %s domain: %s workstation: %s\n",
-               p->user_name, p->domain, p->wks));
+                a->ntlmssp_state->user, a->ntlmssp_state->domain,
+                a->ntlmssp_state->workstation));
 
        /*
         * Store the UNIX credential data (uid/gid pair) in the pipe structure.
@@ -669,11 +666,13 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
        p->pipe_user.ut.gid = a->server_info->gid;
        
        /*
-        * Copy the session key from the ntlmssp state.
+        * We're an authenticated bind over smb, so the session key needs to
+        * be set to "SystemLibraryDTC". Weird, but this is what Windows
+        * does. See the RPC-SAMBA3SESSIONKEY.
         */
 
        data_blob_free(&p->session_key);
-       p->session_key = data_blob(a->ntlmssp_state->session_key.data, a->ntlmssp_state->session_key.length);
+       p->session_key = generic_session_key();
        if (!p->session_key.data) {
                return False;
        }
@@ -688,23 +687,21 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
                }
        }
 
-       if (a->server_info->ptok) {
-               p->pipe_user.nt_user_token =
-                       dup_nt_token(NULL, a->server_info->ptok);
-               if (!p->pipe_user.nt_user_token) {
-                       DEBUG(1,("pipe_ntlmssp_verify_final: dup_nt_token failed.\n"));
-                       data_blob_free(&p->session_key);
-                       SAFE_FREE(p->pipe_user.ut.groups);
-                       return False;
-               }
-
-       } else {
+       if (!a->server_info->ptok) {
                DEBUG(1,("pipe_ntlmssp_verify_final: Error: Authmodule failed to provide nt_user_token\n"));
                data_blob_free(&p->session_key);
                SAFE_FREE(p->pipe_user.ut.groups);
                return False;
        }
 
+       p->pipe_user.nt_user_token = dup_nt_token(NULL, a->server_info->ptok);
+       if (!p->pipe_user.nt_user_token) {
+               DEBUG(1,("pipe_ntlmssp_verify_final: dup_nt_token failed.\n"));
+               data_blob_free(&p->session_key);
+               SAFE_FREE(p->pipe_user.ut.groups);
+               return False;
+       }
+
        return True;
 }
 
@@ -1361,8 +1358,21 @@ static BOOL pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p,
         * JRA. Should we also copy the schannel session key into the pipe session key p->session_key
         * here ? We do that for NTLMSSP, but the session key is already set up from the vuser
         * struct of the person who opened the pipe. I need to test this further. JRA.
+        *
+        * VL. As we are mapping this to guest set the generic key
+        * "SystemLibraryDTC" key here. It's a bit difficult to test against
+        * W2k3, as it does not allow schannel binds against SAMR and LSA
+        * anymore.
         */
 
+       data_blob_free(&p->session_key);
+       p->session_key = generic_session_key();
+       if (p->session_key.data == NULL) {
+               DEBUG(0, ("pipe_schannel_auth_bind: Could not alloc session"
+                         " key\n"));
+               return False;
+       }
+
        init_rpc_hdr_auth(&auth_info, RPC_SCHANNEL_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1);
        if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) {
                DEBUG(0,("pipe_schannel_auth_bind: marshalling of RPC_HDR_AUTH failed.\n"));
@@ -1391,6 +1401,12 @@ static BOOL pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p,
        p->auth.auth_data_free_func = NULL;
        p->auth.auth_type = PIPE_AUTH_TYPE_SCHANNEL;
 
+       if (!set_current_user_guest(&p->pipe_user)) {
+               DEBUG(1, ("pipe_schannel_auth_bind: Could not set guest "
+                         "token\n"));
+               return False;
+       }
+
        p->pipe_bound = True;
 
        return True;
@@ -1641,11 +1657,18 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
 
                case RPC_ANONYMOUS_AUTH_TYPE:
                        /* Unauthenticated bind request. */
+                       /* Get the authenticated pipe user from current_user */
+                       if (!copy_current_user(&p->pipe_user, &current_user)) {
+                               DEBUG(10, ("Could not copy current user\n"));
+                               goto err_exit;
+                       }
                        /* We're finished - no more packets. */
                        p->auth.auth_type = PIPE_AUTH_TYPE_NONE;
                        /* We must set the pipe auth_level here also. */
                        p->auth.auth_level = PIPE_AUTH_LEVEL_NONE;
                        p->pipe_bound = True;
+                       /* The session key was initialized from the SMB
+                        * session in make_internal_rpc_pipe_p */
                        break;
 
                default:
@@ -2148,23 +2171,6 @@ BOOL api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss
        return True;
 }
 
-/****************************************************************************
- Return a user struct for a pipe user.
-****************************************************************************/
-
-struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
-{
-       if (p->pipe_bound &&
-                       (p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP ||
-                       (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) {
-               memcpy(user, &p->pipe_user, sizeof(struct current_user));
-       } else {
-               memcpy(user, &current_user, sizeof(struct current_user));
-       }
-
-       return user;
-}
-
 /****************************************************************************
  Find the set of RPC functions associated with this context_id
 ****************************************************************************/
@@ -2219,9 +2225,7 @@ BOOL api_pipe_request(pipes_struct *p)
        BOOL changed_user = False;
        PIPE_RPC_FNS *pipe_fns;
        
-       if (p->pipe_bound &&
-                       ((p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP) ||
-                        (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) {
+       if (p->pipe_bound) {
                if(!become_authenticated_pipe_user(p)) {
                        prs_mem_free(&p->out_data.rdata);
                        return False;
@@ -2373,6 +2377,9 @@ void get_pipe_fns( int idx, struct api_struct **fns, int *n_fns )
                case PI_EVENTLOG:
                        eventlog_get_pipe_fns( &cmds, &n_cmds );
                        break;
+               case PI_UNIXINFO:
+                       unixinfo_get_pipe_fns( &cmds, &n_cmds );
+                       break;
                case PI_NTSVCS:
                        ntsvcs_get_pipe_fns( &cmds, &n_cmds );
                        break;
index 9cc8b72546f12c0f0efa3da3c44f5cbeef569934..8aa5bb3e6d175e41c14f006d0ea81c10b1441c9e 100644 (file)
@@ -351,8 +351,6 @@ static void *make_internal_rpc_pipe_p(char *pipe_name,
        /* Store the session key and NT_TOKEN */
        if (vuser) {
                p->session_key = data_blob(vuser->session_key.data, vuser->session_key.length);
-               p->pipe_user.nt_user_token = dup_nt_token(
-                       NULL, vuser->nt_user_token);
        }
 
        /*
@@ -1169,6 +1167,13 @@ BOOL close_rpc_pipe_hnd(smb_np_struct *p)
                 p->name, p->pnum, pipes_open));  
 
        DLIST_REMOVE(Pipes, p);
+       
+       /* TODO: Remove from pipe open db */
+       
+       if ( !delete_pipe_opendb( p ) ) {
+               DEBUG(3,("close_rpc_pipe_hnd: failed to delete %s "
+                       "pipe from open db.\n", p->name));
+       }
 
        ZERO_STRUCTP(p);
 
index e045de5639680771466e82464e67098ebabb5b8c..2e0b355db5f82cffcf6dbd27d57210f0f70b08ec 100644 (file)
@@ -1435,7 +1435,7 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
                }
        }
 
-       init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, (uint32 *)type, r_u->status);
+       init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, type, r_u->status);
 
        DEBUG(5,("_samr_lookup_names: %d\n", __LINE__));
 
@@ -2508,7 +2508,8 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
        }
                
        DEBUG(5, ("_samr_create_user: %s can add this account : %s\n",
-               p->pipe_user_name, can_add_account ? "True":"False" ));
+                 uidtoname(p->pipe_user.ut.uid),
+                 can_add_account ? "True":"False" ));
                
        /********** BEGIN Admin BLOCK **********/
 
@@ -3110,9 +3111,11 @@ static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21,
        }
 
        /* we need to separately check for an account rename first */
+       
        if (rpcstr_pull(new_name, id21->uni_user_name.buffer, 
-                       sizeof(new_name), id21->uni_user_name.uni_str_len*2, 0) && 
-          (!strequal(new_name, pdb_get_username(pwd)))) {
+               sizeof(new_name), id21->uni_user_name.uni_str_len*2, 0) 
+               && (!strequal(new_name, pdb_get_username(pwd)))) 
+       {
 
                /* check to see if the new username already exists.  Note: we can't
                   reliably lock all backends, so there is potentially the 
@@ -3435,7 +3438,8 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
        }
        
        DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n",
-               p->pipe_user_name, has_enough_rights ? "" : " not"));
+                 uidtoname(p->pipe_user.ut.uid),
+                 has_enough_rights ? "" : " not"));
 
        /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */
        
@@ -3593,7 +3597,8 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
        }
        
        DEBUG(5, ("_samr_set_userinfo2: %s does%s possess sufficient rights\n",
-               p->pipe_user_name, has_enough_rights ? "" : " not"));
+                 uidtoname(p->pipe_user.ut.uid),
+                 has_enough_rights ? "" : " not"));
 
        /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */
        
index 2b65eb210fd7a1f8e89fcaf3c213a44f90c3e764..c4bec79c9cb00d8e4c744b5286a5cff616bb90f3 100644 (file)
@@ -195,14 +195,13 @@ void copy_id21_to_sam_passwd(struct samu *to, SAM_USER_INFO_21 *from)
                        pdb_set_workstations(to  , new_string, PDB_CHANGED);
        }
 
-       /* is this right? */
-       if ((from->fields_present & ACCT_ADMIN_DESC) &&
-           (from->hdr_unknown_str.buffer)) {
-               old_string = pdb_get_unknown_str(to);
-               new_string = unistr2_static(&from->uni_unknown_str);
-               DEBUG(10,("INFO_21 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string));
+       if ((from->fields_present & ACCT_COMMENT) &&
+           (from->hdr_comment.buffer)) {
+               old_string = pdb_get_comment(to);
+               new_string = unistr2_static(&from->uni_comment);
+               DEBUG(10,("INFO_21 UNI_COMMENT: %s -> %s\n",old_string, new_string));
                if (STRING_CHANGED)
-                       pdb_set_unknown_str(to   , new_string, PDB_CHANGED);
+                       pdb_set_comment(to, new_string, PDB_CHANGED);
        }
        
        if ((from->fields_present & ACCT_CALLBACK) &&
@@ -445,14 +444,13 @@ void copy_id23_to_sam_passwd(struct samu *to, SAM_USER_INFO_23 *from)
                        pdb_set_workstations(to  , new_string, PDB_CHANGED);
        }
 
-       /* is this right? */
-       if ((from->fields_present & ACCT_ADMIN_DESC) &&
-           (from->hdr_unknown_str.buffer)) {
-               old_string = pdb_get_unknown_str(to);
-               new_string = unistr2_static(&from->uni_unknown_str);
+       if ((from->fields_present & ACCT_COMMENT) &&
+           (from->hdr_comment.buffer)) {
+               old_string = pdb_get_comment(to);
+               new_string = unistr2_static(&from->uni_comment);
                DEBUG(10,("INFO_23 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string));
                if (STRING_CHANGED)
-                       pdb_set_unknown_str(to   , new_string, PDB_CHANGED);
+                       pdb_set_comment(to   , new_string, PDB_CHANGED);
        }
        
        if ((from->fields_present & ACCT_CALLBACK) &&
@@ -683,14 +681,13 @@ void copy_id25_to_sam_passwd(struct samu *to, SAM_USER_INFO_25 *from)
                        pdb_set_workstations(to  , new_string, PDB_CHANGED);
        }
 
-       /* is this right? */
-       if ((from->fields_present & ACCT_ADMIN_DESC) &&
-           (from->hdr_unknown_str.buffer)) {
-               old_string = pdb_get_unknown_str(to);
-               new_string = unistr2_static(&from->uni_unknown_str);
+       if ((from->fields_present & ACCT_COMMENT) &&
+           (from->hdr_comment.buffer)) {
+               old_string = pdb_get_comment(to);
+               new_string = unistr2_static(&from->uni_comment);
                DEBUG(10,("INFO_25 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string));
                if (STRING_CHANGED)
-                       pdb_set_unknown_str(to   , new_string, PDB_CHANGED);
+                       pdb_set_comment(to   , new_string, PDB_CHANGED);
        }
        
        if ((from->fields_present & ACCT_CALLBACK) &&
index 0281e3da0ca2ea30b2aa7d76bcbc08f47103d619..3dbad208cc8ad0e4c8054c19e9843feeba2e883a 100644 (file)
@@ -331,7 +331,7 @@ WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
        /* go ahead and re-read the services immediately */
        reload_services( False );
        
-       if ( lp_servicenumber( sharename )  < 0 )
+       if ( !share_defined( sharename ) )
                return WERR_ACCESS_DENIED;
                
        return WERR_OK;
@@ -1509,7 +1509,6 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
 
        fstring name;
        int snum;
-       struct current_user user;
        Printer_entry *Printer=NULL;
 
        if ( !q_u->printername )
@@ -1533,8 +1532,6 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
                return WERR_INVALID_PRINTER_NAME;
        }
 
-       get_current_user(&user, p);
-
        /*
         * First case: the user is opening the print server:
         *
@@ -1599,12 +1596,12 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
                        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
                           and not a printer admin, then fail */
                        
-                       if ((user.ut.uid != 0) &&
-                           !user_has_privileges(user.nt_user_token,
+                       if ((p->pipe_user.ut.uid != 0) &&
+                           !user_has_privileges(p->pipe_user.nt_user_token,
                                                 &se_printop ) &&
                            !token_contains_name_in_list(
-                                   uidtoname(user.ut.uid), NULL,
-                                   user.nt_user_token,
+                                   uidtoname(p->pipe_user.ut.uid), NULL,
+                                   p->pipe_user.nt_user_token,
                                    lp_printer_admin(snum))) {
                                close_printer_handle(p, handle);
                                return WERR_ACCESS_DENIED;
@@ -1657,9 +1654,9 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
                        return WERR_ACCESS_DENIED;
                }
 
-               if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
-                                  snum) ||
-                   !print_access_check(&user, snum,
+               if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
+                                  p->pipe_user.nt_user_token, snum) ||
+                   !print_access_check(&p->pipe_user, snum,
                                        printer_default->access_required)) {
                        DEBUG(3, ("access DENIED for printer open\n"));
                        close_printer_handle(p, handle);
@@ -1953,20 +1950,17 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER
        NT_PRINTER_DRIVER_INFO_LEVEL    info;
        NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
        int                             version;
-       struct current_user             user;
        WERROR                          status;
        WERROR                          status_win2k = WERR_ACCESS_DENIED;
        SE_PRIV                         se_printop = SE_PRINT_OPERATOR; 
        
-       get_current_user(&user, p);
-        
        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
           and not a printer admin, then fail */
                        
-       if ( (user.ut.uid != 0) 
-               && !user_has_privileges(user.nt_user_token, &se_printop ) 
-               && !token_contains_name_in_list( uidtoname(user.ut.uid), 
-                   NULL, user.nt_user_token, lp_printer_admin(-1)) ) 
+       if ( (p->pipe_user.ut.uid != 0) 
+               && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop ) 
+               && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid), 
+                   NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) ) 
        {
                return WERR_ACCESS_DENIED;
        }
@@ -2013,7 +2007,7 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER
                        /* if we get to here, we now have 2 driver info structures to remove */
                        /* remove the Win2k driver first*/
                
-                       status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
+                       status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
                        free_a_printer_driver( info_win2k, 3 );
                
                        /* this should not have failed---if it did, report to client */
@@ -2025,7 +2019,7 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER
                }
        }
        
-       status = delete_printer_driver(info.info_3, &user, version, False);
+       status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
        
        /* if at least one of the deletes succeeded return OK */
        
@@ -2051,20 +2045,17 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV
        int                             version;
        uint32                          flags = q_u->delete_flags;
        BOOL                            delete_files;
-       struct current_user             user;
        WERROR                          status;
        WERROR                          status_win2k = WERR_ACCESS_DENIED;
        SE_PRIV                         se_printop = SE_PRINT_OPERATOR; 
        
-       get_current_user(&user, p);
-       
        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
           and not a printer admin, then fail */
                        
-       if ( (user.ut.uid != 0) 
-               && !user_has_privileges(user.nt_user_token, &se_printop ) 
-               && !token_contains_name_in_list( uidtoname(user.ut.uid), 
-                   NULL, user.nt_user_token, lp_printer_admin(-1)) ) 
+       if ( (p->pipe_user.ut.uid != 0) 
+               && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop ) 
+               && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid), 
+                   NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) ) 
        {
                return WERR_ACCESS_DENIED;
        }
@@ -2150,7 +2141,7 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV
                        /* if we get to here, we now have 2 driver info structures to remove */
                        /* remove the Win2k driver first*/
                
-                       status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
+                       status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
                        free_a_printer_driver( info_win2k, 3 );
                                
                        /* this should not have failed---if it did, report to client */
@@ -2160,7 +2151,7 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV
                }
        }
 
-       status = delete_printer_driver(info.info_3, &user, version, delete_files);
+       status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
 
        if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
                status = WERR_OK;
@@ -4073,7 +4064,7 @@ static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode
  Create a DEVMODE struct. Returns malloced memory.
 ****************************************************************************/
 
-DEVICEMODE *construct_dev_mode(int snum)
+DEVICEMODE *construct_dev_mode(const char *servicename)
 {
        NT_PRINTER_INFO_LEVEL   *printer = NULL;
        DEVICEMODE              *devmode = NULL;
@@ -4082,7 +4073,7 @@ DEVICEMODE *construct_dev_mode(int snum)
        
        DEBUGADD(8,("getting printer characteristics\n"));
 
-       if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum)))) 
+       if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
                return NULL;
 
        if ( !printer->info_2->devmode ) {
@@ -4154,7 +4145,7 @@ static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *p
        printer->cjobs = count;                                                 /* jobs */
        printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
                        
-       if ( !(printer->devmode = construct_dev_mode(snum)) )
+       if ( !(printer->devmode = construct_dev_mode(lp_const_servicename(snum))) )
                DEBUG(8, ("Returning NULL Devicemode!\n"));
 
        printer->secdesc = NULL;
@@ -5640,15 +5631,12 @@ WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, S
        pstring jobname;
        fstring datatype;
        Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
-       struct current_user user;
 
        if (!Printer) {
                DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
                return WERR_BADFID;
        }
 
-       get_current_user(&user, p);
-
        /*
         * a nice thing with NT is it doesn't listen to what you tell it.
         * when asked to send _only_ RAW datas, it tries to send datas
@@ -5672,7 +5660,7 @@ WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, S
 
        unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
        
-       Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
+       Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
 
        /* An error occured in print_job_start() so return an appropriate
           NT error code. */
@@ -5745,13 +5733,10 @@ WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R
 static WERROR control_printer(POLICY_HND *handle, uint32 command,
                              pipes_struct *p)
 {
-       struct current_user user;
        int snum;
        WERROR errcode = WERR_BADFUNC;
        Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
 
-       get_current_user(&user, p);
-
        if (!Printer) {
                DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
                return WERR_BADFID;
@@ -5762,18 +5747,18 @@ static WERROR control_printer(POLICY_HND *handle, uint32 command,
 
        switch (command) {
        case PRINTER_CONTROL_PAUSE:
-               if (print_queue_pause(&user, snum, &errcode)) {
+               if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
        case PRINTER_CONTROL_RESUME:
        case PRINTER_CONTROL_UNPAUSE:
-               if (print_queue_resume(&user, snum, &errcode)) {
+               if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
        case PRINTER_CONTROL_PURGE:
-               if (print_queue_purge(&user, snum, &errcode)) {
+               if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
@@ -5795,7 +5780,6 @@ WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R
        POLICY_HND      *handle = &q_u->handle;
        Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
        int             snum;
-       struct          current_user user;
        WERROR          errcode = WERR_OK;
        
        if (!Printer) {
@@ -5806,9 +5790,7 @@ WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R
        if (!get_printer_snum(p, handle, &snum))
                return WERR_BADFID;
        
-       get_current_user( &user, p );   
-       
-       print_job_delete( &user, snum, Printer->jobid, &errcode );      
+       print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );      
        
        return errcode;
 }
@@ -6018,7 +6000,9 @@ BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
        SE_PRIV se_printop = SE_PRINT_OPERATOR;
        BOOL is_print_op = False;
 
-       standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
+       standard_sub_basic(current_user_info.smb_name,
+                          current_user_info.domain,
+                          remote_machine,sizeof(remote_machine));
        
        slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
                        cmd, printer->info_2->printername, printer->info_2->sharename,
@@ -6544,7 +6528,7 @@ static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
                
        /* this should not be a failure condition if the devmode is NULL */
        
-       devmode = construct_dev_mode(snum);
+       devmode = construct_dev_mode(lp_const_servicename(snum));
 
        for (i=0; i<*returned; i++)
                fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
@@ -6664,7 +6648,6 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u
        uint32 jobid = q_u->jobid;
        uint32 command = q_u->command;
 
-       struct current_user user;
        int snum;
        WERROR errcode = WERR_BADFUNC;
                
@@ -6676,23 +6659,21 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u
                return WERR_INVALID_PRINTER_NAME;
        }
 
-       get_current_user(&user, p);     
-
        switch (command) {
        case JOB_CONTROL_CANCEL:
        case JOB_CONTROL_DELETE:
-               if (print_job_delete(&user, snum, jobid, &errcode)) {
+               if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
        case JOB_CONTROL_PAUSE:
-               if (print_job_pause(&user, snum, jobid, &errcode)) {
+               if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
                        errcode = WERR_OK;
                }               
                break;
        case JOB_CONTROL_RESTART:
        case JOB_CONTROL_RESUME:
-               if (print_job_resume(&user, snum, jobid, &errcode)) {
+               if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
@@ -7618,26 +7599,23 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u,
        SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
        WERROR err = WERR_OK;
        NT_PRINTER_DRIVER_INFO_LEVEL driver;
-       struct current_user user;
        fstring driver_name;
        uint32 version;
 
        ZERO_STRUCT(driver);
 
-       get_current_user(&user, p);
-       
        if (!convert_printer_driver_info(info, &driver, level)) {
                err = WERR_NOMEM;
                goto done;
        }
 
        DEBUG(5,("Cleaning driver's information\n"));
-       err = clean_up_driver_struct(driver, level, &user);
+       err = clean_up_driver_struct(driver, level, &p->pipe_user);
        if (!W_ERROR_IS_OK(err))
                goto done;
 
        DEBUG(5,("Moving driver to final destination\n"));
-       if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
+       if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
                goto done;
        }
 
@@ -8777,7 +8755,7 @@ static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
         */
         
        if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
-               devmode = construct_dev_mode(snum);
+               devmode = construct_dev_mode(lp_const_servicename(snum));
        else {
                if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
                        ZERO_STRUCTP( devmode );
index 0b4eac5cc7304310857e6fa70dac9985a80d7c3e..e4f85d0bdb4db0aa2eb7204f4973080a14f6b67e 100644 (file)
@@ -6,6 +6,7 @@
  *  Copyright (C) Paul Ashton                       1997,
  *  Copyright (C) Jeremy Allison                    2001,
  *  Copyright (C) Jim McDonough <jmcd@us.ibm.com>   2003.
+ *  Copyright (C) Gera;d (Jerry) Carter             2006.
  *  
  *  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
@@ -550,6 +551,35 @@ static BOOL api_srv_net_file_set_secdesc(pipes_struct *p)
        return True;
 }
 
+/*******************************************************************
+*******************************************************************/
+
+static BOOL api_srv_net_file_close(pipes_struct *p)
+{
+       SRV_Q_NET_FILE_CLOSE q_u;
+       SRV_R_NET_FILE_CLOSE r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       /* Unmarshall the net file set info from Win9x */
+       if(!srv_io_q_net_file_close("", &q_u, data, 0)) {
+               DEBUG(0,("api_srv_net_file_close: Failed to unmarshall SRV_Q_NET_FILE_SET_SECDESC.\n"));
+               return False;
+       }
+
+       r_u.status = _srv_net_file_close(p, &q_u, &r_u);
+
+       if(!srv_io_r_net_file_close("", &r_u, rdata, 0)) {
+               DEBUG(0,("api_srv_net_file_close: Failed to marshall SRV_R_NET_FILE_SET_SECDESC.\n"));
+               return False;
+       }
+
+       return True;
+}
+
 /*******************************************************************
 \PIPE\srvsvc commands
 ********************************************************************/
@@ -573,7 +603,8 @@ static struct api_struct api_srv_cmds[] =
       { "SRV_NET_DISK_ENUM"         , SRV_NET_DISK_ENUM         , api_srv_net_disk_enum          },
       { "SRV_NET_NAME_VALIDATE"     , SRV_NET_NAME_VALIDATE     , api_srv_net_name_validate      },
       { "SRV_NET_FILE_QUERY_SECDESC", SRV_NET_FILE_QUERY_SECDESC, api_srv_net_file_query_secdesc },
-      { "SRV_NET_FILE_SET_SECDESC"  , SRV_NET_FILE_SET_SECDESC  , api_srv_net_file_set_secdesc   }
+      { "SRV_NET_FILE_SET_SECDESC"  , SRV_NET_FILE_SET_SECDESC  , api_srv_net_file_set_secdesc   },
+      { "SRV_NET_FILE_CLOSE"        , SRV_NET_FILE_CLOSE        , api_srv_net_file_close         }
 };
 
 void srvsvc_get_pipe_fns( struct api_struct **fns, int *n_fns )
index a936ef5870987bff6a65323a7fbb74b66c7c43cf..12a86ce9f3322675ed31c5debb1ebd2a0409c1be 100644 (file)
@@ -4,6 +4,7 @@
  *  Copyright (C) Andrew Tridgell              1992-1997,
  *  Copyright (C) Jeremy Allison               2001.
  *  Copyright (C) Nigel Williams               2001.
+ *  Copyright (C) Gerald (Jerry) Carter        2006.
  *  
  *  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
 #include "includes.h"
 
 extern struct generic_mapping file_generic_mapping;
+extern userdom_struct current_user_info;
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
 
+/* Use for enumerating connections, pipes, & files */
+
+struct file_enum_count {
+       TALLOC_CTX *ctx;
+       int count;
+       FILE_INFO_3 *info;
+};
+
+struct sess_file_count {
+       pid_t pid;
+       uid_t uid;
+       int count;
+};
+
+/****************************************************************************
+ Count the entries belonging to a service in the connection db.
+****************************************************************************/
+
+static int pipe_enum_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *p)
+{
+       struct pipe_open_rec prec;
+       struct file_enum_count *fenum = (struct file_enum_count *)p;
+       if (dbuf.dsize != sizeof(struct pipe_open_rec))
+               return 0;
+
+       memcpy(&prec, dbuf.dptr, sizeof(struct pipe_open_rec));
+       if ( process_exists(prec.pid) ) {
+               FILE_INFO_3 *f;
+               int i = fenum->count;
+               pstring fullpath;
+               
+               snprintf( fullpath, sizeof(fullpath), "\\PIPE\\%s", prec.name );
+               
+               f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, FILE_INFO_3, i+1 );
+               if ( !f ) {
+                       DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
+                       return 1;
+               }
+               fenum->info = f;
+               
+               
+               init_srv_file_info3( &fenum->info[i], 
+                       (uint32)((procid_to_pid(&prec.pid)<<16) & prec.pnum),
+                       (FILE_READ_DATA|FILE_WRITE_DATA), 
+                       0,
+                       uidtoname( prec.uid ),
+                       fullpath );
+                       
+               fenum->count++;
+       }
+
+       return 0;
+}
+
+/*******************************************************************
+********************************************************************/
+
+static WERROR net_enum_pipes( TALLOC_CTX *ctx, FILE_INFO_3 **info, 
+                              uint32 *count, uint32 resume )
+{
+       struct file_enum_count fenum;
+       TDB_CONTEXT *conn_tdb = conn_tdb_ctx();
+
+       if ( !conn_tdb ) {
+               DEBUG(0,("net_enum_pipes: Failed to retrieve the connections tdb handle!\n"));
+               return WERR_ACCESS_DENIED;
+       }
+       
+       fenum.ctx = ctx;
+       fenum.count = *count;
+       fenum.info = *info;
+
+       if (tdb_traverse(conn_tdb, pipe_enum_fn, &fenum) == -1) {
+               DEBUG(0,("net_enum_pipes: traverse of connections.tdb failed with error %s.\n",
+                       tdb_errorstr(conn_tdb) ));
+               return WERR_NOMEM;
+       }
+       
+       *info  = fenum.info;
+       *count = fenum.count;
+       
+       return WERR_OK;}
+
+/*******************************************************************
+********************************************************************/
+
+/* global needed to make use of the share_mode_forall() callback */
+static struct file_enum_count f_enum_cnt;
+
+static void enum_file_fn( const struct share_mode_entry *e, 
+                          const char *sharepath, const char *fname )
+{
+       struct file_enum_count *fenum = &f_enum_cnt;
+       /* If the pid was not found delete the entry from connections.tdb */
+
+       if ( process_exists(e->pid) ) {
+               FILE_INFO_3 *f;
+               int i = fenum->count;
+               files_struct fsp;
+               struct byte_range_lock *brl;
+               int num_locks = 0;
+               pstring fullpath;
+               uint32 permissions;
+               
+               f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, FILE_INFO_3, i+1 );                  
+               if ( !f ) {
+                       DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
+                       return;
+               }
+               fenum->info = f;
+
+               /* need to count the number of locks on a file */
+               
+               ZERO_STRUCT( fsp );             
+               fsp.dev   = e->dev;
+               fsp.inode = e->inode;
+               
+               if ( (brl = brl_get_locks(NULL,&fsp)) != NULL ) {
+                       num_locks = brl->num_locks;
+                       TALLOC_FREE( brl );
+               }
+               
+               if ( strcmp( fname, "." ) == 0 ) {
+                       pstr_sprintf( fullpath, "C:%s", sharepath );
+               } else {
+                       pstr_sprintf( fullpath, "C:%s/%s", sharepath, fname );
+               }
+               string_replace( fullpath, '/', '\\' );
+               
+               /* mask out create (what ever that is) */
+               permissions = e->share_access & (FILE_READ_DATA|FILE_WRITE_DATA);
+
+               /* now fill in the FILE_INFO_3 struct */
+               init_srv_file_info3( &fenum->info[i], 
+                       e->share_file_id,
+                       permissions,
+                       num_locks,
+                       uidtoname(e->uid),
+                       fullpath );
+                       
+               fenum->count++;
+       }
+
+       return;
+
+}
+
+/*******************************************************************
+********************************************************************/
+
+static WERROR net_enum_files( TALLOC_CTX *ctx, FILE_INFO_3 **info, 
+                              uint32 *count, uint32 resume )
+{
+       f_enum_cnt.ctx = ctx;
+       f_enum_cnt.count = *count;
+       f_enum_cnt.info = *info;
+       
+       share_mode_forall( enum_file_fn );
+       
+       *info  = f_enum_cnt.info;
+       *count = f_enum_cnt.count;
+       
+       return WERR_OK;
+}
+
 /*******************************************************************
  Utility function to get the 'type' of a share from an snum.
  ********************************************************************/
@@ -70,11 +240,16 @@ static void init_srv_share_info_0(pipes_struct *p, SRV_SHARE_INFO_0 *sh0, int sn
 
 static void init_srv_share_info_1(pipes_struct *p, SRV_SHARE_INFO_1 *sh1, int snum)
 {
+       connection_struct *conn = p->conn;
        pstring remark;
 
        char *net_name = lp_servicename(snum);
        pstrcpy(remark, lp_comment(snum));
-       standard_sub_conn(p->conn, remark,sizeof(remark));
+       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                             conn->connectpath, conn->gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             remark, sizeof(remark));
 
        init_srv_share_info1(&sh1->info_1, net_name, get_share_type(snum), remark);
        init_srv_share_info1_str(&sh1->info_1_str, net_name, remark);
@@ -86,15 +261,21 @@ static void init_srv_share_info_1(pipes_struct *p, SRV_SHARE_INFO_1 *sh1, int sn
 
 static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int snum)
 {
+       connection_struct *conn = p->conn;
        pstring remark;
        pstring path;
        pstring passwd;
        int max_connections = lp_max_connections(snum);
        uint32 max_uses = max_connections!=0 ? max_connections : 0xffffffff;
-
+       int count = 0;
        char *net_name = lp_servicename(snum);
+       
        pstrcpy(remark, lp_comment(snum));
-       standard_sub_conn(p->conn, remark,sizeof(remark));
+       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                             conn->connectpath, conn->gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             remark, sizeof(remark));
        pstrcpy(path, "C:");
        pstrcat(path, lp_pathname(snum));
 
@@ -107,7 +288,10 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn
 
        pstrcpy(passwd, "");
 
-       init_srv_share_info2(&sh2->info_2, net_name, get_share_type(snum), remark, 0, max_uses, 1, path, passwd);
+       count = count_current_connections( net_name, False  );
+       init_srv_share_info2(&sh2->info_2, net_name, get_share_type(snum), 
+               remark, 0, max_uses, count, path, passwd);
+
        init_srv_share_info2_str(&sh2->info_2_str, net_name, remark, path, passwd);
 }
 
@@ -179,11 +363,16 @@ out:
 
 static void init_srv_share_info_501(pipes_struct *p, SRV_SHARE_INFO_501 *sh501, int snum)
 {
+       connection_struct *conn = p->conn;
        pstring remark;
 
        const char *net_name = lp_servicename(snum);
        pstrcpy(remark, lp_comment(snum));
-       standard_sub_conn(p->conn, remark, sizeof(remark));
+       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                             conn->connectpath, conn->gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             remark, sizeof(remark));
 
        init_srv_share_info501(&sh501->info_501, net_name, get_share_type(snum), remark, (lp_csc_policy(snum) << 4));
        init_srv_share_info501_str(&sh501->info_501_str, net_name, remark);
@@ -195,6 +384,7 @@ static void init_srv_share_info_501(pipes_struct *p, SRV_SHARE_INFO_501 *sh501,
 
 static void init_srv_share_info_502(pipes_struct *p, SRV_SHARE_INFO_502 *sh502, int snum)
 {
+       connection_struct *conn = p->conn;
        pstring net_name;
        pstring remark;
        pstring path;
@@ -208,7 +398,11 @@ static void init_srv_share_info_502(pipes_struct *p, SRV_SHARE_INFO_502 *sh502,
 
        pstrcpy(net_name, lp_servicename(snum));
        pstrcpy(remark, lp_comment(snum));
-       standard_sub_conn(p->conn, remark,sizeof(remark));
+       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                             conn->connectpath, conn->gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             remark, sizeof(remark));
        pstrcpy(path, "C:");
        pstrcat(path, lp_pathname(snum));
 
@@ -233,10 +427,15 @@ static void init_srv_share_info_502(pipes_struct *p, SRV_SHARE_INFO_502 *sh502,
 
 static void init_srv_share_info_1004(pipes_struct *p, SRV_SHARE_INFO_1004* sh1004, int snum)
 {
+       connection_struct *conn = p->conn;
         pstring remark;
 
        pstrcpy(remark, lp_comment(snum));
-       standard_sub_conn(p->conn, remark, sizeof(remark));
+       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                             conn->connectpath, conn->gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             remark, sizeof(remark));
 
        ZERO_STRUCTP(sh1004);
   
@@ -632,16 +831,6 @@ static void init_srv_r_net_share_get_info(pipes_struct *p, SRV_R_NET_SHARE_GET_I
        r_n->status = status;
 }
 
-/*******************************************************************
- fill in a sess info level 1 structure.
- ********************************************************************/
-
-static void init_srv_sess_0_info(SESS_INFO_0 *se0, SESS_INFO_0_STR *str0, char *name)
-{
-       init_srv_sess_info0(se0, name);
-       init_srv_sess_info0_str(str0, name);
-}
-
 /*******************************************************************
  fill in a sess info level 0 structure.
  ********************************************************************/
@@ -662,11 +851,7 @@ static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto
 
        if (snum) {
                for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) {
-                       init_srv_sess_0_info(&ss0->info_0[num_entries],
-                                                                &ss0->info_0_str[num_entries], session_list[(*snum)].remote_machine);
-
-                       /* move on to creating next session */
-                       /* move on to creating next sess */
+                       init_srv_sess_info0( &ss0->info_0[num_entries], session_list[(*snum)].remote_machine);
                        num_entries++;
                }
 
@@ -687,17 +872,35 @@ static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto
 }
 
 /*******************************************************************
- fill in a sess info level 1 structure.
- ********************************************************************/
+********************************************************************/
 
-static void init_srv_sess_1_info(SESS_INFO_1 *se1, SESS_INFO_1_STR *str1,
-                               char *name, char *user,
-                               uint32 num_opens,
-                               uint32 open_time, uint32 idle_time,
-                               uint32 usr_flgs)
+/* global needed to make use of the share_mode_forall() callback */
+static struct sess_file_count s_file_cnt;
+
+static void sess_file_fn( const struct share_mode_entry *e, 
+                          const char *sharepath, const char *fname )
 {
-       init_srv_sess_info1(se1 , name, user, num_opens, open_time, idle_time, usr_flgs);
-       init_srv_sess_info1_str(str1, name, user);
+       struct sess_file_count *sess = &s_file_cnt;
+       if ( (procid_to_pid(&e->pid) == sess->pid) && (sess->uid == e->uid) ) {
+               sess->count++;
+       }
+       
+       return;
+}
+
+/*******************************************************************
+********************************************************************/
+
+static int net_count_files( uid_t uid, pid_t pid )
+{
+       s_file_cnt.count = 0;
+       s_file_cnt.uid = uid;
+       s_file_cnt.pid = pid;
+       
+       share_mode_forall( sess_file_fn );
+       
+       return s_file_cnt.count;
 }
 
 /*******************************************************************
@@ -708,43 +911,58 @@ static void init_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *sto
 {
        struct sessionid *session_list;
        uint32 num_entries = 0;
-       (*stot) = list_sessions(&session_list);
+       time_t now = time(NULL);
 
+       if ( !snum ) {
+               ss1->num_entries_read = 0;
+               ss1->ptr_sess_info = 0;
+               ss1->num_entries_read2 = 0;
+               
+               (*stot) = 0;
+
+               return;
+       }
+       
        if (ss1 == NULL) {
                (*snum) = 0;
-               SAFE_FREE(session_list);
                return;
        }
 
-       DEBUG(5,("init_srv_sess_1_ss1\n"));
-
-       if (snum) {
-               for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) {
-                       init_srv_sess_1_info(&ss1->info_1[num_entries],
-                                            &ss1->info_1_str[num_entries],
-                                           session_list[*snum].remote_machine,
-                                            session_list[*snum].username,
-                                            1, 10, 5, 0);
-
-                       /* move on to creating next session */
-                       /* move on to creating next sess */
-                       num_entries++;
-               }
+       (*stot) = list_sessions(&session_list);
+       
 
-               ss1->num_entries_read  = num_entries;
-               ss1->ptr_sess_info     = num_entries > 0 ? 1 : 0;
-               ss1->num_entries_read2 = num_entries;
-               
-               if ((*snum) >= (*stot)) {
-                       (*snum) = 0;
+       for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) {
+               uint32 num_files;
+               uint32 connect_time;
+               struct passwd *pw = sys_getpwnam(session_list[*snum].username);
+               BOOL guest;
+                       
+               if ( !pw ) {
+                       DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n",
+                               session_list[*snum].username));
+                       continue;
                }
-
-       } else {
-               ss1->num_entries_read = 0;
-               ss1->ptr_sess_info = 0;
-               ss1->num_entries_read2 = 0;
-               
-               (*stot) = 0;
+                               
+               connect_time = (uint32)(now - session_list[*snum].connect_start);
+               num_files = net_count_files(pw->pw_uid, session_list[*snum].pid);
+               guest = strequal( session_list[*snum].username, lp_guestaccount() );
+                                       
+               init_srv_sess_info1( &ss1->info_1[num_entries], 
+                                    session_list[*snum].remote_machine,
+                                    session_list[*snum].username, 
+                                    num_files,
+                                    connect_time,
+                                    0, 
+                                    guest);
+               num_entries++;
+       }
+
+       ss1->num_entries_read  = num_entries;
+       ss1->ptr_sess_info     = num_entries > 0 ? 1 : 0;
+       ss1->num_entries_read2 = num_entries;
+       
+       if ((*snum) >= (*stot)) {
+               (*snum) = 0;
        }
 
        SAFE_FREE(session_list);
@@ -964,66 +1182,53 @@ static void init_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n,
  makes a SRV_R_NET_FILE_ENUM structure.
 ********************************************************************/
 
-static WERROR init_srv_file_info_ctr(pipes_struct *p, SRV_FILE_INFO_CTR *ctr,
-                                    int switch_value, uint32 *resume_hnd, 
-                                    uint32 *total_entries)  
+static WERROR net_file_enum_3( SRV_R_NET_FILE_ENUM *r, uint32 resume_hnd )
 {
-       WERROR status = WERR_OK;
-       TALLOC_CTX *ctx = p->mem_ctx;
-       DEBUG(5,("init_srv_file_info_ctr: %d\n", __LINE__));
-       *total_entries = 1; /* dummy entries only, for */
+       TALLOC_CTX *ctx = get_talloc_ctx();
+       SRV_FILE_INFO_CTR *ctr = &r->ctr;
 
-       ctr->switch_value = switch_value;
-       ctr->num_entries = *total_entries - *resume_hnd;
+       /* TODO -- Windows enumerates 
+          (b) active pipes
+          (c) open directories and files */
+
+       r->status = net_enum_files( ctx, &ctr->file.info3, &ctr->num_entries, resume_hnd );
+       if ( !W_ERROR_IS_OK(r->status))
+               goto done;
+               
+       r->status = net_enum_pipes( ctx, &ctr->file.info3, &ctr->num_entries, resume_hnd );
+       if ( !W_ERROR_IS_OK(r->status))
+               goto done;
+       
+       r->level = ctr->level = 3;
+       r->total_entries = ctr->num_entries;
+       /* ctr->num_entries = r->total_entries - resume_hnd; */
        ctr->num_entries2 = ctr->num_entries;
+       ctr->ptr_file_info = 1;
 
-       switch (switch_value) {
-       case 3: {
-               int i;
-               if (*total_entries > 0) {
-                       ctr->ptr_entries = 1;
-                       ctr->file.info3 = TALLOC_ARRAY(ctx, SRV_FILE_INFO_3, ctr->num_entries);
-               }
-               for (i=0 ;i<ctr->num_entries;i++) {
-                       init_srv_file_info3(&ctr->file.info3[i].info_3, i+*resume_hnd, 0x35, 0, "\\PIPE\\samr", "dummy user");
-                       init_srv_file_info3_str(&ctr->file.info3[i].info_3_str,  "\\PIPE\\samr", "dummy user");
-                       
-               }
-               ctr->ptr_file_info = 1;
-               *resume_hnd = 0;
-               break;
-       }
-       default:
-               DEBUG(5,("init_srv_file_info_ctr: unsupported switch value %d\n", switch_value));
-               (*resume_hnd = 0);
-               (*total_entries) = 0;
-               ctr->ptr_entries = 0;
-               status = WERR_UNKNOWN_LEVEL;
-               break;
-       }
+       r->status = WERR_OK;
 
-       return status;
+done:
+       if ( ctr->num_entries > 0 ) 
+               ctr->ptr_entries = 1;
+
+       init_enum_hnd(&r->enum_hnd, 0);
+
+       return r->status;
 }
 
 /*******************************************************************
- makes a SRV_R_NET_FILE_ENUM structure.
-********************************************************************/
+*******************************************************************/
 
-static void init_srv_r_net_file_enum(pipes_struct *p, SRV_R_NET_FILE_ENUM *r_n,
-                               uint32 resume_hnd, int file_level, int switch_value)  
+WERROR _srv_net_file_enum(pipes_struct *p, SRV_Q_NET_FILE_ENUM *q_u, SRV_R_NET_FILE_ENUM *r_u)
 {
-       DEBUG(5,("init_srv_r_net_file_enum: %d\n", __LINE__));
-
-       r_n->file_level  = file_level;
-       if (file_level == 0)
-               r_n->status = WERR_UNKNOWN_LEVEL;
-       else
-               r_n->status = init_srv_file_info_ctr(p, &r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries));
-
-       if (!W_ERROR_IS_OK(r_n->status))
-               resume_hnd = 0;
-
-       init_enum_hnd(&r_n->enum_hnd, resume_hnd);
+       switch ( q_u->level ) {
+       case 3:
+               return net_file_enum_3( r_u, get_enum_hnd(&q_u->enum_hnd) );    
+       default:
+               return WERR_UNKNOWN_LEVEL;
+       }
+       
+       return WERR_OK;
 }
 
 /*******************************************************************
@@ -1109,25 +1314,6 @@ WERROR _srv_net_srv_set_info(pipes_struct *p, SRV_Q_NET_SRV_SET_INFO *q_u, SRV_R
        return r_u->status;
 }
 
-/*******************************************************************
-net file enum
-********************************************************************/
-
-WERROR _srv_net_file_enum(pipes_struct *p, SRV_Q_NET_FILE_ENUM *q_u, SRV_R_NET_FILE_ENUM *r_u)
-{
-       DEBUG(5,("srv_net_file_enum: %d\n", __LINE__));
-
-       /* set up the */
-       init_srv_r_net_file_enum(p, r_u,
-                               get_enum_hnd(&q_u->enum_hnd),
-                               q_u->file_level,
-                               q_u->ctr.switch_value);
-
-       DEBUG(5,("srv_net_file_enum: %d\n", __LINE__));
-
-       return r_u->status;
-}
-
 /*******************************************************************
 net conn enum
 ********************************************************************/
@@ -1185,7 +1371,6 @@ net sess del
 WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SESS_DEL *r_u)
 {
        struct sessionid *session_list;
-       struct current_user user;
        int num_sessions, snum;
        fstring username;
        fstring machine;
@@ -1205,11 +1390,9 @@ WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SES
 
        r_u->status = WERR_ACCESS_DENIED;
 
-       get_current_user(&user, p);
-
        /* fail out now if you are not root or not a domain admin */
 
-       if ((user.ut.uid != sec_initial_uid()) && 
+       if ((p->pipe_user.ut.uid != sec_initial_uid()) && 
                ( ! nt_token_check_domain_rid(p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS))) {
 
                goto done;
@@ -1220,7 +1403,7 @@ WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SES
                if ((strequal(session_list[snum].username, username) || username[0] == '\0' ) &&
                    strequal(session_list[snum].remote_machine, machine)) {
                
-                       if (user.ut.uid != sec_initial_uid()) {
+                       if (p->pipe_user.ut.uid != sec_initial_uid()) {
                                not_root = True;
                                become_root();
                        }
@@ -1337,7 +1520,6 @@ char *valid_share_pathname(char *dos_pathname)
 
 WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, SRV_R_NET_SHARE_SET_INFO *r_u)
 {
-       struct current_user user;
        pstring command;
        fstring share_name;
        fstring comment;
@@ -1374,13 +1556,11 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
        if (lp_print_ok(snum))
                return WERR_ACCESS_DENIED;
 
-       get_current_user(&user,p);
-
        is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
        
        /* fail out now if you are not root and not a disk op */
        
-       if ( user.ut.uid != sec_initial_uid() && !is_disk_op )
+       if ( p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op )
                return WERR_ACCESS_DENIED;
 
        switch (q_u->info_level) {
@@ -1525,7 +1705,6 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
 
 WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_SHARE_ADD *r_u)
 {
-       struct current_user user;
        pstring command;
        fstring share_name;
        fstring comment;
@@ -1543,11 +1722,9 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
 
        r_u->parm_error = 0;
 
-       get_current_user(&user,p);
-
        is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
 
-       if (user.ut.uid != sec_initial_uid()  && !is_disk_op ) 
+       if (p->pipe_user.ut.uid != sec_initial_uid()  && !is_disk_op ) 
                return WERR_ACCESS_DENIED;
 
        if (!lp_add_share_cmd() || !*lp_add_share_cmd()) {
@@ -1682,7 +1859,6 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
 
 WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_SHARE_DEL *r_u)
 {
-       struct current_user user;
        pstring command;
        fstring share_name;
        int ret;
@@ -1710,11 +1886,9 @@ WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_S
        if (lp_print_ok(snum))
                return WERR_ACCESS_DENIED;
 
-       get_current_user(&user,p);
-
        is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
 
-       if (user.ut.uid != sec_initial_uid()  && !is_disk_op ) 
+       if (p->pipe_user.ut.uid != sec_initial_uid()  && !is_disk_op ) 
                return WERR_ACCESS_DENIED;
 
        if (!lp_delete_share_cmd() || !*lp_delete_share_cmd()) {
@@ -1826,7 +2000,6 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
        SMB_STRUCT_STAT st;
        BOOL bad_path;
        NTSTATUS nt_status;
-       struct current_user user;
        connection_struct *conn = NULL;
        BOOL became_user = False; 
 
@@ -1839,10 +2012,8 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
        /* Null password is ok - we are already an authenticated user... */
        null_pw = data_blob(NULL, 0);
 
-       get_current_user(&user, p);
-
        become_root();
-       conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status);
+       conn = make_connection(qualname, null_pw, "A:", p->pipe_user.vuid, &nt_status);
        unbecome_root();
 
        if (conn == NULL) {
@@ -1872,18 +2043,18 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
                goto error_exit;
        }
 
-       fsp = open_file_stat(conn, filename, &st);
-       if (!fsp) {
+       nt_status = open_file_stat(conn, filename, &st, &fsp);
+       if (!NT_STATUS_IS_OK(nt_status)) {
                /* Perhaps it is a directory */
-               if (errno == EISDIR)
-                       fsp = open_directory(conn, filename, &st,
+               if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY))
+                       nt_status = open_directory(conn, filename, &st,
                                        READ_CONTROL_ACCESS,
                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
                                        FILE_OPEN,
                                        0,
-                                       NULL);
+                                       NULL, &fsp);
 
-               if (!fsp) {
+               if (!NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", filename));
                        r_u->status = WERR_ACCESS_DENIED;
                        goto error_exit;
@@ -1908,7 +2079,7 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
 
        close_file(fsp, NORMAL_CLOSE);
        unbecome_user();
-       close_cnum(conn, user.vuid);
+       close_cnum(conn, p->pipe_user.vuid);
        return r_u->status;
 
 error_exit:
@@ -1921,7 +2092,7 @@ error_exit:
                unbecome_user();
 
        if (conn) 
-               close_cnum(conn, user.vuid);
+               close_cnum(conn, p->pipe_user.vuid);
 
        return r_u->status;
 }
@@ -1941,7 +2112,6 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
        SMB_STRUCT_STAT st;
        BOOL bad_path;
        NTSTATUS nt_status;
-       struct current_user user;
        connection_struct *conn = NULL;
        BOOL became_user = False;
 
@@ -1954,10 +2124,8 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
        /* Null password is ok - we are already an authenticated user... */
        null_pw = data_blob(NULL, 0);
 
-       get_current_user(&user, p);
-
        become_root();
-       conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status);
+       conn = make_connection(qualname, null_pw, "A:", p->pipe_user.vuid, &nt_status);
        unbecome_root();
 
        if (conn == NULL) {
@@ -1988,19 +2156,19 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
        }
 
 
-       fsp = open_file_stat(conn, filename, &st);
+       nt_status = open_file_stat(conn, filename, &st, &fsp);
 
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(nt_status)) {
                /* Perhaps it is a directory */
-               if (errno == EISDIR)
-                       fsp = open_directory(conn, filename, &st,
+               if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY))
+                       nt_status = open_directory(conn, filename, &st,
                                                FILE_READ_ATTRIBUTES,
                                                FILE_SHARE_READ|FILE_SHARE_WRITE,
                                                FILE_OPEN,
                                                0,
-                                               NULL);
+                                               NULL, &fsp);
 
-               if (!fsp) {
+               if (!NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", filename));
                        r_u->status = WERR_ACCESS_DENIED;
                        goto error_exit;
@@ -2017,7 +2185,7 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
 
        close_file(fsp, NORMAL_CLOSE);
        unbecome_user();
-       close_cnum(conn, user.vuid);
+       close_cnum(conn, p->pipe_user.vuid);
        return r_u->status;
 
 error_exit:
@@ -2031,7 +2199,7 @@ error_exit:
        }
 
        if (conn) {
-               close_cnum(conn, user.vuid);
+               close_cnum(conn, p->pipe_user.vuid);
        }
 
        return r_u->status;
@@ -2133,7 +2301,7 @@ WERROR _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV
 
        switch ( q_u->type ) {
        case 0x9:
-               rpcstr_pull(sharename, q_u->uni_name.buffer, sizeof(sharename), q_u->uni_name.uni_str_len*2, 0);
+               rpcstr_pull(sharename, q_u->sharename.buffer, sizeof(sharename), q_u->sharename.uni_str_len*2, 0);
                if ( !validate_net_name( sharename, INVALID_SHARENAME_CHARS, sizeof(sharename) ) ) {
                        DEBUG(5,("_srv_net_name_validate: Bad sharename \"%s\"\n", sharename));
                        return WERR_INVALID_NAME;
@@ -2146,3 +2314,13 @@ WERROR _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV
 
        return WERR_OK;
 }
+
+
+/********************************************************************
+********************************************************************/
+
+WERROR _srv_net_file_close(pipes_struct *p, SRV_Q_NET_FILE_CLOSE *q_u, SRV_R_NET_FILE_CLOSE *r_u)
+{
+       return WERR_ACCESS_DENIED;
+}
+
index 6062dcee5cebbb79cc263cafca4bb5a91827078d..dd790691d36374f37fbf15e22cf0c7f3aab45f6c 100644 (file)
@@ -624,7 +624,7 @@ static WERROR fill_svc_config( TALLOC_CTX *ctx, const char *name, SERVICE_CONFIG
           the client from showing the "Start" button (if of course the services
           are not running */
 
-       if ( strequal( name, "NETLOGON" ) && ( lp_servicenumber(name) == -1 ) )
+       if ( strequal( name, "NETLOGON" ) && ( !share_defined(name) ) )
                config->start_type = SVCCTL_DISABLED;
        else if ( strequal( name, "WINS" ) && ( !lp_wins_support() ))
                config->start_type = SVCCTL_DISABLED;
diff --git a/source/rpc_server/srv_unixinfo.c b/source/rpc_server/srv_unixinfo.c
new file mode 100644 (file)
index 0000000..f21416d
--- /dev/null
@@ -0,0 +1,163 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  RPC Pipe client / server routines for unixinfo-pipe
+ *  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.
+ */
+
+/* This is the interface to the rpcunixinfo pipe. */
+
+#include "includes.h"
+#include "nterr.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+static BOOL api_sid_to_uid(pipes_struct *p)
+{
+       UNIXINFO_Q_SID_TO_UID q_u;
+       UNIXINFO_R_SID_TO_UID r_u;
+
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if (!unixinfo_io_q_unixinfo_sid_to_uid("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _unixinfo_sid_to_uid(p, &q_u, &r_u);
+
+       if (!unixinfo_io_r_unixinfo_sid_to_uid("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+static BOOL api_uid_to_sid(pipes_struct *p)
+{
+       UNIXINFO_Q_UID_TO_SID q_u;
+       UNIXINFO_R_UID_TO_SID r_u;
+
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if (!unixinfo_io_q_unixinfo_uid_to_sid("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _unixinfo_uid_to_sid(p, &q_u, &r_u);
+
+       if (!unixinfo_io_r_unixinfo_uid_to_sid("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+static BOOL api_sid_to_gid(pipes_struct *p)
+{
+       UNIXINFO_Q_SID_TO_GID q_u;
+       UNIXINFO_R_SID_TO_GID r_u;
+
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if (!unixinfo_io_q_unixinfo_sid_to_gid("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _unixinfo_sid_to_gid(p, &q_u, &r_u);
+
+       if (!unixinfo_io_r_unixinfo_sid_to_gid("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+static BOOL api_gid_to_sid(pipes_struct *p)
+{
+       UNIXINFO_Q_GID_TO_SID q_u;
+       UNIXINFO_R_GID_TO_SID r_u;
+
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if (!unixinfo_io_q_unixinfo_gid_to_sid("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _unixinfo_gid_to_sid(p, &q_u, &r_u);
+
+       if (!unixinfo_io_r_unixinfo_gid_to_sid("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+static BOOL api_getpwuid(pipes_struct *p)
+{
+       UNIXINFO_Q_GETPWUID q_u;
+       UNIXINFO_R_GETPWUID r_u;
+
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if (!unixinfo_io_q_unixinfo_getpwuid("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _unixinfo_getpwuid(p, &q_u, &r_u);
+
+       if (!unixinfo_io_r_unixinfo_getpwuid("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+\pipe\unixinfo commands
+********************************************************************/
+
+struct api_struct api_unixinfo_cmds[] = {
+       {"SID_TO_UID",       UNIXINFO_SID_TO_UID,     api_sid_to_uid },
+       {"UID_TO_SID",       UNIXINFO_UID_TO_SID,     api_uid_to_sid },
+       {"SID_TO_GID",       UNIXINFO_SID_TO_GID,     api_sid_to_gid },
+       {"GID_TO_SID",       UNIXINFO_GID_TO_SID,     api_gid_to_sid },
+       {"GETPWUID",         UNIXINFO_GETPWUID,       api_getpwuid },
+};
+
+
+void unixinfo_get_pipe_fns( struct api_struct **fns, int *n_fns )
+{
+       *fns = api_unixinfo_cmds;
+       *n_fns = sizeof(api_unixinfo_cmds) / sizeof(struct api_struct);
+}
+
+NTSTATUS rpc_unixinfo_init(void)
+{
+       return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION,
+               "unixinfo", "unixinfo", api_unixinfo_cmds,
+               sizeof(api_unixinfo_cmds) / sizeof(struct api_struct));
+}
diff --git a/source/rpc_server/srv_unixinfo_nt.c b/source/rpc_server/srv_unixinfo_nt.c
new file mode 100644 (file)
index 0000000..79756f2
--- /dev/null
@@ -0,0 +1,166 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  RPC Pipe client / server routines for unixinfo-pipe
+ *  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.
+ */
+
+/* This is the interface to the rpcunixinfo pipe. */
+
+#include "includes.h"
+#include "nterr.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+/* Map a sid to a uid */
+
+NTSTATUS _unixinfo_sid_to_uid(pipes_struct *p,
+                             UNIXINFO_Q_SID_TO_UID *q_u,
+                             UNIXINFO_R_SID_TO_UID *r_u)
+{
+       uid_t uid;
+
+       r_u->uid.low = 0;
+       r_u->uid.high = 0;
+
+       r_u->status = sid_to_uid(&q_u->sid, &uid) ? NT_STATUS_OK : NT_STATUS_NONE_MAPPED;
+       if (NT_STATUS_IS_OK(r_u->status))
+               r_u->uid.low = uid;
+
+       return r_u->status;
+}
+
+/* Map a uid to a sid */
+
+NTSTATUS _unixinfo_uid_to_sid(pipes_struct *p,
+                             UNIXINFO_Q_UID_TO_SID *q_u,
+                             UNIXINFO_R_UID_TO_SID *r_u)
+{
+       DOM_SID sid;
+
+       r_u->status = NT_STATUS_NO_SUCH_USER;
+
+       if (q_u->uid.high == 0) {
+               uid_to_sid(&sid, q_u->uid.low);
+               r_u->status = NT_STATUS_OK;
+       }
+
+       init_r_unixinfo_uid_to_sid(r_u,
+                               NT_STATUS_IS_OK(r_u->status) ? &sid : NULL);
+
+       return r_u->status;
+}
+
+/* Map a sid to a gid */
+
+NTSTATUS _unixinfo_sid_to_gid(pipes_struct *p,
+                             UNIXINFO_Q_SID_TO_GID *q_u,
+                             UNIXINFO_R_SID_TO_GID *r_u)
+{
+       gid_t gid;
+
+       r_u->gid.low = 0;
+       r_u->gid.high = 0;
+
+       r_u->status = sid_to_gid(&q_u->sid, &gid) ? NT_STATUS_OK : NT_STATUS_NONE_MAPPED;
+       if (NT_STATUS_IS_OK(r_u->status))
+               r_u->gid.low = gid;
+
+       return r_u->status;
+}
+
+/* Map a gid to a sid */
+
+NTSTATUS _unixinfo_gid_to_sid(pipes_struct *p,
+                             UNIXINFO_Q_GID_TO_SID *q_u,
+                             UNIXINFO_R_GID_TO_SID *r_u)
+{
+       DOM_SID sid;
+
+       r_u->status = NT_STATUS_NO_SUCH_USER;
+
+       if (q_u->gid.high == 0) {
+               gid_to_sid(&sid, q_u->gid.low);
+               r_u->status = NT_STATUS_OK;
+       }
+
+       init_r_unixinfo_gid_to_sid(r_u,
+                               NT_STATUS_IS_OK(r_u->status) ? &sid : NULL);
+
+       return r_u->status;
+}
+
+/* Get unix struct passwd information */
+
+NTSTATUS _unixinfo_getpwuid(pipes_struct *p,
+                           UNIXINFO_Q_GETPWUID *q_u,
+                           UNIXINFO_R_GETPWUID *r_u)
+{
+       int i;
+
+       if (r_u->count > 1023) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       r_u->info = TALLOC_ARRAY(p->mem_ctx, struct unixinfo_getpwuid,
+                                q_u->count);
+
+       if ((r_u->count > 0) && (r_u->info == NULL)) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       r_u->status = NT_STATUS_OK;
+       r_u->count = q_u->count;
+
+       for (i=0; i<r_u->count; i++) {
+               struct passwd *pw;
+               char *homedir, *shell;
+               ssize_t len1, len2;
+
+               r_u->info[i].status = NT_STATUS_NO_SUCH_USER;
+               r_u->info[i].homedir = "";
+               r_u->info[i].shell = "";
+
+               if (q_u->uid[i].high != 0) {
+                       DEBUG(10, ("64-bit uids not yet supported...\n"));
+                       continue;
+               }
+
+               pw = getpwuid(q_u->uid[i].low);
+
+               if (pw == NULL) {
+                       DEBUG(10, ("Did not find uid %d\n", q_u->uid[i].low));
+                       continue;
+               }
+
+               len1 = push_utf8_talloc(p->mem_ctx, &homedir, pw->pw_dir);
+               len2 = push_utf8_talloc(p->mem_ctx, &shell, pw->pw_shell);
+
+               if ((len1 < 0) || (len2 < 0) || (homedir == NULL) ||
+                   (shell == NULL)) {
+                       DEBUG(3, ("push_utf8_talloc failed\n"));
+                       r_u->info[i].status = NT_STATUS_NO_MEMORY;
+                       continue;
+               }
+
+               r_u->info[i].status = NT_STATUS_OK;
+               r_u->info[i].homedir = homedir;
+               r_u->info[i].shell = shell;
+       }
+
+       return r_u->status;
+}
index 1a204e70bc7da7820ca90a25582aadd8b47b281d..2aab35ea3c44a72bdb2bc83d6329446a34674a5d 100644 (file)
@@ -77,7 +77,7 @@ static void display_sam_user_info_21(SAM_USER_INFO_21 *usr)
        unistr2_to_ascii(temp, &usr->uni_workstations, sizeof(temp)-1);
        printf("\tWorkstations:\t%s\n", temp);
        
-       unistr2_to_ascii(temp, &usr->uni_unknown_str, sizeof(temp)-1);
+       unistr2_to_ascii(temp, &usr->uni_comment, sizeof(temp)-1);
        printf("\tUnknown Str :\t%s\n", temp);
        
        unistr2_to_ascii(temp, &usr->uni_munged_dial, sizeof(temp)-1);
index ed5653eb7044876aedd8f3bb3ab49ba69d7f5d45..d77c58ad9596f5abc6af38b281a9ef46bf90eb2e 100644 (file)
@@ -709,17 +709,23 @@ static void display_reg_value(REGISTRY_VALUE value)
                break;
        }
        case REG_MULTI_SZ: {
-               uint16 *curstr = (uint16 *) value.data_p;
-               uint8 *start = value.data_p;
-               printf("%s: REG_MULTI_SZ:\n", value.valuename);
-               while (((uint8 *) curstr < start + value.size)) {
-                       rpcstr_pull(text, curstr, sizeof(text), -1, 
-                                   STR_TERMINATE);
-                       printf("  %s\n", *text != 0 ? text : "NULL");
-                       curstr += strlen(text) + 1;
+               int i, num_values;
+               char **values;
+
+               if (!NT_STATUS_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
+                                                      value.size,
+                                                      &num_values,
+                                                      &values))) {
+                       d_printf("reg_pull_multi_sz failed\n");
+                       break;
+               }
+
+               for (i=0; i<num_values; i++) {
+                       d_printf("%s\n", values[i]);
                }
+               TALLOC_FREE(values);
+               break;
        }
-       break;
        default:
                printf("%s: unknown type %d\n", value.valuename, value.type);
        }
@@ -2012,7 +2018,7 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
         if (!W_ERROR_IS_OK(result))
                 goto done;
                
-       printf("%s\n", timestring(True));
+       printf("%s\n", current_timestring(True));
        printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
 
        /* Set the printer data */
@@ -2088,7 +2094,7 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
         if (!W_ERROR_IS_OK(result))
                 goto done;
                
-       printf("%s\n", timestring(True));
+       printf("%s\n", current_timestring(True));
        printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
 
 done:
diff --git a/source/rpcclient/cmd_unixinfo.c b/source/rpcclient/cmd_unixinfo.c
new file mode 100644 (file)
index 0000000..2e9ab10
--- /dev/null
@@ -0,0 +1,195 @@
+/* 
+   Unix SMB/CIFS implementation.
+   RPC pipe client
+
+   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"
+#include "rpcclient.h"
+
+static NTSTATUS cmd_unixinfo_uid2sid(struct rpc_pipe_client *cli,
+                                    TALLOC_CTX *mem_ctx,
+                                    int argc, const char **argv)
+{
+       uid_t uid;
+       DOM_SID sid;
+       NTSTATUS result;
+
+       if (argc != 2) {
+               printf("Usage: %s uid\n", argv[0]);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       uid = atoi(argv[1]);
+
+       result = rpccli_unixinfo_uid2sid(cli, mem_ctx, uid, &sid);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       printf("%s\n", sid_string_static(&sid));
+
+done:
+       return result;
+}
+
+static NTSTATUS cmd_unixinfo_sid2uid(struct rpc_pipe_client *cli,
+                                    TALLOC_CTX *mem_ctx,
+                                    int argc, const char **argv)
+{
+       uid_t uid;
+       DOM_SID sid;
+       NTSTATUS result;
+
+       if (argc != 2) {
+               printf("Usage: %s sid\n", argv[0]);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (!string_to_sid(&sid, argv[1])) {
+               result = NT_STATUS_INVALID_SID;
+               goto done;
+       }
+
+       result = rpccli_unixinfo_sid2uid(cli, mem_ctx, &sid, &uid);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       printf("%u\n", uid);
+
+done:
+       return result;
+}
+
+static NTSTATUS cmd_unixinfo_gid2sid(struct rpc_pipe_client *cli,
+                                    TALLOC_CTX *mem_ctx,
+                                    int argc, const char **argv)
+{
+       gid_t gid;
+       DOM_SID sid;
+       NTSTATUS result;
+
+       if (argc != 2) {
+               printf("Usage: %s gid\n", argv[0]);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       gid = atoi(argv[1]);
+
+       result = rpccli_unixinfo_gid2sid(cli, mem_ctx, gid, &sid);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       printf("%s\n", sid_string_static(&sid));
+
+done:
+       return result;
+}
+
+static NTSTATUS cmd_unixinfo_sid2gid(struct rpc_pipe_client *cli,
+                                    TALLOC_CTX *mem_ctx,
+                                    int argc, const char **argv)
+{
+       gid_t gid;
+       DOM_SID sid;
+       NTSTATUS result;
+
+       if (argc != 2) {
+               printf("Usage: %s sid\n", argv[0]);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (!string_to_sid(&sid, argv[1])) {
+               result = NT_STATUS_INVALID_SID;
+               goto done;
+       }
+
+       result = rpccli_unixinfo_sid2gid(cli, mem_ctx, &sid, &gid);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       printf("%u\n", gid);
+
+done:
+       return result;
+}
+
+static NTSTATUS cmd_unixinfo_getpwuid(struct rpc_pipe_client *cli,
+                                     TALLOC_CTX *mem_ctx,
+                                     int argc, const char **argv)
+{
+       uid_t *uids;
+       int i, num_uids;
+       struct unixinfo_getpwuid *info;
+       NTSTATUS result;
+
+       if (argc < 2) {
+               printf("Usage: %s uid [uid2 uid3 ...]\n", argv[0]);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       num_uids = argc-1;
+       uids = TALLOC_ARRAY(mem_ctx, uid_t, num_uids);
+
+       if (uids == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0; i<num_uids; i++) {
+               uids[i] = atoi(argv[i+1]);
+       }
+
+       result = rpccli_unixinfo_getpwuid(cli, mem_ctx, num_uids, uids, &info);
+
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
+
+       for (i=0; i<num_uids; i++) {
+               if (NT_STATUS_IS_OK(info[i].status)) {
+                       printf("%d:%s:%s\n", uids[i], info[i].homedir,
+                              info[i].shell);
+               } else {
+                       printf("%d:%s\n", uids[i], nt_errstr(info[i].status));
+               }
+       }
+
+       return NT_STATUS_OK;
+}
+
+/* List of commands exported by this module */
+
+struct cmd_set unixinfo_commands[] = {
+
+       { "UNIXINFO" },
+
+       { "uid2sid", RPC_RTYPE_NTSTATUS, cmd_unixinfo_uid2sid, NULL,
+         PI_UNIXINFO, NULL, "Convert a uid to a sid", "" },
+       { "sid2uid", RPC_RTYPE_NTSTATUS, cmd_unixinfo_sid2uid, NULL,
+         PI_UNIXINFO, NULL, "Convert a sid to a uid", "" },
+       { "gid2sid", RPC_RTYPE_NTSTATUS, cmd_unixinfo_gid2sid, NULL,
+         PI_UNIXINFO, NULL, "Convert a gid to a sid", "" },
+       { "sid2gid", RPC_RTYPE_NTSTATUS, cmd_unixinfo_sid2gid, NULL,
+         PI_UNIXINFO, NULL, "Convert a sid to a gid", "" },
+       { "getpwuid", RPC_RTYPE_NTSTATUS, cmd_unixinfo_getpwuid, NULL,
+         PI_UNIXINFO, NULL, "Get passwd info", "" },
+       { NULL }
+};
index d5425aa43d1785960ca60a1b71365e9e458935f8..4ca674c2b100d03eb4b8181c419e7fbfc841a96e 100644 (file)
@@ -457,6 +457,7 @@ static struct cmd_set separator_command[] = {
 
 /* Various pipe commands */
 
+extern struct cmd_set unixinfo_commands[];
 extern struct cmd_set lsarpc_commands[];
 extern struct cmd_set samr_commands[];
 extern struct cmd_set spoolss_commands[];
@@ -471,6 +472,7 @@ extern struct cmd_set test_commands[];
 
 static struct cmd_set *rpcclient_command_list[] = {
        rpcclient_commands,
+       unixinfo_commands,
        lsarpc_commands,
        ds_commands,
        samr_commands,
index aa5b923d3ddcb815b6f7dcb2b9a6fe7db521ff5e..e8ebd9272c3a139bc272d7d69a669d206265e607 100644 (file)
@@ -4,7 +4,7 @@
    Copyright (C) Tim Potter 2000
    Copyright (C) Jim McDonough <jmcd@us.ibm.com>       2003
    Copyright (C) Simo Sorce 2003
-   Copyright (C) Jeremy Allison 2003.
+   Copyright (C) Jeremy Allison 2006
 
    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
@@ -182,13 +182,14 @@ BOOL idmap_proxyonly(void)
  set up for a sid to a POSIX id.
 **************************************************************************/
 
-NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
+NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, enum idmap_type id_type)
 {
        struct idmap_methods *map = remote_map;
        DOM_SID tmp_sid;
 
-       if (proxyonly)
+       if (proxyonly) {
                return NT_STATUS_UNSUCCESSFUL;
+       }
 
        if (sid_check_is_in_our_domain(sid)) {
                DEBUG(3, ("Refusing to add SID %s to idmap, it's our own "
@@ -204,14 +205,12 @@ NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
 
        DEBUG(10, ("idmap_set_mapping: Set %s to %s %lu\n",
                   sid_string_static(sid),
-                  ((id_type & ID_TYPEMASK) == ID_USERID) ? "UID" : "GID",
-                  ((id_type & ID_TYPEMASK) == ID_USERID) ? (unsigned long)id.uid : 
+                  (id_type == ID_USERID) ? "UID" : "GID",
+                  (id_type == ID_USERID) ? (unsigned long)id.uid : 
                   (unsigned long)id.gid));
 
-       if ( (NT_STATUS_IS_OK(cache_map->
-                             get_sid_from_id(&tmp_sid, id,
-                                             id_type | ID_QUERY_ONLY))) &&
-            sid_equal(sid, &tmp_sid) ) {
+       if ( (NT_STATUS_IS_OK(cache_map->get_sid_from_id(&tmp_sid, id, id_type, IDMAP_FLAG_QUERY_ONLY))) &&
+                               sid_equal(sid, &tmp_sid) ) {
                /* Nothing to do, we already have that mapping */
                DEBUG(10, ("idmap_set_mapping: Mapping already there\n"));
                return NT_STATUS_OK;
@@ -230,14 +229,14 @@ NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
  Get ID from SID. This can create a mapping for a SID to a POSIX id.
 **************************************************************************/
 
-NTSTATUS idmap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
+NTSTATUS idmap_get_id_from_sid(unid_t *id, enum idmap_type *id_type, const DOM_SID *sid, int flags)
 {
        NTSTATUS ret;
-       int loc_type;
-       unid_t loc_id;
+       int cache_flags = flags;
 
-       if (proxyonly)
+       if (proxyonly) {
                return NT_STATUS_UNSUCCESSFUL;
+       }
 
        if (sid_check_is_in_our_domain(sid)) {
                DEBUG(9, ("sid %s is in our domain -- go look in passdb\n",
@@ -251,55 +250,24 @@ NTSTATUS idmap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
                return NT_STATUS_NONE_MAPPED;
        }
 
-       loc_type = *id_type;
-
        if (remote_map) {
                /* We have a central remote idmap so only look in
-                   cache, don't allocate */
-               loc_type |= ID_QUERY_ONLY;
+                   cache, ensure we don't allocate */
+               cache_flags |= IDMAP_FLAG_QUERY_ONLY;
        }
 
-       ret = cache_map->get_id_from_sid(id, &loc_type, sid);
-
+       ret = cache_map->get_id_from_sid(id, id_type, sid, cache_flags);
        if (NT_STATUS_IS_OK(ret)) {
-               *id_type = loc_type & ID_TYPEMASK;
                return NT_STATUS_OK;
        }
 
-       if ((remote_map == NULL) || (loc_type & ID_CACHE_ONLY)) {
+       if ((remote_map == NULL) || (flags & IDMAP_FLAG_CACHE_ONLY)) {
                return ret;
        }
 
-       /* Before forking out to the possibly slow remote map, lets see if we
-        * already have the sid as uid when asking for a gid or vice versa. */
-
-       loc_type = *id_type & ID_TYPEMASK;
-
-       switch (loc_type) {
-       case ID_USERID:
-               loc_type = ID_GROUPID;
-               break;
-       case ID_GROUPID:
-               loc_type = ID_USERID;
-               break;
-       default:
-               loc_type = ID_EMPTY;
-       }
-
-       loc_type |= ID_QUERY_ONLY;
-
-       ret = cache_map->get_id_from_sid(&loc_id, &loc_type, sid);
-
-       if (NT_STATUS_IS_OK(ret)) {
-               /* Ok, we have the uid as gid or vice versa. The remote map
-                * would not know anything different, so return here. */
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       /* Ok, the mapping was not in the cache, give the remote map a
-           second try. */
+       /* Ok, the mapping was not in the cache, give the remote map a try. */
 
-       ret = remote_map->get_id_from_sid(id, id_type, sid);
+       ret = remote_map->get_id_from_sid(id, id_type, sid, flags);
        
        if (NT_STATUS_IS_OK(ret)) {
                /* The remote backend gave us a valid mapping, cache it. */
@@ -313,30 +281,34 @@ NTSTATUS idmap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
  Get SID from ID. This must have been created before.
 **************************************************************************/
 
-NTSTATUS idmap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
+NTSTATUS idmap_get_sid_from_id(DOM_SID *sid, unid_t id, enum idmap_type id_type, int flags)
 {
        NTSTATUS ret;
-       int loc_type;
+       int cache_flags = flags;
 
-       if (proxyonly)
+       if (proxyonly) {
                return NT_STATUS_UNSUCCESSFUL;
+       }
 
-       loc_type = id_type;
        if (remote_map) {
-               loc_type = id_type | ID_QUERY_ONLY;
+               /* We have a central remote idmap so only look in
+                   cache, ensure we don't allocate */
+               cache_flags |= IDMAP_FLAG_QUERY_ONLY;
        }
 
-       ret = cache_map->get_sid_from_id(sid, id, loc_type);
+       ret = cache_map->get_sid_from_id(sid, id, id_type, cache_flags);
 
-       if (NT_STATUS_IS_OK(ret))
+       if (NT_STATUS_IS_OK(ret)) {
                return ret;
+       }
 
-       if ((remote_map == NULL) || (loc_type & ID_CACHE_ONLY))
+       if ((remote_map == NULL) || (flags & IDMAP_FLAG_CACHE_ONLY)) {
                return ret;
+       }
 
-       /* We have a second chance, ask our authoritative backend */
+       /* Not in cache, ask our authoritative backend */
 
-       ret = remote_map->get_sid_from_id(sid, id, id_type);
+       ret = remote_map->get_sid_from_id(sid, id, id_type, flags);
 
        if (NT_STATUS_IS_OK(ret)) {
                /* The remote backend gave us a valid mapping, cache it. */
@@ -350,15 +322,17 @@ NTSTATUS idmap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
  Alloocate a new UNIX uid/gid
 **************************************************************************/
 
-NTSTATUS idmap_allocate_id(unid_t *id, int id_type)
+NTSTATUS idmap_allocate_id(unid_t *id, enum idmap_type id_type)
 {
        /* we have to allocate from the authoritative backend */
        
-       if (proxyonly)
+       if (proxyonly) {
                return NT_STATUS_UNSUCCESSFUL;
+       }
 
-       if ( remote_map )
+       if ( remote_map ) {
                return remote_map->allocate_id( id, id_type );
+       }
 
        return cache_map->allocate_id( id, id_type );
 }
@@ -371,8 +345,9 @@ NTSTATUS idmap_close(void)
 {
        NTSTATUS ret;
 
-       if (proxyonly)
+       if (proxyonly) {
                return NT_STATUS_OK;
+       }
 
        ret = cache_map->close_fn();
        if (!NT_STATUS_IS_OK(ret)) {
@@ -398,6 +373,7 @@ NTSTATUS idmap_close(void)
 void idmap_status(void)
 {
        cache_map->status();
-       if (remote_map)
+       if (remote_map) {
                remote_map->status();
+       }
 }
index 5edfad487d7d43130e31b191fc05ad7e4d880e74..f0adfa4028a3146ae8f98380de412bf63640770b 100644 (file)
@@ -139,7 +139,7 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
        return ads;
 }
 
-static NTSTATUS ad_idmap_init(char *uri)
+static NTSTATUS ad_idmap_init(const char *uri)
 {
        ad_idmap_uri = SMB_STRDUP(uri);
        if (ad_idmap_uri == NULL) {
@@ -149,7 +149,7 @@ static NTSTATUS ad_idmap_init(char *uri)
        return NT_STATUS_OK;
 }
 
-static NTSTATUS ad_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type)
+static NTSTATUS ad_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, enum idmap_type id_type, int flags)
 {
        ADS_STATUS rc;
        NTSTATUS status = NT_STATUS_NONE_MAPPED;
@@ -171,7 +171,7 @@ static NTSTATUS ad_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type)
                return NT_STATUS_NOT_SUPPORTED;
        }
 
-       switch (id_type & ID_TYPEMASK) {
+       switch (id_type) {
                case ID_USERID:
                        if (asprintf(&expr, "(&(|(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d))(%s=%d))",
                                ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
@@ -231,7 +231,7 @@ done:
        return status;
 }
 
-static NTSTATUS ad_idmap_get_id_from_sid(unid_t *unid, int *id_type, const DOM_SID *sid)
+static NTSTATUS ad_idmap_get_id_from_sid(unid_t *unid, enum idmap_type *id_type, const DOM_SID *sid, int flags)
 {
        ADS_STATUS rc;
        NTSTATUS status = NT_STATUS_NONE_MAPPED;
@@ -331,7 +331,7 @@ done:
 
 }
 
-static NTSTATUS ad_idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
+static NTSTATUS ad_idmap_set_mapping(const DOM_SID *sid, unid_t id, enum idmap_type id_type)
 {
        /* Not supported, and probably won't be... */
        /* (It's not particularly feasible with a single-master model.) */
@@ -356,7 +356,7 @@ static NTSTATUS ad_idmap_close(void)
        return NT_STATUS_OK;
 }
 
-static NTSTATUS ad_idmap_allocate_id(unid_t *id, int id_type)
+static NTSTATUS ad_idmap_allocate_id(unid_t *id, enum idmap_type id_type)
 {
        return NT_STATUS_NOT_IMPLEMENTED;
 }
@@ -378,7 +378,7 @@ static struct idmap_methods ad_methods = {
 
 
 /* support for new authentication subsystem */
-NTSTATUS init_module(void)
+NTSTATUS idmap_ad_init(void)
 {
        return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ad", &ad_methods);
 }
index 6169c89b3b9a9674ba87c953d62a2bd11888bbe4..3fec3a142be71b0c4d65bb62ce6e5eb5821cdbaa 100644 (file)
@@ -49,7 +49,7 @@ static struct ldap_idmap_state ldap_state;
  This function cannot be called to modify a mapping, only set a new one
 ***********************************************************************/
 
-static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
+static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, enum idmap_type id_type)
 {
        pstring dn;
        pstring id_str;
@@ -66,12 +66,13 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
        pstr_sprintf(dn, "%s=%s,%s", get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID),
                 sid_string, lp_ldap_idmap_suffix());
 
-       if ( id_type & ID_USERID )
+       if ( id_type == ID_USERID ) {
                fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ) );
-       else
+       } else {
                fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ) );
+       }
 
-       pstr_sprintf(id_str, "%lu", ((id_type & ID_USERID) ? (unsigned long)id.uid :
+       pstr_sprintf(id_str, "%lu", ((id_type == ID_USERID) ? (unsigned long)id.uid :
                                                 (unsigned long)id.gid));       
        
        smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDMAP_ENTRY );
@@ -117,7 +118,7 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
  Allocate a new uid or gid
 *****************************************************************************/
 
-static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
+static NTSTATUS ldap_allocate_id(unid_t *id, enum idmap_type id_type)
 {
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
        int rc = LDAP_SERVER_DOWN;
@@ -133,8 +134,11 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
        uid_t   luid, huid;
        gid_t   lgid, hgid;
 
+       if (id_type != ID_USERID && id_type != ID_GROUPID) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       type = (id_type & ID_USERID) ?
+       type = (id_type == ID_USERID) ?
                get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ) : 
                get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER );
 
@@ -177,15 +181,14 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
        
        /* make sure we still have room to grow */
        
-       if (id_type & ID_USERID) {
+       if (id_type == ID_USERID) {
                id->uid = strtoul(id_str, NULL, 10);
                if (id->uid > huid ) {
                        DEBUG(0,("ldap_allocate_id: Cannot allocate uid above %lu!\n", 
                                 (unsigned long)huid));
                        goto out;
                }
-       }
-       else { 
+       } else { 
                id->gid = strtoul(id_str, NULL, 10);
                if (id->gid > hgid ) {
                        DEBUG(0,("ldap_allocate_id: Cannot allocate gid above %lu!\n", 
@@ -195,7 +198,7 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
        }
        
        pstr_sprintf(new_id_str, "%lu", 
-                ((id_type & ID_USERID) ? (unsigned long)id->uid : 
+                ((id_type == ID_USERID) ? (unsigned long)id->uid : 
                  (unsigned long)id->gid) + 1);
                 
        smbldap_set_mod( &mods, LDAP_MOD_DELETE, type, id_str );                 
@@ -228,7 +231,7 @@ out:
  get a sid from an id
 *****************************************************************************/
 
-static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
+static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, enum idmap_type id_type, int flags)
 {
        LDAPMessage *result = NULL;
        LDAPMessage *entry = NULL;
@@ -241,7 +244,7 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
        const char **attr_list;
 
-       if ( id_type & ID_USERID ) 
+       if ( id_type == ID_USERID ) 
                type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER );
        else 
                type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER );
@@ -289,10 +292,12 @@ out:
 }
 
 /***********************************************************************
- Get an id from a sid 
+ Get an id from a sid - urg. This is assuming the *output* parameter id_type
+ has been initialized with the correct needed type - ID_USERID or ID_GROUPID.
+ This *sucks* and is bad design and needs fixing. JRA.
 ***********************************************************************/
 
-static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
+static NTSTATUS ldap_get_id_from_sid(unid_t *id, enum idmap_type *id_type, const DOM_SID *sid, int flags)
 {
        LDAPMessage *result = NULL;
        LDAPMessage *entry = NULL;
@@ -316,7 +321,7 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si
        pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", 
                LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, sid_str);
                        
-       if ( *id_type & ID_GROUPID ) 
+       if ( *id_type == ID_GROUPID ) 
                type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER );
        else 
                type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER );
@@ -348,7 +353,7 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si
        if ( !count ) {
                int i;
 
-               if (*id_type & ID_QUERY_ONLY) {
+               if (flags & IDMAP_FLAG_QUERY_ONLY) {
                        DEBUG(5,("ldap_get_id_from_sid: No matching entry found and QUERY_ONLY flag set\n"));
                        goto out;
                }
@@ -387,7 +392,7 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si
        DEBUG(10, ("Found mapping entry at dn=%s, looking for %s\n", dn, type));
                
        if ( smbldap_get_single_pstring(ldap_state.smbldap_state->ldap_struct, entry, type, id_str) ) {
-               if ( (*id_type & ID_USERID) )
+               if ( (*id_type == ID_USERID) )
                        id->uid = strtoul(id_str, NULL, 10);
                else
                        id->gid = strtoul(id_str, NULL, 10);
@@ -470,7 +475,7 @@ static NTSTATUS verify_idpool( void )
  Initialise idmap database. 
 *****************************************************************************/
 
-static NTSTATUS ldap_idmap_init( char *params )
+static NTSTATUS ldap_idmap_init( const char *params )
 {
        NTSTATUS nt_status;
 
index 58838512a6824a974b4db029569ba59edeb777f8..23496d696922e12934211b50219dd9236450542c 100644 (file)
@@ -334,7 +334,7 @@ out:
        return status;
 }
 
-static NTSTATUS rid_idmap_init(char *init_param)
+static NTSTATUS rid_idmap_init(const char *init_param)
 {
        int i, j;
        uid_t u_low, u_high;
@@ -432,7 +432,8 @@ out:
        return nt_status;
 }
 
-static NTSTATUS rid_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type)
+static NTSTATUS rid_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, enum idmap_type id_type, int flags)
+
 {
        fstring sid_string;
        int i;
@@ -469,7 +470,7 @@ static NTSTATUS rid_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type
        return NT_STATUS_OK;
 }
 
-static NTSTATUS rid_idmap_get_id_from_sid(unid_t *unid, int *id_type, const DOM_SID *sid)
+static NTSTATUS rid_idmap_get_id_from_sid(unid_t *unid, enum idmap_type *id_type, const DOM_SID *sid, int flags)
 {
        fstring sid_string;
        int i;
@@ -521,7 +522,7 @@ static NTSTATUS rid_idmap_get_id_from_sid(unid_t *unid, int *id_type, const DOM_
 
 }
 
-static NTSTATUS rid_idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
+static NTSTATUS rid_idmap_set_mapping(const DOM_SID *sid, unid_t id, enum idmap_type id_type)
 {
        return NT_STATUS_NOT_IMPLEMENTED;
 }
@@ -533,7 +534,7 @@ static NTSTATUS rid_idmap_close(void)
        return NT_STATUS_OK;
 }
 
-static NTSTATUS rid_idmap_allocate_id(unid_t *id, int id_type)
+static NTSTATUS rid_idmap_allocate_id(unid_t *id, enum idmap_type id_type)
 {
        return NT_STATUS_NOT_IMPLEMENTED;
 }
@@ -553,7 +554,7 @@ static struct idmap_methods rid_methods = {
        rid_idmap_status
 };
 
-NTSTATUS init_module(void)
+NTSTATUS idmap_rid_init(void)
 {
        return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "rid", &rid_methods);
 }
index 4d80364437cb000bb6eabaad28c01d987cdd3f4b..9850921fa3915b535a805cd8a541ebaa56e11970 100644 (file)
@@ -90,7 +90,7 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
  Allocate a new uid or gid
 *****************************************************************************/
 
-static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
+static NTSTATUS ldap_allocate_id(unid_t *id, enum idmap_type id_type)
 {
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
        uid_t   luid, huid;
@@ -104,7 +104,11 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
        const char *id_attrib;
        char *mod;
 
-       id_attrib = (id_type & ID_USERID) ? "uidNumber" : "gidNumber";
+       if (id_type != ID_USERID && id_type != ID_GROUPID) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       id_attrib = (id_type == ID_USERID) ? "uidNumber" : "gidNumber";
 
        idpool_s = new_ldap_search_message(lp_ldap_suffix(),
                                           LDAP_SEARCH_SCOPE_SUB,
@@ -129,7 +133,7 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
        
        /* make sure we still have room to grow */
        
-       if (id_type & ID_USERID) {
+       if (id_type == ID_USERID) {
                id->uid = value;
                if (id->uid > huid ) {
                        DEBUG(0,("ldap_allocate_id: Cannot allocate uid "
index 665c56d2f679523f7d76dbb249f287d5e256908c..02a3178d61a9281f3f02ecde51993870b541e84f 100644 (file)
@@ -6,6 +6,7 @@
    Copyright (C) Tim Potter 2000
    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
    Copyright (C) Simo Sorce 2003
+   Copyright (C) Jeremy Allison 2006
    
    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
@@ -46,16 +47,13 @@ static struct idmap_state {
  Allocate either a user or group id from the pool 
 **********************************************************************/
  
-static NTSTATUS db_allocate_id(unid_t *id, int id_type)
+static NTSTATUS db_allocate_id(unid_t *id, enum idmap_type id_type)
 {
        BOOL ret;
        int hwm;
 
-       if (!id)
-               return NT_STATUS_INVALID_PARAMETER;
-
        /* Get current high water mark */
-       switch (id_type & ID_TYPEMASK) {
+       switch (id_type) {
                case ID_USERID:
 
                        if ((hwm = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) {
@@ -125,274 +123,327 @@ static NTSTATUS db_allocate_id(unid_t *id, int id_type)
        return NT_STATUS_OK;
 }
 
-/* Get a sid from an id */
-static NTSTATUS internal_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
+/* Get a sid from an id - internal non-reverse map checking function. */
+
+static NTSTATUS db_internal_get_sid_from_id(DOM_SID *sid, unid_t id, enum idmap_type id_type)
 {
        TDB_DATA key, data;
-       fstring keystr;
+       TALLOC_CTX *memctx;
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
 
-       if (!sid)
-               return NT_STATUS_INVALID_PARAMETER;
+       if ((memctx = talloc_new(NULL)) == NULL) {
+               DEBUG(0, ("ERROR: Out of memory!\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       switch (id_type & ID_TYPEMASK) {
+       switch (id_type) {
                case ID_USERID:
-                       slprintf(keystr, sizeof(keystr), "UID %lu", (unsigned long)id.uid);
+                       key.dptr = talloc_asprintf(memctx, "UID %lu", (unsigned long)id.uid);
                        break;
                case ID_GROUPID:
-                       slprintf(keystr, sizeof(keystr), "GID %lu", (unsigned long)id.gid);
+                       key.dptr = talloc_asprintf(memctx, "GID %lu", (unsigned long)id.gid);
                        break;
                default:
-                       return NT_STATUS_UNSUCCESSFUL;
+                       ret = NT_STATUS_INVALID_PARAMETER;
+                       goto done;
+       }
+
+       if (key.dptr == NULL) {
+               DEBUG(0, ("ERROR: Out of memory!\n"));
+               ret = NT_STATUS_NO_MEMORY;
+               goto done;
        }
 
-       key.dptr = keystr;
-       key.dsize = strlen(keystr) + 1;
+       key.dsize = strlen(key.dptr) + 1;
 
-       DEBUG(10,("internal_get_sid_from_id: fetching record %s\n", keystr ));
+       DEBUG(10,("db_internal_get_sid_from_id: fetching record %s\n", key.dptr));
 
        data = tdb_fetch(idmap_tdb, key);
 
        if (data.dptr) {
                if (string_to_sid(sid, data.dptr)) {
-                       DEBUG(10,("internal_get_sid_from_id: fetching record %s -> %s\n", keystr, data.dptr ));
+                       DEBUG(10,("db_internal_get_sid_from_id: fetching record %s -> %s\n", key.dptr, data.dptr ));
                        ret = NT_STATUS_OK;
                }
                SAFE_FREE(data.dptr);
        }
 
+done:
+       talloc_free(memctx);
        return ret;
 }
 
-/* Error codes for get_id_from_sid */
-enum getidfromsiderr { GET_ID_FROM_SID_OK = 0, GET_ID_FROM_SID_NOTFOUND, GET_ID_FROM_SID_WRONG_TYPE, GET_ID_FROM_SID_ERR };
+/* Get an id from a sid - internal non-reverse map checking function. */
 
-static enum getidfromsiderr internal_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) 
+static NTSTATUS db_internal_get_id_from_sid(unid_t *id, enum idmap_type *id_type, const DOM_SID *sid)
 {
-       enum getidfromsiderr ret = GET_ID_FROM_SID_ERR;
-       fstring keystr;
+       NTSTATUS ret;
        TDB_DATA key, data;
-       int type = *id_type & ID_TYPEMASK;
+       TALLOC_CTX *memctx;
+       unsigned long rec_id;
+
+       if ((memctx = talloc_new(NULL)) == NULL) {
+               DEBUG(0, ("ERROR: Out of memory!\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
 
        /* Check if sid is present in database */
-       sid_to_string(keystr, sid);
+       if ((key.dptr = talloc_asprintf(memctx, "%s", sid_string_static(sid))) == NULL) {
+               DEBUG(0, ("ERROR: Out of memory!\n"));
+               ret = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
 
-       key.dptr = keystr;
-       key.dsize = strlen(keystr) + 1;
+       key.dsize = strlen(key.dptr) + 1;
 
-       DEBUG(10,("internal_get_id_from_sid: fetching record %s of type 0x%x\n", keystr, type ));
+       DEBUG(10,("db_internal_get_id_from_sid: fetching record %s\n", key.dptr));
 
        data = tdb_fetch(idmap_tdb, key);
        if (!data.dptr) {
-               DEBUG(10,("internal_get_id_from_sid: record %s not found\n", keystr ));
-               return GET_ID_FROM_SID_NOTFOUND;
+               DEBUG(10,("db_internal_get_id_from_sid: record %s not found\n", key.dptr));
+               ret = NT_STATUS_NO_SUCH_USER;
+               goto done;
        } else {
-               DEBUG(10,("internal_get_id_from_sid: record %s -> %s\n", keystr, data.dptr ));
+               DEBUG(10,("db_internal_get_id_from_sid: record %s -> %s\n", key.dptr, data.dptr));
        }
 
-       if (type == ID_EMPTY || type == ID_USERID) {
-               fstring scanstr;
-               /* Parse and return existing uid */
-               fstrcpy(scanstr, "UID %d");
-               
-               if (sscanf(data.dptr, scanstr, &((*id).uid)) == 1) {
-                       /* uid ok? */
-                       if (type == ID_EMPTY) {
-                               *id_type = ID_USERID;
-                       }
-                       DEBUG(10,("internal_get_id_from_sid: %s fetching record %s -> %s \n",
-                                               (type == ID_EMPTY) ? "ID_EMPTY" : "ID_USERID",
-                                               keystr, data.dptr ));
-                       ret = GET_ID_FROM_SID_OK;
-               } else {
-                       ret = GET_ID_FROM_SID_WRONG_TYPE;
-               }
-       }
-       
-       if ((ret != GET_ID_FROM_SID_OK) && (type == ID_EMPTY || type == ID_GROUPID)) {
-               fstring scanstr;
-               /* Parse and return existing gid */
-               fstrcpy(scanstr, "GID %d");
-               
-               if (sscanf(data.dptr, scanstr, &((*id).gid)) == 1) {
-                       /* gid ok? */
-                       if (type == ID_EMPTY) {
-                               *id_type = ID_GROUPID;
-                       }
-                       DEBUG(10,("internal_get_id_from_sid: %s fetching record %s -> %s \n",
-                                               (type == ID_EMPTY) ? "ID_EMPTY" : "ID_GROUPID",
-                                               keystr, data.dptr ));
-                       ret = GET_ID_FROM_SID_OK;
-               } else {
-                       ret = GET_ID_FROM_SID_WRONG_TYPE;
-               }
+       /* What type of record is this ? */
+
+       /* Try and parse and return a uid */
+       if (sscanf(data.dptr, "UID %lu", &rec_id) == 1) {
+               id->uid = (uid_t)rec_id;
+               *id_type = ID_USERID;
+               DEBUG(10,("db_internal_get_id_from_sid: fetching uid record %s -> %s \n",
+                                               key.dptr, data.dptr ));
+               ret = NT_STATUS_OK;
+       } else if (sscanf(data.dptr, "GID %lu", &rec_id) == 1) { /* Try a GID record. */
+               id->gid = (uid_t)rec_id;
+               *id_type = ID_GROUPID;
+               DEBUG(10,("db_internal_get_id_from_sid: fetching gid record %s -> %s \n",
+                                               key.dptr, data.dptr ));
+               ret = NT_STATUS_OK;
+       } else {
+               /* Unknown record type ! */
+               ret = NT_STATUS_INTERNAL_DB_ERROR;
        }
        
        SAFE_FREE(data.dptr);
 
+done:
+       talloc_free(memctx);
        return ret;
 }
 
-/* Get a sid from an id */
-static NTSTATUS db_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type_in)
+/* Get a sid from an id - internal non-reverse map checking function. */
+
+static NTSTATUS db_get_sid_from_id(DOM_SID *sid, unid_t id, enum idmap_type id_type, int flags)
 {
-       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       enum getidfromsiderr iderr;
-       int id_type = id_type_in & ID_TYPEMASK;
-       unid_t id_tmp = id;
-       int id_type_tmp = id_type;
+       NTSTATUS ret;
+       unid_t tmp_id;
+       enum idmap_type tmp_id_type;
 
-       DEBUG(10,("db_get_sid_from_id: id_type_in = 0x%x\n", id_type_in));
+       ret = db_internal_get_sid_from_id(sid, id, id_type);
 
-       ret = internal_get_sid_from_id(sid, id, id_type);
        if (!NT_STATUS_IS_OK(ret)) {
                return ret;
        }
-       
-       iderr = internal_get_id_from_sid(&id_tmp, &id_type_tmp, sid);
-       if (iderr != GET_ID_FROM_SID_OK) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-       if (id_type_tmp != id_type) {
-               return NT_STATUS_UNSUCCESSFUL;
-       } else if (id_type == ID_USERID) { 
-               if (id_tmp.uid != id.uid) {
-                       return NT_STATUS_UNSUCCESSFUL;
-               }
-       } else if (id_type == ID_GROUPID) {
-               if (id_tmp.gid != id.gid) {
-                       return NT_STATUS_UNSUCCESSFUL;
+
+       /* Ensure the reverse mapping exists. */
+
+       ret = db_internal_get_id_from_sid(&tmp_id, &tmp_id_type, sid);
+       if (NT_STATUS_IS_OK(ret)) {
+               /* Check the reverse mapping is the same. */
+               if (tmp_id.uid != id.uid || tmp_id_type != id_type) {
+                       DEBUG(10,("db_get_sid_from_id: reverse mapping mismatch "
+                               "tmp_id = %u, id = %u, tmp_id_type = %u, id_type = %u\n",
+                                       (unsigned int)tmp_id.uid, (unsigned int)id.uid,
+                                       (unsigned int)tmp_id_type, (unsigned int)id_type ));
+                       return NT_STATUS_NO_SUCH_USER;
                }
-       } else {
-               return NT_STATUS_UNSUCCESSFUL;
        }
+
        return ret;
 }
-/* Get an id from a sid */
-static NTSTATUS db_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
+
+/***********************************************************************
+ Why is this function internal and not part of the interface ?????
+ This *sucks* and is bad design and needs fixing. JRA.
+***********************************************************************/
+
+static NTSTATUS db_internal_allocate_new_id_for_sid(unid_t *id, enum idmap_type *id_type, const DOM_SID *sid)
 {
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       enum getidfromsiderr iderr;
+       TDB_DATA sid_data;
+       TDB_DATA ugid_data;
+       TALLOC_CTX *memctx;
+
+       if ((memctx = talloc_new(NULL)) == NULL) {
+               DEBUG(0, ("ERROR: Out of memory!\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       DEBUG(10,("db_get_id_from_sid\n"));
+       if ((sid_data.dptr = talloc_asprintf(memctx, "%s", sid_string_static(sid))) == NULL) {
+               DEBUG(0, ("ERROR: Out of memory!\n"));
+               talloc_free(memctx);
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       if (!sid || !id || !id_type)
-               return NT_STATUS_INVALID_PARAMETER;
+       sid_data.dsize = strlen(sid_data.dptr) + 1;
 
-       iderr = internal_get_id_from_sid(id, id_type, sid);
-       if (iderr == GET_ID_FROM_SID_OK) {
-               DOM_SID sid_tmp;
-               ret = internal_get_sid_from_id(&sid_tmp, *id, *id_type);
-               if (NT_STATUS_IS_OK(ret)) {
-                       if (!sid_equal(&sid_tmp, sid)) {
-                               return NT_STATUS_UNSUCCESSFUL;
-                       }
-               }
-       } else if (iderr == GET_ID_FROM_SID_WRONG_TYPE) {
-               /* We found a record but not the type we wanted.
-                * This is an error, not an opportunity to overwrite...
-                * JRA.
-                */
+       /* Lock the record for this SID. */
+       if (tdb_chainlock(idmap_tdb, sid_data) != 0) {
+               DEBUG(10,("db_internal_allocate_new_id_for_sid: failed to lock record %s. Error %s\n",
+                               sid_data.dptr, tdb_errorstr(idmap_tdb) ));
+               talloc_free(memctx);
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       if (!(*id_type & ID_QUERY_ONLY) && (iderr != GET_ID_FROM_SID_OK) &&
-                  (((*id_type & ID_TYPEMASK) == ID_USERID)
-                   || (*id_type & ID_TYPEMASK) == ID_GROUPID)) {
-               TDB_DATA sid_data;
-               TDB_DATA ugid_data;
-               fstring sid_string;
-               
-               sid_to_string(sid_string, sid);
-               
-               sid_data.dptr = sid_string;
-               sid_data.dsize = strlen(sid_string)+1;
-
-               /* Lock the record for this SID. */
-               if (tdb_chainlock(idmap_tdb, sid_data) != 0) {
-                       DEBUG(10,("db_get_id_from_sid: failed to lock record %s. Error %s\n",
-                                       sid_string, tdb_errorstr(idmap_tdb) ));
-                       return NT_STATUS_UNSUCCESSFUL;
+       do {
+               /* Allocate a new id for this sid */
+               ret = db_allocate_id(id, *id_type);
+               if (!NT_STATUS_IS_OK(ret)) {
+                       goto done;
+               }
+                       
+               /* Store the UID side */
+               /* Store new id */
+               if (*id_type == ID_USERID) {
+                       ugid_data.dptr = talloc_asprintf(memctx, "UID %lu",
+                                                       (unsigned long)((*id).uid));
+               } else {
+                       ugid_data.dptr = talloc_asprintf(memctx, "GID %lu",
+                                                       (unsigned long)((*id).gid));
                }
 
-               do {
-                       fstring ugid_str;
+               if (ugid_data.dptr == NULL) {
+                       DEBUG(0, ("ERROR: Out of memory!\n"));
+                       ret = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
 
-                       /* Allocate a new id for this sid */
-                       ret = db_allocate_id(id, *id_type);
-                       if (!NT_STATUS_IS_OK(ret))
-                               break;
+               ugid_data.dsize = strlen(ugid_data.dptr) + 1;
                        
-                       /* Store the UID side */
-                       /* Store new id */
-                       if (*id_type & ID_USERID) {
-                               slprintf(ugid_str, sizeof(ugid_str), "UID %lu", 
-                                        (unsigned long)((*id).uid));
-                       } else {
-                               slprintf(ugid_str, sizeof(ugid_str), "GID %lu", 
-                                        (unsigned long)((*id).gid));
-                       }
-                       
-                       ugid_data.dptr = ugid_str;
-                       ugid_data.dsize = strlen(ugid_str) + 1;
+               DEBUG(10,("db_internal_allocate_new_id_for_sid: storing %s -> %s\n",
+                               ugid_data.dptr, sid_data.dptr ));
 
-                       DEBUG(10,("db_get_id_from_sid: storing %s -> %s\n",
-                                       ugid_data.dptr, sid_data.dptr ));
+               if (tdb_store(idmap_tdb, ugid_data, sid_data, TDB_INSERT) != -1) {
+                       ret = NT_STATUS_OK;
+                       break;
+               }
+               if (tdb_error(idmap_tdb) != TDB_ERR_EXISTS) {
+                       DEBUG(10,("db_internal_allocate_new_id_for_sid: error %s\n", tdb_errorstr(idmap_tdb)));
+               }
+                               
+               ret = NT_STATUS_INTERNAL_DB_ERROR;
 
-                       if (tdb_store(idmap_tdb, ugid_data, sid_data, TDB_INSERT) != -1) {
-                               ret = NT_STATUS_OK;
-                               break;
-                       }
-                       if (tdb_error(idmap_tdb) != TDB_ERR_EXISTS)
-                               DEBUG(10,("db_get_id_from_sid: error %s\n", tdb_errorstr(idmap_tdb) ));
-                       ret = NT_STATUS_UNSUCCESSFUL;
-               } while (tdb_error(idmap_tdb) == TDB_ERR_EXISTS);
+       } while (tdb_error(idmap_tdb) == TDB_ERR_EXISTS);
 
-               if (NT_STATUS_IS_OK(ret)) {
+       if (NT_STATUS_IS_OK(ret)) {
+               DEBUG(10,("db_internal_allocate_new_id_for_sid: storing %s -> %s\n",
+                       sid_data.dptr, ugid_data.dptr ));
 
-                       DEBUG(10,("db_get_id_from_sid: storing %s -> %s\n",
-                               sid_data.dptr, ugid_data.dptr ));
+               if (tdb_store(idmap_tdb, sid_data, ugid_data, TDB_REPLACE) == -1) {
+                       DEBUG(10,("db_internal_allocate_new_id_for_sid: error %s\n", tdb_errorstr(idmap_tdb) ));
+                       ret = NT_STATUS_INTERNAL_DB_ERROR;
+               }
+       }
 
-                       if (tdb_store(idmap_tdb, sid_data, ugid_data, TDB_REPLACE) == -1) {
-                               DEBUG(10,("db_get_id_from_sid: error %s\n", tdb_errorstr(idmap_tdb) ));
-                               /* TODO: print tdb error !! */
-                               tdb_chainunlock(idmap_tdb, sid_data);
-                               return NT_STATUS_UNSUCCESSFUL;
+  done:
+
+       tdb_chainunlock(idmap_tdb, sid_data);
+       talloc_free(memctx);
+
+       return ret;
+}
+
+/***********************************************************************
+ Get an id from a sid - urg. This is assuming the *output* parameter id_type
+ has been initialized with the correct needed type - ID_USERID or ID_GROUPID.
+ This function also allocates new mappings ! WTF ??????
+ This *sucks* and is bad design and needs fixing. JRA.
+***********************************************************************/
+
+static NTSTATUS db_get_id_from_sid(unid_t *id, enum idmap_type *id_type, const DOM_SID *sid, int flags)
+{
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+       enum idmap_type tmp_id_type = *id_type;
+
+       DEBUG(10,("db_get_id_from_sid %s\n", sid_string_static(sid)));
+
+       ret = db_internal_get_id_from_sid(id, &tmp_id_type, sid);
+
+       if (NT_STATUS_IS_OK(ret)) {
+               DOM_SID sid_tmp;
+
+               /* Check the reverse mapping is the same. Remember *id_type was set as a parameter
+                  to this call... */
+               if (tmp_id_type != *id_type) {
+                       DEBUG(10,("db_get_sid_from_id: sid %s reverse mapping mismatch "
+                               "tmp_id_type = %u, id_type = %u\n",
+                                       sid_string_static(sid),
+                                       (unsigned int)tmp_id_type, (unsigned int)(*id_type) ));
+                       return NT_STATUS_NO_SUCH_USER;
+               }
+
+               ret = db_internal_get_sid_from_id(&sid_tmp, *id, *id_type);
+               if (NT_STATUS_IS_OK(ret)) {
+                       if (!sid_equal(&sid_tmp, sid)) {
+                               DEBUG(10,("db_get_sid_from_id: sid %s reverse mapping SID mismatch"
+                                       "id = %u, id_type = %u\n",
+                                               sid_string_static(sid),
+                                               (unsigned int)id->uid, (unsigned int)(*id_type) ));
+                               return NT_STATUS_NO_SUCH_USER;
                        }
                }
+               return ret;
+       }
 
-               tdb_chainunlock(idmap_tdb, sid_data);
+       if (flags & IDMAP_FLAG_QUERY_ONLY) {
+               return ret;
        }
-       
-       return ret;
+
+       /* We're in to bad design territory.... This call is now
+          *allocating* and storing a new mapping for sid -> id. This SHOULD
+          NOT BE DONE HERE ! There needs to be a separate upper
+          level call for this... I think the reason this was badly
+          designed this way was the desire to reuse cache code with
+          a tdb idmap implementation. They MUST be separated ! JRA */
+
+       return db_internal_allocate_new_id_for_sid(id, id_type, sid);
 }
 
-static NTSTATUS db_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
+static NTSTATUS db_set_mapping(const DOM_SID *sid, unid_t id, enum idmap_type id_type)
 {
+       NTSTATUS ret;
        TDB_DATA ksid, kid, data;
-       fstring ksidstr;
-       fstring kidstr;
+       TALLOC_CTX *memctx;
 
-       DEBUG(10,("db_set_mapping: id_type = 0x%x\n", id_type));
+       DEBUG(10,("db_set_mapping: id_type = 0x%x\n", (unsigned int)id_type));
 
-       if (!sid)
-               return NT_STATUS_INVALID_PARAMETER;
-
-       sid_to_string(ksidstr, sid);
+       if ((memctx = talloc_new(NULL)) == NULL) {
+               DEBUG(0, ("ERROR: Out of memory!\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       ksid.dptr = ksidstr;
-       ksid.dsize = strlen(ksidstr) + 1;
+       if ((ksid.dptr = talloc_asprintf(memctx, "%s", sid_string_static(sid))) == NULL) {
+               DEBUG(0, ("ERROR: Out of memory!\n"));
+               ret = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+       ksid.dsize = strlen(ksid.dptr) + 1;
 
-       if (id_type & ID_USERID) {
-               slprintf(kidstr, sizeof(kidstr), "UID %lu", (unsigned long)id.uid);
-       } else if (id_type & ID_GROUPID) {
-               slprintf(kidstr, sizeof(kidstr), "GID %lu", (unsigned long)id.gid);
+       if (id_type == ID_USERID) {
+               kid.dptr = talloc_asprintf(memctx, "UID %lu", (unsigned long)id.uid);
        } else {
-               return NT_STATUS_INVALID_PARAMETER;
+               kid.dptr = talloc_asprintf(memctx, "GID %lu", (unsigned long)id.gid);
        }
 
-       kid.dptr = kidstr;
-       kid.dsize = strlen(kidstr) + 1;
+       if (kid.dptr == NULL) {
+               DEBUG(0, ("ERROR: Out of memory!\n"));
+               ret = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+       kid.dsize = strlen(kid.dptr) + 1;
 
        /* *DELETE* prevoius mappings if any.
         * This is done both SID and [U|G]ID passed in */
@@ -400,7 +451,7 @@ static NTSTATUS db_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
        /* Lock the record for this SID. */
        if (tdb_chainlock(idmap_tdb, ksid) != 0) {
                DEBUG(10,("db_set_mapping: failed to lock record %s. Error %s\n",
-                               ksidstr, tdb_errorstr(idmap_tdb) ));
+                               ksid.dptr, tdb_errorstr(idmap_tdb) ));
                return NT_STATUS_UNSUCCESSFUL;
        }
 
@@ -424,24 +475,29 @@ static NTSTATUS db_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
        if (tdb_store(idmap_tdb, ksid, kid, TDB_INSERT) == -1) {
                DEBUG(0, ("idb_set_mapping: tdb_store 1 error: %s\n", tdb_errorstr(idmap_tdb)));
                tdb_chainunlock(idmap_tdb, ksid);
-               return NT_STATUS_UNSUCCESSFUL;
+               ret = NT_STATUS_UNSUCCESSFUL;
+               goto done;
        }
        if (tdb_store(idmap_tdb, kid, ksid, TDB_INSERT) == -1) {
                DEBUG(0, ("idb_set_mapping: tdb_store 2 error: %s\n", tdb_errorstr(idmap_tdb)));
                tdb_chainunlock(idmap_tdb, ksid);
-               return NT_STATUS_UNSUCCESSFUL;
+               ret = NT_STATUS_UNSUCCESSFUL;
+               goto done;
        }
 
        tdb_chainunlock(idmap_tdb, ksid);
        DEBUG(10,("db_set_mapping: stored %s -> %s and %s -> %s\n", ksid.dptr, kid.dptr, kid.dptr, ksid.dptr ));
-       return NT_STATUS_OK;
+       ret = NT_STATUS_OK;
+done:
+       talloc_free(memctx);
+       return ret;
 }
 
 /*****************************************************************************
  Initialise idmap database. 
 *****************************************************************************/
 
-static NTSTATUS db_idmap_init( char *params )
+static NTSTATUS db_idmap_init( const char *params )
 {
        SMB_STRUCT_STAT stbuf;
        char *tdbfile = NULL;
index f78d3bdc2337b969c9969d740a729966970010b5..8320b294f8fdb4bd9f12dc63eb64d1111330cabe 100644 (file)
@@ -2,6 +2,7 @@
    Unix SMB/CIFS implementation.
    ID Mapping
    Copyright (C) Simo Sorce 2003
+   Copyright (C) Jeremy Allison 2006
 
    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
@@ -32,10 +33,9 @@ NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid, int flags)
 
        DEBUG(10,("idmap_uid_to_sid: uid = [%lu]\n", (unsigned long)uid));
 
-       flags |= ID_USERID;
        id.uid = uid;
        
-       return idmap_get_sid_from_id(sid, id, flags);
+       return idmap_get_sid_from_id(sid, id, ID_USERID, flags);
 }
 
 /*****************************************************************
@@ -49,10 +49,9 @@ NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid, int flags)
 
        DEBUG(10,("idmap_gid_to_sid: gid = [%lu]\n", (unsigned long)gid));
 
-       flags |= ID_GROUPID;
        id.gid = gid;
 
-       return idmap_get_sid_from_id(sid, id, flags);
+       return idmap_get_sid_from_id(sid, id, ID_GROUPID, flags);
 }
 
 /*****************************************************************
@@ -62,24 +61,32 @@ NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid, int flags)
  was done correctly, False if not.
 *****************************************************************/  
 
-NTSTATUS idmap_sid_to_uid(const DOM_SID *sid, uid_t *uid, uint32 flags)
+NTSTATUS idmap_sid_to_uid(const DOM_SID *sid, uid_t *uid, int flags)
 {
-       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+       NTSTATUS ret;
+       enum idmap_type id_type;
        unid_t id;
 
        DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_static(sid)));
 
-       flags |= ID_USERID;
+       /* For the LDAP and tdb backends we must *KNOW* what we're looking for.
+          This interface design *SUCKS* ! JRA. */
 
-       ret = idmap_get_id_from_sid(&id, (int *)&flags, sid);
-       
-       if ( NT_STATUS_IS_OK(ret) ) {
-               DEBUG(10,("idmap_sid_to_uid: uid = [%lu]\n", (unsigned long)id.uid));
-               *uid = id.uid;
-       } 
+       id_type = ID_USERID;
+       ret = idmap_get_id_from_sid(&id, &id_type, sid, flags);
+
+       if (!NT_STATUS_IS_OK(ret)) {
+               return ret;
+       }
+
+       if (id_type != ID_USERID) {
+               return NT_STATUS_NONE_MAPPED;
+       }
 
-       return ret;
+       DEBUG(10,("idmap_sid_to_uid: uid = [%lu]\n", (unsigned long)id.uid));
+       *uid = id.uid;
 
+       return NT_STATUS_OK;
 }
 
 /*****************************************************************
@@ -91,22 +98,30 @@ NTSTATUS idmap_sid_to_uid(const DOM_SID *sid, uid_t *uid, uint32 flags)
  was done correctly, False if not.
 *****************************************************************/  
 
-NTSTATUS idmap_sid_to_gid(const DOM_SID *sid, gid_t *gid, uint32 flags)
+NTSTATUS idmap_sid_to_gid(const DOM_SID *sid, gid_t *gid, int flags)
 {
-       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+       NTSTATUS ret;
+       enum idmap_type id_type;
        unid_t id;
 
        DEBUG(10,("sid_to_gid: sid = [%s]\n", sid_string_static(sid)));
 
-       flags |= ID_GROUPID;
+       /* For the LDAP and tdb backends we must *KNOW* what we're looking for.
+          This interface design *SUCKS* ! JRA. */
 
-       ret = idmap_get_id_from_sid(&id, (int *)&flags, sid);
+       id_type = ID_GROUPID;
+       ret = idmap_get_id_from_sid(&id, &id_type, sid, flags);
        
-       if ( NT_STATUS_IS_OK(ret) ) 
-       {
-               DEBUG(10,("idmap_sid_to_gid: gid = [%lu]\n", (unsigned long)id.gid));
-               *gid = id.gid;
+       if (!NT_STATUS_IS_OK(ret)) {
+               return ret;
+       }
+
+       if (id_type != ID_GROUPID) {
+               return NT_STATUS_NONE_MAPPED;
        }
 
-       return ret;
+       DEBUG(10,("idmap_sid_to_gid: gid = [%lu]\n", (unsigned long)id.gid));
+       *gid = id.gid;
+
+       return NT_STATUS_OK;
 }
index a0f3096c84207db4fc15241fe791c17172cbc991..30b5628b33635d3f02ab57357b22b93758368485 100644 (file)
@@ -48,6 +48,11 @@ END {
   printf "BOOL %s(int );\n", a[2]
 }
 
+/^FN_LOCAL_PARM_BOOL/ {
+  split($0,a,"[,()]")
+  printf "BOOL %s(const struct share_params *p );\n", a[2]
+}
+
 /^FN_LOCAL_LIST/ {
   split($0,a,"[,()]")
   printf "const char **%s(int );\n", a[2]
@@ -58,6 +63,11 @@ END {
   printf "char *%s(int );\n", a[2]
 }
 
+/^FN_LOCAL_PARM_STRING/ {
+  split($0,a,"[,()]")
+  printf "char *%s(const struct share_params *p );\n", a[2]
+}
+
 /^FN_LOCAL_CONST_STRING/ {
   split($0,a,"[,()]")
   printf "const char *%s(int );\n", a[2]
@@ -70,7 +80,7 @@ END {
 
 /^FN_LOCAL_CHAR/ {
   split($0,a,"[,()]")
-  printf "char %s(int );\n", a[2]
+  printf "char %s(const struct share_params *p );\n", a[2]
 }
 
 /^FN_GLOBAL_BOOL/ {
index 62041c7e331b2e51a478ac47bba2e90569ecbf53..e46e73e3e9074be56386c5ddfdd50a60b2061788 100755 (executable)
@@ -25,7 +25,7 @@ header="$1"
 shift
 headertmp="$header.$$.tmp~"
 
-proto_src="`echo $@ | tr ' ' '\n' | sed -e 's/\.o/\.c/g' | sort | uniq | egrep -v 'ubiqx/|wrapped|modules/getdate'`"
+proto_src="`echo $@ | tr ' ' '\n' | sed -e 's/\.o/\.c/g' | sort | uniq | egrep -v 'tdb/|wrapped|modules/getdate'`"
 
 echo creating $header
 
index fe943b87b5ec62f3ec5ea91334238b712ea25ebf..d7a2db5eb6422a476140643e7fde8aeed712592d 100755 (executable)
@@ -111,12 +111,22 @@ cat >$SERVERCONFFILE<<EOF
        bind interfaces only = yes
        include = $COMMONCONFFILE
 
+       ; Necessary to add the build farm hacks
+       add user script = /bin/false
+       add machine script = /bin/false
+
        kernel oplocks = no
 
 [tmp]
        path = $PREFIX_ABS/tmp
        read only = no
        smbd:sharedelay = 100000
+[hideunread]
+       copy = tmp
+       hide unreadable = yes
+[hideunwrite]
+       copy = tmp
+       hide unwriteable files = yes
 EOF
 
 
@@ -181,8 +191,8 @@ START=`date`
  bin/nmblookup $CONFIGURATION $SERVER
  # make sure smbd is also up set
  echo "wait for smbd"
- bin/smbclient $CONFIGURATION -L $SERVER_IP -N -p 139 | head -2
- bin/smbclient $CONFIGURATION -L $SERVER_IP -N -p 139 | head -2
+ bin/smbclient $CONFIGURATION -L $SERVER_IP -U% -p 139 | head -2
+ bin/smbclient $CONFIGURATION -L $SERVER_IP -U% -p 139 | head -2
 
  failed=0
 
index 2274a1f7fe54b41dd1d613d36f35ce51e28a0bd5..d4a03f858174bf0ec0546796df7ed9453c0705a0 100755 (executable)
@@ -31,12 +31,13 @@ raw="RAW-ACLS RAW-CHKPATH RAW-CLOSE RAW-COMPOSITE RAW-CONTEXT RAW-EAS"
 raw="$raw RAW-IOCTL RAW-LOCK RAW-MKDIR RAW-MUX RAW-NOTIFY RAW-OPEN RAW-OPLOCK"
 raw="$raw RAW-QFILEINFO RAW-QFSINFO RAW-READ RAW-RENAME RAW-SEARCH RAW-SEEK"
 raw="$raw RAW-SFILEINFO RAW-SFILEINFO-BUG RAW-STREAMS RAW-UNLINK RAW-WRITE"
+raw="$raw RAW-SAMBA3HIDE RAW-SAMBA3BADPATH"
 
-rpc="RPC-AUTHCONTEXT"
+rpc="RPC-AUTHCONTEXT RPC-BINDSAMBA3 RPC-NETLOGSAMBA3 RPC-SAMBA3SESSIONKEY"
 
 tests="$base $raw $rpc"
 
-skipped="BASE-CHARSET BASE-DEFER_OPEN BASE-DELAYWRITE BASE-DELETE BASE-OPENATTR BASE-TCONDEV"
+skipped="BASE-CHARSET BASE-DEFER_OPEN BASE-DELAYWRITE BASE-OPENATTR BASE-TCONDEV"
 skipped="$skipped RAW-ACLS RAW-CLOSE RAW-COMPOSITE RAW-CONTEXT RAW-EAS"
 skipped="$skipped RAW-IOCTL RAW-MKDIR RAW-MUX RAW-NOTIFY RAW-OPEN"
 skipped="$skipped RAW-QFILEINFO RAW-QFSINFO RAW-RENAME RAW-SEARCH"
index d0e15345df8743f198d0bd1c72186d7804c1ef43..842d914ecff2f7d476abbeae8814c1a92751d66a 100755 (executable)
@@ -24,7 +24,7 @@ tests="$tests UNLINK BROWSE ATTR TRANS2 MAXFID TORTURE "
 tests="$tests OPLOCK1 OPLOCK2 OPLOCK3"
 tests="$tests DIR DIR1 TCON TCONDEV RW1 RW2 RW3"
 tests="$tests OPEN XCOPY RENAME DELETE PROPERTIES W2K"
-tests="$tests PIPE_NUMBER TCON2 IOCTL CHKPATH FDSESS"
+tests="$tests PIPE_NUMBER TCON2 IOCTL CHKPATH FDSESS LOCAL-SUBSTITUTE"
 
 skipped1="RANDOMIPC NEGNOWAIT NBENCH ERRMAPEXTRACT TRANS2SCAN NTTRANSSCAN"
 skipped2="DENY1 DENY2 OPENATTR CASETABLE EATEST"
index 1bbef325ac32ae37d5553f535d07b76ee55cb708..c561870552c231effce1165245a0e1c3c445bb5e 100644 (file)
@@ -32,7 +32,7 @@ static WERROR netlogon_status( const char *service, SERVICE_STATUS *service_stat
         service_status->type              = 0x20;
         service_status->controls_accepted = SVCCTL_ACCEPT_NONE;
 
-       if ( lp_servicenumber("NETLOGON") != -1 ) {
+       if ( share_defined("NETLOGON") ) {
                service_status->state              = SVCCTL_RUNNING;
                service_status->win32_exit_code    = WERR_SERVICE_NEVER_STARTED;
        }
@@ -57,7 +57,7 @@ static WERROR netlogon_stop( const char *service, SERVICE_STATUS *service_status
 
 static WERROR netlogon_start( const char *service )
 {
-       if ( lp_servicenumber("NETLOGON") == -1 )
+       if ( share_defined("NETLOGON") )
                return WERR_SERVICE_DISABLED;
 
        return WERR_ACCESS_DENIED;
index a8db498ef5a2aaa64871d0098c18aca3277eb2f5..04ab01eb664fef7e2fec9ed2b2388d82223b80ac 100644 (file)
@@ -34,7 +34,7 @@ typedef struct _blocking_lock_record {
        int lock_num;
        SMB_BIG_UINT offset;
        SMB_BIG_UINT count;
-       uint16 lock_pid;
+       uint32 lock_pid;
        enum brl_flavour lock_flav;
        enum brl_type lock_type;
        char *inbuf;
@@ -74,7 +74,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length,
                files_struct *fsp,
                int lock_timeout,
                int lock_num,
-               uint16 lock_pid,
+               uint32 lock_pid,
                enum brl_type lock_type,
                enum brl_flavour lock_flav,
                SMB_BIG_UINT offset, SMB_BIG_UINT count)
@@ -121,7 +121,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length,
        memcpy(blr->inbuf, inbuf, length);
        blr->length = length;
 
-       br_lck = brl_get_locks(blr->fsp);
+       br_lck = brl_get_locks(NULL, blr->fsp);
        if (!br_lck) {
                free_blocking_lock_record(blr);
                return False;
@@ -136,7 +136,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length,
                        PENDING_LOCK,
                        blr->lock_flav,
                        &my_lock_ctx);
-       byte_range_lock_destructor(br_lck);
+       TALLOC_FREE(br_lck);
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
@@ -236,7 +236,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status)
        files_struct *fsp = blr->fsp;
        uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
        SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT) 0;
-       uint16 lock_pid;
+       uint32 lock_pid;
        unsigned char locktype = CVAL(inbuf,smb_vwv3);
        BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
        char *data;
@@ -344,7 +344,7 @@ static BOOL process_lockread(blocking_lock_record *blr)
        data = smb_buf(outbuf) + 3;
  
        status = do_lock_spin(fsp,
-                               SVAL(inbuf,smb_pid),
+                               (uint32)SVAL(inbuf,smb_pid),
                                (SMB_BIG_UINT)numtoread,
                                startpos,
                                READ_LOCK,
@@ -417,7 +417,7 @@ static BOOL process_lock(blocking_lock_record *blr)
 
        errno = 0;
        status = do_lock_spin(fsp,
-                               SVAL(inbuf,smb_pid),
+                               (uint32)SVAL(inbuf,smb_pid),
                                count,
                                offset,
                                WRITE_LOCK,
@@ -471,7 +471,7 @@ static BOOL process_lockingX(blocking_lock_record *blr)
        uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
        uint16 num_locks = SVAL(inbuf,smb_vwv7);
        SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0;
-       uint16 lock_pid;
+       uint32 lock_pid;
        BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
        char *data;
        BOOL my_lock_ctx = False;
@@ -625,7 +625,7 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp)
        for(blr = blocking_lock_queue; blr; blr = next) {
                next = blr->next;
                if(blr->fsp->fnum == fsp->fnum) {
-                       struct byte_range_lock *br_lck = brl_get_locks(fsp);
+                       struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
 
                        if (br_lck) {
                                DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \
@@ -637,7 +637,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
                                        blr->offset,
                                        blr->count,
                                        blr->lock_flav);
-                               byte_range_lock_destructor(br_lck);
+                               TALLOC_FREE(br_lck);
 
                        }
 
@@ -658,7 +658,7 @@ void remove_pending_lock_requests_by_mid(int mid)
                next = blr->next;
                if(SVAL(blr->inbuf,smb_mid) == mid) {
                        files_struct *fsp = blr->fsp;
-                       struct byte_range_lock *br_lck = brl_get_locks(fsp);
+                       struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
 
                        if (br_lck) {
                                DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \
@@ -670,7 +670,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
                                        blr->offset,
                                        blr->count,
                                        blr->lock_flav);
-                               byte_range_lock_destructor(br_lck);
+                               TALLOC_FREE(br_lck);
                        }
 
                        blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
@@ -754,7 +754,7 @@ void process_blocking_lock_queue(time_t t)
                        fsp->fnum, fsp->fsp_name ));
 
                if((blr->expire_time != -1) && (blr->expire_time <= t)) {
-                       struct byte_range_lock *br_lck = brl_get_locks(fsp);
+                       struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
 
                        /*
                         * Lock expired - throw away all previously
@@ -771,7 +771,7 @@ void process_blocking_lock_queue(time_t t)
                                        blr->offset,
                                        blr->count,
                                        blr->lock_flav);
-                               byte_range_lock_destructor(br_lck);
+                               TALLOC_FREE(br_lck);
                        }
 
                        blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
@@ -780,7 +780,7 @@ void process_blocking_lock_queue(time_t t)
                }
 
                if(!change_to_user(conn,vuid)) {
-                       struct byte_range_lock *br_lck = brl_get_locks(fsp);
+                       struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
 
                        /*
                         * Remove the entry and return an error to the client.
@@ -793,7 +793,7 @@ void process_blocking_lock_queue(time_t t)
                                        blr->offset,
                                        blr->count,
                                        blr->lock_flav);
-                               byte_range_lock_destructor(br_lck);
+                               TALLOC_FREE(br_lck);
                        }
 
                        DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n",
@@ -804,7 +804,7 @@ void process_blocking_lock_queue(time_t t)
                }
 
                if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) {
-                       struct byte_range_lock *br_lck = brl_get_locks(fsp);
+                       struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
 
                        /*
                         * Remove the entry and return an error to the client.
@@ -817,7 +817,7 @@ void process_blocking_lock_queue(time_t t)
                                        blr->offset,
                                        blr->count,
                                        blr->lock_flav);
-                               byte_range_lock_destructor(br_lck);
+                               TALLOC_FREE(br_lck);
                        }
 
                        DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));
@@ -834,7 +834,7 @@ void process_blocking_lock_queue(time_t t)
                 */
 
                if(blocking_lock_record_process(blr)) {
-                       struct byte_range_lock *br_lck = brl_get_locks(fsp);
+                       struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
 
                        if (br_lck) {
                                brl_remove_pending_lock(br_lck,
@@ -843,7 +843,7 @@ void process_blocking_lock_queue(time_t t)
                                        blr->offset,
                                        blr->count,
                                        blr->lock_flav);
-                               byte_range_lock_destructor(br_lck);
+                               TALLOC_FREE(br_lck);
                        }
 
                        free_blocking_lock_record(blr);
index 738d12151db5252a33972a60878ff3d5d82d28d5..31f03cc7fad7446fd7aa06570cb9d092dd565637 100644 (file)
@@ -79,17 +79,19 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m
                DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", 
                        dc_name, nt_errstr(nt_status)));
                cli_shutdown(cli);
+               cli = NULL;
                goto failed;
        }
 
        nt_status = trust_pw_find_change_and_store_it(netlogon_pipe, cli->mem_ctx, domain);
   
        cli_shutdown(cli);
+       cli = NULL;
        
 failed:
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n", 
-                       timestring(False), domain));
+                       current_timestring(False), domain));
        }
        else
                DEBUG(5,("change_trust_account_password: sucess!\n"));
index d857611c355cdbe4a2d49438ba4d7c97742de811..52182f31294949fdea3322a7dd4d78b5b74e4a04 100644 (file)
@@ -57,7 +57,7 @@ BOOL conn_snum_used(int snum)
 {
        connection_struct *conn;
        for (conn=Connections;conn;conn=conn->next) {
-               if (conn->service == snum) {
+               if (conn->params->service == snum) {
                        return(True);
                }
        }
@@ -136,8 +136,10 @@ find_again:
                return NULL;
        }
 
-       if ((conn=TALLOC_ZERO_P(mem_ctx, connection_struct))==NULL) {
+       if (!(conn=TALLOC_ZERO_P(mem_ctx, connection_struct)) ||
+           !(conn->params = TALLOC_P(mem_ctx, struct share_params))) {
                DEBUG(0,("talloc_zero() failed!\n"));
+               TALLOC_FREE(mem_ctx);
                return NULL;
        }
        conn->mem_ctx = mem_ctx;
@@ -314,7 +316,7 @@ void msg_force_tdis(int msg_type, struct process_id pid, void *buf, size_t len)
 
        for (conn=Connections;conn;conn=next) {
                next=conn->next;
-               if (strequal(lp_servicename(conn->service), sharename)) {
+               if (strequal(lp_servicename(SNUM(conn)), sharename)) {
                        DEBUG(1,("Forcing close of share %s cnum=%d\n",
                                 sharename, conn->cnum));
                        close_cnum(conn, (uint16)-1);
index 07d3181144f7dfd53c70fdbacdf3cd35c22c21ab..0442a9441add06a5fd30af001222c8f7a64419ec 100644 (file)
@@ -83,7 +83,7 @@ BOOL yield_connection(connection_struct *conn, const char *name)
 struct count_stat {
        pid_t mypid;
        int curr_connections;
-       char *name;
+       const char *name;
        BOOL Clear;
 };
 
@@ -124,43 +124,55 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u
  Claim an entry in the connections database.
 ****************************************************************************/
 
-BOOL claim_connection(connection_struct *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags)
+int count_current_connections( const char *sharename, BOOL clear  )
 {
-       struct connections_key key;
-       struct connections_data crec;
-       TDB_DATA kbuf, dbuf;
-
-       if (!tdb)
-               tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, 
-                              O_RDWR | O_CREAT, 0644);
+       struct count_stat cs;
 
-       if (!tdb)
-               return False;
+       cs.mypid = sys_getpid();
+       cs.curr_connections = 0;
+       cs.name = sharename;
+       cs.Clear = clear;
 
        /*
-        * Enforce the max connections parameter.
+        * This has a race condition, but locking the chain before hand is worse
+        * as it leads to deadlock.
         */
 
-       if (max_connections > 0) {
-               struct count_stat cs;
+       if (tdb_traverse(tdb, count_fn, &cs) == -1) {
+               DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n",
+                       tdb_errorstr(tdb) ));
+               return False;
+       }
+       
+       return cs.curr_connections;
+}
 
-               cs.mypid = sys_getpid();
-               cs.curr_connections = 0;
-               cs.name = lp_servicename(SNUM(conn));
-               cs.Clear = Clear;
+/****************************************************************************
+ Claim an entry in the connections database.
+****************************************************************************/
 
-               /*
-                * This has a race condition, but locking the chain before hand is worse
-                * as it leads to deadlock.
-                */
+BOOL claim_connection(connection_struct *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags)
+{
+       struct connections_key key;
+       struct connections_data crec;
+       TDB_DATA kbuf, dbuf;
 
-               if (tdb_traverse(tdb, count_fn, &cs) == -1) {
-                       DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n",
-                               tdb_errorstr(tdb) ));
+       if (!tdb) {
+               if ( (tdb =conn_tdb_ctx()) == NULL ) {
                        return False;
                }
+       }
+       
+       /*
+        * Enforce the max connections parameter.
+        */
 
-               if (cs.curr_connections >= max_connections) {
+       if (max_connections > 0) {
+               int curr_connections;
+               
+               curr_connections = count_current_connections( lp_servicename(SNUM(conn)), True );
+
+               if (curr_connections >= max_connections) {
                        DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n",
                                max_connections, name ));
                        return False;
@@ -241,3 +253,108 @@ BOOL register_message_flags(BOOL doreg, uint32 msg_flags)
        SAFE_FREE(dbuf.dptr);
        return True;
 }
+
+/*********************************************************************
+*********************************************************************/
+
+static TDB_DATA* make_pipe_rec_key( struct pipe_open_rec *prec )
+{
+       TDB_DATA *kbuf = NULL;
+       fstring key_string;
+       
+       if ( !prec )
+               return NULL;
+       
+       if ( (kbuf = TALLOC_P(prec, TDB_DATA)) == NULL ) {
+               return NULL;
+       }
+       
+       snprintf( key_string, sizeof(key_string), "%s/%d/%d",
+               prec->name, procid_to_pid(&prec->pid), prec->pnum );
+               
+       if ( (kbuf->dptr = talloc_strdup(prec, key_string)) == NULL )
+               return NULL;
+               
+       kbuf->dsize = strlen(key_string)+1;
+       
+       return kbuf;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static void fill_pipe_open_rec( struct pipe_open_rec *prec, smb_np_struct *p )
+{
+       prec->pid = pid_to_procid(sys_getpid());
+       prec->pnum = p->pnum;
+       prec->uid = geteuid();
+       fstrcpy( prec->name, p->name );
+
+       return;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+BOOL store_pipe_opendb( smb_np_struct *p )
+{
+       struct pipe_open_rec *prec;
+       TDB_DATA *key;
+       TDB_DATA data;
+       TDB_CONTEXT *pipe_tdb;
+       BOOL ret = False;
+       
+       if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) {
+               DEBUG(0,("store_pipe_opendb: talloc failed!\n"));
+               return False;
+       }
+       
+       fill_pipe_open_rec( prec, p );
+       if ( (key = make_pipe_rec_key( prec )) == NULL ) {
+               goto done;
+       }
+       
+       data.dptr = (char*)prec;
+       data.dsize = sizeof(struct pipe_open_rec);
+       
+       if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) {
+               goto done;
+       }
+       
+       ret = (tdb_store( pipe_tdb, *key, data, TDB_REPLACE ) != -1);
+       
+done:
+       TALLOC_FREE( prec );    
+       return ret;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+BOOL delete_pipe_opendb( smb_np_struct *p )
+{
+       struct pipe_open_rec *prec;
+       TDB_DATA *key;
+       TDB_CONTEXT *pipe_tdb;
+       BOOL ret = False;
+       
+       if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) {
+               DEBUG(0,("store_pipe_opendb: talloc failed!\n"));
+               return False;
+       }
+       
+       fill_pipe_open_rec( prec, p );
+       if ( (key = make_pipe_rec_key( prec )) == NULL ) {
+               goto done;
+       }
+       
+       if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) {
+               goto done;
+       }
+
+       ret = (tdb_delete( pipe_tdb, *key ) != -1 );
+       
+done:
+       TALLOC_FREE( prec );
+       return ret;
+}
index 5ba9e1ed57558d6c94920bc4b02d57fa59a02f9b..96e0923dbd0b62c99c637199a294ba0677d465d2 100644 (file)
@@ -741,7 +741,7 @@ BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
 
 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
 {
-       mangle_map(filename,True,False,SNUM(conn));
+       mangle_map(filename,True,False,conn->params);
        return mask_match_search(filename,mask,False);
 }
 
@@ -787,8 +787,9 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fn
                    mask_match_search(filename,mask,False) ||
                    mangle_mask_match(conn,filename,mask)) {
 
-                       if (!mangle_is_8_3(filename, False, SNUM(conn)))
-                               mangle_map(filename,True,False,SNUM(conn));
+                       if (!mangle_is_8_3(filename, False, conn->params))
+                               mangle_map(filename,True,False,
+                                          conn->params);
 
                        pstrcpy(fname,filename);
                        *path = 0;
@@ -857,17 +858,17 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S
        /* Pseudo-open the file (note - no fd's created). */
 
        if(S_ISDIR(pst->st_mode)) {
-                fsp = open_directory(conn, name, pst,
+                status = open_directory(conn, name, pst,
                        READ_CONTROL_ACCESS,
                        FILE_SHARE_READ|FILE_SHARE_WRITE,
                        FILE_OPEN,
                        0, /* no create options. */
-                       NULL);
+                       NULL, &fsp);
        } else {
-               fsp = open_file_stat(conn, name, pst);
+               status = open_file_stat(conn, name, pst, &fsp);
        }
 
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                return False;
        }
 
@@ -920,17 +921,17 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_
        if(S_ISDIR(pst->st_mode)) {
                return True;
        } else {
-               fsp = open_file_ntcreate(conn, name, pst,
+               status = open_file_ntcreate(conn, name, pst,
                        FILE_WRITE_ATTRIBUTES,
                        FILE_SHARE_READ|FILE_SHARE_WRITE,
                        FILE_OPEN,
                        0,
                        FILE_ATTRIBUTE_NORMAL,
                        INTERNAL_OPEN_ONLY,
-                       &info);
+                       &info, &fsp);
        }
 
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                return False;
        }
 
index 61145fde2f0d03e781bd8f154ee84d70792a5140..260a8dadbd69176a20c501c4f66a18767c5ea2dd 100644 (file)
@@ -300,8 +300,7 @@ static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_
                 * are not violating security in doing the setxattr.
                 */
 
-               fsp = open_file_fchmod(conn,path,sbuf);
-               if (!fsp)
+               if (!NT_STATUS_IS_OK(open_file_fchmod(conn,path,sbuf,&fsp)))
                        return ret;
                become_root();
                if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) {
@@ -518,8 +517,8 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode,
                 * holding. We need to review this.... may need to
                 * break batch oplocks open by others. JRA.
                 */
-               files_struct *fsp = open_file_fchmod(conn,fname,st);
-               if (!fsp)
+               files_struct *fsp;
+               if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,st,&fsp)))
                        return -1;
                become_root();
                ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode);
index fa236f0de05aae8f85e2d4bec33234cc5fb68699..409781eaa9426a72219231b1e59ca93517ef4737 100644 (file)
 extern struct unix_error_map unix_dos_nt_errmap[];
 
 extern uint32 global_client_caps;
-/* these can be set by some functions to override the error codes */
-static int override_ERR_class;
-static uint32 override_ERR_code;
-static NTSTATUS override_ERR_ntstatus;
-
-/****************************************************************************
- Setting eclass and ecode only and status to NT_STATUS_INVALID forces DOS errors.
- Setting status only and eclass and ecode to -1 forces NT errors.
-****************************************************************************/
-void set_saved_error_triple(int eclass, int ecode, NTSTATUS status)
-{
-       override_ERR_class = eclass;
-       override_ERR_code = ecode;
-       override_ERR_ntstatus = status;
-}
-
-void set_saved_ntstatus(NTSTATUS status)
-{
-       uint8 tmp_eclass;       /* Hmmm. override_ERR_class is not uint8... */
-       override_ERR_ntstatus = status;
-       ntstatus_to_dos(status, &tmp_eclass, &override_ERR_code);
-       override_ERR_class = tmp_eclass;
-       
-}
-
-/****************************************************************************
- Return the current settings of the error triple. Return True if any are set.
-****************************************************************************/
-
-NTSTATUS get_saved_ntstatus(void)
-{
-       return override_ERR_ntstatus;
-}
 
 /****************************************************************************
  Create an error packet from a cached error.
@@ -103,6 +69,10 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_s
        return error_packet(outbuf,eclass,ecode,ntstatus,line,file);
 }
 
+BOOL use_nt_status(void)
+{
+       return lp_nt_status_support() && (global_client_caps & CAP_STATUS32);
+}
 
 /****************************************************************************
  Create an error packet. Normally called using the ERROR() macro.
@@ -117,18 +87,9 @@ int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, in
        BOOL force_nt_status = False;
        BOOL force_dos_status = False;
 
-       if (override_ERR_class != SMB_SUCCESS || !NT_STATUS_IS_OK(override_ERR_ntstatus)) {
-               eclass = override_ERR_class;
-               ecode = override_ERR_code;
-               ntstatus = override_ERR_ntstatus;
-               override_ERR_class = SMB_SUCCESS;
-               override_ERR_code = 0;
-               override_ERR_ntstatus = NT_STATUS_OK;
-       }
-
        if (eclass == (uint8)-1) {
                force_nt_status = True;
-       } else if (NT_STATUS_IS_INVALID(ntstatus)) {
+       } else if (NT_STATUS_IS_DOS(ntstatus)) {
                force_dos_status = True;
        }
 
@@ -146,7 +107,10 @@ int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, in
                         nt_errstr(ntstatus)));
        } else {
                /* We're returning a DOS error only. */
-               if (eclass == 0 && NT_STATUS_V(ntstatus)) {
+               if (NT_STATUS_IS_DOS(ntstatus)) {
+                       eclass = NT_STATUS_DOS_CLASS(ntstatus);
+                       ecode = NT_STATUS_DOS_CODE(ntstatus);
+               } else  if (eclass == 0 && NT_STATUS_V(ntstatus)) {
                        ntstatus_to_dos(ntstatus, &eclass, &ecode);
                }
 
index b4f1f02b7244662492c168de312615ed728557de..7c5eeae5c7d2d19f15d6c32dfeeb82ace7b1dee9 100644 (file)
@@ -101,24 +101,26 @@ enum FAKE_FILE_TYPE is_fake_file(const char *fname)
  Open a fake quota file with a share mode.
 ****************************************************************************/
 
-files_struct *open_fake_file(connection_struct *conn,
+NTSTATUS open_fake_file(connection_struct *conn,
                                enum FAKE_FILE_TYPE fake_file_type,
                                const char *fname,
-                               uint32 access_mask)
+                               uint32 access_mask,
+                               files_struct **result)
 {
        files_struct *fsp = NULL;
+       NTSTATUS status;
 
        /* access check */
        if (current_user.ut.uid != 0) {
                DEBUG(1,("open_fake_file_shared: access_denied to service[%s] file[%s] user[%s]\n",
                        lp_servicename(SNUM(conn)),fname,conn->user));
-               errno = EACCES;
-               return NULL;
+               return NT_STATUS_ACCESS_DENIED;
+
        }
 
-       fsp = file_new(conn);
-       if(!fsp) {
-               return NULL;
+       status = file_new(conn, &fsp);
+       if(!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        DEBUG(5,("open_fake_file_shared: fname = %s, FID = %d, access_mask = 0x%x\n",
@@ -128,7 +130,7 @@ files_struct *open_fake_file(connection_struct *conn,
        fsp->fh->fd = -1;
        fsp->vuid = current_user.vuid;
        fsp->fh->pos = -1;
-       fsp->can_lock = True; /* Should this be true ? */
+       fsp->can_lock = False; /* Should this be true ? - No, JRA */
        fsp->access_mask = access_mask;
        string_set(&fsp->fsp_name,fname);
        
@@ -136,11 +138,12 @@ files_struct *open_fake_file(connection_struct *conn,
        
        if (fsp->fake_file_handle==NULL) {
                file_free(fsp);
-               return NULL;
+               return NT_STATUS_NO_MEMORY;
        }
 
        conn->num_files_open++;
-       return fsp;
+       *result = fsp;
+       return NT_STATUS_OK;
 }
 
 void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh)
index 6c0f8b77585ff06c56b15efdcadd3dbc0db8bc69..1ea5228e919d8dfb880ef1f52503cbbcb7033780 100644 (file)
@@ -46,12 +46,13 @@ static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitiv
  Mangle the 2nd name and check if it is then equal to the first name.
 ****************************************************************************/
 
-static BOOL mangled_equal(const char *name1, const char *name2, int snum)
+static BOOL mangled_equal(const char *name1, const char *name2,
+                         const struct share_params *p)
 {
        pstring tmpname;
        
        pstrcpy(tmpname, name2);
-       mangle_map(tmpname, True, False, snum);
+       mangle_map(tmpname, True, False, p);
        return strequal(name1, tmpname);
 }
 
@@ -189,7 +190,8 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
         * sensitive then searching won't help.
         */
 
-       if (conn->case_sensitive && !mangle_is_mangled(name, SNUM(conn)) && !*lp_mangled_map(SNUM(conn)))
+       if (conn->case_sensitive && !mangle_is_mangled(name, conn->params) &&
+           !*lp_mangled_map(conn->params))
                return(False);
 
        name_has_wildcard = ms_has_wild(start);
@@ -199,7 +201,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
         * just a component. JRA.
         */
 
-       if (mangle_is_mangled(start, SNUM(conn)))
+       if (mangle_is_mangled(start, conn->params))
                component_was_mangled = True;
 
        /* 
@@ -318,7 +320,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
                                 * purposes. Fix inspired by Thomas Neumann <t.neumann@iku-ag.de>.
                                 */
                                if (!conn->case_preserve ||
-                                               (mangle_is_8_3(start, False, SNUM(conn)) &&
+                                   (mangle_is_8_3(start, False, conn->params) &&
                                                 !conn->short_case_preserve)) {
                                        strnorm(start, lp_defaultcase(SNUM(conn)));
                                }
@@ -328,8 +330,8 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
                                 * base of the filename.
                                 */
 
-                               if (mangle_is_mangled(start, SNUM(conn))) {
-                                       mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), SNUM(conn));
+                               if (mangle_is_mangled(start, conn->params)) {
+                                       mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), conn->params);
                                }
 
                                DEBUG(5,("New file %s\n",start));
@@ -444,7 +446,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name
        BOOL mangled;
        long curpos;
 
-       mangled = mangle_is_mangled(name, SNUM(conn));
+       mangled = mangle_is_mangled(name, conn->params);
 
        /* handle null paths */
        if (*path == 0)
@@ -466,7 +468,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name
         */
 
        if (mangled && !conn->case_sensitive) {
-               mangled = !mangle_check_cache( name, maxlength, SNUM(conn));
+               mangled = !mangle_check_cache( name, maxlength, conn->params);
        }
 
        /* open the directory */
@@ -495,7 +497,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name
                 * against unmangled name.
                 */
 
-               if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname, conn->case_sensitive)) {
+               if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) {
                        /* we've found the file, change it's name and return */
                        safe_strcpy(name, dname, maxlength);
                        CloseDir(cur_dir);
index e020d8e13a6baffac712ece125e20b4f31c87cf9..7069818dee4f1f117f10317608028ded587679e6 100644 (file)
@@ -59,7 +59,7 @@ static unsigned long get_gen_count(void)
  Find first available file slot.
 ****************************************************************************/
 
-files_struct *file_new(connection_struct *conn)
+NTSTATUS file_new(connection_struct *conn, files_struct **result)
 {
        int i;
        static int first_file;
@@ -82,14 +82,12 @@ files_struct *file_new(connection_struct *conn)
                /* TODO: We have to unconditionally return a DOS error here,
                 * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with
                 * NTSTATUS negotiated */
-               set_saved_ntstatus(NT_STATUS_TOO_MANY_OPENED_FILES);
-               return NULL;
+               return NT_STATUS_TOO_MANY_OPENED_FILES;
        }
 
        fsp = SMB_MALLOC_P(files_struct);
        if (!fsp) {
-               set_saved_ntstatus(NT_STATUS_NO_MEMORY);
-               return NULL;
+               return NT_STATUS_NO_MEMORY;
        }
 
        ZERO_STRUCTP(fsp);
@@ -97,8 +95,7 @@ files_struct *file_new(connection_struct *conn)
        fsp->fh = SMB_MALLOC_P(struct fd_handle);
        if (!fsp->fh) {
                SAFE_FREE(fsp);
-               set_saved_ntstatus(NT_STATUS_NO_MEMORY);
-               return NULL;
+               return NT_STATUS_NO_MEMORY;
        }
 
        ZERO_STRUCTP(fsp->fh);
@@ -131,8 +128,9 @@ files_struct *file_new(connection_struct *conn)
        if (fsp_fi_cache.fsp == NULL) {
                ZERO_STRUCT(fsp_fi_cache);
        }
-       
-       return fsp;
+
+       *result = fsp;
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
@@ -464,24 +462,16 @@ void file_free(files_struct *fsp)
 }
 
 /****************************************************************************
- Get a fsp from a packet given the offset of a 16 bit fnum.
+ Get an fsp from a 16 bit fnum.
 ****************************************************************************/
 
-files_struct *file_fsp(char *buf, int where)
+files_struct *file_fnum(uint16 fnum)
 {
-       int fnum, count=0;
        files_struct *fsp;
-
-       if (chain_fsp)
-               return chain_fsp;
-
-       if (!buf)
-               return NULL;
-       fnum = SVAL(buf, where);
+       int count=0;
 
        for (fsp=Files;fsp;fsp=fsp->next, count++) {
                if (fsp->fnum == fnum) {
-                       chain_fsp = fsp;
                        if (count > 10) {
                                DLIST_PROMOTE(Files, fsp);
                        }
@@ -491,6 +481,29 @@ files_struct *file_fsp(char *buf, int where)
        return NULL;
 }
 
+/****************************************************************************
+ Get an fsp from a packet given the offset of a 16 bit fnum.
+****************************************************************************/
+
+files_struct *file_fsp(char *buf, int where)
+{
+       files_struct *fsp;
+
+       if (chain_fsp) {
+               return chain_fsp;
+       }
+
+       if (!buf) {
+               return NULL;
+       }
+
+       fsp = file_fnum(SVAL(buf, where));
+       if (fsp) {
+               chain_fsp = fsp;
+       }
+       return fsp;
+}
+
 /****************************************************************************
  Reset the chained fsp - done at the start of a packet reply.
 ****************************************************************************/
@@ -504,15 +517,19 @@ void file_chain_reset(void)
  Duplicate the file handle part for a DOS or FCB open.
 ****************************************************************************/
 
-files_struct *dup_file_fsp(files_struct *fsp,
+NTSTATUS dup_file_fsp(files_struct *fsp,
                                uint32 access_mask,
                                uint32 share_access,
-                               uint32 create_options)
+                               uint32 create_options,
+                               files_struct **result)
 {
-       files_struct *dup_fsp = file_new(fsp->conn);
+       NTSTATUS status;
+       files_struct *dup_fsp;
 
-       if (!dup_fsp) {
-               return NULL;
+       status = file_new(fsp->conn, &dup_fsp);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        SAFE_FREE(dup_fsp->fh);
@@ -547,5 +564,6 @@ files_struct *dup_file_fsp(files_struct *fsp,
        dup_fsp->aio_write_behind = fsp->aio_write_behind;
         string_set(&dup_fsp->fsp_name,fsp->fsp_name);
 
-       return dup_fsp;
+       *result = dup_fsp;
+       return NT_STATUS_OK;
 }
index e4531d8ae980f8d56ab991713fd38a62cad5e61a..2d6db8f2a30a508b21138719d6e7d32330c3c18e 100644 (file)
@@ -72,7 +72,11 @@ static int CopyExpanded(connection_struct *conn,
 
        StrnCpy(buf,src,sizeof(buf)/2);
        pstring_sub(buf,"%S",lp_servicename(snum));
-       standard_sub_conn(conn,buf,sizeof(buf));
+       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                             conn->connectpath, conn->gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             buf, sizeof(buf));
        l = push_ascii(*dst,buf,*n, STR_TERMINATE);
        (*dst) += l;
        (*n) -= l;
@@ -99,7 +103,11 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s)
        }
        StrnCpy(buf,s,sizeof(buf)/2);
        pstring_sub(buf,"%S",lp_servicename(snum));
-       standard_sub_conn(conn,buf,sizeof(buf));
+       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                             conn->connectpath, conn->gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             buf, sizeof(buf));
        return strlen(buf) + 1;
 }
 
@@ -111,7 +119,11 @@ static char *Expand(connection_struct *conn, int snum, char *s)
        }
        StrnCpy(buf,s,sizeof(buf)/2);
        pstring_sub(buf,"%S",lp_servicename(snum));
-       standard_sub_conn(conn,buf,sizeof(buf));
+       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                             conn->connectpath, conn->gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             buf, sizeof(buf));
        return &buf[0];
 }
 
@@ -593,7 +605,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum,
        PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
        
        fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
-       standard_sub_basic( "", location, sizeof(location)-1 );
+       standard_sub_basic( "", "", location, sizeof(location)-1 );
        PACKS(desc,"z", location);                          /* share to retrieve files */
        
        PACKS(desc,"z", driver.info_3->defaultdatatype);    /* default data type */
@@ -2534,7 +2546,6 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
        char *str2 = skip_string(str1,1);
        char *p = skip_string(str2,1);
        uint32 jobid;
-       int snum;
        fstring sharename;
        int uLevel = SVAL(p,2);
        int function = SVAL(p,4);
@@ -2548,9 +2559,9 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
                return False;
        }
 
-       if ( (snum = lp_servicenumber(sharename)) == -1 ) {
-               DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
-                       sharename));
+       if (!share_defined(sharename)) {
+               DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
+                        sharename));
                return False;
        }
   
@@ -2573,14 +2584,14 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
                /* change job place in the queue, 
                   data gives the new place */
                place = SVAL(data,0);
-               if (print_job_set_place(snum, jobid, place)) {
+               if (print_job_set_place(sharename, jobid, place)) {
                        errcode=NERR_Success;
                }
                break;
 
        case 0xb:   
                /* change print job name, data gives the name */
-               if (print_job_set_name(snum, jobid, data)) {
+               if (print_job_set_name(sharename, jobid, data)) {
                        errcode=NERR_Success;
                }
                break;
@@ -2701,7 +2712,11 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
                        SIVAL(p,6,0);
                } else {
                        SIVAL(p,6,PTR_DIFF(p2,*rdata));
-                       standard_sub_conn(conn,comment,sizeof(comment));
+                       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                                             conn->connectpath, conn->gid,
+                                             get_current_username(),
+                                             current_user_info.domain,
+                                             comment, sizeof(comment));
                        StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
                        p2 = skip_string(p2,1);
                }
@@ -3126,8 +3141,12 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
                        SSVALS(p,102,-1);       /* bad_pw_count */
                        SSVALS(p,104,-1);       /* num_logons */
                        SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
-                       pstrcpy(p2,"\\\\%L");
-                       standard_sub_conn(conn, p2,0);
+                       {
+                               pstring tmp;
+                               pstrcpy(tmp, "\\\\%L");
+                               standard_sub_basic("", "", tmp, sizeof(tmp));
+                               pstrcpy(p2, tmp);
+                       }
                        p2 = skip_string(p2,1);
                        SSVAL(p,110,49);        /* country_code */
                        SSVAL(p,112,860);       /* code page */
index ed69a6210e88fd40311c8e872a3a7f15b233f5dc..16f99636eb539b0a4b61c3c99d2823667930b5f8 100644 (file)
@@ -81,22 +81,24 @@ void mangle_change_to_posix(void)
 /*
   see if a filename has come out of our mangling code
 */
-BOOL mangle_is_mangled(const char *s, int snum)
+BOOL mangle_is_mangled(const char *s, const struct share_params *p)
 {
-       return mangle_fns->is_mangled(s, snum);
+       return mangle_fns->is_mangled(s, p);
 }
 
 /*
   see if a filename matches the rules of a 8.3 filename
 */
-BOOL mangle_is_8_3(const char *fname, BOOL check_case, int snum)
+BOOL mangle_is_8_3(const char *fname, BOOL check_case,
+                  const struct share_params *p)
 {
-       return mangle_fns->is_8_3(fname, check_case, False, snum);
+       return mangle_fns->is_8_3(fname, check_case, False, p);
 }
 
-BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case, int snum)
+BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case,
+                            const struct share_params *p)
 {
-       return mangle_fns->is_8_3(fname, check_case, True, snum);
+       return mangle_fns->is_8_3(fname, check_case, True, p);
 }
 
 /*
@@ -105,20 +107,22 @@ BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case, int snum)
   looking for a matching name if it doesn't. It should succeed most of the time
   or there will be a huge performance penalty
 */
-BOOL mangle_check_cache(char *s, size_t maxlen, int snum)
+BOOL mangle_check_cache(char *s, size_t maxlen,
+                       const struct share_params *p)
 {
-       return mangle_fns->check_cache(s, maxlen, snum);
+       return mangle_fns->check_cache(s, maxlen, p);
 }
 
 /* 
    map a long filename to a 8.3 name. 
  */
 
-void mangle_map(pstring OutName, BOOL need83, BOOL cache83, int snum)
+void mangle_map(pstring OutName, BOOL need83, BOOL cache83,
+               const struct share_params *p)
 {
        /* name mangling can be disabled for speed, in which case
           we just truncate the string */
-       if (!lp_manglednames(snum)) {
+       if (!lp_manglednames(p)) {
                if (need83) {
                        string_truncate(OutName, 12);
                }
@@ -126,6 +130,6 @@ void mangle_map(pstring OutName, BOOL need83, BOOL cache83, int snum)
        }
 
        /* invoke the inane "mangled map" code */
-       mangle_map_filename(OutName, snum);
-       mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(snum), snum);
+       mangle_map_filename(OutName, p);
+       mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(p->service), p);
 }
index 2092f430c0772eff91ccc106b4a9f1158764cddc..320e31ab679e3796570d018511fde9ba60a43ddc 100644 (file)
@@ -275,14 +275,15 @@ done:
        return ret;
 }
 
-static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum)
+static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards,
+                  const struct share_params *p)
 {
        const char *f;
        smb_ucs2_t *ucs2name;
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
        size_t size;
 
-       magic_char = lp_magicchar(snum);
+       magic_char = lp_magicchar(p);
 
        if (!fname || !*fname)
                return False;
@@ -360,11 +361,11 @@ static void init_chartest( void )
  *
  * ************************************************************************** **
  */
-static BOOL is_mangled(const char *s, int snum)
+static BOOL is_mangled(const char *s, const struct share_params *p)
 {
        char *magic;
 
-       magic_char = lp_magicchar(snum);
+       magic_char = lp_magicchar(p);
 
        if( !ct_initialized )
                init_chartest();
@@ -460,13 +461,13 @@ static void cache_mangled_name( const char mangled_name[13], char *raw_name )
  * ************************************************************************** **
  */
 
-static BOOL check_cache( char *s, size_t maxlen, int snum )
+static BOOL check_cache( char *s, size_t maxlen, const struct share_params *p )
 {
        TDB_DATA data_val;
        char *ext_start = NULL;
        char *saved_ext = NULL;
 
-       magic_char = lp_magicchar(snum);
+       magic_char = lp_magicchar(p);
 
        /* If the cache isn't initialized, give up. */
        if( !tdb_mangled_cache )
@@ -606,10 +607,11 @@ static void to_8_3(char *s, int default_case)
  * ****************************************************************************
  */
 
-static void name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum)
+static void name_map(char *OutName, BOOL need83, BOOL cache83,
+                    int default_case, const struct share_params *p)
 {
        smb_ucs2_t *OutName_ucs2;
-       magic_char = lp_magicchar(snum);
+       magic_char = lp_magicchar(p);
 
        DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName,
                 need83 ? "True" : "False", cache83 ? "True" : "False"));
index 0a161c9e769f369e68d7065c3bc929195d7f2af0..d1ce1af9eac3acc5686d8bf1ea28203548f99de8 100644 (file)
@@ -101,7 +101,7 @@ static unsigned mangle_prefix;
    hashing the resulting cache entry to match the known hash
 */
 static char **prefix_cache;
-static u32 *prefix_cache_hashes;
+static unsigned int *prefix_cache_hashes;
 
 /* these are the characters we use in the 8.3 hash. Must be 36 chars long */
 static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
@@ -119,10 +119,10 @@ static const char *reserved_names[] =
 
    this hash needs to be fast with a low collision rate (what hash doesn't?)
 */
-static u32 mangle_hash(const char *key, unsigned int length)
+static unsigned int mangle_hash(const char *key, unsigned int length)
 {
-       u32 value;
-       u32   i;
+       unsigned int value;
+       unsigned int   i;
        fstring str;
 
        /* we have to uppercase here to ensure that the mangled name
@@ -139,8 +139,8 @@ static u32 mangle_hash(const char *key, unsigned int length)
 
        /* Set the initial value from the key size. */
        for (value = FNV1_INIT, i=0; i < length; i++) {
-                value *= (u32)FNV1_PRIME;
-                value ^= (u32)(str[i]);
+                value *= (unsigned int)FNV1_PRIME;
+                value ^= (unsigned int)(str[i]);
         }
 
        /* note that we force it to a 31 bit hash, to keep within the limits
@@ -162,7 +162,7 @@ static BOOL cache_init(void)
                return False;
        }
 
-       prefix_cache_hashes = SMB_CALLOC_ARRAY(u32, MANGLE_CACHE_SIZE);
+       prefix_cache_hashes = SMB_CALLOC_ARRAY(unsigned int, MANGLE_CACHE_SIZE);
        if (!prefix_cache_hashes) {
                return False;
        }
@@ -173,7 +173,7 @@ static BOOL cache_init(void)
 /*
   insert an entry into the prefix cache. The string might not be null
   terminated */
-static void cache_insert(const char *prefix, int length, u32 hash)
+static void cache_insert(const char *prefix, int length, unsigned int hash)
 {
        int i = hash % MANGLE_CACHE_SIZE;
 
@@ -188,7 +188,7 @@ static void cache_insert(const char *prefix, int length, u32 hash)
 /*
   lookup an entry in the prefix cache. Return NULL if not found.
 */
-static const char *cache_lookup(u32 hash)
+static const char *cache_lookup(unsigned int hash)
 {
        int i = hash % MANGLE_CACHE_SIZE;
 
@@ -268,7 +268,7 @@ static BOOL is_mangled_component(const char *name, size_t len)
    directory separators. It should return true if any component is
    mangled
  */
-static BOOL is_mangled(const char *name, int snum)
+static BOOL is_mangled(const char *name, const struct share_params *parm)
 {
        const char *p;
        const char *s;
@@ -293,7 +293,7 @@ static BOOL is_mangled(const char *name, int snum)
    simplifies things greatly (it means that we know the string won't
    get larger when converted from UNIX to DOS formats)
 */
-static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, int snum)
+static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, const struct share_params *p)
 {
        int len, i;
        char *dot_p;
@@ -370,15 +370,15 @@ static void mangle_reset(void)
   try to find a 8.3 name in the cache, and if found then
   replace the string with the original long name. 
 */
-static BOOL check_cache(char *name, size_t maxlen, int snum)
+static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p)
 {
-       u32 hash, multiplier;
+       unsigned int hash, multiplier;
        unsigned int i;
        const char *prefix;
        char extension[4];
 
        /* make sure that this is a mangled name from this cache */
-       if (!is_mangled(name, snum)) {
+       if (!is_mangled(name, p)) {
                M_DEBUG(10,("check_cache: %s -> not mangled\n", name));
                return False;
        }
@@ -386,7 +386,7 @@ static BOOL check_cache(char *name, size_t maxlen, int snum)
        /* we need to extract the hash from the 8.3 name */
        hash = base_reverse[(unsigned char)name[7]];
        for (multiplier=36, i=5;i>=mangle_prefix;i--) {
-               u32 v = base_reverse[(unsigned char)name[i]];
+               unsigned int v = base_reverse[(unsigned char)name[i]];
                hash += multiplier * v;
                multiplier *= 36;
        }
@@ -510,21 +510,21 @@ static BOOL is_legal_name(const char *name)
 
   the name parameter must be able to hold 13 bytes
 */
-static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, int snum)
+static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, const struct share_params *p)
 {
        char *dot_p;
        char lead_chars[7];
        char extension[4];
        unsigned int extension_length, i;
        unsigned int prefix_len;
-       u32 hash, v;
+       unsigned int hash, v;
        char new_name[13];
 
        /* reserved names are handled specially */
        if (!is_reserved_name(name)) {
                /* if the name is already a valid 8.3 name then we don't need to 
                   do anything */
-               if (is_8_3(name, False, False, snum)) {
+               if (is_8_3(name, False, False, p)) {
                        return;
                }
 
@@ -724,22 +724,22 @@ struct mangle_fns *mangle_hash2_init(void)
 static void posix_mangle_reset(void)
 {;}
 
-static BOOL posix_is_mangled(const char *s, int snum)
+static BOOL posix_is_mangled(const char *s, const struct share_params *p)
 {
        return False;
 }
 
-static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum)
+static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, const struct share_params *p)
 {
        return False;
 }
 
-static BOOL posix_check_cache( char *s, size_t maxlen, int snum )
+static BOOL posix_check_cache( char *s, size_t maxlen, const struct share_params *p )
 {
        return False;
 }
 
-static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum)
+static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, const struct share_params *p)
 {
        if (need83) {
                memset(OutName, '\0', 13);
index 9e798fd41b46ce6d5912d362346417bdc4c28b06..c5803786ec06b6896485961aeed9c2cd012fe25f 100644 (file)
@@ -201,11 +201,11 @@ static void mangled_map(char *s, const char *MangledMap)
   front end routine to the mangled map code 
   personally I think that the whole idea of "mangled map" is completely bogus
 */
-void mangle_map_filename(fstring fname, int snum)
+void mangle_map_filename(fstring fname, const struct share_params *p)
 {
        char *map;
 
-       map = lp_mangled_map(snum);
+       map = lp_mangled_map(p);
        if (!map || !*map) return;
 
        mangled_map(fname, map);
index 31dab458443cb24b670f65bcb507d4037aae74d6..fd53e60c1414a363d69d898c20466b3c90256331 100644 (file)
@@ -101,7 +101,8 @@ static void msg_deliver(void)
                pstrcpy(s,lp_msg_command());
                pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,NULL,sizeof(alpha_msgfrom)));
                pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,NULL,sizeof(alpha_msgto)));
-               standard_sub_basic(current_user_info.smb_name, s, sizeof(s));
+               standard_sub_basic(current_user_info.smb_name,
+                               current_user_info.domain, s, sizeof(s));
                pstring_sub(s,"%s",name);
                smbrun(s,NULL);
        }
index b22b5674d6fd651b3357038b773d9148a282d001..69da4194fda49a31584e29dcb2ca6b1311f8d5f8 100644 (file)
@@ -135,7 +135,6 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path)
 
        ZERO_STRUCTP(conn);
 
-       conn->service = snum;
        pstrcpy(connpath, path);
        pstring_sub(connpath , "%S", lp_servicename(snum));
 
@@ -145,6 +144,13 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path)
                 DEBUG(0,("talloc_init(connection_struct) failed!\n"));
                 return False;
         }
+
+       if (!(conn->params = TALLOC_P(conn->mem_ctx, struct share_params))) {
+               DEBUG(0, ("TALLOC failed\n"));
+               return False;
+       }
+       
+       conn->params->service = snum;
        
        set_conn_connectpath(conn, connpath);
 
index aa6f79e16571c0c4829b46a8bca5aa04cb913478..0b1bdcadbb1bd88be35c3a7bdef1daa7081e87d9 100644 (file)
@@ -321,7 +321,7 @@ static int nt_open_pipe(char *fname, connection_struct *conn,
        smb_np_struct *p = NULL;
        uint16 vuid = SVAL(inbuf, smb_uid);
        int i;
-
        DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname));
     
        /* See if it is one we want to handle. */
@@ -350,6 +350,12 @@ static int nt_open_pipe(char *fname, connection_struct *conn,
                return(ERROR_DOS(ERRSRV,ERRnofids));
        }
 
+       /* TODO: Add pipe to db */
+       
+       if ( !store_pipe_opendb( p ) ) {
+               DEBUG(3,("nt_open_pipe: failed to store %s pipe open.\n", fname));
+       }
+       
        *ppnum = p->pnum;
        return 0;
 }
@@ -412,10 +418,14 @@ int reply_ntcreate_and_X_quota(connection_struct *conn,
        int result;
        char *p;
        uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess);
-       files_struct *fsp = open_fake_file(conn, fake_file_type, fname, desired_access);
+       files_struct *fsp;
+       NTSTATUS status;
 
-       if (!fsp) {
-               return ERROR_NT(NT_STATUS_ACCESS_DENIED);
+       status = open_fake_file(conn, fake_file_type, fname, desired_access,
+                               &fsp);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return ERROR_NT(status);
        }
 
        set_message(outbuf,34,0,True);
@@ -688,18 +698,18 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
                }
 
-               fsp = open_directory(conn, fname, &sbuf,
+               status = open_directory(conn, fname, &sbuf,
                                        access_mask,
                                        share_access,
                                        create_disposition,
                                        create_options,
-                                       &info);
+                                       &info, &fsp);
 
                restore_case_semantics(conn, file_attributes);
 
-               if(!fsp) {
+               if(!NT_STATUS_IS_OK(status)) {
                        END_PROFILE(SMBntcreateX);
-                       return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+                       return ERROR_NT(status);
                }
        } else {
                /*
@@ -719,15 +729,15 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
                 * before issuing an oplock break request to
                 * our client. JRA.  */
 
-               fsp = open_file_ntcreate(conn,fname,&sbuf,
+               status = open_file_ntcreate(conn,fname,&sbuf,
                                        access_mask,
                                        share_access,
                                        create_disposition,
                                        create_options,
                                        file_attributes,
                                        oplock_request,
-                                       &info);
-               if (!fsp) { 
+                                       &info, &fsp);
+               if (!NT_STATUS_IS_OK(status)) { 
                        /* We cheat here. There are two cases we
                         * care about. One is a directory rename,
                         * where the NT client will attempt to
@@ -747,7 +757,8 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
                         * we handle in the open_file_stat case. JRA.
                         */
 
-                       if(errno == EISDIR) {
+                       if (NT_STATUS_EQUAL(status,
+                                           NT_STATUS_FILE_IS_A_DIRECTORY)) {
 
                                /*
                                 * Fail the open if it was explicitly a non-directory file.
@@ -760,17 +771,17 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
                                }
        
                                oplock_request = 0;
-                               fsp = open_directory(conn, fname, &sbuf,
+                               status = open_directory(conn, fname, &sbuf,
                                                        access_mask,
                                                        share_access,
                                                        create_disposition,
                                                        create_options,
-                                                       &info);
+                                                       &info, &fsp);
 
-                               if(!fsp) {
+                               if(!NT_STATUS_IS_OK(status)) {
                                        restore_case_semantics(conn, file_attributes);
                                        END_PROFILE(SMBntcreateX);
-                                       return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+                                       return ERROR_NT(status);
                                }
                        } else {
 
@@ -780,7 +791,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
                                        /* We have re-scheduled this call. */
                                        return -1;
                                }
-                               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+                               return ERROR_NT(status);
                        }
                } 
        }
@@ -1331,16 +1342,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                 * CreateDirectory() call.
                 */
 
-               fsp = open_directory(conn, fname, &sbuf,
+               status = open_directory(conn, fname, &sbuf,
                                        access_mask,
                                        share_access,
                                        create_disposition,
                                        create_options,
-                                       &info);
-               if(!fsp) {
+                                       &info, &fsp);
+               if(!NT_STATUS_IS_OK(status)) {
                        talloc_destroy(ctx);
                        restore_case_semantics(conn, file_attributes);
-                       return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+                       return ERROR_NT(status);
                }
 
        } else {
@@ -1349,17 +1360,18 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                 * Ordinary file case.
                 */
 
-               fsp = open_file_ntcreate(conn,fname,&sbuf,
+               status = open_file_ntcreate(conn,fname,&sbuf,
                                        access_mask,
                                        share_access,
                                        create_disposition,
                                        create_options,
                                        file_attributes,
                                        oplock_request,
-                                       &info);
+                                       &info, &fsp);
 
-               if (!fsp) { 
-                       if(errno == EISDIR) {
+               if (!NT_STATUS_IS_OK(status)) { 
+                       if (NT_STATUS_EQUAL(status,
+                                           NT_STATUS_FILE_IS_A_DIRECTORY)) {
 
                                /*
                                 * Fail the open if it was explicitly a non-directory file.
@@ -1371,16 +1383,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                                }
        
                                oplock_request = 0;
-                               fsp = open_directory(conn, fname, &sbuf,
+                               status = open_directory(conn, fname, &sbuf,
                                                        access_mask,
                                                        share_access,
                                                        create_disposition,
                                                        create_options,
-                                                       &info);
-                               if(!fsp) {
+                                                       &info, &fsp);
+                               if(!NT_STATUS_IS_OK(status)) {
                                        talloc_destroy(ctx);
                                        restore_case_semantics(conn, file_attributes);
-                                       return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+                                       return ERROR_NT(status);
                                }
                        } else {
                                talloc_destroy(ctx);
@@ -1389,7 +1401,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                                        /* We have re-scheduled this call. */
                                        return -1;
                                }
-                               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+                               return ERROR_NT(status);
                        }
                } 
        }
@@ -1655,39 +1667,29 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
 
        DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname));
 
-        fsp1 = open_file_ntcreate(conn,oldname,&sbuf1,
+        status = open_file_ntcreate(conn,oldname,&sbuf1,
                        FILE_READ_DATA, /* Read-only. */
                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                        FILE_OPEN,
                        0, /* No create options. */
                        FILE_ATTRIBUTE_NORMAL,
                        NO_OPLOCK,
-                       &info);
+                       &info, &fsp1);
 
-       if (!fsp1) {
-               status = get_saved_ntstatus();
-               if (NT_STATUS_IS_OK(status)) {
-                       status = NT_STATUS_ACCESS_DENIED;
-               }
-               set_saved_ntstatus(NT_STATUS_OK);
+       if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-        fsp2 = open_file_ntcreate(conn,newname,&sbuf2,
-                       FILE_WRITE_DATA, /* Write-only. */
+        status = open_file_ntcreate(conn,newname,&sbuf2,
+                       FILE_WRITE_DATA, /* Read-only. */
                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                        FILE_CREATE,
                        0, /* No create options. */
                        fattr,
                        NO_OPLOCK,
-                       &info);
+                       &info, &fsp2);
 
-       if (!fsp2) {
-               status = get_saved_ntstatus();
-               if (NT_STATUS_IS_OK(status)) {
-                       status = NT_STATUS_ACCESS_DENIED;
-               }
-               set_saved_ntstatus(NT_STATUS_OK);
+       if (!NT_STATUS_IS_OK(status)) {
                close_file(fsp1,ERROR_CLOSE);
                return status;
        }
@@ -2389,7 +2391,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
                return ERROR_NT(NT_STATUS_INVALID_HANDLE);
        }
 
-       /* the NULL pointer cheking for fsp->fake_file_handle->pd
+       /* the NULL pointer checking for fsp->fake_file_handle->pd
         * is done by CHECK_NTQUOTA_HANDLE_OK()
         */
        qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->pd;
index 832a8df75598e1914f6fb28f88671252596759fd..7c04cdbe7cc43ca8b4e6b5bf95dda9a4717dc1b4 100644 (file)
@@ -38,24 +38,29 @@ struct deferred_open_record {
  fd support routines - attempt to do a dos_open.
 ****************************************************************************/
 
-static int fd_open(struct connection_struct *conn,
+static BOOL fd_open(struct connection_struct *conn,
                        const char *fname, 
+                       files_struct *fsp,
                        int flags,
                        mode_t mode)
 {
-       int fd;
+       int sav;
+
 #ifdef O_NOFOLLOW
        if (!lp_symlinks(SNUM(conn))) {
                flags |= O_NOFOLLOW;
        }
 #endif
 
-       fd = SMB_VFS_OPEN(conn,fname,flags,mode);
+       fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode);
+       sav = errno;
 
-       DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname,
-               flags, (int)mode, fd, (fd == -1) ? strerror(errno) : "" ));
+       DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n",
+                   fname, flags, (int)mode, fsp->fh->fd,
+               (fsp->fh->fd == -1) ? strerror(errno) : "" ));
 
-       return fd;
+       errno = sav;
+       return fsp->fh->fd != -1;
 }
 
 /****************************************************************************
@@ -179,7 +184,7 @@ void change_owner_to_parent(connection_struct *conn,
  Open a file.
 ****************************************************************************/
 
-static BOOL open_file(files_struct *fsp,
+static NTSTATUS open_file(files_struct *fsp,
                        connection_struct *conn,
                        const char *fname,
                        SMB_STRUCT_STAT *psbuf,
@@ -210,7 +215,7 @@ static BOOL open_file(files_struct *fsp,
                /* It's a read-only share - fail if we wanted to write. */
                if(accmode != O_RDONLY) {
                        DEBUG(3,("Permission denied opening %s\n",fname));
-                       return False;
+                       return NT_STATUS_ACCESS_DENIED;
                } else if(flags & O_CREAT) {
                        /* We don't want to write - but we must make sure that
                           O_CREAT doesn't create the file if we have write
@@ -265,17 +270,15 @@ static BOOL open_file(files_struct *fsp,
                /* Don't create files with Microsoft wildcard characters. */
                if ((local_flags & O_CREAT) && !file_existed &&
                    ms_has_wild(fname))  {
-                       set_saved_ntstatus(NT_STATUS_OBJECT_NAME_INVALID);
-                       return False;
+                       return NT_STATUS_OBJECT_NAME_INVALID;
                }
 
                /* Actually do the open */
-               fsp->fh->fd = fd_open(conn, fname, local_flags, unx_mode);
-               if (fsp->fh->fd == -1)  {
+               if (!fd_open(conn, fname, fsp, local_flags, unx_mode)) {
                        DEBUG(3,("Error opening file %s (%s) (local_flags=%d) "
                                 "(flags=%d)\n",
                                 fname,strerror(errno),local_flags,flags));
-                       return False;
+                       return map_nt_error_from_unix(errno);
                }
 
                /* Inherit the ACL if the file was created. */
@@ -303,8 +306,9 @@ static BOOL open_file(files_struct *fsp,
 
                /* For a non-io open, this stat failing means file not found. JRA */
                if (ret == -1) {
+                       NTSTATUS status = map_nt_error_from_unix(errno);
                        fd_close(conn, fsp);
-                       return False;
+                       return status;
                }
        }
 
@@ -317,7 +321,7 @@ static BOOL open_file(files_struct *fsp,
        if(S_ISDIR(psbuf->st_mode)) {
                fd_close(conn, fsp);
                errno = EISDIR;
-               return False;
+               return NT_STATUS_FILE_IS_A_DIRECTORY;
        }
 
        fsp->mode = psbuf->st_mode;
@@ -351,7 +355,7 @@ static BOOL open_file(files_struct *fsp,
                 conn->num_files_open + 1));
 
        errno = 0;
-       return True;
+       return NT_STATUS_OK;
 }
 
 /*******************************************************************
@@ -894,8 +898,8 @@ static files_struct *fcb_or_dos_open(connection_struct *conn,
        }
 
        /* We need to duplicate this fsp. */
-       dup_fsp = dup_file_fsp(fsp, access_mask, share_access, create_options);
-       if (!dup_fsp) {
+       if (!NT_STATUS_IS_OK(dup_file_fsp(fsp, access_mask, share_access,
+                                         create_options, &dup_fsp))) {
                return NULL;
        }
 
@@ -1081,7 +1085,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, struct timeval requ
  Open a file with a share mode.
 ****************************************************************************/
 
-files_struct *open_file_ntcreate(connection_struct *conn,
+NTSTATUS open_file_ntcreate(connection_struct *conn,
                                 const char *fname,
                                 SMB_STRUCT_STAT *psbuf,
                                 uint32 access_mask,            /* access bits (FILE_READ_DATA etc.) */
@@ -1091,7 +1095,8 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                                 uint32 new_dos_attributes,     /* attributes used for new file. */
                                 int oplock_request,            /* internal Samba oplock codes. */
                                                                /* Information (FILE_EXISTS etc.) */
-                                int *pinfo)
+                                int *pinfo,
+                                files_struct **result)
 {
        int flags=0;
        int flags2=0;
@@ -1099,7 +1104,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
        BOOL def_acl = False;
        SMB_DEV_T dev = 0;
        SMB_INO_T inode = 0;
-       BOOL fsp_open = False;
+       NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED;
        files_struct *fsp = NULL;
        mode_t new_unx_mode = (mode_t)0;
        mode_t unx_mode = (mode_t)0;
@@ -1123,7 +1128,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
 
                DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname));
 
-               return print_fsp_open(conn, fname);
+               return print_fsp_open(conn, fname, &fsp);
        }
 
        /* We add aARCH to this as this mode is only used if the file is
@@ -1162,7 +1167,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
        }
 
        if (!check_name(fname,conn)) {
-               return NULL;
+               return map_nt_error_from_unix(errno);
        } 
 
        new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;
@@ -1181,11 +1186,12 @@ files_struct *open_file_ntcreate(connection_struct *conn,
        if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) {
                /* OS/2 Workplace shell fix may be main code stream in a later
                 * release. */ 
-               set_saved_error_triple(ERRDOS, ERRcannotopen,
-                                      NT_STATUS_OBJECT_NAME_NOT_FOUND);
                DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not "
                         "supported.\n"));
-               return NULL;
+               if (use_nt_status()) {
+                       return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+               }
+               return NT_STATUS_DOS(ERRDOS, ERRcannotopen);
        }
 
        switch( create_disposition ) {
@@ -1213,9 +1219,8 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                                DEBUG(5,("open_file_ntcreate: FILE_OPEN "
                                         "requested for file %s and file "
                                         "doesn't exist.\n", fname ));
-                               set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND);
                                errno = ENOENT;
-                               return NULL;
+                               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
                        }
                        break;
 
@@ -1226,9 +1231,8 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                                DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE "
                                         "requested for file %s and file "
                                         "doesn't exist.\n", fname ));
-                               set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND);
                                errno = ENOENT;
-                               return NULL;
+                               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
                        }
                        flags2 |= O_TRUNC;
                        break;
@@ -1245,7 +1249,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                                } else {
                                        errno = EEXIST;
                                }
-                               return NULL;
+                               return map_nt_error_from_unix(errno);
                        }
                        flags2 |= (O_CREAT|O_EXCL);
                        break;
@@ -1257,8 +1261,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                        break;
 
                default:
-                       set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER);
-                       return NULL;
+                       return NT_STATUS_INVALID_PARAMETER;
        }
 
        /* We only care about matching attributes on file exists and
@@ -1277,7 +1280,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                                 (unsigned int)psbuf->st_mode,
                                 (unsigned int)unx_mode ));
                        errno = EACCES;
-                       return NULL;
+                       return NT_STATUS_ACCESS_DENIED;
                }
        }
 
@@ -1334,14 +1337,13 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                DEBUG(5,("open_file_ntcreate: write access requested for "
                         "file %s on read only %s\n",
                         fname, !CAN_WRITE(conn) ? "share" : "file" ));
-               set_saved_ntstatus(NT_STATUS_ACCESS_DENIED);
                errno = EACCES;
-               return NULL;
+               return NT_STATUS_ACCESS_DENIED;
        }
 
-       fsp = file_new(conn);
-       if(!fsp) {
-               return NULL;
+       status = file_new(conn, &fsp);
+       if(!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        fsp->dev = psbuf->st_dev;
@@ -1367,8 +1369,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                if (lck == NULL) {
                        file_free(fsp);
                        DEBUG(0, ("Could not get share mode lock\n"));
-                       set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
-                       return NULL;
+                       return NT_STATUS_SHARING_VIOLATION;
                }
 
                /* First pass - send break only on batch oplocks. */
@@ -1376,7 +1377,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                        schedule_defer_open(lck, request_time);
                        TALLOC_FREE(lck);
                        file_free(fsp);
-                       return NULL;
+                       return NT_STATUS_SHARING_VIOLATION;
                }
 
                status = open_mode_check(conn, fname, lck,
@@ -1390,16 +1391,15 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                                schedule_defer_open(lck, request_time);
                                TALLOC_FREE(lck);
                                file_free(fsp);
-                               return NULL;
+                               return NT_STATUS_SHARING_VIOLATION;
                        }
                }
 
                if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
                        /* DELETE_PENDING is not deferred for a second */
-                       set_saved_ntstatus(status);
                        TALLOC_FREE(lck);
                        file_free(fsp);
-                       return NULL;
+                       return status;
                }
 
                if (!NT_STATUS_IS_OK(status)) {
@@ -1424,7 +1424,8 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                                                *pinfo = FILE_WAS_OPENED;
                                        }
                                        conn->num_files_open++;
-                                       return fsp_dup;
+                                       *result = fsp_dup;
+                                       return NT_STATUS_OK;
                                }
                        }
 
@@ -1449,13 +1450,13 @@ files_struct *open_file_ntcreate(connection_struct *conn,
 
                        DEBUG(4,("open_file_ntcreate : share_mode deny - "
                                 "calling open_file with flags=0x%X "
-                                "flags2=0x%X mode=0%o returned %d\n",
+                                "flags2=0x%X mode=0%o returned %s\n",
                                 flags, (flags2&~(O_TRUNC|O_CREAT)),
-                                (unsigned int)unx_mode, (int)fsp_open ));
+                                (unsigned int)unx_mode, nt_errstr(fsp_open)));
 
-                       if (!fsp_open && errno) {
+                       if (!NT_STATUS_IS_OK(fsp_open) && errno) {
                                /* Default error. */
-                               set_saved_ntstatus(NT_STATUS_ACCESS_DENIED);
+                               status = NT_STATUS_ACCESS_DENIED;
                        }
 
                        /* 
@@ -1471,7 +1472,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
 
                                /* this is a hack to speed up torture tests
                                   in 'make test' */
-                               timeout_usecs = lp_parm_int(conn->service,
+                               timeout_usecs = lp_parm_int(SNUM(conn),
                                                            "smbd","sharedelay",
                                                            SHARING_VIOLATION_USEC_WAIT);
 
@@ -1502,16 +1503,16 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                        }
 
                        TALLOC_FREE(lck);
-                       if (fsp_open) {
+                       if (NT_STATUS_IS_OK(fsp_open)) {
                                fd_close(conn, fsp);
                                /*
                                 * We have detected a sharing violation here
                                 * so return the correct error code
                                 */
-                               set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
+                               status = NT_STATUS_SHARING_VIOLATION;
                        }
                        file_free(fsp);
-                       return NULL;
+                       return status;
                }
 
                /*
@@ -1542,12 +1543,12 @@ files_struct *open_file_ntcreate(connection_struct *conn,
        fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,
                             access_mask);
 
-       if (!fsp_open) {
+       if (!NT_STATUS_IS_OK(fsp_open)) {
                if (lck != NULL) {
                        TALLOC_FREE(lck);
                }
                file_free(fsp);
-               return NULL;
+               return fsp_open;
        }
 
        if (!file_existed) { 
@@ -1578,8 +1579,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                        DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname));
                        fd_close(conn, fsp);
                        file_free(fsp);
-                       set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
-                       return NULL;
+                       return NT_STATUS_SHARING_VIOLATION;
                }
 
                status = open_mode_check(conn, fname, lck,
@@ -1606,7 +1606,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                        defer_open(lck, request_time, timeval_zero(),
                                   &state);
                        TALLOC_FREE(lck);
-                       return NULL;
+                       return status;
                }
 
                /*
@@ -1642,10 +1642,11 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                 */
                if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) ||
                    (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) {
+                       status = map_nt_error_from_unix(errno);
                        TALLOC_FREE(lck);
                        fd_close(conn,fsp);
                        file_free(fsp);
-                       return NULL;
+                       return status;
                }
        }
 
@@ -1692,16 +1693,15 @@ files_struct *open_file_ntcreate(connection_struct *conn,
 
                /* Handle strange delete on close create semantics. */
                if (create_options & FILE_DELETE_ON_CLOSE) {
-                       NTSTATUS result = can_set_delete_on_close(fsp, True, new_dos_attributes);
+                       status = can_set_delete_on_close(fsp, True, new_dos_attributes);
 
-                       if (!NT_STATUS_IS_OK(result)) {
+                       if (!NT_STATUS_IS_OK(status)) {
                                /* Remember to delete the mode we just added. */
                                del_share_mode(lck, fsp);
                                TALLOC_FREE(lck);
                                fd_close(conn,fsp);
                                file_free(fsp);
-                               set_saved_ntstatus(result);
-                               return NULL;
+                               return status;
                        }
                        /* Note that here we set the *inital* delete on close flag,
                           not the regular one. */
@@ -1770,31 +1770,32 @@ files_struct *open_file_ntcreate(connection_struct *conn,
 
        conn->num_files_open++;
 
-       return fsp;
+       *result = fsp;
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
  Open a file for for write to ensure that we can fchmod it.
 ****************************************************************************/
 
-files_struct *open_file_fchmod(connection_struct *conn, const char *fname,
-                              SMB_STRUCT_STAT *psbuf)
+NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname,
+                         SMB_STRUCT_STAT *psbuf, files_struct **result)
 {
        files_struct *fsp = NULL;
-       BOOL fsp_open;
+       NTSTATUS status;
 
        if (!VALID_STAT(*psbuf)) {
-               return NULL;
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       fsp = file_new(conn);
-       if(!fsp) {
-               return NULL;
+       status = file_new(conn, &fsp);
+       if(!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        /* note! we must use a non-zero desired access or we don't get
            a real file descriptor. Oh what a twisted web we weave. */
-       fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA);
+       status = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA);
 
        /* 
         * This is not a user visible file open.
@@ -1802,12 +1803,13 @@ files_struct *open_file_fchmod(connection_struct *conn, const char *fname,
         * the conn->num_files_open.
         */
 
-       if (!fsp_open) {
+       if (!NT_STATUS_IS_OK(status)) {
                file_free(fsp);
-               return NULL;
+               return status;
        }
 
-       return fsp;
+       *result = fsp;
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
@@ -1825,14 +1827,15 @@ int close_file_fchmod(files_struct *fsp)
  Open a directory from an NT SMB call.
 ****************************************************************************/
 
-files_struct *open_directory(connection_struct *conn,
+NTSTATUS open_directory(connection_struct *conn,
                                const char *fname,
                                SMB_STRUCT_STAT *psbuf,
                                uint32 access_mask,
                                uint32 share_access,
                                uint32 create_disposition,
                                uint32 create_options,
-                               int *pinfo)
+                               int *pinfo,
+                               files_struct **result)
 {
        files_struct *fsp = NULL;
        BOOL dir_existed = VALID_STAT(*psbuf) ? True : False;
@@ -1852,8 +1855,7 @@ files_struct *open_directory(connection_struct *conn,
 
        if (is_ntfs_stream_name(fname)) {
                DEBUG(0,("open_directory: %s is a stream name!\n", fname ));
-               set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY);
-               return NULL;
+               return NT_STATUS_NOT_A_DIRECTORY;
        }
 
        switch( create_disposition ) {
@@ -1864,8 +1866,7 @@ files_struct *open_directory(connection_struct *conn,
                                DEBUG(5,("open_directory: FILE_OPEN requested "
                                         "for directory %s and it doesn't "
                                         "exist.\n", fname ));
-                               set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND);
-                               return NULL;
+                               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
                        }
                        info = FILE_WAS_OPENED;
                        break;
@@ -1877,9 +1878,12 @@ files_struct *open_directory(connection_struct *conn,
                                DEBUG(5,("open_directory: FILE_CREATE "
                                         "requested for directory %s and it "
                                         "already exists.\n", fname ));
-                               set_saved_error_triple(ERRDOS, ERRfilexists,
-                                                      NT_STATUS_OBJECT_NAME_COLLISION);
-                               return NULL;
+                               if (use_nt_status()) {
+                                       return NT_STATUS_OBJECT_NAME_COLLISION;
+                               } else {
+                                       return NT_STATUS_DOS(ERRDOS,
+                                                            ERRfilexists);
+                               }
                        }
                        create_dir = True;
                        info = FILE_WAS_CREATED;
@@ -1903,8 +1907,7 @@ files_struct *open_directory(connection_struct *conn,
                        DEBUG(5,("open_directory: invalid create_disposition "
                                 "0x%x for directory %s\n",
                                 (unsigned int)create_disposition, fname));
-                       set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER);
-                       return NULL;
+                       return NT_STATUS_INVALID_PARAMETER;
        }
 
        if (create_dir) {
@@ -1921,27 +1924,26 @@ files_struct *open_directory(connection_struct *conn,
                                 "Error was %s\n", fname, strerror(errno) ));
                        /* Ensure we return the correct NT status to the
                         * client. */
-                       set_saved_error_triple(0, 0, status);
-                       return NULL;
+                       return status;
                }
 
                /* Ensure we're checking for a symlink here.... */
                /* We don't want to get caught by a symlink racer. */
 
                if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) {
-                       return NULL;
+                       return map_nt_error_from_unix(errno);
                }
 
                if(!S_ISDIR(psbuf->st_mode)) {
                        DEBUG(0,("open_directory: %s is not a directory !\n",
                                 fname ));
-                       return NULL;
+                       return NT_STATUS_NOT_A_DIRECTORY;
                }
        }
 
-       fsp = file_new(conn);
-       if(!fsp) {
-               return NULL;
+       status = file_new(conn, &fsp);
+       if(!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        /*
@@ -1953,7 +1955,7 @@ files_struct *open_directory(connection_struct *conn,
        fsp->dev = psbuf->st_dev;
        fsp->vuid = current_user.vuid;
        fsp->file_pid = global_smbpid;
-       fsp->can_lock = True;
+       fsp->can_lock = False;
        fsp->can_read = False;
        fsp->can_write = False;
 
@@ -1976,8 +1978,7 @@ files_struct *open_directory(connection_struct *conn,
        if (lck == NULL) {
                DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname));
                file_free(fsp);
-               set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
-               return NULL;
+               return NT_STATUS_SHARING_VIOLATION;
        }
 
        status = open_mode_check(conn, fname, lck,
@@ -1985,10 +1986,9 @@ files_struct *open_directory(connection_struct *conn,
                                create_options, &dir_existed);
 
        if (!NT_STATUS_IS_OK(status)) {
-               set_saved_ntstatus(status);
                TALLOC_FREE(lck);
                file_free(fsp);
-               return NULL;
+               return status;
        }
 
        set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK);
@@ -1998,10 +1998,9 @@ files_struct *open_directory(connection_struct *conn,
        if (create_options & FILE_DELETE_ON_CLOSE) {
                status = can_set_delete_on_close(fsp, True, 0);
                if (!NT_STATUS_IS_OK(status)) {
-                       set_saved_ntstatus(status);
                        TALLOC_FREE(lck);
                        file_free(fsp);
-                       return NULL;
+                       return status;
                }
 
                set_delete_on_close_token(lck, &current_user.ut);
@@ -2022,28 +2021,33 @@ files_struct *open_directory(connection_struct *conn,
 
        conn->num_files_open++;
 
-       return fsp;
+       *result = fsp;
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
  Open a pseudo-file (no locking checks - a 'stat' open).
 ****************************************************************************/
 
-files_struct *open_file_stat(connection_struct *conn, char *fname,
-                            SMB_STRUCT_STAT *psbuf)
+NTSTATUS open_file_stat(connection_struct *conn, char *fname,
+                       SMB_STRUCT_STAT *psbuf, files_struct **result)
 {
        files_struct *fsp = NULL;
+       NTSTATUS status;
 
-       if (!VALID_STAT(*psbuf))
-               return NULL;
+       if (!VALID_STAT(*psbuf)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
        /* Can't 'stat' open directories. */
-       if(S_ISDIR(psbuf->st_mode))
-               return NULL;
+       if(S_ISDIR(psbuf->st_mode)) {
+               return NT_STATUS_FILE_IS_A_DIRECTORY;
+       }
 
-       fsp = file_new(conn);
-       if(!fsp)
-               return NULL;
+       status = file_new(conn, &fsp);
+       if(!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
        DEBUG(5,("open_file_stat: 'opening' file %s\n", fname));
 
@@ -2069,7 +2073,8 @@ files_struct *open_file_stat(connection_struct *conn, char *fname,
 
        conn->num_files_open++;
 
-       return fsp;
+       *result = fsp;
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
index 73b0ebb4b32f1b3e300bf69ac3287fbefa78d338..389086e9bf7a840b1bc87fa884a0edb449abf266 100644 (file)
@@ -29,9 +29,6 @@ static user_struct *validated_users;
 static int next_vuid = VUID_OFFSET;
 static int num_validated_vuids;
 
-extern userdom_struct current_user_info;
-
-
 /****************************************************************************
  Check if a uid has been validated, and return an pointer to the user_struct
  if it has. NULL if not. vuid is biased by an offset. This allows us to
@@ -550,9 +547,11 @@ static BOOL user_ok(const char *user, int snum)
                str_list_copy(&invalid, lp_invalid_users(snum));
                if (invalid &&
                    str_list_substitute(invalid, "%S", lp_servicename(snum))) {
-                       if ( invalid &&
-                            str_list_sub_basic(invalid,
-                                               current_user_info.smb_name) ) {
+
+                       /* This is used in sec=share only, so no current user
+                        * around to pass to str_list_sub_basic() */
+
+                       if ( invalid && str_list_sub_basic(invalid, "", "") ) {
                                ret = !user_in_list(user,
                                                    (const char **)invalid);
                        }
@@ -565,9 +564,11 @@ static BOOL user_ok(const char *user, int snum)
                str_list_copy(&valid, lp_valid_users(snum));
                if ( valid &&
                     str_list_substitute(valid, "%S", lp_servicename(snum)) ) {
-                       if ( valid &&
-                            str_list_sub_basic(valid,
-                                               current_user_info.smb_name) ) {
+
+                       /* This is used in sec=share only, so no current user
+                        * around to pass to str_list_sub_basic() */
+
+                       if ( valid && str_list_sub_basic(valid, "", "") ) {
                                ret = user_in_list(user, (const char **)valid);
                        }
                }
index 2d90383706b7ad3701271fca0c2de1f967816f41..52660da2ffe405b35625fc8c7d3728c1fcb1620a 100644 (file)
 #define        PIPE            "\\PIPE\\"
 #define        PIPELEN         strlen(PIPE)
 
+#define MAX_PIPE_NAME_LEN      24
+
+/* PIPE/<name>/<pid>/<pnum> */
+#define PIPEDB_KEY_FORMAT "PIPE/%s/%u/%d"
+
+struct pipe_dbrec {
+       struct process_id pid;
+       int pnum;
+       uid_t uid;
+
+       char name[MAX_PIPE_NAME_LEN];
+       fstring user;
+};
+
+
 extern struct pipe_id_info pipe_names[];
 
 /****************************************************************************
@@ -284,6 +299,8 @@ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf)
        if (!close_rpc_pipe_hnd(p)) {
                return ERROR_DOS(ERRDOS,ERRbadfid);
        }
+       
+       /* TODO: REMOVE PIPE FROM DB */
 
        return(outsize);
 }
index 6e403dba92ad062d917007a83f6d2660da12d883..73744cf26e77b0e7e66416b2863db07ca2e5fa8a 100644 (file)
@@ -3043,8 +3043,7 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_
                return -1;
        }
 
-       fsp = open_file_fchmod(conn,fname,&st);
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,&st,&fsp))) {
                return -1;
        }
 
@@ -4236,12 +4235,19 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
        pstring filename;
        
        ZERO_STRUCT( conn );
-       conn.service = -1;
        
        if ( !(conn.mem_ctx = talloc_init( "novfs_get_nt_acl" )) ) {
                DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
                return NULL;
        }
+
+       if (!(conn.params = TALLOC_P(conn.mem_ctx, struct share_params))) {
+               DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
+               TALLOC_FREE(conn.mem_ctx);
+               return NULL;
+       }
+
+       conn.params->service = -1;
        
        pstrcpy( path, "/" );
        set_conn_connectpath(&conn, path);
index b3ce49360d836ef438258c2d912de69f00e22183..ce352adfd7d079f7c6d7d7a8f8790a15caf8d6a8 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "includes.h"
 
-extern uint16 global_smbpid;
+uint16 global_smbpid;
 extern int keepalive;
 extern struct auth_context *negprot_global_auth_context;
 extern int smb_echo_count;
@@ -172,7 +172,6 @@ BOOL open_was_deferred(uint16 mid)
 
        for (pml = deferred_open_queue; pml; pml = pml->next) {
                if (SVAL(pml->buf.data,smb_mid) == mid) {
-                       set_saved_ntstatus(NT_STATUS_OK);
                        return True;
                }
        }
@@ -459,11 +458,20 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
                }
        }
        
-       maxfd = select_on_fd(smbd_server_fd(), maxfd, &fds);
-       maxfd = select_on_fd(change_notify_fd(), maxfd, &fds);
-       maxfd = select_on_fd(oplock_notify_fd(), maxfd, &fds);
+       {
+               int sav;
+               START_PROFILE(smbd_idle);
+
+               maxfd = select_on_fd(smbd_server_fd(), maxfd, &fds);
+               maxfd = select_on_fd(change_notify_fd(), maxfd, &fds);
+               maxfd = select_on_fd(oplock_notify_fd(), maxfd, &fds);
 
-       selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to);
+               selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to);
+               sav = errno;
+
+               END_PROFILE(smbd_idle);
+               errno = sav;
+       }
 
        /* if we get EINTR then maybe we have received an oplock
           signal - treat this as select returning 1. This is ugly, but
@@ -885,7 +893,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
                pid = sys_getpid();
 
        errno = 0;
-       set_saved_ntstatus(NT_STATUS_OK);
 
        last_message = type;
 
@@ -954,7 +961,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
                        }
 
                        if (!change_to_user(conn,session_tag)) {
-                               return(ERROR_FORCE_DOS(ERRSRV,ERRbaduid));
+                               return(ERROR_NT(NT_STATUS_DOS(ERRSRV,ERRbaduid)));
                        }
 
                        /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
index e68e8662d74f2a236e3851f104e6e10cd67eb103..ff3c6832e4f33c1cd1eb047e8285166858b5dabf 100644 (file)
@@ -427,6 +427,7 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de
        } else {
                *err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
        }
+
        return ret;
 }
 
@@ -453,6 +454,7 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len
        } else {
                *err = check_path_syntax(dest, tmppath);
        }
+
        return ret;
 }
 
@@ -809,6 +811,14 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBchkpth);
+
+               /* Strange DOS error code semantics only for chkpth... */
+               if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
+                       if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
+                               /* We need to map to ERRbadpath */
+                               status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+                       }
+               }
                return ERROR_NT(status);
        }
 
@@ -1370,25 +1380,25 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
                        &access_mask, &share_mode, &create_disposition, &create_options)) {
                END_PROFILE(SMBopen);
-               return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
+               return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
        }
 
-       fsp = open_file_ntcreate(conn,fname,&sbuf,
+       status = open_file_ntcreate(conn,fname,&sbuf,
                        access_mask,
                        share_mode,
                        create_disposition,
                        create_options,
                        dos_attr,
                        oplock_request,
-                       &info);
+                       &info, &fsp);
 
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBopen);
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                        /* We have re-scheduled this call. */
                        return -1;
                }
-               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
+               return ERROR_NT(status);
        }
 
        size = sbuf.st_size;
@@ -1493,25 +1503,25 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                                &create_disposition,
                                &create_options)) {
                END_PROFILE(SMBopenX);
-               return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
+               return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
        }
 
-       fsp = open_file_ntcreate(conn,fname,&sbuf,
+       status = open_file_ntcreate(conn,fname,&sbuf,
                        access_mask,
                        share_mode,
                        create_disposition,
                        create_options,
                        smb_attr,
                        oplock_request,
-                       &smb_action);
+                       &smb_action, &fsp);
       
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBopenX);
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                        /* We have re-scheduled this call. */
                        return -1;
                }
-               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
+               return ERROR_NT(status);
        }
 
        size = sbuf.st_size;
@@ -1672,22 +1682,22 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        }
 
        /* Open file using ntcreate. */
-       fsp = open_file_ntcreate(conn,fname,&sbuf,
+       status = open_file_ntcreate(conn,fname,&sbuf,
                                access_mask,
                                share_mode,
                                create_disposition,
                                create_options,
                                fattr,
                                oplock_request,
-                               NULL);
+                               NULL, &fsp);
   
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcreate);
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                        /* We have re-scheduled this call. */
                        return -1;
                }
-               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
+               return ERROR_NT(status);
        }
  
        outsize = set_message(outbuf,1,0,True);
@@ -1756,25 +1766,25 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        SMB_VFS_STAT(conn,fname,&sbuf);
 
        /* We should fail if file does not exist. */
-       fsp = open_file_ntcreate(conn,fname,&sbuf,
+       status = open_file_ntcreate(conn,fname,&sbuf,
                                FILE_GENERIC_READ | FILE_GENERIC_WRITE,
                                FILE_SHARE_READ|FILE_SHARE_WRITE,
                                FILE_OPEN,
                                0,
                                fattr,
                                oplock_request,
-                               NULL);
+                               NULL, &fsp);
 
        /* close fd from smb_mkstemp() */
        close(tmpfd);
 
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBctemp);
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                        /* We have re-scheduled this call. */
                        return -1;
                }
-               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
+               return ERROR_NT(status);
        }
 
        outsize = set_message(outbuf,1,0,True);
@@ -1822,6 +1832,7 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype,
 {
        files_struct *fsp;
        uint32 fmode;
+       NTSTATUS status;
 
        if (!CAN_WRITE(conn)) {
                return NT_STATUS_MEDIA_WRITE_PROTECTED;
@@ -1836,25 +1847,16 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype,
                return NT_STATUS_OK;
        }
 
-       /* We need a better way to return NT status codes from open... */
-       set_saved_ntstatus(NT_STATUS_OK);
-
-       fsp = open_file_ntcreate(conn, fname, pst,
+       status = open_file_ntcreate(conn, fname, pst,
                                DELETE_ACCESS,
                                FILE_SHARE_READ|FILE_SHARE_WRITE,
                                FILE_OPEN,
                                0,
                                FILE_ATTRIBUTE_NORMAL,
                                0,
-                               NULL);
+                               NULL, &fsp);
 
-       if (!fsp) {
-               NTSTATUS ret = get_saved_ntstatus();
-               if (!NT_STATUS_IS_OK(ret)) {
-                       set_saved_ntstatus(NT_STATUS_OK);
-                       return ret;
-               }
-               set_saved_ntstatus(NT_STATUS_OK);
+       if (!NT_STATUS_IS_OK(status)) {
                return NT_STATUS_ACCESS_DENIED;
        }
        close_file(fsp,NORMAL_CLOSE);
@@ -1870,6 +1872,7 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b
        SMB_STRUCT_STAT sbuf;
        uint32 fattr;
        files_struct *fsp;
+       NTSTATUS status;
 
        DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
 
@@ -1929,26 +1932,17 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b
                /* On open checks the open itself will check the share mode, so
                   don't do it here as we'll get it wrong. */
 
-               /* We need a better way to return NT status codes from open... */
-               set_saved_ntstatus(NT_STATUS_OK);
-
-               fsp = open_file_ntcreate(conn, fname, &sbuf,
+               status = open_file_ntcreate(conn, fname, &sbuf,
                                        DELETE_ACCESS,
                                        FILE_SHARE_NONE,
                                        FILE_OPEN,
                                        0,
                                        FILE_ATTRIBUTE_NORMAL,
                                        0,
-                                       NULL);
+                                       NULL, &fsp);
 
-               if (!fsp) {
-                       NTSTATUS ret = get_saved_ntstatus();
-                       if (!NT_STATUS_IS_OK(ret)) {
-                               set_saved_ntstatus(NT_STATUS_OK);
-                               return ret;
-                       }
-                       set_saved_ntstatus(NT_STATUS_OK);
-                       return NT_STATUS_ACCESS_DENIED;
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
                }
                close_file(fsp,NORMAL_CLOSE);
        }
@@ -1994,8 +1988,8 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B
         * Tine Smukavec <valentin.smukavec@hermes.si>.
         */
        
-       if (!rc && mangle_is_mangled(mask,SNUM(conn)))
-               mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
+       if (!rc && mangle_is_mangled(mask,conn->params))
+               mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
        
        if (!has_wild) {
                pstrcat(directory,"/");
@@ -2331,7 +2325,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
        /* ensure we don't overrun the packet size */
        maxcount = MIN(65535,maxcount);
 
-       if (!is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+       if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
                SMB_STRUCT_STAT st;
                SMB_OFF_T size = 0;
   
@@ -2403,7 +2397,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
         */
        
        status = do_lock_spin(fsp,
-                               SVAL(inbuf,smb_pid), 
+                               (uint32)SVAL(inbuf,smb_pid), 
                                (SMB_BIG_UINT)numtoread,
                                (SMB_BIG_UINT)startpos,
                                WRITE_LOCK,
@@ -2510,7 +2504,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
 
        data = smb_buf(outbuf) + 3;
   
-       if (is_locked(fsp,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
                END_PROFILE(SMBread);
                return ERROR_DOS(ERRDOS,ERRlock);
        }
@@ -2717,7 +2711,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
 
        }
 
-       if (is_locked(fsp,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
                END_PROFILE(SMBreadX);
                return ERROR_DOS(ERRDOS,ERRlock);
        }
@@ -2780,7 +2774,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
        SCVAL(inbuf,smb_com,SMBwritec);
        SCVAL(outbuf,smb_com,SMBwritec);
 
-       if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
                END_PROFILE(SMBwritebraw);
                return(ERROR_DOS(ERRDOS,ERRlock));
        }
@@ -2901,7 +2895,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
        startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
        data = smb_buf(inbuf) + 3;
   
-       if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+       if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
                END_PROFILE(SMBwriteunlock);
                return ERROR_DOS(ERRDOS,ERRlock);
        }
@@ -2924,7 +2918,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
 
        if (numtowrite) {
                status = do_unlock(fsp,
-                               SVAL(inbuf,smb_pid),
+                               (uint32)SVAL(inbuf,smb_pid),
                                (SMB_BIG_UINT)numtowrite, 
                                (SMB_BIG_UINT)startpos,
                                WINDOWS_LOCK);
@@ -2978,7 +2972,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
        startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
        data = smb_buf(inbuf) + 3;
   
-       if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
                END_PROFILE(SMBwrite);
                return ERROR_DOS(ERRDOS,ERRlock);
        }
@@ -3093,7 +3087,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
 #endif /* LARGE_SMB_OFF_T */
        }
 
-       if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
                END_PROFILE(SMBwriteX);
                return ERROR_DOS(ERRDOS,ERRlock);
        }
@@ -3368,7 +3362,7 @@ int reply_writeclose(connection_struct *conn,
        mtime = srv_make_unix_date3(inbuf+smb_vwv4);
        data = smb_buf(inbuf) + 1;
   
-       if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+       if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
                END_PROFILE(SMBwriteclose);
                return ERROR_DOS(ERRDOS,ERRlock);
        }
@@ -3439,7 +3433,7 @@ int reply_lock(connection_struct *conn,
                 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
 
        status = do_lock_spin(fsp,
-                               SVAL(inbuf,smb_pid),
+                               (uint32)SVAL(inbuf,smb_pid),
                                count,
                                offset,
                                WRITE_LOCK,
@@ -3494,7 +3488,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
        offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
        
        status = do_unlock(fsp,
-                       SVAL(inbuf,smb_pid),
+                       (uint32)SVAL(inbuf,smb_pid),
                        count,
                        offset,
                        WINDOWS_LOCK);
@@ -3598,6 +3592,8 @@ int reply_printopen(connection_struct *conn,
 {
        int outsize = 0;
        files_struct *fsp;
+       NTSTATUS status;
+       
        START_PROFILE(SMBsplopen);
        
        if (!CAN_PRINT(conn)) {
@@ -3606,11 +3602,11 @@ int reply_printopen(connection_struct *conn,
        }
 
        /* Open for exclusive use, write only. */
-       fsp = print_fsp_open(conn, NULL);
+       status = print_fsp_open(conn, NULL, &fsp);
 
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBsplopen);
-               return(UNIXERROR(ERRDOS,ERRnoaccess));
+               return(ERROR_NT(status));
        }
 
        outsize = set_message(outbuf,1,0,True);
@@ -3838,6 +3834,17 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
 
        status = mkdir_internal(conn, directory,bad_path);
        if (!NT_STATUS_IS_OK(status)) {
+
+               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION) &&
+                   !use_nt_status()) {
+                       /*
+                        * Yes, in the DOS error code case we get a
+                        * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
+                        * samba4 torture test.
+                        */
+                       status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
+               }
+
                END_PROFILE(SMBmkdir);
                return ERROR_NT(status);
        }
@@ -4408,14 +4415,14 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui
         * Tine Smukavec <valentin.smukavec@hermes.si>.
         */
 
-       if (!rc && mangle_is_mangled(mask,SNUM(conn)))
-               mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
+       if (!rc && mangle_is_mangled(mask, conn->params))
+               mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
 
        if (!has_wild) {
                /*
                 * No wildcards - just process the one file.
                 */
-               BOOL is_short_name = mangle_is_8_3(name, True, SNUM(conn));
+               BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
 
                /* Add a terminating '/' to the directory name. */
                pstrcat(directory,"/");
@@ -4739,6 +4746,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
        pstring dest;
        uint32 dosattrs;
        uint32 new_create_disposition;
+       NTSTATUS status;
  
        *err_ret = 0;
 
@@ -4767,16 +4775,16 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
                }
        }
 
-       fsp1 = open_file_ntcreate(conn,src,&src_sbuf,
+       status = open_file_ntcreate(conn,src,&src_sbuf,
                        FILE_GENERIC_READ,
                        FILE_SHARE_READ|FILE_SHARE_WRITE,
                        FILE_OPEN,
                        0,
                        FILE_ATTRIBUTE_NORMAL,
                        INTERNAL_OPEN_ONLY,
-                       NULL);
+                       NULL, &fsp1);
 
-       if (!fsp1) {
+       if (!NT_STATUS_IS_OK(status)) {
                return(False);
        }
 
@@ -4785,16 +4793,16 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
                ZERO_STRUCTP(&sbuf2);
        }
 
-       fsp2 = open_file_ntcreate(conn,dest,&sbuf2,
+       status = open_file_ntcreate(conn,dest,&sbuf2,
                        FILE_GENERIC_WRITE,
                        FILE_SHARE_READ|FILE_SHARE_WRITE,
                        new_create_disposition,
                        0,
                        dosattrs,
                        INTERNAL_OPEN_ONLY,
-                       NULL);
+                       NULL, &fsp2);
 
-       if (!fsp2) {
+       if (!NT_STATUS_IS_OK(status)) {
                close_file(fsp1,ERROR_CLOSE);
                return(False);
        }
@@ -4926,8 +4934,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
         * Tine Smukavec <valentin.smukavec@hermes.si>.
         */
 
-       if (!rc && mangle_is_mangled(mask, SNUM(conn)))
-               mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
+       if (!rc && mangle_is_mangled(mask, conn->params))
+               mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
 
        has_wild = path_contains_wcard1;
 
@@ -4995,8 +5003,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                        END_PROFILE(SMBcopy);
                        return ERROR_DOS(ERRDOS,error);
                } else {
-                       if((errno == ENOENT) && (bad_path1 || bad_path2)) {
-                               set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
+                       if((errno == ENOENT) && (bad_path1 || bad_path2) &&
+                          !use_nt_status()) {
+                               /* Samba 3.0.22 has ERRDOS/ERRbadpath in the
+                                * DOS error code case
+                                */
+                               return ERROR_DOS(ERRDOS, ERRbadpath);
                        }
                        END_PROFILE(SMBcopy);
                        return(UNIXERROR(ERRDOS,error));
@@ -5067,12 +5079,12 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
  Get a lock pid, dealing with large count requests.
 ****************************************************************************/
 
-uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
+uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
 {
        if(!large_file_format)
-               return SVAL(data,SMB_LPID_OFFSET(data_offset));
+               return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
        else
-               return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
+               return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
 }
 
 /****************************************************************************
@@ -5209,7 +5221,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
        uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
        uint16 num_locks = SVAL(inbuf,smb_vwv7);
        SMB_BIG_UINT count = 0, offset = 0;
-       uint16 lock_pid;
+       uint32 lock_pid;
        int32 lock_timeout = IVAL(inbuf,smb_vwv4);
        int i;
        char *data;
@@ -5229,7 +5241,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                /* we don't support these - and CANCEL_LOCK makes w2k
                   and XP reboot so I don't really want to be
                   compatible! (tridge) */
-               return ERROR_FORCE_DOS(ERRDOS, ERRnoatomiclocks);
+               return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
        }
        
        if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
@@ -5505,7 +5517,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
        tcount = maxcount;
        total_read = 0;
 
-       if (is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
                END_PROFILE(SMBreadBmpx);
                return ERROR_DOS(ERRDOS,ERRlock);
        }
@@ -5637,7 +5649,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
                not an SMBwritebmpx - set this up now so we don't forget */
        SCVAL(outbuf,smb_com,SMBwritec);
 
-       if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
+       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
                END_PROFILE(SMBwriteBmpx);
                return(ERROR_DOS(ERRDOS,ERRlock));
        }
index 2bfeae9f5412579c98a48d3cd3a74be972601c14..0fba6af69700d5e65b6701371a5250b064f07c49 100644 (file)
@@ -912,18 +912,12 @@ void build_options(BOOL screen);
        if (!message_init())
                exit(1);
 
-       /* Initialize our global sam sid first -- quite a lot of the other
-        * initialization routines further down depend on it.
-        */
-
        /* Initialise the password backed before the global_sam_sid
           to ensure that we fetch from ldap before we make a domain sid up */
 
        if(!initialize_password_db(False))
                exit(1);
 
-       /* Fail gracefully if we can't open secrets.tdb */
-
        if (!secrets_init()) {
                DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n"));
                exit(1);
index cb9bfcc27aec90be12d8a1c79e9bf44446345f99..9dcb8a354f416625c2c290fe2dd43d822bc9b4c1 100644 (file)
@@ -371,35 +371,38 @@ static NTSTATUS find_forced_user(int snum, BOOL vuser_is_guest,
 {
        TALLOC_CTX *mem_ctx;
        char *fuser, *found_username;
+       struct nt_user_token *tmp_token;
        NTSTATUS result;
 
-       mem_ctx = talloc_new(NULL);
-       if (mem_ctx == NULL) {
+       if (!(mem_ctx = talloc_new(NULL))) {
                DEBUG(0, ("talloc_new failed\n"));
                return NT_STATUS_NO_MEMORY;
        }
 
-       fuser = talloc_string_sub(mem_ctx, lp_force_user(snum), "%S",
-                                 lp_servicename(snum));
-       if (fuser == NULL) {
-               result = NT_STATUS_NO_MEMORY;
-               goto done;
+       if (!(fuser = talloc_string_sub(mem_ctx, lp_force_user(snum), "%S",
+                                       lp_servicename(snum)))) {
+               TALLOC_FREE(mem_ctx);
+               return NT_STATUS_NO_MEMORY;
+               
        }
 
        result = create_token_from_username(mem_ctx, fuser, vuser_is_guest,
                                            uid, gid, &found_username,
-                                           token);
+                                           &tmp_token);
        if (!NT_STATUS_IS_OK(result)) {
-               goto done;
+               TALLOC_FREE(mem_ctx);
+               return result;
+       }
+
+       if (!(*token = dup_nt_token(NULL, tmp_token))) {
+               TALLOC_FREE(mem_ctx);
+               return NT_STATUS_NO_MEMORY;
        }
 
-       talloc_steal(NULL, *token);
        fstrcpy(username, found_username);
 
-       result = NT_STATUS_OK;
- done:
        TALLOC_FREE(mem_ctx);
-       return result;
+       return NT_STATUS_OK;
 }
 
 /*
@@ -620,7 +623,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                    sizeof(conn->client_address)-1);
        conn->num_files_open = 0;
        conn->lastused = conn->lastused_count = time(NULL);
-       conn->service = snum;
+       conn->params->service = snum;
        conn->used = True;
        conn->printer = (strncmp(dev,"LPT",3) == 0);
        conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
@@ -646,7 +649,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
        string_set(&conn->dirpath,"");
        string_set(&conn->user,user);
 
-       conn->read_only = lp_readonly(conn->service);
+       conn->read_only = lp_readonly(SNUM(conn));
        conn->admin_user = False;
 
        /*
@@ -746,7 +749,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));
+               standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                                     conn->connectpath, conn->gid,
+                                     get_current_username(),
+                                     current_user_info.domain,
+                                     s, sizeof(s));
                set_conn_connectpath(conn,s);
                DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
                         lp_servicename(snum)));
@@ -821,7 +828,11 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
        if (*lp_rootpreexec(snum)) {
                pstring cmd;
                pstrcpy(cmd,lp_rootpreexec(snum));
-               standard_sub_conn(conn,cmd,sizeof(cmd));
+               standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                                     conn->connectpath, conn->gid,
+                                     get_current_username(),
+                                     current_user_info.domain,
+                                     cmd, sizeof(cmd));
                DEBUG(5,("cmd=%s\n",cmd));
                ret = smbrun(cmd,NULL);
                if (ret != 0 && lp_rootpreexec_close(snum)) {
@@ -854,7 +865,11 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
        if (*lp_preexec(snum)) {
                pstring cmd;
                pstrcpy(cmd,lp_preexec(snum));
-               standard_sub_conn(conn,cmd,sizeof(cmd));
+               standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                                     conn->connectpath, conn->gid,
+                                     get_current_username(),
+                                     current_user_info.domain,
+                                     cmd, sizeof(cmd));
                ret = smbrun(cmd,NULL);
                if (ret != 0 && lp_preexec_close(snum)) {
                        DEBUG(1,("preexec gave %d - failing connection\n",
@@ -1148,7 +1163,11 @@ void close_cnum(connection_struct *conn, uint16 vuid)
            change_to_user(conn, vuid))  {
                pstring cmd;
                pstrcpy(cmd,lp_postexec(SNUM(conn)));
-               standard_sub_conn(conn,cmd,sizeof(cmd));
+               standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                                     conn->connectpath, conn->gid,
+                                     get_current_username(),
+                                     current_user_info.domain,
+                                     cmd, sizeof(cmd));
                smbrun(cmd,NULL);
                change_to_root_user();
        }
@@ -1158,7 +1177,11 @@ void close_cnum(connection_struct *conn, uint16 vuid)
        if (*lp_rootpostexec(SNUM(conn)))  {
                pstring cmd;
                pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
-               standard_sub_conn(conn,cmd,sizeof(cmd));
+               standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                                     conn->connectpath, conn->gid,
+                                     get_current_username(),
+                                     current_user_info.domain,
+                                     cmd, sizeof(cmd));
                smbrun(cmd,NULL);
        }
 
index 41f8fd0ed4363744a84e5899ce6a04e440fcce34..bcb840a3fe40b68a61405bf4a99de892503910a6 100644 (file)
@@ -1,8 +1,10 @@
 /* 
    Unix SMB/CIFS implementation.
    session handling for utmp and PAM
-   Copyright (C) tridge@samba.org 2001
-   Copyright (C) abartlet@pcug.org.au 2001
+
+   Copyright (C) tridge@samba.org       2001
+   Copyright (C) abartlet@samba.org     2001
+   Copyright (C) Gerald (Jerry) Carter  2006   
    
    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
@@ -29,6 +31,9 @@
 
 static TDB_CONTEXT *tdb;
 
+/********************************************************************
+********************************************************************/
+
 BOOL session_init(void)
 {
        if (tdb)
@@ -44,7 +49,10 @@ BOOL session_init(void)
        return True;
 }
 
-/* called when a session is created */
+/********************************************************************
+ called when a session is created
+********************************************************************/
+
 BOOL session_claim(user_struct *vuser)
 {
        int i = 0;
@@ -126,6 +134,7 @@ BOOL session_claim(user_struct *vuser)
        sessionid.gid = vuser->gid;
        fstrcpy(sessionid.remote_machine, get_remote_machine_name());
        fstrcpy(sessionid.ip_addr, client_addr());
+       sessionid.connect_start = time(NULL);
 
        client_ip = client_inaddr(&sa);
 
@@ -159,7 +168,10 @@ BOOL session_claim(user_struct *vuser)
        return True;
 }
 
-/* called when a session is destroyed */
+/********************************************************************
+ called when a session is destroyed
+********************************************************************/
+
 void session_yield(user_struct *vuser)
 {
        TDB_DATA dbuf;
@@ -198,6 +210,9 @@ void session_yield(user_struct *vuser)
        tdb_delete(tdb, key);
 }
 
+/********************************************************************
+********************************************************************/
+
 BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *),
                      void *state)
 {
@@ -210,32 +225,40 @@ BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *),
        return True;
 }
 
+/********************************************************************
+********************************************************************/
+
 struct session_list {
        int count;
        struct sessionid *sessions;
 };
 
-static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf,
-                             void *state)
+static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
 {
+       uint32 i;       
        struct session_list *sesslist = (struct session_list *) state;
        const struct sessionid *current = (const struct sessionid *) dbuf.dptr;
 
-       sesslist->count += 1;
-       sesslist->sessions = SMB_REALLOC_ARRAY(sesslist->sessions, struct sessionid,
-                                       sesslist->count);
+       i = sesslist->count;
+       
+       sesslist->sessions = SMB_REALLOC_ARRAY(sesslist->sessions, struct sessionid, i+1);
        if (!sesslist->sessions) {
                sesslist->count = 0;
                return -1;
        }
 
-       memcpy(&sesslist->sessions[sesslist->count - 1], current, 
-              sizeof(struct sessionid));
+       memcpy(&sesslist->sessions[i], current, sizeof(struct sessionid));
+       sesslist->count++;
+
        DEBUG(7,("gather_sessioninfo session from %s@%s\n", 
                 current->username, current->remote_machine));
+
        return 0;
 }
 
+/********************************************************************
+********************************************************************/
+
 int list_sessions(struct sessionid **session_list)
 {
        struct session_list sesslist;
index 468f61560b927c10fdea0181816b7c2de572ade7..5334976d8dc7d903e43fb23241bd57f495db1d74 100644 (file)
@@ -28,6 +28,8 @@
  * + and & may be combined
  */
 
+extern userdom_struct current_user_info;
+
 static BOOL do_group_checks(const char **name, const char **pattern)
 {
        if ((*name)[0] == '@') {
@@ -74,7 +76,8 @@ static BOOL token_contains_name(TALLOC_CTX *mem_ctx,
        enum SID_NAME_USE type;
 
        if (username != NULL) {
-               name = talloc_sub_basic(mem_ctx, username, name);
+               name = talloc_sub_basic(mem_ctx, username,
+                                       current_user_info.domain, name);
        }
        if (sharename != NULL) {
                name = talloc_string_sub(mem_ctx, name, "%S", sharename);
index 548d7c4a487b53cc237d7ae327d0ec0f03f7359f..b453fdd54471838749e64f50642870e50972fca5 100644 (file)
@@ -52,7 +52,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat
        if (!lp_stat_cache())
                return;
 
-       if (sc_size && (tdb_stat_cache->map_size > sc_size*1024)) {
+       if (sc_size && (tdb_map_size(tdb_stat_cache) > sc_size*1024)) {
                reset_stat_cache();
        }
 
@@ -291,12 +291,12 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath,
  JRA. Use a djb-algorithm hash for speed.
 ***************************************************************/
                                                                                                      
-u32 fast_string_hash(TDB_DATA *key)
+unsigned int fast_string_hash(TDB_DATA *key)
 {
-        u32 n = 0;
+        unsigned int n = 0;
         const char *p;
         for (p = key->dptr; *p != '\0'; p++) {
-                n = ((n << 5) + n) ^ (u32)(*p);
+                n = ((n << 5) + n) ^ (unsigned int)(*p);
         }
         return n;
 }
index 8f981a632888de290da7f1fc22fe081336014bb0..300b14a7c083d43d367d503ec34a6b46e9c495e5 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "includes.h"
 
-#if defined(LINUX)
+#if defined(LINUX) && defined(HAVE_FSID_INT)
 static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf)
 {
        struct statvfs statvfs_buf;
@@ -51,7 +51,7 @@ static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf)
 */
 int sys_statvfs(const char *path, vfs_statvfs_struct *statbuf)
 {
-#if defined(LINUX)
+#if defined(LINUX) && defined(HAVE_FSID_INT)
        return linux_statvfs(path, statbuf);
 #else
        /* BB change this to return invalid level */
index 9030737b1b4ac990e1cff557d5175f31f136d0fc..aca1fcd70e9aaab8f68ddd0dc4bc6957a3ce25cf 100644 (file)
@@ -837,16 +837,16 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
        }
 
-       fsp = open_file_ntcreate(conn,fname,&sbuf,
+       status = open_file_ntcreate(conn,fname,&sbuf,
                access_mask,
                share_mode,
                create_disposition,
                create_options,
                open_attr,
                oplock_request,
-               &smb_action);
+               &smb_action, &fsp);
       
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                talloc_destroy(ctx);
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                        /* We have re-scheduled this call. */
@@ -1070,7 +1070,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
        BOOL was_8_3;
        uint32 nt_extmode; /* Used for NT connections instead of mode */
        BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
-       BOOL check_mangled_names = lp_manglednames(SNUM(conn));
+       BOOL check_mangled_names = lp_manglednames(conn->params);
 
        *fname = 0;
        *out_of_space = False;
@@ -1117,7 +1117,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
                        got_match = mask_match(fname, mask, conn->case_sensitive);
 
-               if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
+               if(!got_match && check_mangled_names &&
+                  !mangle_is_8_3(fname, False, conn->params)) {
 
                        /*
                         * It turns out that NT matches wildcards against
@@ -1128,7 +1129,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
 
                        pstring newname;
                        pstrcpy( newname, fname);
-                       mangle_map( newname, True, False, SNUM(conn));
+                       mangle_map( newname, True, False, conn->params);
                        if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
                                got_match = mask_match(newname, mask, conn->case_sensitive);
                }
@@ -1202,7 +1203,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                }
        }
 
-       mangle_map(fname,False,True,SNUM(conn));
+       mangle_map(fname,False,True,conn->params);
 
        p = pdata;
        last_entry_ptr = p;
@@ -1338,7 +1339,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
 
                case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
                        DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
-                       was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
+                       was_8_3 = mangle_is_8_3(fname, True, conn->params);
                        p += 4;
                        SIVAL(p,0,reskey); p += 4;
                        put_long_date(p,cdate); p += 8;
@@ -1361,7 +1362,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        if (!was_8_3 && check_mangled_names) {
                                pstring mangled_name;
                                pstrcpy(mangled_name, fname);
-                               mangle_map(mangled_name,True,True,SNUM(conn));
+                               mangle_map(mangled_name,True,True,
+                                          conn->params);
                                mangled_name[12] = 0;
                                len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
                                if (len < 24) {
@@ -1480,7 +1482,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
 
                case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
                        DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
-                       was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
+                       was_8_3 = mangle_is_8_3(fname, True, conn->params);
                        p += 4;
                        SIVAL(p,0,reskey); p += 4;
                        put_long_date(p,cdate); p += 8;
@@ -1503,7 +1505,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        if (!was_8_3 && check_mangled_names) {
                                pstring mangled_name;
                                pstrcpy(mangled_name, fname);
-                               mangle_map(mangled_name,True,True,SNUM(conn));
+                               mangle_map(mangled_name,True,True,
+                                          conn->params);
                                mangled_name[12] = 0;
                                len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
                                SSVAL(p, 0, len);
@@ -1871,8 +1874,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
         * (see PR#13758). JRA.
         */
 
-       if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
-               mangle_map(mask, True, True, SNUM(conn));
+       if(!mangle_is_8_3_wildcards( mask, False, conn->params))
+               mangle_map(mask, True, True, conn->params);
 
        return(-1);
 }
@@ -2068,8 +2071,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                 * could be mangled. Ensure we check the unmangled name.
                 */
 
-               if (mangle_is_mangled(resume_name, SNUM(conn))) {
-                       mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
+               if (mangle_is_mangled(resume_name, conn->params)) {
+                       mangle_check_cache(resume_name, sizeof(resume_name)-1,
+                                          conn->params);
                }
 
                /*
@@ -2441,17 +2445,10 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
                        SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
                        /* We have POSIX ACLs, pathname and locking capability. */
-#if defined(DEVELOPER) /* Not quite finished yet... */
                        SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
                                        CIFS_UNIX_POSIX_ACLS_CAP|
                                        CIFS_UNIX_POSIX_PATHNAMES_CAP|
                                        CIFS_UNIX_FCNTL_LOCKS_CAP)));
-#else
-                       SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
-                                       CIFS_UNIX_POSIX_ACLS_CAP|
-                                       CIFS_UNIX_POSIX_PATHNAMES_CAP|
-                                       0)));
-#endif
                        break;
 
                case SMB_QUERY_POSIX_FS_INFO:
@@ -2567,11 +2564,10 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                        lp_set_posix_pathnames();
                                        mangle_change_to_posix();
                                }
-#if defined(DEVELOPER)
+
                                if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
                                        lp_set_posix_cifsx_locktype(POSIX_LOCK);
                                }
-#endif
                                break;
                        }
                case SMB_FS_QUOTA_INFORMATION:
@@ -2832,9 +2828,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
        TALLOC_CTX *data_ctx = NULL;
        struct ea_list *ea_list = NULL;
        uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
-#if defined(DEVELOPER)
        char *lock_data = NULL;
-#endif
 
        if (!params)
                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
@@ -3006,7 +3000,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        }
                        break;
                }
-#if defined(DEVELOPER)
+
                case SMB_QUERY_POSIX_LOCK:
                {
                        if (fsp == NULL || fsp->fh->fd == -1) {
@@ -3028,7 +3022,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                return ERROR_NT(NT_STATUS_NO_MEMORY);
                        }
                }
-#endif
                default:
                        break;
        }
@@ -3229,8 +3222,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
                        pstrcpy(short_name,base_name);
                        /* Mangle if not already 8.3 */
-                       if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
-                               mangle_map(short_name,True,True,SNUM(conn));
+                       if(!mangle_is_8_3(short_name, True, conn->params)) {
+                               mangle_map(short_name,True,True,conn->params);
                        }
                        len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
                        data_size = 4 + len;
@@ -3448,7 +3441,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                        {
                                int i;
-                               DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
+                               DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
 
                                for (i=0; i<100; i++)
                                        DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
@@ -3559,13 +3552,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 #endif
 
 
-#if defined(DEVELOPER)
                case SMB_QUERY_POSIX_LOCK:
                {
                        NTSTATUS status = NT_STATUS_INVALID_LEVEL;
                        SMB_BIG_UINT count;
                        SMB_BIG_UINT offset;
-                       uint16 lock_pid;
+                       uint32 lock_pid;
                        enum brl_type lock_type;
 
                        if (total_data != POSIX_LOCK_DATA_SIZE) {
@@ -3586,7 +3578,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
                        }
 
-                       lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
+                       lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
 #if defined(HAVE_LONGLONG)
                        offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
                                        ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
@@ -3632,7 +3624,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        }
                        break;
                }
-#endif
 
                default:
                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
@@ -4030,16 +4021,16 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                                if (fd == -1) {
                                        files_struct *new_fsp = NULL;
  
-                                       new_fsp = open_file_ntcreate(conn, fname, &sbuf,
+                                       status = open_file_ntcreate(conn, fname, &sbuf,
                                                                        FILE_WRITE_DATA,
                                                                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                                                                        FILE_OPEN,
                                                                        0,
                                                                        FILE_ATTRIBUTE_NORMAL,
                                                                        FORCE_OPLOCK_BREAK_TO_NONE,
-                                                                       NULL);
+                                                                       NULL, &new_fsp);
  
-                                       if (new_fsp == NULL) {
+                                       if (!NT_STATUS_IS_OK(status)) {
                                                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                                                        /* We have re-scheduled this call. */
                                                        return -1;
@@ -4404,7 +4395,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                case SMB_FILE_RENAME_INFORMATION:
                {
                        BOOL overwrite;
-                       uint32 root_fid;
+                       /* uint32 root_fid; */  /* Not used */
                        uint32 len;
                        pstring newname;
                        pstring base_name;
@@ -4415,7 +4406,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                        }
 
                        overwrite = (CVAL(pdata,0) ? True : False);
-                       root_fid = IVAL(pdata,4);
+                       /* root_fid = IVAL(pdata,4); */
                        len = IVAL(pdata,8);
                        srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
                        if (!NT_STATUS_IS_OK(status)) {
@@ -4507,12 +4498,11 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                }
 #endif
 
-#if defined(DEVELOPER)
                case SMB_SET_POSIX_LOCK:
                {
                        SMB_BIG_UINT count;
                        SMB_BIG_UINT offset;
-                       uint16 lock_pid;
+                       uint32 lock_pid;
                        BOOL lock_blocking;
                        enum brl_type lock_type;
                        BOOL my_lock_ctx;
@@ -4551,7 +4541,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
                        }
 
-                       lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
+                       lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
 #if defined(HAVE_LONGLONG)
                        offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
                                        ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
@@ -4605,7 +4595,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                        send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
                        return(-1);
                }
-#endif
 
                default:
                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
@@ -4673,16 +4662,16 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                if (fd == -1) {
                        files_struct *new_fsp = NULL;
 
-                       new_fsp = open_file_ntcreate(conn, fname, &sbuf,
+                       status = open_file_ntcreate(conn, fname, &sbuf,
                                                FILE_WRITE_DATA,
                                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                                                FILE_OPEN,
                                                0,
                                                FILE_ATTRIBUTE_NORMAL,
                                                FORCE_OPLOCK_BREAK_TO_NONE,
-                                               NULL);
+                                               NULL, &new_fsp);
        
-                       if (new_fsp == NULL) {
+                       if (!NT_STATUS_IS_OK(status)) {
                                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                                        /* We have re-scheduled this call. */
                                        return -1;
index c62c9d928abac5b2e882269c277e8fc9b941ddc2..48d7f590c399d93930e346a3a6838e13bec0c010 100644 (file)
@@ -102,7 +102,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
 
        readonly_share = is_share_read_only_for_token(vuser->user.unix_name,
                                                      vuser->nt_user_token,
-                                                     conn->service);
+                                                     SNUM(conn));
 
        if (!readonly_share &&
            !share_access_check(conn, snum, vuser, FILE_WRITE_DATA)) {
@@ -129,7 +129,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
 
        ent->admin_user = token_contains_name_in_list(
                vuser->user.unix_name, NULL, vuser->nt_user_token,
-               lp_admin_users(conn->service));
+               lp_admin_users(SNUM(conn)));
 
        conn->read_only = ent->read_only;
        conn->admin_user = ent->admin_user;
diff --git a/source/smbd/vfs-wrap.c b/source/smbd/vfs-wrap.c
deleted file mode 100644 (file)
index ee251c1..0000000
+++ /dev/null
@@ -1,1104 +0,0 @@
-/* 
-   Unix SMB/CIFS implementation.
-   Wrap disk only vfs functions to sidestep dodgy compilers.
-   Copyright (C) Tim Potter 1998
-   
-   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"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_VFS
-
-
-/* Check for NULL pointer parameters in vfswrap_* functions */
-
-/* We don't want to have NULL function pointers lying around.  Someone
-   is sure to try and execute them.  These stubs are used to prevent
-   this possibility. */
-
-int vfswrap_dummy_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user)
-{
-    return 0;    /* Return >= 0 for success */
-}
-
-void vfswrap_dummy_disconnect(vfs_handle_struct *handle, connection_struct *conn)
-{
-}
-
-/* Disk operations */
-
-SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, 
-                              SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
-{
-       SMB_BIG_UINT result;
-
-       result = sys_disk_free(conn, path, small_query, bsize, dfree, dsize);
-       return result;
-}
-
-int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
-{
-#ifdef HAVE_SYS_QUOTAS
-       int result;
-
-       START_PROFILE(syscall_get_quota);
-       result = sys_get_quota(conn->connectpath, qtype, id, qt);
-       END_PROFILE(syscall_get_quota);
-       return result;
-#else
-       errno = ENOSYS;
-       return -1;
-#endif 
-}
-
-int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
-{
-#ifdef HAVE_SYS_QUOTAS
-       int result;
-
-       START_PROFILE(syscall_set_quota);
-       result = sys_set_quota(conn->connectpath, qtype, id, qt);
-       END_PROFILE(syscall_set_quota);
-       return result;
-#else
-       errno = ENOSYS;
-       return -1;
-#endif 
-}
-
-int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
-{
-       errno = ENOSYS;
-       return -1;  /* Not implemented. */
-}
-    
-int vfswrap_statvfs(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, vfs_statvfs_struct *statbuf)
-{
-       return sys_statvfs(path, statbuf);
-}
-
-/* Directory operations */
-
-SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr)
-{
-       SMB_STRUCT_DIR *result;
-
-       START_PROFILE(syscall_opendir);
-       result = sys_opendir(fname);
-       END_PROFILE(syscall_opendir);
-       return result;
-}
-
-SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp)
-{
-       SMB_STRUCT_DIRENT *result;
-
-       START_PROFILE(syscall_readdir);
-       result = sys_readdir(dirp);
-       END_PROFILE(syscall_readdir);
-       return result;
-}
-
-void vfswrap_seekdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp, long offset)
-{
-       START_PROFILE(syscall_seekdir);
-       sys_seekdir(dirp, offset);
-       END_PROFILE(syscall_seekdir);
-}
-
-long vfswrap_telldir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp)
-{
-       long result;
-       START_PROFILE(syscall_telldir);
-       result = sys_telldir(dirp);
-       END_PROFILE(syscall_telldir);
-       return result;
-}
-
-void vfswrap_rewinddir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp)
-{
-       START_PROFILE(syscall_rewinddir);
-       sys_rewinddir(dirp);
-       END_PROFILE(syscall_rewinddir);
-}
-
-int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
-{
-       int result;
-       BOOL has_dacl = False;
-
-       START_PROFILE(syscall_mkdir);
-
-       if (lp_inherit_acls(SNUM(conn)) && (has_dacl = directory_has_default_acl(conn, parent_dirname(path))))
-               mode = 0777;
-
-       result = mkdir(path, mode);
-
-       if (result == 0 && !has_dacl) {
-               /*
-                * We need to do this as the default behavior of POSIX ACLs     
-                * is to set the mask to be the requested group permission
-                * bits, not the group permission bits to be the requested
-                * group permission bits. This is not what we want, as it will
-                * mess up any inherited ACL bits that were set. JRA.
-                */
-               int saved_errno = errno; /* We may get ENOSYS */
-               if ((SMB_VFS_CHMOD_ACL(conn, path, mode) == -1) && (errno == ENOSYS))
-                       errno = saved_errno;
-       }
-
-       END_PROFILE(syscall_mkdir);
-       return result;
-}
-
-int vfswrap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
-{
-       int result;
-
-       START_PROFILE(syscall_rmdir);
-       result = rmdir(path);
-       END_PROFILE(syscall_rmdir);
-       return result;
-}
-
-int vfswrap_closedir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp)
-{
-       int result;
-
-       START_PROFILE(syscall_closedir);
-       result = sys_closedir(dirp);
-       END_PROFILE(syscall_closedir);
-       return result;
-}
-
-/* File operations */
-    
-int vfswrap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
-{
-       int result;
-
-       START_PROFILE(syscall_open);
-       result = sys_open(fname, flags, mode);
-       END_PROFILE(syscall_open);
-       return result;
-}
-
-int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
-{
-       int result;
-
-       START_PROFILE(syscall_close);
-
-       result = close(fd);
-       END_PROFILE(syscall_close);
-       return result;
-}
-
-ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n)
-{
-       ssize_t result;
-
-       START_PROFILE_BYTES(syscall_read, n);
-       result = sys_read(fd, data, n);
-       END_PROFILE(syscall_read);
-       return result;
-}
-
-ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data,
-                       size_t n, SMB_OFF_T offset)
-{
-       ssize_t result;
-
-#if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
-       START_PROFILE_BYTES(syscall_pread, n);
-       result = sys_pread(fd, data, n, offset);
-       END_PROFILE(syscall_pread);
-       if (result == -1 && errno == ESPIPE) {
-               /* Maintain the fiction that pipes can be seeked (sought?) on. */
-               result = SMB_VFS_READ(fsp, fd, data, n);
-               fsp->fh->pos = 0;
-       }
-
-#else /* HAVE_PREAD */
-       SMB_OFF_T   curr;
-       int lerrno;
-   
-       curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
-       if (curr == -1 && errno == ESPIPE) {
-               /* Maintain the fiction that pipes can be seeked (sought?) on. */
-               result = SMB_VFS_READ(fsp, fd, data, n);
-               fsp->fh->pos = 0;
-               return result;
-       }
-
-       if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) {
-               return -1;
-       }
-
-       errno = 0;
-       result = SMB_VFS_READ(fsp, fd, data, n);
-       lerrno = errno;
-
-       SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET);
-       errno = lerrno;
-
-#endif /* HAVE_PREAD */
-
-       return result;
-}
-
-ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n)
-{
-       ssize_t result;
-
-       START_PROFILE_BYTES(syscall_write, n);
-       result = sys_write(fd, data, n);
-       END_PROFILE(syscall_write);
-       return result;
-}
-
-ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data,
-                       size_t n, SMB_OFF_T offset)
-{
-       ssize_t result;
-
-#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
-       START_PROFILE_BYTES(syscall_pwrite, n);
-       result = sys_pwrite(fd, data, n, offset);
-       END_PROFILE(syscall_pwrite);
-
-       if (result == -1 && errno == ESPIPE) {
-               /* Maintain the fiction that pipes can be sought on. */
-               result = SMB_VFS_WRITE(fsp, fd, data, n);
-       }
-
-#else /* HAVE_PWRITE */
-       SMB_OFF_T   curr;
-       int         lerrno;
-
-       curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
-       if (curr == -1) {
-               return -1;
-       }
-
-       if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) {
-               return -1;
-       }
-
-       result = SMB_VFS_WRITE(fsp, fd, data, n);
-       lerrno = errno;
-
-       SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET);
-       errno = lerrno;
-
-#endif /* HAVE_PWRITE */
-
-       return result;
-}
-
-SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence)
-{
-       SMB_OFF_T result = 0;
-
-       START_PROFILE(syscall_lseek);
-
-       /* Cope with 'stat' file opens. */
-       if (filedes != -1)
-               result = sys_lseek(filedes, offset, whence);
-
-       /*
-        * We want to maintain the fiction that we can seek
-        * on a fifo for file system purposes. This allows
-        * people to set up UNIX fifo's that feed data to Windows
-        * applications. JRA.
-        */
-
-       if((result == -1) && (errno == ESPIPE)) {
-               result = 0;
-               errno = 0;
-       }
-
-       END_PROFILE(syscall_lseek);
-       return result;
-}
-
-ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *hdr,
-                       SMB_OFF_T offset, size_t n)
-{
-       ssize_t result;
-
-       START_PROFILE_BYTES(syscall_sendfile, n);
-       result = sys_sendfile(tofd, fromfd, hdr, offset, n);
-       END_PROFILE(syscall_sendfile);
-       return result;
-}
-
-/*********************************************************
- For rename across filesystems Patch from Warren Birnbaum
- <warrenb@hpcvscdp.cv.hp.com>
-**********************************************************/
-
-static int copy_reg(const char *source, const char *dest)
-{
-       SMB_STRUCT_STAT source_stats;
-       int saved_errno;
-       int ifd = -1;
-       int ofd = -1;
-
-       if (sys_lstat (source, &source_stats) == -1)
-               return -1;
-
-       if (!S_ISREG (source_stats.st_mode))
-               return -1;
-
-       if((ifd = sys_open (source, O_RDONLY, 0)) < 0)
-               return -1;
-
-       if (unlink (dest) && errno != ENOENT)
-               return -1;
-
-#ifdef O_NOFOLLOW
-       if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 )
-#else
-       if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 )
-#endif
-               goto err;
-
-       if (transfer_file(ifd, ofd, (size_t)-1) == -1)
-               goto err;
-
-       /*
-        * Try to preserve ownership.  For non-root it might fail, but that's ok.
-        * But root probably wants to know, e.g. if NFS disallows it.
-        */
-
-#ifdef HAVE_FCHOWN
-       if ((fchown(ofd, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
-#else
-       if ((chown(dest, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
-#endif
-               goto err;
-
-       /*
-        * fchown turns off set[ug]id bits for non-root,
-        * so do the chmod last.
-        */
-
-#if defined(HAVE_FCHMOD)
-       if (fchmod (ofd, source_stats.st_mode & 07777))
-#else
-       if (chmod (dest, source_stats.st_mode & 07777))
-#endif
-               goto err;
-
-       if (close (ifd) == -1)
-               goto err;
-
-       if (close (ofd) == -1)
-               return -1;
-
-       /* Try to copy the old file's modtime and access time.  */
-       {
-               struct utimbuf tv;
-
-               tv.actime = source_stats.st_atime;
-               tv.modtime = source_stats.st_mtime;
-               utime(dest, &tv);
-       }
-
-       if (unlink (source) == -1)
-               return -1;
-
-       return 0;
-
-  err:
-
-       saved_errno = errno;
-       if (ifd != -1)
-               close(ifd);
-       if (ofd != -1)
-               close(ofd);
-       errno = saved_errno;
-       return -1;
-}
-
-int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname)
-{
-       int result;
-
-       START_PROFILE(syscall_rename);
-       result = rename(oldname, newname);
-       if (errno == EXDEV) {
-               /* Rename across filesystems needed. */
-               result = copy_reg(oldname, newname);
-       }
-
-       END_PROFILE(syscall_rename);
-       return result;
-}
-
-int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd)
-{
-#ifdef HAVE_FSYNC
-       int result;
-
-       START_PROFILE(syscall_fsync);
-       result = fsync(fd);
-       END_PROFILE(syscall_fsync);
-       return result;
-#else
-       return 0;
-#endif
-}
-
-int vfswrap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
-{
-       int result;
-
-       START_PROFILE(syscall_stat);
-       result = sys_stat(fname, sbuf);
-       END_PROFILE(syscall_stat);
-       return result;
-}
-
-int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
-{
-       int result;
-
-       START_PROFILE(syscall_fstat);
-       result = sys_fstat(fd, sbuf);
-       END_PROFILE(syscall_fstat);
-       return result;
-}
-
-int vfswrap_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
-{
-       int result;
-
-       START_PROFILE(syscall_lstat);
-       result = sys_lstat(path, sbuf);
-       END_PROFILE(syscall_lstat);
-       return result;
-}
-
-int vfswrap_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
-{
-       int result;
-
-       START_PROFILE(syscall_unlink);
-       result = unlink(path);
-       END_PROFILE(syscall_unlink);
-       return result;
-}
-
-int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
-{
-       int result;
-
-       START_PROFILE(syscall_chmod);
-
-       /*
-        * We need to do this due to the fact that the default POSIX ACL
-        * chmod modifies the ACL *mask* for the group owner, not the
-        * group owner bits directly. JRA.
-        */
-
-       
-       {
-               int saved_errno = errno; /* We might get ENOSYS */
-               if ((result = SMB_VFS_CHMOD_ACL(conn, path, mode)) == 0) {
-                       END_PROFILE(syscall_chmod);
-                       return result;
-               }
-               /* Error - return the old errno. */
-               errno = saved_errno;
-       }
-
-       result = chmod(path, mode);
-       END_PROFILE(syscall_chmod);
-       return result;
-}
-
-int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
-{
-       int result;
-       
-       START_PROFILE(syscall_fchmod);
-
-       /*
-        * We need to do this due to the fact that the default POSIX ACL
-        * chmod modifies the ACL *mask* for the group owner, not the
-        * group owner bits directly. JRA.
-        */
-       
-       {
-               int saved_errno = errno; /* We might get ENOSYS */
-               if ((result = SMB_VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) {
-                       END_PROFILE(syscall_fchmod);
-                       return result;
-               }
-               /* Error - return the old errno. */
-               errno = saved_errno;
-       }
-
-#if defined(HAVE_FCHMOD)
-       result = fchmod(fd, mode);
-#else
-       result = -1;
-       errno = ENOSYS;
-#endif
-
-       END_PROFILE(syscall_fchmod);
-       return result;
-}
-
-int vfswrap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid)
-{
-       int result;
-
-       START_PROFILE(syscall_chown);
-       result = sys_chown(path, uid, gid);
-       END_PROFILE(syscall_chown);
-       return result;
-}
-
-int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid)
-{
-#ifdef HAVE_FCHOWN
-       int result;
-
-       START_PROFILE(syscall_fchown);
-       result = fchown(fd, uid, gid);
-       END_PROFILE(syscall_fchown);
-       return result;
-#else
-       errno = ENOSYS;
-       return -1;
-#endif
-}
-
-int vfswrap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
-{
-       int result;
-
-       START_PROFILE(syscall_chdir);
-       result = chdir(path);
-       END_PROFILE(syscall_chdir);
-       return result;
-}
-
-char *vfswrap_getwd(vfs_handle_struct *handle, connection_struct *conn, char *path)
-{
-       char *result;
-
-       START_PROFILE(syscall_getwd);
-       result = sys_getwd(path);
-       END_PROFILE(syscall_getwd);
-       return result;
-}
-
-int vfswrap_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times)
-{
-       int result;
-
-       START_PROFILE(syscall_utime);
-       result = utime(path, times);
-       END_PROFILE(syscall_utime);
-       return result;
-}
-
-/*********************************************************************
- A version of ftruncate that will write the space on disk if strict
- allocate is set.
-**********************************************************************/
-
-static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len)
-{
-       SMB_STRUCT_STAT st;
-       SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
-       unsigned char zero_space[4096];
-       SMB_OFF_T space_to_write;
-
-       if (currpos == -1)
-               return -1;
-
-       if (SMB_VFS_FSTAT(fsp, fd, &st) == -1)
-               return -1;
-
-       space_to_write = len - st.st_size;
-
-#ifdef S_ISFIFO
-       if (S_ISFIFO(st.st_mode))
-               return 0;
-#endif
-
-       if (st.st_size == len)
-               return 0;
-
-       /* Shrink - just ftruncate. */
-       if (st.st_size > len)
-               return sys_ftruncate(fd, len);
-
-       /* Write out the real space on disk. */
-       if (SMB_VFS_LSEEK(fsp, fd, st.st_size, SEEK_SET) != st.st_size)
-               return -1;
-
-       space_to_write = len - st.st_size;
-
-       memset(zero_space, '\0', sizeof(zero_space));
-       while ( space_to_write > 0) {
-               SMB_OFF_T retlen;
-               SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
-
-               retlen = SMB_VFS_WRITE(fsp,fsp->fh->fd,(char *)zero_space,current_len_to_write);
-               if (retlen <= 0)
-                       return -1;
-
-               space_to_write -= retlen;
-       }
-
-       /* Seek to where we were */
-       if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos)
-               return -1;
-
-       return 0;
-}
-
-int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len)
-{
-       int result = -1;
-       SMB_STRUCT_STAT st;
-       char c = 0;
-       SMB_OFF_T currpos;
-
-       START_PROFILE(syscall_ftruncate);
-
-       if (lp_strict_allocate(SNUM(fsp->conn))) {
-               result = strict_allocate_ftruncate(handle, fsp, fd, len);
-               END_PROFILE(syscall_ftruncate);
-               return result;
-       }
-
-       /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
-          sys_ftruncate if the system supports it. Then I discovered that
-          you can have some filesystems that support ftruncate
-          expansion and some that don't! On Linux fat can't do
-          ftruncate extend but ext2 can. */
-
-       result = sys_ftruncate(fd, len);
-       if (result == 0)
-               goto done;
-
-       /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
-          extend a file with ftruncate. Provide alternate implementation
-          for this */
-       currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
-       if (currpos == -1) {
-               goto done;
-       }
-
-       /* Do an fstat to see if the file is longer than the requested
-          size in which case the ftruncate above should have
-          succeeded or shorter, in which case seek to len - 1 and
-          write 1 byte of zero */
-       if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) {
-               goto done;
-       }
-
-#ifdef S_ISFIFO
-       if (S_ISFIFO(st.st_mode)) {
-               result = 0;
-               goto done;
-       }
-#endif
-
-       if (st.st_size == len) {
-               result = 0;
-               goto done;
-       }
-
-       if (st.st_size > len) {
-               /* the sys_ftruncate should have worked */
-               goto done;
-       }
-
-       if (SMB_VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1)
-               goto done;
-
-       if (SMB_VFS_WRITE(fsp, fd, &c, 1)!=1)
-               goto done;
-
-       /* Seek to where we were */
-       if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos)
-               goto done;
-       result = 0;
-
-  done:
-
-       END_PROFILE(syscall_ftruncate);
-       return result;
-}
-
-BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
-{
-       BOOL result;
-
-       START_PROFILE(syscall_fcntl_lock);
-       result =  fcntl_lock(fd, op, offset, count, type);
-       END_PROFILE(syscall_fcntl_lock);
-       return result;
-}
-
-BOOL vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
-{
-       BOOL result;
-
-       START_PROFILE(syscall_fcntl_getlock);
-       result =  fcntl_getlock(fd, poffset, pcount, ptype, ppid);
-       END_PROFILE(syscall_fcntl_getlock);
-       return result;
-}
-
-int vfswrap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
-{
-       int result;
-
-       START_PROFILE(syscall_symlink);
-       result = sys_symlink(oldpath, newpath);
-       END_PROFILE(syscall_symlink);
-       return result;
-}
-
-int vfswrap_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz)
-{
-       int result;
-
-       START_PROFILE(syscall_readlink);
-       result = sys_readlink(path, buf, bufsiz);
-       END_PROFILE(syscall_readlink);
-       return result;
-}
-
-int vfswrap_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
-{
-       int result;
-
-       START_PROFILE(syscall_link);
-       result = sys_link(oldpath, newpath);
-       END_PROFILE(syscall_link);
-       return result;
-}
-
-int vfswrap_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev)
-{
-       int result;
-
-       START_PROFILE(syscall_mknod);
-       result = sys_mknod(pathname, mode, dev);
-       END_PROFILE(syscall_mknod);
-       return result;
-}
-
-char *vfswrap_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path)
-{
-       char *result;
-
-       START_PROFILE(syscall_realpath);
-       result = sys_realpath(path, resolved_path);
-       END_PROFILE(syscall_realpath);
-       return result;
-}
-
-size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, SEC_DESC **ppdesc)
-{
-       size_t result;
-
-       START_PROFILE(fget_nt_acl);
-       result = get_nt_acl(fsp, security_info, ppdesc);
-       END_PROFILE(fget_nt_acl);
-       return result;
-}
-
-size_t vfswrap_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, SEC_DESC **ppdesc)
-{
-       size_t result;
-
-       START_PROFILE(get_nt_acl);
-       result = get_nt_acl(fsp, security_info, ppdesc);
-       END_PROFILE(get_nt_acl);
-       return result;
-}
-
-BOOL vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
-{
-       BOOL result;
-
-       START_PROFILE(fset_nt_acl);
-       result = set_nt_acl(fsp, security_info_sent, psd);
-       END_PROFILE(fset_nt_acl);
-       return result;
-}
-
-BOOL vfswrap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
-{
-       BOOL result;
-
-       START_PROFILE(set_nt_acl);
-       result = set_nt_acl(fsp, security_info_sent, psd);
-       END_PROFILE(set_nt_acl);
-       return result;
-}
-
-int vfswrap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode)
-{
-#ifdef HAVE_NO_ACL
-       errno = ENOSYS;
-       return -1;
-#else
-       int result;
-
-       START_PROFILE(chmod_acl);
-       result = chmod_acl(conn, name, mode);
-       END_PROFILE(chmod_acl);
-       return result;
-#endif
-}
-
-int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
-{
-#ifdef HAVE_NO_ACL
-       errno = ENOSYS;
-       return -1;
-#else
-       int result;
-
-       START_PROFILE(fchmod_acl);
-       result = fchmod_acl(fsp, fd, mode);
-       END_PROFILE(fchmod_acl);
-       return result;
-#endif
-}
-
-int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
-{
-       return sys_acl_get_entry(theacl, entry_id, entry_p);
-}
-
-int vfswrap_sys_acl_get_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
-{
-       return sys_acl_get_tag_type(entry_d, tag_type_p);
-}
-
-int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
-{
-       return sys_acl_get_permset(entry_d, permset_p);
-}
-
-void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d)
-{
-       return sys_acl_get_qualifier(entry_d);
-}
-
-SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
-{
-       return sys_acl_get_file(path_p, type);
-}
-
-SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
-{
-       return sys_acl_get_fd(fd);
-}
-
-int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset)
-{
-       return sys_acl_clear_perms(permset);
-}
-
-int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
-{
-       return sys_acl_add_perm(permset, perm);
-}
-
-char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen)
-{
-       return sys_acl_to_text(theacl, plen);
-}
-
-SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle, connection_struct *conn, int count)
-{
-       return sys_acl_init(count);
-}
-
-int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
-{
-       return sys_acl_create_entry(pacl, pentry);
-}
-
-int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
-{
-       return sys_acl_set_tag_type(entry, tagtype);
-}
-
-int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual)
-{
-       return sys_acl_set_qualifier(entry, qual);
-}
-
-int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
-{
-       return sys_acl_set_permset(entry, permset);
-}
-
-int vfswrap_sys_acl_valid(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl )
-{
-       return sys_acl_valid(theacl );
-}
-
-int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
-{
-       return sys_acl_set_file(name, acltype, theacl);
-}
-
-int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl)
-{
-       return sys_acl_set_fd(fd, theacl);
-}
-
-int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path)
-{
-       return sys_acl_delete_def_file(path);
-}
-
-int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
-{
-       return sys_acl_get_perm(permset, perm);
-}
-
-int vfswrap_sys_acl_free_text(vfs_handle_struct *handle, connection_struct *conn, char *text)
-{
-       return sys_acl_free_text(text);
-}
-
-int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T posix_acl)
-{
-       return sys_acl_free_acl(posix_acl);
-}
-
-int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype)
-{
-       return sys_acl_free_qualifier(qualifier, tagtype);
-}
-
-/****************************************************************
- Extended attribute operations.
-*****************************************************************/
-
-ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size)
-{
-       return sys_getxattr(path, name, value, size);
-}
-
-ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size)
-{
-       return sys_lgetxattr(path, name, value, size);
-}
-
-ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size)
-{
-       return sys_fgetxattr(fd, name, value, size);
-}
-
-ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
-{
-       return sys_listxattr(path, list, size);
-}
-
-ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
-{
-       return sys_llistxattr(path, list, size);
-}
-
-ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size)
-{
-       return sys_flistxattr(fd, list, size);
-}
-
-int vfswrap_removexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
-{
-       return sys_removexattr(path, name);
-}
-
-int vfswrap_lremovexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
-{
-       return sys_lremovexattr(path, name);
-}
-
-int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name)
-{
-       return sys_fremovexattr(fd, name);
-}
-
-int vfswrap_setxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
-{
-       return sys_setxattr(path, name, value, size, flags);
-}
-
-int vfswrap_lsetxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
-{
-       return sys_lsetxattr(path, name, value, size, flags);
-}
-
-int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags)
-{
-       return sys_fsetxattr(fd, name, value, size, flags);
-}
-
-int vfswrap_aio_read(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
-       return sys_aio_read(aiocb);
-}
-
-int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
-       return sys_aio_write(aiocb);
-}
-
-ssize_t vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
-       return sys_aio_return(aiocb);
-}
-
-int vfswrap_aio_cancel(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_STRUCT_AIOCB *aiocb)
-{
-       return sys_aio_cancel(fd, aiocb);
-}
-
-int vfswrap_aio_error(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
-       return sys_aio_error(aiocb);
-}
-
-int vfswrap_aio_fsync(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb)
-{
-       return sys_aio_fsync(op, aiocb);
-}
-
-int vfswrap_aio_suspend(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_AIOCB * const aiocb[], int n, const struct timespec *timeout)
-{
-       return sys_aio_suspend(aiocb, n, timeout);
-}
index 2c9403a079092734c535a9596943d4a6537a1b14..7bb5f798f97838cc82cf6c89d4ad7e7752487594 100644 (file)
@@ -4,6 +4,7 @@
    VFS initialisation and support functions
    Copyright (C) Tim Potter 1999
    Copyright (C) Alexander Bokovoy 2002
+   Copyright (C) James Peach 2006
 
    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
@@ -37,131 +38,6 @@ struct vfs_init_function_entry {
 
 static struct vfs_init_function_entry *backends = NULL;
 
-/* Some structures to help us initialise the vfs operations table */
-
-struct vfs_syminfo {
-       char *name;
-       void *fptr;
-};
-
-/* Default vfs hooks.  WARNING: The order of these initialisers is
-   very important.  They must be in the same order as defined in
-   vfs.h.  Change at your own peril. */
-
-static struct vfs_ops default_vfs = {
-
-       {
-               /* Disk operations */
-       
-               vfswrap_dummy_connect,
-               vfswrap_dummy_disconnect,
-               vfswrap_disk_free,
-               vfswrap_get_quota,
-               vfswrap_set_quota,
-               vfswrap_get_shadow_copy_data,
-               vfswrap_statvfs,
-       
-               /* Directory operations */
-       
-               vfswrap_opendir,
-               vfswrap_readdir,
-               vfswrap_seekdir,
-               vfswrap_telldir,
-               vfswrap_rewinddir,
-               vfswrap_mkdir,
-               vfswrap_rmdir,
-               vfswrap_closedir,
-       
-               /* File operations */
-       
-               vfswrap_open,
-               vfswrap_close,
-               vfswrap_read,
-               vfswrap_pread,
-               vfswrap_write,
-               vfswrap_pwrite,
-               vfswrap_lseek,
-               vfswrap_sendfile,
-               vfswrap_rename,
-               vfswrap_fsync,
-               vfswrap_stat,
-               vfswrap_fstat,
-               vfswrap_lstat,
-               vfswrap_unlink,
-               vfswrap_chmod,
-               vfswrap_fchmod,
-               vfswrap_chown,
-               vfswrap_fchown,
-               vfswrap_chdir,
-               vfswrap_getwd,
-               vfswrap_utime,
-               vfswrap_ftruncate,
-               vfswrap_lock,
-               vfswrap_getlock,
-               vfswrap_symlink,
-               vfswrap_readlink,
-               vfswrap_link,
-               vfswrap_mknod,
-               vfswrap_realpath,
-       
-               /* Windows ACL operations. */
-               vfswrap_fget_nt_acl,
-               vfswrap_get_nt_acl,
-               vfswrap_fset_nt_acl,
-               vfswrap_set_nt_acl,
-       
-               /* POSIX ACL operations. */
-               vfswrap_chmod_acl,
-               vfswrap_fchmod_acl,
-
-               vfswrap_sys_acl_get_entry,
-               vfswrap_sys_acl_get_tag_type,
-               vfswrap_sys_acl_get_permset,
-               vfswrap_sys_acl_get_qualifier,
-               vfswrap_sys_acl_get_file,
-               vfswrap_sys_acl_get_fd,
-               vfswrap_sys_acl_clear_perms,
-               vfswrap_sys_acl_add_perm,
-               vfswrap_sys_acl_to_text,
-               vfswrap_sys_acl_init,
-               vfswrap_sys_acl_create_entry,
-               vfswrap_sys_acl_set_tag_type,
-               vfswrap_sys_acl_set_qualifier,
-               vfswrap_sys_acl_set_permset,
-               vfswrap_sys_acl_valid,
-               vfswrap_sys_acl_set_file,
-               vfswrap_sys_acl_set_fd,
-               vfswrap_sys_acl_delete_def_file,
-               vfswrap_sys_acl_get_perm,
-               vfswrap_sys_acl_free_text,
-               vfswrap_sys_acl_free_acl,
-               vfswrap_sys_acl_free_qualifier,
-
-               /* EA operations. */
-               vfswrap_getxattr,
-               vfswrap_lgetxattr,
-               vfswrap_fgetxattr,
-               vfswrap_listxattr,
-               vfswrap_llistxattr,
-               vfswrap_flistxattr,
-               vfswrap_removexattr,
-               vfswrap_lremovexattr,
-               vfswrap_fremovexattr,
-               vfswrap_setxattr,
-               vfswrap_lsetxattr,
-               vfswrap_fsetxattr,
-
-               /* AIO operations. */
-               vfswrap_aio_read,
-               vfswrap_aio_write,
-               vfswrap_aio_return,
-               vfswrap_aio_cancel,
-               vfswrap_aio_error,
-               vfswrap_aio_fsync,
-               vfswrap_aio_suspend
-       }
-};
-
 /****************************************************************************
     maintain the list of available backends
 ****************************************************************************/
@@ -217,15 +93,20 @@ NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tu
 static void vfs_init_default(connection_struct *conn)
 {
        DEBUG(3, ("Initialising default vfs hooks\n"));
-
-       memcpy(&conn->vfs.ops, &default_vfs.ops, sizeof(default_vfs.ops));
-       memcpy(&conn->vfs_opaque.ops, &default_vfs.ops, sizeof(default_vfs.ops));
+       vfs_init_custom(conn, DEFAULT_VFS_MODULE_NAME);
 }
 
 /****************************************************************************
   initialise custom vfs hooks
  ****************************************************************************/
 
+static inline void vfs_set_operation(struct vfs_ops * vfs, vfs_op_type which,
+                               struct vfs_handle_struct * handle, void * op)
+{
+       ((struct vfs_handle_struct **)&vfs->handles)[which] = handle;
+       ((void**)&vfs->ops)[which] = op;
+}
+
 BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
 {
        vfs_op_tuple *ops;
@@ -292,24 +173,86 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
        for(i=0; ops[i].op != NULL; i++) {
                DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer));
                if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) {
-                       /* Check whether this operation was already made opaque by different module */
-                       if(((void**)&conn->vfs_opaque.ops)[ops[i].type] == ((void**)&default_vfs.ops)[ops[i].type]) {
-                               /* No, it isn't overloaded yet. Overload. */
-                               DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object));
-                               ((void**)&conn->vfs_opaque.ops)[ops[i].type] = ops[i].op;
-                               ((vfs_handle_struct **)&conn->vfs_opaque.handles)[ops[i].type] = handle;
-                       }
+                       /* If this operation was already made opaque by different module, it
+                        * will be overridded here.
+                        */
+                       DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object));
+                       vfs_set_operation(&conn->vfs_opaque, ops[i].type, handle, ops[i].op);
                }
                /* Change current VFS disposition*/
                DEBUGADD(5, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object));
-               ((void**)&conn->vfs.ops)[ops[i].type] = ops[i].op;
-               ((vfs_handle_struct **)&conn->vfs.handles)[ops[i].type] = handle;
+               vfs_set_operation(&conn->vfs, ops[i].type, handle, ops[i].op);
        }
 
        SAFE_FREE(module_name);
        return True;
 }
 
+/*****************************************************************
+ Allow VFS modules to extend files_struct with VFS-specific state.
+ This will be ok for small numbers of extensions, but might need to
+ be refactored if it becomes more widely used.
+******************************************************************/
+
+#define EXT_DATA_AREA(e) ((uint8 *)(e) + sizeof(struct vfs_fsp_data))
+
+void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle, files_struct *fsp, size_t ext_size)
+{
+       struct vfs_fsp_data *ext;
+       void * ext_data;
+
+       /* Prevent VFS modules adding multiple extensions. */
+       if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) {
+               return ext_data;
+       }
+
+       ext = TALLOC_ZERO(handle->conn->mem_ctx,
+                           sizeof(struct vfs_fsp_data) + ext_size);
+       if (ext == NULL) {
+               return NULL;
+       }
+
+       ext->owner = handle;
+       ext->next = fsp->vfs_extension;
+       fsp->vfs_extension = ext;
+       return EXT_DATA_AREA(ext);
+}
+
+void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
+{
+       struct vfs_fsp_data *curr;
+       struct vfs_fsp_data *prev;
+
+       for (curr = fsp->vfs_extension, prev = NULL;
+            curr;
+            prev = curr, curr = curr->next) {
+               if (curr->owner == handle) {
+                   if (prev) {
+                           prev->next = curr->next;
+                   } else {
+                           fsp->vfs_extension = curr->next;
+                   }
+                   TALLOC_FREE(curr);
+                   return;
+               }
+       }
+}
+
+void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
+{
+       struct vfs_fsp_data *head;
+
+       for (head = fsp->vfs_extension; head; head = head->next) {
+               if (head->owner == handle) {
+                       return EXT_DATA_AREA(head);
+               }
+       }
+
+       return NULL;
+}
+
+#undef EXT_DATA_AREA
+
 /*****************************************************************
  Generic VFS init.
 ******************************************************************/
index d4a5b51af4e27c02699984a5f5c356608fa2d762..89ae9396aafd05f91111dafbf772bfc31be40dd9 100644 (file)
@@ -432,7 +432,7 @@ return a connection to a server (existing or new)
 struct smbw_server *smbw_server(char *server, char *share)
 {
        struct smbw_server *srv=NULL;
-       struct cli_state c;
+       struct cli_state *c;
        char *username;
        char *password;
        char *workgroup;
@@ -499,13 +499,13 @@ struct smbw_server *smbw_server(char *server, char *share)
        }
 
        /* have to open a new connection */
-       if (!cli_initialise(&c) || !cli_connect(&c, server_n, &ip)) {
+       if (((c = cli_initialise()) == NULL) || !cli_connect(c, server_n, &ip)) {
                errno = ENOENT;
                return NULL;
        }
 
-       if (!cli_session_request(&c, &calling, &called)) {
-               cli_shutdown(&c);
+       if (!cli_session_request(c, &calling, &called)) {
+               cli_shutdown(c);
                if (strcmp(called.name, "*SMBSERVER")) {
                        make_nmb_name(&called , "*SMBSERVER", 0x20);
                        goto again;
@@ -516,29 +516,29 @@ struct smbw_server *smbw_server(char *server, char *share)
 
        DEBUG(4,(" session request ok\n"));
 
-       if (!cli_negprot(&c)) {
-               cli_shutdown(&c);
+       if (!cli_negprot(c)) {
+               cli_shutdown(c);
                errno = ENOENT;
                return NULL;
        }
 
-       if (!cli_session_setup(&c, username, 
+       if (!cli_session_setup(c, username, 
                               password, strlen(password),
                               password, strlen(password),
                               workgroup) &&
            /* try an anonymous login if it failed */
-           !cli_session_setup(&c, "", "", 1,"", 0, workgroup)) {
-               cli_shutdown(&c);
+           !cli_session_setup(c, "", "", 1,"", 0, workgroup)) {
+               cli_shutdown(c);
                errno = EPERM;
                return NULL;
        }
 
        DEBUG(4,(" session setup ok\n"));
 
-       if (!cli_send_tconX(&c, share, "?????",
+       if (!cli_send_tconX(c, share, "?????",
                            password, strlen(password)+1)) {
-               errno = smbw_errno(&c);
-               cli_shutdown(&c);
+               errno = smbw_errno(c);
+               cli_shutdown(c);
                return NULL;
        }
 
@@ -584,11 +584,11 @@ struct smbw_server *smbw_server(char *server, char *share)
 
        /* some programs play with file descriptors fairly intimately. We
           try to get out of the way by duping to a high fd number */
-       if (fcntl(SMBW_CLI_FD + srv->cli.fd, F_GETFD) && errno == EBADF) {
-               if (dup2(srv->cli.fd,SMBW_CLI_FD+srv->cli.fd) == 
-                   srv->cli.fd+SMBW_CLI_FD) {
-                       close(srv->cli.fd);
-                       srv->cli.fd += SMBW_CLI_FD;
+       if (fcntl(SMBW_CLI_FD + srv->cli->fd, F_GETFD) && errno == EBADF) {
+               if (dup2(srv->cli->fd,SMBW_CLI_FD+srv->cli->fd) == 
+                   srv->cli->fd+SMBW_CLI_FD) {
+                       close(srv->cli->fd);
+                       srv->cli->fd += SMBW_CLI_FD;
                }
        }
 
@@ -597,7 +597,7 @@ struct smbw_server *smbw_server(char *server, char *share)
        return srv;
 
  failed:
-       cli_shutdown(&c);
+       cli_shutdown(c);
        if (!srv) return NULL;
 
        SAFE_FREE(srv->server_name);
index 3f0b1cbb4431bb246ba27068281910604eca9dae..f64cb209649c9c215fa0605ba3f66f040c96a1a0 100644 (file)
@@ -32,7 +32,7 @@
 
 struct smbw_server {
        struct smbw_server *next, *prev;
-       struct cli_state cli;
+       struct cli_state *cli;
        char *server_name;
        char *share_name;
        char *workgroup;
diff --git a/source/tdb/dump.c b/source/tdb/dump.c
new file mode 100644 (file)
index 0000000..577f23a
--- /dev/null
@@ -0,0 +1,135 @@
+ /* 
+   Unix SMB/CIFS implementation.
+
+   trivial database library
+
+   Copyright (C) Andrew Tridgell              1999-2005
+   Copyright (C) Paul `Rusty' Russell             2000
+   Copyright (C) Jeremy Allison                           2000-2003
+   
+     ** NOTE! The following LGPL license applies to the tdb
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "tdb_private.h"
+
+static tdb_off_t tdb_dump_record(struct tdb_context *tdb, tdb_off_t offset)
+{
+       struct list_struct rec;
+       tdb_off_t tailer_ofs, tailer;
+
+       if (tdb->methods->tdb_read(tdb, offset, (char *)&rec, 
+                                  sizeof(rec), DOCONV()) == -1) {
+               printf("ERROR: failed to read record at %u\n", offset);
+               return 0;
+       }
+
+       printf(" rec: offset=0x%08x next=0x%08x rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n",
+              offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, rec.full_hash, rec.magic);
+
+       tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off_t);
+
+       if (tdb_ofs_read(tdb, tailer_ofs, &tailer) == -1) {
+               printf("ERROR: failed to read tailer at %u\n", tailer_ofs);
+               return rec.next;
+       }
+
+       if (tailer != rec.rec_len + sizeof(rec)) {
+               printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n",
+                               (unsigned int)tailer, (unsigned int)(rec.rec_len + sizeof(rec)));
+       }
+       return rec.next;
+}
+
+static int tdb_dump_chain(struct tdb_context *tdb, int i)
+{
+       tdb_off_t rec_ptr, top;
+
+       top = TDB_HASH_TOP(i);
+
+       if (tdb_lock(tdb, i, F_WRLCK) != 0)
+               return -1;
+
+       if (tdb_ofs_read(tdb, top, &rec_ptr) == -1)
+               return tdb_unlock(tdb, i, F_WRLCK);
+
+       if (rec_ptr)
+               printf("hash=%d\n", i);
+
+       while (rec_ptr) {
+               rec_ptr = tdb_dump_record(tdb, rec_ptr);
+       }
+
+       return tdb_unlock(tdb, i, F_WRLCK);
+}
+
+void tdb_dump_all(struct tdb_context *tdb)
+{
+       int i;
+       for (i=0;i<tdb->header.hash_size;i++) {
+               tdb_dump_chain(tdb, i);
+       }
+       printf("freelist:\n");
+       tdb_dump_chain(tdb, -1);
+}
+
+int tdb_printfreelist(struct tdb_context *tdb)
+{
+       int ret;
+       long total_free = 0;
+       tdb_off_t offset, rec_ptr;
+       struct list_struct rec;
+
+       if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0)
+               return ret;
+
+       offset = FREELIST_TOP;
+
+       /* read in the freelist top */
+       if (tdb_ofs_read(tdb, offset, &rec_ptr) == -1) {
+               tdb_unlock(tdb, -1, F_WRLCK);
+               return 0;
+       }
+
+       printf("freelist top=[0x%08x]\n", rec_ptr );
+       while (rec_ptr) {
+               if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec, 
+                                          sizeof(rec), DOCONV()) == -1) {
+                       tdb_unlock(tdb, -1, F_WRLCK);
+                       return -1;
+               }
+
+               if (rec.magic != TDB_FREE_MAGIC) {
+                       printf("bad magic 0x%08x in free list\n", rec.magic);
+                       tdb_unlock(tdb, -1, F_WRLCK);
+                       return -1;
+               }
+
+               printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n", 
+                      rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len);
+               total_free += rec.rec_len;
+
+               /* move to the next record */
+               rec_ptr = rec.next;
+       }
+       printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, 
+               (int)total_free);
+
+       return tdb_unlock(tdb, -1, F_WRLCK);
+}
+
diff --git a/source/tdb/error.c b/source/tdb/error.c
new file mode 100644 (file)
index 0000000..4cf33a2
--- /dev/null
@@ -0,0 +1,58 @@
+ /* 
+   Unix SMB/CIFS implementation.
+
+   trivial database library
+
+   Copyright (C) Andrew Tridgell              1999-2005
+   Copyright (C) Paul `Rusty' Russell             2000
+   Copyright (C) Jeremy Allison                           2000-2003
+   
+     ** NOTE! The following LGPL license applies to the tdb
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "tdb_private.h"
+
+enum TDB_ERROR tdb_error(struct tdb_context *tdb)
+{
+       return tdb->ecode;
+}
+
+static struct tdb_errname {
+       enum TDB_ERROR ecode; const char *estring;
+} emap[] = { {TDB_SUCCESS, "Success"},
+            {TDB_ERR_CORRUPT, "Corrupt database"},
+            {TDB_ERR_IO, "IO Error"},
+            {TDB_ERR_LOCK, "Locking error"},
+            {TDB_ERR_OOM, "Out of memory"},
+            {TDB_ERR_EXISTS, "Record exists"},
+            {TDB_ERR_NOLOCK, "Lock exists on other keys"},
+            {TDB_ERR_EINVAL, "Invalid parameter"},
+            {TDB_ERR_NOEXIST, "Record does not exist"},
+            {TDB_ERR_RDONLY, "write not permitted"} };
+
+/* Error string for the last tdb error */
+const char *tdb_errorstr(struct tdb_context *tdb)
+{
+       u32 i;
+       for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++)
+               if (tdb->ecode == emap[i].ecode)
+                       return emap[i].estring;
+       return "Invalid error code";
+}
+
diff --git a/source/tdb/freelist.c b/source/tdb/freelist.c
new file mode 100644 (file)
index 0000000..3483751
--- /dev/null
@@ -0,0 +1,331 @@
+ /* 
+   Unix SMB/CIFS implementation.
+
+   trivial database library
+
+   Copyright (C) Andrew Tridgell              1999-2005
+   Copyright (C) Paul `Rusty' Russell             2000
+   Copyright (C) Jeremy Allison                           2000-2003
+   
+     ** NOTE! The following LGPL license applies to the tdb
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "tdb_private.h"
+
+/* read a freelist record and check for simple errors */
+static int rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec)
+{
+       if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1)
+               return -1;
+
+       if (rec->magic == TDB_MAGIC) {
+               /* this happens when a app is showdown while deleting a record - we should
+                  not completely fail when this happens */
+               TDB_LOG((tdb, 0,"rec_free_read non-free magic 0x%x at offset=%d - fixing\n", 
+                        rec->magic, off));
+               rec->magic = TDB_FREE_MAGIC;
+               if (tdb->methods->tdb_write(tdb, off, rec, sizeof(*rec)) == -1)
+                       return -1;
+       }
+
+       if (rec->magic != TDB_FREE_MAGIC) {
+               /* Ensure ecode is set for log fn. */
+               tdb->ecode = TDB_ERR_CORRUPT;
+               TDB_LOG((tdb, 0,"rec_free_read bad magic 0x%x at offset=%d\n", 
+                          rec->magic, off));
+               return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
+       }
+       if (tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0)
+               return -1;
+       return 0;
+}
+
+
+
+/* Remove an element from the freelist.  Must have alloc lock. */
+static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_t next)
+{
+       tdb_off_t last_ptr, i;
+
+       /* read in the freelist top */
+       last_ptr = FREELIST_TOP;
+       while (tdb_ofs_read(tdb, last_ptr, &i) != -1 && i != 0) {
+               if (i == off) {
+                       /* We've found it! */
+                       return tdb_ofs_write(tdb, last_ptr, &next);
+               }
+               /* Follow chain (next offset is at start of record) */
+               last_ptr = i;
+       }
+       TDB_LOG((tdb, 0,"remove_from_freelist: not on list at off=%d\n", off));
+       return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
+}
+
+
+/* update a record tailer (must hold allocation lock) */
+static int update_tailer(struct tdb_context *tdb, tdb_off_t offset,
+                        const struct list_struct *rec)
+{
+       tdb_off_t totalsize;
+
+       /* Offset of tailer from record header */
+       totalsize = sizeof(*rec) + rec->rec_len;
+       return tdb_ofs_write(tdb, offset + totalsize - sizeof(tdb_off_t),
+                        &totalsize);
+}
+
+/* Add an element into the freelist. Merge adjacent records if
+   neccessary. */
+int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
+{
+       tdb_off_t right, left;
+
+       /* Allocation and tailer lock */
+       if (tdb_lock(tdb, -1, F_WRLCK) != 0)
+               return -1;
+
+       /* set an initial tailer, so if we fail we don't leave a bogus record */
+       if (update_tailer(tdb, offset, rec) != 0) {
+               TDB_LOG((tdb, 0, "tdb_free: upfate_tailer failed!\n"));
+               goto fail;
+       }
+
+       /* Look right first (I'm an Australian, dammit) */
+       right = offset + sizeof(*rec) + rec->rec_len;
+       if (right + sizeof(*rec) <= tdb->map_size) {
+               struct list_struct r;
+
+               if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) {
+                       TDB_LOG((tdb, 0, "tdb_free: right read failed at %u\n", right));
+                       goto left;
+               }
+
+               /* If it's free, expand to include it. */
+               if (r.magic == TDB_FREE_MAGIC) {
+                       if (remove_from_freelist(tdb, right, r.next) == -1) {
+                               TDB_LOG((tdb, 0, "tdb_free: right free failed at %u\n", right));
+                               goto left;
+                       }
+                       rec->rec_len += sizeof(r) + r.rec_len;
+               }
+       }
+
+left:
+       /* Look left */
+       left = offset - sizeof(tdb_off_t);
+       if (left > TDB_DATA_START(tdb->header.hash_size)) {
+               struct list_struct l;
+               tdb_off_t leftsize;
+               
+               /* Read in tailer and jump back to header */
+               if (tdb_ofs_read(tdb, left, &leftsize) == -1) {
+                       TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left));
+                       goto update;
+               }
+
+               /* it could be uninitialised data */
+               if (leftsize == 0 || leftsize == TDB_PAD_U32) {
+                       goto update;
+               }
+
+               left = offset - leftsize;
+
+               /* Now read in record */
+               if (tdb->methods->tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) {
+                       TDB_LOG((tdb, 0, "tdb_free: left read failed at %u (%u)\n", left, leftsize));
+                       goto update;
+               }
+
+               /* If it's free, expand to include it. */
+               if (l.magic == TDB_FREE_MAGIC) {
+                       if (remove_from_freelist(tdb, left, l.next) == -1) {
+                               TDB_LOG((tdb, 0, "tdb_free: left free failed at %u\n", left));
+                               goto update;
+                       } else {
+                               offset = left;
+                               rec->rec_len += leftsize;
+                       }
+               }
+       }
+
+update:
+       if (update_tailer(tdb, offset, rec) == -1) {
+               TDB_LOG((tdb, 0, "tdb_free: update_tailer failed at %u\n", offset));
+               goto fail;
+       }
+
+       /* Now, prepend to free list */
+       rec->magic = TDB_FREE_MAGIC;
+
+       if (tdb_ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 ||
+           tdb_rec_write(tdb, offset, rec) == -1 ||
+           tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) {
+               TDB_LOG((tdb, 0, "tdb_free record write failed at offset=%d\n", offset));
+               goto fail;
+       }
+
+       /* And we're done. */
+       tdb_unlock(tdb, -1, F_WRLCK);
+       return 0;
+
+ fail:
+       tdb_unlock(tdb, -1, F_WRLCK);
+       return -1;
+}
+
+
+/* 
+   the core of tdb_allocate - called when we have decided which
+   free list entry to use
+ */
+static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, tdb_len_t length, tdb_off_t rec_ptr,
+                               struct list_struct *rec, tdb_off_t last_ptr)
+{
+       struct list_struct newrec;
+       tdb_off_t newrec_ptr;
+
+       memset(&newrec, '\0', sizeof(newrec));
+
+       /* found it - now possibly split it up  */
+       if (rec->rec_len > length + MIN_REC_SIZE) {
+               /* Length of left piece */
+               length = TDB_ALIGN(length, TDB_ALIGNMENT);
+               
+               /* Right piece to go on free list */
+               newrec.rec_len = rec->rec_len - (sizeof(*rec) + length);
+               newrec_ptr = rec_ptr + sizeof(*rec) + length;
+               
+               /* And left record is shortened */
+               rec->rec_len = length;
+       } else {
+               newrec_ptr = 0;
+       }
+       
+       /* Remove allocated record from the free list */
+       if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) {
+               return 0;
+       }
+       
+       /* Update header: do this before we drop alloc
+          lock, otherwise tdb_free() might try to
+          merge with us, thinking we're free.
+          (Thanks Jeremy Allison). */
+       rec->magic = TDB_MAGIC;
+       if (tdb_rec_write(tdb, rec_ptr, rec) == -1) {
+               return 0;
+       }
+       
+       /* Did we create new block? */
+       if (newrec_ptr) {
+               /* Update allocated record tailer (we
+                  shortened it). */
+               if (update_tailer(tdb, rec_ptr, rec) == -1) {
+                       return 0;
+               }
+               
+               /* Free new record */
+               if (tdb_free(tdb, newrec_ptr, &newrec) == -1) {
+                       return 0;
+               }
+       }
+       
+       /* all done - return the new record offset */
+       return rec_ptr;
+}
+
+/* allocate some space from the free list. The offset returned points
+   to a unconnected list_struct within the database with room for at
+   least length bytes of total data
+
+   0 is returned if the space could not be allocated
+ */
+tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec)
+{
+       tdb_off_t rec_ptr, last_ptr, newrec_ptr;
+       struct {
+               tdb_off_t rec_ptr, last_ptr;
+               tdb_len_t rec_len;
+       } bestfit;
+
+       if (tdb_lock(tdb, -1, F_WRLCK) == -1)
+               return 0;
+
+       /* Extra bytes required for tailer */
+       length += sizeof(tdb_off_t);
+
+ again:
+       last_ptr = FREELIST_TOP;
+
+       /* read in the freelist top */
+       if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1)
+               goto fail;
+
+       bestfit.rec_ptr = 0;
+       bestfit.last_ptr = 0;
+       bestfit.rec_len = 0;
+
+       /* 
+          this is a best fit allocation strategy. Originally we used
+          a first fit strategy, but it suffered from massive fragmentation
+          issues when faced with a slowly increasing record size.
+        */
+       while (rec_ptr) {
+               if (rec_free_read(tdb, rec_ptr, rec) == -1) {
+                       goto fail;
+               }
+
+               if (rec->rec_len >= length) {
+                       if (bestfit.rec_ptr == 0 ||
+                           rec->rec_len < bestfit.rec_len) {
+                               bestfit.rec_len = rec->rec_len;
+                               bestfit.rec_ptr = rec_ptr;
+                               bestfit.last_ptr = last_ptr;
+                               /* consider a fit to be good enough if
+                                  we aren't wasting more than half
+                                  the space */
+                               if (bestfit.rec_len < 2*length) {
+                                       break;
+                               }
+                       }
+               }
+
+               /* move to the next record */
+               last_ptr = rec_ptr;
+               rec_ptr = rec->next;
+       }
+
+       if (bestfit.rec_ptr != 0) {
+               if (rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) {
+                       goto fail;
+               }
+
+               newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr);
+               tdb_unlock(tdb, -1, F_WRLCK);
+               return newrec_ptr;
+       }
+
+       /* we didn't find enough space. See if we can expand the
+          database and if we can then try again */
+       if (tdb_expand(tdb, length + sizeof(*rec)) == 0)
+               goto again;
+ fail:
+       tdb_unlock(tdb, -1, F_WRLCK);
+       return 0;
+}
+
diff --git a/source/tdb/io.c b/source/tdb/io.c
new file mode 100644 (file)
index 0000000..ac6f4cd
--- /dev/null
@@ -0,0 +1,412 @@
+ /* 
+   Unix SMB/CIFS implementation.
+
+   trivial database library
+
+   Copyright (C) Andrew Tridgell              1999-2005
+   Copyright (C) Paul `Rusty' Russell             2000
+   Copyright (C) Jeremy Allison                           2000-2003
+   
+     ** NOTE! The following LGPL license applies to the tdb
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#include "tdb_private.h"
+
+#ifndef HAVE_PREAD
+ static ssize_t pread(int fd, void *buf, size_t count, off_t offset)
+{
+       if (lseek(fd, offset, SEEK_SET) != offset) {
+               errno = EIO;
+               return -1;
+       }
+       return read(fd, buf, count);
+}
+#endif
+
+#ifndef HAVE_PWRITE
+ static ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
+{
+       if (lseek(fd, offset, SEEK_SET) != offset) {
+               errno = EIO;
+               return -1;
+       }
+       return write(fd, buf, count);
+}
+#endif
+
+/* check for an out of bounds access - if it is out of bounds then
+   see if the database has been expanded by someone else and expand
+   if necessary 
+   note that "len" is the minimum length needed for the db
+*/
+static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe)
+{
+       struct stat st;
+       if (len <= tdb->map_size)
+               return 0;
+       if (tdb->flags & TDB_INTERNAL) {
+               if (!probe) {
+                       /* Ensure ecode is set for log fn. */
+                       tdb->ecode = TDB_ERR_IO;
+                       TDB_LOG((tdb, 0,"tdb_oob len %d beyond internal malloc size %d\n",
+                                (int)len, (int)tdb->map_size));
+               }
+               return TDB_ERRCODE(TDB_ERR_IO, -1);
+       }
+
+       if (fstat(tdb->fd, &st) == -1) {
+               return TDB_ERRCODE(TDB_ERR_IO, -1);
+       }
+
+       if (st.st_size < (size_t)len) {
+               if (!probe) {
+                       /* Ensure ecode is set for log fn. */
+                       tdb->ecode = TDB_ERR_IO;
+                       TDB_LOG((tdb, 0,"tdb_oob len %d beyond eof at %d\n",
+                                (int)len, (int)st.st_size));
+               }
+               return TDB_ERRCODE(TDB_ERR_IO, -1);
+       }
+
+       /* Unmap, update size, remap */
+       if (tdb_munmap(tdb) == -1)
+               return TDB_ERRCODE(TDB_ERR_IO, -1);
+       tdb->map_size = st.st_size;
+       tdb_mmap(tdb);
+       return 0;
+}
+
+/* write a lump of data at a specified offset */
+static int tdb_write(struct tdb_context *tdb, tdb_off_t off, 
+                    const void *buf, tdb_len_t len)
+{
+       if (len == 0) {
+               return 0;
+       }
+
+       if (tdb->read_only || tdb->traverse_read) {
+               tdb->ecode = TDB_ERR_RDONLY;
+               return -1;
+       }
+
+       if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0)
+               return -1;
+
+       if (tdb->map_ptr) {
+               memcpy(off + (char *)tdb->map_ptr, buf, len);
+       } else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) {
+               /* Ensure ecode is set for log fn. */
+               tdb->ecode = TDB_ERR_IO;
+               TDB_LOG((tdb, 0,"tdb_write failed at %d len=%d (%s)\n",
+                          off, len, strerror(errno)));
+               return TDB_ERRCODE(TDB_ERR_IO, -1);
+       }
+       return 0;
+}
+
+/* Endian conversion: we only ever deal with 4 byte quantities */
+void *tdb_convert(void *buf, u32 size)
+{
+       u32 i, *p = buf;
+       for (i = 0; i < size / 4; i++)
+               p[i] = TDB_BYTEREV(p[i]);
+       return buf;
+}
+
+
+/* read a lump of data at a specified offset, maybe convert */
+static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, 
+                   tdb_len_t len, int cv)
+{
+       if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) {
+               return -1;
+       }
+
+       if (tdb->map_ptr) {
+               memcpy(buf, off + (char *)tdb->map_ptr, len);
+       } else {
+               ssize_t ret = pread(tdb->fd, buf, len, off);
+               if (ret != (ssize_t)len) {
+                       /* Ensure ecode is set for log fn. */
+                       tdb->ecode = TDB_ERR_IO;
+                       TDB_LOG((tdb, 0,"tdb_read failed at %d len=%d ret=%d (%s) map_size=%d\n",
+                                off, len, (int)ret, strerror(errno), (int)tdb->map_size));
+                       return TDB_ERRCODE(TDB_ERR_IO, -1);
+               }
+       }
+       if (cv) {
+               tdb_convert(buf, len);
+       }
+       return 0;
+}
+
+
+
+/*
+  do an unlocked scan of the hash table heads to find the next non-zero head. The value
+  will then be confirmed with the lock held
+*/             
+static void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain)
+{
+       u32 h = *chain;
+       if (tdb->map_ptr) {
+               for (;h < tdb->header.hash_size;h++) {
+                       if (0 != *(u32 *)(TDB_HASH_TOP(h) + (unsigned char *)tdb->map_ptr)) {
+                               break;
+                       }
+               }
+       } else {
+               u32 off=0;
+               for (;h < tdb->header.hash_size;h++) {
+                       if (tdb_ofs_read(tdb, TDB_HASH_TOP(h), &off) != 0 || off != 0) {
+                               break;
+                       }
+               }
+       }
+       (*chain) = h;
+}
+
+
+int tdb_munmap(struct tdb_context *tdb)
+{
+       if (tdb->flags & TDB_INTERNAL)
+               return 0;
+
+#ifdef HAVE_MMAP
+       if (tdb->map_ptr) {
+               int ret = munmap(tdb->map_ptr, tdb->map_size);
+               if (ret != 0)
+                       return ret;
+       }
+#endif
+       tdb->map_ptr = NULL;
+       return 0;
+}
+
+void tdb_mmap(struct tdb_context *tdb)
+{
+       if (tdb->flags & TDB_INTERNAL)
+               return;
+
+#ifdef HAVE_MMAP
+       if (!(tdb->flags & TDB_NOMMAP)) {
+               tdb->map_ptr = mmap(NULL, tdb->map_size, 
+                                   PROT_READ|(tdb->read_only? 0:PROT_WRITE), 
+                                   MAP_SHARED|MAP_FILE, tdb->fd, 0);
+
+               /*
+                * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!!
+                */
+
+               if (tdb->map_ptr == MAP_FAILED) {
+                       tdb->map_ptr = NULL;
+                       TDB_LOG((tdb, 2, "tdb_mmap failed for size %d (%s)\n", 
+                                tdb->map_size, strerror(errno)));
+               }
+       } else {
+               tdb->map_ptr = NULL;
+       }
+#else
+       tdb->map_ptr = NULL;
+#endif
+}
+
+/* expand a file.  we prefer to use ftruncate, as that is what posix
+  says to use for mmap expansion */
+static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t addition)
+{
+       char buf[1024];
+
+       if (tdb->read_only || tdb->traverse_read) {
+               tdb->ecode = TDB_ERR_RDONLY;
+               return -1;
+       }
+
+       if (ftruncate(tdb->fd, size+addition) == -1) {
+               char b = 0;
+               if (pwrite(tdb->fd,  &b, 1, (size+addition) - 1) != 1) {
+                       TDB_LOG((tdb, 0, "expand_file to %d failed (%s)\n", 
+                                size+addition, strerror(errno)));
+                       return -1;
+               }
+       }
+
+       /* now fill the file with something. This ensures that the
+          file isn't sparse, which would be very bad if we ran out of
+          disk. This must be done with write, not via mmap */
+       memset(buf, TDB_PAD_BYTE, sizeof(buf));
+       while (addition) {
+               int n = addition>sizeof(buf)?sizeof(buf):addition;
+               int ret = pwrite(tdb->fd, buf, n, size);
+               if (ret != n) {
+                       TDB_LOG((tdb, 0, "expand_file write of %d failed (%s)\n", 
+                                  n, strerror(errno)));
+                       return -1;
+               }
+               addition -= n;
+               size += n;
+       }
+       return 0;
+}
+
+
+/* expand the database at least size bytes by expanding the underlying
+   file and doing the mmap again if necessary */
+int tdb_expand(struct tdb_context *tdb, tdb_off_t size)
+{
+       struct list_struct rec;
+       tdb_off_t offset;
+
+       if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
+               TDB_LOG((tdb, 0, "lock failed in tdb_expand\n"));
+               return -1;
+       }
+
+       /* must know about any previous expansions by another process */
+       tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1);
+
+       /* always make room for at least 10 more records, and round
+           the database up to a multiple of the page size */
+       size = TDB_ALIGN(tdb->map_size + size*10, tdb->page_size) - tdb->map_size;
+
+       if (!(tdb->flags & TDB_INTERNAL))
+               tdb_munmap(tdb);
+
+       /*
+        * We must ensure the file is unmapped before doing this
+        * to ensure consistency with systems like OpenBSD where
+        * writes and mmaps are not consistent.
+        */
+
+       /* expand the file itself */
+       if (!(tdb->flags & TDB_INTERNAL)) {
+               if (tdb->methods->tdb_expand_file(tdb, tdb->map_size, size) != 0)
+                       goto fail;
+       }
+
+       tdb->map_size += size;
+
+       if (tdb->flags & TDB_INTERNAL) {
+               char *new_map_ptr = realloc(tdb->map_ptr, tdb->map_size);
+               if (!new_map_ptr) {
+                       tdb->map_size -= size;
+                       goto fail;
+               }
+               tdb->map_ptr = new_map_ptr;
+       } else {
+               /*
+                * We must ensure the file is remapped before adding the space
+                * to ensure consistency with systems like OpenBSD where
+                * writes and mmaps are not consistent.
+                */
+
+               /* We're ok if the mmap fails as we'll fallback to read/write */
+               tdb_mmap(tdb);
+       }
+
+       /* form a new freelist record */
+       memset(&rec,'\0',sizeof(rec));
+       rec.rec_len = size - sizeof(rec);
+
+       /* link it into the free list */
+       offset = tdb->map_size - size;
+       if (tdb_free(tdb, offset, &rec) == -1)
+               goto fail;
+
+       tdb_unlock(tdb, -1, F_WRLCK);
+       return 0;
+ fail:
+       tdb_unlock(tdb, -1, F_WRLCK);
+       return -1;
+}
+
+/* read/write a tdb_off_t */
+int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d)
+{
+       return tdb->methods->tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV());
+}
+
+int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d)
+{
+       tdb_off_t off = *d;
+       return tdb->methods->tdb_write(tdb, offset, CONVERT(off), sizeof(*d));
+}
+
+
+/* read a lump of data, allocating the space for it */
+char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len)
+{
+       char *buf;
+
+       /* some systems don't like zero length malloc */
+       if (len == 0) {
+               len = 1;
+       }
+
+       if (!(buf = malloc(len))) {
+               /* Ensure ecode is set for log fn. */
+               tdb->ecode = TDB_ERR_OOM;
+               TDB_LOG((tdb, 0,"tdb_alloc_read malloc failed len=%d (%s)\n",
+                          len, strerror(errno)));
+               return TDB_ERRCODE(TDB_ERR_OOM, buf);
+       }
+       if (tdb->methods->tdb_read(tdb, offset, buf, len, 0) == -1) {
+               SAFE_FREE(buf);
+               return NULL;
+       }
+       return buf;
+}
+
+/* read/write a record */
+int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
+{
+       if (tdb->methods->tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1)
+               return -1;
+       if (TDB_BAD_MAGIC(rec)) {
+               /* Ensure ecode is set for log fn. */
+               tdb->ecode = TDB_ERR_CORRUPT;
+               TDB_LOG((tdb, 0,"tdb_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset));
+               return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
+       }
+       return tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0);
+}
+
+int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
+{
+       struct list_struct r = *rec;
+       return tdb->methods->tdb_write(tdb, offset, CONVERT(r), sizeof(r));
+}
+
+static const struct tdb_methods io_methods = {
+       tdb_read,
+       tdb_write,
+       tdb_next_hash_chain,
+       tdb_oob,
+       tdb_expand_file,
+       tdb_brlock
+};
+
+/*
+  initialise the default methods table
+*/
+void tdb_io_init(struct tdb_context *tdb)
+{
+       tdb->methods = &io_methods;
+}
diff --git a/source/tdb/lock.c b/source/tdb/lock.c
new file mode 100644 (file)
index 0000000..a96d77a
--- /dev/null
@@ -0,0 +1,276 @@
+ /* 
+   Unix SMB/CIFS implementation.
+
+   trivial database library
+
+   Copyright (C) Andrew Tridgell              1999-2005
+   Copyright (C) Paul `Rusty' Russell             2000
+   Copyright (C) Jeremy Allison                           2000-2003
+   
+     ** NOTE! The following LGPL license applies to the tdb
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "tdb_private.h"
+
+/* a byte range locking function - return 0 on success
+   this functions locks/unlocks 1 byte at the specified offset.
+
+   On error, errno is also set so that errors are passed back properly
+   through tdb_open(). 
+
+   note that a len of zero means lock to end of file
+*/
+int tdb_brlock_len(struct tdb_context *tdb, tdb_off_t offset, 
+                  int rw_type, int lck_type, int probe, size_t len)
+{
+       struct flock fl;
+       int ret;
+
+       if (tdb->flags & TDB_NOLOCK) {
+               return 0;
+       }
+
+       if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) {
+               tdb->ecode = TDB_ERR_RDONLY;
+               return -1;
+       }
+
+       fl.l_type = rw_type;
+       fl.l_whence = SEEK_SET;
+       fl.l_start = offset;
+       fl.l_len = len;
+       fl.l_pid = 0;
+
+       do {
+               ret = fcntl(tdb->fd,lck_type,&fl);
+       } while (ret == -1 && errno == EINTR);
+
+       if (ret == -1) {
+               /* Generic lock error. errno set by fcntl.
+                * EAGAIN is an expected return from non-blocking
+                * locks. */
+               if (!probe && lck_type != F_SETLK) {
+                       /* Ensure error code is set for log fun to examine. */
+                       tdb->ecode = TDB_ERR_LOCK;
+                       TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n", 
+                                tdb->fd, offset, rw_type, lck_type, (int)len));
+               }
+               return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+       }
+       return 0;
+}
+
+
+/*
+  upgrade a read lock to a write lock. This needs to be handled in a
+  special way as some OSes (such as solaris) have too conservative
+  deadlock detection and claim a deadlock when progress can be
+  made. For those OSes we may loop for a while.  
+*/
+int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len)
+{
+       int count = 1000;
+       while (count--) {
+               struct timeval tv;
+               if (tdb_brlock_len(tdb, offset, F_WRLCK, F_SETLKW, 1, len) == 0) {
+                       return 0;
+               }
+               if (errno != EDEADLK) {
+                       break;
+               }
+               /* sleep for as short a time as we can - more portable than usleep() */
+               tv.tv_sec = 0;
+               tv.tv_usec = 1;
+               select(0, NULL, NULL, NULL, &tv);
+       }
+       TDB_LOG((tdb, 5,"tdb_brlock_upgrade failed at offset %d\n", offset));
+       return -1;
+}
+
+
+/* a byte range locking function - return 0 on success
+   this functions locks/unlocks 1 byte at the specified offset.
+
+   On error, errno is also set so that errors are passed back properly
+   through tdb_open(). */
+int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, 
+              int rw_type, int lck_type, int probe)
+{
+       return tdb_brlock_len(tdb, offset, rw_type, lck_type, probe, 1);
+}
+
+/* lock a list in the database. list -1 is the alloc list */
+int tdb_lock(struct tdb_context *tdb, int list, int ltype)
+{
+       if (list < -1 || list >= (int)tdb->header.hash_size) {
+               TDB_LOG((tdb, 0,"tdb_lock: invalid list %d for ltype=%d\n", 
+                          list, ltype));
+               return -1;
+       }
+       if (tdb->flags & TDB_NOLOCK)
+               return 0;
+
+       /* Since fcntl locks don't nest, we do a lock for the first one,
+          and simply bump the count for future ones */
+       if (tdb->locked[list+1].count == 0) {
+               if (tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) {
+                       TDB_LOG((tdb, 0,"tdb_lock failed on list %d ltype=%d (%s)\n", 
+                                list, ltype, strerror(errno)));
+                       return -1;
+               }
+               tdb->locked[list+1].ltype = ltype;
+               tdb->num_locks++;
+       }
+       tdb->locked[list+1].count++;
+       return 0;
+}
+
+/* unlock the database: returns void because it's too late for errors. */
+       /* changed to return int it may be interesting to know there
+          has been an error  --simo */
+int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
+{
+       int ret = -1;
+
+       if (tdb->flags & TDB_NOLOCK)
+               return 0;
+
+       /* Sanity checks */
+       if (list < -1 || list >= (int)tdb->header.hash_size) {
+               TDB_LOG((tdb, 0, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size));
+               return ret;
+       }
+
+       if (tdb->locked[list+1].count==0) {
+               TDB_LOG((tdb, 0, "tdb_unlock: count is 0\n"));
+               return ret;
+       }
+
+       if (tdb->locked[list+1].count == 1) {
+               /* Down to last nested lock: unlock underneath */
+               ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, F_SETLKW, 0);
+               tdb->num_locks--;
+       } else {
+               ret = 0;
+       }
+       tdb->locked[list+1].count--;
+
+       if (ret)
+               TDB_LOG((tdb, 0,"tdb_unlock: An error occurred unlocking!\n")); 
+       return ret;
+}
+
+
+
+/* lock/unlock entire database */
+int tdb_lockall(struct tdb_context *tdb)
+{
+       u32 i;
+
+       /* There are no locks on read-only dbs */
+       if (tdb->read_only || tdb->traverse_read)
+               return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+       for (i = 0; i < tdb->header.hash_size; i++) 
+               if (tdb_lock(tdb, i, F_WRLCK))
+                       break;
+
+       /* If error, release locks we have... */
+       if (i < tdb->header.hash_size) {
+               u32 j;
+
+               for ( j = 0; j < i; j++)
+                       tdb_unlock(tdb, j, F_WRLCK);
+               return TDB_ERRCODE(TDB_ERR_NOLOCK, -1);
+       }
+
+       return 0;
+}
+void tdb_unlockall(struct tdb_context *tdb)
+{
+       u32 i;
+       for (i=0; i < tdb->header.hash_size; i++)
+               tdb_unlock(tdb, i, F_WRLCK);
+}
+
+/* lock/unlock one hash chain. This is meant to be used to reduce
+   contention - it cannot guarantee how many records will be locked */
+int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key)
+{
+       return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
+}
+
+int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
+{
+       return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
+}
+
+int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key)
+{
+       return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
+}
+
+int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key)
+{
+       return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
+}
+
+
+
+/* record lock stops delete underneath */
+int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off)
+{
+       return off ? tdb->methods->tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0) : 0;
+}
+
+/*
+  Write locks override our own fcntl readlocks, so check it here.
+  Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not
+  an error to fail to get the lock here.
+*/
+int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off)
+{
+       struct tdb_traverse_lock *i;
+       for (i = &tdb->travlocks; i; i = i->next)
+               if (i->off == off)
+                       return -1;
+       return tdb->methods->tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1);
+}
+
+/*
+  Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not
+  an error to fail to get the lock here.
+*/
+int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off)
+{
+       return tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0);
+}
+
+/* fcntl locks don't stack: avoid unlocking someone else's */
+int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off)
+{
+       struct tdb_traverse_lock *i;
+       u32 count = 0;
+
+       if (off == 0)
+               return 0;
+       for (i = &tdb->travlocks; i; i = i->next)
+               if (i->off == off)
+                       count++;
+       return (count == 1 ? tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0) : 0);
+}
diff --git a/source/tdb/open.c b/source/tdb/open.c
new file mode 100644 (file)
index 0000000..cb4a9cd
--- /dev/null
@@ -0,0 +1,453 @@
+ /* 
+   Unix SMB/CIFS implementation.
+
+   trivial database library
+
+   Copyright (C) Andrew Tridgell              1999-2005
+   Copyright (C) Paul `Rusty' Russell             2000
+   Copyright (C) Jeremy Allison                           2000-2003
+   
+     ** NOTE! The following LGPL license applies to the tdb
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "tdb_private.h"
+
+/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */
+static struct tdb_context *tdbs = NULL;
+
+
+/* This is based on the hash algorithm from gdbm */
+static unsigned int default_tdb_hash(TDB_DATA *key)
+{
+       u32 value;      /* Used to compute the hash value.  */
+       u32   i;        /* Used to cycle through random values. */
+
+       /* Set the initial value from the key size. */
+       for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
+               value = (value + (key->dptr[i] << (i*5 % 24)));
+
+       return (1103515243 * value + 12345);  
+}
+
+
+/* initialise a new database with a specified hash size */
+static int tdb_new_database(struct tdb_context *tdb, int hash_size)
+{
+       struct tdb_header *newdb;
+       int size, ret = -1;
+
+       /* We make it up in memory, then write it out if not internal */
+       size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t);
+       if (!(newdb = calloc(size, 1)))
+               return TDB_ERRCODE(TDB_ERR_OOM, -1);
+
+       /* Fill in the header */
+       newdb->version = TDB_VERSION;
+       newdb->hash_size = hash_size;
+       if (tdb->flags & TDB_INTERNAL) {
+               tdb->map_size = size;
+               tdb->map_ptr = (char *)newdb;
+               memcpy(&tdb->header, newdb, sizeof(tdb->header));
+               /* Convert the `ondisk' version if asked. */
+               CONVERT(*newdb);
+               return 0;
+       }
+       if (lseek(tdb->fd, 0, SEEK_SET) == -1)
+               goto fail;
+
+       if (ftruncate(tdb->fd, 0) == -1)
+               goto fail;
+
+       /* This creates an endian-converted header, as if read from disk */
+       CONVERT(*newdb);
+       memcpy(&tdb->header, newdb, sizeof(tdb->header));
+       /* Don't endian-convert the magic food! */
+       memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
+       if (write(tdb->fd, newdb, size) != size) {
+               ret = -1;
+       } else {
+               ret = 0;
+       }
+
+  fail:
+       SAFE_FREE(newdb);
+       return ret;
+}
+
+
+
+static int tdb_already_open(dev_t device,
+                           ino_t ino)
+{
+       struct tdb_context *i;
+       
+       for (i = tdbs; i; i = i->next) {
+               if (i->device == device && i->inode == ino) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+/* open the database, creating it if necessary 
+
+   The open_flags and mode are passed straight to the open call on the
+   database file. A flags value of O_WRONLY is invalid. The hash size
+   is advisory, use zero for a default value.
+
+   Return is NULL on error, in which case errno is also set.  Don't 
+   try to call tdb_error or tdb_errname, just do strerror(errno).
+
+   @param name may be NULL for internal databases. */
+struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags,
+                     int open_flags, mode_t mode)
+{
+       return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL);
+}
+
+/* a default logging function */
+static void null_log_fn(struct tdb_context *tdb, int level, const char *fmt, ...)
+{
+}
+
+
+struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
+                        int open_flags, mode_t mode,
+                        tdb_log_func log_fn,
+                        tdb_hash_func hash_fn)
+{
+       struct tdb_context *tdb;
+       struct stat st;
+       int rev = 0, locked = 0;
+       unsigned char *vp;
+       u32 vertest;
+
+       if (!(tdb = calloc(1, sizeof *tdb))) {
+               /* Can't log this */
+               errno = ENOMEM;
+               goto fail;
+       }
+       tdb_io_init(tdb);
+       tdb->fd = -1;
+       tdb->name = NULL;
+       tdb->map_ptr = NULL;
+       tdb->flags = tdb_flags;
+       tdb->open_flags = open_flags;
+       tdb->log_fn = log_fn?log_fn:null_log_fn;
+       tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
+
+       /* cache the page size */
+       tdb->page_size = getpagesize();
+       if (tdb->page_size <= 0) {
+               tdb->page_size = 0x2000;
+       }
+
+       if ((open_flags & O_ACCMODE) == O_WRONLY) {
+               TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n",
+                        name));
+               errno = EINVAL;
+               goto fail;
+       }
+       
+       if (hash_size == 0)
+               hash_size = DEFAULT_HASH_SIZE;
+       if ((open_flags & O_ACCMODE) == O_RDONLY) {
+               tdb->read_only = 1;
+               /* read only databases don't do locking or clear if first */
+               tdb->flags |= TDB_NOLOCK;
+               tdb->flags &= ~TDB_CLEAR_IF_FIRST;
+       }
+
+       /* internal databases don't mmap or lock, and start off cleared */
+       if (tdb->flags & TDB_INTERNAL) {
+               tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP);
+               tdb->flags &= ~TDB_CLEAR_IF_FIRST;
+               if (tdb_new_database(tdb, hash_size) != 0) {
+                       TDB_LOG((tdb, 0, "tdb_open_ex: tdb_new_database failed!"));
+                       goto fail;
+               }
+               goto internal;
+       }
+
+       if ((tdb->fd = open(name, open_flags, mode)) == -1) {
+               TDB_LOG((tdb, 5, "tdb_open_ex: could not open file %s: %s\n",
+                        name, strerror(errno)));
+               goto fail;      /* errno set by open(2) */
+       }
+
+       /* ensure there is only one process initialising at once */
+       if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) {
+               TDB_LOG((tdb, 0, "tdb_open_ex: failed to get global lock on %s: %s\n",
+                        name, strerror(errno)));
+               goto fail;      /* errno set by tdb_brlock */
+       }
+
+       /* we need to zero database if we are the only one with it open */
+       if ((tdb_flags & TDB_CLEAR_IF_FIRST) &&
+           (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) {
+               open_flags |= O_CREAT;
+               if (ftruncate(tdb->fd, 0) == -1) {
+                       TDB_LOG((tdb, 0, "tdb_open_ex: "
+                                "failed to truncate %s: %s\n",
+                                name, strerror(errno)));
+                       goto fail; /* errno set by ftruncate */
+               }
+       }
+
+       if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
+           || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0
+           || (tdb->header.version != TDB_VERSION
+               && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) {
+               /* its not a valid database - possibly initialise it */
+               if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) {
+                       errno = EIO; /* ie bad format or something */
+                       goto fail;
+               }
+               rev = (tdb->flags & TDB_CONVERT);
+       }
+       vp = (unsigned char *)&tdb->header.version;
+       vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) |
+                 (((u32)vp[2]) << 8) | (u32)vp[3];
+       tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0;
+       if (!rev)
+               tdb->flags &= ~TDB_CONVERT;
+       else {
+               tdb->flags |= TDB_CONVERT;
+               tdb_convert(&tdb->header, sizeof(tdb->header));
+       }
+       if (fstat(tdb->fd, &st) == -1)
+               goto fail;
+
+       if (tdb->header.rwlocks != 0) {
+               TDB_LOG((tdb, 5, "tdb_open_ex: spinlocks no longer supported\n"));
+               goto fail;
+       }
+
+       /* Is it already in the open list?  If so, fail. */
+       if (tdb_already_open(st.st_dev, st.st_ino)) {
+               TDB_LOG((tdb, 2, "tdb_open_ex: "
+                        "%s (%d,%d) is already open in this process\n",
+                        name, (int)st.st_dev, (int)st.st_ino));
+               errno = EBUSY;
+               goto fail;
+       }
+
+       if (!(tdb->name = (char *)strdup(name))) {
+               errno = ENOMEM;
+               goto fail;
+       }
+
+       tdb->map_size = st.st_size;
+       tdb->device = st.st_dev;
+       tdb->inode = st.st_ino;
+       tdb->locked = calloc(tdb->header.hash_size+1, sizeof(tdb->locked[0]));
+       if (!tdb->locked) {
+               TDB_LOG((tdb, 2, "tdb_open_ex: "
+                        "failed to allocate lock structure for %s\n",
+                        name));
+               errno = ENOMEM;
+               goto fail;
+       }
+       tdb_mmap(tdb);
+       if (locked) {
+               if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) {
+                       TDB_LOG((tdb, 0, "tdb_open_ex: "
+                                "failed to take ACTIVE_LOCK on %s: %s\n",
+                                name, strerror(errno)));
+                       goto fail;
+               }
+
+       }
+
+       /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if
+          we didn't get the initial exclusive lock as we need to let all other
+          users know we're using it. */
+
+       if (tdb_flags & TDB_CLEAR_IF_FIRST) {
+               /* leave this lock in place to indicate it's in use */
+               if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)
+                       goto fail;
+       }
+
+       /* if needed, run recovery */
+       if (tdb_transaction_recover(tdb) == -1) {
+               goto fail;
+       }
+
+ internal:
+       /* Internal (memory-only) databases skip all the code above to
+        * do with disk files, and resume here by releasing their
+        * global lock and hooking into the active list. */
+       if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1)
+               goto fail;
+       tdb->next = tdbs;
+       tdbs = tdb;
+       return tdb;
+
+ fail:
+       { int save_errno = errno;
+
+       if (!tdb)
+               return NULL;
+       
+       if (tdb->map_ptr) {
+               if (tdb->flags & TDB_INTERNAL)
+                       SAFE_FREE(tdb->map_ptr);
+               else
+                       tdb_munmap(tdb);
+       }
+       SAFE_FREE(tdb->name);
+       if (tdb->fd != -1)
+               if (close(tdb->fd) != 0)
+                       TDB_LOG((tdb, 5, "tdb_open_ex: failed to close tdb->fd on error!\n"));
+       SAFE_FREE(tdb->locked);
+       SAFE_FREE(tdb);
+       errno = save_errno;
+       return NULL;
+       }
+}
+
+/**
+ * Close a database.
+ *
+ * @returns -1 for error; 0 for success.
+ **/
+int tdb_close(struct tdb_context *tdb)
+{
+       struct tdb_context **i;
+       int ret = 0;
+
+       if (tdb->transaction) {
+               tdb_transaction_cancel(tdb);
+       }
+
+       if (tdb->map_ptr) {
+               if (tdb->flags & TDB_INTERNAL)
+                       SAFE_FREE(tdb->map_ptr);
+               else
+                       tdb_munmap(tdb);
+       }
+       SAFE_FREE(tdb->name);
+       if (tdb->fd != -1)
+               ret = close(tdb->fd);
+       SAFE_FREE(tdb->locked);
+
+       /* Remove from contexts list */
+       for (i = &tdbs; *i; i = &(*i)->next) {
+               if (*i == tdb) {
+                       *i = tdb->next;
+                       break;
+               }
+       }
+
+       memset(tdb, 0, sizeof(*tdb));
+       SAFE_FREE(tdb);
+
+       return ret;
+}
+
+/* register a loging function */
+void tdb_logging_function(struct tdb_context *tdb, void (*fn)(struct tdb_context *, int , const char *, ...))
+{
+       tdb->log_fn = fn?fn:null_log_fn;
+}
+
+
+/* reopen a tdb - this can be used after a fork to ensure that we have an independent
+   seek pointer from our parent and to re-establish locks */
+int tdb_reopen(struct tdb_context *tdb)
+{
+       struct stat st;
+
+       if (tdb->flags & TDB_INTERNAL) {
+               return 0; /* Nothing to do. */
+       }
+
+       if (tdb->num_locks != 0) {
+               TDB_LOG((tdb, 0, "tdb_reopen: reopen not allowed with locks held\n"));
+               goto fail;
+       }
+
+       if (tdb->transaction != 0) {
+               TDB_LOG((tdb, 0, "tdb_reopen: reopen not allowed inside a transaction\n"));
+               goto fail;
+       }
+
+       if (tdb_munmap(tdb) != 0) {
+               TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno)));
+               goto fail;
+       }
+       if (close(tdb->fd) != 0)
+               TDB_LOG((tdb, 0, "tdb_reopen: WARNING closing tdb->fd failed!\n"));
+       tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0);
+       if (tdb->fd == -1) {
+               TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno)));
+               goto fail;
+       }
+       if ((tdb->flags & TDB_CLEAR_IF_FIRST) && 
+           (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) {
+               TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n"));
+               goto fail;
+       }
+       if (fstat(tdb->fd, &st) != 0) {
+               TDB_LOG((tdb, 0, "tdb_reopen: fstat failed (%s)\n", strerror(errno)));
+               goto fail;
+       }
+       if (st.st_ino != tdb->inode || st.st_dev != tdb->device) {
+               TDB_LOG((tdb, 0, "tdb_reopen: file dev/inode has changed!\n"));
+               goto fail;
+       }
+       tdb_mmap(tdb);
+
+       return 0;
+
+fail:
+       tdb_close(tdb);
+       return -1;
+}
+
+/* reopen all tdb's */
+int tdb_reopen_all(int parent_longlived)
+{
+       struct tdb_context *tdb;
+
+       for (tdb=tdbs; tdb; tdb = tdb->next) {
+               /*
+                * If the parent is longlived (ie. a
+                * parent daemon architecture), we know
+                * it will keep it's active lock on a
+                * tdb opened with CLEAR_IF_FIRST. Thus
+                * for child processes we don't have to
+                * add an active lock. This is essential
+                * to improve performance on systems that
+                * keep POSIX locks as a non-scalable data
+                * structure in the kernel.
+                */
+               if (parent_longlived) {
+                       /* Ensure no clear-if-first. */
+                       tdb->flags &= ~TDB_CLEAR_IF_FIRST;
+               }
+
+               if (tdb_reopen(tdb) != 0)
+                       return -1;
+       }
+
+       return 0;
+}
diff --git a/source/tdb/spinlock.c b/source/tdb/spinlock.c
deleted file mode 100644 (file)
index e42a690..0000000
+++ /dev/null
@@ -1,472 +0,0 @@
-/* 
-   Unix SMB/CIFS implementation.
-
-   trivial database library 
-
-   Copyright (C) Anton Blanchard                   2001
-   
-     ** NOTE! The following LGPL license applies to the tdb
-     ** library. This does NOT imply that all of Samba is released
-     ** under the LGPL
-   
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser 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
-   Lesser General Public License for more details.
-   
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef STANDALONE
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <signal.h>
-#include "tdb.h"
-#include "spinlock.h"
-
-#define DEBUG
-#else
-#include "includes.h"
-#endif
-
-#ifdef USE_SPINLOCKS
-
-/*
- * ARCH SPECIFIC
- */
-
-#if defined(SPARC_SPINLOCKS)
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
-       unsigned int result;
-
-       asm volatile("ldstub    [%1], %0"
-               : "=r" (result)
-               : "r" (lock)
-               : "memory");
-
-       return (result == 0) ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
-       asm volatile("":::"memory");
-       *lock = 0;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
-       *lock = 0;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
-       return (*lock != 0);
-}
-
-#elif defined(POWERPC_SPINLOCKS) 
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
-       unsigned int result;
-
-       __asm__ __volatile__(
-"1:    lwarx           %0,0,%1\n\
-       cmpwi           0,%0,0\n\
-       li              %0,0\n\
-       bne-            2f\n\
-       li              %0,1\n\
-       stwcx.          %0,0,%1\n\
-       bne-            1b\n\
-       isync\n\
-2:"    : "=&r"(result)
-       : "r"(lock)
-       : "cr0", "memory");
-
-       return (result == 1) ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
-       asm volatile("eieio":::"memory");
-       *lock = 0;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
-       *lock = 0;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
-       return (*lock != 0);
-}
-
-#elif defined(INTEL_SPINLOCKS) 
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
-       int oldval;
-
-       asm volatile("xchgl %0,%1"
-               : "=r" (oldval), "=m" (*lock)
-               : "0" (0)
-               : "memory");
-
-       return oldval > 0 ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
-       asm volatile("":::"memory");
-       *lock = 1;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
-       *lock = 1;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
-       return (*lock != 1);
-}
-
-#elif defined(MIPS_SPINLOCKS) && defined(sgi) && (_COMPILER_VERSION >= 730)
-
-/* Implement spinlocks on IRIX using the MIPSPro atomic fetch operations. See
- * sync(3) for the details of the intrinsic operations.
- *
- * "sgi" and "_COMPILER_VERSION" are always defined by MIPSPro.
- */
-
-#ifdef STANDALONE
-
-/* MIPSPro 7.3 has "__inline" as an extension, but not "inline. */
-#define inline __inline
-
-#endif /* STANDALONE */
-
-/* Returns 0 if the lock is acquired, EBUSY otherwise. */
-static inline int __spin_trylock(spinlock_t *lock)
-{
-        unsigned int val;
-        val = __lock_test_and_set(lock, 1);
-        return val == 0 ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
-        __lock_release(lock);
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
-        __lock_release(lock);
-}
-
-/* Returns 1 if the lock is held, 0 otherwise. */
-static inline int __spin_is_locked(spinlock_t *lock)
-{
-        unsigned int val;
-        val = __add_and_fetch(lock, 0);
-       return val;
-}
-
-#elif defined(MIPS_SPINLOCKS) 
-
-static inline unsigned int load_linked(unsigned long addr)
-{
-       unsigned int res;
-
-       __asm__ __volatile__("ll\t%0,(%1)"
-               : "=r" (res)
-               : "r" (addr));
-
-       return res;
-}
-
-static inline unsigned int store_conditional(unsigned long addr, unsigned int value)
-{
-       unsigned int res;
-
-       __asm__ __volatile__("sc\t%0,(%2)"
-               : "=r" (res)
-               : "0" (value), "r" (addr));
-       return res;
-}
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
-       unsigned int mw;
-
-       do {
-               mw = load_linked(lock);
-               if (mw) 
-                       return EBUSY;
-       } while (!store_conditional(lock, 1));
-
-       asm volatile("":::"memory");
-
-       return 0;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
-       asm volatile("":::"memory");
-       *lock = 0;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
-       *lock = 0;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
-       return (*lock != 0);
-}
-
-#else
-#error Need to implement spinlock code in spinlock.c
-#endif
-
-/*
- * OS SPECIFIC
- */
-
-static void yield_cpu(void)
-{
-       struct timespec tm;
-
-#ifdef USE_SCHED_YIELD
-       sched_yield();
-#else
-       /* Linux will busy loop for delays < 2ms on real time tasks */
-       tm.tv_sec = 0;
-       tm.tv_nsec = 2000000L + 1;
-       nanosleep(&tm, NULL);
-#endif
-}
-
-/*
- * GENERIC
- */
-
-static int smp_machine = 0;
-
-static inline void __spin_lock(spinlock_t *lock)
-{
-       int ntries = 0;
-
-       while(__spin_trylock(lock)) {
-               while(__spin_is_locked(lock)) {
-                       if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
-                               continue;
-                       yield_cpu();
-               }
-       }
-}
-
-static void __read_lock(tdb_rwlock_t *rwlock)
-{
-       int ntries = 0;
-
-       while(1) {
-               __spin_lock(&rwlock->lock);
-
-               if (!(rwlock->count & RWLOCK_BIAS)) {
-                       rwlock->count++;
-                       __spin_unlock(&rwlock->lock);
-                       return;
-               }
-       
-               __spin_unlock(&rwlock->lock);
-
-               while(rwlock->count & RWLOCK_BIAS) {
-                       if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
-                               continue;
-                       yield_cpu();
-               }
-       }
-}
-
-static void __write_lock(tdb_rwlock_t *rwlock)
-{
-       int ntries = 0;
-
-       while(1) {
-               __spin_lock(&rwlock->lock);
-
-               if (rwlock->count == 0) {
-                       rwlock->count |= RWLOCK_BIAS;
-                       __spin_unlock(&rwlock->lock);
-                       return;
-               }
-
-               __spin_unlock(&rwlock->lock);
-
-               while(rwlock->count != 0) {
-                       if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
-                               continue;
-                       yield_cpu();
-               }
-       }
-}
-
-static void __write_unlock(tdb_rwlock_t *rwlock)
-{
-       __spin_lock(&rwlock->lock);
-
-#ifdef DEBUG
-       if (!(rwlock->count & RWLOCK_BIAS))
-               fprintf(stderr, "bug: write_unlock\n");
-#endif
-
-       rwlock->count &= ~RWLOCK_BIAS;
-       __spin_unlock(&rwlock->lock);
-}
-
-static void __read_unlock(tdb_rwlock_t *rwlock)
-{
-       __spin_lock(&rwlock->lock);
-
-#ifdef DEBUG
-       if (!rwlock->count)
-               fprintf(stderr, "bug: read_unlock\n");
-
-       if (rwlock->count & RWLOCK_BIAS)
-               fprintf(stderr, "bug: read_unlock\n");
-#endif
-
-       rwlock->count--;
-       __spin_unlock(&rwlock->lock);
-}
-
-/* TDB SPECIFIC */
-
-/* lock a list in the database. list -1 is the alloc list */
-int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type)
-{
-       tdb_rwlock_t *rwlocks;
-
-       if (!tdb->map_ptr) return -1;
-       rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
-
-       switch(rw_type) {
-       case F_RDLCK:
-               __read_lock(&rwlocks[list+1]);
-               break;
-
-       case F_WRLCK:
-               __write_lock(&rwlocks[list+1]);
-               break;
-
-       default:
-               return TDB_ERRCODE(TDB_ERR_LOCK, -1);
-       }
-       return 0;
-}
-
-/* unlock the database. */
-int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type)
-{
-       tdb_rwlock_t *rwlocks;
-
-       if (!tdb->map_ptr) return -1;
-       rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
-
-       switch(rw_type) {
-       case F_RDLCK:
-               __read_unlock(&rwlocks[list+1]);
-               break;
-
-       case F_WRLCK:
-               __write_unlock(&rwlocks[list+1]);
-               break;
-
-       default:
-               return TDB_ERRCODE(TDB_ERR_LOCK, -1);
-       }
-
-       return 0;
-}
-
-int tdb_create_rwlocks(int fd, unsigned int hash_size)
-{
-       unsigned size, i;
-       tdb_rwlock_t *rwlocks;
-
-       size = TDB_SPINLOCK_SIZE(hash_size);
-       rwlocks = malloc(size);
-       if (!rwlocks)
-               return -1;
-
-       for(i = 0; i < hash_size+1; i++) {
-               __spin_lock_init(&rwlocks[i].lock);
-               rwlocks[i].count = 0;
-       }
-
-       /* Write it out (appending to end) */
-       if (write(fd, rwlocks, size) != size) {
-               free(rwlocks);
-               return -1;
-       }
-       smp_machine = this_is_smp();
-       free(rwlocks);
-       return 0;
-}
-
-int tdb_clear_spinlocks(TDB_CONTEXT *tdb)
-{
-       tdb_rwlock_t *rwlocks;
-       unsigned i;
-
-       if (tdb->header.rwlocks == 0) return 0;
-       if (!tdb->map_ptr) return -1;
-
-       /* We're mmapped here */
-       rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
-       for(i = 0; i < tdb->header.hash_size+1; i++) {
-               __spin_lock_init(&rwlocks[i].lock);
-               rwlocks[i].count = 0;
-       }
-       return 0;
-}
-#else
-int tdb_create_rwlocks(int fd, unsigned int hash_size) { return 0; }
-int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; }
-int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; }
-
-/* Non-spinlock version: remove spinlock pointer */
-int tdb_clear_spinlocks(TDB_CONTEXT *tdb)
-{
-       tdb_off off = (tdb_off)((char *)&tdb->header.rwlocks
-                               - (char *)&tdb->header);
-
-       tdb->header.rwlocks = 0;
-       if (lseek(tdb->fd, off, SEEK_SET) != off
-           || write(tdb->fd, (void *)&tdb->header.rwlocks,
-                    sizeof(tdb->header.rwlocks)) 
-           != sizeof(tdb->header.rwlocks))
-               return -1;
-       return 0;
-}
-#endif
diff --git a/source/tdb/spinlock.h b/source/tdb/spinlock.h
deleted file mode 100644 (file)
index 967fe37..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef __SPINLOCK_H__
-#define __SPINLOCK_H__
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "tdb.h"
-
-#ifdef USE_SPINLOCKS
-
-#define RWLOCK_BIAS 0x1000UL
-
-/* OS SPECIFIC */
-#define MAX_BUSY_LOOPS 1000
-#undef USE_SCHED_YIELD
-
-/* ARCH SPECIFIC */
-/* We should make sure these are padded to a cache line */
-#if defined(SPARC_SPINLOCKS)
-typedef volatile char spinlock_t;
-#elif defined(POWERPC_SPINLOCKS)
-typedef volatile unsigned long spinlock_t;
-#elif defined(INTEL_SPINLOCKS)
-typedef volatile int spinlock_t;
-#elif defined(MIPS_SPINLOCKS)
-typedef volatile unsigned long spinlock_t;
-#else
-#error Need to implement spinlock code in spinlock.h
-#endif
-
-typedef struct {
-       spinlock_t lock;
-       volatile int count;
-} tdb_rwlock_t;
-
-int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type);
-int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type);
-int tdb_create_rwlocks(int fd, unsigned int hash_size);
-int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
-
-#define TDB_SPINLOCK_SIZE(hash_size) (((hash_size) + 1) * sizeof(tdb_rwlock_t))
-
-#else /* !USE_SPINLOCKS */
-#if 0
-#define tdb_create_rwlocks(fd, hash_size) 0
-#define tdb_spinlock(tdb, list, rw_type) (-1)
-#define tdb_spinunlock(tdb, list, rw_type) (-1)
-#else
-int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type);
-int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type);
-int tdb_create_rwlocks(int fd, unsigned int hash_size);
-#endif
-int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
-#define TDB_SPINLOCK_SIZE(hash_size) 0
-
-#endif
-
-#endif
index ad73a1d9aa03acaaf5f005011749460807c2073e..1fae6b6de1d36ed5eab4328f20ea5afb1e464574 100644 (file)
@@ -3,7 +3,7 @@
 
    trivial database library
 
-   Copyright (C) Andrew Tridgell              1999-2004
+   Copyright (C) Andrew Tridgell              1999-2005
    Copyright (C) Paul `Rusty' Russell             2000
    Copyright (C) Jeremy Allison                           2000-2003
    
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
-   
+
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
+#include "tdb_private.h"
 
-/* NOTE: If you use tdbs under valgrind, and in particular if you run
- * tdbtorture, you may get spurious "uninitialized value" warnings.  I
- * think this is because valgrind doesn't understand that the mmap'd
- * area may be written to by other processes.  Memory can, from the
- * point of view of the grinded process, spontaneously become
- * initialized.
- *
- * I can think of a few solutions.  [mbp 20030311]
- *
- * 1 - Write suppressions for Valgrind so that it doesn't complain
- * about this.  Probably the most reasonable but people need to
- * remember to use them.
- *
- * 2 - Use IO not mmap when running under valgrind.  Not so nice.
- *
- * 3 - Use the special valgrind macros to mark memory as valid at the
- * right time.  Probably too hard -- the process just doesn't know.
- */ 
-
-#ifdef STANDALONE
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include "tdb.h"
-#include "spinlock.h"
-#else
-#include "includes.h"
-
-#if defined(PARANOID_MALLOC_CHECKER)
-#ifdef malloc
-#undef malloc
-#endif
-
-#ifdef realloc
-#undef realloc
-#endif
-
-#ifdef calloc
-#undef calloc
-#endif
-
-#ifdef strdup
-#undef strdup
-#endif
-
-#ifdef strndup
-#undef strndup
-#endif
-
-#endif
-
-#endif
-
-#define TDB_MAGIC_FOOD "TDB file\n"
-#define TDB_VERSION (0x26011967 + 6)
-#define TDB_MAGIC (0x26011999U)
-#define TDB_FREE_MAGIC (~TDB_MAGIC)
-#define TDB_DEAD_MAGIC (0xFEE1DEAD)
-#define TDB_ALIGNMENT 4
-#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT)
-#define DEFAULT_HASH_SIZE 131
-#define TDB_PAGE_SIZE 0x2000
-#define FREELIST_TOP (sizeof(struct tdb_header))
-#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1))
-#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24))
-#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC)
-#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r))
-#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off))
-#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + TDB_SPINLOCK_SIZE(hash_size))
-
-
-/* NB assumes there is a local variable called "tdb" that is the
- * current context, also takes doubly-parenthesized print-style
- * argument. */
-#define TDB_LOG(x) (tdb->log_fn?((tdb->log_fn x),0) : 0)
-
-/* lock offsets */
-#define GLOBAL_LOCK 0
-#define ACTIVE_LOCK 4
-
-#ifndef MAP_FILE
-#define MAP_FILE 0
-#endif
-
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *)-1)
-#endif
-
-/* free memory if the pointer is valid and zero the pointer */
-#ifndef SAFE_FREE
-#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0)
-#endif
-
-#define BUCKET(hash) ((hash) % tdb->header.hash_size)
 TDB_DATA tdb_null;
 
-/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */
-static TDB_CONTEXT *tdbs = NULL;
-
-static int tdb_munmap(TDB_CONTEXT *tdb)
+/*
+  increment the tdb sequence number if the tdb has been opened using
+  the TDB_SEQNUM flag
+*/
+static void tdb_increment_seqnum(struct tdb_context *tdb)
 {
-       if (tdb->flags & TDB_INTERNAL)
-               return 0;
-
-#ifdef HAVE_MMAP
-       if (tdb->map_ptr) {
-               int ret = munmap(tdb->map_ptr, tdb->map_size);
-               if (ret != 0)
-                       return ret;
+       tdb_off_t seqnum=0;
+       
+       if (!(tdb->flags & TDB_SEQNUM)) {
+               return;
        }
-#endif
-       tdb->map_ptr = NULL;
-       return 0;
-}
 
-static void tdb_mmap(TDB_CONTEXT *tdb)
-{
-       if (tdb->flags & TDB_INTERNAL)
+       if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1) != 0) {
                return;
-
-#ifdef HAVE_MMAP
-       if (!(tdb->flags & TDB_NOMMAP)) {
-               tdb->map_ptr = mmap(NULL, tdb->map_size, 
-                                   PROT_READ|(tdb->read_only? 0:PROT_WRITE), 
-                                   MAP_SHARED|MAP_FILE, tdb->fd, 0);
-
-               /*
-                * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!!
-                */
-
-               if (tdb->map_ptr == MAP_FAILED) {
-                       tdb->map_ptr = NULL;
-                       TDB_LOG((tdb, 2, "tdb_mmap failed for size %d (%s)\n", 
-                                tdb->map_size, strerror(errno)));
-               }
-       } else {
-               tdb->map_ptr = NULL;
        }
-#else
-       tdb->map_ptr = NULL;
-#endif
-}
 
-/* Endian conversion: we only ever deal with 4 byte quantities */
-static void *convert(void *buf, u32 size)
-{
-       u32 i, *p = buf;
-       for (i = 0; i < size / 4; i++)
-               p[i] = TDB_BYTEREV(p[i]);
-       return buf;
-}
-#define DOCONV() (tdb->flags & TDB_CONVERT)
-#define CONVERT(x) (DOCONV() ? convert(&x, sizeof(x)) : &x)
-
-/* the body of the database is made of one list_struct for the free space
-   plus a separate data list for each hash value */
-struct list_struct {
-       tdb_off next; /* offset of the next record in the list */
-       tdb_len rec_len; /* total byte length of record */
-       tdb_len key_len; /* byte length of key */
-       tdb_len data_len; /* byte length of data */
-       u32 full_hash; /* the full 32 bit hash of the key */
-       u32 magic;   /* try to catch errors */
-       /* the following union is implied:
-               union {
-                       char record[rec_len];
-                       struct {
-                               char key[key_len];
-                               char data[data_len];
-                       }
-                       u32 totalsize; (tailer)
-               }
+       /* we ignore errors from this, as we have no sane way of
+          dealing with them.
        */
-};
-
-/***************************************************************
- Allow a caller to set a "alarm" flag that tdb can check to abort
- a blocking lock on SIGALRM.
-***************************************************************/
-
-static sig_atomic_t *palarm_fired;
-
-void tdb_set_lock_alarm(sig_atomic_t *palarm)
-{
-       palarm_fired = palarm;
-}
-
-/* a byte range locking function - return 0 on success
-   this functions locks/unlocks 1 byte at the specified offset.
-
-   On error, errno is also set so that errors are passed back properly
-   through tdb_open(). */
-static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, 
-                     int rw_type, int lck_type, int probe)
-{
-       struct flock fl;
-       int ret;
-
-       if (tdb->flags & TDB_NOLOCK)
-               return 0;
-       if ((rw_type == F_WRLCK) && (tdb->read_only)) {
-               errno = EACCES;
-               return -1;
-       }
-
-       fl.l_type = rw_type;
-       fl.l_whence = SEEK_SET;
-       fl.l_start = offset;
-       fl.l_len = 1;
-       fl.l_pid = 0;
-
-       do {
-               ret = fcntl(tdb->fd,lck_type,&fl);
-               if (ret == -1 && errno == EINTR && palarm_fired && *palarm_fired)
-                       break;
-       } while (ret == -1 && errno == EINTR);
-
-       if (ret == -1) {
-               if (!probe && lck_type != F_SETLK) {
-                       /* Ensure error code is set for log fun to examine. */
-                       if (errno == EINTR && palarm_fired && *palarm_fired)
-                               tdb->ecode = TDB_ERR_LOCK_TIMEOUT;
-                       else
-                               tdb->ecode = TDB_ERR_LOCK;
-                       TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", 
-                                tdb->fd, offset, rw_type, lck_type));
-               }
-               /* Was it an alarm timeout ? */
-               if (errno == EINTR && palarm_fired && *palarm_fired) {
-                       TDB_LOG((tdb, 5, "tdb_brlock timed out (fd=%d) at offset %d rw_type=%d lck_type=%d\n", 
-                                tdb->fd, offset, rw_type, lck_type));
-                       return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1);
-               }
-               /* Otherwise - generic lock error. errno set by fcntl.
-                * EAGAIN is an expected return from non-blocking
-                * locks. */
-               if (errno != EAGAIN) {
-                       TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n", 
-                                tdb->fd, offset, rw_type, lck_type, 
-                                strerror(errno)));
-               }
-               return TDB_ERRCODE(TDB_ERR_LOCK, -1);
-       }
-       return 0;
-}
-
-/* lock a list in the database. list -1 is the alloc list */
-static int tdb_lock(TDB_CONTEXT *tdb, int list, int ltype)
-{
-       if (list < -1 || list >= (int)tdb->header.hash_size) {
-               TDB_LOG((tdb, 0,"tdb_lock: invalid list %d for ltype=%d\n", 
-                          list, ltype));
-               return -1;
-       }
-       if (tdb->flags & TDB_NOLOCK)
-               return 0;
-
-       /* Since fcntl locks don't nest, we do a lock for the first one,
-          and simply bump the count for future ones */
-       if (tdb->locked[list+1].count == 0) {
-               if (!tdb->read_only && tdb->header.rwlocks) {
-                       if (tdb_spinlock(tdb, list, ltype)) {
-                               TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list %d ltype=%d\n", 
-                                          list, ltype));
-                               return -1;
-                       }
-               } else if (tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) {
-                       TDB_LOG((tdb, 0,"tdb_lock failed on list %d ltype=%d (%s)\n", 
-                                          list, ltype, strerror(errno)));
-                       return -1;
-               }
-               tdb->locked[list+1].ltype = ltype;
-       }
-       tdb->locked[list+1].count++;
-       return 0;
-}
-
-/* unlock the database: returns void because it's too late for errors. */
-       /* changed to return int it may be interesting to know there
-          has been an error  --simo */
-static int tdb_unlock(TDB_CONTEXT *tdb, int list, int ltype)
-{
-       int ret = -1;
-
-       if (tdb->flags & TDB_NOLOCK)
-               return 0;
-
-       /* Sanity checks */
-       if (list < -1 || list >= (int)tdb->header.hash_size) {
-               TDB_LOG((tdb, 0, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size));
-               return ret;
-       }
-
-       if (tdb->locked[list+1].count==0) {
-               TDB_LOG((tdb, 0, "tdb_unlock: count is 0\n"));
-               return ret;
-       }
-
-       if (tdb->locked[list+1].count == 1) {
-               /* Down to last nested lock: unlock underneath */
-               if (!tdb->read_only && tdb->header.rwlocks) {
-                       ret = tdb_spinunlock(tdb, list, ltype);
-               } else {
-                       ret = tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, F_SETLKW, 0);
-               }
-       } else {
-               ret = 0;
-       }
-       tdb->locked[list+1].count--;
-
-       if (ret)
-               TDB_LOG((tdb, 0,"tdb_unlock: An error occurred unlocking!\n")); 
-       return ret;
-}
-
-/* check for an out of bounds access - if it is out of bounds then
-   see if the database has been expanded by someone else and expand
-   if necessary 
-   note that "len" is the minimum length needed for the db
-*/
-static int tdb_oob(TDB_CONTEXT *tdb, tdb_off len, int probe)
-{
-       struct stat st;
-       if (len <= tdb->map_size)
-               return 0;
-       if (tdb->flags & TDB_INTERNAL) {
-               if (!probe) {
-                       /* Ensure ecode is set for log fn. */
-                       tdb->ecode = TDB_ERR_IO;
-                       TDB_LOG((tdb, 0,"tdb_oob len %d beyond internal malloc size %d\n",
-                                (int)len, (int)tdb->map_size));
-               }
-               return TDB_ERRCODE(TDB_ERR_IO, -1);
-       }
-
-       if (fstat(tdb->fd, &st) == -1)
-               return TDB_ERRCODE(TDB_ERR_IO, -1);
-
-       if (st.st_size < (size_t)len) {
-               if (!probe) {
-                       /* Ensure ecode is set for log fn. */
-                       tdb->ecode = TDB_ERR_IO;
-                       TDB_LOG((tdb, 0,"tdb_oob len %d beyond eof at %d\n",
-                                (int)len, (int)st.st_size));
-               }
-               return TDB_ERRCODE(TDB_ERR_IO, -1);
-       }
-
-       /* Unmap, update size, remap */
-       if (tdb_munmap(tdb) == -1)
-               return TDB_ERRCODE(TDB_ERR_IO, -1);
-       tdb->map_size = st.st_size;
-       tdb_mmap(tdb);
-       return 0;
-}
-
-/* write a lump of data at a specified offset */
-static int tdb_write(TDB_CONTEXT *tdb, tdb_off off, void *buf, tdb_len len)
-{
-       if (tdb_oob(tdb, off + len, 0) != 0)
-               return -1;
-
-       if (tdb->map_ptr)
-               memcpy(off + (char *)tdb->map_ptr, buf, len);
-#ifdef HAVE_PWRITE
-       else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) {
-#else
-       else if (lseek(tdb->fd, off, SEEK_SET) != off
-                || write(tdb->fd, buf, len) != (ssize_t)len) {
-#endif
-               /* Ensure ecode is set for log fn. */
-               tdb->ecode = TDB_ERR_IO;
-               TDB_LOG((tdb, 0,"tdb_write failed at %d len=%d (%s)\n",
-                          off, len, strerror(errno)));
-               return TDB_ERRCODE(TDB_ERR_IO, -1);
-       }
-       return 0;
-}
-
-/* read a lump of data at a specified offset, maybe convert */
-static int tdb_read(TDB_CONTEXT *tdb,tdb_off off,void *buf,tdb_len len,int cv)
-{
-       if (tdb_oob(tdb, off + len, 0) != 0)
-               return -1;
-
-       if (tdb->map_ptr)
-               memcpy(buf, off + (char *)tdb->map_ptr, len);
-#ifdef HAVE_PREAD
-       else if (pread(tdb->fd, buf, len, off) != (ssize_t)len) {
-#else
-       else if (lseek(tdb->fd, off, SEEK_SET) != off
-                || read(tdb->fd, buf, len) != (ssize_t)len) {
-#endif
-               /* Ensure ecode is set for log fn. */
-               tdb->ecode = TDB_ERR_IO;
-               TDB_LOG((tdb, 0,"tdb_read failed at %d len=%d (%s)\n",
-                          off, len, strerror(errno)));
-               return TDB_ERRCODE(TDB_ERR_IO, -1);
-       }
-       if (cv)
-               convert(buf, len);
-       return 0;
-}
-
-/* read a lump of data, allocating the space for it */
-static char *tdb_alloc_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_len len)
-{
-       char *buf;
+       tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
+       seqnum++;
+       tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum);
 
-       if (!(buf = malloc(len))) {
-               /* Ensure ecode is set for log fn. */
-               tdb->ecode = TDB_ERR_OOM;
-               TDB_LOG((tdb, 0,"tdb_alloc_read malloc failed len=%d (%s)\n",
-                          len, strerror(errno)));
-               return TDB_ERRCODE(TDB_ERR_OOM, buf);
-       }
-       if (tdb_read(tdb, offset, buf, len, 0) == -1) {
-               SAFE_FREE(buf);
-               return NULL;
-       }
-       return buf;
-}
-
-/* read/write a tdb_off */
-static int ofs_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d)
-{
-       return tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV());
-}
-static int ofs_write(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d)
-{
-       tdb_off off = *d;
-       return tdb_write(tdb, offset, CONVERT(off), sizeof(*d));
-}
-
-/* read/write a record */
-static int rec_read(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec)
-{
-       if (tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1)
-               return -1;
-       if (TDB_BAD_MAGIC(rec)) {
-               /* Ensure ecode is set for log fn. */
-               tdb->ecode = TDB_ERR_CORRUPT;
-               TDB_LOG((tdb, 0,"rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset));
-               return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
-       }
-       return tdb_oob(tdb, rec->next+sizeof(*rec), 0);
-}
-static int rec_write(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec)
-{
-       struct list_struct r = *rec;
-       return tdb_write(tdb, offset, CONVERT(r), sizeof(r));
+       tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1);
 }
 
-/* read a freelist record and check for simple errors */
-static int rec_free_read(TDB_CONTEXT *tdb, tdb_off off, struct list_struct *rec)
-{
-       if (tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1)
-               return -1;
-
-       if (rec->magic == TDB_MAGIC) {
-               /* this happens when a app is showdown while deleting a record - we should
-                  not completely fail when this happens */
-               TDB_LOG((tdb, 0,"rec_free_read non-free magic 0x%x at offset=%d - fixing\n", 
-                        rec->magic, off));
-               rec->magic = TDB_FREE_MAGIC;
-               if (tdb_write(tdb, off, rec, sizeof(*rec)) == -1)
-                       return -1;
-       }
-
-       if (rec->magic != TDB_FREE_MAGIC) {
-               /* Ensure ecode is set for log fn. */
-               tdb->ecode = TDB_ERR_CORRUPT;
-               TDB_LOG((tdb, 0,"rec_free_read bad magic 0x%x at offset=%d\n", 
-                          rec->magic, off));
-               return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
-       }
-       if (tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0)
-               return -1;
-       return 0;
-}
-
-/* update a record tailer (must hold allocation lock) */
-static int update_tailer(TDB_CONTEXT *tdb, tdb_off offset,
-                        const struct list_struct *rec)
-{
-       tdb_off totalsize;
-
-       /* Offset of tailer from record header */
-       totalsize = sizeof(*rec) + rec->rec_len;
-       return ofs_write(tdb, offset + totalsize - sizeof(tdb_off),
-                        &totalsize);
-}
-
-static tdb_off tdb_dump_record(TDB_CONTEXT *tdb, tdb_off offset)
-{
-       struct list_struct rec;
-       tdb_off tailer_ofs, tailer;
-
-       if (tdb_read(tdb, offset, (char *)&rec, sizeof(rec), DOCONV()) == -1) {
-               printf("ERROR: failed to read record at %u\n", offset);
-               return 0;
-       }
-
-       printf(" rec: offset=%u next=%d rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n",
-              offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, rec.full_hash, rec.magic);
-
-       tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off);
-       if (ofs_read(tdb, tailer_ofs, &tailer) == -1) {
-               printf("ERROR: failed to read tailer at %u\n", tailer_ofs);
-               return rec.next;
-       }
-
-       if (tailer != rec.rec_len + sizeof(rec)) {
-               printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n",
-                               (unsigned)tailer, (unsigned)(rec.rec_len + sizeof(rec)));
-       }
-       return rec.next;
-}
-
-static int tdb_dump_chain(TDB_CONTEXT *tdb, int i)
-{
-       tdb_off rec_ptr, top;
-       int hash_length = 0;
-
-       top = TDB_HASH_TOP(i);
-
-       if (tdb_lock(tdb, i, F_WRLCK) != 0)
-               return -1;
-
-       if (ofs_read(tdb, top, &rec_ptr) == -1)
-               return tdb_unlock(tdb, i, F_WRLCK);
-
-       if (rec_ptr)
-               printf("hash=%d\n", i);
-
-       while (rec_ptr) {
-               rec_ptr = tdb_dump_record(tdb, rec_ptr);
-               hash_length += 1;
-       }
-
-       printf("chain %d length %d\n", i, hash_length);
-
-       return tdb_unlock(tdb, i, F_WRLCK);
-}
-
-void tdb_dump_all(TDB_CONTEXT *tdb)
-{
-       int i;
-       for (i=0;i<tdb->header.hash_size;i++) {
-               tdb_dump_chain(tdb, i);
-       }
-       tdb_printfreelist(tdb);
-}
-
-int tdb_printfreelist(TDB_CONTEXT *tdb)
-{
-       int ret;
-       long total_free = 0;
-       tdb_off offset, rec_ptr;
-       struct list_struct rec;
-
-       if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0)
-               return ret;
-
-       offset = FREELIST_TOP;
-
-       /* read in the freelist top */
-       if (ofs_read(tdb, offset, &rec_ptr) == -1) {
-               tdb_unlock(tdb, -1, F_WRLCK);
-               return 0;
-       }
-
-       printf("freelist top=[0x%08x]\n", rec_ptr );
-       while (rec_ptr) {
-               if (tdb_read(tdb, rec_ptr, (char *)&rec, sizeof(rec), DOCONV()) == -1) {
-                       tdb_unlock(tdb, -1, F_WRLCK);
-                       return -1;
-               }
-
-               if (rec.magic != TDB_FREE_MAGIC) {
-                       printf("bad magic 0x%08x in free list\n", rec.magic);
-                       tdb_unlock(tdb, -1, F_WRLCK);
-                       return -1;
-               }
-
-               printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)]\n", rec.next, rec.rec_len, rec.rec_len );
-               total_free += rec.rec_len;
-
-               /* move to the next record */
-               rec_ptr = rec.next;
-       }
-       printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, 
-               (int)total_free);
-
-       return tdb_unlock(tdb, -1, F_WRLCK);
-}
-
-/* Remove an element from the freelist.  Must have alloc lock. */
-static int remove_from_freelist(TDB_CONTEXT *tdb, tdb_off off, tdb_off next)
-{
-       tdb_off last_ptr, i;
-
-       /* read in the freelist top */
-       last_ptr = FREELIST_TOP;
-       while (ofs_read(tdb, last_ptr, &i) != -1 && i != 0) {
-               if (i == off) {
-                       /* We've found it! */
-                       return ofs_write(tdb, last_ptr, &next);
-               }
-               /* Follow chain (next offset is at start of record) */
-               last_ptr = i;
-       }
-       TDB_LOG((tdb, 0,"remove_from_freelist: not on list at off=%d\n", off));
-       return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
-}
-
-/* Add an element into the freelist. Merge adjacent records if
-   neccessary. */
-static int tdb_free(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec)
-{
-       tdb_off right, left;
-
-       /* Allocation and tailer lock */
-       if (tdb_lock(tdb, -1, F_WRLCK) != 0)
-               return -1;
-
-       /* set an initial tailer, so if we fail we don't leave a bogus record */
-       if (update_tailer(tdb, offset, rec) != 0) {
-               TDB_LOG((tdb, 0, "tdb_free: upfate_tailer failed!\n"));
-               goto fail;
-       }
-
-       /* Look right first (I'm an Australian, dammit) */
-       right = offset + sizeof(*rec) + rec->rec_len;
-       if (right + sizeof(*rec) <= tdb->map_size) {
-               struct list_struct r;
-
-               if (tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) {
-                       TDB_LOG((tdb, 0, "tdb_free: right read failed at %u\n", right));
-                       goto left;
-               }
-
-               /* If it's free, expand to include it. */
-               if (r.magic == TDB_FREE_MAGIC) {
-                       if (remove_from_freelist(tdb, right, r.next) == -1) {
-                               TDB_LOG((tdb, 0, "tdb_free: right free failed at %u\n", right));
-                               goto left;
-                       }
-                       rec->rec_len += sizeof(r) + r.rec_len;
-               }
-       }
-
-left:
-       /* Look left */
-       left = offset - sizeof(tdb_off);
-       if (left > TDB_DATA_START(tdb->header.hash_size)) {
-               struct list_struct l;
-               tdb_off leftsize;
-               
-               /* Read in tailer and jump back to header */
-               if (ofs_read(tdb, left, &leftsize) == -1) {
-                       TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left));
-                       goto update;
-               }
-               left = offset - leftsize;
-
-               /* Now read in record */
-               if (tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) {
-                       TDB_LOG((tdb, 0, "tdb_free: left read failed at %u (%u)\n", left, leftsize));
-                       goto update;
-               }
-
-               /* If it's free, expand to include it. */
-               if (l.magic == TDB_FREE_MAGIC) {
-                       if (remove_from_freelist(tdb, left, l.next) == -1) {
-                               TDB_LOG((tdb, 0, "tdb_free: left free failed at %u\n", left));
-                               goto update;
-                       } else {
-                               offset = left;
-                               rec->rec_len += leftsize;
-                       }
-               }
-       }
-
-update:
-       if (update_tailer(tdb, offset, rec) == -1) {
-               TDB_LOG((tdb, 0, "tdb_free: update_tailer failed at %u\n", offset));
-               goto fail;
-       }
-
-       /* Now, prepend to free list */
-       rec->magic = TDB_FREE_MAGIC;
-
-       if (ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 ||
-           rec_write(tdb, offset, rec) == -1 ||
-           ofs_write(tdb, FREELIST_TOP, &offset) == -1) {
-               TDB_LOG((tdb, 0, "tdb_free record write failed at offset=%d\n", offset));
-               goto fail;
-       }
-
-       /* And we're done. */
-       tdb_unlock(tdb, -1, F_WRLCK);
-       return 0;
-
- fail:
-       tdb_unlock(tdb, -1, F_WRLCK);
-       return -1;
-}
-
-
-/* expand a file.  we prefer to use ftruncate, as that is what posix
-  says to use for mmap expansion */
-static int expand_file(TDB_CONTEXT *tdb, tdb_off size, tdb_off addition)
-{
-       char buf[1024];
-#if HAVE_FTRUNCATE_EXTEND
-       if (ftruncate(tdb->fd, size+addition) != 0) {
-               TDB_LOG((tdb, 0, "expand_file ftruncate to %d failed (%s)\n", 
-                          size+addition, strerror(errno)));
-               return -1;
-       }
-#else
-       char b = 0;
-
-#ifdef HAVE_PWRITE
-       if (pwrite(tdb->fd,  &b, 1, (size+addition) - 1) != 1) {
-#else
-       if (lseek(tdb->fd, (size+addition) - 1, SEEK_SET) != (size+addition) - 1 || 
-           write(tdb->fd, &b, 1) != 1) {
-#endif
-               TDB_LOG((tdb, 0, "expand_file to %d failed (%s)\n", 
-                          size+addition, strerror(errno)));
-               return -1;
-       }
-#endif
-
-       /* now fill the file with something. This ensures that the file isn't sparse, which would be
-          very bad if we ran out of disk. This must be done with write, not via mmap */
-       memset(buf, 0x42, sizeof(buf));
-       while (addition) {
-               int n = addition>sizeof(buf)?sizeof(buf):addition;
-#ifdef HAVE_PWRITE
-               int ret = pwrite(tdb->fd, buf, n, size);
-#else
-               int ret;
-               if (lseek(tdb->fd, size, SEEK_SET) != size)
-                       return -1;
-               ret = write(tdb->fd, buf, n);
-#endif
-               if (ret != n) {
-                       TDB_LOG((tdb, 0, "expand_file write of %d failed (%s)\n", 
-                                  n, strerror(errno)));
-                       return -1;
-               }
-               addition -= n;
-               size += n;
-       }
-       return 0;
-}
-
-
-/* expand the database at least size bytes by expanding the underlying
-   file and doing the mmap again if necessary */
-static int tdb_expand(TDB_CONTEXT *tdb, tdb_off size)
-{
-       struct list_struct rec;
-       tdb_off offset;
-
-       if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
-               TDB_LOG((tdb, 0, "lock failed in tdb_expand\n"));
-               return -1;
-       }
-
-       /* must know about any previous expansions by another process */
-       tdb_oob(tdb, tdb->map_size + 1, 1);
-
-       /* always make room for at least 10 more records, and round
-           the database up to a multiple of TDB_PAGE_SIZE */
-       size = TDB_ALIGN(tdb->map_size + size*10, TDB_PAGE_SIZE) - tdb->map_size;
-
-       if (!(tdb->flags & TDB_INTERNAL))
-               tdb_munmap(tdb);
-
-       /*
-        * We must ensure the file is unmapped before doing this
-        * to ensure consistency with systems like OpenBSD where
-        * writes and mmaps are not consistent.
-        */
-
-       /* expand the file itself */
-       if (!(tdb->flags & TDB_INTERNAL)) {
-               if (expand_file(tdb, tdb->map_size, size) != 0)
-                       goto fail;
-       }
-
-       tdb->map_size += size;
-
-       if (tdb->flags & TDB_INTERNAL) {
-               char *new_map_ptr = realloc(tdb->map_ptr, tdb->map_size);
-               if (!new_map_ptr) {
-                       tdb->map_size -= size;
-                       goto fail;
-               }
-               tdb->map_ptr = new_map_ptr;
-       } else {
-               /*
-                * We must ensure the file is remapped before adding the space
-                * to ensure consistency with systems like OpenBSD where
-                * writes and mmaps are not consistent.
-                */
-
-               /* We're ok if the mmap fails as we'll fallback to read/write */
-               tdb_mmap(tdb);
-       }
-
-       /* form a new freelist record */
-       memset(&rec,'\0',sizeof(rec));
-       rec.rec_len = size - sizeof(rec);
-
-       /* link it into the free list */
-       offset = tdb->map_size - size;
-       if (tdb_free(tdb, offset, &rec) == -1)
-               goto fail;
-
-       tdb_unlock(tdb, -1, F_WRLCK);
-       return 0;
- fail:
-       tdb_unlock(tdb, -1, F_WRLCK);
-       return -1;
-}
-
-/* allocate some space from the free list. The offset returned points
-   to a unconnected list_struct within the database with room for at
-   least length bytes of total data
-
-   0 is returned if the space could not be allocated
- */
-static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length,
-                           struct list_struct *rec)
-{
-       tdb_off rec_ptr, last_ptr, newrec_ptr;
-       struct list_struct newrec;
-
-       memset(&newrec, '\0', sizeof(newrec));
-
-       if (tdb_lock(tdb, -1, F_WRLCK) == -1)
-               return 0;
-
-       /* Extra bytes required for tailer */
-       length += sizeof(tdb_off);
-
- again:
-       last_ptr = FREELIST_TOP;
-
-       /* read in the freelist top */
-       if (ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1)
-               goto fail;
-
-       /* keep looking until we find a freelist record big enough */
-       while (rec_ptr) {
-               if (rec_free_read(tdb, rec_ptr, rec) == -1)
-                       goto fail;
-
-               if (rec->rec_len >= length) {
-                       /* found it - now possibly split it up  */
-                       if (rec->rec_len > length + MIN_REC_SIZE) {
-                               /* Length of left piece */
-                               length = TDB_ALIGN(length, TDB_ALIGNMENT);
-
-                               /* Right piece to go on free list */
-                               newrec.rec_len = rec->rec_len
-                                       - (sizeof(*rec) + length);
-                               newrec_ptr = rec_ptr + sizeof(*rec) + length;
-
-                               /* And left record is shortened */
-                               rec->rec_len = length;
-                       } else
-                               newrec_ptr = 0;
-
-                       /* Remove allocated record from the free list */
-                       if (ofs_write(tdb, last_ptr, &rec->next) == -1)
-                               goto fail;
-
-                       /* Update header: do this before we drop alloc
-                           lock, otherwise tdb_free() might try to
-                           merge with us, thinking we're free.
-                           (Thanks Jeremy Allison). */
-                       rec->magic = TDB_MAGIC;
-                       if (rec_write(tdb, rec_ptr, rec) == -1)
-                               goto fail;
-
-                       /* Did we create new block? */
-                       if (newrec_ptr) {
-                               /* Update allocated record tailer (we
-                                   shortened it). */
-                               if (update_tailer(tdb, rec_ptr, rec) == -1)
-                                       goto fail;
-
-                               /* Free new record */
-                               if (tdb_free(tdb, newrec_ptr, &newrec) == -1)
-                                       goto fail;
-                       }
-
-                       /* all done - return the new record offset */
-                       tdb_unlock(tdb, -1, F_WRLCK);
-                       return rec_ptr;
-               }
-               /* move to the next record */
-               last_ptr = rec_ptr;
-               rec_ptr = rec->next;
-       }
-       /* we didn't find enough space. See if we can expand the
-          database and if we can then try again */
-       if (tdb_expand(tdb, length + sizeof(*rec)) == 0)
-               goto again;
- fail:
-       tdb_unlock(tdb, -1, F_WRLCK);
-       return 0;
-}
-
-/* initialise a new database with a specified hash size */
-static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size)
-{
-       struct tdb_header *newdb;
-       int size, ret = -1;
-
-       /* We make it up in memory, then write it out if not internal */
-       size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off);
-       if (!(newdb = calloc(size, 1)))
-               return TDB_ERRCODE(TDB_ERR_OOM, -1);
-
-       /* Fill in the header */
-       newdb->version = TDB_VERSION;
-       newdb->hash_size = hash_size;
-#ifdef USE_SPINLOCKS
-       newdb->rwlocks = size;
-#endif
-       if (tdb->flags & TDB_INTERNAL) {
-               tdb->map_size = size;
-               tdb->map_ptr = (char *)newdb;
-               memcpy(&tdb->header, newdb, sizeof(tdb->header));
-               /* Convert the `ondisk' version if asked. */
-               CONVERT(*newdb);
-               return 0;
-       }
-       if (lseek(tdb->fd, 0, SEEK_SET) == -1)
-               goto fail;
-
-       if (ftruncate(tdb->fd, 0) == -1)
-               goto fail;
-
-       /* This creates an endian-converted header, as if read from disk */
-       CONVERT(*newdb);
-       memcpy(&tdb->header, newdb, sizeof(tdb->header));
-       /* Don't endian-convert the magic food! */
-       memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
-       if (write(tdb->fd, newdb, size) != size)
-               ret = -1;
-       else
-               ret = tdb_create_rwlocks(tdb->fd, hash_size);
-
-  fail:
-       SAFE_FREE(newdb);
-       return ret;
-}
 
 /* Returns 0 on fail.  On success, return offset of record, and fills
    in rec */
-static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash,
+static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, u32 hash,
                        struct list_struct *r)
 {
-       tdb_off rec_ptr;
+       tdb_off_t rec_ptr;
        
        /* read in the hash top */
-       if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
+       if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
                return 0;
 
        /* keep looking until we find the right record */
        while (rec_ptr) {
-               if (rec_read(tdb, rec_ptr, r) == -1)
+               if (tdb_rec_read(tdb, rec_ptr, r) == -1)
                        return 0;
 
                if (!TDB_DEAD(r) && hash==r->full_hash && key.dsize==r->key_len) {
@@ -1040,8 +93,8 @@ static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash,
 }
 
 /* As tdb_find, but if you succeed, keep the lock */
-static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype,
-                            struct list_struct *rec)
+tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype,
+                          struct list_struct *rec)
 {
        u32 rec_ptr;
 
@@ -1052,60 +105,34 @@ static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int
        return rec_ptr;
 }
 
-enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb)
-{
-       return tdb->ecode;
-}
-
-static struct tdb_errname {
-       enum TDB_ERROR ecode; const char *estring;
-} emap[] = { {TDB_SUCCESS, "Success"},
-            {TDB_ERR_CORRUPT, "Corrupt database"},
-            {TDB_ERR_IO, "IO Error"},
-            {TDB_ERR_LOCK, "Locking error"},
-            {TDB_ERR_OOM, "Out of memory"},
-            {TDB_ERR_EXISTS, "Record exists"},
-            {TDB_ERR_NOLOCK, "Lock exists on other keys"},
-            {TDB_ERR_NOEXIST, "Record does not exist"} };
-
-/* Error string for the last tdb error */
-const char *tdb_errorstr(TDB_CONTEXT *tdb)
-{
-       u32 i;
-       for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++)
-               if (tdb->ecode == emap[i].ecode)
-                       return emap[i].estring;
-       return "Invalid error code";
-}
 
 /* update an entry in place - this only works if the new data size
    is <= the old data size and the key exists.
    on failure return -1.
 */
-
-static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf)
+static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf)
 {
        struct list_struct rec;
-       tdb_off rec_ptr;
+       tdb_off_t rec_ptr;
 
        /* find entry */
        if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
                return -1;
 
        /* must be long enough key, data and tailer */
-       if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off)) {
+       if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off_t)) {
                tdb->ecode = TDB_SUCCESS; /* Not really an error */
                return -1;
        }
 
-       if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len,
+       if (tdb->methods->tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len,
                      dbuf.dptr, dbuf.dsize) == -1)
                return -1;
 
        if (dbuf.dsize != rec.data_len) {
                /* update size */
                rec.data_len = dbuf.dsize;
-               return rec_write(tdb, rec_ptr, &rec);
+               return tdb_rec_write(tdb, rec_ptr, &rec);
        }
  
        return 0;
@@ -1114,13 +141,12 @@ static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA db
 /* find an entry in the database given a key */
 /* If an entry doesn't exist tdb_err will be set to
  * TDB_ERR_NOEXIST. If a key has no data attached
- * tdb_err will not be set. Both will return a
- * zero pptr and zero dsize.
+ * then the TDB_DATA will have zero length but
+ * a non-zero pointer
  */
-
-TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key)
+TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key)
 {
-       tdb_off rec_ptr;
+       tdb_off_t rec_ptr;
        struct list_struct rec;
        TDB_DATA ret;
        u32 hash;
@@ -1130,11 +156,8 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key)
        if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
                return tdb_null;
 
-       if (rec.data_len)
-               ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len,
-                                         rec.data_len);
-       else
-               ret.dptr = NULL;
+       ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len,
+                                 rec.data_len);
        ret.dsize = rec.data_len;
        tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
        return ret;
@@ -1146,7 +169,7 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key)
    this doesn't match the conventions in the rest of this module, but is
    compatible with gdbm
 */
-static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
+static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
 {
        struct list_struct rec;
        
@@ -1156,82 +179,39 @@ static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
        return 1;
 }
 
-int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key)
-{
-       u32 hash = tdb->hash_fn(&key);
-       return tdb_exists_hash(tdb, key, hash);
-}
-
-/* record lock stops delete underneath */
-static int lock_record(TDB_CONTEXT *tdb, tdb_off off)
-{
-       return off ? tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0) : 0;
-}
-/*
-  Write locks override our own fcntl readlocks, so check it here.
-  Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not
-  an error to fail to get the lock here.
-*/
-static int write_lock_record(TDB_CONTEXT *tdb, tdb_off off)
-{
-       struct tdb_traverse_lock *i;
-       for (i = &tdb->travlocks; i; i = i->next)
-               if (i->off == off)
-                       return -1;
-       return tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1);
-}
-
-/*
-  Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not
-  an error to fail to get the lock here.
-*/
-
-static int write_unlock_record(TDB_CONTEXT *tdb, tdb_off off)
-{
-       return tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0);
-}
-/* fcntl locks don't stack: avoid unlocking someone else's */
-static int unlock_record(TDB_CONTEXT *tdb, tdb_off off)
-{
-       struct tdb_traverse_lock *i;
-       u32 count = 0;
-
-       if (off == 0)
-               return 0;
-       for (i = &tdb->travlocks; i; i = i->next)
-               if (i->off == off)
-                       count++;
-       return (count == 1 ? tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0) : 0);
+int tdb_exists(struct tdb_context *tdb, TDB_DATA key)
+{
+       u32 hash = tdb->hash_fn(&key);
+       return tdb_exists_hash(tdb, key, hash);
 }
 
 /* actually delete an entry in the database given the offset */
-static int do_delete(TDB_CONTEXT *tdb, tdb_off rec_ptr, struct list_struct*rec)
+int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct*rec)
 {
-       tdb_off last_ptr, i;
+       tdb_off_t last_ptr, i;
        struct list_struct lastrec;
 
-       if (tdb->read_only) return -1;
+       if (tdb->read_only || tdb->traverse_read) return -1;
 
-       if (write_lock_record(tdb, rec_ptr) == -1) {
+       if (tdb_write_lock_record(tdb, rec_ptr) == -1) {
                /* Someone traversing here: mark it as dead */
                rec->magic = TDB_DEAD_MAGIC;
-               return rec_write(tdb, rec_ptr, rec);
+               return tdb_rec_write(tdb, rec_ptr, rec);
        }
-       if (write_unlock_record(tdb, rec_ptr) != 0)
+       if (tdb_write_unlock_record(tdb, rec_ptr) != 0)
                return -1;
 
        /* find previous record in hash chain */
-       if (ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1)
+       if (tdb_ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1)
                return -1;
        for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next)
-               if (rec_read(tdb, i, &lastrec) == -1)
+               if (tdb_rec_read(tdb, i, &lastrec) == -1)
                        return -1;
 
        /* unlink it: next ptr is at start of record. */
        if (last_ptr == 0)
                last_ptr = TDB_HASH_TOP(rec->full_hash);
-       if (ofs_write(tdb, last_ptr, &rec->next) == -1)
+       if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1)
                return -1;
 
        /* recover the space */
@@ -1240,283 +220,27 @@ static int do_delete(TDB_CONTEXT *tdb, tdb_off rec_ptr, struct list_struct*rec)
        return 0;
 }
 
-/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */
-static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock,
-                        struct list_struct *rec)
-{
-       int want_next = (tlock->off != 0);
-
-       /* Lock each chain from the start one. */
-       for (; tlock->hash < tdb->header.hash_size; tlock->hash++) {
-
-               /* this is an optimisation for the common case where
-                  the hash chain is empty, which is particularly
-                  common for the use of tdb with ldb, where large
-                  hashes are used. In that case we spend most of our
-                  time in tdb_brlock(), locking empty hash chains.
-
-                  To avoid this, we do an unlocked pre-check to see
-                  if the hash chain is empty before starting to look
-                  inside it. If it is empty then we can avoid that
-                  hash chain. If it isn't empty then we can't believe
-                  the value we get back, as we read it without a
-                  lock, so instead we get the lock and re-fetch the
-                  value below.
-
-                  Notice that not doing this optimisation on the
-                  first hash chain is critical. We must guarantee
-                  that we have done at least one fcntl lock at the
-                  start of a search to guarantee that memory is
-                  coherent on SMP systems. If records are added by
-                  others during the search then thats OK, and we
-                  could possibly miss those with this trick, but we
-                  could miss them anyway without this trick, so the
-                  semantics don't change.
-
-                  With a non-indexed ldb search this trick gains us a
-                  factor of around 80 in speed on a linux 2.6.x
-                  system (testing using ldbtest).
-                */
-               if (!tlock->off && tlock->hash != 0) {
-                       u32 off;
-                       if (tdb->map_ptr) {
-                               for (;tlock->hash < tdb->header.hash_size;tlock->hash++) {
-                                       if (0 != *(u32 *)(TDB_HASH_TOP(tlock->hash) + (unsigned char *)tdb->map_ptr)) {
-                                               break;
-                                       }
-                               }
-                               if (tlock->hash == tdb->header.hash_size) {
-                                       continue;
-                               }
-                       } else {
-                               if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), &off) == 0 &&
-                                   off == 0) {
-                                       continue;
-                               }
-                       }
-               }
-
-               if (tdb_lock(tdb, tlock->hash, F_WRLCK) == -1)
-                       return -1;
-
-               /* No previous record?  Start at top of chain. */
-               if (!tlock->off) {
-                       if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash),
-                                    &tlock->off) == -1)
-                               goto fail;
-               } else {
-                       /* Otherwise unlock the previous record. */
-                       if (unlock_record(tdb, tlock->off) != 0)
-                               goto fail;
-               }
-
-               if (want_next) {
-                       /* We have offset of old record: grab next */
-                       if (rec_read(tdb, tlock->off, rec) == -1)
-                               goto fail;
-                       tlock->off = rec->next;
-               }
-
-               /* Iterate through chain */
-               while( tlock->off) {
-                       tdb_off current;
-                       if (rec_read(tdb, tlock->off, rec) == -1)
-                               goto fail;
-
-                       /* Detect infinite loops. From "Shlomi Yaakobovich" <Shlomi@exanet.com>. */
-                       if (tlock->off == rec->next) {
-                               TDB_LOG((tdb, 0, "tdb_next_lock: loop detected.\n"));
-                               goto fail;
-                       }
-
-                       if (!TDB_DEAD(rec)) {
-                               /* Woohoo: we found one! */
-                               if (lock_record(tdb, tlock->off) != 0)
-                                       goto fail;
-                               return tlock->off;
-                       }
-
-                       /* Try to clean dead ones from old traverses */
-                       current = tlock->off;
-                       tlock->off = rec->next;
-                       if (!tdb->read_only && 
-                           do_delete(tdb, current, rec) != 0)
-                               goto fail;
-               }
-               tdb_unlock(tdb, tlock->hash, F_WRLCK);
-               want_next = 0;
-       }
-       /* We finished iteration without finding anything */
-       return TDB_ERRCODE(TDB_SUCCESS, 0);
-
- fail:
-       tlock->off = 0;
-       if (tdb_unlock(tdb, tlock->hash, F_WRLCK) != 0)
-               TDB_LOG((tdb, 0, "tdb_next_lock: On error unlock failed!\n"));
-       return -1;
-}
-
-/* traverse the entire database - calling fn(tdb, key, data) on each element.
-   return -1 on error or the record count traversed
-   if fn is NULL then it is not called
-   a non-zero return value from fn() indicates that the traversal should stop
-  */
-int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *private_val)
-{
-       TDB_DATA key, dbuf;
-       struct list_struct rec;
-       struct tdb_traverse_lock tl = { NULL, 0, 0 };
-       int ret, count = 0;
-
-       /* This was in the initializaton, above, but the IRIX compiler
-        * did not like it.  crh
-        */
-       tl.next = tdb->travlocks.next;
-
-       /* fcntl locks don't stack: beware traverse inside traverse */
-       tdb->travlocks.next = &tl;
-
-       /* tdb_next_lock places locks on the record returned, and its chain */
-       while ((ret = tdb_next_lock(tdb, &tl, &rec)) > 0) {
-               count++;
-               /* now read the full record */
-               key.dptr = tdb_alloc_read(tdb, tl.off + sizeof(rec), 
-                                         rec.key_len + rec.data_len);
-               if (!key.dptr) {
-                       ret = -1;
-                       if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0)
-                               goto out;
-                       if (unlock_record(tdb, tl.off) != 0)
-                               TDB_LOG((tdb, 0, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n"));
-                       goto out;
-               }
-               key.dsize = rec.key_len;
-               dbuf.dptr = key.dptr + rec.key_len;
-               dbuf.dsize = rec.data_len;
-
-               /* Drop chain lock, call out */
-               if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) {
-                       ret = -1;
-                       SAFE_FREE(key.dptr);
-                       goto out;
-               }
-               if (fn && fn(tdb, key, dbuf, private_val)) {
-                       /* They want us to terminate traversal */
-                       ret = count;
-                       if (unlock_record(tdb, tl.off) != 0) {
-                               TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));;
-                               ret = -1;
-                       }
-                       SAFE_FREE(key.dptr);
-                       goto out;
-               }
-               SAFE_FREE(key.dptr);
-       }
-out:
-       tdb->travlocks.next = tl.next;
-       if (ret < 0)
-               return -1;
-       else
-               return count;
-}
-
-/* find the first entry in the database and return its key */
-TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb)
-{
-       TDB_DATA key;
-       struct list_struct rec;
-
-       /* release any old lock */
-       if (unlock_record(tdb, tdb->travlocks.off) != 0)
-               return tdb_null;
-       tdb->travlocks.off = tdb->travlocks.hash = 0;
-
-       if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0)
-               return tdb_null;
-       /* now read the key */
-       key.dsize = rec.key_len;
-       key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize);
-       if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0)
-               TDB_LOG((tdb, 0, "tdb_firstkey: error occurred while tdb_unlocking!\n"));
-       return key;
-}
-
-/* find the next entry in the database, returning its key */
-TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey)
-{
-       u32 oldhash;
-       TDB_DATA key = tdb_null;
-       struct list_struct rec;
-       char *k = NULL;
-
-       /* Is locked key the old key?  If so, traverse will be reliable. */
-       if (tdb->travlocks.off) {
-               if (tdb_lock(tdb,tdb->travlocks.hash,F_WRLCK))
-                       return tdb_null;
-               if (rec_read(tdb, tdb->travlocks.off, &rec) == -1
-                   || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),
-                                           rec.key_len))
-                   || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) {
-                       /* No, it wasn't: unlock it and start from scratch */
-                       if (unlock_record(tdb, tdb->travlocks.off) != 0) {
-                               SAFE_FREE(k);
-                               return tdb_null;
-                       }
-                       if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) {
-                               SAFE_FREE(k);
-                               return tdb_null;
-                       }
-                       tdb->travlocks.off = 0;
-               }
-
-               SAFE_FREE(k);
-       }
-
-       if (!tdb->travlocks.off) {
-               /* No previous element: do normal find, and lock record */
-               tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), F_WRLCK, &rec);
-               if (!tdb->travlocks.off)
-                       return tdb_null;
-               tdb->travlocks.hash = BUCKET(rec.full_hash);
-               if (lock_record(tdb, tdb->travlocks.off) != 0) {
-                       TDB_LOG((tdb, 0, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno)));
-                       return tdb_null;
-               }
-       }
-       oldhash = tdb->travlocks.hash;
-
-       /* Grab next record: locks chain and returned record,
-          unlocks old record */
-       if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) {
-               key.dsize = rec.key_len;
-               key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec),
-                                         key.dsize);
-               /* Unlock the chain of this new record */
-               if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0)
-                       TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
-       }
-       /* Unlock the chain of old record */
-       if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0)
-               TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
-       return key;
-}
-
 /* delete an entry in the database given a key */
-static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
+static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
 {
-       tdb_off rec_ptr;
+       tdb_off_t rec_ptr;
        struct list_struct rec;
        int ret;
 
        if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec)))
                return -1;
-       ret = do_delete(tdb, rec_ptr, &rec);
+       ret = tdb_do_delete(tdb, rec_ptr, &rec);
+
+       if (ret == 0) {
+               tdb_increment_seqnum(tdb);
+       }
+
        if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0)
                TDB_LOG((tdb, 0, "tdb_delete: WARNING tdb_unlock failed!\n"));
        return ret;
 }
 
-int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
+int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
 {
        u32 hash = tdb->hash_fn(&key);
        return tdb_delete_hash(tdb, key, hash);
@@ -1527,14 +251,19 @@ int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
 
    return 0 on success, -1 on failure
 */
-int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
+int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
 {
        struct list_struct rec;
        u32 hash;
-       tdb_off rec_ptr;
+       tdb_off_t rec_ptr;
        char *p = NULL;
        int ret = 0;
 
+       if (tdb->read_only || tdb->traverse_read) {
+               tdb->ecode = TDB_ERR_RDONLY;
+               return -1;
+       }
+
        /* find which hash bucket it is in */
        hash = tdb->hash_fn(&key);
        if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
@@ -1555,7 +284,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
                        /* if the record doesn't exist and we are in TDB_MODIFY mode then
                         we should fail the store */
                        goto fail;
-       }
+               }
        }
        /* reset the error code potentially set by the tdb_update() */
        tdb->ecode = TDB_SUCCESS;
@@ -1583,7 +312,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
                goto fail;
 
        /* Read hash top into next ptr */
-       if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1)
+       if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1)
                goto fail;
 
        rec.key_len = key.dsize;
@@ -1592,12 +321,15 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
        rec.magic = TDB_MAGIC;
 
        /* write out and point the top of the hash chain at it */
-       if (rec_write(tdb, rec_ptr, &rec) == -1
-           || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1
-           || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) {
+       if (tdb_rec_write(tdb, rec_ptr, &rec) == -1
+           || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1
+           || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) {
                /* Need to tdb_unallocate() here */
                goto fail;
        }
+
+       tdb_increment_seqnum(tdb);
+
  out:
        SAFE_FREE(p); 
        tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
@@ -1607,521 +339,92 @@ fail:
        goto out;
 }
 
-/* Attempt to append data to an entry in place - this only works if the new data size
-   is <= the old data size and the key exists.
-   on failure return -1. Record must be locked before calling.
-*/
-static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA new_dbuf)
-{
-       struct list_struct rec;
-       tdb_off rec_ptr;
-
-       /* find entry */
-       if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
-               return -1;
-
-       /* Append of 0 is always ok. */
-       if (new_dbuf.dsize == 0)
-               return 0;
-
-       /* must be long enough for key, old data + new data and tailer */
-       if (rec.rec_len < key.dsize + rec.data_len + new_dbuf.dsize + sizeof(tdb_off)) {
-               /* No room. */
-               tdb->ecode = TDB_SUCCESS; /* Not really an error */
-               return -1;
-       }
-
-       if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len + rec.data_len,
-                     new_dbuf.dptr, new_dbuf.dsize) == -1)
-               return -1;
-
-       /* update size */
-       rec.data_len += new_dbuf.dsize;
-       return rec_write(tdb, rec_ptr, &rec);
-}
 
 /* Append to an entry. Create if not exist. */
-
-int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf)
+int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
 {
-       struct list_struct rec;
        u32 hash;
-       tdb_off rec_ptr;
-       char *p = NULL;
-       int ret = 0;
-       size_t new_data_size = 0;
+       TDB_DATA dbuf;
+       int ret = -1;
 
        /* find which hash bucket it is in */
        hash = tdb->hash_fn(&key);
        if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
                return -1;
 
-       /* first try in-place. */
-       if (tdb_append_inplace(tdb, key, hash, new_dbuf) == 0)
-               goto out;
-
-       /* reset the error code potentially set by the tdb_append_inplace() */
-       tdb->ecode = TDB_SUCCESS;
-
-       /* find entry */
-       if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) {
-               if (tdb->ecode != TDB_ERR_NOEXIST)
-                       goto fail;
-
-               /* Not found - create. */
+       dbuf = tdb_fetch(tdb, key);
 
-               ret = tdb_store(tdb, key, new_dbuf, TDB_INSERT);
-               goto out;
+       if (dbuf.dptr == NULL) {
+               dbuf.dptr = malloc(new_dbuf.dsize);
+       } else {
+               dbuf.dptr = realloc(dbuf.dptr, dbuf.dsize + new_dbuf.dsize);
        }
 
-       new_data_size = rec.data_len + new_dbuf.dsize;
-
-       /* Copy key+old_value+value *before* allocating free space in case malloc
-          fails and we are left with a dead spot in the tdb. */
-
-       if (!(p = (char *)malloc(key.dsize + new_data_size))) {
+       if (dbuf.dptr == NULL) {
                tdb->ecode = TDB_ERR_OOM;
-               goto fail;
-       }
-
-       /* Copy the key in place. */
-       memcpy(p, key.dptr, key.dsize);
-
-       /* Now read the old data into place. */
-       if (rec.data_len &&
-               tdb_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, p + key.dsize, rec.data_len, 0) == -1)
-                       goto fail;
-
-       /* Finally append the new data. */
-       if (new_dbuf.dsize)
-               memcpy(p+key.dsize+rec.data_len, new_dbuf.dptr, new_dbuf.dsize);
-
-       /* delete any existing record - if it doesn't exist we don't
-           care.  Doing this first reduces fragmentation, and avoids
-           coalescing with `allocated' block before it's updated. */
-
-       tdb_delete_hash(tdb, key, hash);
-
-       if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec)))
-               goto fail;
-
-       /* Read hash top into next ptr */
-       if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1)
-               goto fail;
-
-       rec.key_len = key.dsize;
-       rec.data_len = new_data_size;
-       rec.full_hash = hash;
-       rec.magic = TDB_MAGIC;
-
-       /* write out and point the top of the hash chain at it */
-       if (rec_write(tdb, rec_ptr, &rec) == -1
-           || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+new_data_size)==-1
-           || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) {
-               /* Need to tdb_unallocate() here */
-               goto fail;
-       }
-
- out:
-       SAFE_FREE(p); 
-       tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
-       return ret;
-
-fail:
-       ret = -1;
-       goto out;
-}
-
-static int tdb_already_open(dev_t device,
-                           ino_t ino)
-{
-       TDB_CONTEXT *i;
-       
-       for (i = tdbs; i; i = i->next) {
-               if (i->device == device && i->inode == ino) {
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-
-/* This is based on the hash algorithm from gdbm */
-static u32 default_tdb_hash(TDB_DATA *key)
-{
-       u32 value;      /* Used to compute the hash value.  */
-       u32   i;        /* Used to cycle through random values. */
-
-       /* Set the initial value from the key size. */
-       for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
-               value = (value + (key->dptr[i] << (i*5 % 24)));
-
-       return (1103515243 * value + 12345);  
-}
-
-/* open the database, creating it if necessary 
-
-   The open_flags and mode are passed straight to the open call on the
-   database file. A flags value of O_WRONLY is invalid. The hash size
-   is advisory, use zero for a default value.
-
-   Return is NULL on error, in which case errno is also set.  Don't 
-   try to call tdb_error or tdb_errname, just do strerror(errno).
-
-   @param name may be NULL for internal databases. */
-TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags,
-                     int open_flags, mode_t mode)
-{
-       return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL);
-}
-
-
-TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
-                        int open_flags, mode_t mode,
-                        tdb_log_func log_fn,
-                        tdb_hash_func hash_fn)
-{
-       TDB_CONTEXT *tdb;
-       struct stat st;
-       int rev = 0, locked = 0;
-       unsigned char *vp;
-       u32 vertest;
-
-       if (!(tdb = calloc(1, sizeof *tdb))) {
-               /* Can't log this */
-               errno = ENOMEM;
-               goto fail;
-       }
-       tdb->fd = -1;
-       tdb->name = NULL;
-       tdb->map_ptr = NULL;
-       tdb->flags = tdb_flags;
-       tdb->open_flags = open_flags;
-       tdb->log_fn = log_fn;
-       tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
-
-       if ((open_flags & O_ACCMODE) == O_WRONLY) {
-               TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n",
-                        name));
-               errno = EINVAL;
-               goto fail;
-       }
-       
-       if (hash_size == 0)
-               hash_size = DEFAULT_HASH_SIZE;
-       if ((open_flags & O_ACCMODE) == O_RDONLY) {
-               tdb->read_only = 1;
-               /* read only databases don't do locking or clear if first */
-               tdb->flags |= TDB_NOLOCK;
-               tdb->flags &= ~TDB_CLEAR_IF_FIRST;
-       }
-
-       /* internal databases don't mmap or lock, and start off cleared */
-       if (tdb->flags & TDB_INTERNAL) {
-               tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP);
-               tdb->flags &= ~TDB_CLEAR_IF_FIRST;
-               if (tdb_new_database(tdb, hash_size) != 0) {
-                       TDB_LOG((tdb, 0, "tdb_open_ex: tdb_new_database failed!"));
-                       goto fail;
-               }
-               goto internal;
-       }
-
-       if ((tdb->fd = open(name, open_flags, mode)) == -1) {
-               TDB_LOG((tdb, 5, "tdb_open_ex: could not open file %s: %s\n",
-                        name, strerror(errno)));
-               goto fail;      /* errno set by open(2) */
-       }
-
-       /* ensure there is only one process initialising at once */
-       if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) {
-               TDB_LOG((tdb, 0, "tdb_open_ex: failed to get global lock on %s: %s\n",
-                        name, strerror(errno)));
-               goto fail;      /* errno set by tdb_brlock */
-       }
-
-       /* we need to zero database if we are the only one with it open */
-       if ((tdb_flags & TDB_CLEAR_IF_FIRST) &&
-               (locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) {
-               open_flags |= O_CREAT;
-               if (ftruncate(tdb->fd, 0) == -1) {
-                       TDB_LOG((tdb, 0, "tdb_open_ex: "
-                                "failed to truncate %s: %s\n",
-                                name, strerror(errno)));
-                       goto fail; /* errno set by ftruncate */
-               }
-       }
-
-       if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
-           || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0
-           || (tdb->header.version != TDB_VERSION
-               && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) {
-               /* its not a valid database - possibly initialise it */
-               if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) {
-                       errno = EIO; /* ie bad format or something */
-                       goto fail;
-               }
-               rev = (tdb->flags & TDB_CONVERT);
-       }
-       vp = (unsigned char *)&tdb->header.version;
-       vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) |
-                 (((u32)vp[2]) << 8) | (u32)vp[3];
-       tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0;
-       if (!rev)
-               tdb->flags &= ~TDB_CONVERT;
-       else {
-               tdb->flags |= TDB_CONVERT;
-               convert(&tdb->header, sizeof(tdb->header));
-       }
-       if (fstat(tdb->fd, &st) == -1)
-               goto fail;
-
-       /* Is it already in the open list?  If so, fail. */
-       if (tdb_already_open(st.st_dev, st.st_ino)) {
-               TDB_LOG((tdb, 2, "tdb_open_ex: "
-                        "%s (%d,%d) is already open in this process\n",
-                        name, (int)st.st_dev, (int)st.st_ino));
-               errno = EBUSY;
-               goto fail;
-       }
-
-       if (!(tdb->name = (char *)strdup(name))) {
-               errno = ENOMEM;
-               goto fail;
-       }
-
-       tdb->map_size = st.st_size;
-       tdb->device = st.st_dev;
-       tdb->inode = st.st_ino;
-       tdb->locked = calloc(tdb->header.hash_size+1, sizeof(tdb->locked[0]));
-       if (!tdb->locked) {
-               TDB_LOG((tdb, 2, "tdb_open_ex: "
-                        "failed to allocate lock structure for %s\n",
-                        name));
-               errno = ENOMEM;
-               goto fail;
-       }
-       tdb_mmap(tdb);
-       if (locked) {
-               if (!tdb->read_only)
-                       if (tdb_clear_spinlocks(tdb) != 0) {
-                               TDB_LOG((tdb, 0, "tdb_open_ex: "
-                               "failed to clear spinlock\n"));
-                               goto fail;
-                       }
-               if (tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) {
-                       TDB_LOG((tdb, 0, "tdb_open_ex: "
-                                "failed to take ACTIVE_LOCK on %s: %s\n",
-                                name, strerror(errno)));
-                       goto fail;
-               }
-
-       }
-
-       /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if
-          we didn't get the initial exclusive lock as we need to let all other
-          users know we're using it. */
-
-       if (tdb_flags & TDB_CLEAR_IF_FIRST) {
-               /* leave this lock in place to indicate it's in use */
-               if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)
-                       goto fail;
+               goto failed;
        }
 
+       memcpy(dbuf.dptr + dbuf.dsize, new_dbuf.dptr, new_dbuf.dsize);
+       dbuf.dsize += new_dbuf.dsize;
 
- internal:
-       /* Internal (memory-only) databases skip all the code above to
-        * do with disk files, and resume here by releasing their
-        * global lock and hooking into the active list. */
-       if (tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1)
-               goto fail;
-       tdb->next = tdbs;
-       tdbs = tdb;
-       return tdb;
-
- fail:
-       { int save_errno = errno;
-
-       if (!tdb)
-               return NULL;
+       ret = tdb_store(tdb, key, dbuf, 0);
        
-       if (tdb->map_ptr) {
-               if (tdb->flags & TDB_INTERNAL)
-                       SAFE_FREE(tdb->map_ptr);
-               else
-                       tdb_munmap(tdb);
-       }
-       SAFE_FREE(tdb->name);
-       if (tdb->fd != -1)
-               if (close(tdb->fd) != 0)
-                       TDB_LOG((tdb, 5, "tdb_open_ex: failed to close tdb->fd on error!\n"));
-       SAFE_FREE(tdb->locked);
-       SAFE_FREE(tdb);
-       errno = save_errno;
-       return NULL;
-       }
-}
-
-/**
- * Close a database.
- *
- * @returns -1 for error; 0 for success.
- **/
-int tdb_close(TDB_CONTEXT *tdb)
-{
-       TDB_CONTEXT **i;
-       int ret = 0;
-
-       if (tdb->map_ptr) {
-               if (tdb->flags & TDB_INTERNAL)
-                       SAFE_FREE(tdb->map_ptr);
-               else
-                       tdb_munmap(tdb);
-       }
-       SAFE_FREE(tdb->name);
-       if (tdb->fd != -1)
-               ret = close(tdb->fd);
-       SAFE_FREE(tdb->locked);
-
-       /* Remove from contexts list */
-       for (i = &tdbs; *i; i = &(*i)->next) {
-               if (*i == tdb) {
-                       *i = tdb->next;
-                       break;
-               }
-       }
-
-       memset(tdb, 0, sizeof(*tdb));
-       SAFE_FREE(tdb);
-
+failed:
+       tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
+       SAFE_FREE(dbuf.dptr);
        return ret;
 }
 
-/* lock/unlock entire database */
-int tdb_lockall(TDB_CONTEXT *tdb)
-{
-       u32 i;
-
-       /* There are no locks on read-only dbs */
-       if (tdb->read_only)
-               return TDB_ERRCODE(TDB_ERR_LOCK, -1);
-       for (i = 0; i < tdb->header.hash_size; i++) 
-               if (tdb_lock(tdb, i, F_WRLCK))
-                       break;
-
-       /* If error, release locks we have... */
-       if (i < tdb->header.hash_size) {
-               u32 j;
-
-               for ( j = 0; j < i; j++)
-                       tdb_unlock(tdb, j, F_WRLCK);
-               return TDB_ERRCODE(TDB_ERR_NOLOCK, -1);
-       }
-
-       return 0;
-}
-void tdb_unlockall(TDB_CONTEXT *tdb)
-{
-       u32 i;
-       for (i=0; i < tdb->header.hash_size; i++)
-               tdb_unlock(tdb, i, F_WRLCK);
-}
-
-/* lock/unlock one hash chain. This is meant to be used to reduce
-   contention - it cannot guarantee how many records will be locked */
-int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key)
-{
-       return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
-}
 
-int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key)
+/*
+  return the name of the current tdb file
+  useful for external logging functions
+*/
+const char *tdb_name(struct tdb_context *tdb)
 {
-       return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
+       return tdb->name;
 }
 
-int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key)
+/*
+  return the underlying file descriptor being used by tdb, or -1
+  useful for external routines that want to check the device/inode
+  of the fd
+*/
+int tdb_fd(struct tdb_context *tdb)
 {
-       return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
+       return tdb->fd;
 }
 
-int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key)
+/*
+  return the current logging function
+  useful for external tdb routines that wish to log tdb errors
+*/
+tdb_log_func tdb_log_fn(struct tdb_context *tdb)
 {
-       return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
+       return tdb->log_fn;
 }
 
 
-/* register a loging function */
-void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , const char *, ...))
-{
-       tdb->log_fn = fn;
-}
-
-/* reopen a tdb - this can be used after a fork to ensure that we have an independent
-   seek pointer from our parent and to re-establish locks */
-int tdb_reopen(TDB_CONTEXT *tdb)
+/*
+  get the tdb sequence number. Only makes sense if the writers opened
+  with TDB_SEQNUM set. Note that this sequence number will wrap quite
+  quickly, so it should only be used for a 'has something changed'
+  test, not for code that relies on the count of the number of changes
+  made. If you want a counter then use a tdb record.
+
+  The aim of this sequence number is to allow for a very lightweight
+  test of a possible tdb change.
+*/
+int tdb_get_seqnum(struct tdb_context *tdb)
 {
-       struct stat st;
-
-       if (tdb->flags & TDB_INTERNAL)
-               return 0; /* Nothing to do. */
-       if (tdb_munmap(tdb) != 0) {
-               TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno)));
-               goto fail;
-       }
-       if (close(tdb->fd) != 0)
-               TDB_LOG((tdb, 0, "tdb_reopen: WARNING closing tdb->fd failed!\n"));
-       tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0);
-       if (tdb->fd == -1) {
-               TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno)));
-               goto fail;
-       }
-       if ((tdb->flags & TDB_CLEAR_IF_FIRST) &&
-                       (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) {
-               TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n"));
-               goto fail;
-       }
-       if (fstat(tdb->fd, &st) != 0) {
-               TDB_LOG((tdb, 0, "tdb_reopen: fstat failed (%s)\n", strerror(errno)));
-               goto fail;
-       }
-       if (st.st_ino != tdb->inode || st.st_dev != tdb->device) {
-               TDB_LOG((tdb, 0, "tdb_reopen: file dev/inode has changed!\n"));
-               goto fail;
-       }
-       tdb_mmap(tdb);
-
-       return 0;
+       tdb_off_t seqnum=0;
 
-fail:
-       tdb_close(tdb);
-       return -1;
+       tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
+       return seqnum;
 }
 
-/* reopen all tdb's */
-int tdb_reopen_all(int parent_longlived)
+int tdb_hash_size(struct tdb_context *tdb)
 {
-       TDB_CONTEXT *tdb;
-
-       for (tdb=tdbs; tdb; tdb = tdb->next) {
-               /*
-                * If the parent is longlived (ie. a
-                * parent daemon architecture), we know
-                * it will keep it's active lock on a
-                * tdb opened with CLEAR_IF_FIRST. Thus
-                * for child processes we don't have to
-                * add an active lock. This is essential
-                * to improve performance on systems that
-                * keep POSIX locks as a non-scalable data
-                * structure in the kernel.
-                */
-               if (parent_longlived) {
-                       /* Ensure no clear-if-first. */
-                       tdb->flags &= ~TDB_CLEAR_IF_FIRST;
-               }
-
-               if (tdb_reopen(tdb) != 0)
-                       return -1;
-       }
-
-       return 0;
+       return tdb->header.hash_size;
 }
index b5b87ee5a542e64bb3744de12418bae0bbe1df3d..82f8828c89d0405f310429e2fb22fcae37f2baf4 100644 (file)
@@ -3,9 +3,9 @@
 
 /* 
    Unix SMB/CIFS implementation.
-   
+
    trivial database library
-   
+
    Copyright (C) Andrew Tridgell 1999-2004
    
      ** NOTE! The following LGPL license applies to the tdb
@@ -21,7 +21,7 @@
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
-   
+
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 extern "C" {
 #endif
 
-#ifndef PRINTF_ATTRIBUTE
-/** Use gcc attribute to check printf fns.  a1 is the 1-based index of
- * the parameter containing the format, and a2 the index of the first
- * argument. Note that some gcc 2.x versions don't handle this
- * properly **/
-#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 )
-#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
-#else
-#define PRINTF_ATTRIBUTE(a1, a2)
-#endif
-#endif
 
 /* flags to tdb_store() */
 #define TDB_REPLACE 1
@@ -56,102 +45,83 @@ extern "C" {
 #define TDB_NOMMAP   8 /* don't use mmap */
 #define TDB_CONVERT 16 /* convert endian (internal use) */
 #define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */
+#define TDB_NOSYNC   64 /* don't use synchronous transactions */
+#define TDB_SEQNUM   128 /* maintain a sequence number */
 
 #define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret)
 
 /* error codes */
 enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, 
                TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT,
-               TDB_ERR_NOEXIST};
-
-#ifndef u32
-#define u32 unsigned
-#endif
+               TDB_ERR_NOEXIST, TDB_ERR_EINVAL, TDB_ERR_RDONLY};
 
-typedef struct {
+typedef struct TDB_DATA {
        char *dptr;
        size_t dsize;
 } TDB_DATA;
 
-typedef u32 tdb_len;
-typedef u32 tdb_off;
-
-/* this is stored at the front of every database */
-struct tdb_header {
-       char magic_food[32]; /* for /etc/magic */
-       u32 version; /* version of the code */
-       u32 hash_size; /* number of hash entries */
-       tdb_off rwlocks;
-       tdb_off reserved[31];
-};
-
-struct tdb_lock_type {
-       u32 count;
-       u32 ltype;
-};
-
-struct tdb_traverse_lock {
-       struct tdb_traverse_lock *next;
-       u32 off;
-       u32 hash;
-};
+#ifndef PRINTF_ATTRIBUTE
+#if (__GNUC__ >= 3)
+/** Use gcc attribute to check printf fns.  a1 is the 1-based index of
+ * the parameter containing the format, and a2 the index of the first
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#else
+#define PRINTF_ATTRIBUTE(a1, a2)
+#endif
+#endif
 
 /* this is the context structure that is returned from a db open */
-typedef struct tdb_context {
-       char *name; /* the name of the database */
-       void *map_ptr; /* where it is currently mapped */
-       int fd; /* open file descriptor for the database */
-       tdb_len map_size; /* how much space has been mapped */
-       int read_only; /* opened read-only */
-       struct tdb_lock_type *locked; /* array of chain locks */
-       enum TDB_ERROR ecode; /* error code for last tdb error */
-       struct tdb_header header; /* a cached copy of the header */
-       u32 flags; /* the flags passed to tdb_open */
-       struct tdb_traverse_lock travlocks; /* current traversal locks */
-       struct tdb_context *next; /* all tdbs to avoid multiple opens */
-       dev_t device;   /* uniquely identifies this tdb */
-       ino_t inode;    /* uniquely identifies this tdb */
-       void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */
-       u32 (*hash_fn)(TDB_DATA *key);
-       int open_flags; /* flags used in the open - needed by reopen */
-} TDB_CONTEXT;
-
-typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *);
-typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...);
-typedef u32 (*tdb_hash_func)(TDB_DATA *key);
-
-TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags,
+typedef struct tdb_context TDB_CONTEXT;
+
+typedef int (*tdb_traverse_func)(struct tdb_context *, TDB_DATA, TDB_DATA, void *);
+typedef void (*tdb_log_func)(struct tdb_context *, int , const char *, ...);
+typedef unsigned int (*tdb_hash_func)(TDB_DATA *key);
+
+struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags,
                      int open_flags, mode_t mode);
-TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
+struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
                         int open_flags, mode_t mode,
                         tdb_log_func log_fn,
                         tdb_hash_func hash_fn);
 
-int tdb_reopen(TDB_CONTEXT *tdb);
-int tdb_reopen_all(int);
-void tdb_logging_function(TDB_CONTEXT *tdb, tdb_log_func);
-enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb);
-const char *tdb_errorstr(TDB_CONTEXT *tdb);
-TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key);
-int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key);
-int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
-int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf);
-int tdb_close(TDB_CONTEXT *tdb);
-TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
-TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key);
-int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *);
-int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
-int tdb_lockall(TDB_CONTEXT *tdb);
-void tdb_unlockall(TDB_CONTEXT *tdb);
+int tdb_reopen(struct tdb_context *tdb);
+int tdb_reopen_all(int parent_longlived);
+void tdb_logging_function(struct tdb_context *tdb, tdb_log_func);
+enum TDB_ERROR tdb_error(struct tdb_context *tdb);
+const char *tdb_errorstr(struct tdb_context *tdb);
+TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key);
+int tdb_delete(struct tdb_context *tdb, TDB_DATA key);
+int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
+int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf);
+int tdb_close(struct tdb_context *tdb);
+TDB_DATA tdb_firstkey(struct tdb_context *tdb);
+TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA key);
+int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *);
+int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *);
+int tdb_exists(struct tdb_context *tdb, TDB_DATA key);
+int tdb_lockall(struct tdb_context *tdb);
+void tdb_unlockall(struct tdb_context *tdb);
+const char *tdb_name(struct tdb_context *tdb);
+int tdb_fd(struct tdb_context *tdb);
+tdb_log_func tdb_log_fn(struct tdb_context *tdb);
+int tdb_transaction_start(struct tdb_context *tdb);
+int tdb_transaction_commit(struct tdb_context *tdb);
+int tdb_transaction_cancel(struct tdb_context *tdb);
+int tdb_transaction_recover(struct tdb_context *tdb);
+int tdb_get_seqnum(struct tdb_context *tdb);
+int tdb_hash_size(struct tdb_context *tdb);
 
 /* Low level locking functions: use with care */
-void tdb_set_lock_alarm(sig_atomic_t *palarm);
-int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key);
-int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key);
+int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key);
+int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key);
+int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key);
+int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key);
 
 /* Debug functions. Not used in production. */
-void tdb_dump_all(TDB_CONTEXT *tdb);
-int tdb_printfreelist(TDB_CONTEXT *tdb);
+void tdb_dump_all(struct tdb_context *tdb);
+int tdb_printfreelist(struct tdb_context *tdb);
 
 extern TDB_DATA tdb_null;
 
diff --git a/source/tdb/tdb_private.h b/source/tdb/tdb_private.h
new file mode 100644 (file)
index 0000000..d10c1c4
--- /dev/null
@@ -0,0 +1,241 @@
+ /* 
+   Unix SMB/CIFS implementation.
+
+   trivial database library - private includes
+
+   Copyright (C) Andrew Tridgell              2005
+   
+     ** NOTE! The following LGPL license applies to the tdb
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _SAMBA_BUILD_
+#include "config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include "tdb.h"
+
+#ifndef HAVE_PREAD_DECL
+ssize_t pread(int fd, void *buf, size_t count, off_t offset);
+#endif
+#ifndef HAVE_PWRITE_DECL
+ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
+#endif
+
+#else
+#include "includes.h"
+#undef malloc
+#undef realloc
+#undef calloc
+#undef strdup
+#endif
+
+#ifndef u32
+#define u32 unsigned
+#endif
+
+#ifndef HAVE_GETPAGESIZE
+#define getpagesize() 0x2000
+#endif
+
+typedef u32 tdb_len_t;
+typedef u32 tdb_off_t;
+
+#ifndef offsetof
+#define offsetof(t,f) ((unsigned int)&((t *)0)->f)
+#endif
+
+#define TDB_MAGIC_FOOD "TDB file\n"
+#define TDB_VERSION (0x26011967 + 6)
+#define TDB_MAGIC (0x26011999U)
+#define TDB_FREE_MAGIC (~TDB_MAGIC)
+#define TDB_DEAD_MAGIC (0xFEE1DEAD)
+#define TDB_RECOVERY_MAGIC (0xf53bc0e7U)
+#define TDB_ALIGNMENT 4
+#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT)
+#define DEFAULT_HASH_SIZE 131
+#define FREELIST_TOP (sizeof(struct tdb_header))
+#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1))
+#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24))
+#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC)
+#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r))
+#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off_t))
+#define TDB_HASHTABLE_SIZE(tdb) ((tdb->header.hash_size+1)*sizeof(tdb_off_t))
+#define TDB_DATA_START(hash_size) TDB_HASH_TOP(hash_size-1)
+#define TDB_RECOVERY_HEAD offsetof(struct tdb_header, recovery_start)
+#define TDB_SEQNUM_OFS    offsetof(struct tdb_header, sequence_number)
+#define TDB_PAD_BYTE 0x42
+#define TDB_PAD_U32  0x42424242
+
+/* NB assumes there is a local variable called "tdb" that is the
+ * current context, also takes doubly-parenthesized print-style
+ * argument. */
+#define TDB_LOG(x) tdb->log_fn x
+
+/* lock offsets */
+#define GLOBAL_LOCK      0
+#define ACTIVE_LOCK      4
+#define TRANSACTION_LOCK 8
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+/* free memory if the pointer is valid and zero the pointer */
+#ifndef SAFE_FREE
+#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
+#endif
+
+#define BUCKET(hash) ((hash) % tdb->header.hash_size)
+
+#define DOCONV() (tdb->flags & TDB_CONVERT)
+#define CONVERT(x) (DOCONV() ? tdb_convert(&x, sizeof(x)) : &x)
+
+
+/* the body of the database is made of one list_struct for the free space
+   plus a separate data list for each hash value */
+struct list_struct {
+       tdb_off_t next; /* offset of the next record in the list */
+       tdb_len_t rec_len; /* total byte length of record */
+       tdb_len_t key_len; /* byte length of key */
+       tdb_len_t data_len; /* byte length of data */
+       u32 full_hash; /* the full 32 bit hash of the key */
+       u32 magic;   /* try to catch errors */
+       /* the following union is implied:
+               union {
+                       char record[rec_len];
+                       struct {
+                               char key[key_len];
+                               char data[data_len];
+                       }
+                       u32 totalsize; (tailer)
+               }
+       */
+};
+
+
+/* this is stored at the front of every database */
+struct tdb_header {
+       char magic_food[32]; /* for /etc/magic */
+       u32 version; /* version of the code */
+       u32 hash_size; /* number of hash entries */
+       tdb_off_t rwlocks; /* obsolete - kept to detect old formats */
+       tdb_off_t recovery_start; /* offset of transaction recovery region */
+       tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */
+       tdb_off_t reserved[29];
+};
+
+struct tdb_lock_type {
+       u32 count;
+       u32 ltype;
+};
+
+struct tdb_traverse_lock {
+       struct tdb_traverse_lock *next;
+       u32 off;
+       u32 hash;
+       int lock_rw;
+};
+
+
+struct tdb_methods {
+       int (*tdb_read)(struct tdb_context *, tdb_off_t , void *, tdb_len_t , int );
+       int (*tdb_write)(struct tdb_context *, tdb_off_t, const void *, tdb_len_t);
+       void (*next_hash_chain)(struct tdb_context *, u32 *);
+       int (*tdb_oob)(struct tdb_context *, tdb_off_t , int );
+       int (*tdb_expand_file)(struct tdb_context *, tdb_off_t , tdb_off_t );
+       int (*tdb_brlock)(struct tdb_context *, tdb_off_t , int, int, int);
+};
+
+struct tdb_context {
+       char *name; /* the name of the database */
+       void *map_ptr; /* where it is currently mapped */
+       int fd; /* open file descriptor for the database */
+       tdb_len_t map_size; /* how much space has been mapped */
+       int read_only; /* opened read-only */
+       int traverse_read; /* read-only traversal */
+       struct tdb_lock_type *locked; /* array of chain locks */
+       enum TDB_ERROR ecode; /* error code for last tdb error */
+       struct tdb_header header; /* a cached copy of the header */
+       u32 flags; /* the flags passed to tdb_open */
+       struct tdb_traverse_lock travlocks; /* current traversal locks */
+       struct tdb_context *next; /* all tdbs to avoid multiple opens */
+       dev_t device;   /* uniquely identifies this tdb */
+       ino_t inode;    /* uniquely identifies this tdb */
+       void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */
+       unsigned int (*hash_fn)(TDB_DATA *key);
+       int open_flags; /* flags used in the open - needed by reopen */
+       unsigned int num_locks; /* number of chain locks held */
+       const struct tdb_methods *methods;
+       struct tdb_transaction *transaction;
+       int page_size;
+};
+
+
+/*
+  internal prototypes
+*/
+int tdb_munmap(struct tdb_context *tdb);
+void tdb_mmap(struct tdb_context *tdb);
+int tdb_lock(struct tdb_context *tdb, int list, int ltype);
+int tdb_unlock(struct tdb_context *tdb, int list, int ltype);
+int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe);
+int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len);
+int tdb_brlock_len(struct tdb_context *tdb, tdb_off_t offset, 
+                  int rw_type, int lck_type, int probe, size_t len);
+int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
+int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
+int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
+int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
+void *tdb_convert(void *buf, u32 size);
+int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
+tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec);
+int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
+int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
+int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off);
+int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off);
+int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
+int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
+int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct *rec);
+char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len);
+tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype,
+                          struct list_struct *rec);
+void tdb_io_init(struct tdb_context *tdb);
+int tdb_expand(struct tdb_context *tdb, tdb_off_t size);
+
+
index 7967a6bbf543e9589e00c9df74c0000065df2cec..c337924d6cf459992b64e39a8cfdada99fedae2c 100644 (file)
@@ -77,7 +77,7 @@ static int copy_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
        TDB_CONTEXT *tdb_new = (TDB_CONTEXT *)state;
 
        if (tdb_store(tdb_new, key, dbuf, TDB_INSERT) != 0) {
-               fprintf(stderr,"Failed to insert into %s\n", tdb_new->name);
+               fprintf(stderr,"Failed to insert into %s\n", tdb_name(tdb));
                failed = 1;
                return 1;
        }
@@ -122,7 +122,7 @@ int backup_tdb(const char *old_name, const char *new_name)
 
        /* create the new tdb */
        unlink(tmp_name);
-       tdb_new = tdb_open(tmp_name, tdb->header.hash_size, 
+       tdb_new = tdb_open(tmp_name, tdb_hash_size(tdb),
                           TDB_DEFAULT, O_RDWR|O_CREAT|O_EXCL, 
                           st.st_mode & 0777);
        if (!tdb_new) {
@@ -179,7 +179,7 @@ int backup_tdb(const char *old_name, const char *new_name)
        }
 
        /* make sure the new tdb has reached stable storage */
-       fsync(tdb_new->fd);
+       fsync(tdb_fd(tdb_new));
 
        /* close the new tdb and rename it to .bak */
        tdb_close(tdb_new);
index fc45fa936060c61d7ad48b647be90be5ee57283a..e13f7e3e67895785dead9fd28b9a1ad263195f46 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include "includes.h"
+#include "tdb_private.h"
 #include <fnmatch.h>
 
+/***************************************************************
+ Allow a caller to set a "alarm" flag that tdb can check to abort
+ a blocking lock on SIGALRM.
+***************************************************************/
+
+static sig_atomic_t *palarm_fired;
+
+static void tdb_set_lock_alarm(sig_atomic_t *palarm)
+{
+       palarm_fired = palarm;
+}
+
 /* these are little tdb utility functions that are meant to make
    dealing with a tdb database a little less cumbersome in Samba */
 
@@ -641,129 +653,6 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...)
 }
 
 
-/**
- * Pack SID passed by pointer
- *
- * @param pack_buf pointer to buffer which is to be filled with packed data
- * @param bufsize size of packing buffer
- * @param sid pointer to sid to be packed
- *
- * @return length of the packed representation of the whole structure
- **/
-size_t tdb_sid_pack(char* pack_buf, int bufsize, DOM_SID* sid)
-{
-       int idx;
-       size_t len = 0;
-       
-       if (!sid || !pack_buf) return -1;
-       
-       len += tdb_pack(pack_buf + len, bufsize - len, "bb", sid->sid_rev_num,
-                       sid->num_auths);
-       
-       for (idx = 0; idx < 6; idx++) {
-               len += tdb_pack(pack_buf + len, bufsize - len, "b", sid->id_auth[idx]);
-       }
-       
-       for (idx = 0; idx < MAXSUBAUTHS; idx++) {
-               len += tdb_pack(pack_buf + len, bufsize - len, "d", sid->sub_auths[idx]);
-       }
-       
-       return len;
-}
-
-
-/**
- * Unpack SID into a pointer
- *
- * @param pack_buf pointer to buffer with packed representation
- * @param bufsize size of the buffer
- * @param sid pointer to sid structure to be filled with unpacked data
- *
- * @return size of structure unpacked from buffer
- **/
-size_t tdb_sid_unpack(char* pack_buf, int bufsize, DOM_SID* sid)
-{
-       int idx, len = 0;
-       
-       if (!sid || !pack_buf) return -1;
-
-       len += tdb_unpack(pack_buf + len, bufsize - len, "bb",
-                         &sid->sid_rev_num, &sid->num_auths);
-                         
-       for (idx = 0; idx < 6; idx++) {
-               len += tdb_unpack(pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]);
-       }
-       
-       for (idx = 0; idx < MAXSUBAUTHS; idx++) {
-               len += tdb_unpack(pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]);
-       }
-       
-       return len;
-}
-
-
-/**
- * Pack TRUSTED_DOM_PASS passed by pointer
- *
- * @param pack_buf pointer to buffer which is to be filled with packed data
- * @param bufsize size of the buffer
- * @param pass pointer to trusted domain password to be packed
- *
- * @return length of the packed representation of the whole structure
- **/
-size_t tdb_trusted_dom_pass_pack(char* pack_buf, int bufsize, TRUSTED_DOM_PASS* pass)
-{
-       int idx, len = 0;
-       
-       if (!pack_buf || !pass) return -1;
-       
-       /* packing unicode domain name and password */
-       len += tdb_pack(pack_buf + len, bufsize - len, "d", pass->uni_name_len);
-       
-       for (idx = 0; idx < 32; idx++)
-               len +=  tdb_pack(pack_buf + len, bufsize - len, "w", pass->uni_name[idx]);
-       
-       len += tdb_pack(pack_buf + len, bufsize - len, "dPd", pass->pass_len,
-                            pass->pass, pass->mod_time);
-
-       /* packing SID structure */
-       len += tdb_sid_pack(pack_buf + len, bufsize - len, &pass->domain_sid);
-
-       return len;
-}
-
-
-/**
- * Unpack TRUSTED_DOM_PASS passed by pointer
- *
- * @param pack_buf pointer to buffer with packed representation
- * @param bufsize size of the buffer
- * @param pass pointer to trusted domain password to be filled with unpacked data
- *
- * @return size of structure unpacked from buffer
- **/
-size_t tdb_trusted_dom_pass_unpack(char* pack_buf, int bufsize, TRUSTED_DOM_PASS* pass)
-{
-       int idx, len = 0;
-       
-       if (!pack_buf || !pass) return -1;
-
-       /* unpack unicode domain name and plaintext password */
-       len += tdb_unpack(pack_buf, bufsize - len, "d", &pass->uni_name_len);
-       
-       for (idx = 0; idx < 32; idx++)
-               len +=  tdb_unpack(pack_buf + len, bufsize - len, "w", &pass->uni_name[idx]);
-
-       len += tdb_unpack(pack_buf + len, bufsize - len, "dPd", &pass->pass_len, &pass->pass,
-                         &pass->mod_time);
-       
-       /* unpack domain sid */
-       len += tdb_sid_unpack(pack_buf + len, bufsize - len, &pass->domain_sid);
-       
-       return len;     
-}
-
-
 /****************************************************************************
  Log tdb messages via DEBUG().
 ****************************************************************************/
@@ -805,15 +694,6 @@ TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags,
        return tdb;
 }
 
-/****************************************************************************
-  return the name of the current tdb file useful for external logging
-  functions
-****************************************************************************/
-const char *tdb_name(struct tdb_context *tdb)
-{
-       return tdb->name;
-}
-
 /****************************************************************************
  Allow tdb_delete to be used as a tdb_traversal_fn.
 ****************************************************************************/
@@ -893,3 +773,43 @@ void tdb_search_list_free(TDB_LIST_NODE* node)
                node = next_node;
        };
 }
+
+size_t tdb_map_size(struct tdb_context *tdb)
+{
+       return tdb->map_size;
+}
+
+int tdb_get_flags(struct tdb_context *tdb)
+{
+       return tdb->flags;
+}
+
+/****************************************************************************
+ tdb_store, wrapped in a transaction. This way we make sure that a process
+ that dies within writing does not leave a corrupt tdb behind.
+****************************************************************************/
+
+int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf,
+                   int flag)
+{
+       int res;
+
+       if ((res = tdb_transaction_start(tdb)) != 0) {
+               DEBUG(5, ("tdb_transaction_start failed\n"));
+               return res;
+       }
+
+       if ((res = tdb_store(tdb, key, dbuf, flag)) != 0) {
+               DEBUG(10, ("tdb_store failed\n"));
+               if (tdb_transaction_cancel(tdb) != 0) {
+                       smb_panic("Cancelling transaction failed\n");
+               }
+               return res;
+       }
+
+       if ((res = tdb_transaction_commit(tdb)) != 0) {
+               DEBUG(5, ("tdb_transaction_commit failed\n"));
+       }
+
+       return res;
+}
index 1a181a962f2ff24847eb3679b1c3a5c72032aa08..44351619f451da25c159a697e197d4bce80eb19b 100644 (file)
@@ -1,8 +1,7 @@
 /* 
    Unix SMB/CIFS implementation.
    tdb utility functions
-   Copyright (C) Andrew Tridgell   1999
-   Copyright (C) Rafal Szczesniak  2002
+   Copyright (C) Andrew Tridgell 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
@@ -22,6 +21,7 @@
 #ifndef __TDBUTIL_H__
 #define __TDBUTIL_H__
 
+#include "tdb.h"
 
 /* single node of a list returned by tdb_search_keys */
 typedef struct keys_node 
@@ -31,8 +31,38 @@ typedef struct keys_node
 } TDB_LIST_NODE;
 
 
-TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT*, const char*);
+TDB_LIST_NODE *tdb_search_keys(struct tdb_context*, const char*);
 void tdb_search_list_free(TDB_LIST_NODE*);
-
+int32_t tdb_change_int32_atomic(struct tdb_context *tdb, const char *keystr, int32_t *oldval, int32_t change_val);
+int tdb_lock_bystring(struct tdb_context *tdb, const char *keyval);
+int tdb_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval,
+                                  int timeout);
+void tdb_unlock_bystring(struct tdb_context *tdb, const char *keyval);
+int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval,
+                                       unsigned int timeout);
+void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval);
+int32_t tdb_fetch_int32(struct tdb_context *tdb, const char *keystr);
+BOOL tdb_store_uint32(struct tdb_context *tdb, const char *keystr, uint32_t value);
+int tdb_store_int32(struct tdb_context *tdb, const char *keystr, int32_t v);
+BOOL tdb_fetch_uint32(struct tdb_context *tdb, const char *keystr, uint32_t *value);
+int tdb_traverse_delete_fn(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA dbuf,
+                     void *state);
+int tdb_store_bystring(struct tdb_context *tdb, const char *keystr, TDB_DATA data, int flags);
+TDB_DATA tdb_fetch_bystring(struct tdb_context *tdb, const char *keystr);
+int tdb_delete_bystring(struct tdb_context *tdb, const char *keystr);
+struct tdb_context *tdb_open_log(const char *name, int hash_size,
+                                int tdb_flags, int open_flags, mode_t mode);
+int tdb_unpack(char *buf, int bufsize, const char *fmt, ...);
+size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...);
+TDB_DATA make_tdb_data(const char *dptr, size_t dsize);
+TDB_DATA string_tdb_data(const char *string);
+int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf,
+                   int flag);
+BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr,
+                             uint32 *oldval, uint32 change_val);
+int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key,
+                               unsigned int timeout);
+int tdb_get_flags(struct tdb_context *tdb);
+size_t tdb_map_size(struct tdb_context *tdb);
 
 #endif /* __TDBUTIL_H__ */
diff --git a/source/tdb/transaction.c b/source/tdb/transaction.c
new file mode 100644 (file)
index 0000000..aa54c4a
--- /dev/null
@@ -0,0 +1,1043 @@
+ /* 
+   Unix SMB/CIFS implementation.
+
+   trivial database library
+
+   Copyright (C) Andrew Tridgell              2005
+
+     ** NOTE! The following LGPL license applies to the tdb
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "tdb_private.h"
+
+/*
+  transaction design:
+
+  - only allow a single transaction at a time per database. This makes
+    using the transaction API simpler, as otherwise the caller would
+    have to cope with temporary failures in transactions that conflict
+    with other current transactions
+
+  - keep the transaction recovery information in the same file as the
+    database, using a special 'transaction recovery' record pointed at
+    by the header. This removes the need for extra journal files as
+    used by some other databases
+
+  - dymacially allocated the transaction recover record, re-using it
+    for subsequent transactions. If a larger record is needed then
+    tdb_free() the old record to place it on the normal tdb freelist
+    before allocating the new record
+
+  - during transactions, keep a linked list of writes all that have
+    been performed by intercepting all tdb_write() calls. The hooked
+    transaction versions of tdb_read() and tdb_write() check this
+    linked list and try to use the elements of the list in preference
+    to the real database.
+
+  - don't allow any locks to be held when a transaction starts,
+    otherwise we can end up with deadlock (plus lack of lock nesting
+    in posix locks would mean the lock is lost)
+
+  - if the caller gains a lock during the transaction but doesn't
+    release it then fail the commit
+
+  - allow for nested calls to tdb_transaction_start(), re-using the
+    existing transaction record. If the inner transaction is cancelled
+    then a subsequent commit will fail
+  - keep a mirrored copy of the tdb hash chain heads to allow for the
+    fast hash heads scan on traverse, updating the mirrored copy in
+    the transaction version of tdb_write
+
+  - allow callers to mix transaction and non-transaction use of tdb,
+    although once a transaction is started then an exclusive lock is
+    gained until the transaction is committed or cancelled
+
+  - the commit stategy involves first saving away all modified data
+    into a linearised buffer in the transaction recovery area, then
+    marking the transaction recovery area with a magic value to
+    indicate a valid recovery record. In total 4 fsync/msync calls are
+    needed per commit to prevent race conditions. It might be possible
+    to reduce this to 3 or even 2 with some more work.
+
+  - check for a valid recovery record on open of the tdb, while the
+    global lock is held. Automatically recover from the transaction
+    recovery area if needed, then continue with the open as
+    usual. This allows for smooth crash recovery with no administrator
+    intervention.
+
+  - if TDB_NOSYNC is passed to flags in tdb_open then transactions are
+    still available, but no transaction recovery area is used and no
+    fsync/msync calls are made.
+
+*/
+
+
+/*
+  hold the context of any current transaction
+*/
+struct tdb_transaction {
+       /* we keep a mirrored copy of the tdb hash heads here so
+          tdb_next_hash_chain() can operate efficiently */
+       u32 *hash_heads;
+
+       /* the original io methods - used to do IOs to the real db */
+       const struct tdb_methods *io_methods;
+
+       /* the list of transaction elements. We use a doubly linked
+          list with a last pointer to allow us to keep the list
+          ordered, with first element at the front of the list. It
+          needs to be doubly linked as the read/write traversals need
+          to be backwards, while the commit needs to be forwards */
+       struct tdb_transaction_el {
+               struct tdb_transaction_el *next, *prev;
+               tdb_off_t offset;
+               tdb_len_t length;
+               unsigned char *data;
+       } *elements, *elements_last;
+
+       /* non-zero when an internal transaction error has
+          occurred. All write operations will then fail until the
+          transaction is ended */
+       int transaction_error;
+
+       /* when inside a transaction we need to keep track of any
+          nested tdb_transaction_start() calls, as these are allowed,
+          but don't create a new transaction */
+       int nesting;
+
+       /* old file size before transaction */
+       tdb_len_t old_map_size;
+};
+
+
+/*
+  read while in a transaction. We need to check first if the data is in our list
+  of transaction elements, then if not do a real read
+*/
+static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf, 
+                           tdb_len_t len, int cv)
+{
+       struct tdb_transaction_el *el;
+
+       /* we need to walk the list backwards to get the most recent data */
+       for (el=tdb->transaction->elements_last;el;el=el->prev) {
+               tdb_len_t partial;
+
+               if (off+len <= el->offset) {
+                       continue;
+               }
+               if (off >= el->offset + el->length) {
+                       continue;
+               }
+
+               /* an overlapping read - needs to be split into up to
+                  2 reads and a memcpy */
+               if (off < el->offset) {
+                       partial = el->offset - off;
+                       if (transaction_read(tdb, off, buf, partial, cv) != 0) {
+                               goto fail;
+                       }
+                       len -= partial;
+                       off += partial;
+                       buf = (void *)(partial + (char *)buf);
+               }
+               if (off + len <= el->offset + el->length) {
+                       partial = len;
+               } else {
+                       partial = el->offset + el->length - off;
+               }
+               memcpy(buf, el->data + (off - el->offset), partial);
+               if (cv) {
+                       tdb_convert(buf, len);
+               }
+               len -= partial;
+               off += partial;
+               buf = (void *)(partial + (char *)buf);
+               
+               if (len != 0 && transaction_read(tdb, off, buf, len, cv) != 0) {
+                       goto fail;
+               }
+
+               return 0;
+       }
+
+       /* its not in the transaction elements - do a real read */
+       return tdb->transaction->io_methods->tdb_read(tdb, off, buf, len, cv);
+
+fail:
+       TDB_LOG((tdb, 0, "transaction_read: failed at off=%d len=%d\n", off, len));
+       tdb->ecode = TDB_ERR_IO;
+       tdb->transaction->transaction_error = 1;
+       return -1;
+}
+
+
+/*
+  write while in a transaction
+*/
+static int transaction_write(struct tdb_context *tdb, tdb_off_t off, 
+                            const void *buf, tdb_len_t len)
+{
+       struct tdb_transaction_el *el, *best_el=NULL;
+
+       if (len == 0) {
+               return 0;
+       }
+       
+       /* if the write is to a hash head, then update the transaction
+          hash heads */
+       if (len == sizeof(tdb_off_t) && off >= FREELIST_TOP &&
+           off < FREELIST_TOP+TDB_HASHTABLE_SIZE(tdb)) {
+               u32 chain = (off-FREELIST_TOP) / sizeof(tdb_off_t);
+               memcpy(&tdb->transaction->hash_heads[chain], buf, len);
+       }
+
+       /* first see if we can replace an existing entry */
+       for (el=tdb->transaction->elements_last;el;el=el->prev) {
+               tdb_len_t partial;
+
+               if (best_el == NULL && off == el->offset+el->length) {
+                       best_el = el;
+               }
+
+               if (off+len <= el->offset) {
+                       continue;
+               }
+               if (off >= el->offset + el->length) {
+                       continue;
+               }
+
+               /* an overlapping write - needs to be split into up to
+                  2 writes and a memcpy */
+               if (off < el->offset) {
+                       partial = el->offset - off;
+                       if (transaction_write(tdb, off, buf, partial) != 0) {
+                               goto fail;
+                       }
+                       len -= partial;
+                       off += partial;
+                       buf = (const void *)(partial + (const char *)buf);
+               }
+               if (off + len <= el->offset + el->length) {
+                       partial = len;
+               } else {
+                       partial = el->offset + el->length - off;
+               }
+               memcpy(el->data + (off - el->offset), buf, partial);
+               len -= partial;
+               off += partial;
+               buf = (const void *)(partial + (const char *)buf);
+               
+               if (len != 0 && transaction_write(tdb, off, buf, len) != 0) {
+                       goto fail;
+               }
+
+               return 0;
+       }
+
+       /* see if we can append the new entry to an existing entry */
+       if (best_el && best_el->offset + best_el->length == off && 
+           (off+len < tdb->transaction->old_map_size ||
+            off > tdb->transaction->old_map_size)) {
+               unsigned char *data = best_el->data;
+               el = best_el;
+               el->data = realloc(el->data, el->length + len);
+               if (el->data == NULL) {
+                       tdb->ecode = TDB_ERR_OOM;
+                       tdb->transaction->transaction_error = 1;
+                       el->data = data;
+                       return -1;
+               }
+               if (buf) {
+                       memcpy(el->data + el->length, buf, len);
+               } else {
+                       memset(el->data + el->length, TDB_PAD_BYTE, len);
+               }
+               el->length += len;
+               return 0;
+       }
+
+       /* add a new entry at the end of the list */
+       el = malloc(sizeof(*el));
+       if (el == NULL) {
+               tdb->ecode = TDB_ERR_OOM;
+               tdb->transaction->transaction_error = 1;                
+               return -1;
+       }
+       el->next = NULL;
+       el->prev = tdb->transaction->elements_last;
+       el->offset = off;
+       el->length = len;
+       el->data = malloc(len);
+       if (el->data == NULL) {
+               free(el);
+               tdb->ecode = TDB_ERR_OOM;
+               tdb->transaction->transaction_error = 1;                
+               return -1;
+       }
+       if (buf) {
+               memcpy(el->data, buf, len);
+       } else {
+               memset(el->data, TDB_PAD_BYTE, len);
+       }
+       if (el->prev) {
+               el->prev->next = el;
+       } else {
+               tdb->transaction->elements = el;
+       }
+       tdb->transaction->elements_last = el;
+       return 0;
+
+fail:
+       TDB_LOG((tdb, 0, "transaction_write: failed at off=%d len=%d\n", off, len));
+       tdb->ecode = TDB_ERR_IO;
+       tdb->transaction->transaction_error = 1;
+       return -1;
+}
+
+/*
+  accelerated hash chain head search, using the cached hash heads
+*/
+static void transaction_next_hash_chain(struct tdb_context *tdb, u32 *chain)
+{
+       u32 h = *chain;
+       for (;h < tdb->header.hash_size;h++) {
+               /* the +1 takes account of the freelist */
+               if (0 != tdb->transaction->hash_heads[h+1]) {
+                       break;
+               }
+       }
+       (*chain) = h;
+}
+
+/*
+  out of bounds check during a transaction
+*/
+static int transaction_oob(struct tdb_context *tdb, tdb_off_t len, int probe)
+{
+       if (len <= tdb->map_size) {
+               return 0;
+       }
+       return TDB_ERRCODE(TDB_ERR_IO, -1);
+}
+
+/*
+  transaction version of tdb_expand().
+*/
+static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size, 
+                                  tdb_off_t addition)
+{
+       /* add a write to the transaction elements, so subsequent
+          reads see the zero data */
+       if (transaction_write(tdb, size, NULL, addition) != 0) {
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+  brlock during a transaction - ignore them
+*/
+int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset, 
+                      int rw_type, int lck_type, int probe)
+{
+       return 0;
+}
+
+static const struct tdb_methods transaction_methods = {
+       transaction_read,
+       transaction_write,
+       transaction_next_hash_chain,
+       transaction_oob,
+       transaction_expand_file,
+       transaction_brlock
+};
+
+
+/*
+  start a tdb transaction. No token is returned, as only a single
+  transaction is allowed to be pending per tdb_context
+*/
+int tdb_transaction_start(struct tdb_context *tdb)
+{
+       /* some sanity checks */
+       if (tdb->read_only || (tdb->flags & TDB_INTERNAL) || tdb->traverse_read) {
+               TDB_LOG((tdb, 0, "tdb_transaction_start: cannot start a transaction on a read-only or internal db\n"));
+               tdb->ecode = TDB_ERR_EINVAL;
+               return -1;
+       }
+
+       /* cope with nested tdb_transaction_start() calls */
+       if (tdb->transaction != NULL) {
+               tdb->transaction->nesting++;
+               TDB_LOG((tdb, 0, "tdb_transaction_start: nesting %d\n", 
+                        tdb->transaction->nesting));
+               return 0;
+       }
+
+       if (tdb->num_locks != 0) {
+               /* the caller must not have any locks when starting a
+                  transaction as otherwise we'll be screwed by lack
+                  of nested locks in posix */
+               TDB_LOG((tdb, 0, "tdb_transaction_start: cannot start a transaction with locks held\n"));
+               tdb->ecode = TDB_ERR_LOCK;
+               return -1;
+       }
+
+       if (tdb->travlocks.next != NULL) {
+               /* you cannot use transactions inside a traverse (although you can use
+                  traverse inside a transaction) as otherwise you can end up with
+                  deadlock */
+               TDB_LOG((tdb, 0, "tdb_transaction_start: cannot start a transaction within a traverse\n"));
+               tdb->ecode = TDB_ERR_LOCK;
+               return -1;
+       }
+
+       tdb->transaction = calloc(sizeof(struct tdb_transaction), 1);
+       if (tdb->transaction == NULL) {
+               tdb->ecode = TDB_ERR_OOM;
+               return -1;
+       }
+
+       /* get the transaction write lock. This is a blocking lock. As
+          discussed with Volker, there are a number of ways we could
+          make this async, which we will probably do in the future */
+       if (tdb_brlock_len(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
+               TDB_LOG((tdb, 0, "tdb_transaction_start: failed to get transaction lock\n"));
+               tdb->ecode = TDB_ERR_LOCK;
+               SAFE_FREE(tdb->transaction);
+               return -1;
+       }
+       
+       /* get a read lock from the freelist to the end of file. This
+          is upgraded to a write lock during the commit */
+       if (tdb_brlock_len(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) {
+               TDB_LOG((tdb, 0, "tdb_transaction_start: failed to get hash locks\n"));
+               tdb->ecode = TDB_ERR_LOCK;
+               goto fail;
+       }
+
+       /* setup a copy of the hash table heads so the hash scan in
+          traverse can be fast */
+       tdb->transaction->hash_heads = calloc(tdb->header.hash_size+1, sizeof(tdb_off_t));
+       if (tdb->transaction->hash_heads == NULL) {
+               tdb->ecode = TDB_ERR_OOM;
+               goto fail;
+       }
+       if (tdb->methods->tdb_read(tdb, FREELIST_TOP, tdb->transaction->hash_heads,
+                                  TDB_HASHTABLE_SIZE(tdb), 0) != 0) {
+               TDB_LOG((tdb, 0, "tdb_transaction_start: failed to read hash heads\n"));
+               tdb->ecode = TDB_ERR_IO;
+               goto fail;
+       }
+
+       /* make sure we know about any file expansions already done by
+          anyone else */
+       tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1);
+       tdb->transaction->old_map_size = tdb->map_size;
+
+       /* finally hook the io methods, replacing them with
+          transaction specific methods */
+       tdb->transaction->io_methods = tdb->methods;
+       tdb->methods = &transaction_methods;
+
+       /* by calling this transaction write here, we ensure that we don't grow the
+          transaction linked list due to hash table updates */
+       if (transaction_write(tdb, FREELIST_TOP, tdb->transaction->hash_heads, 
+                             TDB_HASHTABLE_SIZE(tdb)) != 0) {
+               TDB_LOG((tdb, 0, "tdb_transaction_start: failed to prime hash table\n"));
+               tdb->ecode = TDB_ERR_IO;
+               goto fail;
+       }
+
+       return 0;
+       
+fail:
+       tdb_brlock_len(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
+       tdb_brlock_len(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+       SAFE_FREE(tdb->transaction->hash_heads);
+       SAFE_FREE(tdb->transaction);
+       return -1;
+}
+
+
+/*
+  cancel the current transaction
+*/
+int tdb_transaction_cancel(struct tdb_context *tdb)
+{      
+       if (tdb->transaction == NULL) {
+               TDB_LOG((tdb, 0, "tdb_transaction_cancel: no transaction\n"));
+               return -1;
+       }
+
+       if (tdb->transaction->nesting != 0) {
+               tdb->transaction->transaction_error = 1;
+               tdb->transaction->nesting--;
+               return 0;
+       }               
+
+       tdb->map_size = tdb->transaction->old_map_size;
+
+       /* free all the transaction elements */
+       while (tdb->transaction->elements) {
+               struct tdb_transaction_el *el = tdb->transaction->elements;
+               tdb->transaction->elements = el->next;
+               free(el->data);
+               free(el);
+       }
+
+       /* remove any locks created during the transaction */
+       if (tdb->num_locks != 0) {
+               int h;
+               for (h=0;h<tdb->header.hash_size+1;h++) {
+                       if (tdb->locked[h].count != 0) {
+                               tdb_brlock_len(tdb,FREELIST_TOP+4*h,F_UNLCK,F_SETLKW, 0, 1);
+                               tdb->locked[h].count = 0;
+                       }
+               }
+               tdb->num_locks = 0;
+       }
+
+       /* restore the normal io methods */
+       tdb->methods = tdb->transaction->io_methods;
+
+       tdb_brlock_len(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
+       tdb_brlock_len(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+       SAFE_FREE(tdb->transaction->hash_heads);
+       SAFE_FREE(tdb->transaction);
+       
+       return 0;
+}
+
+/*
+  sync to disk
+*/
+static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t length)
+{      
+       if (fsync(tdb->fd) != 0) {
+               tdb->ecode = TDB_ERR_IO;
+               TDB_LOG((tdb, 0, "tdb_transaction: fsync failed\n"));
+               return -1;
+       }
+#ifdef MS_SYNC
+       if (tdb->map_ptr) {
+               tdb_off_t moffset = offset & ~(tdb->page_size-1);
+               if (msync(moffset + (char *)tdb->map_ptr, 
+                         length + (offset - moffset), MS_SYNC) != 0) {
+                       tdb->ecode = TDB_ERR_IO;
+                       TDB_LOG((tdb, 0, "tdb_transaction: msync failed - %s\n",
+                                strerror(errno)));
+                       return -1;
+               }
+       }
+#endif
+       return 0;
+}
+
+
+/*
+  work out how much space the linearised recovery data will consume
+*/
+static tdb_len_t tdb_recovery_size(struct tdb_context *tdb)
+{
+       struct tdb_transaction_el *el;
+       tdb_len_t recovery_size = 0;
+
+       recovery_size = sizeof(u32);
+       for (el=tdb->transaction->elements;el;el=el->next) {
+               if (el->offset >= tdb->transaction->old_map_size) {
+                       continue;
+               }
+               recovery_size += 2*sizeof(tdb_off_t) + el->length;
+       }
+
+       return recovery_size;
+}
+
+/*
+  allocate the recovery area, or use an existing recovery area if it is
+  large enough
+*/
+static int tdb_recovery_allocate(struct tdb_context *tdb, 
+                                tdb_len_t *recovery_size,
+                                tdb_off_t *recovery_offset,
+                                tdb_len_t *recovery_max_size)
+{
+       struct list_struct rec;
+       const struct tdb_methods *methods = tdb->transaction->io_methods;
+       tdb_off_t recovery_head;
+
+       if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {
+               TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to read recovery head\n"));
+               return -1;
+       }
+
+       rec.rec_len = 0;
+
+       if (recovery_head != 0 && 
+           methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) {
+               TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to read recovery record\n"));
+               return -1;
+       }
+
+       *recovery_size = tdb_recovery_size(tdb);
+
+       if (recovery_head != 0 && *recovery_size <= rec.rec_len) {
+               /* it fits in the existing area */
+               *recovery_max_size = rec.rec_len;
+               *recovery_offset = recovery_head;
+               return 0;
+       }
+
+       /* we need to free up the old recovery area, then allocate a
+          new one at the end of the file. Note that we cannot use
+          tdb_allocate() to allocate the new one as that might return
+          us an area that is being currently used (as of the start of
+          the transaction) */
+       if (recovery_head != 0) {
+               if (tdb_free(tdb, recovery_head, &rec) == -1) {
+                       TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to free previous recovery area\n"));
+                       return -1;
+               }
+       }
+
+       /* the tdb_free() call might have increased the recovery size */
+       *recovery_size = tdb_recovery_size(tdb);
+
+       /* round up to a multiple of page size */
+       *recovery_max_size = TDB_ALIGN(sizeof(rec) + *recovery_size, tdb->page_size) - sizeof(rec);
+       *recovery_offset = tdb->map_size;
+       recovery_head = *recovery_offset;
+
+       if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, 
+                                    (tdb->map_size - tdb->transaction->old_map_size) +
+                                    sizeof(rec) + *recovery_max_size) == -1) {
+               TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to create recovery area\n"));
+               return -1;
+       }
+
+       /* remap the file (if using mmap) */
+       methods->tdb_oob(tdb, tdb->map_size + 1, 1);
+
+       /* we have to reset the old map size so that we don't try to expand the file
+          again in the transaction commit, which would destroy the recovery area */
+       tdb->transaction->old_map_size = tdb->map_size;
+
+       /* write the recovery header offset and sync - we can sync without a race here
+          as the magic ptr in the recovery record has not been set */
+       CONVERT(recovery_head);
+       if (methods->tdb_write(tdb, TDB_RECOVERY_HEAD, 
+                              &recovery_head, sizeof(tdb_off_t)) == -1) {
+               TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to write recovery head\n"));
+               return -1;
+       }
+
+       return 0;
+}
+
+
+/*
+  setup the recovery data that will be used on a crash during commit
+*/
+static int transaction_setup_recovery(struct tdb_context *tdb, 
+                                     tdb_off_t *magic_offset)
+{
+       struct tdb_transaction_el *el;
+       tdb_len_t recovery_size;
+       unsigned char *data, *p;
+       const struct tdb_methods *methods = tdb->transaction->io_methods;
+       struct list_struct *rec;
+       tdb_off_t recovery_offset, recovery_max_size;
+       tdb_off_t old_map_size = tdb->transaction->old_map_size;
+       u32 magic, tailer;
+
+       /*
+         check that the recovery area has enough space
+       */
+       if (tdb_recovery_allocate(tdb, &recovery_size, 
+                                 &recovery_offset, &recovery_max_size) == -1) {
+               return -1;
+       }
+
+       data = malloc(recovery_size + sizeof(*rec));
+       if (data == NULL) {
+               tdb->ecode = TDB_ERR_OOM;
+               return -1;
+       }
+
+       rec = (struct list_struct *)data;
+       memset(rec, 0, sizeof(*rec));
+
+       rec->magic    = 0;
+       rec->data_len = recovery_size;
+       rec->rec_len  = recovery_max_size;
+       rec->key_len  = old_map_size;
+       CONVERT(rec);
+
+       /* build the recovery data into a single blob to allow us to do a single
+          large write, which should be more efficient */
+       p = data + sizeof(*rec);
+       for (el=tdb->transaction->elements;el;el=el->next) {
+               if (el->offset >= old_map_size) {
+                       continue;
+               }
+               if (el->offset + el->length > tdb->transaction->old_map_size) {
+                       TDB_LOG((tdb, 0, "tdb_transaction_commit: transaction data over new region boundary\n"));
+                       free(data);
+                       tdb->ecode = TDB_ERR_CORRUPT;
+                       return -1;
+               }
+               memcpy(p, &el->offset, 4);
+               memcpy(p+4, &el->length, 4);
+               if (DOCONV()) {
+                       tdb_convert(p, 8);
+               }
+               /* the recovery area contains the old data, not the
+                  new data, so we have to call the original tdb_read
+                  method to get it */
+               if (methods->tdb_read(tdb, el->offset, p + 8, el->length, 0) != 0) {
+                       free(data);
+                       tdb->ecode = TDB_ERR_IO;
+                       return -1;
+               }
+               p += 8 + el->length;
+       }
+
+       /* and the tailer */
+       tailer = sizeof(*rec) + recovery_max_size;
+       memcpy(p, &tailer, 4);
+       CONVERT(p);
+
+       /* write the recovery data to the recovery area */
+       if (methods->tdb_write(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) {
+               TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to write recovery data\n"));
+               free(data);
+               tdb->ecode = TDB_ERR_IO;
+               return -1;
+       }
+
+       /* as we don't have ordered writes, we have to sync the recovery
+          data before we update the magic to indicate that the recovery
+          data is present */
+       if (transaction_sync(tdb, recovery_offset, sizeof(*rec) + recovery_size) == -1) {
+               free(data);
+               return -1;
+       }
+
+       free(data);
+
+       magic = TDB_RECOVERY_MAGIC;
+       CONVERT(magic);
+
+       *magic_offset = recovery_offset + offsetof(struct list_struct, magic);
+
+       if (methods->tdb_write(tdb, *magic_offset, &magic, sizeof(magic)) == -1) {
+               TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to write recovery magic\n"));
+               tdb->ecode = TDB_ERR_IO;
+               return -1;
+       }
+
+       /* ensure the recovery magic marker is on disk */
+       if (transaction_sync(tdb, *magic_offset, sizeof(magic)) == -1) {
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+  commit the current transaction
+*/
+int tdb_transaction_commit(struct tdb_context *tdb)
+{      
+       const struct tdb_methods *methods;
+       tdb_off_t magic_offset = 0;
+       u32 zero = 0;
+
+       if (tdb->transaction == NULL) {
+               TDB_LOG((tdb, 0, "tdb_transaction_commit: no transaction\n"));
+               return -1;
+       }
+
+       if (tdb->transaction->transaction_error) {
+               tdb->ecode = TDB_ERR_IO;
+               tdb_transaction_cancel(tdb);
+               TDB_LOG((tdb, 0, "tdb_transaction_commit: transaction error pending\n"));
+               return -1;
+       }
+
+       if (tdb->transaction->nesting != 0) {
+               tdb->transaction->nesting--;
+               return 0;
+       }               
+
+       /* check for a null transaction */
+       if (tdb->transaction->elements == NULL) {
+               tdb_transaction_cancel(tdb);
+               return 0;
+       }
+
+       methods = tdb->transaction->io_methods;
+       
+       /* if there are any locks pending then the caller has not
+          nested their locks properly, so fail the transaction */
+       if (tdb->num_locks) {
+               tdb->ecode = TDB_ERR_LOCK;
+               TDB_LOG((tdb, 0, "tdb_transaction_commit: locks pending on commit\n"));
+               tdb_transaction_cancel(tdb);
+               return -1;
+       }
+
+       /* upgrade the main transaction lock region to a write lock */
+       if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) {
+               TDB_LOG((tdb, 0, "tdb_transaction_start: failed to upgrade hash locks\n"));
+               tdb->ecode = TDB_ERR_LOCK;
+               tdb_transaction_cancel(tdb);
+               return -1;
+       }
+
+       /* get the global lock - this prevents new users attaching to the database
+          during the commit */
+       if (tdb_brlock_len(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
+               TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to get global lock\n"));
+               tdb->ecode = TDB_ERR_LOCK;
+               tdb_transaction_cancel(tdb);
+               return -1;
+       }
+
+       if (!(tdb->flags & TDB_NOSYNC)) {
+               /* write the recovery data to the end of the file */
+               if (transaction_setup_recovery(tdb, &magic_offset) == -1) {
+                       TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to setup recovery data\n"));
+                       tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+                       tdb_transaction_cancel(tdb);
+                       return -1;
+               }
+       }
+
+       /* expand the file to the new size if needed */
+       if (tdb->map_size != tdb->transaction->old_map_size) {
+               if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, 
+                                            tdb->map_size - 
+                                            tdb->transaction->old_map_size) == -1) {
+                       tdb->ecode = TDB_ERR_IO;
+                       TDB_LOG((tdb, 0, "tdb_transaction_commit: expansion failed\n"));
+                       tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+                       tdb_transaction_cancel(tdb);
+                       return -1;
+               }
+               tdb->map_size = tdb->transaction->old_map_size;
+               methods->tdb_oob(tdb, tdb->map_size + 1, 1);
+       }
+
+       /* perform all the writes */
+       while (tdb->transaction->elements) {
+               struct tdb_transaction_el *el = tdb->transaction->elements;
+
+               if (methods->tdb_write(tdb, el->offset, el->data, el->length) == -1) {
+                       TDB_LOG((tdb, 0, "tdb_transaction_commit: write failed during commit\n"));
+                       
+                       /* we've overwritten part of the data and
+                          possibly expanded the file, so we need to
+                          run the crash recovery code */
+                       tdb->methods = methods;
+                       tdb_transaction_recover(tdb); 
+
+                       tdb_transaction_cancel(tdb);
+                       tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+
+                       TDB_LOG((tdb, 0, "tdb_transaction_commit: write failed\n"));
+                       return -1;
+               }
+               tdb->transaction->elements = el->next;
+               free(el->data); 
+               free(el);
+       } 
+
+       if (!(tdb->flags & TDB_NOSYNC)) {
+               /* ensure the new data is on disk */
+               if (transaction_sync(tdb, 0, tdb->map_size) == -1) {
+                       return -1;
+               }
+
+               /* remove the recovery marker */
+               if (methods->tdb_write(tdb, magic_offset, &zero, 4) == -1) {
+                       TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to remove recovery magic\n"));
+                       return -1;
+               }
+
+               /* ensure the recovery marker has been removed on disk */
+               if (transaction_sync(tdb, magic_offset, 4) == -1) {
+                       return -1;
+               }
+       }
+
+       tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+
+       /*
+         TODO: maybe write to some dummy hdr field, or write to magic
+         offset without mmap, before the last sync, instead of the
+         utime() call
+       */
+
+       /* on some systems (like Linux 2.6.x) changes via mmap/msync
+          don't change the mtime of the file, this means the file may
+          not be backed up (as tdb rounding to block sizes means that
+          file size changes are quite rare too). The following forces
+          mtime changes when a transaction completes */
+#ifdef HAVE_UTIME
+       utime(tdb->name, NULL);
+#endif
+
+       /* use a transaction cancel to free memory and remove the
+          transaction locks */
+       tdb_transaction_cancel(tdb);
+       return 0;
+}
+
+
+/*
+  recover from an aborted transaction. Must be called with exclusive
+  database write access already established (including the global
+  lock to prevent new processes attaching)
+*/
+int tdb_transaction_recover(struct tdb_context *tdb)
+{
+       tdb_off_t recovery_head, recovery_eof;
+       unsigned char *data, *p;
+       u32 zero = 0;
+       struct list_struct rec;
+
+       /* find the recovery area */
+       if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {
+               TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to read recovery head\n"));
+               tdb->ecode = TDB_ERR_IO;
+               return -1;
+       }
+
+       if (recovery_head == 0) {
+               /* we have never allocated a recovery record */
+               return 0;
+       }
+
+       /* read the recovery record */
+       if (tdb->methods->tdb_read(tdb, recovery_head, &rec, 
+                                  sizeof(rec), DOCONV()) == -1) {
+               TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to read recovery record\n"));         
+               tdb->ecode = TDB_ERR_IO;
+               return -1;
+       }
+
+       if (rec.magic != TDB_RECOVERY_MAGIC) {
+               /* there is no valid recovery data */
+               return 0;
+       }
+
+       if (tdb->read_only) {
+               TDB_LOG((tdb, 0, "tdb_transaction_recover: attempt to recover read only database\n"));
+               tdb->ecode = TDB_ERR_CORRUPT;
+               return -1;
+       }
+
+       recovery_eof = rec.key_len;
+
+       data = malloc(rec.data_len);
+       if (data == NULL) {
+               TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to allocate recovery data\n"));               
+               tdb->ecode = TDB_ERR_OOM;
+               return -1;
+       }
+
+       /* read the full recovery data */
+       if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data,
+                                  rec.data_len, 0) == -1) {
+               TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to read recovery data\n"));           
+               tdb->ecode = TDB_ERR_IO;
+               return -1;
+       }
+
+       /* recover the file data */
+       p = data;
+       while (p+8 < data + rec.data_len) {
+               u32 ofs, len;
+               if (DOCONV()) {
+                       tdb_convert(p, 8);
+               }
+               memcpy(&ofs, p, 4);
+               memcpy(&len, p+4, 4);
+
+               if (tdb->methods->tdb_write(tdb, ofs, p+8, len) == -1) {
+                       free(data);
+                       TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to recover %d bytes at offset %d\n", len, ofs));
+                       tdb->ecode = TDB_ERR_IO;
+                       return -1;
+               }
+               p += 8 + len;
+       }
+
+       free(data);
+
+       if (transaction_sync(tdb, 0, tdb->map_size) == -1) {
+               TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to sync recovery\n"));
+               tdb->ecode = TDB_ERR_IO;
+               return -1;
+       }
+
+       /* if the recovery area is after the recovered eof then remove it */
+       if (recovery_eof <= recovery_head) {
+               if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) {
+                       TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to remove recovery head\n"));
+                       tdb->ecode = TDB_ERR_IO;
+                       return -1;                      
+               }
+       }
+
+       /* remove the recovery magic */
+       if (tdb_ofs_write(tdb, recovery_head + offsetof(struct list_struct, magic), 
+                         &zero) == -1) {
+               TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to remove recovery magic\n"));
+               tdb->ecode = TDB_ERR_IO;
+               return -1;                      
+       }
+       
+       /* reduce the file size to the old size */
+       tdb_munmap(tdb);
+       if (ftruncate(tdb->fd, recovery_eof) != 0) {
+               TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to reduce to recovery size\n"));
+               tdb->ecode = TDB_ERR_IO;
+               return -1;                      
+       }
+       tdb->map_size = recovery_eof;
+       tdb_mmap(tdb);
+
+       if (transaction_sync(tdb, 0, recovery_eof) == -1) {
+               TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to sync2 recovery\n"));
+               tdb->ecode = TDB_ERR_IO;
+               return -1;
+       }
+
+       TDB_LOG((tdb, 0, "tdb_transaction_recover: recovered %d byte database\n", 
+                recovery_eof));
+
+       /* all done */
+       return 0;
+}
diff --git a/source/tdb/traverse.c b/source/tdb/traverse.c
new file mode 100644 (file)
index 0000000..d070e0a
--- /dev/null
@@ -0,0 +1,334 @@
+ /* 
+   Unix SMB/CIFS implementation.
+
+   trivial database library
+
+   Copyright (C) Andrew Tridgell              1999-2005
+   Copyright (C) Paul `Rusty' Russell             2000
+   Copyright (C) Jeremy Allison                           2000-2003
+   
+     ** NOTE! The following LGPL license applies to the tdb
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "tdb_private.h"
+
+/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */
+static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tlock,
+                        struct list_struct *rec)
+{
+       int want_next = (tlock->off != 0);
+
+       /* Lock each chain from the start one. */
+       for (; tlock->hash < tdb->header.hash_size; tlock->hash++) {
+               if (!tlock->off && tlock->hash != 0) {
+                       /* this is an optimisation for the common case where
+                          the hash chain is empty, which is particularly
+                          common for the use of tdb with ldb, where large
+                          hashes are used. In that case we spend most of our
+                          time in tdb_brlock(), locking empty hash chains.
+                          
+                          To avoid this, we do an unlocked pre-check to see
+                          if the hash chain is empty before starting to look
+                          inside it. If it is empty then we can avoid that
+                          hash chain. If it isn't empty then we can't believe
+                          the value we get back, as we read it without a
+                          lock, so instead we get the lock and re-fetch the
+                          value below.
+                          
+                          Notice that not doing this optimisation on the
+                          first hash chain is critical. We must guarantee
+                          that we have done at least one fcntl lock at the
+                          start of a search to guarantee that memory is
+                          coherent on SMP systems. If records are added by
+                          others during the search then thats OK, and we
+                          could possibly miss those with this trick, but we
+                          could miss them anyway without this trick, so the
+                          semantics don't change.
+                          
+                          With a non-indexed ldb search this trick gains us a
+                          factor of around 80 in speed on a linux 2.6.x
+                          system (testing using ldbtest).
+                       */
+                       tdb->methods->next_hash_chain(tdb, &tlock->hash);
+                       if (tlock->hash == tdb->header.hash_size) {
+                               continue;
+                       }
+               }
+
+               if (tdb_lock(tdb, tlock->hash, tlock->lock_rw) == -1)
+                       return -1;
+
+               /* No previous record?  Start at top of chain. */
+               if (!tlock->off) {
+                       if (tdb_ofs_read(tdb, TDB_HASH_TOP(tlock->hash),
+                                    &tlock->off) == -1)
+                               goto fail;
+               } else {
+                       /* Otherwise unlock the previous record. */
+                       if (tdb_unlock_record(tdb, tlock->off) != 0)
+                               goto fail;
+               }
+
+               if (want_next) {
+                       /* We have offset of old record: grab next */
+                       if (tdb_rec_read(tdb, tlock->off, rec) == -1)
+                               goto fail;
+                       tlock->off = rec->next;
+               }
+
+               /* Iterate through chain */
+               while( tlock->off) {
+                       tdb_off_t current;
+                       if (tdb_rec_read(tdb, tlock->off, rec) == -1)
+                               goto fail;
+
+                       /* Detect infinite loops. From "Shlomi Yaakobovich" <Shlomi@exanet.com>. */
+                       if (tlock->off == rec->next) {
+                               TDB_LOG((tdb, 0, "tdb_next_lock: loop detected.\n"));
+                               goto fail;
+                       }
+
+                       if (!TDB_DEAD(rec)) {
+                               /* Woohoo: we found one! */
+                               if (tdb_lock_record(tdb, tlock->off) != 0)
+                                       goto fail;
+                               return tlock->off;
+                       }
+
+                       /* Try to clean dead ones from old traverses */
+                       current = tlock->off;
+                       tlock->off = rec->next;
+                       if (!(tdb->read_only || tdb->traverse_read) && 
+                           tdb_do_delete(tdb, current, rec) != 0)
+                               goto fail;
+               }
+               tdb_unlock(tdb, tlock->hash, tlock->lock_rw);
+               want_next = 0;
+       }
+       /* We finished iteration without finding anything */
+       return TDB_ERRCODE(TDB_SUCCESS, 0);
+
+ fail:
+       tlock->off = 0;
+       if (tdb_unlock(tdb, tlock->hash, tlock->lock_rw) != 0)
+               TDB_LOG((tdb, 0, "tdb_next_lock: On error unlock failed!\n"));
+       return -1;
+}
+
+/* traverse the entire database - calling fn(tdb, key, data) on each element.
+   return -1 on error or the record count traversed
+   if fn is NULL then it is not called
+   a non-zero return value from fn() indicates that the traversal should stop
+  */
+static int tdb_traverse_internal(struct tdb_context *tdb, 
+                                tdb_traverse_func fn, void *private_data,
+                                struct tdb_traverse_lock *tl)
+{
+       TDB_DATA key, dbuf;
+       struct list_struct rec;
+       int ret, count = 0;
+
+       /* This was in the initializaton, above, but the IRIX compiler
+        * did not like it.  crh
+        */
+       tl->next = tdb->travlocks.next;
+
+       /* fcntl locks don't stack: beware traverse inside traverse */
+       tdb->travlocks.next = tl;
+
+       /* tdb_next_lock places locks on the record returned, and its chain */
+       while ((ret = tdb_next_lock(tdb, tl, &rec)) > 0) {
+               count++;
+               /* now read the full record */
+               key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec), 
+                                         rec.key_len + rec.data_len);
+               if (!key.dptr) {
+                       ret = -1;
+                       if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0)
+                               goto out;
+                       if (tdb_unlock_record(tdb, tl->off) != 0)
+                               TDB_LOG((tdb, 0, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n"));
+                       goto out;
+               }
+               key.dsize = rec.key_len;
+               dbuf.dptr = key.dptr + rec.key_len;
+               dbuf.dsize = rec.data_len;
+
+               /* Drop chain lock, call out */
+               if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) {
+                       ret = -1;
+                       SAFE_FREE(key.dptr);
+                       goto out;
+               }
+               if (fn && fn(tdb, key, dbuf, private_data)) {
+                       /* They want us to terminate traversal */
+                       ret = count;
+                       if (tdb_unlock_record(tdb, tl->off) != 0) {
+                               TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));;
+                               ret = -1;
+                       }
+                       SAFE_FREE(key.dptr);
+                       goto out;
+               }
+               SAFE_FREE(key.dptr);
+       }
+out:
+       tdb->travlocks.next = tl->next;
+       if (ret < 0)
+               return -1;
+       else
+               return count;
+}
+
+
+/*
+  a write style traverse - temporarily marks the db read only
+*/
+int tdb_traverse_read(struct tdb_context *tdb, 
+                     tdb_traverse_func fn, void *private_data)
+{
+       struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK };
+       int ret;
+       
+       /* we need to get a read lock on the transaction lock here to
+          cope with the lock ordering semantics of solaris10 */
+       if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_RDLCK, F_SETLKW, 0) == -1) {
+               TDB_LOG((tdb, 0, "tdb_traverse_read: failed to get transaction lock\n"));
+               tdb->ecode = TDB_ERR_LOCK;
+               return -1;
+       }
+
+       tdb->traverse_read++;
+       ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
+       tdb->traverse_read--;
+
+       tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0);
+
+       return ret;
+}
+
+/*
+  a write style traverse - needs to get the transaction lock to
+  prevent deadlocks
+*/
+int tdb_traverse(struct tdb_context *tdb, 
+                tdb_traverse_func fn, void *private_data)
+{
+       struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK };
+       int ret;
+
+       if (tdb->read_only || tdb->traverse_read) {
+               return tdb_traverse_read(tdb, fn, private_data);
+       }
+       
+       if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0) == -1) {
+               TDB_LOG((tdb, 0, "tdb_traverse: failed to get transaction lock\n"));
+               tdb->ecode = TDB_ERR_LOCK;
+               return -1;
+       }
+
+       ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
+
+       tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0);
+
+       return ret;
+}
+
+
+/* find the first entry in the database and return its key */
+TDB_DATA tdb_firstkey(struct tdb_context *tdb)
+{
+       TDB_DATA key;
+       struct list_struct rec;
+
+       /* release any old lock */
+       if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0)
+               return tdb_null;
+       tdb->travlocks.off = tdb->travlocks.hash = 0;
+
+       if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0)
+               return tdb_null;
+       /* now read the key */
+       key.dsize = rec.key_len;
+       key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize);
+       if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0)
+               TDB_LOG((tdb, 0, "tdb_firstkey: error occurred while tdb_unlocking!\n"));
+       return key;
+}
+
+/* find the next entry in the database, returning its key */
+TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)
+{
+       u32 oldhash;
+       TDB_DATA key = tdb_null;
+       struct list_struct rec;
+       char *k = NULL;
+
+       /* Is locked key the old key?  If so, traverse will be reliable. */
+       if (tdb->travlocks.off) {
+               if (tdb_lock(tdb,tdb->travlocks.hash,F_WRLCK))
+                       return tdb_null;
+               if (tdb_rec_read(tdb, tdb->travlocks.off, &rec) == -1
+                   || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),
+                                           rec.key_len))
+                   || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) {
+                       /* No, it wasn't: unlock it and start from scratch */
+                       if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) {
+                               SAFE_FREE(k);
+                               return tdb_null;
+                       }
+                       if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) {
+                               SAFE_FREE(k);
+                               return tdb_null;
+                       }
+                       tdb->travlocks.off = 0;
+               }
+
+               SAFE_FREE(k);
+       }
+
+       if (!tdb->travlocks.off) {
+               /* No previous element: do normal find, and lock record */
+               tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), F_WRLCK, &rec);
+               if (!tdb->travlocks.off)
+                       return tdb_null;
+               tdb->travlocks.hash = BUCKET(rec.full_hash);
+               if (tdb_lock_record(tdb, tdb->travlocks.off) != 0) {
+                       TDB_LOG((tdb, 0, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno)));
+                       return tdb_null;
+               }
+       }
+       oldhash = tdb->travlocks.hash;
+
+       /* Grab next record: locks chain and returned record,
+          unlocks old record */
+       if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) {
+               key.dsize = rec.key_len;
+               key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec),
+                                         key.dsize);
+               /* Unlock the chain of this new record */
+               if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0)
+                       TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
+       }
+       /* Unlock the chain of old record */
+       if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0)
+               TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
+       return key;
+}
+
index cc683977e8cdee215f4868601cfa7fc1c93fe1e5..6cecd693f835497d5a857af6edd69d1cb753194b 100644 (file)
@@ -94,7 +94,7 @@ static NTSTATUS cmd_show_data(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int ar
 
 static NTSTATUS cmd_connect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
 {
-       SMB_VFS_CONNECT(vfs->conn, lp_servicename(vfs->conn->service), "vfstest");
+       SMB_VFS_CONNECT(vfs->conn, lp_servicename(SNUM(vfs->conn)), "vfstest");
        return NT_STATUS_OK;
 }
 
@@ -200,9 +200,10 @@ static NTSTATUS cmd_closedir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int arg
 
 static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
 {
-       int flags, fd;
+       int flags;
        mode_t mode;
        const char *flagstr;
+       files_struct *fsp;
 
        mode = 00400;
 
@@ -278,18 +279,21 @@ static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c
                }
        }
 
-       fd = SMB_VFS_OPEN(vfs->conn, argv[1], flags, mode);
-       if (fd == -1) {
+       fsp = SMB_MALLOC_P(struct files_struct);
+       fsp->fsp_name = SMB_STRDUP(argv[1]);
+       fsp->fh = SMB_MALLOC_P(struct fd_handle);
+       fsp->conn = vfs->conn;
+
+       fsp->fh->fd = SMB_VFS_OPEN(vfs->conn, argv[1], fsp, flags, mode);
+       if (fsp->fh->fd == -1) {
                printf("open: error=%d (%s)\n", errno, strerror(errno));
+               SAFE_FREE(fsp->fh);
+               SAFE_FREE(fsp);
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       vfs->files[fd] = SMB_MALLOC_P(struct files_struct);
-       vfs->files[fd]->fsp_name = SMB_STRDUP(argv[1]);
-       vfs->files[fd]->fh = SMB_MALLOC_P(struct fd_handle);
-       vfs->files[fd]->fh->fd = fd;
-       vfs->files[fd]->conn = vfs->conn;
-       printf("open: fd=%d\n", fd);
+       vfs->files[fsp->fh->fd] = fsp;
+       printf("open: fd=%d\n", fsp->fh->fd);
        return NT_STATUS_OK;
 }
 
index b946e48666ebb1019e3d54281bdeb37a9f254183..3559a55a4677295d66ebdf1ddc6243d33e96ad16 100644 (file)
@@ -113,9 +113,13 @@ static struct record preset[] = {
 
 static struct record *recorded;
 
-static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, 
-                     enum brl_type lock_type,
-                     br_off start, br_off size)
+static void print_brl(SMB_DEV_T dev,
+                       SMB_INO_T ino,
+                       struct process_id pid, 
+                       enum brl_type lock_type,
+                       enum brl_flavour lock_flav,
+                       br_off start,
+                       br_off size)
 {
 #if NASTY_POSIX_LOCK_HACK
        {
@@ -178,7 +182,7 @@ static struct cli_state *connect_one(char *share, int snum)
         zero_ip(&ip);
 
        /* have to open a new connection */
-       if (!(c=cli_initialise(NULL)) || !cli_connect(c, server_n, &ip)) {
+       if (!(c=cli_initialise()) || !cli_connect(c, server_n, &ip)) {
                DEBUG(0,("Connection to %s failed\n", server_n));
                return NULL;
        }
index 519acebe8e81413621b1b66a69139aa78ce6d00e..5f2f2499acd3ce8350fe9e7a1a6c344dc88c3c24 100644 (file)
@@ -135,6 +135,7 @@ static BOOL try_unlock(struct cli_state *c, int fstype,
 
 static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, 
                      enum brl_type lock_type,
+                     enum brl_flavour lock_flav,
                      br_off start, br_off size)
 {
        printf("%6d   %05x:%05x    %s  %.0f:%.0f(%.0f)\n", 
index ffc9a20e71cdd3c6ee35bb8e07f8d7578807f6cd..44d26cdc5ad74146ef240d36787a128ef07a8230 100644 (file)
@@ -184,7 +184,7 @@ struct cli_state *connect_one(char *share)
         zero_ip(&ip);
 
        /* have to open a new connection */
-       if (!(c=cli_initialise(NULL)) || !cli_connect(c, server_n, &ip)) {
+       if (!(c=cli_initialise()) || !cli_connect(c, server_n, &ip)) {
                DEBUG(0,("Connection to %s failed\n", server_n));
                return NULL;
        }
index d2b17f0f6352d9f8f69788acda669906a5aeb754..7673f922090103bf9999dd729fb6befc13dc0289 100644 (file)
@@ -62,7 +62,9 @@ static void report_nss_error(const char *who, NSS_STATUS status)
 static struct passwd *nss_getpwent(void)
 {
        NSS_STATUS (*_nss_getpwent_r)(struct passwd *, char *, 
-                                     size_t , int *) = find_fn("getpwent_r");
+                                     size_t , int *) =
+               (NSS_STATUS (*)(struct passwd *, char *,
+                               size_t, int *))find_fn("getpwent_r");
        static struct passwd pwd;
        static char buf[1000];
        NSS_STATUS status;
@@ -84,7 +86,9 @@ static struct passwd *nss_getpwent(void)
 static struct passwd *nss_getpwnam(const char *name)
 {
        NSS_STATUS (*_nss_getpwnam_r)(const char *, struct passwd *, char *, 
-                                     size_t , int *) = find_fn("getpwnam_r");
+                                     size_t , int *) =
+               (NSS_STATUS (*)(const char *, struct passwd *, char *,
+                               size_t, int *))find_fn("getpwnam_r");
        static struct passwd pwd;
        static char buf[1000];
        NSS_STATUS status;
@@ -106,7 +110,9 @@ static struct passwd *nss_getpwnam(const char *name)
 static struct passwd *nss_getpwuid(uid_t uid)
 {
        NSS_STATUS (*_nss_getpwuid_r)(uid_t , struct passwd *, char *, 
-                                     size_t , int *) = find_fn("getpwuid_r");
+                                     size_t , int *) =
+               (NSS_STATUS (*)(uid_t, struct passwd *, char *,
+                               size_t, int *))find_fn("getpwuid_r");
        static struct passwd pwd;
        static char buf[1000];
        NSS_STATUS status;
@@ -127,7 +133,8 @@ static struct passwd *nss_getpwuid(uid_t uid)
 
 static void nss_setpwent(void)
 {
-       NSS_STATUS (*_nss_setpwent)(void) = find_fn("setpwent");
+       NSS_STATUS (*_nss_setpwent)(void) =
+               (NSS_STATUS(*)(void))find_fn("setpwent");
        NSS_STATUS status;
        
        if (!_nss_setpwent)
@@ -141,7 +148,8 @@ static void nss_setpwent(void)
 
 static void nss_endpwent(void)
 {
-       NSS_STATUS (*_nss_endpwent)(void) = find_fn("endpwent");
+       NSS_STATUS (*_nss_endpwent)(void) =
+               (NSS_STATUS (*)(void))find_fn("endpwent");
        NSS_STATUS status;
 
        if (!_nss_endpwent)
@@ -157,7 +165,9 @@ static void nss_endpwent(void)
 static struct group *nss_getgrent(void)
 {
        NSS_STATUS (*_nss_getgrent_r)(struct group *, char *, 
-                                     size_t , int *) = find_fn("getgrent_r");
+                                     size_t , int *) =
+               (NSS_STATUS (*)(struct group *, char *,
+                               size_t, int *))find_fn("getgrent_r");
        static struct group grp;
        static char *buf;
        static int buflen = 1024;
@@ -167,13 +177,13 @@ static struct group *nss_getgrent(void)
                return NULL;
 
        if (!buf) 
-               buf = SMB_MALLOC(buflen);
+               buf = SMB_MALLOC_ARRAY(char, buflen);
 
 again: 
        status = _nss_getgrent_r(&grp, buf, buflen, &nss_errno);
        if (status == NSS_STATUS_TRYAGAIN) {
                buflen *= 2;
-               buf = SMB_REALLOC(buf, buflen);
+               buf = SMB_REALLOC_ARRAY(buf, char, buflen);
                if (!buf) {
                        return NULL;
                }
@@ -192,7 +202,9 @@ again:
 static struct group *nss_getgrnam(const char *name)
 {
        NSS_STATUS (*_nss_getgrnam_r)(const char *, struct group *, char *, 
-                                     size_t , int *) = find_fn("getgrnam_r");
+                                     size_t , int *) =
+               (NSS_STATUS (*)(const char *, struct group *, char *,
+                               size_t, int *))find_fn("getgrnam_r");
        static struct group grp;
        static char *buf;
        static int buflen = 1000;
@@ -202,12 +214,12 @@ static struct group *nss_getgrnam(const char *name)
                return NULL;
 
        if (!buf) 
-               buf = SMB_MALLOC(buflen);
+               buf = SMB_MALLOC_ARRAY(char, buflen);
 again: 
        status = _nss_getgrnam_r(name, &grp, buf, buflen, &nss_errno);
        if (status == NSS_STATUS_TRYAGAIN) {
                buflen *= 2;
-               buf = SMB_REALLOC(buf, buflen);
+               buf = SMB_REALLOC_ARRAY(buf, char, buflen);
                if (!buf) {
                        return NULL;
                }
@@ -226,7 +238,9 @@ again:
 static struct group *nss_getgrgid(gid_t gid)
 {
        NSS_STATUS (*_nss_getgrgid_r)(gid_t , struct group *, char *, 
-                                     size_t , int *) = find_fn("getgrgid_r");
+                                     size_t , int *) =
+               (NSS_STATUS (*)(gid_t, struct group *, char *,
+                               size_t, int *))find_fn("getgrgid_r");
        static struct group grp;
        static char *buf;
        static int buflen = 1000;
@@ -236,13 +250,13 @@ static struct group *nss_getgrgid(gid_t gid)
                return NULL;
 
        if (!buf) 
-               buf = SMB_MALLOC(buflen);
+               buf = SMB_MALLOC_ARRAY(char, buflen);
 
 again: 
        status = _nss_getgrgid_r(gid, &grp, buf, buflen, &nss_errno);
        if (status == NSS_STATUS_TRYAGAIN) {
                buflen *= 2;
-               buf = SMB_REALLOC(buf, buflen);
+               buf = SMB_REALLOC_ARRAY(buf, char, buflen);
                if (!buf) {
                        return NULL;
                }
@@ -260,7 +274,8 @@ again:
 
 static void nss_setgrent(void)
 {
-       NSS_STATUS (*_nss_setgrent)(void) = find_fn("setgrent");
+       NSS_STATUS (*_nss_setgrent)(void) =
+               (NSS_STATUS (*)(void))find_fn("setgrent");
        NSS_STATUS status;
 
        if (!_nss_setgrent)
@@ -274,7 +289,8 @@ static void nss_setgrent(void)
 
 static void nss_endgrent(void)
 {
-       NSS_STATUS (*_nss_endgrent)(void) = find_fn("endgrent");
+       NSS_STATUS (*_nss_endgrent)(void) =
+               (NSS_STATUS (*)(void))find_fn("endgrent");
        NSS_STATUS status;
 
        if (!_nss_endgrent)
@@ -290,7 +306,9 @@ static int nss_initgroups(char *user, gid_t group, gid_t **groups, long int *sta
 {
        NSS_STATUS (*_nss_initgroups)(char *, gid_t , long int *,
                                      long int *, gid_t **, long int , int *) = 
-               find_fn("initgroups_dyn");
+               (NSS_STATUS (*)(char *, gid_t, long int *,
+                               long int *, gid_t **,
+                               long int, int *))find_fn("initgroups_dyn");
        NSS_STATUS status;
 
        if (!_nss_initgroups) 
diff --git a/source/torture/pdbtest.c b/source/torture/pdbtest.c
new file mode 100644 (file)
index 0000000..e1a35b7
--- /dev/null
@@ -0,0 +1,392 @@
+/* 
+   Unix SMB/CIFS implementation.
+   passdb testing utility
+   
+   Copyright (C) Wilco Baan Hofman 2006
+   Copyright (C) Jelmer Vernooij 2006
+
+   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"
+
+static BOOL samu_correct(struct samu *s1, struct samu *s2)
+{
+       BOOL ret = True;
+       uint32 s1_len, s2_len;
+       const char *s1_buf, *s2_buf;
+       const uint8 *d1_buf, *d2_buf;
+               
+       /* Check Unix username */
+       s1_buf = pdb_get_username(s1);
+       s2_buf = pdb_get_username(s2);
+       if (s2_buf == NULL && s1_buf != NULL) {
+               DEBUG(0, ("Username is not set\n"));
+               ret = False;
+       } else if (s1_buf == NULL) {
+               /* Do nothing */
+       } else if (strcmp(s1_buf,s2_buf)) {
+               DEBUG(0, ("Username not written correctly, want %s, got \"%s\"\n",
+                                       pdb_get_username(s1),
+                                       pdb_get_username(s2)));
+               ret = False;
+       }
+
+       /* Check NT username */
+       s1_buf = pdb_get_nt_username(s1);
+       s2_buf = pdb_get_nt_username(s2);
+       if (s2_buf == NULL && s1_buf != NULL) {
+               DEBUG(0, ("NT Username is not set\n"));
+               ret = False;
+       } else if (s1_buf == NULL) {
+               /* Do nothing */
+       } else if (strcmp(s1_buf, s2_buf)) {
+               DEBUG(0, ("NT Username not written correctly, want \"%s\", got \"%s\"\n",
+                                       pdb_get_nt_username(s1),
+                                       pdb_get_nt_username(s2)));
+               ret = False;
+       }
+
+       /* Check acct ctrl */
+       if (pdb_get_acct_ctrl(s1) != pdb_get_acct_ctrl(s2)) {
+               DEBUG(0, ("Acct ctrl field not written correctly, want %d (0x%X), got %d (0x%X)\n",
+                                       pdb_get_acct_ctrl(s1),
+                                       pdb_get_acct_ctrl(s1),
+                                       pdb_get_acct_ctrl(s2),
+                                       pdb_get_acct_ctrl(s2)));
+               ret = False;
+       }
+
+       /* Check NT password */
+       d1_buf = pdb_get_nt_passwd(s1);
+       d2_buf = pdb_get_nt_passwd(s2);
+       if (d2_buf == NULL && d1_buf != NULL) {
+               DEBUG(0, ("NT password is not set\n"));
+               ret = False;
+       } else if (d1_buf == NULL) {
+               /* Do nothing */
+       } else if (memcmp(d1_buf, d2_buf, NT_HASH_LEN)) {
+               DEBUG(0, ("NT password not written correctly\n"));
+               ret = False;
+       }
+
+       /* Check lanman password */
+       d1_buf = pdb_get_lanman_passwd(s1);
+       d2_buf = pdb_get_lanman_passwd(s2);
+       if (d2_buf == NULL && d1_buf != NULL) {
+               DEBUG(0, ("Lanman password is not set\n"));
+       } else if (d1_buf == NULL) {
+               /* Do nothing */
+       } else if (memcmp(d1_buf, d2_buf, NT_HASH_LEN)) {
+               DEBUG(0, ("Lanman password not written correctly\n"));
+               ret = False;
+       }
+
+       /* Check password history */
+       d1_buf = pdb_get_pw_history(s1, &s1_len);
+       d2_buf = pdb_get_pw_history(s2, &s2_len);
+       if (d2_buf == NULL && d1_buf != NULL) {
+               DEBUG(0, ("Password history is not set\n"));
+       } else if (d1_buf == NULL) {
+               /* Do nothing */
+       } else if (s1_len != s1_len) {
+               DEBUG(0, ("Password history not written correctly, lengths differ, want %d, got %d\n",
+                                       s1_len, s2_len));
+               ret = False;
+       } else if (strncmp(s1_buf, s2_buf, s1_len)) {
+               DEBUG(0, ("Password history not written correctly\n"));
+               ret = False;
+       }
+
+       /* Check logon time */
+       if (pdb_get_logon_time(s1) != pdb_get_logon_time(s2)) {
+               DEBUG(0, ("Logon time is not written correctly\n"));
+               ret = False;
+       }
+
+       /* Check logoff time */
+       if (pdb_get_logoff_time(s1) != pdb_get_logoff_time(s2)) {
+               DEBUG(0, ("Logoff time is not written correctly\n"));
+               ret = False;
+       }
+       
+       /* Check kickoff time */
+       if (pdb_get_kickoff_time(s1) != pdb_get_logoff_time(s2)) {
+               DEBUG(0, ("Kickoff time is not written correctly\n"));
+               ret = False;
+       }
+       
+       /* Check bad password time */
+       if (pdb_get_bad_password_time(s1) != pdb_get_bad_password_time(s2)) {
+               DEBUG(0, ("Bad password time is not written correctly\n"));
+               ret = False;
+       }
+       
+       /* Check password last set time */
+       if (pdb_get_pass_last_set_time(s1) != pdb_get_pass_last_set_time(s2)) {
+               DEBUG(0, ("Password last set time is not written correctly\n"));
+               ret = False;
+       }
+       
+       /* Check password can change time */
+       if (pdb_get_pass_can_change_time(s1) != pdb_get_pass_can_change_time(s2)) {
+               DEBUG(0, ("Password can change time is not written correctly\n"));
+               ret = False;
+       }
+       
+       /* Check password must change time */
+       if (pdb_get_pass_must_change_time(s1) != pdb_get_pass_must_change_time(s2)) {
+               DEBUG(0, ("Password must change time is not written correctly\n"));
+               ret = False;
+       }
+       
+       /* Check logon divs */
+       if (pdb_get_logon_divs(s1) != pdb_get_logon_divs(s2)) {
+               DEBUG(0, ("Logon divs not written correctly\n"));
+               ret = False;
+       }
+       
+       /* Check logon hours */
+       if (pdb_get_hours_len(s1) != pdb_get_hours_len(s2)) {
+               DEBUG(0, ("Logon hours length not written correctly\n"));
+               ret = False;
+       } else if (pdb_get_hours_len(s1) != 0) {
+               d1_buf = pdb_get_hours(s1);
+               d2_buf = pdb_get_hours(s2);
+               if (d2_buf == NULL && d2_buf != NULL) {
+                       DEBUG(0, ("Logon hours is not set\n"));
+                       ret = False;
+               } else if (d1_buf == NULL) {
+                       /* Do nothing */
+               } else if (memcmp(d1_buf, d2_buf, MAX_HOURS_LEN)) {
+                       DEBUG(0, ("Logon hours is not written correctly\n"));
+                       ret = False;
+               }
+       }
+       
+       /* Check profile path */
+       s1_buf = pdb_get_profile_path(s1);
+       s2_buf = pdb_get_profile_path(s2);
+       if (s2_buf == NULL && s1_buf != NULL) {
+               DEBUG(0, ("Profile path is not set\n"));
+               ret = False;
+       } else if (s1_buf == NULL) {
+               /* Do nothing */
+       } else if (strcmp(s1_buf, s2_buf)) {
+               DEBUG(0, ("Profile path is not written correctly\n"));
+               ret = False;
+       }
+
+       /* Check home dir */
+       s1_buf = pdb_get_homedir(s1);
+       s2_buf = pdb_get_homedir(s2);
+       if (s2_buf == NULL && s1_buf != NULL) {
+               DEBUG(0, ("Home dir is not set\n"));
+               ret = False;
+       } else if (s1_buf == NULL) {
+               /* Do nothing */
+       } else if (strcmp(s1_buf, s2_buf)) {
+               DEBUG(0, ("Home dir is not written correctly\n"));
+               ret = False;
+       }
+       
+       /* Check logon script */
+       s1_buf = pdb_get_logon_script(s1);
+       s2_buf = pdb_get_logon_script(s2);
+       if (s2_buf == NULL && s1_buf != NULL) {
+               DEBUG(0, ("Logon script not set\n"));
+               ret = False;
+       } else if (s1_buf == NULL) {
+               /* Do nothing */
+       } else if (strcmp(s1_buf, s2_buf)) {
+               DEBUG(0, ("Logon script is not written correctly\n"));
+               ret = False;
+       }
+       
+       /* TODO Check user and group sids */
+               
+       return ret;     
+}
+
+
+int main(int argc, char **argv)
+{
+       TALLOC_CTX *ctx;
+       struct samu *out = NULL;
+       struct samu *in = NULL;
+       NTSTATUS rv;
+       int i;
+       struct timeval tv;
+       BOOL error = False;
+       struct passwd *pwd;
+       uint8 *buf;
+       uint32 expire, min_age, history;
+       struct pdb_methods *pdb;
+       poptContext pc;
+       static char *backend = NULL;
+       static const char *unix_user = "nobody";
+       struct poptOption long_options[] = {
+               {"username", 'u', POPT_ARG_STRING, &unix_user, 0, "Unix user to use for testing", "USERNAME" },
+               {"backend", 'b', POPT_ARG_STRING, &backend, 0, "Backend to use if not default", "BACKEND[:SETTINGS]" },
+               POPT_AUTOHELP
+               POPT_COMMON_SAMBA
+               POPT_TABLEEND
+       };
+
+       load_case_tables();
+
+       pc = poptGetContext("vfstest", argc, (const char **) argv,
+                           long_options, 0);
+
+       poptSetOtherOptionHelp(pc, "backend[:settings] username");
+       
+       while(poptGetNextOpt(pc) != -1);
+
+       poptFreeContext(pc);
+
+       /* Load configuration */
+       lp_load(dyn_CONFIGFILE, False, False, True, True);
+       setup_logging("pdbtest", True);
+
+       if (backend == NULL) {
+               backend = lp_passdb_backend();
+       }
+
+       rv = make_pdb_method_name(&pdb, backend);
+       if (NT_STATUS_IS_ERR(rv)) {
+               fprintf(stderr, "Error initializing '%s': %s\n", backend, get_friendly_nt_error_msg(rv));
+               exit(1);
+       }
+       
+       ctx = talloc_init("PDBTEST");
+       
+       if (!(out = samu_new(ctx))) {
+               fprintf(stderr, "Can't create samu structure.\n");
+               exit(1);
+       }
+       
+       if ((pwd = getpwnam_alloc(ctx, unix_user)) == NULL) {
+               fprintf(stderr, "Error getting user information for %s\n", unix_user);
+               exit(1);
+       }
+       
+       samu_set_unix(out, pwd);
+
+       pdb_set_profile_path(out, "\\\\torture\\profile", PDB_SET);
+       pdb_set_homedir(out, "\\\\torture\\home", PDB_SET);
+       pdb_set_logon_script(out, "torture_script.cmd", PDB_SET);
+
+       pdb_get_account_policy(AP_PASSWORD_HISTORY, &history);
+       if (history * PW_HISTORY_ENTRY_LEN < NT_HASH_LEN) {
+               buf = TALLOC(ctx, NT_HASH_LEN);
+       } else {
+               buf = TALLOC(ctx, history * PW_HISTORY_ENTRY_LEN);
+       }
+
+       /* Generate some random hashes */
+       GetTimeOfDay(&tv);
+       srand(tv.tv_usec);
+       for (i = 0; i < NT_HASH_LEN; i++) {
+               buf[i] = (uint8) rand();
+       }
+       pdb_set_nt_passwd(out, buf, PDB_SET);
+       for (i = 0; i < LM_HASH_LEN; i++) {
+               buf[i] = (uint8) rand();
+       }
+       pdb_set_lanman_passwd(out, buf, PDB_SET);
+       for (i = 0; i < history * PW_HISTORY_ENTRY_LEN; i++) {
+               buf[i] = (uint8) rand();
+       }
+       pdb_set_pw_history(out, buf, history, PDB_SET);
+
+       pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire);
+       pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age);
+       pdb_set_pass_last_set_time(out, time(NULL), PDB_SET);
+       
+       if (expire == 0 || expire == (uint32)-1) {
+               pdb_set_pass_must_change_time(out, get_time_t_max(), PDB_SET);
+       } else {
+               pdb_set_pass_must_change_time(out, time(NULL)+expire, PDB_SET);
+       }
+
+       if (min_age == (uint32)-1) {
+               pdb_set_pass_can_change_time(out, 0, PDB_SET);
+       } else {
+               pdb_set_pass_can_change_time(out, time(NULL)+min_age, PDB_SET);
+       }
+       
+       /* Create account */
+       if (!NT_STATUS_IS_OK(rv = pdb->add_sam_account(pdb, out))) {
+               fprintf(stderr, "Error in add_sam_account: %s\n", 
+                               get_friendly_nt_error_msg(rv));
+               exit(1);
+       }
+
+       if (!(in = samu_new(ctx))) {
+               fprintf(stderr, "Can't create samu structure.\n");
+               exit(1);
+       }
+       
+       /* Get account information through getsampwnam() */
+       if (NT_STATUS_IS_ERR(pdb->getsampwnam(pdb, in, out->username))) {
+               fprintf(stderr, "Error getting sampw of added user %s.\n",
+                               out->username);
+               if (!NT_STATUS_IS_OK(rv = pdb->delete_sam_account(pdb, out))) {
+                       fprintf(stderr, "Error in delete_sam_account %s\n", 
+                                       get_friendly_nt_error_msg(rv));
+               }
+               TALLOC_FREE(ctx);
+       }
+       
+       /* Verify integrity */
+       if (samu_correct(out, in)) {
+               printf("User info written correctly\n");
+       } else {
+               printf("User info NOT written correctly\n");
+               error = True;
+       }
+       
+       /* Delete account */
+       if (!NT_STATUS_IS_OK(rv = pdb->delete_sam_account(pdb, out))) {
+               fprintf(stderr, "Error in delete_sam_account %s\n", 
+                                       get_friendly_nt_error_msg(rv));
+       }
+
+       pdb->setsampwent(pdb, False, 0);
+       while (NT_STATUS_IS_OK(pdb->getsampwent(pdb, out))) {
+               if (pdb_get_username(out) == NULL) {
+                       fprintf(stderr, "Got bad username through getsampwent()\n");
+                       error = True;
+                       break;
+               }
+               if (NT_STATUS_IS_ERR(pdb->getsampwnam(pdb, in, pdb_get_username(out)))) {
+                       fprintf(stderr, "Error getting samu through getsampwnam() of an account we got through getsampwent!\n");
+                       error = True;
+                       continue;
+               }
+               if (!samu_correct(out, in)) {
+                       printf("Record gotten through getsampwnam() differs from same record through getsampwent()\n");
+               }
+       }
+       pdb->endsampwent(pdb);
+       
+       TALLOC_FREE(ctx);
+
+       if (error) {
+               return 1;
+       }
+       return 0;
+}
index d69cc8eb8df9abe387d2cd8ccb60e102a75cba7d..98f2dc105faa393c8481c8bc87801ce82b3d3526 100644 (file)
@@ -493,7 +493,7 @@ enum client_action
        strupper_m(global_myname);
        fstrcpy(cli_info.myhostname, global_myname);
 
-       DEBUG(3,("%s client started (version %s)\n",timestring(False),SAMBA_VERSION_STRING));
+       DEBUG(3,("%s client started (version %s)\n",current_timestring(False),SAMBA_VERSION_STRING));
 
        if (*smb_cli->domain == 0)
        {
index 1893be83699ca69b3c2b79ead8a9e0600403c9ae..1510cd70f4cd1a58fb57dc0d35e76dcef167a459 100644 (file)
@@ -49,7 +49,7 @@ static NTSTATUS try_trans2(struct cli_state *cli,
                         int op,
                         char *param, char *data,
                         int param_len, int data_len,
-                        int *rparam_len, int *rdata_len)
+                        unsigned int *rparam_len, unsigned int *rdata_len)
 {
        uint16 setup = op;
        char *rparam=NULL, *rdata=NULL;
@@ -80,7 +80,7 @@ static NTSTATUS try_trans2_len(struct cli_state *cli,
                             int op, int level,
                             char *param, char *data,
                             int param_len, int *data_len,
-                            int *rparam_len, int *rdata_len)
+                            unsigned int *rparam_len, unsigned int *rdata_len)
 {
        NTSTATUS ret=NT_STATUS_OK;
 
@@ -115,7 +115,7 @@ static BOOL scan_trans2(struct cli_state *cli, int op, int level,
 {
        int data_len = 0;
        int param_len = 0;
-       int rparam_len, rdata_len;
+       unsigned int rparam_len, rdata_len;
        pstring param, data;
        NTSTATUS status;
 
@@ -253,7 +253,7 @@ static NTSTATUS try_nttrans(struct cli_state *cli,
                         int op,
                         char *param, char *data,
                         int param_len, int data_len,
-                        int *rparam_len, int *rdata_len)
+                        unsigned int *rparam_len, unsigned int *rdata_len)
 {
        char *rparam=NULL, *rdata=NULL;
 
@@ -282,7 +282,7 @@ static NTSTATUS try_nttrans_len(struct cli_state *cli,
                             int op, int level,
                             char *param, char *data,
                             int param_len, int *data_len,
-                            int *rparam_len, int *rdata_len)
+                            unsigned int *rparam_len, unsigned int *rdata_len)
 {
        NTSTATUS ret=NT_STATUS_OK;
 
@@ -317,7 +317,7 @@ static BOOL scan_nttrans(struct cli_state *cli, int op, int level,
 {
        int data_len = 0;
        int param_len = 0;
-       int rparam_len, rdata_len;
+       unsigned int rparam_len, rdata_len;
        pstring param, data;
        NTSTATUS status;
 
index 0b3bfc18f4af76957f5d9458001a27b20fa426c5..25e249ed2e175c19a58304585b4e4cb04a166f85 100644 (file)
@@ -94,28 +94,27 @@ void *shm_setup(int size)
 }
 
 
-static BOOL open_nbt_connection(struct cli_state *c)
+static struct cli_state *open_nbt_connection(void)
 {
        struct nmb_name called, calling;
        struct in_addr ip;
-
-       ZERO_STRUCTP(c);
+       struct cli_state *c;
 
        make_nmb_name(&calling, myname, 0x0);
        make_nmb_name(&called , host, 0x20);
 
         zero_ip(&ip);
 
-       if (!cli_initialise(c)) {
+       if (!(c = cli_initialise())) {
                printf("Failed initialize cli_struct to connect with %s\n", host);
-               return False;
+               return NULL;
        }
 
        c->port = port_to_use;
 
        if (!cli_connect(c, host, &ip)) {
                printf("Failed to connect with %s\n", host);
-               return False;
+               return NULL;
        }
 
        c->use_kerberos = use_kerberos;
@@ -131,7 +130,7 @@ static BOOL open_nbt_connection(struct cli_state *c)
                 */
                if (!cli_connect(c, host, &ip)) {
                        printf("Failed to connect with %s\n", host);
-                       return False;
+                       return NULL;
                }
 
                make_nmb_name(&called, "*SMBSERVER", 0x20);
@@ -140,11 +139,11 @@ static BOOL open_nbt_connection(struct cli_state *c)
                        printf("We tried with a called name of %s & %s\n",
                                host, "*SMBSERVER");
                        cli_shutdown(c);
-                       return False;
+                       return NULL;
                }
        }
 
-       return True;
+       return c;
 }
 
 BOOL torture_open_connection(struct cli_state **c)
@@ -462,8 +461,8 @@ static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2)
        int fnum1;
        int fnum2;
        int i;
-       uchar buf[131072];
-       uchar buf_rd[131072];
+       char buf[131072];
+       char buf_rd[131072];
        BOOL correct = True;
        ssize_t bytes_read;
 
@@ -494,7 +493,7 @@ static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2)
                        printf("%d\r", i); fflush(stdout);
                }
 
-               generate_random_buffer(buf, buf_size);
+               generate_random_buffer((unsigned char *)buf, buf_size);
 
                if (cli_write(c1, fnum1, 0, buf, 0, buf_size) != buf_size) {
                        printf("write failed (%s)\n", cli_errstr(c1));
@@ -2174,20 +2173,20 @@ static void rand_buf(char *buf, int len)
 static BOOL run_negprot_nowait(int dummy)
 {
        int i;
-       static struct cli_state cli;
+       static struct cli_state *cli;
        BOOL correct = True;
 
        printf("starting negprot nowait test\n");
 
-       if (!open_nbt_connection(&cli)) {
+       if (!(cli = open_nbt_connection())) {
                return False;
        }
 
        for (i=0;i<50000;i++) {
-               cli_negprot_send(&cli);
+               cli_negprot_send(cli);
        }
 
-       if (!torture_close_connection(&cli)) {
+       if (!torture_close_connection(cli)) {
                correct = False;
        }
 
@@ -2202,7 +2201,7 @@ static BOOL run_randomipc(int dummy)
 {
        char *rparam = NULL;
        char *rdata = NULL;
-       int rdrcnt,rprcnt;
+       unsigned int rdrcnt,rprcnt;
        pstring param;
        int api, param_len, i;
        struct cli_state *cli;
@@ -4418,7 +4417,8 @@ static BOOL run_eatest(int dummy)
 
        for (i = 0; i < num_eas; i++) {
                printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
-               dump_data(0, ea_list[i].value.data, ea_list[i].value.length);
+               dump_data(0, (char *)ea_list[i].value.data,
+                         ea_list[i].value.length);
        }
 
        /* Setting EA's to zero length deletes them. Test this */
@@ -4445,7 +4445,8 @@ static BOOL run_eatest(int dummy)
        printf("num_eas = %d\n", num_eas);
        for (i = 0; i < num_eas; i++) {
                printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
-               dump_data(0, ea_list[i].value.data, ea_list[i].value.length);
+               dump_data(0, (char *)ea_list[i].value.data,
+                         ea_list[i].value.length);
        }
 
        if (num_eas != 0) {
@@ -4550,8 +4551,8 @@ static BOOL run_dirtest1(int dummy)
 
 static BOOL run_error_map_extract(int dummy) {
        
-       static struct cli_state c_dos;
-       static struct cli_state c_nt;
+       static struct cli_state *c_dos;
+       static struct cli_state *c_nt;
 
        uint32 error;
 
@@ -4564,81 +4565,81 @@ static BOOL run_error_map_extract(int dummy) {
 
        /* NT-Error connection */
 
-       if (!open_nbt_connection(&c_nt)) {
+       if (!(c_nt = open_nbt_connection())) {
                return False;
        }
 
-       c_nt.use_spnego = False;
+       c_nt->use_spnego = False;
 
-       if (!cli_negprot(&c_nt)) {
-               printf("%s rejected the NT-error negprot (%s)\n",host, cli_errstr(&c_nt));
-               cli_shutdown(&c_nt);
+       if (!cli_negprot(c_nt)) {
+               printf("%s rejected the NT-error negprot (%s)\n",host, cli_errstr(c_nt));
+               cli_shutdown(c_nt);
                return False;
        }
 
-       if (!cli_session_setup(&c_nt, "", "", 0, "", 0,
+       if (!cli_session_setup(c_nt, "", "", 0, "", 0,
                               workgroup)) {
-               printf("%s rejected the NT-error initial session setup (%s)\n",host, cli_errstr(&c_nt));
+               printf("%s rejected the NT-error initial session setup (%s)\n",host, cli_errstr(c_nt));
                return False;
        }
 
        /* DOS-Error connection */
 
-       if (!open_nbt_connection(&c_dos)) {
+       if (!(c_dos = open_nbt_connection())) {
                return False;
        }
 
-       c_dos.use_spnego = False;
-       c_dos.force_dos_errors = True;
+       c_dos->use_spnego = False;
+       c_dos->force_dos_errors = True;
 
-       if (!cli_negprot(&c_dos)) {
-               printf("%s rejected the DOS-error negprot (%s)\n",host, cli_errstr(&c_dos));
-               cli_shutdown(&c_dos);
+       if (!cli_negprot(c_dos)) {
+               printf("%s rejected the DOS-error negprot (%s)\n",host, cli_errstr(c_dos));
+               cli_shutdown(c_dos);
                return False;
        }
 
-       if (!cli_session_setup(&c_dos, "", "", 0, "", 0,
+       if (!cli_session_setup(c_dos, "", "", 0, "", 0,
                               workgroup)) {
-               printf("%s rejected the DOS-error initial session setup (%s)\n",host, cli_errstr(&c_dos));
+               printf("%s rejected the DOS-error initial session setup (%s)\n",host, cli_errstr(c_dos));
                return False;
        }
 
        for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
                fstr_sprintf(user, "%X", error);
 
-               if (cli_session_setup(&c_nt, user, 
+               if (cli_session_setup(c_nt, user, 
                                       password, strlen(password),
                                       password, strlen(password),
                                      workgroup)) {
                        printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
                }
                
-               flgs2 = SVAL(c_nt.inbuf,smb_flg2);
+               flgs2 = SVAL(c_nt->inbuf,smb_flg2);
                
                /* Case #1: 32-bit NT errors */
                if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
-                       nt_status = NT_STATUS(IVAL(c_nt.inbuf,smb_rcls));
+                       nt_status = NT_STATUS(IVAL(c_nt->inbuf,smb_rcls));
                } else {
                        printf("/** Dos error on NT connection! (%s) */\n", 
-                              cli_errstr(&c_nt));
+                              cli_errstr(c_nt));
                        nt_status = NT_STATUS(0xc0000000);
                }
 
-               if (cli_session_setup(&c_dos, user, 
+               if (cli_session_setup(c_dos, user, 
                                       password, strlen(password),
                                       password, strlen(password),
                                       workgroup)) {
                        printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
                }
-               flgs2 = SVAL(c_dos.inbuf,smb_flg2), errnum;
+               flgs2 = SVAL(c_dos->inbuf,smb_flg2), errnum;
                
                /* Case #1: 32-bit NT errors */
                if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
                        printf("/** NT error on DOS connection! (%s) */\n", 
-                              cli_errstr(&c_nt));
+                              cli_errstr(c_nt));
                        errnum = errclass = 0;
                } else {
-                       cli_dos_error(&c_dos, &errclass, &errnum);
+                       cli_dos_error(c_dos, &errclass, &errnum);
                }
 
                if (NT_STATUS_V(nt_status) != error) { 
@@ -4655,6 +4656,42 @@ static BOOL run_error_map_extract(int dummy) {
        return True;
 }
 
+static BOOL run_local_substitute(int dummy)
+{
+       TALLOC_CTX *mem_ctx;
+       int diff = 0;
+
+       if ((mem_ctx = talloc_init("run_local_subst")) == NULL) {
+               printf("talloc_init failed\n");
+               return False;
+       }
+
+       diff |= strcmp(talloc_sub_specified(mem_ctx, "%U", "bla", "", -1, -1),
+                      "bla");
+       diff |= strcmp(talloc_sub_specified(mem_ctx, "%u%U", "bla", "", -1, -1),
+                      "blabla");
+       diff |= strcmp(talloc_sub_specified(mem_ctx, "%g", "", "", -1, -1),
+                      "NO_GROUP");
+       diff |= strcmp(talloc_sub_specified(mem_ctx, "%G", "", "", -1, -1),
+                      "NO_GROUP");
+       diff |= strcmp(talloc_sub_specified(mem_ctx, "%g", "", "", -1, 0),
+                      gidtoname(0));
+       diff |= strcmp(talloc_sub_specified(mem_ctx, "%G", "", "", -1, 0),
+                      gidtoname(0));
+       diff |= strcmp(talloc_sub_specified(mem_ctx, "%D%u", "u", "dom", -1, 0),
+                      "domu");
+       diff |= strcmp(talloc_sub_specified(mem_ctx, "%i %I", "", "", -1, -1),
+                      "0.0.0.0 0.0.0.0");
+
+       /* Different captialization rules in sub_basic... */
+
+       diff |= strcmp(talloc_sub_basic(mem_ctx, "BLA", "dom", "%U%D"),
+                      "blaDOM");
+
+       TALLOC_FREE(mem_ctx);
+       return (diff == 0);
+}
+
 static double create_procs(BOOL (*fn)(int), BOOL *result)
 {
        int i, status;
@@ -4805,6 +4842,7 @@ static struct {
        {"CHKPATH",  torture_chkpath_test, 0},
        {"FDSESS", run_fdsesstest, 0},
        { "EATEST", run_eatest, 0},
+       { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
        {NULL, NULL, 0}};
 
 
index 61bb4b0bf654abbc4ebf26ee44d7a3fdadf945db..fa0545988e9eb3064844db8e16e5ec333f0eac3c 100644 (file)
@@ -575,6 +575,6 @@ int main(int argc, char *argv[])
                        process_cmd(&vfs, line);
        }
        
-       free(vfs.conn);
+       conn_free(vfs.conn);
        return 0;
 }
index bec4d81ae2bfa6194c392c7a661876b7515cb16f..6d1b2b253529a731bd8945bf79c8277c0d52f7cc 100644 (file)
@@ -145,6 +145,8 @@ static void newblock( dbg_Token old, dbg_Token newtok )
     case dbg_lineno:
       (void)printf( ")" );
       break;
+    default:
+      break;
     }
 
   switch( newtok )
@@ -158,6 +160,8 @@ static void newblock( dbg_Token old, dbg_Token newtok )
     case dbg_lineno:
       (void)printf( "(" );
       break;
+    default:
+      break;
     }
   } /* newblock */
 
index bef2a0a83c2a8fe4637cb7771cc7593051bcc7f4..8b4fb042fcf73d928261ee4c8887251d1eb12d25 100644 (file)
@@ -77,6 +77,7 @@ const char *opt_target_workgroup = NULL;
 int opt_machine_pass = 0;
 BOOL opt_localgroup = False;
 BOOL opt_domaingroup = False;
+static BOOL do_talloc_report=False;
 const char *opt_newntname = "";
 int opt_rid = 0;
 int opt_acls = 0;
@@ -513,7 +514,7 @@ static int net_changesecretpw(int argc, const char **argv)
                        set_line_buffering(stdout);
                        set_line_buffering(stderr);
                }
-               
+
                trust_pw = get_pass("Enter machine password: ", opt_stdin);
 
                if (!secrets_store_machine_password(trust_pw, lp_workgroup(), sec_channel_type)) {
@@ -884,6 +885,7 @@ static struct functable net_func[] = {
                {"timestamps",  0, POPT_ARG_NONE,     &opt_timestamps},
                {"exclude",     'e', POPT_ARG_STRING, &opt_exclude},
                {"destination", 0, POPT_ARG_STRING,   &opt_destination},
+               {"tallocreport", 0, POPT_ARG_NONE, &do_talloc_report},
 
                POPT_COMMON_SAMBA
                { 0, 0, 0, 0}
@@ -947,6 +949,10 @@ static struct functable net_func[] = {
                }
        }
 
+       if (do_talloc_report) {
+               talloc_enable_leak_report();
+       }
+
        if (opt_requester_name) {
                set_global_myname(opt_requester_name);
        }
index 9d122a466bbe7adb320219b44a62141c6fe96ace..bfbc80759aa9ae0f495c63c66a625f1f8046ff0c 100644 (file)
@@ -506,7 +506,8 @@ static int ads_user_info(int argc, const char **argv)
                return -1;
        }
        
-       grouplist = ldap_get_values(ads->ld, res, "memberOf");
+       grouplist = ldap_get_values((LDAP *)ads->ld,
+                                   (LDAPMessage *)res, "memberOf");
 
        if (grouplist) {
                int i;
@@ -591,7 +592,7 @@ int net_ads_user(int argc, const char **argv)
                                          shortattrs, usergrp_display, 
                                          disp_fields);
                ads_destroy(&ads);
-               return 0;
+               return ADS_ERR_OK(rc) ? 0 : -1;
        }
 
        return net_run_function(argc, argv, func, net_ads_user_usage);
@@ -716,7 +717,7 @@ int net_ads_group(int argc, const char **argv)
                                          disp_fields);
 
                ads_destroy(&ads);
-               return 0;
+               return ADS_ERR_OK(rc) ? 0 : -1;
        }
        return net_run_function(argc, argv, func, net_ads_group_usage);
 }
@@ -1011,7 +1012,7 @@ static ADS_STATUS net_precreate_machine_acct( ADS_STRUCT *ads, const char *ou )
        asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
        free(ou_str);
 
-       rc = ads_search_dn(ads, (void**)&res, dn, NULL);
+       rc = ads_search_dn(ads, &res, dn, NULL);
        ads_msgfree(ads, res);
 
        if (ADS_ERR_OK(rc)) {
@@ -1340,7 +1341,7 @@ static int net_ads_printer_publish(int argc, const char **argv)
                return -1;
        }
 
-       srv_dn = ldap_get_dn(ads->ld, res);
+       srv_dn = ldap_get_dn((LDAP *)ads->ld, (LDAPMessage *)res);
        srv_cn = ldap_explode_dn(srv_dn, 1);
 
        asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn);
index 47e1f93b69f20cad4813c1db1e49d7d8ac036a3a..87da952247ae839ce044045f9e36d5da5b93a335 100644 (file)
@@ -185,6 +185,7 @@ static NTSTATUS net_idmap_fixup_hwm(void)
 /***********************************************************
  Write entries from stdin to current local idmap
  **********************************************************/
+
 static int net_idmap_restore(int argc, const char **argv)
 {
        if (!idmap_init(lp_idmap_backend())) {
@@ -193,10 +194,11 @@ static int net_idmap_restore(int argc, const char **argv)
        }
 
        while (!feof(stdin)) {
-               fstring line, sid_string, fmt_string;
+               fstring line, sid_string, fmt_string1, fmt_string2;
                int len;
                unid_t id;
-               int type = ID_EMPTY;
+               enum idmap_type type;
+               unsigned long idval;
                DOM_SID sid;
 
                if (fgets(line, sizeof(line)-1, stdin) == NULL)
@@ -207,20 +209,16 @@ static int net_idmap_restore(int argc, const char **argv)
                if ( (len > 0) && (line[len-1] == '\n') )
                        line[len-1] = '\0';
 
-               /* Yuck - this is broken for sizeof(gid_t) != sizeof(int) */
-               snprintf(fmt_string, sizeof(fmt_string), "GID %%d %%%us", FSTRING_LEN);
-               if (sscanf(line, fmt_string, &id.gid, sid_string) == 2) {
-                       type = ID_GROUPID;
-               }
-
-               /* Yuck - this is broken for sizeof(uid_t) != sizeof(int) */
+               snprintf(fmt_string1, sizeof(fmt_string1), "GID %%ul %%%us", FSTRING_LEN);
+               snprintf(fmt_string2, sizeof(fmt_string2), "UID %%ul %%%us", FSTRING_LEN);
 
-               snprintf(fmt_string, sizeof(fmt_string), "UID %%d %%%us", FSTRING_LEN);
-               if (sscanf(line, fmt_string, &id.uid, sid_string) == 2) {
+               if (sscanf(line, fmt_string1, &idval, sid_string) == 2) {
+                       type = ID_GROUPID;
+                       id.gid = (gid_t)idval;
+               } else if (sscanf(line, fmt_string2, &idval, sid_string) == 2) {
                        type = ID_USERID;
-               }
-
-               if (type == ID_EMPTY) {
+                       id.uid = (uid_t)idval;
+               } else {
                        d_printf("ignoring invalid line [%s]\n", line);
                        continue;
                }
index f32348935fc64229d1c861a4cfffbccb55356f0c..f2cd4adb176fcc86f591dd1901e4f97ff17212c2 100644 (file)
@@ -4934,12 +4934,12 @@ static int rpc_file_close(int argc, const char **argv)
  * @param str3   strings for FILE_INFO_3
  **/
 
-static void display_file_info_3(FILE_INFO_3 *info3, FILE_INFO_3_STR *str3)
+static void display_file_info_3( FILE_INFO_3 *info3 )
 {
        fstring user = "", path = "";
 
-       rpcstr_pull_unistr2_fstring(user, &str3->uni_user_name);
-       rpcstr_pull_unistr2_fstring(path, &str3->uni_path_name);
+       rpcstr_pull_unistr2_fstring(user, info3->user);
+       rpcstr_pull_unistr2_fstring(path, info3->path);
 
        d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
                 info3->id, user, info3->perms, info3->num_locks, path);
@@ -4994,8 +4994,7 @@ static NTSTATUS rpc_file_list_internals(const DOM_SID *domain_sid,
                 "\nFileId  Opened by            Perms  Locks  Path"\
                 "\n------  ---------            -----  -----  ---- \n");
        for (i = 0; i < ctr.num_entries; i++)
-               display_file_info_3(&ctr.file.info3[i].info_3, 
-                                   &ctr.file.info3[i].info_3_str);
+               display_file_info_3(&ctr.file.info3[i]);
  done:
        return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
@@ -6269,7 +6268,7 @@ static int rpc_trustdom(int argc, const char **argv)
  */
 BOOL net_rpc_check(unsigned flags)
 {
-       struct cli_state cli;
+       struct cli_state *cli;
        BOOL ret = False;
        struct in_addr server_ip;
        char *server_name = NULL;
@@ -6278,23 +6277,23 @@ BOOL net_rpc_check(unsigned flags)
        if (!net_find_server(NULL, flags, &server_ip, &server_name))
                return False;
 
-       ZERO_STRUCT(cli);
-       if (cli_initialise(&cli) == False)
+       if ((cli = cli_initialise()) == NULL) {
                return False;
+       }
 
-       if (!cli_connect(&cli, server_name, &server_ip))
+       if (!cli_connect(cli, server_name, &server_ip))
                goto done;
        if (!attempt_netbios_session_request(&cli, global_myname(), 
                                             server_name, &server_ip))
                goto done;
-       if (!cli_negprot(&cli))
+       if (!cli_negprot(cli))
                goto done;
-       if (cli.protocol < PROTOCOL_NT1)
+       if (cli->protocol < PROTOCOL_NT1)
                goto done;
 
        ret = True;
  done:
-       cli_shutdown(&cli);
+       cli_shutdown(cli);
        return ret;
 }
 
index 8808d549ac591a4ebfe6f2d5e0c6edc86d66704c..50ab50bace33875696fbdd73883543692d7cdd33 100644 (file)
@@ -129,18 +129,23 @@ static void display_reg_value(const char *subkey, REGISTRY_VALUE value)
                break;
 
        case REG_MULTI_SZ: {
-               uint16 *curstr = (uint16 *) value.data_p;
-               uint8 *start = value.data_p;
-               d_printf("\t[%s:%s]: REG_MULTI_SZ:\n", subkey, value.valuename);
-               while ((*curstr != 0) && 
-                      ((uint8 *) curstr < start + value.size)) {
-                       rpcstr_pull(text, curstr, sizeof(text), -1, 
-                                   STR_TERMINATE);
-                       d_printf("%s\n", text);
-                       curstr += strlen(text) + 1;
+               int i, num_values;
+               char **values;
+
+               if (!NT_STATUS_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
+                                                      value.size,
+                                                      &num_values,
+                                                      &values))) {
+                       d_printf("reg_pull_multi_sz failed\n");
+                       break;
+               }
+
+               for (i=0; i<num_values; i++) {
+                       d_printf("%s\n", values[i]);
                }
+               TALLOC_FREE(values);
+               break;
        }
-       break;
 
        default:
                d_printf("\t%s: unknown type %d\n", value.valuename, value.type);
index 873cb7b4597e2ee1ae05bd1023d1af1d13089d0b..3eaff901554be71987f6e861237e70c343192c04 100644 (file)
 /********************************************************************
 ********************************************************************/
 
-char* dump_regval_type( uint32 type )
-{
-       static fstring string;
-       
-       switch (type) {
-       case REG_SZ:
-               fstrcpy( string, "REG_SZ" );
-               break;
-       case REG_MULTI_SZ:
-               fstrcpy( string, "REG_MULTI_SZ" );
-               break;
-       case REG_EXPAND_SZ:
-               fstrcpy( string, "REG_EXPAND_SZ" );
-               break;
-       case REG_DWORD:
-               fstrcpy( string, "REG_DWORD" );
-               break;
-       case REG_BINARY:
-               fstrcpy( string, "REG_BINARY" );
-               break;
-       default:
-               fstr_sprintf( string, "UNKNOWN [%d]", type );
-       }
-       
-       return string;
-}
-/********************************************************************
-********************************************************************/
-
 void dump_regval_buffer( uint32 type, REGVAL_BUFFER *buffer )
 {
        pstring string;
@@ -64,9 +35,26 @@ void dump_regval_buffer( uint32 type, REGVAL_BUFFER *buffer )
                rpcstr_pull( string, buffer->buffer, sizeof(string), -1, STR_TERMINATE );
                d_printf("%s\n", string);
                break;
-       case REG_MULTI_SZ:
+       case REG_MULTI_SZ: {
+               int i, num_values;
+               char **values;
+
                d_printf("\n");
+
+               if (!NT_STATUS_IS_OK(reg_pull_multi_sz(NULL, buffer->buffer,
+                                                      buffer->buf_len,
+                                                      &num_values,
+                                                      &values))) {
+                       d_printf("reg_pull_multi_sz failed\n");
+                       break;
+               }
+
+               for (i=0; i<num_values; i++) {
+                       d_printf("%s\n", values[i]);
+               }
+               TALLOC_FREE(values);
                break;
+       }
        case REG_DWORD:
                value = IVAL( buffer->buffer, 0 );
                d_printf( "0x%x\n", value );
@@ -113,16 +101,17 @@ static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid,
        
        result = rpccli_reg_connect(pipe_hnd, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive );
        if ( !W_ERROR_IS_OK(result) ) {
-               d_fprintf(stderr, "Unable to connect to remote registry\n");
+               d_fprintf(stderr, "Unable to connect to remote registry: "
+                         "%s\n", dos_errstr(result));
                return werror_to_ntstatus(result);
        }
        
-       if ( strlen( subpath ) != 0 ) {
-               result = rpccli_reg_open_entry(pipe_hnd, mem_ctx, &pol_hive, subpath, MAXIMUM_ALLOWED_ACCESS, &pol_key );
-               if ( !W_ERROR_IS_OK(result) ) {
-                       d_fprintf(stderr, "Unable to open [%s]\n", argv[0]);
-                       return werror_to_ntstatus(result);
-               }
+       result = rpccli_reg_open_entry(pipe_hnd, mem_ctx, &pol_hive, subpath,
+                                      MAXIMUM_ALLOWED_ACCESS, &pol_key );
+       if ( !W_ERROR_IS_OK(result) ) {
+               d_fprintf(stderr, "Unable to open [%s]: %s\n", argv[0],
+                         dos_errstr(result));
+               return werror_to_ntstatus(result);
        }
        
        /* get the subkeys */
@@ -173,7 +162,7 @@ static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid,
                }
                        
                d_printf("Valuename  = %s\n", name );
-               d_printf("Type       = %s\n", dump_regval_type(type) );
+               d_printf("Type       = %s\n", reg_type_lookup(type));
                d_printf("Data       = " );
                dump_regval_buffer( type, &value );
                d_printf("\n" );
@@ -279,7 +268,7 @@ static void dump_values( REGF_NK_REC *nk )
 
        for ( i=0; i<nk->num_values; i++ ) {
                d_printf( "\"%s\" = ", nk->values[i].valuename ? nk->values[i].valuename : "(default)" );
-               d_printf( "(%s) ", dump_regval_type( nk->values[i].type ) );
+               d_printf( "(%s) ", reg_type_lookup( nk->values[i].type ) );
 
                data_size = nk->values[i].data_size & ~VK_DATA_IN_OFFSET;
                switch ( nk->values[i].type ) {
index 4f99c3035c846ab1b61ad6d2888c6a4ec6281fe8..861040533c62fdb4c796fc085edc70d38feef4bd 100644 (file)
@@ -42,7 +42,7 @@ static void display_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *g)
        d_printf("\n");
 }
 
-static const char *display_time(NTTIME *nttime)
+static const char *display_time(const UINT64_S *nttime)
 {
        static fstring string;
 
@@ -123,11 +123,19 @@ static void display_account_info(uint32 rid, SAM_ACCOUNT_INFO *a)
               pdb_encode_acct_ctrl(a->acb_info, NEW_PW_FORMAT_SPACE_PADDED_LEN));
 }
 
+static time_t uint64s_nt_time_to_unix_abs(const UINT64_S *src)
+{
+       NTTIME nttime;
+       nttime.high = src->high;
+       nttime.low = src->low;
+       return nt_time_to_unix_abs(&nttime);
+}
+
 static void display_domain_info(SAM_DOMAIN_INFO *a)
 {
        time_t u_logout;
 
-       u_logout = nt_time_to_unix_abs((NTTIME *)&a->force_logoff);
+       u_logout = uint64s_nt_time_to_unix_abs(&a->force_logoff);
 
        d_printf("Domain name: %s\n", unistr2_static(&a->uni_dom_name));
 
@@ -136,11 +144,11 @@ static void display_domain_info(SAM_DOMAIN_INFO *a)
 
        d_printf("Force Logoff: %d\n", (int)u_logout);
 
-       d_printf("Max Password Age: %s\n", display_time((NTTIME *)&a->max_pwd_age));
-       d_printf("Min Password Age: %s\n", display_time((NTTIME *)&a->min_pwd_age));
+       d_printf("Max Password Age: %s\n", display_time(&a->max_pwd_age));
+       d_printf("Min Password Age: %s\n", display_time(&a->min_pwd_age));
 
-       d_printf("Lockout Time: %s\n", display_time((NTTIME *)&a->account_lockout.lockout_duration));
-       d_printf("Lockout Reset Time: %s\n", display_time((NTTIME *)&a->account_lockout.reset_count));
+       d_printf("Lockout Time: %s\n", display_time(&a->account_lockout.lockout_duration));
+       d_printf("Lockout Reset Time: %s\n", display_time(&a->account_lockout.reset_count));
 
        d_printf("Bad Attempt Lockout: %d\n", a->account_lockout.bad_attempt_lockout);
        d_printf("User must logon to change password: %d\n", a->logon_chgpass);
@@ -858,11 +866,11 @@ static NTSTATUS fetch_domain_info(uint32 rid, SAM_DOMAIN_INFO *delta)
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        pstring domname;
 
-       u_max_age = nt_time_to_unix_abs((NTTIME *)&delta->max_pwd_age);
-       u_min_age = nt_time_to_unix_abs((NTTIME *)&delta->min_pwd_age);
-       u_logout = nt_time_to_unix_abs((NTTIME *)&delta->force_logoff);
-       u_lockoutreset = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.reset_count);
-       u_lockouttime = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.lockout_duration);
+       u_max_age = uint64s_nt_time_to_unix_abs(&delta->max_pwd_age);
+       u_min_age = uint64s_nt_time_to_unix_abs(&delta->min_pwd_age);
+       u_logout = uint64s_nt_time_to_unix_abs(&delta->force_logoff);
+       u_lockoutreset = uint64s_nt_time_to_unix_abs(&delta->account_lockout.reset_count);
+       u_lockouttime = uint64s_nt_time_to_unix_abs(&delta->account_lockout.lockout_duration);
 
        unistr2_to_ascii(domname, &delta->uni_dom_name, sizeof(domname) - 1);
 
index f6486286a65f466b885fb6e1d96063253adcee9f..f6269627dab44bc2bd24769a4de04f0698fd8467 100644 (file)
@@ -30,8 +30,10 @@ static time_t cli_servertime(const char *host, struct in_addr *ip, int *zone)
        time_t ret = 0;
        struct cli_state *cli = NULL;
 
-       cli = cli_initialise(NULL);
-       if (!cli) goto done;
+       cli = cli_initialise();
+       if (!cli) {
+               goto done;
+       }
 
        if (!cli_connect(cli, host, ip)) {
                fprintf(stderr,"Can't contact server\n");
@@ -58,7 +60,9 @@ static time_t cli_servertime(const char *host, struct in_addr *ip, int *zone)
        if (zone) *zone = cli->serverzone;
 
 done:
-       if (cli) cli_shutdown(cli);
+       if (cli) {
+               cli_shutdown(cli);
+       }
        return ret;
 }
 
index ef24f9f16117eab2b2a77ff886a6395918870b9e..fc9e3e9546a072cdcfec304f1c362c78c1b42b69 100644 (file)
@@ -515,7 +515,7 @@ static NTSTATUS ntlm_auth_start_ntlmssp_server(NTLMSSP_STATE **ntlmssp_state)
        NTSTATUS status = ntlmssp_server_start(ntlmssp_state);
        
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(1, ("Could not start NTLMSSP client: %s\n",
+               DEBUG(1, ("Could not start NTLMSSP server: %s\n",
                          nt_errstr(status)));
                return status;
        }
index c8ea966a558a6e961501f97fc91109db5ce8333f..e69715affd024300c9a1860176aae6d3000c542f 100644 (file)
@@ -445,6 +445,7 @@ static BOOL test_plaintext(enum ntlm_break break_which)
        DATA_BLOB nt_response = data_blob(NULL, 0);
        DATA_BLOB lm_response = data_blob(NULL, 0);
        char *password;
+       smb_ucs2_t *nt_response_ucs2;
 
        uchar user_session_key[16];
        uchar lm_key[16];
@@ -457,12 +458,13 @@ static BOOL test_plaintext(enum ntlm_break break_which)
        flags |= WBFLAG_PAM_LMKEY;
        flags |= WBFLAG_PAM_USER_SESSION_KEY;
 
-       if ((push_ucs2_allocate((smb_ucs2_t **)&nt_response.data, opt_password)) == -1) {
+       if ((push_ucs2_allocate(&nt_response_ucs2, opt_password)) == -1) {
                DEBUG(0, ("push_ucs2_allocate failed!\n"));
                exit(1);
        }
 
-       nt_response.length = strlen_w(((void *)nt_response.data))*sizeof(smb_ucs2_t);
+       nt_response.data = (unsigned char *)nt_response_ucs2;
+       nt_response.length = strlen_w(nt_response_ucs2)*sizeof(smb_ucs2_t);
 
        if ((password = strdup_upper(opt_password)) == NULL) {
                DEBUG(0, ("strdup_upper failed!\n"));
@@ -472,7 +474,7 @@ static BOOL test_plaintext(enum ntlm_break break_which)
        if ((convert_string_allocate(NULL, CH_UNIX, 
                                     CH_DOS, password,
                                     strlen(password)+1, 
-                                    (void**)&lm_response.data,True)) == -1) {
+                                    &lm_response.data,True)) == -1) {
                DEBUG(0, ("convert_string_allocate failed!\n"));
                exit(1);
        }
diff --git a/source/utils/sharesec.c b/source/utils/sharesec.c
new file mode 100644 (file)
index 0000000..aa4210b
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ *  Unix SMB/Netbios implementation.
+ *  Utility for managing share permissions
+ *
+ *  Copyright (C) Tim Potter                    2000
+ *  Copyright (C) Jeremy Allison                2000
+ *  Copyright (C) Jelmer Vernooij               2003
+ *  Copyright (C) Gerald (Jerry) Carter         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"
+
+#define CREATE_ACCESS_READ READ_CONTROL_ACCESS
+
+/* numeric is set when the user wants numeric SIDs and ACEs rather
+   than going via LSA calls to resolve them */
+static BOOL numeric = False;
+
+enum acl_mode {SMB_ACL_REMOVE, SMB_ACL_MODIFY, SMB_ACL_ADD, SMB_ACL_REPLACE,  SMB_ACL_VIEW };
+enum exit_values {EXIT_OK, EXIT_FAILED, EXIT_PARSE_ERROR};
+
+struct perm_value {
+       const char *perm;
+       uint32 mask;
+};
+
+/* These values discovered by inspection */
+
+static const struct perm_value special_values[] = {
+       { "R", 0x00120089 },
+       { "W", 0x00120116 },
+       { "X", 0x001200a0 },
+       { "D", 0x00010000 },
+       { "P", 0x00040000 },
+       { "O", 0x00080000 },
+       { NULL, 0 },
+};
+
+static const struct perm_value standard_values[] = {
+       { "READ",   0x001200a9 },
+       { "CHANGE", 0x001301bf },
+       { "FULL",   0x001f01ff },
+       { NULL, 0 },
+};
+
+/********************************************************************
+ print an ACE on a FILE, using either numeric or ascii representation
+********************************************************************/
+
+static void print_ace(FILE *f, SEC_ACE *ace)
+{
+       const struct perm_value *v;
+       fstring sidstr;
+       int do_print = 0;
+       uint32 got_mask;
+
+       sid_to_string(sidstr, &ace->trustee);
+
+       fprintf(f, "%s:", sidstr);
+
+       if (numeric) {
+               fprintf(f, "%d/%d/0x%08x", 
+                       ace->type, ace->flags, ace->info.mask);
+               return;
+       }
+
+       /* Ace type */
+
+       if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) {
+               fprintf(f, "ALLOWED");
+       } else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) {
+               fprintf(f, "DENIED");
+       } else {
+               fprintf(f, "%d", ace->type);
+       }
+
+       /* Not sure what flags can be set in a file ACL */
+
+       fprintf(f, "/%d/", ace->flags);
+
+       /* Standard permissions */
+
+       for (v = standard_values; v->perm; v++) {
+               if (ace->info.mask == v->mask) {
+                       fprintf(f, "%s", v->perm);
+                       return;
+               }
+       }
+
+       /* Special permissions.  Print out a hex value if we have
+          leftover bits in the mask. */
+
+       got_mask = ace->info.mask;
+
+ again:
+       for (v = special_values; v->perm; v++) {
+               if ((ace->info.mask & v->mask) == v->mask) {
+                       if (do_print) {
+                               fprintf(f, "%s", v->perm);
+                       }
+                       got_mask &= ~v->mask;
+               }
+       }
+
+       if (!do_print) {
+               if (got_mask != 0) {
+                       fprintf(f, "0x%08x", ace->info.mask);
+               } else {
+                       do_print = 1;
+                       goto again;
+               }
+       }
+}
+
+/********************************************************************
+ print a ascii version of a security descriptor on a FILE handle
+********************************************************************/
+
+static void sec_desc_print(FILE *f, SEC_DESC *sd)
+{
+       fstring sidstr;
+       uint32 i;
+
+       fprintf(f, "REVISION:%d\n", sd->revision);
+
+       /* Print owner and group sid */
+
+       if (sd->owner_sid) {
+               sid_to_string(sidstr, sd->owner_sid);
+       } else {
+               fstrcpy(sidstr, "");
+       }
+
+       fprintf(f, "OWNER:%s\n", sidstr);
+
+       if (sd->grp_sid) {
+               sid_to_string(sidstr, sd->grp_sid);
+       } else {
+               fstrcpy(sidstr, "");
+       }
+
+       fprintf(f, "GROUP:%s\n", sidstr);
+
+       /* Print aces */
+       for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
+               SEC_ACE *ace = &sd->dacl->ace[i];
+               fprintf(f, "ACL:");
+               print_ace(f, ace);
+               fprintf(f, "\n");
+       }
+
+}
+
+/********************************************************************
+********************************************************************/
+
+static BOOL parse_ace( TALLOC_CTX *ctx, SEC_ACE *ace, char *entry )
+{
+       SEC_ACCESS sa;
+       char *p = strchr_m( entry, ':' );
+       DOM_SID sid;
+       uint32 mask;
+       
+       if ( !p )
+               return False;
+               
+       *p = '\0';
+       p++;
+       
+       string_to_sid( &sid, entry );
+       
+       switch ( *p ) {
+               case 'F':
+               case 'f':
+                       mask = GENERIC_RIGHTS_FILE_ALL_ACCESS|STD_RIGHT_ALL_ACCESS;
+                       break;
+
+               case 'R':
+               case 'r':
+                       mask = GENERIC_RIGHTS_FILE_READ|GENERIC_RIGHTS_FILE_EXECUTE|\
+                               STANDARD_RIGHTS_READ_ACCESS|STANDARD_RIGHTS_EXECUTE_ACCESS;
+                       break;
+
+               default:
+                       return False;
+       }
+       
+       init_sec_access( &sa, mask );
+
+       /* no flags on share permissions */
+       init_sec_ace( ace, &sid, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0 );
+       
+       return True;
+}
+
+
+/********************************************************************
+********************************************************************/
+
+static SEC_DESC* parse_acl_string( TALLOC_CTX *ctx, const char *szACL, size_t *sd_size )
+{
+       SEC_DESC *sd = NULL;
+       SEC_ACE *ace;
+       SEC_ACL *acl;
+       int num_ace;
+       const char *pacl;
+       int i;
+       
+       if ( !szACL )
+               return NULL;
+
+       pacl = szACL;
+       num_ace = count_chars( pacl, ',' ) + 1;
+       
+       if ( !(ace = TALLOC_ZERO_ARRAY( ctx, SEC_ACE, num_ace )) ) 
+               return NULL;
+       
+       for ( i=0; i<num_ace; i++ ) {
+               char *end_acl = strchr_m( pacl, ',' );
+               fstring acl_string;
+
+               strncpy( acl_string, pacl, MIN( PTR_DIFF( end_acl, pacl ), sizeof(fstring)-1) );
+               acl_string[MIN( PTR_DIFF( end_acl, pacl ), sizeof(fstring)-1)] = '\0';
+               
+               if ( !parse_ace( ctx, &ace[i], acl_string ) )
+                       return NULL;
+
+               pacl = end_acl;
+               pacl++;
+       }
+       
+       if ( !(acl = make_sec_acl( ctx, NT4_ACL_REVISION, num_ace, ace )) )
+               return NULL;
+               
+       sd = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, 
+               &global_sid_Builtin_Administrators,
+               &global_sid_Builtin_Administrators,
+               NULL, acl, sd_size);
+
+       return sd;
+}
+
+/********************************************************************
+  main program
+********************************************************************/
+
+int main(int argc, const char *argv[])
+{
+       int opt;
+       enum acl_mode mode = SMB_ACL_REPLACE;
+       static char *the_acl = NULL;
+       fstring sharename;
+       BOOL force_acl = False;
+       size_t sd_size = 0;
+       SEC_DESC *secdesc;
+       int snum;
+       poptContext pc;
+       TALLOC_CTX *ctx;
+       BOOL initialize_sid = False;
+       struct poptOption long_options[] = {
+               POPT_AUTOHELP
+#if 0
+               { "remove", 'r', POPT_ARG_STRING, NULL, 'r', "Delete an ACE", "ACL" },
+               { "modify", 'm', POPT_ARG_STRING, NULL, 'm', "Modify an acl", "ACL" },
+               { "add", 'a', POPT_ARG_STRING, NULL, 'a', "Add an ACE", "ACL" },
+#endif
+               { "replace", 'R', POPT_ARG_STRING, NULL, 'R', "Set share mission ACL", "ACLS" },
+               { "view", 'v', POPT_ARG_NONE, NULL, 'v', "View current share permissions" },
+               { "machine-sid", 'M', POPT_ARG_NONE, NULL, 'M', "Initialize the machine SID" },
+               { "force", 'F', POPT_ARG_NONE, NULL, 'F', "Force storing the ACL", "ACLS" },
+               POPT_COMMON_SAMBA
+               { NULL }
+       };
+
+       if ( !(ctx = talloc_init("main")) ) {
+               fprintf( stderr, "Failed to initialize talloc context!\n");
+               return -1;
+       }
+
+       /* set default debug level to 1 regardless of what smb.conf sets */
+       setup_logging( "sharesec", True );
+       DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
+       dbf = x_stderr;
+       x_setbuf( x_stderr, NULL );
+
+       setlinebuf(stdout);
+
+       load_case_tables();
+
+       lp_load( dyn_CONFIGFILE, False, False, False, True );
+
+       pc = poptGetContext("smbcacls", argc, argv, long_options, 0);
+       
+       poptSetOtherOptionHelp(pc, "sharename\n");
+
+       while ((opt = poptGetNextOpt(pc)) != -1) {
+               switch (opt) {
+#if 0
+               case 'r':
+                       the_acl = smb_xstrdup(poptGetOptArg(pc));
+                       mode = SMB_ACL_REMOVE;
+                       break;
+
+               case 'm':
+                       the_acl = smb_xstrdup(poptGetOptArg(pc));
+                       mode = SMB_ACL_MODIFY;
+                       break;
+
+               case 'a':
+                       the_acl = smb_xstrdup(poptGetOptArg(pc));
+                       mode = SMB_ACL_ADD;
+                       break;
+#endif
+               case 'R':
+                       the_acl = smb_xstrdup(poptGetOptArg(pc));
+                       mode = SMB_ACL_REPLACE;
+                       break;
+
+               case 'v':
+                       mode = SMB_ACL_VIEW;
+                       break;
+
+               case 'F':
+                       force_acl = True;
+                       break;
+                       
+               case 'M':
+                       initialize_sid = True;
+                       break;
+               }
+       }
+       
+       /* check for initializing secrets.tdb first */
+       
+       if ( initialize_sid ) {
+               DOM_SID *sid = get_global_sam_sid();
+               
+               if ( !sid ) {
+                       fprintf( stderr, "Failed to retrieve Machine SID!\n");
+                       return 3;
+               }
+               
+               printf ("%s\n", sid_string_static( sid ) );
+               return 0;
+       }
+
+       if ( mode == SMB_ACL_VIEW && force_acl ) {
+               fprintf( stderr, "Invalid combination of -F and -v\n");
+               return -1;
+       }
+
+       /* get the sharename */
+
+       if(!poptPeekArg(pc)) { 
+               poptPrintUsage(pc, stderr, 0);  
+               return -1;
+       }
+       
+       fstrcpy(sharename, poptGetArg(pc));
+       
+       snum = lp_servicenumber( sharename );
+       
+       if ( snum == -1 && !force_acl ) {
+               fprintf( stderr, "Invalid sharename: %s\n", sharename);
+               return -1;
+       }
+               
+       switch ( mode ) {
+               case SMB_ACL_VIEW:
+                       if (!(secdesc = get_share_security( ctx, snum, &sd_size )) ) {
+                               fprintf(stderr, "Unable to retrieve permissions for share [%s]\n", sharename);
+                               return -1;
+                       }
+                       sec_desc_print( stdout, secdesc );
+                       break;
+
+               case SMB_ACL_REMOVE:
+               case SMB_ACL_ADD:
+               case SMB_ACL_MODIFY:
+                       printf( "Not implemented\n");
+                       break;
+
+               case SMB_ACL_REPLACE:
+                       if ( !(secdesc = parse_acl_string( ctx, the_acl, &sd_size )) ) {
+                               fprintf( stderr, "Failed to parse acl\n");
+                               return -1;
+                       }
+                       
+                       if ( !set_share_security( ctx, lp_servicename(snum), secdesc ) ) {
+                               fprintf( stderr, "Failed to store acl for share [%s]\n", sharename );
+                               return 2;
+                       }
+                       break;
+       }
+
+       talloc_destroy(ctx);
+
+       return 0;
+}
index 0c6a1341c037cb16128cc0bc4b4c4b2bbd76e7f7..a23492f9dcc721efe61d37794c8e5beef05d2daf 100644 (file)
@@ -890,7 +890,7 @@ static BOOL do_winbind_offline(const struct process_id pid,
                ret = send_message(pid, MSG_WINBIND_OFFLINE, NULL, 0, False);
 
                /* Check that the entry "WINBINDD_OFFLINE" still exists. */
-               tdb->ecode = TDB_SUCCESS;
+               /* tdb->ecode = TDB_SUCCESS; */
                d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
 
                /* As this is a key with no data we don't need to free, we
index 163d99a2f69bf8be6725463b9cbfd829792c3e21..58349f1f9a57fb1acea13aa04913a5577c33236f 100644 (file)
@@ -48,6 +48,9 @@ static BOOL numeric_only = False;
 
 const char *username = NULL;
 
+extern BOOL status_profile_dump(BOOL be_verbose);
+extern BOOL status_profile_rates(BOOL be_verbose);
+
 /* added by OH */
 static void Ucrit_addUid(uid_t uid)
 {
@@ -182,368 +185,6 @@ static void print_brl(SMB_DEV_T dev,
               (double)start, (double)size);
 }
 
-
-/*******************************************************************
- dump the elements of the profile structure
-  ******************************************************************/
-static int profile_dump(void)
-{
-#ifdef WITH_PROFILE
-       if (!profile_setup(True)) {
-               fprintf(stderr,"Failed to initialise profile memory\n");
-               return -1;
-       }
-
-       d_printf("smb_count:                      %u\n", profile_p->smb_count);
-       d_printf("uid_changes:                    %u\n", profile_p->uid_changes);
-       d_printf("************************ System Calls ****************************\n");
-       d_printf("opendir_count:                  %u\n", profile_p->syscall_opendir_count);
-       d_printf("opendir_time:                   %u\n", profile_p->syscall_opendir_time);
-       d_printf("readdir_count:                  %u\n", profile_p->syscall_readdir_count);
-       d_printf("readdir_time:                   %u\n", profile_p->syscall_readdir_time);
-       d_printf("mkdir_count:                    %u\n", profile_p->syscall_mkdir_count);
-       d_printf("mkdir_time:                     %u\n", profile_p->syscall_mkdir_time);
-       d_printf("rmdir_count:                    %u\n", profile_p->syscall_rmdir_count);
-       d_printf("rmdir_time:                     %u\n", profile_p->syscall_rmdir_time);
-       d_printf("closedir_count:                 %u\n", profile_p->syscall_closedir_count);
-       d_printf("closedir_time:                  %u\n", profile_p->syscall_closedir_time);
-       d_printf("open_count:                     %u\n", profile_p->syscall_open_count);
-       d_printf("open_time:                      %u\n", profile_p->syscall_open_time);
-       d_printf("close_count:                    %u\n", profile_p->syscall_close_count);
-       d_printf("close_time:                     %u\n", profile_p->syscall_close_time);
-       d_printf("read_count:                     %u\n", profile_p->syscall_read_count);
-       d_printf("read_time:                      %u\n", profile_p->syscall_read_time);
-       d_printf("read_bytes:                     %u\n", profile_p->syscall_read_bytes);
-       d_printf("write_count:                    %u\n", profile_p->syscall_write_count);
-       d_printf("write_time:                     %u\n", profile_p->syscall_write_time);
-       d_printf("write_bytes:                    %u\n", profile_p->syscall_write_bytes);
-       d_printf("pread_count:                    %u\n", profile_p->syscall_pread_count);
-       d_printf("pread_time:                     %u\n", profile_p->syscall_pread_time);
-       d_printf("pread_bytes:                    %u\n", profile_p->syscall_pread_bytes);
-       d_printf("pwrite_count:                   %u\n", profile_p->syscall_pwrite_count);
-       d_printf("pwrite_time:                    %u\n", profile_p->syscall_pwrite_time);
-       d_printf("pwrite_bytes:                   %u\n", profile_p->syscall_pwrite_bytes);
-#ifdef WITH_SENDFILE
-       d_printf("sendfile_count:                 %u\n", profile_p->syscall_sendfile_count);
-       d_printf("sendfile_time:                  %u\n", profile_p->syscall_sendfile_time);
-       d_printf("sendfile_bytes:                 %u\n", profile_p->syscall_sendfile_bytes);
-#endif
-       d_printf("lseek_count:                    %u\n", profile_p->syscall_lseek_count);
-       d_printf("lseek_time:                     %u\n", profile_p->syscall_lseek_time);
-       d_printf("rename_count:                   %u\n", profile_p->syscall_rename_count);
-       d_printf("rename_time:                    %u\n", profile_p->syscall_rename_time);
-       d_printf("fsync_count:                    %u\n", profile_p->syscall_fsync_count);
-       d_printf("fsync_time:                     %u\n", profile_p->syscall_fsync_time);
-       d_printf("stat_count:                     %u\n", profile_p->syscall_stat_count);
-       d_printf("stat_time:                      %u\n", profile_p->syscall_stat_time);
-       d_printf("fstat_count:                    %u\n", profile_p->syscall_fstat_count);
-       d_printf("fstat_time:                     %u\n", profile_p->syscall_fstat_time);
-       d_printf("lstat_count:                    %u\n", profile_p->syscall_lstat_count);
-       d_printf("lstat_time:                     %u\n", profile_p->syscall_lstat_time);
-       d_printf("unlink_count:                   %u\n", profile_p->syscall_unlink_count);
-       d_printf("unlink_time:                    %u\n", profile_p->syscall_unlink_time);
-       d_printf("chmod_count:                    %u\n", profile_p->syscall_chmod_count);
-       d_printf("chmod_time:                     %u\n", profile_p->syscall_chmod_time);
-       d_printf("fchmod_count:                   %u\n", profile_p->syscall_fchmod_count);
-       d_printf("fchmod_time:                    %u\n", profile_p->syscall_fchmod_time);
-       d_printf("chown_count:                    %u\n", profile_p->syscall_chown_count);
-       d_printf("chown_time:                     %u\n", profile_p->syscall_chown_time);
-       d_printf("fchown_count:                   %u\n", profile_p->syscall_fchown_count);
-       d_printf("fchown_time:                    %u\n", profile_p->syscall_fchown_time);
-       d_printf("chdir_count:                    %u\n", profile_p->syscall_chdir_count);
-       d_printf("chdir_time:                     %u\n", profile_p->syscall_chdir_time);
-       d_printf("getwd_count:                    %u\n", profile_p->syscall_getwd_count);
-       d_printf("getwd_time:                     %u\n", profile_p->syscall_getwd_time);
-       d_printf("utime_count:                    %u\n", profile_p->syscall_utime_count);
-       d_printf("utime_time:                     %u\n", profile_p->syscall_utime_time);
-       d_printf("ftruncate_count:                %u\n", profile_p->syscall_ftruncate_count);
-       d_printf("ftruncate_time:                 %u\n", profile_p->syscall_ftruncate_time);
-       d_printf("fcntl_lock_count:               %u\n", profile_p->syscall_fcntl_lock_count);
-       d_printf("fcntl_lock_time:                %u\n", profile_p->syscall_fcntl_lock_time);
-       d_printf("readlink_count:                 %u\n", profile_p->syscall_readlink_count);
-       d_printf("readlink_time:                  %u\n", profile_p->syscall_readlink_time);
-       d_printf("symlink_count:                  %u\n", profile_p->syscall_symlink_count);
-       d_printf("symlink_time:                   %u\n", profile_p->syscall_symlink_time);
-       d_printf("************************ Statcache *******************************\n");
-       d_printf("lookups:                        %u\n", profile_p->statcache_lookups);
-       d_printf("misses:                         %u\n", profile_p->statcache_misses);
-       d_printf("hits:                           %u\n", profile_p->statcache_hits);
-       d_printf("************************ Writecache ******************************\n");
-       d_printf("read_hits:                      %u\n", profile_p->writecache_read_hits);
-       d_printf("abutted_writes:                 %u\n", profile_p->writecache_abutted_writes);
-       d_printf("total_writes:                   %u\n", profile_p->writecache_total_writes);
-       d_printf("non_oplock_writes:              %u\n", profile_p->writecache_non_oplock_writes);
-       d_printf("direct_writes:                  %u\n", profile_p->writecache_direct_writes);
-       d_printf("init_writes:                    %u\n", profile_p->writecache_init_writes);
-       d_printf("flushed_writes[SEEK]:           %u\n", profile_p->writecache_flushed_writes[SEEK_FLUSH]);
-       d_printf("flushed_writes[READ]:           %u\n", profile_p->writecache_flushed_writes[READ_FLUSH]);
-       d_printf("flushed_writes[WRITE]:          %u\n", profile_p->writecache_flushed_writes[WRITE_FLUSH]);
-       d_printf("flushed_writes[READRAW]:        %u\n", profile_p->writecache_flushed_writes[READRAW_FLUSH]);
-       d_printf("flushed_writes[OPLOCK_RELEASE]: %u\n", profile_p->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH]);
-       d_printf("flushed_writes[CLOSE]:          %u\n", profile_p->writecache_flushed_writes[CLOSE_FLUSH]);
-       d_printf("flushed_writes[SYNC]:           %u\n", profile_p->writecache_flushed_writes[SYNC_FLUSH]);
-       d_printf("flushed_writes[SIZECHANGE]:     %u\n", profile_p->writecache_flushed_writes[SIZECHANGE_FLUSH]);
-       d_printf("num_perfect_writes:             %u\n", profile_p->writecache_num_perfect_writes);
-       d_printf("num_write_caches:               %u\n", profile_p->writecache_num_write_caches);
-       d_printf("allocated_write_caches:         %u\n", profile_p->writecache_allocated_write_caches);
-       d_printf("************************ SMB Calls *******************************\n");
-       d_printf("mkdir_count:                    %u\n", profile_p->SMBmkdir_count);
-       d_printf("mkdir_time:                     %u\n", profile_p->SMBmkdir_time);
-       d_printf("rmdir_count:                    %u\n", profile_p->SMBrmdir_count);
-       d_printf("rmdir_time:                     %u\n", profile_p->SMBrmdir_time);
-       d_printf("open_count:                     %u\n", profile_p->SMBopen_count);
-       d_printf("open_time:                      %u\n", profile_p->SMBopen_time);
-       d_printf("create_count:                   %u\n", profile_p->SMBcreate_count);
-       d_printf("create_time:                    %u\n", profile_p->SMBcreate_time);
-       d_printf("close_count:                    %u\n", profile_p->SMBclose_count);
-       d_printf("close_time:                     %u\n", profile_p->SMBclose_time);
-       d_printf("flush_count:                    %u\n", profile_p->SMBflush_count);
-       d_printf("flush_time:                     %u\n", profile_p->SMBflush_time);
-       d_printf("unlink_count:                   %u\n", profile_p->SMBunlink_count);
-       d_printf("unlink_time:                    %u\n", profile_p->SMBunlink_time);
-       d_printf("mv_count:                       %u\n", profile_p->SMBmv_count);
-       d_printf("mv_time:                        %u\n", profile_p->SMBmv_time);
-       d_printf("getatr_count:                   %u\n", profile_p->SMBgetatr_count);
-       d_printf("getatr_time:                    %u\n", profile_p->SMBgetatr_time);
-       d_printf("setatr_count:                   %u\n", profile_p->SMBsetatr_count);
-       d_printf("setatr_time:                    %u\n", profile_p->SMBsetatr_time);
-       d_printf("read_count:                     %u\n", profile_p->SMBread_count);
-       d_printf("read_time:                      %u\n", profile_p->SMBread_time);
-       d_printf("write_count:                    %u\n", profile_p->SMBwrite_count);
-       d_printf("write_time:                     %u\n", profile_p->SMBwrite_time);
-       d_printf("lock_count:                     %u\n", profile_p->SMBlock_count);
-       d_printf("lock_time:                      %u\n", profile_p->SMBlock_time);
-       d_printf("unlock_count:                   %u\n", profile_p->SMBunlock_count);
-       d_printf("unlock_time:                    %u\n", profile_p->SMBunlock_time);
-       d_printf("ctemp_count:                    %u\n", profile_p->SMBctemp_count);
-       d_printf("ctemp_time:                     %u\n", profile_p->SMBctemp_time);
-       d_printf("mknew_count:                    %u\n", profile_p->SMBmknew_count);
-       d_printf("mknew_time:                     %u\n", profile_p->SMBmknew_time);
-       d_printf("chkpth_count:                   %u\n", profile_p->SMBchkpth_count);
-       d_printf("chkpth_time:                    %u\n", profile_p->SMBchkpth_time);
-       d_printf("exit_count:                     %u\n", profile_p->SMBexit_count);
-       d_printf("exit_time:                      %u\n", profile_p->SMBexit_time);
-       d_printf("lseek_count:                    %u\n", profile_p->SMBlseek_count);
-       d_printf("lseek_time:                     %u\n", profile_p->SMBlseek_time);
-       d_printf("lockread_count:                 %u\n", profile_p->SMBlockread_count);
-       d_printf("lockread_time:                  %u\n", profile_p->SMBlockread_time);
-       d_printf("writeunlock_count:              %u\n", profile_p->SMBwriteunlock_count);
-       d_printf("writeunlock_time:               %u\n", profile_p->SMBwriteunlock_time);
-       d_printf("readbraw_count:                 %u\n", profile_p->SMBreadbraw_count);
-       d_printf("readbraw_time:                  %u\n", profile_p->SMBreadbraw_time);
-       d_printf("readBmpx_count:                 %u\n", profile_p->SMBreadBmpx_count);
-       d_printf("readBmpx_time:                  %u\n", profile_p->SMBreadBmpx_time);
-       d_printf("readBs_count:                   %u\n", profile_p->SMBreadBs_count);
-       d_printf("readBs_time:                    %u\n", profile_p->SMBreadBs_time);
-       d_printf("writebraw_count:                %u\n", profile_p->SMBwritebraw_count);
-       d_printf("writebraw_time:                 %u\n", profile_p->SMBwritebraw_time);
-       d_printf("writeBmpx_count:                %u\n", profile_p->SMBwriteBmpx_count);
-       d_printf("writeBmpx_time:                 %u\n", profile_p->SMBwriteBmpx_time);
-       d_printf("writeBs_count:                  %u\n", profile_p->SMBwriteBs_count);
-       d_printf("writeBs_time:                   %u\n", profile_p->SMBwriteBs_time);
-       d_printf("writec_count:                   %u\n", profile_p->SMBwritec_count);
-       d_printf("writec_time:                    %u\n", profile_p->SMBwritec_time);
-       d_printf("setattrE_count:                 %u\n", profile_p->SMBsetattrE_count);
-       d_printf("setattrE_time:                  %u\n", profile_p->SMBsetattrE_time);
-       d_printf("getattrE_count:                 %u\n", profile_p->SMBgetattrE_count);
-       d_printf("getattrE_time:                  %u\n", profile_p->SMBgetattrE_time);
-       d_printf("lockingX_count:                 %u\n", profile_p->SMBlockingX_count);
-       d_printf("lockingX_time:                  %u\n", profile_p->SMBlockingX_time);
-       d_printf("trans_count:                    %u\n", profile_p->SMBtrans_count);
-       d_printf("trans_time:                     %u\n", profile_p->SMBtrans_time);
-       d_printf("transs_count:                   %u\n", profile_p->SMBtranss_count);
-       d_printf("transs_time:                    %u\n", profile_p->SMBtranss_time);
-       d_printf("ioctl_count:                    %u\n", profile_p->SMBioctl_count);
-       d_printf("ioctl_time:                     %u\n", profile_p->SMBioctl_time);
-       d_printf("ioctls_count:                   %u\n", profile_p->SMBioctls_count);
-       d_printf("ioctls_time:                    %u\n", profile_p->SMBioctls_time);
-       d_printf("copy_count:                     %u\n", profile_p->SMBcopy_count);
-       d_printf("copy_time:                      %u\n", profile_p->SMBcopy_time);
-       d_printf("move_count:                     %u\n", profile_p->SMBmove_count);
-       d_printf("move_time:                      %u\n", profile_p->SMBmove_time);
-       d_printf("echo_count:                     %u\n", profile_p->SMBecho_count);
-       d_printf("echo_time:                      %u\n", profile_p->SMBecho_time);
-       d_printf("writeclose_count:               %u\n", profile_p->SMBwriteclose_count);
-       d_printf("writeclose_time:                %u\n", profile_p->SMBwriteclose_time);
-       d_printf("openX_count:                    %u\n", profile_p->SMBopenX_count);
-       d_printf("openX_time:                     %u\n", profile_p->SMBopenX_time);
-       d_printf("readX_count:                    %u\n", profile_p->SMBreadX_count);
-       d_printf("readX_time:                     %u\n", profile_p->SMBreadX_time);
-       d_printf("writeX_count:                   %u\n", profile_p->SMBwriteX_count);
-       d_printf("writeX_time:                    %u\n", profile_p->SMBwriteX_time);
-       d_printf("trans2_count:                   %u\n", profile_p->SMBtrans2_count);
-       d_printf("trans2_time:                    %u\n", profile_p->SMBtrans2_time);
-       d_printf("transs2_count:                  %u\n", profile_p->SMBtranss2_count);
-       d_printf("transs2_time:                   %u\n", profile_p->SMBtranss2_time);
-       d_printf("findclose_count:                %u\n", profile_p->SMBfindclose_count);
-       d_printf("findclose_time:                 %u\n", profile_p->SMBfindclose_time);
-       d_printf("findnclose_count:               %u\n", profile_p->SMBfindnclose_count);
-       d_printf("findnclose_time:                %u\n", profile_p->SMBfindnclose_time);
-       d_printf("tcon_count:                     %u\n", profile_p->SMBtcon_count);
-       d_printf("tcon_time:                      %u\n", profile_p->SMBtcon_time);
-       d_printf("tdis_count:                     %u\n", profile_p->SMBtdis_count);
-       d_printf("tdis_time:                      %u\n", profile_p->SMBtdis_time);
-       d_printf("negprot_count:                  %u\n", profile_p->SMBnegprot_count);
-       d_printf("negprot_time:                   %u\n", profile_p->SMBnegprot_time);
-       d_printf("sesssetupX_count:               %u\n", profile_p->SMBsesssetupX_count);
-       d_printf("sesssetupX_time:                %u\n", profile_p->SMBsesssetupX_time);
-       d_printf("ulogoffX_count:                 %u\n", profile_p->SMBulogoffX_count);
-       d_printf("ulogoffX_time:                  %u\n", profile_p->SMBulogoffX_time);
-       d_printf("tconX_count:                    %u\n", profile_p->SMBtconX_count);
-       d_printf("tconX_time:                     %u\n", profile_p->SMBtconX_time);
-       d_printf("dskattr_count:                  %u\n", profile_p->SMBdskattr_count);
-       d_printf("dskattr_time:                   %u\n", profile_p->SMBdskattr_time);
-       d_printf("search_count:                   %u\n", profile_p->SMBsearch_count);
-       d_printf("search_time:                    %u\n", profile_p->SMBsearch_time);
-       d_printf("ffirst_count:                   %u\n", profile_p->SMBffirst_count);
-       d_printf("ffirst_time:                    %u\n", profile_p->SMBffirst_time);
-       d_printf("funique_count:                  %u\n", profile_p->SMBfunique_count);
-       d_printf("funique_time:                   %u\n", profile_p->SMBfunique_time);
-       d_printf("fclose_count:                   %u\n", profile_p->SMBfclose_count);
-       d_printf("fclose_time:                    %u\n", profile_p->SMBfclose_time);
-       d_printf("nttrans_count:                  %u\n", profile_p->SMBnttrans_count);
-       d_printf("nttrans_time:                   %u\n", profile_p->SMBnttrans_time);
-       d_printf("nttranss_count:                 %u\n", profile_p->SMBnttranss_count);
-       d_printf("nttranss_time:                  %u\n", profile_p->SMBnttranss_time);
-       d_printf("ntcreateX_count:                %u\n", profile_p->SMBntcreateX_count);
-       d_printf("ntcreateX_time:                 %u\n", profile_p->SMBntcreateX_time);
-       d_printf("ntcancel_count:                 %u\n", profile_p->SMBntcancel_count);
-       d_printf("ntcancel_time:                  %u\n", profile_p->SMBntcancel_time);
-       d_printf("splopen_count:                  %u\n", profile_p->SMBsplopen_count);
-       d_printf("splopen_time:                   %u\n", profile_p->SMBsplopen_time);
-       d_printf("splwr_count:                    %u\n", profile_p->SMBsplwr_count);
-       d_printf("splwr_time:                     %u\n", profile_p->SMBsplwr_time);
-       d_printf("splclose_count:                 %u\n", profile_p->SMBsplclose_count);
-       d_printf("splclose_time:                  %u\n", profile_p->SMBsplclose_time);
-       d_printf("splretq_count:                  %u\n", profile_p->SMBsplretq_count);
-       d_printf("splretq_time:                   %u\n", profile_p->SMBsplretq_time);
-       d_printf("sends_count:                    %u\n", profile_p->SMBsends_count);
-       d_printf("sends_time:                     %u\n", profile_p->SMBsends_time);
-       d_printf("sendb_count:                    %u\n", profile_p->SMBsendb_count);
-       d_printf("sendb_time:                     %u\n", profile_p->SMBsendb_time);
-       d_printf("fwdname_count:                  %u\n", profile_p->SMBfwdname_count);
-       d_printf("fwdname_time:                   %u\n", profile_p->SMBfwdname_time);
-       d_printf("cancelf_count:                  %u\n", profile_p->SMBcancelf_count);
-       d_printf("cancelf_time:                   %u\n", profile_p->SMBcancelf_time);
-       d_printf("getmac_count:                   %u\n", profile_p->SMBgetmac_count);
-       d_printf("getmac_time:                    %u\n", profile_p->SMBgetmac_time);
-       d_printf("sendstrt_count:                 %u\n", profile_p->SMBsendstrt_count);
-       d_printf("sendstrt_time:                  %u\n", profile_p->SMBsendstrt_time);
-       d_printf("sendend_count:                  %u\n", profile_p->SMBsendend_count);
-       d_printf("sendend_time:                   %u\n", profile_p->SMBsendend_time);
-       d_printf("sendtxt_count:                  %u\n", profile_p->SMBsendtxt_count);
-       d_printf("sendtxt_time:                   %u\n", profile_p->SMBsendtxt_time);
-       d_printf("invalid_count:                  %u\n", profile_p->SMBinvalid_count);
-       d_printf("invalid_time:                   %u\n", profile_p->SMBinvalid_time);
-       d_printf("************************ Pathworks Calls *************************\n");
-       d_printf("setdir_count:                   %u\n", profile_p->pathworks_setdir_count);
-       d_printf("setdir_time:                    %u\n", profile_p->pathworks_setdir_time);
-       d_printf("************************ Trans2 Calls ****************************\n");
-       d_printf("open_count:                     %u\n", profile_p->Trans2_open_count);
-       d_printf("open_time:                      %u\n", profile_p->Trans2_open_time);
-       d_printf("findfirst_count:                %u\n", profile_p->Trans2_findfirst_count);
-       d_printf("findfirst_time:                 %u\n", profile_p->Trans2_findfirst_time);
-       d_printf("findnext_count:                 %u\n", profile_p->Trans2_findnext_count);
-       d_printf("findnext_time:                  %u\n", profile_p->Trans2_findnext_time);
-       d_printf("qfsinfo_count:                  %u\n", profile_p->Trans2_qfsinfo_count);
-       d_printf("qfsinfo_time:                   %u\n", profile_p->Trans2_qfsinfo_time);
-       d_printf("setfsinfo_count:                %u\n", profile_p->Trans2_setfsinfo_count);
-       d_printf("setfsinfo_time:                 %u\n", profile_p->Trans2_setfsinfo_time);
-       d_printf("qpathinfo_count:                %u\n", profile_p->Trans2_qpathinfo_count);
-       d_printf("qpathinfo_time:                 %u\n", profile_p->Trans2_qpathinfo_time);
-       d_printf("setpathinfo_count:              %u\n", profile_p->Trans2_setpathinfo_count);
-       d_printf("setpathinfo_time:               %u\n", profile_p->Trans2_setpathinfo_time);
-       d_printf("qfileinfo_count:                %u\n", profile_p->Trans2_qfileinfo_count);
-       d_printf("qfileinfo_time:                 %u\n", profile_p->Trans2_qfileinfo_time);
-       d_printf("setfileinfo_count:              %u\n", profile_p->Trans2_setfileinfo_count);
-       d_printf("setfileinfo_time:               %u\n", profile_p->Trans2_setfileinfo_time);
-       d_printf("fsctl_count:                    %u\n", profile_p->Trans2_fsctl_count);
-       d_printf("fsctl_time:                     %u\n", profile_p->Trans2_fsctl_time);
-       d_printf("ioctl_count:                    %u\n", profile_p->Trans2_ioctl_count);
-       d_printf("ioctl_time:                     %u\n", profile_p->Trans2_ioctl_time);
-       d_printf("findnotifyfirst_count:          %u\n", profile_p->Trans2_findnotifyfirst_count);
-       d_printf("findnotifyfirst_time:           %u\n", profile_p->Trans2_findnotifyfirst_time);
-       d_printf("findnotifynext_count:           %u\n", profile_p->Trans2_findnotifynext_count);
-       d_printf("findnotifynext_time:            %u\n", profile_p->Trans2_findnotifynext_time);
-       d_printf("mkdir_count:                    %u\n", profile_p->Trans2_mkdir_count);
-       d_printf("mkdir_time:                     %u\n", profile_p->Trans2_mkdir_time);
-       d_printf("session_setup_count:            %u\n", profile_p->Trans2_session_setup_count);
-       d_printf("session_setup_time:             %u\n", profile_p->Trans2_session_setup_time);
-       d_printf("get_dfs_referral_count:         %u\n", profile_p->Trans2_get_dfs_referral_count);
-       d_printf("get_dfs_referral_time:          %u\n", profile_p->Trans2_get_dfs_referral_time);
-       d_printf("report_dfs_inconsistancy_count: %u\n", profile_p->Trans2_report_dfs_inconsistancy_count);
-       d_printf("report_dfs_inconsistancy_time:  %u\n", profile_p->Trans2_report_dfs_inconsistancy_time);
-       d_printf("************************ NT Transact Calls ***********************\n");
-       d_printf("create_count:                   %u\n", profile_p->NT_transact_create_count);
-       d_printf("create_time:                    %u\n", profile_p->NT_transact_create_time);
-       d_printf("ioctl_count:                    %u\n", profile_p->NT_transact_ioctl_count);
-       d_printf("ioctl_time:                     %u\n", profile_p->NT_transact_ioctl_time);
-       d_printf("set_security_desc_count:        %u\n", profile_p->NT_transact_set_security_desc_count);
-       d_printf("set_security_desc_time:         %u\n", profile_p->NT_transact_set_security_desc_time);
-       d_printf("notify_change_count:            %u\n", profile_p->NT_transact_notify_change_count);
-       d_printf("notify_change_time:             %u\n", profile_p->NT_transact_notify_change_time);
-       d_printf("rename_count:                   %u\n", profile_p->NT_transact_rename_count);
-       d_printf("rename_time:                    %u\n", profile_p->NT_transact_rename_time);
-       d_printf("query_security_desc_count:      %u\n", profile_p->NT_transact_query_security_desc_count);
-       d_printf("query_security_desc_time:       %u\n", profile_p->NT_transact_query_security_desc_time);
-       d_printf("************************ ACL Calls *******************************\n");
-       d_printf("get_nt_acl_count:               %u\n", profile_p->get_nt_acl_count);
-       d_printf("get_nt_acl_time:                %u\n", profile_p->get_nt_acl_time);
-       d_printf("fget_nt_acl_count:              %u\n", profile_p->fget_nt_acl_count);
-       d_printf("fget_nt_acl_time:               %u\n", profile_p->fget_nt_acl_time);
-       d_printf("set_nt_acl_count:               %u\n", profile_p->set_nt_acl_count);
-       d_printf("set_nt_acl_time:                %u\n", profile_p->set_nt_acl_time);
-       d_printf("fset_nt_acl_count:              %u\n", profile_p->fset_nt_acl_count);
-       d_printf("fset_nt_acl_time:               %u\n", profile_p->fset_nt_acl_time);
-       d_printf("chmod_acl_count:                %u\n", profile_p->chmod_acl_count);
-       d_printf("chmod_acl_time:                 %u\n", profile_p->chmod_acl_time);
-       d_printf("fchmod_acl_count:               %u\n", profile_p->fchmod_acl_count);
-       d_printf("fchmod_acl_time:                %u\n", profile_p->fchmod_acl_time);
-       d_printf("************************ NMBD Calls ****************************\n");
-       d_printf("name_release_count:             %u\n", profile_p->name_release_count);
-       d_printf("name_release_time:              %u\n", profile_p->name_release_time);
-       d_printf("name_refresh_count:             %u\n", profile_p->name_refresh_count);
-       d_printf("name_refresh_time:              %u\n", profile_p->name_refresh_time);
-       d_printf("name_registration_count:        %u\n", profile_p->name_registration_count);
-       d_printf("name_registration_time:         %u\n", profile_p->name_registration_time);
-       d_printf("node_status_count:              %u\n", profile_p->node_status_count);
-       d_printf("node_status_time:               %u\n", profile_p->node_status_time);
-       d_printf("name_query_count:               %u\n", profile_p->name_query_count);
-       d_printf("name_query_time:                %u\n", profile_p->name_query_time);
-       d_printf("host_announce_count:            %u\n", profile_p->host_announce_count);
-       d_printf("host_announce_time:             %u\n", profile_p->host_announce_time);
-       d_printf("workgroup_announce_count:       %u\n", profile_p->workgroup_announce_count);
-       d_printf("workgroup_announce_time:        %u\n", profile_p->workgroup_announce_time);
-       d_printf("local_master_announce_count:    %u\n", profile_p->local_master_announce_count);
-       d_printf("local_master_announce_time:     %u\n", profile_p->local_master_announce_time);
-       d_printf("master_browser_announce_count:  %u\n", profile_p->master_browser_announce_count);
-       d_printf("master_browser_announce_time:   %u\n", profile_p->master_browser_announce_time);
-       d_printf("lm_host_announce_count:         %u\n", profile_p->lm_host_announce_count);
-       d_printf("lm_host_announce_time:          %u\n", profile_p->lm_host_announce_time);
-       d_printf("get_backup_list_count:          %u\n", profile_p->get_backup_list_count);
-       d_printf("get_backup_list_time:           %u\n", profile_p->get_backup_list_time);
-       d_printf("reset_browser_count:            %u\n", profile_p->reset_browser_count);
-       d_printf("reset_browser_time:             %u\n", profile_p->reset_browser_time);
-       d_printf("announce_request_count:         %u\n", profile_p->announce_request_count);
-       d_printf("announce_request_time:          %u\n", profile_p->announce_request_time);
-       d_printf("lm_announce_request_count:      %u\n", profile_p->lm_announce_request_count);
-       d_printf("lm_announce_request_time:       %u\n", profile_p->lm_announce_request_time);
-       d_printf("domain_logon_count:             %u\n", profile_p->domain_logon_count);
-       d_printf("domain_logon_time:              %u\n", profile_p->domain_logon_time);
-       d_printf("sync_browse_lists_count:        %u\n", profile_p->sync_browse_lists_count);
-       d_printf("sync_browse_lists_time:         %u\n", profile_p->sync_browse_lists_time);
-       d_printf("run_elections_count:            %u\n", profile_p->run_elections_count);
-       d_printf("run_elections_time:             %u\n", profile_p->run_elections_time);
-       d_printf("election_count:                 %u\n", profile_p->election_count);
-       d_printf("election_time:                  %u\n", profile_p->election_time);
-#else /* WITH_PROFILE */
-       fprintf(stderr, "Profile data unavailable\n");
-#endif /* WITH_PROFILE */
-
-       return 0;
-}
-
-
 static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
 {
        struct connections_data crec;
@@ -602,7 +243,7 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo
  int main(int argc, char *argv[])
 {
        int c;
-       static int profile_only = 0;
+       int profile_only = 0;
        TDB_CONTEXT *tdb;
        BOOL show_processes, show_locks, show_shares;
        poptContext pc;
@@ -614,9 +255,8 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo
                {"shares",      'S', POPT_ARG_NONE,     &shares_only, 'S', "Show shares only" },
                {"user",        'u', POPT_ARG_STRING,   &username, 'u', "Switch to user" },
                {"brief",       'b', POPT_ARG_NONE,     &brief, 'b', "Be brief" },
-#ifdef WITH_PROFILE
-               {"profile",     'P', POPT_ARG_NONE,     &profile_only, 'P', "Do profiling" },
-#endif /* WITH_PROFILE */
+               {"profile",     'P', POPT_ARG_NONE, NULL, 'P', "Do profiling" },
+               {"profile-rates", 'R', POPT_ARG_NONE, NULL, 'R', "Show call rates" },
                {"byterange",   'B', POPT_ARG_NONE,     &show_brl, 'B', "Include byte range locks"},
                {"numeric",     'n', POPT_ARG_NONE,     &numeric_only, 'n', "Numeric uid/gid"},
                POPT_COMMON_SAMBA
@@ -643,6 +283,9 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo
                case 'u':                                      
                        Ucrit_addUid(nametouid(poptGetOptArg(pc)));
                        break;
+               case 'P':
+               case 'R':
+                       profile_only = c;
                }
        }
 
@@ -663,11 +306,18 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo
                fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
                return (-1);
        }
-       
-       if (profile_only) {
-               return profile_dump();
+
+       switch (profile_only) {
+               case 'P':
+                       /* Dump profile data */
+                       return status_profile_dump(verbose);
+               case 'R':
+                       /* Continuously display rate-converted data */
+                       return status_profile_rates(verbose);
+               default:
+                       break;
        }
-       
+
        if ( show_processes ) {
                tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0);
                if (!tdb) {
diff --git a/source/utils/status_profile.c b/source/utils/status_profile.c
new file mode 100644 (file)
index 0000000..fc5b5e1
--- /dev/null
@@ -0,0 +1,544 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * status reporting
+ * Copyright (C) Andrew Tridgell 1994-1998
+ * Copyright (C) James Peach 2005-2006
+ *
+ * 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"
+
+static void profile_separator(const char * title)
+{
+    char line[79 + 1];
+    char * end;
+
+    snprintf(line, sizeof(line), "**** %s ", title);
+
+    for (end = line + strlen(line); end < &line[sizeof(line) -1]; ++end) {
+           *end = '*';
+    }
+
+    line[sizeof(line) - 1] = '\0';
+    d_printf("%s\n", line);
+}
+
+/*******************************************************************
+ dump the elements of the profile structure
+  ******************************************************************/
+BOOL status_profile_dump(BOOL verbose)
+{
+#ifdef WITH_PROFILE
+       if (!profile_setup(True)) {
+               fprintf(stderr,"Failed to initialise profile memory\n");
+               return False;
+       }
+
+       d_printf("smb_count:                      %u\n", profile_p->smb_count);
+       d_printf("uid_changes:                    %u\n", profile_p->uid_changes);
+
+       profile_separator("System Calls");
+       d_printf("opendir_count:                  %u\n", profile_p->syscall_opendir_count);
+       d_printf("opendir_time:                   %u\n", profile_p->syscall_opendir_time);
+       d_printf("readdir_count:                  %u\n", profile_p->syscall_readdir_count);
+       d_printf("readdir_time:                   %u\n", profile_p->syscall_readdir_time);
+       d_printf("mkdir_count:                    %u\n", profile_p->syscall_mkdir_count);
+       d_printf("mkdir_time:                     %u\n", profile_p->syscall_mkdir_time);
+       d_printf("rmdir_count:                    %u\n", profile_p->syscall_rmdir_count);
+       d_printf("rmdir_time:                     %u\n", profile_p->syscall_rmdir_time);
+       d_printf("closedir_count:                 %u\n", profile_p->syscall_closedir_count);
+       d_printf("closedir_time:                  %u\n", profile_p->syscall_closedir_time);
+       d_printf("open_count:                     %u\n", profile_p->syscall_open_count);
+       d_printf("open_time:                      %u\n", profile_p->syscall_open_time);
+       d_printf("close_count:                    %u\n", profile_p->syscall_close_count);
+       d_printf("close_time:                     %u\n", profile_p->syscall_close_time);
+       d_printf("read_count:                     %u\n", profile_p->syscall_read_count);
+       d_printf("read_time:                      %u\n", profile_p->syscall_read_time);
+       d_printf("read_bytes:                     %u\n", profile_p->syscall_read_bytes);
+       d_printf("write_count:                    %u\n", profile_p->syscall_write_count);
+       d_printf("write_time:                     %u\n", profile_p->syscall_write_time);
+       d_printf("write_bytes:                    %u\n", profile_p->syscall_write_bytes);
+       d_printf("pread_count:                    %u\n", profile_p->syscall_pread_count);
+       d_printf("pread_time:                     %u\n", profile_p->syscall_pread_time);
+       d_printf("pread_bytes:                    %u\n", profile_p->syscall_pread_bytes);
+       d_printf("pwrite_count:                   %u\n", profile_p->syscall_pwrite_count);
+       d_printf("pwrite_time:                    %u\n", profile_p->syscall_pwrite_time);
+       d_printf("pwrite_bytes:                   %u\n", profile_p->syscall_pwrite_bytes);
+#ifdef WITH_SENDFILE
+       d_printf("sendfile_count:                 %u\n", profile_p->syscall_sendfile_count);
+       d_printf("sendfile_time:                  %u\n", profile_p->syscall_sendfile_time);
+       d_printf("sendfile_bytes:                 %u\n", profile_p->syscall_sendfile_bytes);
+#endif
+       d_printf("lseek_count:                    %u\n", profile_p->syscall_lseek_count);
+       d_printf("lseek_time:                     %u\n", profile_p->syscall_lseek_time);
+       d_printf("rename_count:                   %u\n", profile_p->syscall_rename_count);
+       d_printf("rename_time:                    %u\n", profile_p->syscall_rename_time);
+       d_printf("fsync_count:                    %u\n", profile_p->syscall_fsync_count);
+       d_printf("fsync_time:                     %u\n", profile_p->syscall_fsync_time);
+       d_printf("stat_count:                     %u\n", profile_p->syscall_stat_count);
+       d_printf("stat_time:                      %u\n", profile_p->syscall_stat_time);
+       d_printf("fstat_count:                    %u\n", profile_p->syscall_fstat_count);
+       d_printf("fstat_time:                     %u\n", profile_p->syscall_fstat_time);
+       d_printf("lstat_count:                    %u\n", profile_p->syscall_lstat_count);
+       d_printf("lstat_time:                     %u\n", profile_p->syscall_lstat_time);
+       d_printf("unlink_count:                   %u\n", profile_p->syscall_unlink_count);
+       d_printf("unlink_time:                    %u\n", profile_p->syscall_unlink_time);
+       d_printf("chmod_count:                    %u\n", profile_p->syscall_chmod_count);
+       d_printf("chmod_time:                     %u\n", profile_p->syscall_chmod_time);
+       d_printf("fchmod_count:                   %u\n", profile_p->syscall_fchmod_count);
+       d_printf("fchmod_time:                    %u\n", profile_p->syscall_fchmod_time);
+       d_printf("chown_count:                    %u\n", profile_p->syscall_chown_count);
+       d_printf("chown_time:                     %u\n", profile_p->syscall_chown_time);
+       d_printf("fchown_count:                   %u\n", profile_p->syscall_fchown_count);
+       d_printf("fchown_time:                    %u\n", profile_p->syscall_fchown_time);
+       d_printf("chdir_count:                    %u\n", profile_p->syscall_chdir_count);
+       d_printf("chdir_time:                     %u\n", profile_p->syscall_chdir_time);
+       d_printf("getwd_count:                    %u\n", profile_p->syscall_getwd_count);
+       d_printf("getwd_time:                     %u\n", profile_p->syscall_getwd_time);
+       d_printf("utime_count:                    %u\n", profile_p->syscall_utime_count);
+       d_printf("utime_time:                     %u\n", profile_p->syscall_utime_time);
+       d_printf("ftruncate_count:                %u\n", profile_p->syscall_ftruncate_count);
+       d_printf("ftruncate_time:                 %u\n", profile_p->syscall_ftruncate_time);
+       d_printf("fcntl_lock_count:               %u\n", profile_p->syscall_fcntl_lock_count);
+       d_printf("fcntl_lock_time:                %u\n", profile_p->syscall_fcntl_lock_time);
+       d_printf("readlink_count:                 %u\n", profile_p->syscall_readlink_count);
+       d_printf("readlink_time:                  %u\n", profile_p->syscall_readlink_time);
+       d_printf("symlink_count:                  %u\n", profile_p->syscall_symlink_count);
+       d_printf("symlink_time:                   %u\n", profile_p->syscall_symlink_time);
+
+       profile_separator("Stat Cache");
+       d_printf("lookups:                        %u\n", profile_p->statcache_lookups);
+       d_printf("misses:                         %u\n", profile_p->statcache_misses);
+       d_printf("hits:                           %u\n", profile_p->statcache_hits);
+
+       profile_separator("Write Cache");
+       d_printf("read_hits:                      %u\n", profile_p->writecache_read_hits);
+       d_printf("abutted_writes:                 %u\n", profile_p->writecache_abutted_writes);
+       d_printf("total_writes:                   %u\n", profile_p->writecache_total_writes);
+       d_printf("non_oplock_writes:              %u\n", profile_p->writecache_non_oplock_writes);
+       d_printf("direct_writes:                  %u\n", profile_p->writecache_direct_writes);
+       d_printf("init_writes:                    %u\n", profile_p->writecache_init_writes);
+       d_printf("flushed_writes[SEEK]:           %u\n", profile_p->writecache_flushed_writes[SEEK_FLUSH]);
+       d_printf("flushed_writes[READ]:           %u\n", profile_p->writecache_flushed_writes[READ_FLUSH]);
+       d_printf("flushed_writes[WRITE]:          %u\n", profile_p->writecache_flushed_writes[WRITE_FLUSH]);
+       d_printf("flushed_writes[READRAW]:        %u\n", profile_p->writecache_flushed_writes[READRAW_FLUSH]);
+       d_printf("flushed_writes[OPLOCK_RELEASE]: %u\n", profile_p->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH]);
+       d_printf("flushed_writes[CLOSE]:          %u\n", profile_p->writecache_flushed_writes[CLOSE_FLUSH]);
+       d_printf("flushed_writes[SYNC]:           %u\n", profile_p->writecache_flushed_writes[SYNC_FLUSH]);
+       d_printf("flushed_writes[SIZECHANGE]:     %u\n", profile_p->writecache_flushed_writes[SIZECHANGE_FLUSH]);
+       d_printf("num_perfect_writes:             %u\n", profile_p->writecache_num_perfect_writes);
+       d_printf("num_write_caches:               %u\n", profile_p->writecache_num_write_caches);
+       d_printf("allocated_write_caches:         %u\n", profile_p->writecache_allocated_write_caches);
+
+       profile_separator("SMB Calls");
+       d_printf("mkdir_count:                    %u\n", profile_p->SMBmkdir_count);
+       d_printf("mkdir_time:                     %u\n", profile_p->SMBmkdir_time);
+       d_printf("rmdir_count:                    %u\n", profile_p->SMBrmdir_count);
+       d_printf("rmdir_time:                     %u\n", profile_p->SMBrmdir_time);
+       d_printf("open_count:                     %u\n", profile_p->SMBopen_count);
+       d_printf("open_time:                      %u\n", profile_p->SMBopen_time);
+       d_printf("create_count:                   %u\n", profile_p->SMBcreate_count);
+       d_printf("create_time:                    %u\n", profile_p->SMBcreate_time);
+       d_printf("close_count:                    %u\n", profile_p->SMBclose_count);
+       d_printf("close_time:                     %u\n", profile_p->SMBclose_time);
+       d_printf("flush_count:                    %u\n", profile_p->SMBflush_count);
+       d_printf("flush_time:                     %u\n", profile_p->SMBflush_time);
+       d_printf("unlink_count:                   %u\n", profile_p->SMBunlink_count);
+       d_printf("unlink_time:                    %u\n", profile_p->SMBunlink_time);
+       d_printf("mv_count:                       %u\n", profile_p->SMBmv_count);
+       d_printf("mv_time:                        %u\n", profile_p->SMBmv_time);
+       d_printf("getatr_count:                   %u\n", profile_p->SMBgetatr_count);
+       d_printf("getatr_time:                    %u\n", profile_p->SMBgetatr_time);
+       d_printf("setatr_count:                   %u\n", profile_p->SMBsetatr_count);
+       d_printf("setatr_time:                    %u\n", profile_p->SMBsetatr_time);
+       d_printf("read_count:                     %u\n", profile_p->SMBread_count);
+       d_printf("read_time:                      %u\n", profile_p->SMBread_time);
+       d_printf("write_count:                    %u\n", profile_p->SMBwrite_count);
+       d_printf("write_time:                     %u\n", profile_p->SMBwrite_time);
+       d_printf("lock_count:                     %u\n", profile_p->SMBlock_count);
+       d_printf("lock_time:                      %u\n", profile_p->SMBlock_time);
+       d_printf("unlock_count:                   %u\n", profile_p->SMBunlock_count);
+       d_printf("unlock_time:                    %u\n", profile_p->SMBunlock_time);
+       d_printf("ctemp_count:                    %u\n", profile_p->SMBctemp_count);
+       d_printf("ctemp_time:                     %u\n", profile_p->SMBctemp_time);
+       d_printf("mknew_count:                    %u\n", profile_p->SMBmknew_count);
+       d_printf("mknew_time:                     %u\n", profile_p->SMBmknew_time);
+       d_printf("chkpth_count:                   %u\n", profile_p->SMBchkpth_count);
+       d_printf("chkpth_time:                    %u\n", profile_p->SMBchkpth_time);
+       d_printf("exit_count:                     %u\n", profile_p->SMBexit_count);
+       d_printf("exit_time:                      %u\n", profile_p->SMBexit_time);
+       d_printf("lseek_count:                    %u\n", profile_p->SMBlseek_count);
+       d_printf("lseek_time:                     %u\n", profile_p->SMBlseek_time);
+       d_printf("lockread_count:                 %u\n", profile_p->SMBlockread_count);
+       d_printf("lockread_time:                  %u\n", profile_p->SMBlockread_time);
+       d_printf("writeunlock_count:              %u\n", profile_p->SMBwriteunlock_count);
+       d_printf("writeunlock_time:               %u\n", profile_p->SMBwriteunlock_time);
+       d_printf("readbraw_count:                 %u\n", profile_p->SMBreadbraw_count);
+       d_printf("readbraw_time:                  %u\n", profile_p->SMBreadbraw_time);
+       d_printf("readBmpx_count:                 %u\n", profile_p->SMBreadBmpx_count);
+       d_printf("readBmpx_time:                  %u\n", profile_p->SMBreadBmpx_time);
+       d_printf("readBs_count:                   %u\n", profile_p->SMBreadBs_count);
+       d_printf("readBs_time:                    %u\n", profile_p->SMBreadBs_time);
+       d_printf("writebraw_count:                %u\n", profile_p->SMBwritebraw_count);
+       d_printf("writebraw_time:                 %u\n", profile_p->SMBwritebraw_time);
+       d_printf("writeBmpx_count:                %u\n", profile_p->SMBwriteBmpx_count);
+       d_printf("writeBmpx_time:                 %u\n", profile_p->SMBwriteBmpx_time);
+       d_printf("writeBs_count:                  %u\n", profile_p->SMBwriteBs_count);
+       d_printf("writeBs_time:                   %u\n", profile_p->SMBwriteBs_time);
+       d_printf("writec_count:                   %u\n", profile_p->SMBwritec_count);
+       d_printf("writec_time:                    %u\n", profile_p->SMBwritec_time);
+       d_printf("setattrE_count:                 %u\n", profile_p->SMBsetattrE_count);
+       d_printf("setattrE_time:                  %u\n", profile_p->SMBsetattrE_time);
+       d_printf("getattrE_count:                 %u\n", profile_p->SMBgetattrE_count);
+       d_printf("getattrE_time:                  %u\n", profile_p->SMBgetattrE_time);
+       d_printf("lockingX_count:                 %u\n", profile_p->SMBlockingX_count);
+       d_printf("lockingX_time:                  %u\n", profile_p->SMBlockingX_time);
+       d_printf("trans_count:                    %u\n", profile_p->SMBtrans_count);
+       d_printf("trans_time:                     %u\n", profile_p->SMBtrans_time);
+       d_printf("transs_count:                   %u\n", profile_p->SMBtranss_count);
+       d_printf("transs_time:                    %u\n", profile_p->SMBtranss_time);
+       d_printf("ioctl_count:                    %u\n", profile_p->SMBioctl_count);
+       d_printf("ioctl_time:                     %u\n", profile_p->SMBioctl_time);
+       d_printf("ioctls_count:                   %u\n", profile_p->SMBioctls_count);
+       d_printf("ioctls_time:                    %u\n", profile_p->SMBioctls_time);
+       d_printf("copy_count:                     %u\n", profile_p->SMBcopy_count);
+       d_printf("copy_time:                      %u\n", profile_p->SMBcopy_time);
+       d_printf("move_count:                     %u\n", profile_p->SMBmove_count);
+       d_printf("move_time:                      %u\n", profile_p->SMBmove_time);
+       d_printf("echo_count:                     %u\n", profile_p->SMBecho_count);
+       d_printf("echo_time:                      %u\n", profile_p->SMBecho_time);
+       d_printf("writeclose_count:               %u\n", profile_p->SMBwriteclose_count);
+       d_printf("writeclose_time:                %u\n", profile_p->SMBwriteclose_time);
+       d_printf("openX_count:                    %u\n", profile_p->SMBopenX_count);
+       d_printf("openX_time:                     %u\n", profile_p->SMBopenX_time);
+       d_printf("readX_count:                    %u\n", profile_p->SMBreadX_count);
+       d_printf("readX_time:                     %u\n", profile_p->SMBreadX_time);
+       d_printf("writeX_count:                   %u\n", profile_p->SMBwriteX_count);
+       d_printf("writeX_time:                    %u\n", profile_p->SMBwriteX_time);
+       d_printf("trans2_count:                   %u\n", profile_p->SMBtrans2_count);
+       d_printf("trans2_time:                    %u\n", profile_p->SMBtrans2_time);
+       d_printf("transs2_count:                  %u\n", profile_p->SMBtranss2_count);
+       d_printf("transs2_time:                   %u\n", profile_p->SMBtranss2_time);
+       d_printf("findclose_count:                %u\n", profile_p->SMBfindclose_count);
+       d_printf("findclose_time:                 %u\n", profile_p->SMBfindclose_time);
+       d_printf("findnclose_count:               %u\n", profile_p->SMBfindnclose_count);
+       d_printf("findnclose_time:                %u\n", profile_p->SMBfindnclose_time);
+       d_printf("tcon_count:                     %u\n", profile_p->SMBtcon_count);
+       d_printf("tcon_time:                      %u\n", profile_p->SMBtcon_time);
+       d_printf("tdis_count:                     %u\n", profile_p->SMBtdis_count);
+       d_printf("tdis_time:                      %u\n", profile_p->SMBtdis_time);
+       d_printf("negprot_count:                  %u\n", profile_p->SMBnegprot_count);
+       d_printf("negprot_time:                   %u\n", profile_p->SMBnegprot_time);
+       d_printf("sesssetupX_count:               %u\n", profile_p->SMBsesssetupX_count);
+       d_printf("sesssetupX_time:                %u\n", profile_p->SMBsesssetupX_time);
+       d_printf("ulogoffX_count:                 %u\n", profile_p->SMBulogoffX_count);
+       d_printf("ulogoffX_time:                  %u\n", profile_p->SMBulogoffX_time);
+       d_printf("tconX_count:                    %u\n", profile_p->SMBtconX_count);
+       d_printf("tconX_time:                     %u\n", profile_p->SMBtconX_time);
+       d_printf("dskattr_count:                  %u\n", profile_p->SMBdskattr_count);
+       d_printf("dskattr_time:                   %u\n", profile_p->SMBdskattr_time);
+       d_printf("search_count:                   %u\n", profile_p->SMBsearch_count);
+       d_printf("search_time:                    %u\n", profile_p->SMBsearch_time);
+       d_printf("ffirst_count:                   %u\n", profile_p->SMBffirst_count);
+       d_printf("ffirst_time:                    %u\n", profile_p->SMBffirst_time);
+       d_printf("funique_count:                  %u\n", profile_p->SMBfunique_count);
+       d_printf("funique_time:                   %u\n", profile_p->SMBfunique_time);
+       d_printf("fclose_count:                   %u\n", profile_p->SMBfclose_count);
+       d_printf("fclose_time:                    %u\n", profile_p->SMBfclose_time);
+       d_printf("nttrans_count:                  %u\n", profile_p->SMBnttrans_count);
+       d_printf("nttrans_time:                   %u\n", profile_p->SMBnttrans_time);
+       d_printf("nttranss_count:                 %u\n", profile_p->SMBnttranss_count);
+       d_printf("nttranss_time:                  %u\n", profile_p->SMBnttranss_time);
+       d_printf("ntcreateX_count:                %u\n", profile_p->SMBntcreateX_count);
+       d_printf("ntcreateX_time:                 %u\n", profile_p->SMBntcreateX_time);
+       d_printf("ntcancel_count:                 %u\n", profile_p->SMBntcancel_count);
+       d_printf("ntcancel_time:                  %u\n", profile_p->SMBntcancel_time);
+       d_printf("splopen_count:                  %u\n", profile_p->SMBsplopen_count);
+       d_printf("splopen_time:                   %u\n", profile_p->SMBsplopen_time);
+       d_printf("splwr_count:                    %u\n", profile_p->SMBsplwr_count);
+       d_printf("splwr_time:                     %u\n", profile_p->SMBsplwr_time);
+       d_printf("splclose_count:                 %u\n", profile_p->SMBsplclose_count);
+       d_printf("splclose_time:                  %u\n", profile_p->SMBsplclose_time);
+       d_printf("splretq_count:                  %u\n", profile_p->SMBsplretq_count);
+       d_printf("splretq_time:                   %u\n", profile_p->SMBsplretq_time);
+       d_printf("sends_count:                    %u\n", profile_p->SMBsends_count);
+       d_printf("sends_time:                     %u\n", profile_p->SMBsends_time);
+       d_printf("sendb_count:                    %u\n", profile_p->SMBsendb_count);
+       d_printf("sendb_time:                     %u\n", profile_p->SMBsendb_time);
+       d_printf("fwdname_count:                  %u\n", profile_p->SMBfwdname_count);
+       d_printf("fwdname_time:                   %u\n", profile_p->SMBfwdname_time);
+       d_printf("cancelf_count:                  %u\n", profile_p->SMBcancelf_count);
+       d_printf("cancelf_time:                   %u\n", profile_p->SMBcancelf_time);
+       d_printf("getmac_count:                   %u\n", profile_p->SMBgetmac_count);
+       d_printf("getmac_time:                    %u\n", profile_p->SMBgetmac_time);
+       d_printf("sendstrt_count:                 %u\n", profile_p->SMBsendstrt_count);
+       d_printf("sendstrt_time:                  %u\n", profile_p->SMBsendstrt_time);
+       d_printf("sendend_count:                  %u\n", profile_p->SMBsendend_count);
+       d_printf("sendend_time:                   %u\n", profile_p->SMBsendend_time);
+       d_printf("sendtxt_count:                  %u\n", profile_p->SMBsendtxt_count);
+       d_printf("sendtxt_time:                   %u\n", profile_p->SMBsendtxt_time);
+       d_printf("invalid_count:                  %u\n", profile_p->SMBinvalid_count);
+       d_printf("invalid_time:                   %u\n", profile_p->SMBinvalid_time);
+
+       profile_separator("Pathworks Calls");
+       d_printf("setdir_count:                   %u\n", profile_p->pathworks_setdir_count);
+       d_printf("setdir_time:                    %u\n", profile_p->pathworks_setdir_time);
+
+       profile_separator("Trans2 Calls");
+       d_printf("open_count:                     %u\n", profile_p->Trans2_open_count);
+       d_printf("open_time:                      %u\n", profile_p->Trans2_open_time);
+       d_printf("findfirst_count:                %u\n", profile_p->Trans2_findfirst_count);
+       d_printf("findfirst_time:                 %u\n", profile_p->Trans2_findfirst_time);
+       d_printf("findnext_count:                 %u\n", profile_p->Trans2_findnext_count);
+       d_printf("findnext_time:                  %u\n", profile_p->Trans2_findnext_time);
+       d_printf("qfsinfo_count:                  %u\n", profile_p->Trans2_qfsinfo_count);
+       d_printf("qfsinfo_time:                   %u\n", profile_p->Trans2_qfsinfo_time);
+       d_printf("setfsinfo_count:                %u\n", profile_p->Trans2_setfsinfo_count);
+       d_printf("setfsinfo_time:                 %u\n", profile_p->Trans2_setfsinfo_time);
+       d_printf("qpathinfo_count:                %u\n", profile_p->Trans2_qpathinfo_count);
+       d_printf("qpathinfo_time:                 %u\n", profile_p->Trans2_qpathinfo_time);
+       d_printf("setpathinfo_count:              %u\n", profile_p->Trans2_setpathinfo_count);
+       d_printf("setpathinfo_time:               %u\n", profile_p->Trans2_setpathinfo_time);
+       d_printf("qfileinfo_count:                %u\n", profile_p->Trans2_qfileinfo_count);
+       d_printf("qfileinfo_time:                 %u\n", profile_p->Trans2_qfileinfo_time);
+       d_printf("setfileinfo_count:              %u\n", profile_p->Trans2_setfileinfo_count);
+       d_printf("setfileinfo_time:               %u\n", profile_p->Trans2_setfileinfo_time);
+       d_printf("fsctl_count:                    %u\n", profile_p->Trans2_fsctl_count);
+       d_printf("fsctl_time:                     %u\n", profile_p->Trans2_fsctl_time);
+       d_printf("ioctl_count:                    %u\n", profile_p->Trans2_ioctl_count);
+       d_printf("ioctl_time:                     %u\n", profile_p->Trans2_ioctl_time);
+       d_printf("findnotifyfirst_count:          %u\n", profile_p->Trans2_findnotifyfirst_count);
+       d_printf("findnotifyfirst_time:           %u\n", profile_p->Trans2_findnotifyfirst_time);
+       d_printf("findnotifynext_count:           %u\n", profile_p->Trans2_findnotifynext_count);
+       d_printf("findnotifynext_time:            %u\n", profile_p->Trans2_findnotifynext_time);
+       d_printf("mkdir_count:                    %u\n", profile_p->Trans2_mkdir_count);
+       d_printf("mkdir_time:                     %u\n", profile_p->Trans2_mkdir_time);
+       d_printf("session_setup_count:            %u\n", profile_p->Trans2_session_setup_count);
+       d_printf("session_setup_time:             %u\n", profile_p->Trans2_session_setup_time);
+       d_printf("get_dfs_referral_count:         %u\n", profile_p->Trans2_get_dfs_referral_count);
+       d_printf("get_dfs_referral_time:          %u\n", profile_p->Trans2_get_dfs_referral_time);
+       d_printf("report_dfs_inconsistancy_count: %u\n", profile_p->Trans2_report_dfs_inconsistancy_count);
+       d_printf("report_dfs_inconsistancy_time:  %u\n", profile_p->Trans2_report_dfs_inconsistancy_time);
+
+       profile_separator("NT Transact Calls");
+       d_printf("create_count:                   %u\n", profile_p->NT_transact_create_count);
+       d_printf("create_time:                    %u\n", profile_p->NT_transact_create_time);
+       d_printf("ioctl_count:                    %u\n", profile_p->NT_transact_ioctl_count);
+       d_printf("ioctl_time:                     %u\n", profile_p->NT_transact_ioctl_time);
+       d_printf("set_security_desc_count:        %u\n", profile_p->NT_transact_set_security_desc_count);
+       d_printf("set_security_desc_time:         %u\n", profile_p->NT_transact_set_security_desc_time);
+       d_printf("notify_change_count:            %u\n", profile_p->NT_transact_notify_change_count);
+       d_printf("notify_change_time:             %u\n", profile_p->NT_transact_notify_change_time);
+       d_printf("rename_count:                   %u\n", profile_p->NT_transact_rename_count);
+       d_printf("rename_time:                    %u\n", profile_p->NT_transact_rename_time);
+       d_printf("query_security_desc_count:      %u\n", profile_p->NT_transact_query_security_desc_count);
+       d_printf("query_security_desc_time:       %u\n", profile_p->NT_transact_query_security_desc_time);
+
+       profile_separator("ACL Calls");
+       d_printf("get_nt_acl_count:               %u\n", profile_p->get_nt_acl_count);
+       d_printf("get_nt_acl_time:                %u\n", profile_p->get_nt_acl_time);
+       d_printf("fget_nt_acl_count:              %u\n", profile_p->fget_nt_acl_count);
+       d_printf("fget_nt_acl_time:               %u\n", profile_p->fget_nt_acl_time);
+       d_printf("set_nt_acl_count:               %u\n", profile_p->set_nt_acl_count);
+       d_printf("set_nt_acl_time:                %u\n", profile_p->set_nt_acl_time);
+       d_printf("fset_nt_acl_count:              %u\n", profile_p->fset_nt_acl_count);
+       d_printf("fset_nt_acl_time:               %u\n", profile_p->fset_nt_acl_time);
+       d_printf("chmod_acl_count:                %u\n", profile_p->chmod_acl_count);
+       d_printf("chmod_acl_time:                 %u\n", profile_p->chmod_acl_time);
+       d_printf("fchmod_acl_count:               %u\n", profile_p->fchmod_acl_count);
+       d_printf("fchmod_acl_time:                %u\n", profile_p->fchmod_acl_time);
+
+       profile_separator("NMBD Calls");
+       d_printf("name_release_count:             %u\n", profile_p->name_release_count);
+       d_printf("name_release_time:              %u\n", profile_p->name_release_time);
+       d_printf("name_refresh_count:             %u\n", profile_p->name_refresh_count);
+       d_printf("name_refresh_time:              %u\n", profile_p->name_refresh_time);
+       d_printf("name_registration_count:        %u\n", profile_p->name_registration_count);
+       d_printf("name_registration_time:         %u\n", profile_p->name_registration_time);
+       d_printf("node_status_count:              %u\n", profile_p->node_status_count);
+       d_printf("node_status_time:               %u\n", profile_p->node_status_time);
+       d_printf("name_query_count:               %u\n", profile_p->name_query_count);
+       d_printf("name_query_time:                %u\n", profile_p->name_query_time);
+       d_printf("host_announce_count:            %u\n", profile_p->host_announce_count);
+       d_printf("host_announce_time:             %u\n", profile_p->host_announce_time);
+       d_printf("workgroup_announce_count:       %u\n", profile_p->workgroup_announce_count);
+       d_printf("workgroup_announce_time:        %u\n", profile_p->workgroup_announce_time);
+       d_printf("local_master_announce_count:    %u\n", profile_p->local_master_announce_count);
+       d_printf("local_master_announce_time:     %u\n", profile_p->local_master_announce_time);
+       d_printf("master_browser_announce_count:  %u\n", profile_p->master_browser_announce_count);
+       d_printf("master_browser_announce_time:   %u\n", profile_p->master_browser_announce_time);
+       d_printf("lm_host_announce_count:         %u\n", profile_p->lm_host_announce_count);
+       d_printf("lm_host_announce_time:          %u\n", profile_p->lm_host_announce_time);
+       d_printf("get_backup_list_count:          %u\n", profile_p->get_backup_list_count);
+       d_printf("get_backup_list_time:           %u\n", profile_p->get_backup_list_time);
+       d_printf("reset_browser_count:            %u\n", profile_p->reset_browser_count);
+       d_printf("reset_browser_time:             %u\n", profile_p->reset_browser_time);
+       d_printf("announce_request_count:         %u\n", profile_p->announce_request_count);
+       d_printf("announce_request_time:          %u\n", profile_p->announce_request_time);
+       d_printf("lm_announce_request_count:      %u\n", profile_p->lm_announce_request_count);
+       d_printf("lm_announce_request_time:       %u\n", profile_p->lm_announce_request_time);
+       d_printf("domain_logon_count:             %u\n", profile_p->domain_logon_count);
+       d_printf("domain_logon_time:              %u\n", profile_p->domain_logon_time);
+       d_printf("sync_browse_lists_count:        %u\n", profile_p->sync_browse_lists_count);
+       d_printf("sync_browse_lists_time:         %u\n", profile_p->sync_browse_lists_time);
+       d_printf("run_elections_count:            %u\n", profile_p->run_elections_count);
+       d_printf("run_elections_time:             %u\n", profile_p->run_elections_time);
+       d_printf("election_count:                 %u\n", profile_p->election_count);
+       d_printf("election_time:                  %u\n", profile_p->election_time);
+#else /* WITH_PROFILE */
+       fprintf(stderr, "Profile data unavailable\n");
+#endif /* WITH_PROFILE */
+
+       return True;
+}
+
+#ifdef WITH_PROFILE
+
+static void sample_delay(int delay_msec)
+{
+       poll(NULL, 0, delay_msec);
+}
+
+/* Convert microseconds to milliseconds. */
+#define usec_to_msec(s) ((s) / 1000)
+/* Convert microseconds to seconds. */
+#define usec_to_sec(s) ((s) / 1000000)
+/* One second in microseconds. */
+#define one_second_usec (1000000)
+
+#define sample_interval_usec one_second_usec
+
+#define percent_time(used, period) ((double)(used) / (double)(period) * 100.0 )
+
+static int print_count_samples(
+       const struct profile_stats * const current,
+       const struct profile_stats * const last,
+       SMB_BIG_UINT delta_usec)
+{
+       int i;
+       int count = 0;
+       unsigned step;
+       SMB_BIG_UINT spent;
+       int delta_sec;
+       const char * name;
+       char buf[40];
+
+       if (delta_usec == 0) {
+               return 0;
+       }
+
+       buf[0] = '\0';
+       delta_sec = usec_to_sec(delta_usec);
+
+       for (i = 0; i < PR_VALUE_MAX; ++i) {
+               step = current->count[i] - last->count[i];
+               spent = current->time[i] - last->time[i];
+
+               if (step) {
+                       ++count;
+
+                       name = profile_value_name(i);
+
+                       if (buf[0] == '\0') {
+                               snprintf(buf, sizeof(buf),
+                                       "%s %d/sec (%.2f%%)",
+                                       name, step / delta_sec,
+                                       percent_time(spent, delta_usec));
+                       } else {
+                               printf("%-40s %s %d/sec (%.2f%%)\n",
+                                       buf, name, step / delta_sec,
+                                       percent_time(spent, delta_usec));
+                               buf[0] = '\0';
+                       }
+               }
+       }
+
+       return count;
+}
+
+static struct profile_stats    sample_data[2];
+static SMB_BIG_UINT            sample_time[2];
+
+BOOL status_profile_rates(BOOL verbose)
+{
+       SMB_BIG_UINT remain_usec;
+       SMB_BIG_UINT next_usec;
+       SMB_BIG_UINT delta_usec;
+
+       int last = 0;
+       int current = 1;
+       int tmp;
+
+       if (verbose) {
+           fprintf(stderr, "Sampling stats at %d sec intervals\n",
+                   usec_to_sec(sample_interval_usec));
+       }
+
+       if (!profile_setup(True)) {
+               fprintf(stderr,"Failed to initialise profile memory\n");
+               return False;
+       }
+
+       memcpy(&sample_data[last], profile_p, sizeof(*profile_p));
+       for (;;) {
+               sample_time[current] = profile_timestamp();
+               next_usec = sample_time[current] + sample_interval_usec;
+
+               /* Take a sample. */
+               memcpy(&sample_data[current], profile_p, sizeof(*profile_p));
+
+               /* Rate convert some values and print results. */
+               delta_usec = sample_time[current] - sample_time[last];
+
+               if (print_count_samples(&sample_data[current],
+                       &sample_data[last], delta_usec)) {
+                       printf("\n");
+               }
+
+               /* Swap sampling buffers. */
+               tmp = last;
+               last = current;
+               current = tmp;
+
+               /* Delay until next sample time. */
+               remain_usec = next_usec - profile_timestamp();
+               if (remain_usec > sample_interval_usec) {
+                       fprintf(stderr, "eek! falling behind sampling rate!\n");
+               } else {
+                       if (verbose) {
+                           fprintf(stderr,
+                                   "delaying for %lu msec\n",
+                                   (unsigned long )usec_to_msec(remain_usec));
+                       }
+
+                       sample_delay(usec_to_msec(remain_usec));
+               }
+
+       }
+
+       return True;
+}
+
+#else /* WITH_PROFILE */
+
+BOOL status_profile_rates(BOOL verbose)
+{
+       fprintf(stderr, "Profile data unavailable\n");
+       return False;
+}
+
+#endif /* WITH_PROFILE */
+
index d259717da0bfd25208812e7404cb9ca48281bd97..b53e139ca94496ed420b884f8b78bebe977ad181 100644 (file)
@@ -60,16 +60,16 @@ BOOL nmbd_running(void)
    then closing it */
 BOOL smbd_running(void)
 {
-       static struct cli_state cli;
+       struct cli_state *cli;
 
-       if (!cli_initialise(&cli))
+       if ((cli = cli_initialise()) == NULL)
                return False;
 
-       if (!cli_connect(&cli, global_myname(), &loopback_ip)) {
-               cli_shutdown(&cli);
+       if (!cli_connect(cli, global_myname(), &loopback_ip)) {
+               cli_shutdown(cli);
                return False;
        }
 
-       cli_shutdown(&cli);
+       cli_shutdown(cli);
        return True;
 }
index fb79f41f13c9ac9a87e3e00bb4d7f947728461cd..207614655db8a709cb0d547c5309388803307497 100644 (file)
@@ -57,8 +57,8 @@ static int qsort_cmp_list(const void *x, const void *y) {
        struct pri_list *a = (struct pri_list *)x;
        struct pri_list *b = (struct pri_list *)y;
        if (a->pri > b->pri) return -1;
-       if (a->pri == b->pri) return 0;
-       return 1;
+       if (a->pri < b->pri) return 1;
+       return 0;
 }
 
 /*
index d1fd0b4f9bc702d6128e23e84a0517d71903d84d..d43f8941bc14d2c39ddaeb5764c3031bb9aee3a7 100644 (file)
@@ -432,7 +432,7 @@ static void write_config(FILE *f, BOOL show_defaults)
 {
        fprintf(f, "# Samba config file created using SWAT\n");
        fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
-       fprintf(f, "# Date: %s\n\n", timestring(False));
+       fprintf(f, "# Date: %s\n\n", current_timestring(False));
        
        lp_dump(f, show_defaults, iNumNonAutoPrintServices);
 }