summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2006-07-11 18:01:26 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:19:14 -0500
commit9dafb7f48ca3e7af956b0a7d1720c2546fc4cfb8 (patch)
tree8e6f198af4605246bd3681c25826d8efe5c0d08b /source
parentf131bf8f16fd8b7c49e6065ecbf6f8686b2f4269 (diff)
downloadsamba-9dafb7f48ca3e7af956b0a7d1720c2546fc4cfb8.tar.gz
r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need
to do the upper layer directories but this is what everyone is waiting for.... Jeremy.
Diffstat (limited to 'source')
-rw-r--r--source/Doxyfile6
-rw-r--r--source/Makefile.in109
-rw-r--r--source/aclocal.m494
-rw-r--r--source/auth/auth_domain.c11
-rw-r--r--source/auth/auth_server.c9
-rw-r--r--source/auth/auth_util.c104
-rw-r--r--source/client/client.c2
-rw-r--r--source/client/clitar.c4
-rwxr-xr-xsource/client/mount.cifs.c10
-rw-r--r--source/client/smbctool.c2
-rw-r--r--source/client/smbmount.c2
-rw-r--r--source/configure.in133
-rw-r--r--source/include/client.h4
-rw-r--r--source/include/idmap.h30
-rw-r--r--source/include/includes.h18
-rw-r--r--source/include/libsmb_internal.h2
-rw-r--r--source/include/locking.h88
-rw-r--r--source/include/mangle.h12
-rw-r--r--source/include/nt_status.h9
-rw-r--r--source/include/ntdomain.h10
-rw-r--r--source/include/nterr.h3
-rw-r--r--source/include/passdb.h8
-rw-r--r--source/include/rpc_netlogon.h10
-rw-r--r--source/include/rpc_reg.h1
-rw-r--r--source/include/rpc_samr.h12
-rw-r--r--source/include/rpc_secdes.h36
-rw-r--r--source/include/rpc_srvsvc.h246
-rw-r--r--source/include/rpc_unixinfo.h172
-rw-r--r--source/include/session.h3
-rw-r--r--source/include/smb.h80
-rw-r--r--source/include/smb_macros.h31
-rw-r--r--source/include/smbprofile.h1041
-rw-r--r--source/include/talloc.h3
-rw-r--r--source/include/vfs.h129
-rw-r--r--source/include/vfs_macros.h350
-rw-r--r--source/lib/account_pol.c16
-rw-r--r--source/lib/afs.c7
-rw-r--r--source/lib/charcnv.c18
-rw-r--r--source/lib/data_blob.c2
-rw-r--r--source/lib/debug.c2
-rw-r--r--source/lib/popt_common.c10
-rw-r--r--source/lib/socket_wrapper.c17
-rw-r--r--source/lib/substitute.c182
-rw-r--r--source/lib/system.c78
-rw-r--r--source/lib/talloc.c7
-rw-r--r--source/lib/talloctort.c4
-rw-r--r--source/lib/time.c47
-rw-r--r--source/lib/util.c6
-rw-r--r--source/lib/util_reg.c110
-rw-r--r--source/lib/util_str.c122
-rw-r--r--source/libads/dns.c4
-rw-r--r--source/libads/ldap.c9
-rw-r--r--source/libads/sasl.c2
-rw-r--r--source/libmsrpc/cac_lsarpc.c2
-rw-r--r--source/libmsrpc/cac_samr.c18
-rw-r--r--source/libmsrpc/cac_svcctl.c2
-rw-r--r--source/libmsrpc/cac_winreg.c4
-rw-r--r--source/libmsrpc/libmsrpc_internal.c41
-rw-r--r--source/libndr/libndr.h296
-rw-r--r--source/libndr/misc.h37
-rw-r--r--source/libndr/ndr.c961
-rw-r--r--source/libndr/ndr_basic.c826
-rw-r--r--source/libndr/ndr_misc.c171
-rw-r--r--source/libndr/ndr_sec.h35
-rw-r--r--source/libndr/ndr_sec_helper.c187
-rw-r--r--source/libndr/ndr_string.c612
-rw-r--r--source/libndr/security.h260
-rw-r--r--source/libndr/sid.c97
-rw-r--r--source/libsmb/cliconnect.c39
-rw-r--r--source/libsmb/clidfs.c5
-rw-r--r--source/libsmb/clientgen.c40
-rw-r--r--source/libsmb/clikrb5.c2
-rw-r--r--source/libsmb/clirap2.c2
-rw-r--r--source/libsmb/libsmb_cache.c8
-rw-r--r--source/libsmb/libsmbclient.c224
-rw-r--r--source/libsmb/passchange.c108
-rw-r--r--source/libsmb/trusts_util.c2
-rw-r--r--source/locking/brlock.c304
-rw-r--r--source/locking/locking.c87
-rw-r--r--source/locking/posix.c1291
-rw-r--r--source/modules/charset_macosxfs.c2
-rw-r--r--source/modules/vfs_afsacl.c3
-rw-r--r--source/modules/vfs_audit.c60
-rw-r--r--source/modules/vfs_cacheprime.c200
-rw-r--r--source/modules/vfs_cap.c124
-rw-r--r--source/modules/vfs_catia.c80
-rw-r--r--source/modules/vfs_commit.c189
-rw-r--r--source/modules/vfs_default.c1327
-rw-r--r--source/modules/vfs_default_quota.c16
-rw-r--r--source/modules/vfs_expand_msdfs.c12
-rw-r--r--source/modules/vfs_extd_audit.c60
-rw-r--r--source/modules/vfs_fake_perms.c4
-rw-r--r--source/modules/vfs_full_audit.c335
-rw-r--r--source/modules/vfs_netatalk.c62
-rw-r--r--source/modules/vfs_prealloc.c214
-rw-r--r--source/modules/vfs_readonly.c5
-rw-r--r--source/modules/vfs_recycle.c64
-rw-r--r--source/modules/vfs_shadow_copy.c28
-rw-r--r--source/nmbd/nmbd_synclists.c33
-rw-r--r--source/nsswitch/pam_winbind.c30
-rw-r--r--source/nsswitch/wb_client.c110
-rw-r--r--source/nsswitch/wbinfo.c106
-rw-r--r--source/nsswitch/winbindd.c1
-rw-r--r--source/nsswitch/winbindd.h9
-rw-r--r--source/nsswitch/winbindd_ads.c1
-rw-r--r--source/nsswitch/winbindd_async.c173
-rw-r--r--source/nsswitch/winbindd_cache.c136
-rw-r--r--source/nsswitch/winbindd_cm.c2
-rw-r--r--source/nsswitch/winbindd_dual.c1
-rw-r--r--source/nsswitch/winbindd_nss.h3
-rw-r--r--source/nsswitch/winbindd_passdb.c64
-rw-r--r--source/nsswitch/winbindd_reconnect.c25
-rw-r--r--source/nsswitch/winbindd_rpc.c56
-rw-r--r--source/nsswitch/winbindd_sid.c40
-rw-r--r--source/nsswitch/winbindd_user.c18
-rw-r--r--source/nsswitch/winbindd_util.c2
-rw-r--r--source/param/loadparm.c42
-rw-r--r--source/passdb/login_cache.c2
-rw-r--r--source/passdb/lookup_sid.c184
-rw-r--r--source/passdb/passdb.c20
-rw-r--r--source/passdb/pdb_get_set.c21
-rw-r--r--source/passdb/pdb_interface.c16
-rw-r--r--source/passdb/pdb_ldap.c58
-rw-r--r--source/passdb/pdb_nds.c11
-rw-r--r--source/passdb/pdb_smbpasswd.c27
-rw-r--r--source/passdb/pdb_tdb.c43
-rw-r--r--source/passdb/secrets.c193
-rw-r--r--source/printing/nt_printing.c28
-rw-r--r--source/printing/print_generic.c11
-rw-r--r--source/printing/printfsp.c20
-rw-r--r--source/printing/printing.c45
-rw-r--r--source/profile/profile.c181
-rw-r--r--source/python/py_smb.c2
-rw-r--r--source/registry/reg_printing.c4
-rw-r--r--source/rpc_client/cli_lsarpc.c38
-rw-r--r--source/rpc_client/cli_srvsvc.c29
-rw-r--r--source/rpc_client/cli_unixinfo.c226
-rw-r--r--source/rpc_client/ndr.c90
-rw-r--r--source/rpc_parse/parse_eventlog.c2
-rw-r--r--source/rpc_parse/parse_lsa.c12
-rw-r--r--source/rpc_parse/parse_ntsvcs.c4
-rw-r--r--source/rpc_parse/parse_prs.c32
-rw-r--r--source/rpc_parse/parse_reg.c44
-rw-r--r--source/rpc_parse/parse_rpc.c11
-rw-r--r--source/rpc_parse/parse_samr.c50
-rw-r--r--source/rpc_parse/parse_shutdown.c10
-rw-r--r--source/rpc_parse/parse_spoolss.c2
-rw-r--r--source/rpc_parse/parse_srv.c524
-rw-r--r--source/rpc_parse/parse_svcctl.c14
-rw-r--r--source/rpc_parse/parse_unixinfo.c266
-rw-r--r--source/rpc_server/srv_dfs_nt.c10
-rw-r--r--source/rpc_server/srv_lsa_nt.c31
-rw-r--r--source/rpc_server/srv_pipe.c105
-rw-r--r--source/rpc_server/srv_pipe_hnd.c9
-rw-r--r--source/rpc_server/srv_samr_nt.c17
-rw-r--r--source/rpc_server/srv_samr_util.c35
-rw-r--r--source/rpc_server/srv_spoolss_nt.c98
-rw-r--r--source/rpc_server/srv_srvsvc.c33
-rw-r--r--source/rpc_server/srv_srvsvc_nt.c520
-rw-r--r--source/rpc_server/srv_svcctl_nt.c2
-rw-r--r--source/rpc_server/srv_unixinfo.c163
-rw-r--r--source/rpc_server/srv_unixinfo_nt.c166
-rw-r--r--source/rpcclient/cmd_samr.c2
-rw-r--r--source/rpcclient/cmd_spoolss.c28
-rw-r--r--source/rpcclient/cmd_unixinfo.c195
-rw-r--r--source/rpcclient/rpcclient.c2
-rw-r--r--source/sam/idmap.c106
-rw-r--r--source/sam/idmap_ad.c14
-rw-r--r--source/sam/idmap_ldap.c41
-rw-r--r--source/sam/idmap_rid.c13
-rw-r--r--source/sam/idmap_smbldap.c10
-rw-r--r--source/sam/idmap_tdb.c436
-rw-r--r--source/sam/idmap_util.c61
-rw-r--r--source/script/mkproto.awk12
-rwxr-xr-xsource/script/mkproto.sh2
-rwxr-xr-xsource/script/tests/selftest.sh14
-rwxr-xr-xsource/script/tests/test_posix_s3.sh5
-rwxr-xr-xsource/script/tests/test_smbtorture_s3.sh2
-rw-r--r--source/services/svc_netlogon.c4
-rw-r--r--source/smbd/blocking.c40
-rw-r--r--source/smbd/change_trust_pw.c4
-rw-r--r--source/smbd/conn.c8
-rw-r--r--source/smbd/connection.c169
-rw-r--r--source/smbd/dir.c21
-rw-r--r--source/smbd/dosmode.c7
-rw-r--r--source/smbd/error.c54
-rw-r--r--source/smbd/fake_file.c23
-rw-r--r--source/smbd/filename.c22
-rw-r--r--source/smbd/files.c70
-rw-r--r--source/smbd/lanman.c45
-rw-r--r--source/smbd/mangle.c28
-rw-r--r--source/smbd/mangle_hash.c18
-rw-r--r--source/smbd/mangle_hash2.c44
-rw-r--r--source/smbd/mangle_map.c4
-rw-r--r--source/smbd/message.c3
-rw-r--r--source/smbd/msdfs.c8
-rw-r--r--source/smbd/nttrans.c98
-rw-r--r--source/smbd/open.c229
-rw-r--r--source/smbd/password.c19
-rw-r--r--source/smbd/pipes.c17
-rw-r--r--source/smbd/posix_acls.c12
-rw-r--r--source/smbd/process.c23
-rw-r--r--source/smbd/reply.c172
-rw-r--r--source/smbd/server.c6
-rw-r--r--source/smbd/service.c63
-rw-r--r--source/smbd/session.c45
-rw-r--r--source/smbd/share_access.c5
-rw-r--r--source/smbd/statcache.c8
-rw-r--r--source/smbd/statvfs.c4
-rw-r--r--source/smbd/trans2.c83
-rw-r--r--source/smbd/uid.c4
-rw-r--r--source/smbd/vfs-wrap.c1104
-rw-r--r--source/smbd/vfs.c217
-rw-r--r--source/smbwrapper/smbw.c36
-rw-r--r--source/smbwrapper/smbw.h2
-rw-r--r--source/tdb/dump.c135
-rw-r--r--source/tdb/error.c58
-rw-r--r--source/tdb/freelist.c331
-rw-r--r--source/tdb/io.c412
-rw-r--r--source/tdb/lock.c276
-rw-r--r--source/tdb/open.c453
-rw-r--r--source/tdb/spinlock.c472
-rw-r--r--source/tdb/spinlock.h59
-rw-r--r--source/tdb/tdb.c1941
-rw-r--r--source/tdb/tdb.h146
-rw-r--r--source/tdb/tdb_private.h241
-rw-r--r--source/tdb/tdbback.c6
-rw-r--r--source/tdb/tdbutil.c186
-rw-r--r--source/tdb/tdbutil.h38
-rw-r--r--source/tdb/transaction.c1043
-rw-r--r--source/tdb/traverse.c334
-rw-r--r--source/torture/cmd_vfs.c24
-rw-r--r--source/torture/locktest.c12
-rw-r--r--source/torture/locktest2.c1
-rw-r--r--source/torture/masktest.c2
-rw-r--r--source/torture/nsstest.c52
-rw-r--r--source/torture/pdbtest.c392
-rw-r--r--source/torture/rpctorture.c2
-rw-r--r--source/torture/scanner.c12
-rw-r--r--source/torture/torture.c126
-rw-r--r--source/torture/vfstest.c2
-rw-r--r--source/utils/debug2html.c4
-rw-r--r--source/utils/net.c8
-rw-r--r--source/utils/net_ads.c11
-rw-r--r--source/utils/net_idmap.c26
-rw-r--r--source/utils/net_rpc.c23
-rw-r--r--source/utils/net_rpc_printer.c25
-rw-r--r--source/utils/net_rpc_registry.c67
-rw-r--r--source/utils/net_rpc_samsync.c30
-rw-r--r--source/utils/net_time.c10
-rw-r--r--source/utils/ntlm_auth.c2
-rw-r--r--source/utils/ntlm_auth_diagnostics.c8
-rw-r--r--source/utils/sharesec.c414
-rw-r--r--source/utils/smbcontrol.c2
-rw-r--r--source/utils/status.c390
-rw-r--r--source/utils/status_profile.c544
-rw-r--r--source/web/diagnose.c10
-rw-r--r--source/web/neg_lang.c4
-rw-r--r--source/web/swat.c2
259 files changed, 19090 insertions, 9042 deletions
diff --git a/source/Doxyfile b/source/Doxyfile
index c1040781d84..cdcb658908a 100644
--- a/source/Doxyfile
+++ b/source/Doxyfile
@@ -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 =
diff --git a/source/Makefile.in b/source/Makefile.in
index 127936125bf..3f586180f04 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -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; \
diff --git a/source/aclocal.m4 b/source/aclocal.m4
index af7ed7b4068..1f2120c68b3 100644
--- a/source/aclocal.m4
+++ b/source/aclocal.m4
@@ -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
+ ])
+])
+
diff --git a/source/auth/auth_domain.c b/source/auth/auth_domain.c
index bedd318c3c3..8ad6329da98 100644
--- a/source/auth/auth_domain.c
+++ b/source/auth/auth_domain.c
@@ -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;
}
diff --git a/source/auth/auth_server.c b/source/auth/auth_server.c
index 7bec1b4128d..6e4dba0be2d 100644
--- a/source/auth/auth_server.c
+++ b/source/auth/auth_server.c
@@ -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;
diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c
index 493d7393d07..823bf8c3228 100644
--- a/source/auth/auth_util.c
+++ b/source/auth/auth_util.c
@@ -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
diff --git a/source/client/client.c b/source/client/client.c
index 3c2d7afe2d6..99fffa71232 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -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;
diff --git a/source/client/clitar.c b/source/client/clitar.c
index 14c28acfc5a..f0d0ac595c2 100644
--- a/source/client/clitar.c
+++ b/source/client/clitar.c
@@ -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. */
diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c
index ac98b992bb2..ab1f203412f 100755
--- a/source/client/mount.cifs.c
+++ b/source/client/mount.cifs.c
@@ -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);
diff --git a/source/client/smbctool.c b/source/client/smbctool.c
index fd385ee6817..b7042f99cb2 100644
--- a/source/client/smbctool.c
+++ b/source/client/smbctool.c
@@ -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;
diff --git a/source/client/smbmount.c b/source/client/smbmount.c
index 7a3ccb7630d..f1cd81198f0 100644
--- a/source/client/smbmount.c
+++ b/source/client/smbmount.c
@@ -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) {
diff --git a/source/configure.in b/source/configure.in
index 884c2cea6ab..5359ff8bf41 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -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])
@@ -5593,6 +5621,89 @@ if test "${ac_cv_prog_CC}" = "insure"; then
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
AC_MSG_RESULT([Using libraries:])
diff --git a/source/include/client.h b/source/include/client.h
index c6d7b162fcd..d11d198e1a5 100644
--- a/source/include/client.h
+++ b/source/include/client.h
@@ -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
diff --git a/source/include/idmap.h b/source/include/idmap.h
index 474982f2926..ee248ef26f2 100644
--- a/source/include/idmap.h
+++ b/source/include/idmap.h
@@ -24,32 +24,32 @@
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);
diff --git a/source/include/includes.h b/source/include/includes.h
index 59e8e5cd0fb..ab2f6a96410 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -101,6 +101,10 @@
#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"
diff --git a/source/include/libsmb_internal.h b/source/include/libsmb_internal.h
index 5aca12554f3..42bf2373c1b 100644
--- a/source/include/libsmb_internal.h
+++ b/source/include/libsmb_internal.h
@@ -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
index 00000000000..983d59a853f
--- /dev/null
+++ b/source/include/locking.h
@@ -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_ */
diff --git a/source/include/mangle.h b/source/include/mangle.h
index 2bdef4ad646..3d19ef9ed4f 100644
--- a/source/include/mangle.h
+++ b/source/include/mangle.h
@@ -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_ */
diff --git a/source/include/nt_status.h b/source/include/nt_status.h
index 14c83eba4b3..c48beafb6e7 100644
--- a/source/include/nt_status.h
+++ b/source/include/nt_status.h
@@ -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
diff --git a/source/include/ntdomain.h b/source/include/ntdomain.h
index c27ec3675b4..0114df0e2d0 100644
--- a/source/include/ntdomain.h
+++ b/source/include/ntdomain.h
@@ -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;
diff --git a/source/include/nterr.h b/source/include/nterr.h
index 417719625e7..6cf5a756d29 100644
--- a/source/include/nterr.h
+++ b/source/include/nterr.h
@@ -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. */
diff --git a/source/include/passdb.h b/source/include/passdb.h
index 74063d0fff1..35bb93aa31c 100644
--- a/source/include/passdb.h
+++ b/source/include/passdb.h
@@ -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;
diff --git a/source/include/rpc_netlogon.h b/source/include/rpc_netlogon.h
index 9df7701de41..f80dc3121d1 100644
--- a/source/include/rpc_netlogon.h
+++ b/source/include/rpc_netlogon.h
@@ -43,11 +43,6 @@
#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
@@ -66,11 +61,6 @@
#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
diff --git a/source/include/rpc_reg.h b/source/include/rpc_reg.h
index c454a1d6f94..883e2a8146a 100644
--- a/source/include/rpc_reg.h
+++ b/source/include/rpc_reg.h
@@ -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
diff --git a/source/include/rpc_samr.h b/source/include/rpc_samr.h
index 910ccee1135..ed4e51837f7 100644
--- a/source/include/rpc_samr.h
+++ b/source/include/rpc_samr.h
@@ -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;
diff --git a/source/include/rpc_secdes.h b/source/include/rpc_secdes.h
index c385e41fd30..2ac60bd9b12 100644
--- a/source/include/rpc_secdes.h
+++ b/source/include/rpc_secdes.h
@@ -43,33 +43,6 @@
#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.
*/
@@ -80,11 +53,6 @@
#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
diff --git a/source/include/rpc_srvsvc.h b/source/include/rpc_srvsvc.h
index f84054b878b..31032f64a4d 100644
--- a/source/include/rpc_srvsvc.h
+++ b/source/include/rpc_srvsvc.h
@@ -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
index 00000000000..f2f4382fc47
--- /dev/null
+++ b/source/include/rpc_unixinfo.h
@@ -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
diff --git a/source/include/session.h b/source/include/session.h
index f613afee09a..8c8faab5325 100644
--- a/source/include/session.h
+++ b/source/include/session.h
@@ -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;
};
diff --git a/source/include/smb.h b/source/include/smb.h
index e0f2e8483cb..3109948f59e 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -52,11 +52,6 @@
#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
diff --git a/source/include/smb_macros.h b/source/include/smb_macros.h
index 554dbbc0878..e296ddd1403 100644
--- a/source/include/smb_macros.h
+++ b/source/include/smb_macros.h
@@ -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
@@ -93,20 +91,24 @@
#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)
@@ -122,7 +124,7 @@
/* 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 */
@@ -133,10 +135,10 @@
#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))
@@ -182,7 +184,6 @@
#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 */
diff --git a/source/include/smbprofile.h b/source/include/smbprofile.h
index b8a9a49be1a..d29f066796b 100644
--- a/source/include/smbprofile.h
+++ b/source/include/smbprofile.h
@@ -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
@@ -26,102 +27,711 @@
#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 {
diff --git a/source/include/talloc.h b/source/include/talloc.h
index 17032ac7acc..db88ce6ed56 100644
--- a/source/include/talloc.h
+++ b/source/include/talloc.h
@@ -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);
diff --git a/source/include/vfs.h b/source/include/vfs.h
index fb99d824125..6ef9e829bcc 100644
--- a/source/include/vfs.h
+++ b/source/include/vfs.h
@@ -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"
diff --git a/source/include/vfs_macros.h b/source/include/vfs_macros.h
index e08b386a6ac..2d6f8580f68 100644
--- a/source/include/vfs_macros.h
+++ b/source/include/vfs_macros.h
@@ -28,26 +28,26 @@
********************************************************************/
/* 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)))
@@ -55,27 +55,27 @@
#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)))
@@ -84,44 +84,44 @@
#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. */
@@ -140,26 +140,26 @@
********************************************************************/
/* 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)))
@@ -167,27 +167,27 @@
#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)))
@@ -196,44 +196,44 @@
#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. */
@@ -252,27 +252,27 @@
********************************************************************/
/* 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)))
@@ -280,27 +280,27 @@
#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)))
@@ -309,44 +309,44 @@
#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. */
diff --git a/source/lib/account_pol.c b/source/lib/account_pol.c
index 6bf7346fe7f..8d844741f5d 100644
--- a/source/lib/account_pol.c
+++ b/source/lib/account_pol.c
@@ -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 */
diff --git a/source/lib/afs.c b/source/lib/afs.c
index 8a304adcf0c..ea83fdebc25 100644
--- a/source/lib/afs.c
+++ b/source/lib/afs.c
@@ -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));
diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c
index 097d746a638..fffdf010a05 100644
--- a/source/lib/charcnv.c
+++ b/source/lib/charcnv.c
@@ -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;
diff --git a/source/lib/data_blob.c b/source/lib/data_blob.c
index ccd0d27f47b..860ef5ad10f 100644
--- a/source/lib/data_blob.c
+++ b/source/lib/data_blob.c
@@ -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);
diff --git a/source/lib/debug.c b/source/lib/debug.c
index 2b6c42b8eb0..bf75bdf3d3f 100644
--- a/source/lib/debug.c
+++ b/source/lib/debug.c
@@ -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 );
}
diff --git a/source/lib/popt_common.c b/source/lib/popt_common.c
index d29e171be08..0c0ed86dd1f 100644
--- a/source/lib/popt_common.c
+++ b/source/lib/popt_common.c
@@ -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" },
diff --git a/source/lib/socket_wrapper.c b/source/lib/socket_wrapper.c
index e9c1404d113..04c337267fd 100644
--- a/source/lib/socket_wrapper.c
+++ b/source/lib/socket_wrapper.c
@@ -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,
diff --git a/source/lib/substitute.c b/source/lib/substitute.c
index ff9deb8a5f0..430c8029b8f 100644
--- a/source/lib/substitute.c
+++ b/source/lib/substitute.c
@@ -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 );
diff --git a/source/lib/system.c b/source/lib/system.c
index 2e5f42307bd..24c726b8f75 100644
--- a/source/lib/system.c
+++ b/source/lib/system.c
@@ -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);
diff --git a/source/lib/talloc.c b/source/lib/talloc.c
index 51087ef9791..9d824411379 100644
--- a/source/lib/talloc.c
+++ b/source/lib/talloc.c
@@ -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;
diff --git a/source/lib/talloctort.c b/source/lib/talloctort.c
index 6504203a7ad..3ce45e20714 100644
--- a/source/lib/talloctort.c
+++ b/source/lib/talloctort.c
@@ -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();
diff --git a/source/lib/time.c b/source/lib/time.c
index 9a539d415e8..0bfdfac856b 100644
--- a/source/lib/time.c
+++ b/source/lib/time.c
@@ -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.
diff --git a/source/lib/util.c b/source/lib/util.c
index a1efecfbbba..96263bf3947 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -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
index 00000000000..3f0b2d6a42c
--- /dev/null
+++ b/source/lib/util_reg.c
@@ -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;
+}
diff --git a/source/lib/util_str.c b/source/lib/util_str.c
index 938fb0f47b0..2580521c3b9 100644
--- a/source/lib/util_str.c
+++ b/source/lib/util_str.c
@@ -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;
+}
+
diff --git a/source/libads/dns.c b/source/libads/dns.c
index d2e263a9d1b..321b4355277 100644
--- a/source/libads/dns.c
+++ b/source/libads/dns.c
@@ -39,8 +39,12 @@
#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
diff --git a/source/libads/ldap.c b/source/libads/ldap.c
index b017ff941b9..58eca99f9e1 100644
--- a/source/libads/ldap.c
+++ b/source/libads/ldap.c
@@ -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);
}
/**
diff --git a/source/libads/sasl.c b/source/libads/sasl.c
index a12af43eb37..3c0bea93d6c 100644
--- a/source/libads/sasl.c
+++ b/source/libads/sasl.c
@@ -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);
diff --git a/source/libmsrpc/cac_lsarpc.c b/source/libmsrpc/cac_lsarpc.c
index 7b62b4d4627..72c429e7247 100644
--- a/source/libmsrpc/cac_lsarpc.c
+++ b/source/libmsrpc/cac_lsarpc.c
@@ -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;
diff --git a/source/libmsrpc/cac_samr.c b/source/libmsrpc/cac_samr.c
index 60c6562988e..a29ee7a41eb 100644
--- a/source/libmsrpc/cac_samr.c
+++ b/source/libmsrpc/cac_samr.c
@@ -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;
diff --git a/source/libmsrpc/cac_svcctl.c b/source/libmsrpc/cac_svcctl.c
index 83dc0364930..51a5b5d2dd9 100644
--- a/source/libmsrpc/cac_svcctl.c
+++ b/source/libmsrpc/cac_svcctl.c
@@ -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;
}
diff --git a/source/libmsrpc/cac_winreg.c b/source/libmsrpc/cac_winreg.c
index 6ef898eb16d..91db33d2953 100644
--- a/source/libmsrpc/cac_winreg.c
+++ b/source/libmsrpc/cac_winreg.c
@@ -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;
}
diff --git a/source/libmsrpc/libmsrpc_internal.c b/source/libmsrpc/libmsrpc_internal.c
index 3a47361db29..a097bc181ce 100644
--- a/source/libmsrpc/libmsrpc_internal.c
+++ b/source/libmsrpc/libmsrpc_internal.c
@@ -23,30 +23,33 @@
#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
index 00000000000..817c4610751
--- /dev/null
+++ b/source/libndr/libndr.h
@@ -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
index 00000000000..d929379870f
--- /dev/null
+++ b/source/libndr/misc.h
@@ -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
index 00000000000..2aff7a88f0a
--- /dev/null
+++ b/source/libndr/ndr.c
@@ -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
index 00000000000..31a48f67c45
--- /dev/null
+++ b/source/libndr/ndr_basic.c
@@ -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
index 00000000000..2f9004ae666
--- /dev/null
+++ b/source/libndr/ndr_misc.c
@@ -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
index 00000000000..0858eac72c5
--- /dev/null
+++ b/source/libndr/ndr_sec.h
@@ -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
index 00000000000..edbdd9a40eb
--- /dev/null
+++ b/source/libndr/ndr_sec_helper.c
@@ -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
index 00000000000..d6c842a6537
--- /dev/null
+++ b/source/libndr/ndr_string.c
@@ -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
index 00000000000..8f790f387ed
--- /dev/null
+++ b/source/libndr/security.h
@@ -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
index 00000000000..0bb42a3683b
--- /dev/null
+++ b/source/libndr/sid.c
@@ -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;
+}
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index 7f5b5d7fa57..4c3c4f45650 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -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;
}
}
diff --git a/source/libsmb/clidfs.c b/source/libsmb/clidfs.c
index e564bc42957..4280b0628eb 100644
--- a/source/libsmb/clidfs.c
+++ b/source/libsmb/clidfs.c
@@ -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;
diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c
index 8342df0f1d1..4608d40d462 100644
--- a/source/libsmb/clientgen.c
+++ b/source/libsmb/clientgen.c
@@ -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);
}
/****************************************************************************
diff --git a/source/libsmb/clikrb5.c b/source/libsmb/clikrb5.c
index abb3843bacb..d40fc31dc44 100644
--- a/source/libsmb/clikrb5.c
+++ b/source/libsmb/clikrb5.c
@@ -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)
{
diff --git a/source/libsmb/clirap2.c b/source/libsmb/clirap2.c
index 147683689d6..3c23310f66c 100644
--- a/source/libsmb/clirap2.c
+++ b/source/libsmb/clirap2.c
@@ -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;
diff --git a/source/libsmb/libsmb_cache.c b/source/libsmb/libsmb_cache.c
index 5d948ea5e25..8c4fd7c89f7 100644
--- a/source/libsmb/libsmb_cache.c
+++ b/source/libsmb/libsmb_cache.c
@@ -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;
}
diff --git a/source/libsmb/libsmbclient.c b/source/libsmb/libsmbclient.c
index ca2624305e6..db788f46e9b 100644
--- a/source/libsmb/libsmbclient.c
+++ b/source/libsmb/libsmbclient.c
@@ -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) {
/*
diff --git a/source/libsmb/passchange.c b/source/libsmb/passchange.c
index 673671d28db..0d3dcf4d755 100644
--- a/source/libsmb/passchange.c
+++ b/source/libsmb/passchange.c
@@ -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;
}
}
diff --git a/source/libsmb/trusts_util.c b/source/libsmb/trusts_util.c
index 55108bf72f2..e4061883eb1 100644
--- a/source/libsmb/trusts_util.c
+++ b/source/libsmb/trusts_util.c
@@ -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.
diff --git a/source/locking/brlock.c b/source/locking/brlock.c
index 574552e9e21..9c8a7a17ee6 100644
--- a/source/locking/brlock.c
+++ b/source/locking/brlock.c
@@ -32,29 +32,6 @@
#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;
}
diff --git a/source/locking/locking.c b/source/locking/locking.c
index 9d3ca956014..ac50c9b648f 100644
--- a/source/locking/locking.c
+++ b/source/locking/locking.c
@@ -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);
}
diff --git a/source/locking/posix.c b/source/locking/posix.c
index 4a5f59b622d..59b62170e82 100644
--- a/source/locking/posix.c
+++ b/source/locking/posix.c
@@ -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
@@ -28,481 +28,17 @@
#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;
-};
-
-/*******************************************************************
- Form a static locking key for a dev/inode pair.
-******************************************************************/
-
-static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
-{
- static struct posix_lock_key key;
- TDB_DATA kbuf;
-
- memset(&key, '\0', sizeof(key));
- key.device = dev;
- key.inode = inode;
- kbuf.dptr = (char *)&key;
- kbuf.dsize = sizeof(key);
- return kbuf;
-}
-
-/*******************************************************************
- Convenience function to get a key from an fsp.
-******************************************************************/
-
-static TDB_DATA locking_key_fsp(files_struct *fsp)
-{
- return locking_key(fsp->dev, fsp->inode);
-}
-
-/****************************************************************************
- Add an fd to the pending close tdb.
-****************************************************************************/
-
-static BOOL add_fd_to_close_entry(files_struct *fsp)
-{
- TDB_DATA kbuf = locking_key_fsp(fsp);
- TDB_DATA dbuf;
-
- dbuf.dptr = NULL;
- dbuf.dsize = 0;
-
- dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
-
- dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int));
- if (!dbuf.dptr) {
- DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n"));
- return False;
- }
-
- memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int));
- dbuf.dsize += sizeof(int);
-
- if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
- DEBUG(0,("add_fd_to_close_entry: tdb_store fail !\n"));
- }
-
- SAFE_FREE(dbuf.dptr);
- return True;
-}
-
-/****************************************************************************
- Remove all fd entries for a specific dev/inode pair from the tdb.
-****************************************************************************/
-
-static void delete_close_entries(files_struct *fsp)
-{
- TDB_DATA kbuf = locking_key_fsp(fsp);
-
- if (tdb_delete(posix_pending_close_tdb, kbuf) == -1)
- DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));
-}
-
-/****************************************************************************
- Get the array of POSIX pending close records for an open fsp. Caller must
- free. Returns number of entries.
-****************************************************************************/
-
-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;
-
- *entries = NULL;
- dbuf.dptr = NULL;
-
- dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
-
- if (!dbuf.dptr) {
- return 0;
- }
-
- *entries = (int *)dbuf.dptr;
- count = (size_t)(dbuf.dsize / sizeof(int));
-
- return count;
-}
-
-/****************************************************************************
- Get the array of POSIX locks for an fsp. Caller must free. Returns
- number of entries.
-****************************************************************************/
-
-static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entries)
-{
- TDB_DATA kbuf = locking_key_fsp(fsp);
- TDB_DATA dbuf;
- size_t count = 0;
-
- *entries = NULL;
-
- dbuf.dptr = NULL;
-
- dbuf = tdb_fetch(posix_lock_tdb, kbuf);
-
- if (!dbuf.dptr) {
- return 0;
- }
-
- *entries = (struct posix_lock *)dbuf.dptr;
- count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
-
- return count;
-}
-
-/****************************************************************************
- 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.
-****************************************************************************/
-
-int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
-{
- 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.
- */
-
- count = get_posix_lock_entries(fsp, &entries);
-
- /*
- * 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*.
- */
-
- for (i = 0; i < count; i++) {
- if (entries[i].fd != fsp->fh->fd) {
- locks_on_other_fds = True;
- break;
- }
- }
-
- 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;
- }
-
- SAFE_FREE(entries);
- fsp->fh->fd = -1;
- return 0;
- }
-
- SAFE_FREE(entries);
-
- /*
- * No outstanding POSIX locks. Get the pending close fd's
- * from the tdb and close them all.
- */
-
- count = get_posix_pending_close_entries(fsp, &fd_array);
-
- if (count) {
- DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count ));
-
- for(i = 0; i < count; i++) {
- if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) {
- saved_errno = errno;
- }
- }
-
- /*
- * Delete all fd's stored in the tdb
- * for this dev/inode pair.
- */
-
- delete_close_entries(fsp);
- }
-
- SAFE_FREE(fd_array);
-
- /*
- * Finally close the fd associated with this fsp.
- */
-
- ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
-
- if (saved_errno != 0) {
- errno = saved_errno;
- ret = -1;
- }
-
- fsp->fh->fd = -1;
-
- return ret;
-}
-
/****************************************************************************
- Debugging aid :-).
+ 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.
****************************************************************************/
-static const char *posix_lock_type_name(int lock_type)
-{
- return (lock_type == F_RDLCK) ? "READ" : "WRITE";
-}
-
-/****************************************************************************
- Delete a POSIX lock entry by index number. Used if the tdb add succeeds, but
- then the POSIX fcntl lock fails.
-****************************************************************************/
-
-static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry)
-{
- TDB_DATA kbuf = locking_key_fsp(fsp);
- TDB_DATA dbuf;
- struct posix_lock *locks;
- size_t count;
-
- dbuf.dptr = NULL;
-
- dbuf = tdb_fetch(posix_lock_tdb, kbuf);
-
- if (!dbuf.dptr) {
- DEBUG(10,("delete_posix_lock_entry_by_index: tdb_fetch failed !\n"));
- goto fail;
- }
-
- 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);
- }
-
- SAFE_FREE(dbuf.dptr);
-
- return True;
-
- fail:
-
- SAFE_FREE(dbuf.dptr);
- return False;
-}
-
-/****************************************************************************
- 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.
-****************************************************************************/
-
-static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type, size_t *pentry_num)
-{
- TDB_DATA kbuf = locking_key_fsp(fsp);
- TDB_DATA dbuf;
- struct posix_lock pl;
-
- dbuf.dptr = NULL;
- dbuf.dsize = 0;
-
- dbuf = tdb_fetch(posix_lock_tdb, kbuf);
-
- *pentry_num = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
-
- /*
- * Add new record.
- */
-
- pl.fd = fsp->fh->fd;
- pl.start = start;
- pl.size = size;
- pl.lock_type = lock_type;
-
- dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(struct posix_lock));
- if (!dbuf.dptr) {
- DEBUG(0,("add_posix_lock_entry: Realloc fail !\n"));
- goto fail;
- }
-
- memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(struct posix_lock));
- dbuf.dsize += sizeof(struct posix_lock);
-
- 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;
- }
-
- 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;
-}
-
-/****************************************************************************
- 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.
-****************************************************************************/
-
-static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, struct posix_lock *pl)
-{
- TDB_DATA kbuf = locking_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);
-
- if (!dbuf.dptr) {
- DEBUG(10,("delete_posix_lock_entry: tdb_fetch failed !\n"));
- goto fail;
- }
-
- /* 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;
- }
- }
-
- 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++;
- }
-
- 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;
-}
-
/****************************************************************************
Utility function to map a lock type correctly depending on the open
mode of a file.
@@ -519,16 +55,6 @@ static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type)
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
/*
* This return should be the most normal, as we attempt
@@ -539,6 +65,15 @@ static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type)
}
/****************************************************************************
+ Debugging aid :-).
+****************************************************************************/
+
+static const char *posix_lock_type_name(int lock_type)
+{
+ return (lock_type == F_RDLCK) ? "READ" : "WRITE";
+}
+
+/****************************************************************************
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.
@@ -608,15 +143,17 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
* We must truncate the count to less than max_positive_lock_offset.
*/
- if (u_count & ~((SMB_BIG_UINT)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)
+ 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.
@@ -729,7 +266,6 @@ static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T
return ret;
}
-
/****************************************************************************
POSIX function to see if a file region is locked. Returns True if the
region is locked, False otherwise.
@@ -774,6 +310,411 @@ BOOL is_posix_locked(files_struct *fsp,
return True;
}
+/****************************************************************************
+ Next - the functions that deal with in memory database storing representations
+ of either Windows CIFS locks or POSIX CIFS locks.
+****************************************************************************/
+
+/* The key used in the in-memory POSIX databases. */
+
+struct lock_ref_count_key {
+ SMB_DEV_T device;
+ SMB_INO_T inode;
+ char r;
+};
+
+struct fd_key {
+ SMB_DEV_T device;
+ SMB_INO_T inode;
+};
+
+/*******************************************************************
+ Form a static locking key for a dev/inode pair for the fd array.
+******************************************************************/
+
+static TDB_DATA fd_array_key(SMB_DEV_T dev, SMB_INO_T inode)
+{
+ static struct fd_key key;
+ TDB_DATA kbuf;
+
+ memset(&key, '\0', sizeof(key));
+ key.device = dev;
+ key.inode = inode;
+ kbuf.dptr = (char *)&key;
+ kbuf.dsize = sizeof(key);
+ return kbuf;
+}
+
+/*******************************************************************
+ Form a static locking key for a dev/inode pair for the lock ref count
+******************************************************************/
+
+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;
+
+ memset(&key, '\0', sizeof(key));
+ key.device = dev;
+ key.inode = inode;
+ key.r = 'r';
+ kbuf.dptr = (char *)&key;
+ kbuf.dsize = sizeof(key);
+ return kbuf;
+}
+
+/*******************************************************************
+ Convenience function to get an fd_array key from an fsp.
+******************************************************************/
+
+static TDB_DATA fd_array_key_fsp(files_struct *fsp)
+{
+ return fd_array_key(fsp->dev, fsp->inode);
+}
+
+/*******************************************************************
+ Convenience function to get a lock ref count key from an fsp.
+******************************************************************/
+
+static TDB_DATA locking_ref_count_key_fsp(files_struct *fsp)
+{
+ return locking_ref_count_key(fsp->dev, fsp->inode);
+}
+
+/*******************************************************************
+ Create the in-memory POSIX lock databases.
+********************************************************************/
+
+BOOL posix_locking_init(int read_only)
+{
+ if (posix_pending_close_tdb) {
+ return True;
+ }
+
+ 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;
+ }
+
+ 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;
+}
+
+/****************************************************************************
+ Next - the functions that deal with storing fd's that have outstanding
+ POSIX locks when closed.
+****************************************************************************/
+
+/****************************************************************************
+ 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.
+****************************************************************************/
+
+/****************************************************************************
+ Keep a reference count of the number of Windows locks open on this dev/ino
+ pair. Creates entry if it doesn't exist.
+****************************************************************************/
+
+static void increment_windows_lock_ref_count(files_struct *fsp)
+{
+ TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
+ TDB_DATA dbuf;
+ int lock_ref_count;
+
+ 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);
+ }
+
+ 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);
+
+ DEBUG(10,("increment_windows_lock_ref_count for file now %s = %d\n",
+ fsp->fsp_name, lock_ref_count ));
+}
+
+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 = tdb_fetch(posix_pending_close_tdb, kbuf);
+ if (!dbuf.dptr) {
+ smb_panic("decrement_windows_lock_ref_count: logic error.\n");
+ }
+
+ memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
+ lock_ref_count--;
+ memcpy(dbuf.dptr, &lock_ref_count, sizeof(int));
+
+ 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,("decrement_windows_lock_ref_count for file now %s = %d\n",
+ fsp->fsp_name, lock_ref_count ));
+}
+
+/****************************************************************************
+ Ensure the lock ref count is zero.
+****************************************************************************/
+
+void zero_windows_lock_ref_count(files_struct *fsp)
+{
+ TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
+ TDB_DATA dbuf;
+ int lock_ref_count;
+
+ dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+ if (!dbuf.dptr) {
+ return;
+ }
+
+ 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");
+ }
+
+ 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");
+ }
+ SAFE_FREE(dbuf.dptr);
+
+ DEBUG(10,("zero_windows_lock_ref_count for file now %s = %d\n",
+ fsp->fsp_name, lock_ref_count ));
+}
+
+/****************************************************************************
+ Fetch the lock ref count.
+****************************************************************************/
+
+static int get_windows_lock_ref_count(files_struct *fsp)
+{
+ TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
+ TDB_DATA dbuf;
+ int lock_ref_count;
+
+ dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+ if (!dbuf.dptr) {
+ lock_ref_count = 0;
+ } else {
+ memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
+ }
+
+ DEBUG(10,("get_windows_lock_count for file %s = %d\n",
+ fsp->fsp_name, lock_ref_count ));
+ return lock_ref_count;
+}
+
+/****************************************************************************
+ Delete a lock_ref_count entry.
+****************************************************************************/
+
+static void delete_windows_lock_ref_count(files_struct *fsp)
+{
+ TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
+
+ /* 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));
+}
+
+/****************************************************************************
+ Add an fd to the pending close tdb.
+****************************************************************************/
+
+static void add_fd_to_close_entry(files_struct *fsp)
+{
+ TDB_DATA kbuf = fd_array_key_fsp(fsp);
+ TDB_DATA dbuf;
+
+ dbuf.dptr = NULL;
+ dbuf.dsize = 0;
+
+ dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+
+ dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int));
+ if (!dbuf.dptr) {
+ smb_panic("add_fd_to_close_entry: Realloc fail !\n");
+ }
+
+ memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int));
+ dbuf.dsize += sizeof(int);
+
+ if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
+ smb_panic("add_fd_to_close_entry: tdb_store_fail.\n");
+ }
+
+ DEBUG(10,("add_fd_to_close_entry: added fd %d file %s\n",
+ fsp->fh->fd, fsp->fsp_name ));
+
+ SAFE_FREE(dbuf.dptr);
+}
+
+/****************************************************************************
+ Remove all fd entries for a specific dev/inode pair from the tdb.
+****************************************************************************/
+
+static void delete_close_entries(files_struct *fsp)
+{
+ TDB_DATA kbuf = fd_array_key_fsp(fsp);
+
+ if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) {
+ smb_panic("delete_close_entries: tdb_delete fail !\n");
+ }
+}
+
+/****************************************************************************
+ Get the array of POSIX pending close records for an open fsp. Caller must
+ free. Returns number of entries.
+****************************************************************************/
+
+static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries)
+{
+ TDB_DATA kbuf = fd_array_key_fsp(fsp);
+ TDB_DATA dbuf;
+ size_t count = 0;
+
+ *entries = NULL;
+ dbuf.dptr = NULL;
+
+ dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+
+ if (!dbuf.dptr) {
+ return 0;
+ }
+
+ *entries = (int *)dbuf.dptr;
+ count = (size_t)(dbuf.dsize / sizeof(int));
+
+ return count;
+}
+
+/****************************************************************************
+ 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.
+****************************************************************************/
+
+int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
+{
+ int saved_errno = 0;
+ int ret;
+ int *fd_array = NULL;
+ size_t count, i;
+
+ 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;
+ }
+
+ if (get_windows_lock_ref_count(fsp)) {
+
+ /*
+ * 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.
+ */
+
+ add_fd_to_close_entry(fsp);
+ fsp->fh->fd = -1;
+ return 0;
+ }
+
+ /*
+ * 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);
+
+ if (count) {
+ DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count ));
+
+ for(i = 0; i < count; i++) {
+ if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) {
+ saved_errno = errno;
+ }
+ }
+
+ /*
+ * 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);
+
+ /*
+ * Finally close the fd associated with this fsp.
+ */
+
+ ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
+
+ if (saved_errno != 0) {
+ errno = saved_errno;
+ ret = -1;
+ }
+
+ fsp->fh->fd = -1;
+
+ 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;
}
diff --git a/source/modules/charset_macosxfs.c b/source/modules/charset_macosxfs.c
index 6f50d879ba4..a9003c7a826 100644
--- a/source/modules/charset_macosxfs.c
+++ b/source/modules/charset_macosxfs.c
@@ -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);
}
diff --git a/source/modules/vfs_afsacl.c b/source/modules/vfs_afsacl.c
index 53272ca06fe..11498fccf9e 100644
--- a/source/modules/vfs_afsacl.c
+++ b/source/modules/vfs_afsacl.c
@@ -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 */
diff --git a/source/modules/vfs_audit.c b/source/modules/vfs_audit.c
index 9f5179a47ce..b240cafd29f 100644
--- a/source/modules/vfs_audit.c
+++ b/source/modules/vfs_audit.c
@@ -29,17 +29,17 @@
/* 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
index 00000000000..196441c4dda
--- /dev/null
+++ b/source/modules/vfs_cacheprime.c
@@ -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: */
diff --git a/source/modules/vfs_cap.c b/source/modules/vfs_cap.c
index b1bfcd75f2f..54f74dde678 100644
--- a/source/modules/vfs_cap.c
+++ b/source/modules/vfs_cap.c
@@ -28,28 +28,28 @@
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)
diff --git a/source/modules/vfs_catia.c b/source/modules/vfs_catia.c
index 69735de3f43..f5c7e95794f 100644
--- a/source/modules/vfs_catia.c
+++ b/source/modules/vfs_catia.c
@@ -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
index 00000000000..9d817c017d2
--- /dev/null
+++ b/source/modules/vfs_commit.c
@@ -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
index 00000000000..82eec46d378
--- /dev/null
+++ b/source/modules/vfs_default.c
@@ -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);
+}
diff --git a/source/modules/vfs_default_quota.c b/source/modules/vfs_default_quota.c
index 9922a30315d..55dc287b88a 100644
--- a/source/modules/vfs_default_quota.c
+++ b/source/modules/vfs_default_quota.c
@@ -92,11 +92,11 @@
#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 */
diff --git a/source/modules/vfs_expand_msdfs.c b/source/modules/vfs_expand_msdfs.c
index d22f6a7f98e..fdd9ac6fbd8 100644
--- a/source/modules/vfs_expand_msdfs.c
+++ b/source/modules/vfs_expand_msdfs.c
@@ -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;
}
diff --git a/source/modules/vfs_extd_audit.c b/source/modules/vfs_extd_audit.c
index cb8c3ffd6ab..1c3b25103c8 100644
--- a/source/modules/vfs_extd_audit.c
+++ b/source/modules/vfs_extd_audit.c
@@ -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,
diff --git a/source/modules/vfs_fake_perms.c b/source/modules/vfs_fake_perms.c
index decbe01d3ca..8bd8bbf5321 100644
--- a/source/modules/vfs_fake_perms.c
+++ b/source/modules/vfs_fake_perms.c
@@ -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;
diff --git a/source/modules/vfs_full_audit.c b/source/modules/vfs_full_audit.c
index b9ffd6fc05f..fd15c5c3585 100644
--- a/source/modules/vfs_full_audit.c
+++ b/source/modules/vfs_full_audit.c
@@ -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,
diff --git a/source/modules/vfs_netatalk.c b/source/modules/vfs_netatalk.c
index e9d4360cd80..279160d9665 100644
--- a/source/modules/vfs_netatalk.c
+++ b/source/modules/vfs_netatalk.c
@@ -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
index 00000000000..94db6423700
--- /dev/null
+++ b/source/modules/vfs_prealloc.c
@@ -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);
+}
+
diff --git a/source/modules/vfs_readonly.c b/source/modules/vfs_readonly.c
index ee9e40c2fca..e69f7dac016 100644
--- a/source/modules/vfs_readonly.c
+++ b/source/modules/vfs_readonly.c
@@ -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 {
diff --git a/source/modules/vfs_recycle.c b/source/modules/vfs_recycle.c
index 42f2f51416e..cb5eaffa54d 100644
--- a/source/modules/vfs_recycle.c
+++ b/source/modules/vfs_recycle.c
@@ -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;
}
diff --git a/source/modules/vfs_shadow_copy.c b/source/modules/vfs_shadow_copy.c
index db1c8d007dc..447c53d773a 100644
--- a/source/modules/vfs_shadow_copy.c
+++ b/source/modules/vfs_shadow_copy.c
@@ -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;
}
diff --git a/source/nmbd/nmbd_synclists.c b/source/nmbd/nmbd_synclists.c
index 28ad92ed108..0e67c3f69c0 100644
--- a/source/nmbd/nmbd_synclists.c
+++ b/source/nmbd/nmbd_synclists.c
@@ -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);
}
/*******************************************************************
diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c
index 78776256e99..118ba358e16 100644
--- a/source/nsswitch/pam_winbind.c
+++ b/source/nsswitch/pam_winbind.c
@@ -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) {
diff --git a/source/nsswitch/wb_client.c b/source/nsswitch/wb_client.c
index de1edf054d1..b1a79471375 100644
--- a/source/nsswitch/wb_client.c
+++ b/source/nsswitch/wb_client.c
@@ -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)
diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c
index 27ec27d0be5..a393855f026 100644
--- a/source/nsswitch/wbinfo.c
+++ b/source/nsswitch/wbinfo.c
@@ -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",
diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c
index 046ea40f59a..e5582915b2f 100644
--- a/source/nsswitch/winbindd.c
+++ b/source/nsswitch/winbindd.c
@@ -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 */
diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h
index 7d5330dccb2..a16613258b1 100644
--- a/source/nsswitch/winbindd.h
+++ b/source/nsswitch/winbindd.h
@@ -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,
diff --git a/source/nsswitch/winbindd_ads.c b/source/nsswitch/winbindd_ads.c
index 250b5f3b8c2..07127a63166 100644
--- a/source/nsswitch/winbindd_ads.c
+++ b/source/nsswitch/winbindd_ads.c
@@ -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,
diff --git a/source/nsswitch/winbindd_async.c b/source/nsswitch/winbindd_async.c
index 7f282df929d..6169b8299ec 100644
--- a/source/nsswitch/winbindd_async.c
+++ b/source/nsswitch/winbindd_async.c
@@ -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);
}
diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c
index b267a3f7705..95a66420c59 100644
--- a/source/nsswitch/winbindd_cache.c
+++ b/source/nsswitch/winbindd_cache.c
@@ -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,
diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c
index c1276bd9612..2b8a8898ac6 100644
--- a/source/nsswitch/winbindd_cm.c
+++ b/source/nsswitch/winbindd_cm.c
@@ -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;
diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c
index 0cc35277b05..5908c78d9a8 100644
--- a/source/nsswitch/winbindd_dual.c
+++ b/source/nsswitch/winbindd_dual.c
@@ -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" },
diff --git a/source/nsswitch/winbindd_nss.h b/source/nsswitch/winbindd_nss.h
index 2afefcc12ca..6167a10c464 100644
--- a/source/nsswitch/winbindd_nss.h
+++ b/source/nsswitch/winbindd_nss.h
@@ -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 */
diff --git a/source/nsswitch/winbindd_passdb.c b/source/nsswitch/winbindd_passdb.c
index b949ea08085..d73917ef830 100644
--- a/source/nsswitch/winbindd_passdb.c
+++ b/source/nsswitch/winbindd_passdb.c
@@ -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,
diff --git a/source/nsswitch/winbindd_reconnect.c b/source/nsswitch/winbindd_reconnect.c
index 7bc8be12131..8c5d59f9af0 100644
--- a/source/nsswitch/winbindd_reconnect.c
+++ b/source/nsswitch/winbindd_reconnect.c
@@ -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,
diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c
index 27feea2f671..d8797ee2bc6 100644
--- a/source/nsswitch/winbindd_rpc.c
+++ b/source/nsswitch/winbindd_rpc.c
@@ -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,
diff --git a/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c
index d489e267cb2..4a9e17e4c70 100644
--- a/source/nsswitch/winbindd_sid.c
+++ b/source/nsswitch/winbindd_sid.c
@@ -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);
diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c
index a73b5c394cd..8a0ebbafa50 100644
--- a/source/nsswitch/winbindd_user.c
+++ b/source/nsswitch/winbindd_user.c
@@ -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",
diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c
index 67b94817adb..25ba20bb9f3 100644
--- a/source/nsswitch/winbindd_util.c
+++ b/source/nsswitch/winbindd_util.c
@@ -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");
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index b6c027f8714..c308378a227 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -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.
********************************************************************/
diff --git a/source/passdb/login_cache.c b/source/passdb/login_cache.c
index 9a19dcf437a..7fd3b47826f 100644
--- a/source/passdb/login_cache.c
+++ b/source/passdb/login_cache.c
@@ -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;
diff --git a/source/passdb/lookup_sid.c b/source/passdb/lookup_sid.c
index dba43ed6c4f..a7a3fdc94d5 100644
--- a/source/passdb/lookup_sid.c
+++ b/source/passdb/lookup_sid.c
@@ -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) {
diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c
index cbb30ead023..f74b1fbe3ba 100644
--- a/source/passdb/passdb.c
+++ b/source/passdb/passdb.c
@@ -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;
diff --git a/source/passdb/pdb_get_set.c b/source/passdb/pdb_get_set.c
index 2e69240b1af..3b774b510b0 100644
--- a/source/passdb/pdb_get_set.c
+++ b/source/passdb/pdb_get_set.c
@@ -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;
diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c
index a0310d0c71f..20aa72d24ee 100644
--- a/source/passdb/pdb_interface.c
+++ b/source/passdb/pdb_interface.c
@@ -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);
}
diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c
index 4d0c84b5433..83f8d7183cc 100644
--- a/source/passdb/pdb_ldap.c
+++ b/source/passdb/pdb_ldap.c
@@ -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 */
diff --git a/source/passdb/pdb_nds.c b/source/passdb/pdb_nds.c
index 08ad96efa4b..ab4a1a7f208 100644
--- a/source/passdb/pdb_nds.c
+++ b/source/passdb/pdb_nds.c
@@ -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;
diff --git a/source/passdb/pdb_smbpasswd.c b/source/passdb/pdb_smbpasswd.c
index a8a42196d48..aec1db48b5d 100644
--- a/source/passdb/pdb_smbpasswd.c
+++ b/source/passdb/pdb_smbpasswd.c
@@ -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)
diff --git a/source/passdb/pdb_tdb.c b/source/passdb/pdb_tdb.c
index f3ae4b7b02e..ac8cbbe91a3 100644
--- a/source/passdb/pdb_tdb.c
+++ b/source/passdb/pdb_tdb.c
@@ -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 */
diff --git a/source/passdb/secrets.c b/source/passdb/secrets.c
index 04d6da2814a..f72a7cb8d54 100644
--- a/source/passdb/secrets.c
+++ b/source/passdb/secrets.c
@@ -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;
diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c
index bcdf0e04625..4b71f6e0b66 100644
--- a/source/printing/nt_printing.c
+++ b/source/printing/nt_printing.c
@@ -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)
diff --git a/source/printing/print_generic.c b/source/printing/print_generic.c
index 1ea762695b1..aef4e50bfaa 100644
--- a/source/printing/print_generic.c
+++ b/source/printing/print_generic.c
@@ -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);
diff --git a/source/printing/printfsp.c b/source/printing/printfsp.c
index c248851822b..5278c60f992 100644
--- a/source/printing/printfsp.c
+++ b/source/printing/printfsp.c
@@ -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;
}
/****************************************************************************
diff --git a/source/printing/printing.c b/source/printing/printing.c
index 9dd6bec0be4..bb756c88707 100644
--- a/source/printing/printing.c
+++ b/source/printing/printing.c
@@ -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);
diff --git a/source/profile/profile.c b/source/profile/profile.c
index c3512ec01d8..926cc508dd2 100644
--- a/source/profile/profile.c
+++ b/source/profile/profile.c
@@ -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 */
diff --git a/source/python/py_smb.c b/source/python/py_smb.c
index 679c113f397..f92a9e258dc 100644
--- a/source/python/py_smb.c
+++ b/source/python/py_smb.c
@@ -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);
diff --git a/source/registry/reg_printing.c b/source/registry/reg_printing.c
index 3ecff3d6964..338bc7af6a7 100644
--- a/source/registry/reg_printing.c
+++ b/source/registry/reg_printing.c
@@ -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 );
diff --git a/source/rpc_client/cli_lsarpc.c b/source/rpc_client/cli_lsarpc.c
index 97d8eb621be..7e29332ef97 100644
--- a/source/rpc_client/cli_lsarpc.c
+++ b/source/rpc_client/cli_lsarpc.c
@@ -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;
}
diff --git a/source/rpc_client/cli_srvsvc.c b/source/rpc_client/cli_srvsvc.c
index 0d50e94d577..7b4818b4b06 100644
--- a/source/rpc_client/cli_srvsvc.c
+++ b/source/rpc_client/cli_srvsvc.c
@@ -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
index 00000000000..b9a960dfd1a
--- /dev/null
+++ b/source/rpc_client/cli_unixinfo.c
@@ -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
index 00000000000..985490f71cb
--- /dev/null
+++ b/source/rpc_client/ndr.c
@@ -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;
+}
diff --git a/source/rpc_parse/parse_eventlog.c b/source/rpc_parse/parse_eventlog.c
index 4aff9734eed..addf433feb8 100644
--- a/source/rpc_parse/parse_eventlog.c
+++ b/source/rpc_parse/parse_eventlog.c
@@ -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) )
diff --git a/source/rpc_parse/parse_lsa.c b/source/rpc_parse/parse_lsa.c
index ae4cff53e4b..919b7c39552 100644
--- a/source/rpc_parse/parse_lsa.c
+++ b/source/rpc_parse/parse_lsa.c
@@ -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;
diff --git a/source/rpc_parse/parse_ntsvcs.c b/source/rpc_parse/parse_ntsvcs.c
index 599257e8020..ab5f3f75e87 100644
--- a/source/rpc_parse/parse_ntsvcs.c
+++ b/source/rpc_parse/parse_ntsvcs.c
@@ -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;
diff --git a/source/rpc_parse/parse_prs.c b/source/rpc_parse/parse_prs.c
index 14e190892d7..29a3e60aa90 100644
--- a/source/rpc_parse/parse_prs.c
+++ b/source/rpc_parse/parse_prs.c
@@ -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;
+}
diff --git a/source/rpc_parse/parse_reg.c b/source/rpc_parse/parse_reg.c
index fef1332e5c7..1820a595eda 100644
--- a/source/rpc_parse/parse_reg.c
+++ b/source/rpc_parse/parse_reg.c
@@ -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;
diff --git a/source/rpc_parse/parse_rpc.c b/source/rpc_parse/parse_rpc.c
index 2d166c773b4..240cac886cf 100644
--- a/source/rpc_parse/parse_rpc.c
+++ b/source/rpc_parse/parse_rpc.c
@@ -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 }
};
diff --git a/source/rpc_parse/parse_samr.c b/source/rpc_parse/parse_samr.c
index 9026d503c30..26da7b426d7 100644
--- a/source/rpc_parse/parse_samr.c
+++ b/source/rpc_parse/parse_samr.c
@@ -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) */
diff --git a/source/rpc_parse/parse_shutdown.c b/source/rpc_parse/parse_shutdown.c
index da338077333..8c417c05dce 100644
--- a/source/rpc_parse/parse_shutdown.c
+++ b/source/rpc_parse/parse_shutdown.c
@@ -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;
diff --git a/source/rpc_parse/parse_spoolss.c b/source/rpc_parse/parse_spoolss.c
index 2884883e893..8d4a757a74a 100644
--- a/source/rpc_parse/parse_spoolss.c
+++ b/source/rpc_parse/parse_spoolss.c
@@ -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;
diff --git a/source/rpc_parse/parse_srv.c b/source/rpc_parse/parse_srv.c
index 7d15eda630f..5123d1c2cca 100644
--- a/source/rpc_parse/parse_srv.c
+++ b/source/rpc_parse/parse_srv.c
@@ -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;
}
@@ -1699,53 +1655,32 @@ static BOOL srv_io_srv_sess_info_0(const char *desc, SRV_SESS_INFO_0 *ss0, prs_s
}
/*******************************************************************
- 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;
}
@@ -1884,36 +1806,12 @@ static BOOL srv_io_srv_sess_ctr(const char *desc, SRV_SESS_INFO_CTR **pp_ctr, pr
}
/*******************************************************************
- 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;
@@ -2434,22 +2327,10 @@ BOOL srv_io_r_net_conn_enum(const char *desc, SRV_R_NET_CONN_ENUM *r_n, prs_str
}
/*******************************************************************
- 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,63 +2618,17 @@ 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.
********************************************************************/
@@ -3411,25 +3280,6 @@ BOOL srv_io_r_net_disk_enum(const char *desc, SRV_R_NET_DISK_ENUM *r_n, prs_stru
}
/*******************************************************************
- 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;
+}
diff --git a/source/rpc_parse/parse_svcctl.c b/source/rpc_parse/parse_svcctl.c
index 2cb44c63195..dc4ee3e6e99 100644
--- a/source/rpc_parse/parse_svcctl.c
+++ b/source/rpc_parse/parse_svcctl.c
@@ -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
index 00000000000..391713ce901
--- /dev/null
+++ b/source/rpc_parse/parse_unixinfo.c
@@ -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;
+}
diff --git a/source/rpc_server/srv_dfs_nt.c b/source/rpc_server/srv_dfs_nt.c
index 8239584522a..c7f8e05d91c 100644
--- a/source/rpc_server/srv_dfs_nt.c
+++ b/source/rpc_server/srv_dfs_nt.c
@@ -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;
}
diff --git a/source/rpc_server/srv_lsa_nt.c b/source/rpc_server/srv_lsa_nt.c
index efa7156eea6..2cc5ef61104 100644
--- a/source/rpc_server/srv_lsa_nt.c
+++ b/source/rpc_server/srv_lsa_nt.c
@@ -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;
diff --git a/source/rpc_server/srv_pipe.c b/source/rpc_server/srv_pipe.c
index 812a720d905..e2c5e865ed1 100644
--- a/source/rpc_server/srv_pipe.c
+++ b/source/rpc_server/srv_pipe.c
@@ -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:
@@ -2149,23 +2172,6 @@ BOOL api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss
}
/****************************************************************************
- 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;
diff --git a/source/rpc_server/srv_pipe_hnd.c b/source/rpc_server/srv_pipe_hnd.c
index 9cc8b72546f..8aa5bb3e6d1 100644
--- a/source/rpc_server/srv_pipe_hnd.c
+++ b/source/rpc_server/srv_pipe_hnd.c
@@ -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);
diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c
index e045de56396..2e0b355db5f 100644
--- a/source/rpc_server/srv_samr_nt.c
+++ b/source/rpc_server/srv_samr_nt.c
@@ -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 ================ */
diff --git a/source/rpc_server/srv_samr_util.c b/source/rpc_server/srv_samr_util.c
index 2b65eb210fd..c4bec79c9cb 100644
--- a/source/rpc_server/srv_samr_util.c
+++ b/source/rpc_server/srv_samr_util.c
@@ -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) &&
diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c
index 0281e3da0ca..3dbad208cc8 100644
--- a/source/rpc_server/srv_spoolss_nt.c
+++ b/source/rpc_server/srv_spoolss_nt.c
@@ -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 );
diff --git a/source/rpc_server/srv_srvsvc.c b/source/rpc_server/srv_srvsvc.c
index 0b4eac5cc73..e4f85d0bdb4 100644
--- a/source/rpc_server/srv_srvsvc.c
+++ b/source/rpc_server/srv_srvsvc.c
@@ -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
@@ -551,6 +552,35 @@ static BOOL api_srv_net_file_set_secdesc(pipes_struct *p)
}
/*******************************************************************
+*******************************************************************/
+
+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 )
diff --git a/source/rpc_server/srv_srvsvc_nt.c b/source/rpc_server/srv_srvsvc_nt.c
index a936ef58709..12a86ce9f33 100644
--- a/source/rpc_server/srv_srvsvc_nt.c
+++ b/source/rpc_server/srv_srvsvc_nt.c
@@ -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
@@ -25,10 +26,179 @@
#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);
@@ -633,16 +832,6 @@ static void init_srv_r_net_share_get_info(pipes_struct *p, SRV_R_NET_SHARE_GET_I
}
/*******************************************************************
- 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;
}
/*******************************************************************
@@ -1110,25 +1315,6 @@ WERROR _srv_net_srv_set_info(pipes_struct *p, SRV_Q_NET_SRV_SET_INFO *q_u, SRV_R
}
/*******************************************************************
-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;
+}
+
diff --git a/source/rpc_server/srv_svcctl_nt.c b/source/rpc_server/srv_svcctl_nt.c
index 6062dcee5ce..dd790691d36 100644
--- a/source/rpc_server/srv_svcctl_nt.c
+++ b/source/rpc_server/srv_svcctl_nt.c
@@ -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
index 00000000000..f21416dfabe
--- /dev/null
+++ b/source/rpc_server/srv_unixinfo.c
@@ -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
index 00000000000..79756f20a74
--- /dev/null
+++ b/source/rpc_server/srv_unixinfo_nt.c
@@ -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;
+}
diff --git a/source/rpcclient/cmd_samr.c b/source/rpcclient/cmd_samr.c
index 1a204e70bc7..2aab35ea3c4 100644
--- a/source/rpcclient/cmd_samr.c
+++ b/source/rpcclient/cmd_samr.c
@@ -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);
diff --git a/source/rpcclient/cmd_spoolss.c b/source/rpcclient/cmd_spoolss.c
index ed5653eb704..d77c58ad959 100644
--- a/source/rpcclient/cmd_spoolss.c
+++ b/source/rpcclient/cmd_spoolss.c
@@ -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
index 00000000000..2e9ab106522
--- /dev/null
+++ b/source/rpcclient/cmd_unixinfo.c
@@ -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 }
+};
diff --git a/source/rpcclient/rpcclient.c b/source/rpcclient/rpcclient.c
index d5425aa43d1..4ca674c2b10 100644
--- a/source/rpcclient/rpcclient.c
+++ b/source/rpcclient/rpcclient.c
@@ -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,
diff --git a/source/sam/idmap.c b/source/sam/idmap.c
index aa5b923d3dd..e8ebd9272c3 100644
--- a/source/sam/idmap.c
+++ b/source/sam/idmap.c
@@ -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();
+ }
}
diff --git a/source/sam/idmap_ad.c b/source/sam/idmap_ad.c
index 5edfad487d7..f0adfa4028a 100644
--- a/source/sam/idmap_ad.c
+++ b/source/sam/idmap_ad.c
@@ -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);
}
diff --git a/source/sam/idmap_ldap.c b/source/sam/idmap_ldap.c
index 6169c89b3b9..3fec3a142be 100644
--- a/source/sam/idmap_ldap.c
+++ b/source/sam/idmap_ldap.c
@@ -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;
diff --git a/source/sam/idmap_rid.c b/source/sam/idmap_rid.c
index 58838512a68..23496d69692 100644
--- a/source/sam/idmap_rid.c
+++ b/source/sam/idmap_rid.c
@@ -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);
}
diff --git a/source/sam/idmap_smbldap.c b/source/sam/idmap_smbldap.c
index 4d80364437c..9850921fa39 100644
--- a/source/sam/idmap_smbldap.c
+++ b/source/sam/idmap_smbldap.c
@@ -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 "
diff --git a/source/sam/idmap_tdb.c b/source/sam/idmap_tdb.c
index 665c56d2f67..02a3178d61a 100644
--- a/source/sam/idmap_tdb.c
+++ b/source/sam/idmap_tdb.c
@@ -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;
diff --git a/source/sam/idmap_util.c b/source/sam/idmap_util.c
index f78d3bdc233..8320b294f8f 100644
--- a/source/sam/idmap_util.c
+++ b/source/sam/idmap_util.c
@@ -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;
}
diff --git a/source/script/mkproto.awk b/source/script/mkproto.awk
index a0f3096c842..30b5628b336 100644
--- a/source/script/mkproto.awk
+++ b/source/script/mkproto.awk
@@ -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/ {
diff --git a/source/script/mkproto.sh b/source/script/mkproto.sh
index 62041c7e331..e46e73e3e90 100755
--- a/source/script/mkproto.sh
+++ b/source/script/mkproto.sh
@@ -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
diff --git a/source/script/tests/selftest.sh b/source/script/tests/selftest.sh
index fe943b87b5e..d7a2db5eb64 100755
--- a/source/script/tests/selftest.sh
+++ b/source/script/tests/selftest.sh
@@ -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
diff --git a/source/script/tests/test_posix_s3.sh b/source/script/tests/test_posix_s3.sh
index 2274a1f7fe5..d4a03f85817 100755
--- a/source/script/tests/test_posix_s3.sh
+++ b/source/script/tests/test_posix_s3.sh
@@ -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"
diff --git a/source/script/tests/test_smbtorture_s3.sh b/source/script/tests/test_smbtorture_s3.sh
index d0e15345df8..842d914ecff 100755
--- a/source/script/tests/test_smbtorture_s3.sh
+++ b/source/script/tests/test_smbtorture_s3.sh
@@ -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"
diff --git a/source/services/svc_netlogon.c b/source/services/svc_netlogon.c
index 1bbef325ac3..c561870552c 100644
--- a/source/services/svc_netlogon.c
+++ b/source/services/svc_netlogon.c
@@ -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;
diff --git a/source/smbd/blocking.c b/source/smbd/blocking.c
index a8db498ef5a..04ab01eb664 100644
--- a/source/smbd/blocking.c
+++ b/source/smbd/blocking.c
@@ -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);
diff --git a/source/smbd/change_trust_pw.c b/source/smbd/change_trust_pw.c
index 738d12151db..31f03cc7fad 100644
--- a/source/smbd/change_trust_pw.c
+++ b/source/smbd/change_trust_pw.c
@@ -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"));
diff --git a/source/smbd/conn.c b/source/smbd/conn.c
index d857611c355..52182f31294 100644
--- a/source/smbd/conn.c
+++ b/source/smbd/conn.c
@@ -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);
diff --git a/source/smbd/connection.c b/source/smbd/connection.c
index 07d3181144f..0442a9441ad 100644
--- a/source/smbd/connection.c
+++ b/source/smbd/connection.c
@@ -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;
+}
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index 5ba9e1ed575..96e0923dbd0 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -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;
}
diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c
index 61145fde2f0..260a8dadbd6 100644
--- a/source/smbd/dosmode.c
+++ b/source/smbd/dosmode.c
@@ -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);
diff --git a/source/smbd/error.c b/source/smbd/error.c
index fa236f0de05..409781eaa94 100644
--- a/source/smbd/error.c
+++ b/source/smbd/error.c
@@ -24,40 +24,6 @@
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);
}
diff --git a/source/smbd/fake_file.c b/source/smbd/fake_file.c
index b4f1f02b724..7c5eeae5c7d 100644
--- a/source/smbd/fake_file.c
+++ b/source/smbd/fake_file.c
@@ -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)
diff --git a/source/smbd/filename.c b/source/smbd/filename.c
index 6c0f8b77585..1ea5228e919 100644
--- a/source/smbd/filename.c
+++ b/source/smbd/filename.c
@@ -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);
diff --git a/source/smbd/files.c b/source/smbd/files.c
index e020d8e13a6..7069818dee4 100644
--- a/source/smbd/files.c
+++ b/source/smbd/files.c
@@ -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);
}
@@ -492,6 +482,29 @@ files_struct *file_fsp(char *buf, int where)
}
/****************************************************************************
+ 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;
}
diff --git a/source/smbd/lanman.c b/source/smbd/lanman.c
index e4531d8ae98..2d6db8f2a30 100644
--- a/source/smbd/lanman.c
+++ b/source/smbd/lanman.c
@@ -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 */
diff --git a/source/smbd/mangle.c b/source/smbd/mangle.c
index ed69a6210e8..16f99636eb5 100644
--- a/source/smbd/mangle.c
+++ b/source/smbd/mangle.c
@@ -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);
}
diff --git a/source/smbd/mangle_hash.c b/source/smbd/mangle_hash.c
index 2092f430c07..320e31ab679 100644
--- a/source/smbd/mangle_hash.c
+++ b/source/smbd/mangle_hash.c
@@ -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"));
diff --git a/source/smbd/mangle_hash2.c b/source/smbd/mangle_hash2.c
index 0a161c9e769..d1ce1af9eac 100644
--- a/source/smbd/mangle_hash2.c
+++ b/source/smbd/mangle_hash2.c
@@ -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);
diff --git a/source/smbd/mangle_map.c b/source/smbd/mangle_map.c
index 9e798fd41b4..c5803786ec0 100644
--- a/source/smbd/mangle_map.c
+++ b/source/smbd/mangle_map.c
@@ -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);
diff --git a/source/smbd/message.c b/source/smbd/message.c
index 31dab458443..fd53e60c141 100644
--- a/source/smbd/message.c
+++ b/source/smbd/message.c
@@ -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);
}
diff --git a/source/smbd/msdfs.c b/source/smbd/msdfs.c
index b22b5674d6f..69da4194fda 100644
--- a/source/smbd/msdfs.c
+++ b/source/smbd/msdfs.c
@@ -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);
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index aa6f79e1657..0b1bdcadbb1 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -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;
diff --git a/source/smbd/open.c b/source/smbd/open.c
index 832a8df7559..7c04cdbe7cc 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -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;
}
/****************************************************************************
diff --git a/source/smbd/password.c b/source/smbd/password.c
index 73b0ebb4b32..389086e9bf7 100644
--- a/source/smbd/password.c
+++ b/source/smbd/password.c
@@ -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);
}
}
diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c
index 2d90383706b..52660da2ffe 100644
--- a/source/smbd/pipes.c
+++ b/source/smbd/pipes.c
@@ -31,6 +31,21 @@
#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);
}
diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c
index 6e403dba92a..73744cf26e7 100644
--- a/source/smbd/posix_acls.c
+++ b/source/smbd/posix_acls.c
@@ -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);
diff --git a/source/smbd/process.c b/source/smbd/process.c
index b3ce49360d8..ce352adfd7d 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -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. */
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index e68e8662d74..ff3c6832e4f 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -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));
}
diff --git a/source/smbd/server.c b/source/smbd/server.c
index 2bfeae9f541..0fba6af6970 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -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);
diff --git a/source/smbd/service.c b/source/smbd/service.c
index cb9bfcc27ae..9dcb8a354f4 100644
--- a/source/smbd/service.c
+++ b/source/smbd/service.c
@@ -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);
}
diff --git a/source/smbd/session.c b/source/smbd/session.c
index 41f8fd0ed43..bcb840a3fe4 100644
--- a/source/smbd/session.c
+++ b/source/smbd/session.c
@@ -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;
diff --git a/source/smbd/share_access.c b/source/smbd/share_access.c
index 468f61560b9..5334976d8dc 100644
--- a/source/smbd/share_access.c
+++ b/source/smbd/share_access.c
@@ -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);
diff --git a/source/smbd/statcache.c b/source/smbd/statcache.c
index 548d7c4a487..b453fdd5447 100644
--- a/source/smbd/statcache.c
+++ b/source/smbd/statcache.c
@@ -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;
}
diff --git a/source/smbd/statvfs.c b/source/smbd/statvfs.c
index 8f981a63288..300b14a7c08 100644
--- a/source/smbd/statvfs.c
+++ b/source/smbd/statvfs.c
@@ -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 */
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index 9030737b1b4..aca1fcd70e9 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -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;
diff --git a/source/smbd/uid.c b/source/smbd/uid.c
index c62c9d928ab..48d7f590c39 100644
--- a/source/smbd/uid.c
+++ b/source/smbd/uid.c
@@ -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
index ee251c17d8d..00000000000
--- a/source/smbd/vfs-wrap.c
+++ /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);
-}
diff --git a/source/smbd/vfs.c b/source/smbd/vfs.c
index 2c9403a0790..7bb5f798f97 100644
--- a/source/smbd/vfs.c
+++ b/source/smbd/vfs.c
@@ -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,18 +173,15 @@ 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);
@@ -311,6 +189,71 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
}
/*****************************************************************
+ 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.
******************************************************************/
diff --git a/source/smbwrapper/smbw.c b/source/smbwrapper/smbw.c
index d4a5b51af4e..89ae9396aaf 100644
--- a/source/smbwrapper/smbw.c
+++ b/source/smbwrapper/smbw.c
@@ -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);
diff --git a/source/smbwrapper/smbw.h b/source/smbwrapper/smbw.h
index 3f0b1cbb443..f64cb209649 100644
--- a/source/smbwrapper/smbw.h
+++ b/source/smbwrapper/smbw.h
@@ -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
index 00000000000..577f23aac68
--- /dev/null
+++ b/source/tdb/dump.c
@@ -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
index 00000000000..4cf33a29ab2
--- /dev/null
+++ b/source/tdb/error.c
@@ -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
index 00000000000..34837511647
--- /dev/null
+++ b/source/tdb/freelist.c
@@ -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
index 00000000000..ac6f4cdf573
--- /dev/null
+++ b/source/tdb/io.c
@@ -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
index 00000000000..a96d77a229a
--- /dev/null
+++ b/source/tdb/lock.c
@@ -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
index 00000000000..cb4a9cd9945
--- /dev/null
+++ b/source/tdb/open.c
@@ -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
index e42a6901c71..00000000000
--- a/source/tdb/spinlock.c
+++ /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
index 967fe37457f..00000000000
--- a/source/tdb/spinlock.h
+++ /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
diff --git a/source/tdb/tdb.c b/source/tdb/tdb.c
index ad73a1d9aa0..1fae6b6de1d 100644
--- a/source/tdb/tdb.c
+++ b/source/tdb/tdb.c
@@ -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
@@ -20,1004 +20,57 @@
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));
+ tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1);
}
-/* 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));
-}
-
-/* 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)
+int tdb_exists(struct 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);
-}
-
/* 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;
+ dbuf = tdb_fetch(tdb, key);
- /* 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. */
-
- 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;
+ goto failed;
}
- out:
- SAFE_FREE(p);
- tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
- return ret;
-
-fail:
- ret = -1;
- goto out;
-}
+ memcpy(dbuf.dptr + dbuf.dsize, new_dbuf.dptr, new_dbuf.dsize);
+ dbuf.dsize += new_dbuf.dsize;
-static int tdb_already_open(dev_t device,
- ino_t ino)
-{
- TDB_CONTEXT *i;
+ ret = tdb_store(tdb, key, dbuf, 0);
- 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;
- }
-
-
- 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;
-
- 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;
+ tdb_off_t seqnum=0;
- 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;
-
-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;
}
diff --git a/source/tdb/tdb.h b/source/tdb/tdb.h
index b5b87ee5a54..82f8828c89d 100644
--- a/source/tdb/tdb.h
+++ b/source/tdb/tdb.h
@@ -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
@@ -31,17 +31,6 @@
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
index 00000000000..d10c1c46bf6
--- /dev/null
+++ b/source/tdb/tdb_private.h
@@ -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);
+
+
diff --git a/source/tdb/tdbback.c b/source/tdb/tdbback.c
index 7967a6bbf54..c337924d6cf 100644
--- a/source/tdb/tdbback.c
+++ b/source/tdb/tdbback.c
@@ -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);
diff --git a/source/tdb/tdbutil.c b/source/tdb/tdbutil.c
index fc45fa93606..e13f7e3e678 100644
--- a/source/tdb/tdbutil.c
+++ b/source/tdb/tdbutil.c
@@ -19,9 +19,21 @@
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().
****************************************************************************/
@@ -806,15 +695,6 @@ TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags,
}
/****************************************************************************
- 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;
+}
diff --git a/source/tdb/tdbutil.h b/source/tdb/tdbutil.h
index 1a181a962f2..44351619f45 100644
--- a/source/tdb/tdbutil.h
+++ b/source/tdb/tdbutil.h
@@ -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
index 00000000000..aa54c4ae3c8
--- /dev/null
+++ b/source/tdb/transaction.c
@@ -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
index 00000000000..d070e0a7662
--- /dev/null
+++ b/source/tdb/traverse.c
@@ -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;
+}
+
diff --git a/source/torture/cmd_vfs.c b/source/torture/cmd_vfs.c
index cc683977e8c..6cecd693f83 100644
--- a/source/torture/cmd_vfs.c
+++ b/source/torture/cmd_vfs.c
@@ -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;
}
diff --git a/source/torture/locktest.c b/source/torture/locktest.c
index b946e48666e..3559a55a467 100644
--- a/source/torture/locktest.c
+++ b/source/torture/locktest.c
@@ -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;
}
diff --git a/source/torture/locktest2.c b/source/torture/locktest2.c
index 519acebe8e8..5f2f2499acd 100644
--- a/source/torture/locktest2.c
+++ b/source/torture/locktest2.c
@@ -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",
diff --git a/source/torture/masktest.c b/source/torture/masktest.c
index ffc9a20e71c..44d26cdc5ad 100644
--- a/source/torture/masktest.c
+++ b/source/torture/masktest.c
@@ -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;
}
diff --git a/source/torture/nsstest.c b/source/torture/nsstest.c
index d2b17f0f635..7673f922090 100644
--- a/source/torture/nsstest.c
+++ b/source/torture/nsstest.c
@@ -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
index 00000000000..e1a35b79127
--- /dev/null
+++ b/source/torture/pdbtest.c
@@ -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;
+}
diff --git a/source/torture/rpctorture.c b/source/torture/rpctorture.c
index d69cc8eb8df..98f2dc105fa 100644
--- a/source/torture/rpctorture.c
+++ b/source/torture/rpctorture.c
@@ -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)
{
diff --git a/source/torture/scanner.c b/source/torture/scanner.c
index 1893be83699..1510cd70f4c 100644
--- a/source/torture/scanner.c
+++ b/source/torture/scanner.c
@@ -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;
diff --git a/source/torture/torture.c b/source/torture/torture.c
index 0b3bfc18f4a..25e249ed2e1 100644
--- a/source/torture/torture.c
+++ b/source/torture/torture.c
@@ -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}};
diff --git a/source/torture/vfstest.c b/source/torture/vfstest.c
index 61bb4b0bf65..fa0545988e9 100644
--- a/source/torture/vfstest.c
+++ b/source/torture/vfstest.c
@@ -575,6 +575,6 @@ int main(int argc, char *argv[])
process_cmd(&vfs, line);
}
- free(vfs.conn);
+ conn_free(vfs.conn);
return 0;
}
diff --git a/source/utils/debug2html.c b/source/utils/debug2html.c
index bec4d81ae2b..6d1b2b25352 100644
--- a/source/utils/debug2html.c
+++ b/source/utils/debug2html.c
@@ -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 */
diff --git a/source/utils/net.c b/source/utils/net.c
index bef2a0a83c2..8b4fb042fcf 100644
--- a/source/utils/net.c
+++ b/source/utils/net.c
@@ -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);
}
diff --git a/source/utils/net_ads.c b/source/utils/net_ads.c
index 9d122a466bb..bfbc80759aa 100644
--- a/source/utils/net_ads.c
+++ b/source/utils/net_ads.c
@@ -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);
diff --git a/source/utils/net_idmap.c b/source/utils/net_idmap.c
index 47e1f93b69f..87da952247a 100644
--- a/source/utils/net_idmap.c
+++ b/source/utils/net_idmap.c
@@ -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;
}
diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c
index f32348935fc..f2cd4adb176 100644
--- a/source/utils/net_rpc.c
+++ b/source/utils/net_rpc.c
@@ -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;
}
diff --git a/source/utils/net_rpc_printer.c b/source/utils/net_rpc_printer.c
index 8808d549ac5..50ab50bace3 100644
--- a/source/utils/net_rpc_printer.c
+++ b/source/utils/net_rpc_printer.c
@@ -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);
diff --git a/source/utils/net_rpc_registry.c b/source/utils/net_rpc_registry.c
index 873cb7b4597..3eaff901554 100644
--- a/source/utils/net_rpc_registry.c
+++ b/source/utils/net_rpc_registry.c
@@ -25,35 +25,6 @@
/********************************************************************
********************************************************************/
-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 ) {
diff --git a/source/utils/net_rpc_samsync.c b/source/utils/net_rpc_samsync.c
index 4f99c3035c8..861040533c6 100644
--- a/source/utils/net_rpc_samsync.c
+++ b/source/utils/net_rpc_samsync.c
@@ -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);
diff --git a/source/utils/net_time.c b/source/utils/net_time.c
index f6486286a65..f6269627dab 100644
--- a/source/utils/net_time.c
+++ b/source/utils/net_time.c
@@ -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;
}
diff --git a/source/utils/ntlm_auth.c b/source/utils/ntlm_auth.c
index ef24f9f1611..fc9e3e9546a 100644
--- a/source/utils/ntlm_auth.c
+++ b/source/utils/ntlm_auth.c
@@ -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;
}
diff --git a/source/utils/ntlm_auth_diagnostics.c b/source/utils/ntlm_auth_diagnostics.c
index c8ea966a558..e69715affd0 100644
--- a/source/utils/ntlm_auth_diagnostics.c
+++ b/source/utils/ntlm_auth_diagnostics.c
@@ -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
index 00000000000..aa4210b51dc
--- /dev/null
+++ b/source/utils/sharesec.c
@@ -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;
+}
diff --git a/source/utils/smbcontrol.c b/source/utils/smbcontrol.c
index 0c6a1341c03..a23492f9dcc 100644
--- a/source/utils/smbcontrol.c
+++ b/source/utils/smbcontrol.c
@@ -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
diff --git a/source/utils/status.c b/source/utils/status.c
index 163d99a2f69..58349f1f9a5 100644
--- a/source/utils/status.c
+++ b/source/utils/status.c
@@ -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
index 00000000000..fc5b5e10ffd
--- /dev/null
+++ b/source/utils/status_profile.c
@@ -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 */
+
diff --git a/source/web/diagnose.c b/source/web/diagnose.c
index d259717da0b..b53e139ca94 100644
--- a/source/web/diagnose.c
+++ b/source/web/diagnose.c
@@ -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;
}
diff --git a/source/web/neg_lang.c b/source/web/neg_lang.c
index fb79f41f13c..207614655db 100644
--- a/source/web/neg_lang.c
+++ b/source/web/neg_lang.c
@@ -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;
}
/*
diff --git a/source/web/swat.c b/source/web/swat.c
index d1fd0b4f9bc..d43f8941bc1 100644
--- a/source/web/swat.c
+++ b/source/web/swat.c
@@ -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);
}