From fbdcf2663b56007a438ac4f0d8d82436b1bfe688 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Jul 2006 18:01:26 +0000 Subject: 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. (This used to be commit 9dafb7f48ca3e7af956b0a7d1720c2546fc4cfb8) --- source3/Doxyfile | 6 - source3/Makefile.in | 109 +- source3/aclocal.m4 | 94 ++ source3/auth/auth_domain.c | 11 + source3/auth/auth_server.c | 9 +- source3/auth/auth_util.c | 104 +- source3/client/client.c | 2 +- source3/client/clitar.c | 4 + source3/client/mount.cifs.c | 10 + source3/client/smbctool.c | 2 +- source3/client/smbmount.c | 2 +- source3/configure.in | 133 +- source3/include/client.h | 4 - source3/include/idmap.h | 30 +- source3/include/includes.h | 18 +- source3/include/libsmb_internal.h | 2 +- source3/include/locking.h | 88 ++ source3/include/mangle.h | 12 +- source3/include/nt_status.h | 9 +- source3/include/ntdomain.h | 10 +- source3/include/nterr.h | 3 - source3/include/passdb.h | 8 +- source3/include/rpc_netlogon.h | 10 - source3/include/rpc_reg.h | 1 + source3/include/rpc_samr.h | 12 +- source3/include/rpc_secdes.h | 36 - source3/include/rpc_srvsvc.h | 246 ++-- source3/include/rpc_unixinfo.h | 172 +++ source3/include/session.h | 3 + source3/include/smb.h | 80 +- source3/include/smb_macros.h | 31 +- source3/include/smbprofile.h | 1041 ++++++++++----- source3/include/talloc.h | 3 +- source3/include/vfs.h | 129 +- source3/include/vfs_macros.h | 350 ++--- source3/lib/account_pol.c | 16 +- source3/lib/afs.c | 7 +- source3/lib/charcnv.c | 18 +- source3/lib/data_blob.c | 2 +- source3/lib/debug.c | 2 +- source3/lib/popt_common.c | 10 +- source3/lib/socket_wrapper.c | 17 +- source3/lib/substitute.c | 182 +-- source3/lib/system.c | 78 ++ source3/lib/talloc.c | 7 +- source3/lib/talloctort.c | 4 +- source3/lib/time.c | 47 +- source3/lib/util.c | 6 +- source3/lib/util_reg.c | 110 ++ source3/lib/util_str.c | 122 +- source3/libads/dns.c | 4 + source3/libads/ldap.c | 9 +- source3/libads/sasl.c | 2 - source3/libmsrpc/cac_lsarpc.c | 2 +- source3/libmsrpc/cac_samr.c | 18 +- source3/libmsrpc/cac_svcctl.c | 2 +- source3/libmsrpc/cac_winreg.c | 4 +- source3/libmsrpc/libmsrpc_internal.c | 41 +- source3/libndr/libndr.h | 296 +++++ source3/libndr/misc.h | 37 + source3/libndr/ndr.c | 961 ++++++++++++++ source3/libndr/ndr_basic.c | 826 ++++++++++++ source3/libndr/ndr_misc.c | 171 +++ source3/libndr/ndr_sec.h | 35 + source3/libndr/ndr_sec_helper.c | 187 +++ source3/libndr/ndr_string.c | 612 +++++++++ source3/libndr/security.h | 260 ++++ source3/libndr/sid.c | 97 ++ source3/libsmb/cliconnect.c | 39 +- source3/libsmb/clidfs.c | 5 +- source3/libsmb/clientgen.c | 40 +- source3/libsmb/clikrb5.c | 2 +- source3/libsmb/clirap2.c | 2 +- source3/libsmb/libsmb_cache.c | 8 +- source3/libsmb/libsmbclient.c | 224 ++-- source3/libsmb/passchange.c | 108 +- source3/libsmb/trusts_util.c | 2 +- source3/locking/brlock.c | 304 +++-- source3/locking/locking.c | 87 +- source3/locking/posix.c | 1419 ++++++++++---------- source3/modules/charset_macosxfs.c | 2 +- source3/modules/vfs_afsacl.c | 3 +- source3/modules/vfs_audit.c | 60 +- source3/modules/vfs_cacheprime.c | 200 +++ source3/modules/vfs_cap.c | 124 +- source3/modules/vfs_catia.c | 80 +- source3/modules/vfs_commit.c | 189 +++ source3/modules/vfs_default.c | 1327 +++++++++++++++++++ source3/modules/vfs_default_quota.c | 16 +- source3/modules/vfs_expand_msdfs.c | 12 +- source3/modules/vfs_extd_audit.c | 60 +- source3/modules/vfs_fake_perms.c | 4 +- source3/modules/vfs_full_audit.c | 335 +++-- source3/modules/vfs_netatalk.c | 62 +- source3/modules/vfs_prealloc.c | 214 +++ source3/modules/vfs_readonly.c | 5 +- source3/modules/vfs_recycle.c | 64 +- source3/modules/vfs_shadow_copy.c | 28 +- source3/nmbd/nmbd_synclists.c | 33 +- source3/nsswitch/pam_winbind.c | 30 +- source3/nsswitch/wb_client.c | 110 ++ source3/nsswitch/wbinfo.c | 106 +- source3/nsswitch/winbindd.c | 1 + source3/nsswitch/winbindd.h | 9 + source3/nsswitch/winbindd_ads.c | 1 + source3/nsswitch/winbindd_async.c | 173 ++- source3/nsswitch/winbindd_cache.c | 136 +- source3/nsswitch/winbindd_cm.c | 2 +- source3/nsswitch/winbindd_dual.c | 1 + source3/nsswitch/winbindd_nss.h | 3 +- source3/nsswitch/winbindd_passdb.c | 64 +- source3/nsswitch/winbindd_reconnect.c | 25 + source3/nsswitch/winbindd_rpc.c | 56 +- source3/nsswitch/winbindd_sid.c | 40 +- source3/nsswitch/winbindd_user.c | 18 +- source3/nsswitch/winbindd_util.c | 2 +- source3/param/loadparm.c | 42 +- source3/passdb/login_cache.c | 2 +- source3/passdb/lookup_sid.c | 184 ++- source3/passdb/passdb.c | 20 +- source3/passdb/pdb_get_set.c | 21 +- source3/passdb/pdb_interface.c | 16 +- source3/passdb/pdb_ldap.c | 58 +- source3/passdb/pdb_nds.c | 11 +- source3/passdb/pdb_smbpasswd.c | 27 +- source3/passdb/pdb_tdb.c | 43 +- source3/passdb/secrets.c | 193 ++- source3/printing/nt_printing.c | 28 +- source3/printing/print_generic.c | 11 +- source3/printing/printfsp.c | 20 +- source3/printing/printing.c | 45 +- source3/profile/profile.c | 181 ++- source3/python/py_smb.c | 2 +- source3/registry/reg_printing.c | 4 +- source3/rpc_client/cli_lsarpc.c | 38 +- source3/rpc_client/cli_srvsvc.c | 29 +- source3/rpc_client/cli_unixinfo.c | 226 ++++ source3/rpc_client/ndr.c | 90 ++ source3/rpc_parse/parse_eventlog.c | 2 +- source3/rpc_parse/parse_lsa.c | 12 +- source3/rpc_parse/parse_ntsvcs.c | 4 +- source3/rpc_parse/parse_prs.c | 32 +- source3/rpc_parse/parse_reg.c | 44 +- source3/rpc_parse/parse_rpc.c | 11 + source3/rpc_parse/parse_samr.c | 50 +- source3/rpc_parse/parse_shutdown.c | 10 +- source3/rpc_parse/parse_spoolss.c | 2 +- source3/rpc_parse/parse_srv.c | 524 +++----- source3/rpc_parse/parse_svcctl.c | 14 +- source3/rpc_parse/parse_unixinfo.c | 266 ++++ source3/rpc_server/srv_dfs_nt.c | 10 +- source3/rpc_server/srv_lsa_nt.c | 31 +- source3/rpc_server/srv_pipe.c | 105 +- source3/rpc_server/srv_pipe_hnd.c | 9 +- source3/rpc_server/srv_samr_nt.c | 17 +- source3/rpc_server/srv_samr_util.c | 35 +- source3/rpc_server/srv_spoolss_nt.c | 98 +- source3/rpc_server/srv_srvsvc.c | 33 +- source3/rpc_server/srv_srvsvc_nt.c | 520 +++++--- source3/rpc_server/srv_svcctl_nt.c | 2 +- source3/rpc_server/srv_unixinfo.c | 163 +++ source3/rpc_server/srv_unixinfo_nt.c | 166 +++ source3/rpcclient/cmd_samr.c | 2 +- source3/rpcclient/cmd_spoolss.c | 28 +- source3/rpcclient/cmd_unixinfo.c | 195 +++ source3/rpcclient/rpcclient.c | 2 + source3/sam/idmap.c | 106 +- source3/sam/idmap_ad.c | 14 +- source3/sam/idmap_ldap.c | 41 +- source3/sam/idmap_rid.c | 13 +- source3/sam/idmap_smbldap.c | 10 +- source3/sam/idmap_tdb.c | 436 ++++--- source3/sam/idmap_util.c | 61 +- source3/script/mkproto.awk | 12 +- source3/script/mkproto.sh | 2 +- source3/script/tests/selftest.sh | 14 +- source3/script/tests/test_posix_s3.sh | 5 +- source3/script/tests/test_smbtorture_s3.sh | 2 +- source3/services/svc_netlogon.c | 4 +- source3/smbd/blocking.c | 40 +- source3/smbd/change_trust_pw.c | 4 +- source3/smbd/conn.c | 8 +- source3/smbd/connection.c | 169 ++- source3/smbd/dir.c | 21 +- source3/smbd/dosmode.c | 7 +- source3/smbd/error.c | 54 +- source3/smbd/fake_file.c | 23 +- source3/smbd/filename.c | 22 +- source3/smbd/files.c | 70 +- source3/smbd/lanman.c | 45 +- source3/smbd/mangle.c | 28 +- source3/smbd/mangle_hash.c | 18 +- source3/smbd/mangle_hash2.c | 44 +- source3/smbd/mangle_map.c | 4 +- source3/smbd/message.c | 3 +- source3/smbd/msdfs.c | 8 +- source3/smbd/nttrans.c | 98 +- source3/smbd/open.c | 229 ++-- source3/smbd/password.c | 19 +- source3/smbd/pipes.c | 17 + source3/smbd/posix_acls.c | 12 +- source3/smbd/process.c | 23 +- source3/smbd/reply.c | 172 +-- source3/smbd/server.c | 6 - source3/smbd/service.c | 63 +- source3/smbd/session.c | 45 +- source3/smbd/share_access.c | 5 +- source3/smbd/statcache.c | 8 +- source3/smbd/statvfs.c | 4 +- source3/smbd/trans2.c | 83 +- source3/smbd/uid.c | 4 +- source3/smbd/vfs-wrap.c | 1104 ---------------- source3/smbd/vfs.c | 217 ++-- source3/smbwrapper/smbw.c | 36 +- source3/smbwrapper/smbw.h | 2 +- source3/tdb/dump.c | 135 ++ source3/tdb/error.c | 58 + source3/tdb/freelist.c | 331 +++++ source3/tdb/io.c | 412 ++++++ source3/tdb/lock.c | 276 ++++ source3/tdb/open.c | 453 +++++++ source3/tdb/spinlock.c | 472 ------- source3/tdb/spinlock.h | 59 - source3/tdb/tdb.c | 1947 ++-------------------------- source3/tdb/tdb.h | 146 +-- source3/tdb/tdb_private.h | 241 ++++ source3/tdb/tdbback.c | 6 +- source3/tdb/tdbutil.c | 186 +-- source3/tdb/tdbutil.h | 38 +- source3/tdb/transaction.c | 1043 +++++++++++++++ source3/tdb/traverse.c | 334 +++++ source3/torture/cmd_vfs.c | 24 +- source3/torture/locktest.c | 12 +- source3/torture/locktest2.c | 1 + source3/torture/masktest.c | 2 +- source3/torture/nsstest.c | 52 +- source3/torture/pdbtest.c | 392 ++++++ source3/torture/rpctorture.c | 2 +- source3/torture/scanner.c | 12 +- source3/torture/torture.c | 126 +- source3/torture/vfstest.c | 2 +- source3/utils/debug2html.c | 4 + source3/utils/net.c | 8 +- source3/utils/net_ads.c | 11 +- source3/utils/net_idmap.c | 26 +- source3/utils/net_rpc.c | 23 +- source3/utils/net_rpc_printer.c | 25 +- source3/utils/net_rpc_registry.c | 67 +- source3/utils/net_rpc_samsync.c | 30 +- source3/utils/net_time.c | 10 +- source3/utils/ntlm_auth.c | 2 +- source3/utils/ntlm_auth_diagnostics.c | 8 +- source3/utils/sharesec.c | 414 ++++++ source3/utils/smbcontrol.c | 2 +- source3/utils/status.c | 390 +----- source3/utils/status_profile.c | 544 ++++++++ source3/web/diagnose.c | 10 +- source3/web/neg_lang.c | 4 +- source3/web/swat.c | 2 +- 259 files changed, 19157 insertions(+), 9109 deletions(-) create mode 100644 source3/include/locking.h create mode 100644 source3/include/rpc_unixinfo.h create mode 100644 source3/lib/util_reg.c create mode 100644 source3/libndr/libndr.h create mode 100644 source3/libndr/misc.h create mode 100644 source3/libndr/ndr.c create mode 100644 source3/libndr/ndr_basic.c create mode 100644 source3/libndr/ndr_misc.c create mode 100644 source3/libndr/ndr_sec.h create mode 100644 source3/libndr/ndr_sec_helper.c create mode 100644 source3/libndr/ndr_string.c create mode 100644 source3/libndr/security.h create mode 100644 source3/libndr/sid.c create mode 100644 source3/modules/vfs_cacheprime.c create mode 100644 source3/modules/vfs_commit.c create mode 100644 source3/modules/vfs_default.c create mode 100644 source3/modules/vfs_prealloc.c create mode 100644 source3/rpc_client/cli_unixinfo.c create mode 100644 source3/rpc_client/ndr.c create mode 100644 source3/rpc_parse/parse_unixinfo.c create mode 100644 source3/rpc_server/srv_unixinfo.c create mode 100644 source3/rpc_server/srv_unixinfo_nt.c create mode 100644 source3/rpcclient/cmd_unixinfo.c delete mode 100644 source3/smbd/vfs-wrap.c create mode 100644 source3/tdb/dump.c create mode 100644 source3/tdb/error.c create mode 100644 source3/tdb/freelist.c create mode 100644 source3/tdb/io.c create mode 100644 source3/tdb/lock.c create mode 100644 source3/tdb/open.c delete mode 100644 source3/tdb/spinlock.c delete mode 100644 source3/tdb/spinlock.h create mode 100644 source3/tdb/tdb_private.h create mode 100644 source3/tdb/transaction.c create mode 100644 source3/tdb/traverse.c create mode 100644 source3/torture/pdbtest.c create mode 100644 source3/utils/sharesec.c create mode 100644 source3/utils/status_profile.c diff --git a/source3/Doxyfile b/source3/Doxyfile index c1040781d84..cdcb658908a 100644 --- a/source3/Doxyfile +++ b/source3/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/source3/Makefile.in b/source3/Makefile.in index 127936125bf..3f586180f04 100644 --- a/source3/Makefile.in +++ b/source3/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/source3/aclocal.m4 b/source3/aclocal.m4 index af7ed7b4068..1f2120c68b3 100644 --- a/source3/aclocal.m4 +++ b/source3/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 +#include +#include + +/* 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/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index bedd318c3c3..8ad6329da98 100644 --- a/source3/auth/auth_domain.c +++ b/source3/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/source3/auth/auth_server.c b/source3/auth/auth_server.c index 7bec1b4128d..6e4dba0be2d 100644 --- a/source3/auth/auth_server.c +++ b/source3/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/source3/auth/auth_util.c b/source3/auth/auth_util.c index 493d7393d07..823bf8c3228 100644 --- a/source3/auth/auth_util.c +++ b/source3/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/source3/client/client.c b/source3/client/client.c index 3c2d7afe2d6..99fffa71232 100644 --- a/source3/client/client.c +++ b/source3/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/source3/client/clitar.c b/source3/client/clitar.c index 14c28acfc5a..f0d0ac595c2 100644 --- a/source3/client/clitar.c +++ b/source3/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/source3/client/mount.cifs.c b/source3/client/mount.cifs.c index ac98b992bb2..ab1f203412f 100755 --- a/source3/client/mount.cifs.c +++ b/source3/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/source3/client/smbctool.c b/source3/client/smbctool.c index fd385ee6817..b7042f99cb2 100644 --- a/source3/client/smbctool.c +++ b/source3/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/source3/client/smbmount.c b/source3/client/smbmount.c index 7a3ccb7630d..f1cd81198f0 100644 --- a/source3/client/smbmount.c +++ b/source3/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/source3/configure.in b/source3/configure.in index 884c2cea6ab..5359ff8bf41 100644 --- a/source3/configure.in +++ b/source3/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 ]) + 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 ],[struct statvfs buf; buf.f_fsid = 0], + samba_cv_fsid_int=yes,samba_cv_fsid_int=no)]) +if test x"$samba_cv_fsid_int" = x"yes"; then + AC_DEFINE(HAVE_FSID_INT, 1, [Whether statvfs.f_fsid is an integer]) +fi + if test $space = no; then # DEC Alpha running OSF/1 AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)]) @@ -5545,6 +5567,7 @@ SMB_MODULE(rpc_spoolss, \$(RPC_SPOOLSS_OBJ), "bin/librpc_spoolss.$SHLIBEXT", RPC SMB_MODULE(rpc_eventlog, \$(RPC_EVENTLOG_OBJ), "bin/librpc_eventlog.$SHLIBEXT", RPC) SMB_MODULE(rpc_samr, \$(RPC_SAMR_OBJ), "bin/librpc_samr.$SHLIBEXT", RPC) SMB_MODULE(rpc_echo, \$(RPC_ECHO_OBJ), "bin/librpc_echo.$SHLIBEXT", RPC) +SMB_MODULE(rpc_unixinfo, \$(RPC_UNIXINFO_OBJ), "bin/librpc_unixinfo.$SHLIBEXT", RPC) SMB_SUBSYSTEM(RPC,smbd/server.o) SMB_MODULE(idmap_ldap, sam/idmap_ldap.o, "bin/ldap.$SHLIBEXT", IDMAP) @@ -5568,6 +5591,7 @@ SMB_MODULE(auth_builtin, \$(AUTH_BUILTIN_OBJ), "bin/builtin.$SHLIBEXT", AUTH) SMB_MODULE(auth_script, \$(AUTH_SCRIPT_OBJ), "bin/script.$SHLIBEXT", AUTH) SMB_SUBSYSTEM(AUTH,auth/auth.o) +SMB_MODULE(vfs_default, \$(VFS_DEFAULT_OBJ), "bin/default.$SHLIBEXT", VFS) SMB_MODULE(vfs_recycle, \$(VFS_RECYCLE_OBJ), "bin/recycle.$SHLIBEXT", VFS) SMB_MODULE(vfs_audit, \$(VFS_AUDIT_OBJ), "bin/audit.$SHLIBEXT", VFS) SMB_MODULE(vfs_extd_audit, \$(VFS_EXTD_AUDIT_OBJ), "bin/extd_audit.$SHLIBEXT", VFS) @@ -5581,6 +5605,10 @@ SMB_MODULE(vfs_expand_msdfs, \$(VFS_EXPAND_MSDFS_OBJ), "bin/expand_msdfs.$SHLIBE SMB_MODULE(vfs_shadow_copy, \$(VFS_SHADOW_COPY_OBJ), "bin/shadow_copy.$SHLIBEXT", VFS) SMB_MODULE(vfs_afsacl, \$(VFS_AFSACL_OBJ), "bin/afsacl.$SHLIBEXT", VFS) SMB_MODULE(vfs_catia, \$(VFS_CATIA_OBJ), "bin/catia.$SHLIBEXT", VFS) +SMB_MODULE(vfs_cacheprime, \$(VFS_CACHEPRIME_OBJ), "bin/cacheprime.$SHLIBEXT", VFS) +SMB_MODULE(vfs_prealloc, \$(VFS_PREALLOC_OBJ), "bin/prealloc.$SHLIBEXT", VFS) +SMB_MODULE(vfs_commit, \$(VFS_COMMIT_OBJ), "bin/commit.$SHLIBEXT", VFS) + SMB_SUBSYSTEM(VFS,smbd/vfs.o) AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules]) @@ -5592,6 +5620,89 @@ if test "${ac_cv_prog_CC}" = "insure"; then CPPFLAGS="$CPPFLAGS -D__INSURE__" fi +################################################# +# If run from the build farm, enable NASTY hacks +################################################# +AC_MSG_CHECKING(whether to enable build farm hacks) +if test x"$RUN_FROM_BUILD_FARM" = x"yes"; then + AC_MSG_RESULT(yes) + AC_DEFINE(ENABLE_BUILD_FARM_HACKS, 1, [Defined if running in the build farm]) +else + AC_MSG_RESULT(no) +fi + +################################################# +# check for bad librt/libpthread interactions + +if test x"$samba_cv_HAVE_KERNEL_OPLOCKS_LINUX" = x"yes" -o \ + x"$samba_cv_HAVE_KERNEL_CHANGE_NOTIFY" = x"yes" -o \ + x"$samba_cv_HAVE_AIO64" = x"yes" -o \ + x"$samba_cv_HAVE_AIO" = x"yes" ; then + +SMB_IF_RTSIGNAL_BUG( + [ + # Have RT_SIGNAL bug, need to check whether the problem will + # affect anything we have configured. + + rt_do_error=no + if test x"$samba_cv_HAVE_KERNEL_OPLOCKS_LINUX" = x"yes"; then + if test x"$rt_signal_lease_ok" = x"no" ; then + rt_do_error=yes + fi + fi + + if test x"$samba_cv_HAVE_KERNEL_CHANGE_NOTIFY" = x"yes"; then + if test x"$rt_signal_notify_ok" = x"no" ; then + rt_do_error=yes + fi + fi + + if test x"$samba_cv_HAVE_AIO64" = x"yes" -o \ + x"$samba_cv_HAVE_AIO" = x"yes" ; then + if test x"$rt_signal_aio_ok" = x"no" ; then + rt_do_error=yes + fi + fi + + if test x"$rt_do_error" = x"yes" ; then + SMB_IS_LIBPTHREAD_LINKED( + [ + cat< #endif +#if HAVE_INTTYPES_H +#include +#endif + #ifdef TIME_WITH_SYS_TIME #include #include @@ -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/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index 5aca12554f3..42bf2373c1b 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/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/source3/include/locking.h b/source3/include/locking.h new file mode 100644 index 00000000000..983d59a853f --- /dev/null +++ b/source3/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/source3/include/mangle.h b/source3/include/mangle.h index 2bdef4ad646..3d19ef9ed4f 100644 --- a/source3/include/mangle.h +++ b/source3/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/source3/include/nt_status.h b/source3/include/nt_status.h index 14c83eba4b3..c48beafb6e7 100644 --- a/source3/include/nt_status.h +++ b/source3/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/source3/include/ntdomain.h b/source3/include/ntdomain.h index c27ec3675b4..0114df0e2d0 100644 --- a/source3/include/ntdomain.h +++ b/source3/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/source3/include/nterr.h b/source3/include/nterr.h index 417719625e7..6cf5a756d29 100644 --- a/source3/include/nterr.h +++ b/source3/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/source3/include/passdb.h b/source3/include/passdb.h index 74063d0fff1..35bb93aa31c 100644 --- a/source3/include/passdb.h +++ b/source3/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/source3/include/rpc_netlogon.h b/source3/include/rpc_netlogon.h index 9df7701de41..f80dc3121d1 100644 --- a/source3/include/rpc_netlogon.h +++ b/source3/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/source3/include/rpc_reg.h b/source3/include/rpc_reg.h index c454a1d6f94..883e2a8146a 100644 --- a/source3/include/rpc_reg.h +++ b/source3/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/source3/include/rpc_samr.h b/source3/include/rpc_samr.h index 910ccee1135..ed4e51837f7 100644 --- a/source3/include/rpc_samr.h +++ b/source3/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/source3/include/rpc_secdes.h b/source3/include/rpc_secdes.h index c385e41fd30..2ac60bd9b12 100644 --- a/source3/include/rpc_secdes.h +++ b/source3/include/rpc_secdes.h @@ -43,33 +43,6 @@ #define SEC_ACE_OBJECT_PRESENT 0x00000001 /* thanks for Jim McDonough */ #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/source3/include/rpc_srvsvc.h b/source3/include/rpc_srvsvc.h index f84054b878b..31032f64a4d 100644 --- a/source3/include/rpc_srvsvc.h +++ b/source3/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/source3/include/rpc_unixinfo.h b/source3/include/rpc_unixinfo.h new file mode 100644 index 00000000000..f2f4382fc47 --- /dev/null +++ b/source3/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/source3/include/session.h b/source3/include/session.h index f613afee09a..8c8faab5325 100644 --- a/source3/include/session.h +++ b/source3/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 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/source3/include/smb.h b/source3/include/smb.h index e0f2e8483cb..3109948f59e 100644 --- a/source3/include/smb.h +++ b/source3/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/source3/include/smb_macros.h b/source3/include/smb_macros.h index 554dbbc0878..e296ddd1403 100644 --- a/source3/include/smb_macros.h +++ b/source3/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/source3/include/smbprofile.h b/source3/include/smbprofile.h index b8a9a49be1a..d29f066796b 100644 --- a/source3/include/smbprofile.h +++ b/source3/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/source3/include/talloc.h b/source3/include/talloc.h index 17032ac7acc..db88ce6ed56 100644 --- a/source3/include/talloc.h +++ b/source3/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/source3/include/vfs.h b/source3/include/vfs.h index fb99d824125..6ef9e829bcc 100644 --- a/source3/include/vfs.h +++ b/source3/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/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index e08b386a6ac..2d6f8580f68 100644 --- a/source3/include/vfs_macros.h +++ b/source3/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/source3/lib/account_pol.c b/source3/lib/account_pol.c index 6bf7346fe7f..8d844741f5d 100644 --- a/source3/lib/account_pol.c +++ b/source3/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/source3/lib/afs.c b/source3/lib/afs.c index 8a304adcf0c..ea83fdebc25 100644 --- a/source3/lib/afs.c +++ b/source3/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 = ¤t_user.nt_user_token->user_sids[0]; pstring_sub(afs_username, "%s", sid_string_static(user_sid)); diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index 097d746a638..fffdf010a05 100644 --- a/source3/lib/charcnv.c +++ b/source3/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/source3/lib/data_blob.c b/source3/lib/data_blob.c index ccd0d27f47b..860ef5ad10f 100644 --- a/source3/lib/data_blob.c +++ b/source3/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/source3/lib/debug.c b/source3/lib/debug.c index 2b6c42b8eb0..bf75bdf3d3f 100644 --- a/source3/lib/debug.c +++ b/source3/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/source3/lib/popt_common.c b/source3/lib/popt_common.c index d29e171be08..0c0ed86dd1f 100644 --- a/source3/lib/popt_common.c +++ b/source3/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/source3/lib/socket_wrapper.c b/source3/lib/socket_wrapper.c index e9c1404d113..04c337267fd 100644 --- a/source3/lib/socket_wrapper.c +++ b/source3/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/source3/lib/substitute.c b/source3/lib/substitute.c index ff9deb8a5f0..430c8029b8f 100644 --- a/source3/lib/substitute.c +++ b/source3/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/source3/lib/system.c b/source3/lib/system.c index 2e5f42307bd..24c726b8f75 100644 --- a/source3/lib/system.c +++ b/source3/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 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/source3/lib/util_str.c b/source3/lib/util_str.c index 938fb0f47b0..2580521c3b9 100644 --- a/source3/lib/util_str.c +++ b/source3/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/source3/libads/dns.c b/source3/libads/dns.c index d2e263a9d1b..321b4355277 100644 --- a/source3/libads/dns.c +++ b/source3/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/source3/libads/ldap.c b/source3/libads/ldap.c index b017ff941b9..58eca99f9e1 100644 --- a/source3/libads/ldap.c +++ b/source3/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/source3/libads/sasl.c b/source3/libads/sasl.c index a12af43eb37..3c0bea93d6c 100644 --- a/source3/libads/sasl.c +++ b/source3/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/source3/libmsrpc/cac_lsarpc.c b/source3/libmsrpc/cac_lsarpc.c index 7b62b4d4627..72c429e7247 100644 --- a/source3/libmsrpc/cac_lsarpc.c +++ b/source3/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/source3/libmsrpc/cac_samr.c b/source3/libmsrpc/cac_samr.c index 60c6562988e..a29ee7a41eb 100644 --- a/source3/libmsrpc/cac_samr.c +++ b/source3/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/source3/libmsrpc/cac_svcctl.c b/source3/libmsrpc/cac_svcctl.c index 83dc0364930..51a5b5d2dd9 100644 --- a/source3/libmsrpc/cac_svcctl.c +++ b/source3/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/source3/libmsrpc/cac_winreg.c b/source3/libmsrpc/cac_winreg.c index 6ef898eb16d..91db33d2953 100644 --- a/source3/libmsrpc/cac_winreg.c +++ b/source3/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/source3/libmsrpc/libmsrpc_internal.c b/source3/libmsrpc/libmsrpc_internal.c index 3a47361db29..a097bc181ce 100644 --- a/source3/libmsrpc/libmsrpc_internal.c +++ b/source3/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/source3/libndr/libndr.h b/source3/libndr/libndr.h new file mode 100644 index 00000000000..817c4610751 --- /dev/null +++ b/source3/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/source3/libndr/misc.h b/source3/libndr/misc.h new file mode 100644 index 00000000000..d929379870f --- /dev/null +++ b/source3/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/source3/libndr/ndr.c b/source3/libndr/ndr.c new file mode 100644 index 00000000000..2aff7a88f0a --- /dev/null +++ b/source3/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;idepth;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;idepth;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/source3/libndr/ndr_basic.c b/source3/libndr/ndr_basic.c new file mode 100644 index 00000000000..31a48f67c45 --- /dev/null +++ b/source3/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;idata[i] != 0) { + break; + } + } + if (ioffset;idata[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;iprint(ndr, "%-25s: %s", name, s); + return; + } + + ndr->print(ndr, "%s: ARRAY(%d)", name, count); + ndr->depth++; + for (i=0;idepth--; +} + +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/source3/libndr/ndr_misc.c b/source3/libndr/ndr_misc.c new file mode 100644 index 00000000000..2f9004ae666 --- /dev/null +++ b/source3/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;itime_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/source3/libndr/ndr_sec.h b/source3/libndr/ndr_sec.h new file mode 100644 index 00000000000..0858eac72c5 --- /dev/null +++ b/source3/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/source3/libndr/ndr_sec_helper.c b/source3/libndr/ndr_sec_helper.c new file mode 100644 index 00000000000..edbdd9a40eb --- /dev/null +++ b/source3/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;inum_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/source3/libndr/ndr_string.c b/source3/libndr/ndr_string.c new file mode 100644 index 00000000000..d6c842a6537 --- /dev/null +++ b/source3/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;idepth--; +} + +/** + * 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/source3/libndr/security.h b/source3/libndr/security.h new file mode 100644 index 00000000000..8f790f387ed --- /dev/null +++ b/source3/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/source3/libndr/sid.c b/source3/libndr/sid.c new file mode 100644 index 00000000000..0bb42a3683b --- /dev/null +++ b/source3/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/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 7f5b5d7fa57..4c3c4f45650 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/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" . - */ + /* 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/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index e564bc42957..4280b0628eb 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/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/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 8342df0f1d1..4608d40d462 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/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/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c index abb3843bacb..d40fc31dc44 100644 --- a/source3/libsmb/clikrb5.c +++ b/source3/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/source3/libsmb/clirap2.c b/source3/libsmb/clirap2.c index 147683689d6..3c23310f66c 100644 --- a/source3/libsmb/clirap2.c +++ b/source3/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/source3/libsmb/libsmb_cache.c b/source3/libsmb/libsmb_cache.c index 5d948ea5e25..8c4fd7c89f7 100644 --- a/source3/libsmb/libsmb_cache.c +++ b/source3/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/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c index ca2624305e6..db788f46e9b 100644 --- a/source3/libsmb/libsmbclient.c +++ b/source3/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/source3/libsmb/passchange.c b/source3/libsmb/passchange.c index 673671d28db..0d3dcf4d755 100644 --- a/source3/libsmb/passchange.c +++ b/source3/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 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/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 55108bf72f2..e4061883eb1 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/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/source3/locking/brlock.c b/source3/locking/brlock.c index 574552e9e21..9c8a7a17ee6 100644 --- a/source3/locking/brlock.c +++ b/source3/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/source3/locking/locking.c b/source3/locking/locking.c index 9d3ca956014..ac50c9b648f 100644 --- a/source3/locking/locking.c +++ b/source3/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/source3/locking/posix.c b/source3/locking/posix.c index 4a5f59b622d..59b62170e82 100644 --- a/source3/locking/posix.c +++ b/source3/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 @@ -27,753 +27,694 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_LOCKING -/* - * The POSIX locking database handle. - */ - -static TDB_CONTEXT *posix_lock_tdb; - /* * The pending close database handle. */ static TDB_CONTEXT *posix_pending_close_tdb; -/* - * The data in POSIX lock records is an unsorted linear array of these - * records. It is unnecessary to store the count as tdb provides the - * size of the record. - */ - -struct posix_lock { - int fd; - SMB_OFF_T start; - SMB_OFF_T size; - int lock_type; -}; - -/* - * The data in POSIX pending close records is an unsorted linear array of int - * records. It is unnecessary to store the count as tdb provides the - * size of the record. - */ - -/* The key used in both the POSIX databases. */ - -struct posix_lock_key { - SMB_DEV_T device; - SMB_INO_T inode; -}; +/**************************************************************************** + First - the functions that deal with the underlying system locks - these + functions are used no matter if we're mapping CIFS Windows locks or CIFS + POSIX locks onto POSIX. +****************************************************************************/ -/******************************************************************* - Form a static locking key for a dev/inode pair. -******************************************************************/ +/**************************************************************************** + Utility function to map a lock type correctly depending on the open + mode of a file. +****************************************************************************/ -static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) +static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type) { - static struct posix_lock_key key; - TDB_DATA kbuf; + if((lock_type == WRITE_LOCK) && !fsp->can_write) { + /* + * Many UNIX's cannot get a write lock on a file opened read-only. + * Win32 locking semantics allow this. + * Do the best we can and attempt a read-only lock. + */ + DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n")); + return F_RDLCK; + } - memset(&key, '\0', sizeof(key)); - key.device = dev; - key.inode = inode; - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); - return kbuf; + /* + * This return should be the most normal, as we attempt + * to always open files read/write. + */ + + return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK; } -/******************************************************************* - Convenience function to get a key from an fsp. -******************************************************************/ +/**************************************************************************** + Debugging aid :-). +****************************************************************************/ -static TDB_DATA locking_key_fsp(files_struct *fsp) +static const char *posix_lock_type_name(int lock_type) { - return locking_key(fsp->dev, fsp->inode); + return (lock_type == F_RDLCK) ? "READ" : "WRITE"; } /**************************************************************************** - Add an fd to the pending close tdb. + Check to see if the given unsigned lock range is within the possible POSIX + range. Modifies the given args to be in range if possible, just returns + False if not. ****************************************************************************/ -static BOOL add_fd_to_close_entry(files_struct *fsp) +static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, + SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) { - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; + SMB_OFF_T offset = (SMB_OFF_T)u_offset; + SMB_OFF_T count = (SMB_OFF_T)u_count; - dbuf.dptr = NULL; - dbuf.dsize = 0; + /* + * For the type of system we are, attempt to + * find the maximum positive lock offset as an SMB_OFF_T. + */ - dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); +#if defined(MAX_POSITIVE_LOCK_OFFSET) /* Some systems have arbitrary limits. */ - dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); - if (!dbuf.dptr) { - DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n")); + SMB_OFF_T max_positive_lock_offset = (MAX_POSITIVE_LOCK_OFFSET); + +#elif defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) + + /* + * In this case SMB_OFF_T is 64 bits, + * and the underlying system can handle 64 bit signed locks. + */ + + SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4); + SMB_OFF_T mask = (mask2<<1); + SMB_OFF_T max_positive_lock_offset = ~mask; + +#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + + /* + * In this case either SMB_OFF_T is 32 bits, + * or the underlying system cannot handle 64 bit signed locks. + * All offsets & counts must be 2^31 or less. + */ + + SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF; + +#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + + /* + * POSIX locks of length zero mean lock to end-of-file. + * Win32 locks of length zero are point probes. Ignore + * any Win32 locks of length zero. JRA. + */ + + if (count == (SMB_OFF_T)0) { + DEBUG(10,("posix_lock_in_range: count = 0, ignoring.\n")); return False; } - memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int)); - dbuf.dsize += sizeof(int); + /* + * If the given offset was > max_positive_lock_offset then we cannot map this at all + * ignore this lock. + */ - if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - DEBUG(0,("add_fd_to_close_entry: tdb_store fail !\n")); + if (u_offset & ~((SMB_BIG_UINT)max_positive_lock_offset)) { + DEBUG(10,("posix_lock_in_range: (offset = %.0f) offset > %.0f and we cannot handle this. Ignoring lock.\n", + (double)u_offset, (double)((SMB_BIG_UINT)max_positive_lock_offset) )); + return False; } - SAFE_FREE(dbuf.dptr); + /* + * We must truncate the count to less than max_positive_lock_offset. + */ + + if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset)) { + count = max_positive_lock_offset; + } + + /* + * Truncate count to end at max lock offset. + */ + + if (offset + count < 0 || offset + count > max_positive_lock_offset) { + count = max_positive_lock_offset - offset; + } + + /* + * If we ate all the count, ignore this lock. + */ + + if (count == 0) { + DEBUG(10,("posix_lock_in_range: Count = 0. Ignoring lock u_offset = %.0f, u_count = %.0f\n", + (double)u_offset, (double)u_count )); + return False; + } + + /* + * The mapping was successful. + */ + + DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n", + (double)offset, (double)count )); + + *offset_out = offset; + *count_out = count; + return True; } /**************************************************************************** - Remove all fd entries for a specific dev/inode pair from the tdb. + Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and + broken NFS implementations. ****************************************************************************/ -static void delete_close_entries(files_struct *fsp) +static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { - TDB_DATA kbuf = locking_key_fsp(fsp); + BOOL ret; - if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) - DEBUG(0,("delete_close_entries: tdb_delete fail !\n")); -} + DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type)); -/**************************************************************************** - Get the array of POSIX pending close records for an open fsp. Caller must - free. Returns number of entries. -****************************************************************************/ + ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type); -static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries) -{ - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - size_t count = 0; + if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { - *entries = NULL; - dbuf.dptr = NULL; + DEBUG(0,("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", + (double)offset,(double)count)); + DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno))); + DEBUG(0,("on 32 bit NFS mounted file systems.\n")); - dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + /* + * If the offset is > 0x7FFFFFFF then this will cause problems on + * 32 bit NFS mounted filesystems. Just ignore it. + */ - if (!dbuf.dptr) { - return 0; - } + if (offset & ~((SMB_OFF_T)0x7fffffff)) { + DEBUG(0,("Offset greater than 31 bits. Returning success.\n")); + return True; + } - *entries = (int *)dbuf.dptr; - count = (size_t)(dbuf.dsize / sizeof(int)); + if (count & ~((SMB_OFF_T)0x7fffffff)) { + /* 32 bit NFS file system, retry with smaller offset */ + DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); + errno = 0; + count &= 0x7fffffff; + ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type); + } + } - return count; + DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed")); + return ret; } /**************************************************************************** - Get the array of POSIX locks for an fsp. Caller must free. Returns - number of entries. + Actual function that gets POSIX locks. Copes with 64 -> 32 bit cruft and + broken NFS implementations. ****************************************************************************/ -static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entries) +static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype) { - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - size_t count = 0; + pid_t pid; + BOOL ret; - *entries = NULL; + DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n", + fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype)); - dbuf.dptr = NULL; + ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid); - dbuf = tdb_fetch(posix_lock_tdb, kbuf); + if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { - if (!dbuf.dptr) { - return 0; - } + DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset %.0f, length %.0f returned\n", + (double)*poffset,(double)*pcount)); + DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno))); + DEBUG(0,("on 32 bit NFS mounted file systems.\n")); - *entries = (struct posix_lock *)dbuf.dptr; - count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); + /* + * If the offset is > 0x7FFFFFFF then this will cause problems on + * 32 bit NFS mounted filesystems. Just ignore it. + */ - return count; + if (*poffset & ~((SMB_OFF_T)0x7fffffff)) { + DEBUG(0,("Offset greater than 31 bits. Returning success.\n")); + return True; + } + + if (*pcount & ~((SMB_OFF_T)0x7fffffff)) { + /* 32 bit NFS file system, retry with smaller offset */ + DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); + errno = 0; + *pcount &= 0x7fffffff; + ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid); + } + } + + DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? "successful" : "failed")); + return ret; } /**************************************************************************** - Deal with pending closes needed by POSIX locking support. - Note that posix_locking_close_file() is expected to have been called - to delete all locks on this fsp before this function is called. + POSIX function to see if a file region is locked. Returns True if the + region is locked, False otherwise. ****************************************************************************/ -int fd_close_posix(struct connection_struct *conn, files_struct *fsp) +BOOL is_posix_locked(files_struct *fsp, + SMB_BIG_UINT *pu_offset, + SMB_BIG_UINT *pu_count, + enum brl_type *plock_type, + enum brl_flavour lock_flav) { - int saved_errno = 0; - int ret; - size_t count, i; - struct posix_lock *entries = NULL; - int *fd_array = NULL; - BOOL locks_on_other_fds = False; - - if (!lp_posix_locking(SNUM(conn))) { - /* - * No POSIX to worry about, just close. - */ - ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); - fsp->fh->fd = -1; - return ret; - } - - /* - * Get the number of outstanding POSIX locks on this dev/inode pair. - */ + SMB_OFF_T offset; + SMB_OFF_T count; + int posix_lock_type = map_posix_lock_type(fsp,*plock_type); - count = get_posix_lock_entries(fsp, &entries); + DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n", + fsp->fsp_name, (double)*pu_offset, (double)*pu_count, posix_lock_type_name(*plock_type) )); /* - * Check if there are any outstanding locks belonging to - * other fd's. This should never be the case if posix_locking_close_file() - * has been called first, but it never hurts to be *sure*. + * If the requested lock won't fit in the POSIX range, we will + * never set it, so presume it is not locked. */ - for (i = 0; i < count; i++) { - if (entries[i].fd != fsp->fh->fd) { - locks_on_other_fds = True; - break; - } + if(!posix_lock_in_range(&offset, &count, *pu_offset, *pu_count)) { + return False; } - if (locks_on_other_fds) { - - /* - * There are outstanding locks on this dev/inode pair on other fds. - * Add our fd to the pending close tdb and set fsp->fh->fd to -1. - */ - - if (!add_fd_to_close_entry(fsp)) { - SAFE_FREE(entries); - return -1; - } + if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) { + return False; + } - SAFE_FREE(entries); - fsp->fh->fd = -1; - return 0; + if (posix_lock_type == F_UNLCK) { + return False; } - SAFE_FREE(entries); + if (lock_flav == POSIX_LOCK) { + /* Only POSIX lock queries need to know the details. */ + *pu_offset = (SMB_BIG_UINT)offset; + *pu_count = (SMB_BIG_UINT)count; + *plock_type = (posix_lock_type == F_RDLCK) ? READ_LOCK : WRITE_LOCK; + } + return True; +} - /* - * No outstanding POSIX locks. Get the pending close fd's - * from the tdb and close them all. - */ +/**************************************************************************** + Next - the functions that deal with in memory database storing representations + of either Windows CIFS locks or POSIX CIFS locks. +****************************************************************************/ - count = get_posix_pending_close_entries(fsp, &fd_array); +/* The key used in the in-memory POSIX databases. */ - if (count) { - DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); +struct lock_ref_count_key { + SMB_DEV_T device; + SMB_INO_T inode; + char r; +}; - for(i = 0; i < count; i++) { - if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) { - saved_errno = errno; - } - } +struct fd_key { + SMB_DEV_T device; + SMB_INO_T inode; +}; - /* - * Delete all fd's stored in the tdb - * for this dev/inode pair. - */ +/******************************************************************* + Form a static locking key for a dev/inode pair for the fd array. +******************************************************************/ - delete_close_entries(fsp); - } +static TDB_DATA fd_array_key(SMB_DEV_T dev, SMB_INO_T inode) +{ + static struct fd_key key; + TDB_DATA kbuf; - SAFE_FREE(fd_array); + memset(&key, '\0', sizeof(key)); + key.device = dev; + key.inode = inode; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + return kbuf; +} - /* - * Finally close the fd associated with this fsp. - */ +/******************************************************************* + Form a static locking key for a dev/inode pair for the lock ref count +******************************************************************/ - ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); +static TDB_DATA locking_ref_count_key(SMB_DEV_T dev, SMB_INO_T inode) +{ + static struct lock_ref_count_key key; + TDB_DATA kbuf; - if (saved_errno != 0) { - errno = saved_errno; - ret = -1; - } + memset(&key, '\0', sizeof(key)); + key.device = dev; + key.inode = inode; + key.r = 'r'; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + return kbuf; +} - fsp->fh->fd = -1; +/******************************************************************* + Convenience function to get an fd_array key from an fsp. +******************************************************************/ - return ret; +static TDB_DATA fd_array_key_fsp(files_struct *fsp) +{ + return fd_array_key(fsp->dev, fsp->inode); } -/**************************************************************************** - Debugging aid :-). -****************************************************************************/ +/******************************************************************* + Convenience function to get a lock ref count key from an fsp. +******************************************************************/ -static const char *posix_lock_type_name(int lock_type) +static TDB_DATA locking_ref_count_key_fsp(files_struct *fsp) { - return (lock_type == F_RDLCK) ? "READ" : "WRITE"; + return locking_ref_count_key(fsp->dev, fsp->inode); } -/**************************************************************************** - Delete a POSIX lock entry by index number. Used if the tdb add succeeds, but - then the POSIX fcntl lock fails. -****************************************************************************/ +/******************************************************************* + Create the in-memory POSIX lock databases. +********************************************************************/ -static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry) +BOOL posix_locking_init(int read_only) { - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - struct posix_lock *locks; - size_t count; - - dbuf.dptr = NULL; + if (posix_pending_close_tdb) { + return True; + } - dbuf = tdb_fetch(posix_lock_tdb, kbuf); - - if (!dbuf.dptr) { - DEBUG(10,("delete_posix_lock_entry_by_index: tdb_fetch failed !\n")); - goto fail; + if (!posix_pending_close_tdb) { + posix_pending_close_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, + read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); } - - count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); - locks = (struct posix_lock *)dbuf.dptr; - - if (count == 1) { - tdb_delete(posix_lock_tdb, kbuf); - } else { - if (entry < count-1) { - memmove(&locks[entry], &locks[entry+1], sizeof(struct posix_lock)*((count-1) - entry)); - } - dbuf.dsize -= sizeof(struct posix_lock); - tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); + if (!posix_pending_close_tdb) { + DEBUG(0,("Failed to open POSIX pending close database.\n")); + return False; } - SAFE_FREE(dbuf.dptr); + return True; +} + +/******************************************************************* + Delete the in-memory POSIX lock databases. +********************************************************************/ +BOOL posix_locking_end(void) +{ + if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0) { + return False; + } return True; +} - fail: +/**************************************************************************** + Next - the functions that deal with storing fd's that have outstanding + POSIX locks when closed. +****************************************************************************/ - SAFE_FREE(dbuf.dptr); - return False; -} +/**************************************************************************** + The records in posix_pending_close_tdb are composed of an array of ints + keyed by dev/ino pair. + The first int is a reference count of the number of outstanding locks on + all open fd's on this dev/ino pair. Any subsequent ints are the fd's that + were open on this dev/ino pair that should have been closed, but can't as + the lock ref count is non zero. +****************************************************************************/ /**************************************************************************** - Add an entry into the POSIX locking tdb. We return the index number of the - added lock (used in case we need to delete *exactly* this entry). Returns - False on fail, True on success. + Keep a reference count of the number of Windows locks open on this dev/ino + pair. Creates entry if it doesn't exist. ****************************************************************************/ -static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type, size_t *pentry_num) +static void increment_windows_lock_ref_count(files_struct *fsp) { - TDB_DATA kbuf = locking_key_fsp(fsp); + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); TDB_DATA dbuf; - struct posix_lock pl; - - dbuf.dptr = NULL; - dbuf.dsize = 0; + int lock_ref_count; - dbuf = tdb_fetch(posix_lock_tdb, kbuf); + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + if (dbuf.dptr == NULL) { + dbuf.dptr = (char *)SMB_MALLOC_P(int); + if (!dbuf.dptr) { + smb_panic("increment_windows_lock_ref_count: malloc fail.\n"); + } + memset(dbuf.dptr, '\0', sizeof(int)); + dbuf.dsize = sizeof(int); + } - *pentry_num = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); + memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); + lock_ref_count++; + memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); + + if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { + smb_panic("increment_windows_lock_ref_count: tdb_store_fail.\n"); + } + SAFE_FREE(dbuf.dptr); - /* - * Add new record. - */ + DEBUG(10,("increment_windows_lock_ref_count for file now %s = %d\n", + fsp->fsp_name, lock_ref_count )); +} - pl.fd = fsp->fh->fd; - pl.start = start; - pl.size = size; - pl.lock_type = lock_type; +static void decrement_windows_lock_ref_count(files_struct *fsp) +{ + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); + TDB_DATA dbuf; + int lock_ref_count; - dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(struct posix_lock)); + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); if (!dbuf.dptr) { - DEBUG(0,("add_posix_lock_entry: Realloc fail !\n")); - goto fail; + smb_panic("decrement_windows_lock_ref_count: logic error.\n"); } - memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(struct posix_lock)); - dbuf.dsize += sizeof(struct posix_lock); + memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); + lock_ref_count--; + memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); - if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - DEBUG(0,("add_posix_lock: Failed to add lock entry on file %s\n", fsp->fsp_name)); - goto fail; + if (lock_ref_count < 0) { + smb_panic("decrement_windows_lock_ref_count: lock_count logic error.\n"); } + if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { + smb_panic("decrement_windows_lock_ref_count: tdb_store_fail.\n"); + } SAFE_FREE(dbuf.dptr); - DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: dev=%.0f inode=%.0f\n", - fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, - (double)fsp->dev, (double)fsp->inode )); - - return True; - - fail: - - SAFE_FREE(dbuf.dptr); - return False; -} - -/**************************************************************************** - Calculate if locks have any overlap at all. -****************************************************************************/ - -static BOOL does_lock_overlap(SMB_OFF_T start1, SMB_OFF_T size1, SMB_OFF_T start2, SMB_OFF_T size2) -{ - if (start1 >= start2 && start1 <= start2 + size2) - return True; - - if (start1 < start2 && start1 + size1 > start2) - return True; - - return False; + DEBUG(10,("decrement_windows_lock_ref_count for file now %s = %d\n", + fsp->fsp_name, lock_ref_count )); } /**************************************************************************** - Delete an entry from the POSIX locking tdb. Returns a copy of the entry being - deleted and the number of records that are overlapped by this one, or -1 on error. + Ensure the lock ref count is zero. ****************************************************************************/ -static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, struct posix_lock *pl) +void zero_windows_lock_ref_count(files_struct *fsp) { - TDB_DATA kbuf = locking_key_fsp(fsp); + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); TDB_DATA dbuf; - struct posix_lock *locks; - size_t i, count; - BOOL found = False; - int num_overlapping_records = 0; - - dbuf.dptr = NULL; - - dbuf = tdb_fetch(posix_lock_tdb, kbuf); + int lock_ref_count; + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); if (!dbuf.dptr) { - DEBUG(10,("delete_posix_lock_entry: tdb_fetch failed !\n")); - goto fail; + return; } - /* There are existing locks - find a match. */ - locks = (struct posix_lock *)dbuf.dptr; - count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); - - /* - * Search for and delete the first record that matches the - * unlock criteria. - */ - - for (i=0; ifd == fsp->fh->fd && - entry->start == start && - entry->size == size) { - - /* Make a copy */ - *pl = *entry; - - /* Found it - delete it. */ - if (count == 1) { - tdb_delete(posix_lock_tdb, kbuf); - } else { - if (i < count-1) { - memmove(&locks[i], &locks[i+1], sizeof(struct posix_lock)*((count-1) - i)); - } - dbuf.dsize -= sizeof(struct posix_lock); - tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); - } - count--; - found = True; - break; - } + memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); + if (lock_ref_count < 0) { + smb_panic("zero_windows_lock_ref_count: lock_count logic error.\n"); } - if (!found) - goto fail; - - /* - * Count the number of entries that are - * overlapped by this unlock request. - */ - - for (i = 0; i < count; i++) { - struct posix_lock *entry = &locks[i]; - - if (fsp->fh->fd == entry->fd && - does_lock_overlap( start, size, entry->start, entry->size)) - num_overlapping_records++; + lock_ref_count = 0; + memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); + + if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { + smb_panic("zero_windows_lock_ref_count: tdb_store_fail.\n"); } - - DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n", - posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size, - (unsigned int)num_overlapping_records )); - SAFE_FREE(dbuf.dptr); - return num_overlapping_records; - - fail: - - SAFE_FREE(dbuf.dptr); - return -1; + DEBUG(10,("zero_windows_lock_ref_count for file now %s = %d\n", + fsp->fsp_name, lock_ref_count )); } /**************************************************************************** - Utility function to map a lock type correctly depending on the open - mode of a file. + Fetch the lock ref count. ****************************************************************************/ -static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type) +static int get_windows_lock_ref_count(files_struct *fsp) { - if((lock_type == WRITE_LOCK) && !fsp->can_write) { - /* - * Many UNIX's cannot get a write lock on a file opened read-only. - * Win32 locking semantics allow this. - * Do the best we can and attempt a read-only lock. - */ - DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n")); - return F_RDLCK; - } -#if 0 - /* We no longer open files write-only. */ - else if((lock_type == READ_LOCK) && !fsp->can_read) { - /* - * Ditto for read locks on write only files. - */ - DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n")); - return F_WRLCK; - } -#endif + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); + TDB_DATA dbuf; + int lock_ref_count; - /* - * This return should be the most normal, as we attempt - * to always open files read/write. - */ + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + if (!dbuf.dptr) { + lock_ref_count = 0; + } else { + memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); + } - return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK; + DEBUG(10,("get_windows_lock_count for file %s = %d\n", + fsp->fsp_name, lock_ref_count )); + return lock_ref_count; } /**************************************************************************** - Check to see if the given unsigned lock range is within the possible POSIX - range. Modifies the given args to be in range if possible, just returns - False if not. + Delete a lock_ref_count entry. ****************************************************************************/ -static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, - SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) +static void delete_windows_lock_ref_count(files_struct *fsp) { - SMB_OFF_T offset = (SMB_OFF_T)u_offset; - SMB_OFF_T count = (SMB_OFF_T)u_count; - - /* - * For the type of system we are, attempt to - * find the maximum positive lock offset as an SMB_OFF_T. - */ - -#if defined(MAX_POSITIVE_LOCK_OFFSET) /* Some systems have arbitrary limits. */ - - SMB_OFF_T max_positive_lock_offset = (MAX_POSITIVE_LOCK_OFFSET); - -#elif defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS) + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); - /* - * In this case SMB_OFF_T is 64 bits, - * and the underlying system can handle 64 bit signed locks. - */ - - SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4); - SMB_OFF_T mask = (mask2<<1); - SMB_OFF_T max_positive_lock_offset = ~mask; - -#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + /* Not a bug if it doesn't exist - no locks were ever granted. */ + tdb_delete(posix_pending_close_tdb, kbuf); + DEBUG(10,("delete_windows_lock_ref_count for file %s\n", fsp->fsp_name)); +} - /* - * In this case either SMB_OFF_T is 32 bits, - * or the underlying system cannot handle 64 bit signed locks. - * All offsets & counts must be 2^31 or less. - */ +/**************************************************************************** + Add an fd to the pending close tdb. +****************************************************************************/ - SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF; +static void add_fd_to_close_entry(files_struct *fsp) +{ + TDB_DATA kbuf = fd_array_key_fsp(fsp); + TDB_DATA dbuf; -#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */ + dbuf.dptr = NULL; + dbuf.dsize = 0; - /* - * POSIX locks of length zero mean lock to end-of-file. - * Win32 locks of length zero are point probes. Ignore - * any Win32 locks of length zero. JRA. - */ + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - if (count == (SMB_OFF_T)0) { - DEBUG(10,("posix_lock_in_range: count = 0, ignoring.\n")); - return False; + dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); + if (!dbuf.dptr) { + smb_panic("add_fd_to_close_entry: Realloc fail !\n"); } - /* - * If the given offset was > max_positive_lock_offset then we cannot map this at all - * ignore this lock. - */ + memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int)); + dbuf.dsize += sizeof(int); - if (u_offset & ~((SMB_BIG_UINT)max_positive_lock_offset)) { - DEBUG(10,("posix_lock_in_range: (offset = %.0f) offset > %.0f and we cannot handle this. Ignoring lock.\n", - (double)u_offset, (double)((SMB_BIG_UINT)max_positive_lock_offset) )); - return False; + if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { + smb_panic("add_fd_to_close_entry: tdb_store_fail.\n"); } - /* - * We must truncate the count to less than max_positive_lock_offset. - */ - - if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset)) - count = max_positive_lock_offset; + DEBUG(10,("add_fd_to_close_entry: added fd %d file %s\n", + fsp->fh->fd, fsp->fsp_name )); - /* - * Truncate count to end at max lock offset. - */ + SAFE_FREE(dbuf.dptr); +} - if (offset + count < 0 || offset + count > max_positive_lock_offset) - count = max_positive_lock_offset - offset; +/**************************************************************************** + Remove all fd entries for a specific dev/inode pair from the tdb. +****************************************************************************/ - /* - * If we ate all the count, ignore this lock. - */ +static void delete_close_entries(files_struct *fsp) +{ + TDB_DATA kbuf = fd_array_key_fsp(fsp); - if (count == 0) { - DEBUG(10,("posix_lock_in_range: Count = 0. Ignoring lock u_offset = %.0f, u_count = %.0f\n", - (double)u_offset, (double)u_count )); - return False; + if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) { + smb_panic("delete_close_entries: tdb_delete fail !\n"); } - - /* - * The mapping was successful. - */ - - DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n", - (double)offset, (double)count )); - - *offset_out = offset; - *count_out = count; - - return True; } /**************************************************************************** - Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and - broken NFS implementations. + Get the array of POSIX pending close records for an open fsp. Caller must + free. Returns number of entries. ****************************************************************************/ -static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) +static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries) { - BOOL ret; - - DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type)); - - ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type); - - if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { - - DEBUG(0,("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", - (double)offset,(double)count)); - DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno))); - DEBUG(0,("on 32 bit NFS mounted file systems.\n")); + TDB_DATA kbuf = fd_array_key_fsp(fsp); + TDB_DATA dbuf; + size_t count = 0; - /* - * If the offset is > 0x7FFFFFFF then this will cause problems on - * 32 bit NFS mounted filesystems. Just ignore it. - */ + *entries = NULL; + dbuf.dptr = NULL; - if (offset & ~((SMB_OFF_T)0x7fffffff)) { - DEBUG(0,("Offset greater than 31 bits. Returning success.\n")); - return True; - } + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - if (count & ~((SMB_OFF_T)0x7fffffff)) { - /* 32 bit NFS file system, retry with smaller offset */ - DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); - errno = 0; - count &= 0x7fffffff; - ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type); - } + if (!dbuf.dptr) { + return 0; } - DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed")); - return ret; + *entries = (int *)dbuf.dptr; + count = (size_t)(dbuf.dsize / sizeof(int)); + + return count; } /**************************************************************************** - Actual function that gets POSIX locks. Copes with 64 -> 32 bit cruft and - broken NFS implementations. + Deal with pending closes needed by POSIX locking support. + Note that posix_locking_close_file() is expected to have been called + to delete all locks on this fsp before this function is called. ****************************************************************************/ -static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype) +int fd_close_posix(struct connection_struct *conn, files_struct *fsp) { - pid_t pid; - BOOL ret; - - DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n", - fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype)); - - ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid); + int saved_errno = 0; + int ret; + int *fd_array = NULL; + size_t count, i; - if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { + if (!lp_locking(SNUM(fsp->conn)) || !lp_posix_locking(SNUM(conn)) || lp_posix_cifsu_locktype()) { + /* + * No locking or POSIX to worry about or we want POSIX semantics + * which will lose all locks on all fd's open on this dev/inode, + * just close. + */ + ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); + fsp->fh->fd = -1; + return ret; + } - DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset %.0f, length %.0f returned\n", - (double)*poffset,(double)*pcount)); - DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno))); - DEBUG(0,("on 32 bit NFS mounted file systems.\n")); + if (get_windows_lock_ref_count(fsp)) { /* - * If the offset is > 0x7FFFFFFF then this will cause problems on - * 32 bit NFS mounted filesystems. Just ignore it. + * There are outstanding locks on this dev/inode pair on other fds. + * Add our fd to the pending close tdb and set fsp->fh->fd to -1. */ - if (*poffset & ~((SMB_OFF_T)0x7fffffff)) { - DEBUG(0,("Offset greater than 31 bits. Returning success.\n")); - return True; - } - - if (*pcount & ~((SMB_OFF_T)0x7fffffff)) { - /* 32 bit NFS file system, retry with smaller offset */ - DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); - errno = 0; - *pcount &= 0x7fffffff; - ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid); - } + add_fd_to_close_entry(fsp); + fsp->fh->fd = -1; + return 0; } - DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? "successful" : "failed")); - return ret; -} + /* + * No outstanding locks. Get the pending close fd's + * from the tdb and close them all. + */ + count = get_posix_pending_close_entries(fsp, &fd_array); -/**************************************************************************** - POSIX function to see if a file region is locked. Returns True if the - region is locked, False otherwise. -****************************************************************************/ + if (count) { + DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); -BOOL is_posix_locked(files_struct *fsp, - SMB_BIG_UINT *pu_offset, - SMB_BIG_UINT *pu_count, - enum brl_type *plock_type, - enum brl_flavour lock_flav) -{ - SMB_OFF_T offset; - SMB_OFF_T count; - int posix_lock_type = map_posix_lock_type(fsp,*plock_type); + for(i = 0; i < count; i++) { + if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) { + saved_errno = errno; + } + } - DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n", - fsp->fsp_name, (double)*pu_offset, (double)*pu_count, posix_lock_type_name(*plock_type) )); + /* + * Delete all fd's stored in the tdb + * for this dev/inode pair. + */ + + delete_close_entries(fsp); + } + + SAFE_FREE(fd_array); + + /* Don't need a lock ref count on this dev/ino anymore. */ + delete_windows_lock_ref_count(fsp); /* - * If the requested lock won't fit in the POSIX range, we will - * never set it, so presume it is not locked. + * Finally close the fd associated with this fsp. */ - if(!posix_lock_in_range(&offset, &count, *pu_offset, *pu_count)) { - return False; - } + ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); - if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) { - return False; - } + if (saved_errno != 0) { + errno = saved_errno; + ret = -1; + } - if (posix_lock_type == F_UNLCK) { - return False; - } + fsp->fh->fd = -1; - if (lock_flav == POSIX_LOCK) { - /* Only POSIX lock queries need to know the details. */ - *pu_offset = (SMB_BIG_UINT)offset; - *pu_count = (SMB_BIG_UINT)count; - *plock_type = (posix_lock_type == F_RDLCK) ? READ_LOCK : WRITE_LOCK; - } - return True; + return ret; } +/**************************************************************************** + Next - the functions that deal with the mapping CIFS Windows locks onto + the underlying system POSIX locks. +****************************************************************************/ + /* * Structure used when splitting a lock range * into a POSIX lock range. Doubly linked list. @@ -792,22 +733,14 @@ struct lock_list { understand it :-). ****************************************************************************/ -static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhead, files_struct *fsp) +static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, + struct lock_list *lhead, + const struct lock_context *lock_ctx, /* Lock context lhead belongs to. */ + files_struct *fsp, + const struct lock_struct *plocks, + int num_locks) { - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - struct posix_lock *locks; - size_t num_locks, i; - - dbuf.dptr = NULL; - - dbuf = tdb_fetch(posix_lock_tdb, kbuf); - - if (!dbuf.dptr) - return lhead; - - locks = (struct posix_lock *)dbuf.dptr; - num_locks = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); + int i; /* * Check the current lock list on this dev/inode pair. @@ -818,10 +751,19 @@ static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhea (double)lhead->start, (double)lhead->size )); for (i=0; ilock_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; ifsp_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/source3/modules/charset_macosxfs.c b/source3/modules/charset_macosxfs.c index 6f50d879ba4..a9003c7a826 100644 --- a/source3/modules/charset_macosxfs.c +++ b/source3/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/source3/modules/vfs_afsacl.c b/source3/modules/vfs_afsacl.c index 53272ca06fe..11498fccf9e 100644 --- a/source3/modules/vfs_afsacl.c +++ b/source3/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/source3/modules/vfs_audit.c b/source3/modules/vfs_audit.c index 9f5179a47ce..b240cafd29f 100644 --- a/source3/modules/vfs_audit.c +++ b/source3/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/source3/modules/vfs_cacheprime.c b/source3/modules/vfs_cacheprime.c new file mode 100644 index 00000000000..196441c4dda --- /dev/null +++ b/source3/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/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index b1bfcd75f2f..54f74dde678 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/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/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index 69735de3f43..f5c7e95794f 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/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/source3/modules/vfs_commit.c b/source3/modules/vfs_commit.c new file mode 100644 index 00000000000..9d817c017d2 --- /dev/null +++ b/source3/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/source3/modules/vfs_default.c b/source3/modules/vfs_default.c new file mode 100644 index 00000000000..82eec46d378 --- /dev/null +++ b/source3/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 + +**********************************************************/ + +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/source3/modules/vfs_default_quota.c b/source3/modules/vfs_default_quota.c index 9922a30315d..55dc287b88a 100644 --- a/source3/modules/vfs_default_quota.c +++ b/source3/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/source3/modules/vfs_expand_msdfs.c b/source3/modules/vfs_expand_msdfs.c index d22f6a7f98e..fdd9ac6fbd8 100644 --- a/source3/modules/vfs_expand_msdfs.c +++ b/source3/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/source3/modules/vfs_extd_audit.c b/source3/modules/vfs_extd_audit.c index cb8c3ffd6ab..1c3b25103c8 100644 --- a/source3/modules/vfs_extd_audit.c +++ b/source3/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/source3/modules/vfs_fake_perms.c b/source3/modules/vfs_fake_perms.c index decbe01d3ca..8bd8bbf5321 100644 --- a/source3/modules/vfs_fake_perms.c +++ b/source3/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/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index b9ffd6fc05f..fd15c5c3585 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/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/source3/modules/vfs_netatalk.c b/source3/modules/vfs_netatalk.c index e9d4360cd80..279160d9665 100644 --- a/source3/modules/vfs_netatalk.c +++ b/source3/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/source3/modules/vfs_prealloc.c b/source3/modules/vfs_prealloc.c new file mode 100644 index 00000000000..94db6423700 --- /dev/null +++ b/source3/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: 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 +#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: = + * where + * is the file extension in lower case + * 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/source3/modules/vfs_readonly.c b/source3/modules/vfs_readonly.c index ee9e40c2fca..e69f7dac016 100644 --- a/source3/modules/vfs_readonly.c +++ b/source3/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], ¤t_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/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c index 42f2f51416e..cb5eaffa54d 100644 --- a/source3/modules/vfs_recycle.c +++ b/source3/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/source3/modules/vfs_shadow_copy.c b/source3/modules/vfs_shadow_copy.c index db1c8d007dc..447c53d773a 100644 --- a/source3/modules/vfs_shadow_copy.c +++ b/source3/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/source3/nmbd/nmbd_synclists.c b/source3/nmbd/nmbd_synclists.c index 28ad92ed108..0e67c3f69c0 100644 --- a/source3/nmbd/nmbd_synclists.c +++ b/source3/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/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 78776256e99..118ba358e16 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/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/source3/nsswitch/wb_client.c b/source3/nsswitch/wb_client.c index de1edf054d1..b1a79471375 100644 --- a/source3/nsswitch/wb_client.c +++ b/source3/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; iresponse.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; irequest.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; imem_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/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index b267a3f7705..95a66420c59 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/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; istatus)) { + 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; itdb, 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/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index c1276bd9612..2b8a8898ac6 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/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/source3/nsswitch/winbindd_dual.c b/source3/nsswitch/winbindd_dual.c index 0cc35277b05..5908c78d9a8 100644 --- a/source3/nsswitch/winbindd_dual.c +++ b/source3/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/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h index 2afefcc12ca..6167a10c464 100644 --- a/source3/nsswitch/winbindd_nss.h +++ b/source3/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/source3/nsswitch/winbindd_passdb.c b/source3/nsswitch/winbindd_passdb.c index b949ea08085..d73917ef830 100644 --- a/source3/nsswitch/winbindd_passdb.c +++ b/source3/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; isid); - 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/source3/nsswitch/winbindd_reconnect.c b/source3/nsswitch/winbindd_reconnect.c index 7bc8be12131..8c5d59f9af0 100644 --- a/source3/nsswitch/winbindd_reconnect.c +++ b/source3/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/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index 27feea2f671..d8797ee2bc6 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/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; iname)); @@ -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/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c index d489e267cb2..4a9e17e4c70 100644 --- a/source3/nsswitch/winbindd_sid.c +++ b/source3/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/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index a73b5c394cd..8a0ebbafa50 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/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/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 67b94817adb..25ba20bb9f3 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/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/source3/param/loadparm.c b/source3/param/loadparm.c index b6c027f8714..c308378a227 100644 --- a/source3/param/loadparm.c +++ b/source3/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/source3/passdb/login_cache.c b/source3/passdb/login_cache.c index 9a19dcf437a..7fd3b47826f 100644 --- a/source3/passdb/login_cache.c +++ b/source3/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/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index dba43ed6c4f..a7a3fdc94d5 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/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; inum_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; jnum_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; jnum_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/source3/passdb/passdb.c b/source3/passdb/passdb.c index cbb30ead023..f74b1fbe3ba 100644 --- a/source3/passdb/passdb.c +++ b/source3/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/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index 2e69240b1af..3b774b510b0 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/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/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index a0310d0c71f..20aa72d24ee 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/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/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 4d0c84b5433..83f8d7183cc 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/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/source3/passdb/pdb_nds.c b/source3/passdb/pdb_nds.c index 08ad96efa4b..ab4a1a7f208 100644 --- a/source3/passdb/pdb_nds.c +++ b/source3/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/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index a8a42196d48..aec1db48b5d 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/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/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index f3ae4b7b02e..ac8cbbe91a3 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/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/source3/passdb/secrets.c b/source3/passdb/secrets.c index 04d6da2814a..f72a7cb8d54 100644 --- a/source3/passdb/secrets.c +++ b/source3/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/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index bcdf0e04625..4b71f6e0b66 100644 --- a/source3/printing/nt_printing.c +++ b/source3/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/source3/printing/print_generic.c b/source3/printing/print_generic.c index 1ea762695b1..aef4e50bfaa 100644 --- a/source3/printing/print_generic.c +++ b/source3/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/source3/printing/printfsp.c b/source3/printing/printfsp.c index c248851822b..5278c60f992 100644 --- a/source3/printing/printfsp.c +++ b/source3/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(¤t_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/source3/printing/printing.c b/source3/printing/printing.c index 9dd6bec0be4..bb756c88707 100644 --- a/source3/printing/printing.c +++ b/source3/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= 0); + SMB_ASSERT(val < PR_VALUE_MAX); + return valnames[val]; +} + #endif /* WITH_PROFILE */ diff --git a/source3/python/py_smb.c b/source3/python/py_smb.c index 679c113f397..f92a9e258dc 100644 --- a/source3/python/py_smb.c +++ b/source3/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/source3/registry/reg_printing.c b/source3/registry/reg_printing.c index 3ecff3d6964..338bc7af6a7 100644 --- a/source3/registry/reg_printing.c +++ b/source3/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/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c index 97d8eb621be..7e29332ef97 100644 --- a/source3/rpc_client/cli_lsarpc.c +++ b/source3/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/source3/rpc_client/cli_srvsvc.c b/source3/rpc_client/cli_srvsvc.c index 0d50e94d577..7b4818b4b06 100644 --- a/source3/rpc_client/cli_srvsvc.c +++ b/source3/rpc_client/cli_srvsvc.c @@ -5,6 +5,8 @@ Copyright (C) Tim Potter 2001 Copyright (C) Jim McDonough 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/source3/rpc_client/cli_unixinfo.c b/source3/rpc_client/cli_unixinfo.c new file mode 100644 index 00000000000..b9a960dfd1a --- /dev/null +++ b/source3/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; ipipe_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/source3/rpc_parse/parse_eventlog.c b/source3/rpc_parse/parse_eventlog.c index 4aff9734eed..addf433feb8 100644 --- a/source3/rpc_parse/parse_eventlog.c +++ b/source3/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/source3/rpc_parse/parse_lsa.c b/source3/rpc_parse/parse_lsa.c index ae4cff53e4b..919b7c39552 100644 --- a/source3/rpc_parse/parse_lsa.c +++ b/source3/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/source3/rpc_parse/parse_ntsvcs.c b/source3/rpc_parse/parse_ntsvcs.c index 599257e8020..ab5f3f75e87 100644 --- a/source3/rpc_parse/parse_ntsvcs.c +++ b/source3/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/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index 14e190892d7..29a3e60aa90 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/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/source3/rpc_parse/parse_reg.c b/source3/rpc_parse/parse_reg.c index fef1332e5c7..1820a595eda 100644 --- a/source3/rpc_parse/parse_reg.c +++ b/source3/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/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c index 2d166c773b4..240cac886cf 100644 --- a/source3/rpc_parse/parse_rpc.c +++ b/source3/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/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index 9026d503c30..26da7b426d7 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/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/source3/rpc_parse/parse_shutdown.c b/source3/rpc_parse/parse_shutdown.c index da338077333..8c417c05dce 100644 --- a/source3/rpc_parse/parse_shutdown.c +++ b/source3/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/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c index 2884883e893..8d4a757a74a 100644 --- a/source3/rpc_parse/parse_spoolss.c +++ b/source3/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/source3/rpc_parse/parse_srv.c b/source3/rpc_parse/parse_srv.c index 7d15eda630f..5123d1c2cca 100644 --- a/source3/rpc_parse/parse_srv.c +++ b/source3/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; } @@ -1698,54 +1654,33 @@ static BOOL srv_io_srv_sess_info_0(const char *desc, SRV_SESS_INFO_0 *ss0, prs_s return True; } -/******************************************************************* - Inits a SESS_INFO_1_STR structure -********************************************************************/ - -void init_srv_sess_info1_str(SESS_INFO_1_STR *ss1, const char *name, const char *user) -{ - DEBUG(5,("init_srv_sess_info1_str\n")); - - init_unistr2(&ss1->uni_name, name, UNI_STR_TERMINATE); - init_unistr2(&ss1->uni_user, user, UNI_STR_TERMINATE); -} - -/******************************************************************* - Reads or writes a structure. -********************************************************************/ - -static BOOL srv_io_sess_info1_str(const char *desc, SESS_INFO_1_STR *ss1, prs_struct *ps, int depth) -{ - if (ss1 == NULL) - return False; - - prs_debug(ps, depth, desc, "srv_io_sess_info1_str"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!smb_io_unistr2("", &ss1->uni_name, True, ps, depth)) - return False; - if(!smb_io_unistr2("", &(ss1->uni_user), True, ps, depth)) - return False; - - return True; -} - /******************************************************************* Inits a SESS_INFO_1 structure ********************************************************************/ -void init_srv_sess_info1(SESS_INFO_1 *ss1, - const char *name, const char *user, - uint32 num_opens, uint32 open_time, uint32 idle_time, - uint32 user_flags) +void init_srv_sess_info1( SESS_INFO_1 *ss1, const char *name, const char *user, + uint32 num_opens, uint32 open_time, uint32 idle_time, + uint32 user_flags) { DEBUG(5,("init_srv_sess_info1: %s\n", name)); - ss1->ptr_name = (name != NULL) ? 1 : 0; - ss1->ptr_user = (user != NULL) ? 1 : 0; + ZERO_STRUCTP( ss1 ); + + if ( name ) { + if ( (ss1->sharename = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) { + DEBUG(0,("init_srv_sess_info0: talloc failed!\n")); + return; + } + init_unistr2( ss1->sharename, name, UNI_STR_TERMINATE ); + } + + if ( user ) { + if ( (ss1->username = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) { + DEBUG(0,("init_srv_sess_info0: talloc failed!\n")); + return; + } + init_unistr2( ss1->username, user, UNI_STR_TERMINATE ); + } ss1->num_opens = num_opens; ss1->open_time = open_time; @@ -1753,37 +1688,6 @@ void init_srv_sess_info1(SESS_INFO_1 *ss1, ss1->user_flags = user_flags; } -/******************************************************************* -reads or writes a structure. -********************************************************************/ - -static BOOL srv_io_sess_info1(const char *desc, SESS_INFO_1 *ss1, prs_struct *ps, int depth) -{ - if (ss1 == NULL) - return False; - - prs_debug(ps, depth, desc, "srv_io_sess_info1"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("ptr_name ", ps, depth, &ss1->ptr_name)) - return False; - if(!prs_uint32("ptr_user ", ps, depth, &ss1->ptr_user)) - return False; - - if(!prs_uint32("num_opens ", ps, depth, &ss1->num_opens)) - return False; - if(!prs_uint32("open_time ", ps, depth, &ss1->open_time)) - return False; - if(!prs_uint32("idle_time ", ps, depth, &ss1->idle_time)) - return False; - if(!prs_uint32("user_flags", ps, depth, &ss1->user_flags)) - return False; - - return True; -} /******************************************************************* Reads or writes a structure. @@ -1818,13 +1722,31 @@ static BOOL srv_io_srv_sess_info_1(const char *desc, SRV_SESS_INFO_1 *ss1, prs_s SMB_ASSERT_ARRAY(ss1->info_1, num_entries); + /* first the pointers and flags */ + for (i = 0; i < num_entries; i++) { - if(!srv_io_sess_info1("", &ss1->info_1[i], ps, depth)) + + if ( !prs_io_unistr2_p("", ps, depth, &ss1->info_1[i].sharename )) + return False; + if ( !prs_io_unistr2_p("", ps, depth, &ss1->info_1[i].username )) + return False; + + if(!prs_uint32("num_opens ", ps, depth, &ss1->info_1[i].num_opens)) + return False; + if(!prs_uint32("open_time ", ps, depth, &ss1->info_1[i].open_time)) + return False; + if(!prs_uint32("idle_time ", ps, depth, &ss1->info_1[i].idle_time)) + return False; + if(!prs_uint32("user_flags", ps, depth, &ss1->info_1[i].user_flags)) return False; } + /* now the strings */ + for (i = 0; i < num_entries; i++) { - if(!srv_io_sess_info1_str("", &ss1->info_1_str[i], ps, depth)) + if ( !prs_io_unistr2("", ps, depth, ss1->info_1[i].sharename )) + return False; + if ( !prs_io_unistr2("", ps, depth, ss1->info_1[i].username )) return False; } @@ -1883,37 +1805,13 @@ static BOOL srv_io_srv_sess_ctr(const char *desc, SRV_SESS_INFO_CTR **pp_ctr, pr return True; } -/******************************************************************* - Inits a SRV_Q_NET_SESS_ENUM structure. -********************************************************************/ - -void init_srv_q_net_sess_enum(SRV_Q_NET_SESS_ENUM *q_n, - const char *srv_name, const char *qual_name, - const char *user_name, uint32 sess_level, - SRV_SESS_INFO_CTR *ctr, uint32 preferred_len, - ENUM_HND *hnd) -{ - q_n->ctr = ctr; - - DEBUG(5,("init_q_net_sess_enum\n")); - - init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name); - init_buf_unistr2(&q_n->uni_qual_name, &q_n->ptr_qual_name, qual_name); - init_buf_unistr2(&q_n->uni_user_name, &q_n->ptr_user_name, user_name); - - q_n->sess_level = sess_level; - q_n->preferred_len = preferred_len; - - memcpy(&q_n->enum_hnd, hnd, sizeof(*hnd)); -} - /******************************************************************* Reads or writes a structure. ********************************************************************/ -BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_n, prs_struct *ps, int depth) +BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_u, prs_struct *ps, int depth) { - if (q_n == NULL) + if (q_u == NULL) return False; prs_debug(ps, depth, desc, "srv_io_q_net_sess_enum"); @@ -1922,41 +1820,36 @@ BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_n, prs_stru if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name)) - return False; - if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth)) + if(!prs_pointer("servername", ps, depth, (void*)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_qual_name", ps, depth, &q_n->ptr_qual_name)) - return False; - if(!smb_io_unistr2("", &q_n->uni_qual_name, q_n->ptr_qual_name, ps, depth)) + if(!prs_pointer("qualifier", ps, depth, (void*)&q_u->qualifier, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_user_name", ps, depth, &q_n->ptr_user_name)) - return False; - if(!smb_io_unistr2("", &q_n->uni_user_name, q_n->ptr_user_name, ps, depth)) + + if(!prs_pointer("username", ps, depth, (void*)&q_u->username, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("sess_level", ps, depth, &q_n->sess_level)) + if(!prs_uint32("sess_level", ps, depth, &q_u->sess_level)) return False; - if (q_n->sess_level != (uint32)-1) { - if(!srv_io_srv_sess_ctr("sess_ctr", &q_n->ctr, ps, depth)) + if (q_u->sess_level != (uint32)-1) { + if(!srv_io_srv_sess_ctr("sess_ctr", &q_u->ctr, ps, depth)) return False; } - if(!prs_uint32("preferred_len", ps, depth, &q_n->preferred_len)) + if(!prs_uint32("preferred_len", ps, depth, &q_u->preferred_len)) return False; - if(!smb_io_enum_hnd("enum_hnd", &q_n->enum_hnd, ps, depth)) + if(!smb_io_enum_hnd("enum_hnd", &q_u->enum_hnd, ps, depth)) return False; return True; @@ -2433,23 +2326,11 @@ BOOL srv_io_r_net_conn_enum(const char *desc, SRV_R_NET_CONN_ENUM *r_n, prs_str return True; } -/******************************************************************* - Inits a FILE_INFO_3_STR structure -********************************************************************/ - -void init_srv_file_info3_str(FILE_INFO_3_STR *fi3, const char *user_name, const char *path_name) -{ - DEBUG(5,("init_srv_file_info3_str\n")); - - init_unistr2(&fi3->uni_path_name, path_name, UNI_STR_TERMINATE); - init_unistr2(&fi3->uni_user_name, user_name, UNI_STR_TERMINATE); -} - /******************************************************************* Reads or writes a structure. ********************************************************************/ -static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_struct *ps, int depth) +static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3 *sh1, prs_struct *ps, int depth) { if (sh1 == NULL) return False; @@ -2460,10 +2341,15 @@ static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_st if(!prs_align(ps)) return False; - if(!smb_io_unistr2("", &sh1->uni_path_name, True, ps, depth)) - return False; - if(!smb_io_unistr2("", &sh1->uni_user_name, True, ps, depth)) - return False; + if ( sh1->path ) { + if(!smb_io_unistr2("", sh1->path, True, ps, depth)) + return False; + } + + if ( sh1->user ) { + if(!smb_io_unistr2("", sh1->user, True, ps, depth)) + return False; + } return True; } @@ -2472,18 +2358,26 @@ static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_st Inits a FILE_INFO_3 structure ********************************************************************/ -void init_srv_file_info3(FILE_INFO_3 *fl3, - uint32 id, uint32 perms, uint32 num_locks, - const char *path_name, const char *user_name) +void init_srv_file_info3( FILE_INFO_3 *fl3, uint32 id, uint32 perms, uint32 num_locks, + const char *user_name, const char *path_name ) { - DEBUG(5,("init_srv_file_info3: %s %s\n", path_name, user_name)); - fl3->id = id; fl3->perms = perms; fl3->num_locks = num_locks; - fl3->ptr_path_name = (path_name != NULL) ? 1 : 0; - fl3->ptr_user_name = (user_name != NULL) ? 1 : 0; + if ( path_name ) { + if ( (fl3->path = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) + return; + init_unistr2(fl3->path, path_name, UNI_STR_TERMINATE); + } + + if ( user_name ) { + if ( (fl3->user = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) + return; + init_unistr2(fl3->user, user_name, UNI_STR_TERMINATE); + } + + return; } /******************************************************************* @@ -2492,6 +2386,8 @@ void init_srv_file_info3(FILE_INFO_3 *fl3, static BOOL srv_io_file_info3(const char *desc, FILE_INFO_3 *fl3, prs_struct *ps, int depth) { + uint32 uni_p; + if (fl3 == NULL) return False; @@ -2507,10 +2403,24 @@ static BOOL srv_io_file_info3(const char *desc, FILE_INFO_3 *fl3, prs_struct *ps return False; if(!prs_uint32("num_locks ", ps, depth, &fl3->num_locks)) return False; - if(!prs_uint32("ptr_path_name", ps, depth, &fl3->ptr_path_name)) + + uni_p = fl3->path ? 1 : 0; + if(!prs_uint32("ptr", ps, depth, &uni_p)) return False; - if(!prs_uint32("ptr_user_name", ps, depth, &fl3->ptr_user_name)) + if (UNMARSHALLING(ps)) { + if ( (fl3->path = PRS_ALLOC_MEM( ps, UNISTR2, 1)) == NULL ) { + return False; + } + } + + uni_p = fl3->user ? 1 : 0; + if(!prs_uint32("ptr", ps, depth, &uni_p)) return False; + if (UNMARSHALLING(ps)) { + if ( (fl3->user = PRS_ALLOC_MEM( ps, UNISTR2, 1)) == NULL ) { + return False; + } + } return True; } @@ -2528,55 +2438,53 @@ static BOOL srv_io_srv_file_ctr(const char *desc, SRV_FILE_INFO_CTR *ctr, prs_st depth++; if (UNMARSHALLING(ps)) { - memset(ctr, '\0', sizeof(SRV_FILE_INFO_CTR)); + ZERO_STRUCTP(ctr); } if(!prs_align(ps)) return False; - if(!prs_uint32("switch_value", ps, depth, &ctr->switch_value)) + if(!prs_uint32("level", ps, depth, &ctr->level)) return False; - if (ctr->switch_value != 3) { - DEBUG(5,("%s File info %d level not supported\n", - tab_depth(depth), ctr->switch_value)); - } + if(!prs_uint32("ptr_file_info", ps, depth, &ctr->ptr_file_info)) return False; if(!prs_uint32("num_entries", ps, depth, &ctr->num_entries)) return False; if(!prs_uint32("ptr_entries", ps, depth, &ctr->ptr_entries)) return False; + if (ctr->ptr_entries == 0) return True; - if(!prs_uint32("num_entries2", ps, depth, - &ctr->num_entries2)) + + if(!prs_uint32("num_entries2", ps, depth, &ctr->num_entries2)) return False; - switch (ctr->switch_value) { + switch (ctr->level) { case 3: { - SRV_FILE_INFO_3 *info3 = ctr->file.info3; + FILE_INFO_3 *info3 = ctr->file.info3; int num_entries = ctr->num_entries; int i; if (UNMARSHALLING(ps)) { - if (!(info3 = PRS_ALLOC_MEM(ps, SRV_FILE_INFO_3, num_entries))) + if (!(info3 = PRS_ALLOC_MEM(ps, FILE_INFO_3, num_entries))) return False; ctr->file.info3 = info3; } for (i = 0; i < num_entries; i++) { - if(!srv_io_file_info3("", &ctr->file.info3[i].info_3, ps, depth)) + if(!srv_io_file_info3("", &ctr->file.info3[i], ps, depth)) return False; } + for (i = 0; i < num_entries; i++) { - if(!srv_io_file_info3_str("", &ctr->file.info3[i].info_3_str, ps, depth)) + if(!srv_io_file_info3_str("", &ctr->file.info3[i], ps, depth)) return False; } break; } default: - DEBUG(5,("%s no file info at switch_value %d\n", - tab_depth(depth), ctr->switch_value)); + DEBUG(5,("%s no file info at switch_value %d\n", tab_depth(depth), ctr->level)); break; } @@ -2594,13 +2502,28 @@ void init_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n, uint32 preferred_len, ENUM_HND *hnd) { - DEBUG(5,("init_q_net_file_enum\n")); + uint32 ptr; - init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name); - init_buf_unistr2(&q_n->uni_qual_name, &q_n->ptr_qual_name, qual_name); - init_buf_unistr2(&q_n->uni_user_name, &q_n->ptr_user_name, user_name); + if ( srv_name ) { + if ( (q_n->servername = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) + return; + init_buf_unistr2(q_n->servername, &ptr, srv_name); + } + + if ( qual_name ) { + if ( (q_n->qualifier = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) + return; + init_buf_unistr2(q_n->qualifier, &ptr, qual_name); + } + + if ( user_name ) { + if ( (q_n->username = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) + return; + init_buf_unistr2(q_n->username, &ptr, user_name); + } + + q_n->level = q_n->ctr.level = file_level; - q_n->file_level = q_n->ctr.switch_value = file_level; q_n->preferred_len = preferred_len; q_n->ctr.ptr_file_info = 1; q_n->ctr.num_entries = 0; @@ -2613,9 +2536,9 @@ void init_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n, Reads or writes a structure. ********************************************************************/ -BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_n, prs_struct *ps, int depth) +BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_u, prs_struct *ps, int depth) { - if (q_n == NULL) + if (q_u == NULL) return False; prs_debug(ps, depth, desc, "srv_io_q_net_file_enum"); @@ -2624,41 +2547,33 @@ BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_n, prs_stru if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name)) + if(!prs_pointer("servername", ps, depth, (void*)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; - if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth)) - return False; - if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_qual_name", ps, depth, &q_n->ptr_qual_name)) - return False; - if(!smb_io_unistr2("", &q_n->uni_qual_name, q_n->ptr_qual_name, ps, depth)) + if(!prs_pointer("qualifier", ps, depth, (void*)&q_u->qualifier, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; - if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_user_name", ps, depth, &q_n->ptr_user_name)) - return False; - if(!smb_io_unistr2("", &q_n->uni_user_name, q_n->ptr_user_name, ps, depth)) + if(!prs_pointer("username", ps, depth, (void*)&q_u->username, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; - if(!prs_align(ps)) return False; - if(!prs_uint32("file_level", ps, depth, &q_n->file_level)) + + if(!prs_uint32("level", ps, depth, &q_u->level)) return False; - if (q_n->file_level != (uint32)-1) { - if(!srv_io_srv_file_ctr("file_ctr", &q_n->ctr, ps, depth)) + if (q_u->level != (uint32)-1) { + if(!srv_io_srv_file_ctr("file_ctr", &q_u->ctr, ps, depth)) return False; } - if(!prs_uint32("preferred_len", ps, depth, &q_n->preferred_len)) + if(!prs_uint32("preferred_len", ps, depth, &q_u->preferred_len)) return False; - if(!smb_io_enum_hnd("enum_hnd", &q_n->enum_hnd, ps, depth)) + if(!smb_io_enum_hnd("enum_hnd", &q_u->enum_hnd, ps, depth)) return False; return True; @@ -2679,10 +2594,10 @@ BOOL srv_io_r_net_file_enum(const char *desc, SRV_R_NET_FILE_ENUM *r_n, prs_stru if(!prs_align(ps)) return False; - if(!prs_uint32("file_level", ps, depth, &r_n->file_level)) + if(!prs_uint32("level", ps, depth, &r_n->level)) return False; - if (r_n->file_level != 0) { + if (r_n->level != 0) { if(!srv_io_srv_file_ctr("file_ctr", &r_n->ctr, ps, depth)) return False; } @@ -2703,62 +2618,16 @@ BOOL srv_io_r_net_file_enum(const char *desc, SRV_R_NET_FILE_ENUM *r_n, prs_stru void init_srv_q_net_file_close(SRV_Q_NET_FILE_CLOSE *q_n, const char *server, uint32 file_id) { - q_n->ptr_srv_name = 1; - init_unistr2(&q_n->uni_srv_name, server, UNI_STR_TERMINATE); - q_n->file_id = file_id; -} - -/******************************************************************* - Reads or writes a structure. -********************************************************************/ -BOOL srv_io_q_net_file_close(const char *desc, SRV_Q_NET_FILE_CLOSE *q_n, - prs_struct *ps, int depth) -{ - if (q_n == NULL) - return False; - - prs_debug(ps, depth, desc, "srv_io_q_net_file_close"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name)) - return False; - if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth)) - return False; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("file_id", ps, depth, &q_n->file_id)) - return False; + if ( server ) { + if ( (q_n->servername = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) { + return; + } + init_unistr2(q_n->servername, server, UNI_STR_TERMINATE); + } - return True; + q_n->file_id = file_id; } -/******************************************************************* - Reads or writes a structure. -********************************************************************/ - -BOOL srv_io_r_net_file_close(const char *desc, SRV_R_NET_FILE_CLOSE *q_n, - prs_struct *ps, int depth) -{ - if (q_n == NULL) - return False; - - prs_debug(ps, depth, desc, "srv_io_r_net_file_close"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_werror("status", ps, depth, &q_n->status)) - return False; - - return True; -} - /******************************************************************* Inits a SRV_INFO_100 structure. ********************************************************************/ @@ -3410,25 +3279,6 @@ BOOL srv_io_r_net_disk_enum(const char *desc, SRV_R_NET_DISK_ENUM *r_n, prs_stru return True; } -/******************************************************************* - initialises a structure. - ********************************************************************/ - -BOOL init_srv_q_net_name_validate(SRV_Q_NET_NAME_VALIDATE *q_n, const char *srv_name, const char *share_name, int type) -{ - uint32 ptr_share_name; - - DEBUG(5,("init_srv_q_net_name_validate\n")); - - init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name); - init_buf_unistr2(&q_n->uni_name, &ptr_share_name, share_name); - - q_n->type = type; - q_n->flags = 0; - - return True; -} - /******************************************************************* Reads or writes a structure. ********************************************************************/ @@ -3444,16 +3294,13 @@ BOOL srv_io_q_net_name_validate(const char *desc, SRV_Q_NET_NAME_VALIDATE *q_n, if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name)) - return False; - - if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth)) + if(!prs_pointer("servername", ps, depth, (void*)&q_n->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; if(!prs_align(ps)) return False; - if(!smb_io_unistr2("", &q_n->uni_name, True, ps, depth)) + if(!smb_io_unistr2("", &q_n->sharename, True, ps, depth)) return False; if(!prs_align(ps)) @@ -3663,3 +3510,48 @@ void init_srv_q_net_remote_tod(SRV_Q_NET_REMOTE_TOD *q_u, const char *server) q_u->ptr_srv_name = 1; init_unistr2(&q_u->uni_srv_name, server, UNI_STR_TERMINATE); } + + +/******************************************************************* + Reads or writes a structure. +********************************************************************/ + +BOOL srv_io_q_net_file_close(const char *desc, SRV_Q_NET_FILE_CLOSE *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "srv_io_q_net_file_close"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_pointer("servername", ps, depth, (void*)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) + return False; + if(!prs_align(ps)) + return False; + + if(!prs_uint32("file_id", ps, depth, &q_u->file_id)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +BOOL srv_io_r_net_file_close(const char *desc, SRV_R_NET_FILE_CLOSE *r_n, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "srv_io_r_net_file_close"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_werror("status", ps, depth, &r_n->status)) + return False; + + return True; +} diff --git a/source3/rpc_parse/parse_svcctl.c b/source3/rpc_parse/parse_svcctl.c index 2cb44c63195..dc4ee3e6e99 100644 --- a/source3/rpc_parse/parse_svcctl.c +++ b/source3/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/source3/rpc_parse/parse_unixinfo.c b/source3/rpc_parse/parse_unixinfo.c new file mode 100644 index 00000000000..391713ce901 --- /dev/null +++ b/source3/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; icount; 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; icount; 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/source3/rpc_server/srv_dfs_nt.c b/source3/rpc_server/srv_dfs_nt.c index 8239584522a..c7f8e05d91c 100644 --- a/source3/rpc_server/srv_dfs_nt.c +++ b/source3/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/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index efa7156eea6..2cc5ef61104 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/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/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 812a720d905..e2c5e865ed1 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/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, ¤t_user)) { + DEBUG(10, ("Could not copy current user\n")); + goto err_exit; + } /* We're finished - no more packets. */ p->auth.auth_type = PIPE_AUTH_TYPE_NONE; /* We must set the pipe auth_level here also. */ p->auth.auth_level = PIPE_AUTH_LEVEL_NONE; p->pipe_bound = True; + /* The session key was initialized from the SMB + * session in make_internal_rpc_pipe_p */ break; default: @@ -2148,23 +2171,6 @@ BOOL api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss return True; } -/**************************************************************************** - Return a user struct for a pipe user. -****************************************************************************/ - -struct current_user *get_current_user(struct current_user *user, pipes_struct *p) -{ - if (p->pipe_bound && - (p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP || - (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) { - memcpy(user, &p->pipe_user, sizeof(struct current_user)); - } else { - memcpy(user, ¤t_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/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 9cc8b72546f..8aa5bb3e6d1 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/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/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index e045de56396..2e0b355db5f 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/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/source3/rpc_server/srv_samr_util.c b/source3/rpc_server/srv_samr_util.c index 2b65eb210fd..c4bec79c9cb 100644 --- a/source3/rpc_server/srv_samr_util.c +++ b/source3/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/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 0281e3da0ca..3dbad208cc8 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/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/source3/rpc_server/srv_srvsvc.c b/source3/rpc_server/srv_srvsvc.c index 0b4eac5cc73..e4f85d0bdb4 100644 --- a/source3/rpc_server/srv_srvsvc.c +++ b/source3/rpc_server/srv_srvsvc.c @@ -6,6 +6,7 @@ * Copyright (C) Paul Ashton 1997, * Copyright (C) Jeremy Allison 2001, * Copyright (C) Jim McDonough 2003. + * Copyright (C) Gera;d (Jerry) Carter 2006. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -550,6 +551,35 @@ static BOOL api_srv_net_file_set_secdesc(pipes_struct *p) return True; } +/******************************************************************* +*******************************************************************/ + +static BOOL api_srv_net_file_close(pipes_struct *p) +{ + SRV_Q_NET_FILE_CLOSE q_u; + SRV_R_NET_FILE_CLOSE r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + /* Unmarshall the net file set info from Win9x */ + if(!srv_io_q_net_file_close("", &q_u, data, 0)) { + DEBUG(0,("api_srv_net_file_close: Failed to unmarshall SRV_Q_NET_FILE_SET_SECDESC.\n")); + return False; + } + + r_u.status = _srv_net_file_close(p, &q_u, &r_u); + + if(!srv_io_r_net_file_close("", &r_u, rdata, 0)) { + DEBUG(0,("api_srv_net_file_close: Failed to marshall SRV_R_NET_FILE_SET_SECDESC.\n")); + return False; + } + + return True; +} + /******************************************************************* \PIPE\srvsvc commands ********************************************************************/ @@ -573,7 +603,8 @@ static struct api_struct api_srv_cmds[] = { "SRV_NET_DISK_ENUM" , SRV_NET_DISK_ENUM , api_srv_net_disk_enum }, { "SRV_NET_NAME_VALIDATE" , SRV_NET_NAME_VALIDATE , api_srv_net_name_validate }, { "SRV_NET_FILE_QUERY_SECDESC", SRV_NET_FILE_QUERY_SECDESC, api_srv_net_file_query_secdesc }, - { "SRV_NET_FILE_SET_SECDESC" , SRV_NET_FILE_SET_SECDESC , api_srv_net_file_set_secdesc } + { "SRV_NET_FILE_SET_SECDESC" , SRV_NET_FILE_SET_SECDESC , api_srv_net_file_set_secdesc }, + { "SRV_NET_FILE_CLOSE" , SRV_NET_FILE_CLOSE , api_srv_net_file_close } }; void srvsvc_get_pipe_fns( struct api_struct **fns, int *n_fns ) diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index a936ef58709..12a86ce9f33 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/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); @@ -632,16 +831,6 @@ static void init_srv_r_net_share_get_info(pipes_struct *p, SRV_R_NET_SHARE_GET_I r_n->status = status; } -/******************************************************************* - fill in a sess info level 1 structure. - ********************************************************************/ - -static void init_srv_sess_0_info(SESS_INFO_0 *se0, SESS_INFO_0_STR *str0, char *name) -{ - init_srv_sess_info0(se0, name); - init_srv_sess_info0_str(str0, name); -} - /******************************************************************* fill in a sess info level 0 structure. ********************************************************************/ @@ -662,11 +851,7 @@ static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto if (snum) { for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) { - init_srv_sess_0_info(&ss0->info_0[num_entries], - &ss0->info_0_str[num_entries], session_list[(*snum)].remote_machine); - - /* move on to creating next session */ - /* move on to creating next sess */ + init_srv_sess_info0( &ss0->info_0[num_entries], session_list[(*snum)].remote_machine); num_entries++; } @@ -687,17 +872,35 @@ static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto } /******************************************************************* - fill in a sess info level 1 structure. - ********************************************************************/ +********************************************************************/ -static void init_srv_sess_1_info(SESS_INFO_1 *se1, SESS_INFO_1_STR *str1, - char *name, char *user, - uint32 num_opens, - uint32 open_time, uint32 idle_time, - uint32 usr_flgs) +/* global needed to make use of the share_mode_forall() callback */ +static struct sess_file_count s_file_cnt; + +static void sess_file_fn( const struct share_mode_entry *e, + const char *sharepath, const char *fname ) { - init_srv_sess_info1(se1 , name, user, num_opens, open_time, idle_time, usr_flgs); - init_srv_sess_info1_str(str1, name, user); + struct sess_file_count *sess = &s_file_cnt; + + if ( (procid_to_pid(&e->pid) == sess->pid) && (sess->uid == e->uid) ) { + sess->count++; + } + + return; +} + +/******************************************************************* +********************************************************************/ + +static int net_count_files( uid_t uid, pid_t pid ) +{ + s_file_cnt.count = 0; + s_file_cnt.uid = uid; + s_file_cnt.pid = pid; + + share_mode_forall( sess_file_fn ); + + return s_file_cnt.count; } /******************************************************************* @@ -708,43 +911,58 @@ static void init_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *sto { struct sessionid *session_list; uint32 num_entries = 0; - (*stot) = list_sessions(&session_list); + time_t now = time(NULL); + if ( !snum ) { + ss1->num_entries_read = 0; + ss1->ptr_sess_info = 0; + ss1->num_entries_read2 = 0; + + (*stot) = 0; + + return; + } + if (ss1 == NULL) { (*snum) = 0; - SAFE_FREE(session_list); return; } - DEBUG(5,("init_srv_sess_1_ss1\n")); - - if (snum) { - for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) { - init_srv_sess_1_info(&ss1->info_1[num_entries], - &ss1->info_1_str[num_entries], - session_list[*snum].remote_machine, - session_list[*snum].username, - 1, 10, 5, 0); - - /* move on to creating next session */ - /* move on to creating next sess */ - num_entries++; - } + (*stot) = list_sessions(&session_list); + - ss1->num_entries_read = num_entries; - ss1->ptr_sess_info = num_entries > 0 ? 1 : 0; - ss1->num_entries_read2 = num_entries; - - if ((*snum) >= (*stot)) { - (*snum) = 0; + for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) { + uint32 num_files; + uint32 connect_time; + struct passwd *pw = sys_getpwnam(session_list[*snum].username); + BOOL guest; + + if ( !pw ) { + DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n", + session_list[*snum].username)); + continue; } - - } else { - ss1->num_entries_read = 0; - ss1->ptr_sess_info = 0; - ss1->num_entries_read2 = 0; - - (*stot) = 0; + + connect_time = (uint32)(now - session_list[*snum].connect_start); + num_files = net_count_files(pw->pw_uid, session_list[*snum].pid); + guest = strequal( session_list[*snum].username, lp_guestaccount() ); + + init_srv_sess_info1( &ss1->info_1[num_entries], + session_list[*snum].remote_machine, + session_list[*snum].username, + num_files, + connect_time, + 0, + guest); + num_entries++; + } + + ss1->num_entries_read = num_entries; + ss1->ptr_sess_info = num_entries > 0 ? 1 : 0; + ss1->num_entries_read2 = num_entries; + + if ((*snum) >= (*stot)) { + (*snum) = 0; } SAFE_FREE(session_list); @@ -964,66 +1182,53 @@ static void init_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n, makes a SRV_R_NET_FILE_ENUM structure. ********************************************************************/ -static WERROR init_srv_file_info_ctr(pipes_struct *p, SRV_FILE_INFO_CTR *ctr, - int switch_value, uint32 *resume_hnd, - uint32 *total_entries) +static WERROR net_file_enum_3( SRV_R_NET_FILE_ENUM *r, uint32 resume_hnd ) { - WERROR status = WERR_OK; - TALLOC_CTX *ctx = p->mem_ctx; - DEBUG(5,("init_srv_file_info_ctr: %d\n", __LINE__)); - *total_entries = 1; /* dummy entries only, for */ + TALLOC_CTX *ctx = get_talloc_ctx(); + SRV_FILE_INFO_CTR *ctr = &r->ctr; - ctr->switch_value = switch_value; - ctr->num_entries = *total_entries - *resume_hnd; + /* TODO -- Windows enumerates + (b) active pipes + (c) open directories and files */ + + r->status = net_enum_files( ctx, &ctr->file.info3, &ctr->num_entries, resume_hnd ); + if ( !W_ERROR_IS_OK(r->status)) + goto done; + + r->status = net_enum_pipes( ctx, &ctr->file.info3, &ctr->num_entries, resume_hnd ); + if ( !W_ERROR_IS_OK(r->status)) + goto done; + + r->level = ctr->level = 3; + r->total_entries = ctr->num_entries; + /* ctr->num_entries = r->total_entries - resume_hnd; */ ctr->num_entries2 = ctr->num_entries; + ctr->ptr_file_info = 1; - switch (switch_value) { - case 3: { - int i; - if (*total_entries > 0) { - ctr->ptr_entries = 1; - ctr->file.info3 = TALLOC_ARRAY(ctx, SRV_FILE_INFO_3, ctr->num_entries); - } - for (i=0 ;inum_entries;i++) { - init_srv_file_info3(&ctr->file.info3[i].info_3, i+*resume_hnd, 0x35, 0, "\\PIPE\\samr", "dummy user"); - init_srv_file_info3_str(&ctr->file.info3[i].info_3_str, "\\PIPE\\samr", "dummy user"); - - } - ctr->ptr_file_info = 1; - *resume_hnd = 0; - break; - } - default: - DEBUG(5,("init_srv_file_info_ctr: unsupported switch value %d\n", switch_value)); - (*resume_hnd = 0); - (*total_entries) = 0; - ctr->ptr_entries = 0; - status = WERR_UNKNOWN_LEVEL; - break; - } + r->status = WERR_OK; - return status; +done: + if ( ctr->num_entries > 0 ) + ctr->ptr_entries = 1; + + init_enum_hnd(&r->enum_hnd, 0); + + return r->status; } /******************************************************************* - makes a SRV_R_NET_FILE_ENUM structure. -********************************************************************/ +*******************************************************************/ -static void init_srv_r_net_file_enum(pipes_struct *p, SRV_R_NET_FILE_ENUM *r_n, - uint32 resume_hnd, int file_level, int switch_value) +WERROR _srv_net_file_enum(pipes_struct *p, SRV_Q_NET_FILE_ENUM *q_u, SRV_R_NET_FILE_ENUM *r_u) { - DEBUG(5,("init_srv_r_net_file_enum: %d\n", __LINE__)); - - r_n->file_level = file_level; - if (file_level == 0) - r_n->status = WERR_UNKNOWN_LEVEL; - else - r_n->status = init_srv_file_info_ctr(p, &r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries)); - - if (!W_ERROR_IS_OK(r_n->status)) - resume_hnd = 0; - - init_enum_hnd(&r_n->enum_hnd, resume_hnd); + switch ( q_u->level ) { + case 3: + return net_file_enum_3( r_u, get_enum_hnd(&q_u->enum_hnd) ); + default: + return WERR_UNKNOWN_LEVEL; + } + + return WERR_OK; } /******************************************************************* @@ -1109,25 +1314,6 @@ WERROR _srv_net_srv_set_info(pipes_struct *p, SRV_Q_NET_SRV_SET_INFO *q_u, SRV_R return r_u->status; } -/******************************************************************* -net file enum -********************************************************************/ - -WERROR _srv_net_file_enum(pipes_struct *p, SRV_Q_NET_FILE_ENUM *q_u, SRV_R_NET_FILE_ENUM *r_u) -{ - DEBUG(5,("srv_net_file_enum: %d\n", __LINE__)); - - /* set up the */ - init_srv_r_net_file_enum(p, r_u, - get_enum_hnd(&q_u->enum_hnd), - q_u->file_level, - q_u->ctr.switch_value); - - DEBUG(5,("srv_net_file_enum: %d\n", __LINE__)); - - return r_u->status; -} - /******************************************************************* net conn enum ********************************************************************/ @@ -1185,7 +1371,6 @@ net sess del WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SESS_DEL *r_u) { struct sessionid *session_list; - struct current_user user; int num_sessions, snum; fstring username; fstring machine; @@ -1205,11 +1390,9 @@ WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SES r_u->status = WERR_ACCESS_DENIED; - get_current_user(&user, p); - /* fail out now if you are not root or not a domain admin */ - if ((user.ut.uid != sec_initial_uid()) && + if ((p->pipe_user.ut.uid != sec_initial_uid()) && ( ! nt_token_check_domain_rid(p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS))) { goto done; @@ -1220,7 +1403,7 @@ WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SES if ((strequal(session_list[snum].username, username) || username[0] == '\0' ) && strequal(session_list[snum].remote_machine, machine)) { - if (user.ut.uid != sec_initial_uid()) { + if (p->pipe_user.ut.uid != sec_initial_uid()) { not_root = True; become_root(); } @@ -1337,7 +1520,6 @@ char *valid_share_pathname(char *dos_pathname) WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, SRV_R_NET_SHARE_SET_INFO *r_u) { - struct current_user user; pstring command; fstring share_name; fstring comment; @@ -1374,13 +1556,11 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S if (lp_print_ok(snum)) return WERR_ACCESS_DENIED; - get_current_user(&user,p); - is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop ); /* fail out now if you are not root and not a disk op */ - if ( user.ut.uid != sec_initial_uid() && !is_disk_op ) + if ( p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op ) return WERR_ACCESS_DENIED; switch (q_u->info_level) { @@ -1525,7 +1705,6 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_SHARE_ADD *r_u) { - struct current_user user; pstring command; fstring share_name; fstring comment; @@ -1543,11 +1722,9 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S r_u->parm_error = 0; - get_current_user(&user,p); - is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop ); - if (user.ut.uid != sec_initial_uid() && !is_disk_op ) + if (p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op ) return WERR_ACCESS_DENIED; if (!lp_add_share_cmd() || !*lp_add_share_cmd()) { @@ -1682,7 +1859,6 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_SHARE_DEL *r_u) { - struct current_user user; pstring command; fstring share_name; int ret; @@ -1710,11 +1886,9 @@ WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_S if (lp_print_ok(snum)) return WERR_ACCESS_DENIED; - get_current_user(&user,p); - is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop ); - if (user.ut.uid != sec_initial_uid() && !is_disk_op ) + if (p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op ) return WERR_ACCESS_DENIED; if (!lp_delete_share_cmd() || !*lp_delete_share_cmd()) { @@ -1826,7 +2000,6 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC SMB_STRUCT_STAT st; BOOL bad_path; NTSTATUS nt_status; - struct current_user user; connection_struct *conn = NULL; BOOL became_user = False; @@ -1839,10 +2012,8 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC /* Null password is ok - we are already an authenticated user... */ null_pw = data_blob(NULL, 0); - get_current_user(&user, p); - become_root(); - conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status); + conn = make_connection(qualname, null_pw, "A:", p->pipe_user.vuid, &nt_status); unbecome_root(); if (conn == NULL) { @@ -1872,18 +2043,18 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC goto error_exit; } - fsp = open_file_stat(conn, filename, &st); - if (!fsp) { + nt_status = open_file_stat(conn, filename, &st, &fsp); + if (!NT_STATUS_IS_OK(nt_status)) { /* Perhaps it is a directory */ - if (errno == EISDIR) - fsp = open_directory(conn, filename, &st, + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY)) + nt_status = open_directory(conn, filename, &st, READ_CONTROL_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, - NULL); + NULL, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", filename)); r_u->status = WERR_ACCESS_DENIED; goto error_exit; @@ -1908,7 +2079,7 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC close_file(fsp, NORMAL_CLOSE); unbecome_user(); - close_cnum(conn, user.vuid); + close_cnum(conn, p->pipe_user.vuid); return r_u->status; error_exit: @@ -1921,7 +2092,7 @@ error_exit: unbecome_user(); if (conn) - close_cnum(conn, user.vuid); + close_cnum(conn, p->pipe_user.vuid); return r_u->status; } @@ -1941,7 +2112,6 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ SMB_STRUCT_STAT st; BOOL bad_path; NTSTATUS nt_status; - struct current_user user; connection_struct *conn = NULL; BOOL became_user = False; @@ -1954,10 +2124,8 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ /* Null password is ok - we are already an authenticated user... */ null_pw = data_blob(NULL, 0); - get_current_user(&user, p); - become_root(); - conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status); + conn = make_connection(qualname, null_pw, "A:", p->pipe_user.vuid, &nt_status); unbecome_root(); if (conn == NULL) { @@ -1988,19 +2156,19 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ } - fsp = open_file_stat(conn, filename, &st); + nt_status = open_file_stat(conn, filename, &st, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(nt_status)) { /* Perhaps it is a directory */ - if (errno == EISDIR) - fsp = open_directory(conn, filename, &st, + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY)) + nt_status = open_directory(conn, filename, &st, FILE_READ_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, - NULL); + NULL, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", filename)); r_u->status = WERR_ACCESS_DENIED; goto error_exit; @@ -2017,7 +2185,7 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ close_file(fsp, NORMAL_CLOSE); unbecome_user(); - close_cnum(conn, user.vuid); + close_cnum(conn, p->pipe_user.vuid); return r_u->status; error_exit: @@ -2031,7 +2199,7 @@ error_exit: } if (conn) { - close_cnum(conn, user.vuid); + close_cnum(conn, p->pipe_user.vuid); } return r_u->status; @@ -2133,7 +2301,7 @@ WERROR _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV switch ( q_u->type ) { case 0x9: - rpcstr_pull(sharename, q_u->uni_name.buffer, sizeof(sharename), q_u->uni_name.uni_str_len*2, 0); + rpcstr_pull(sharename, q_u->sharename.buffer, sizeof(sharename), q_u->sharename.uni_str_len*2, 0); if ( !validate_net_name( sharename, INVALID_SHARENAME_CHARS, sizeof(sharename) ) ) { DEBUG(5,("_srv_net_name_validate: Bad sharename \"%s\"\n", sharename)); return WERR_INVALID_NAME; @@ -2146,3 +2314,13 @@ WERROR _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV return WERR_OK; } + + +/******************************************************************** +********************************************************************/ + +WERROR _srv_net_file_close(pipes_struct *p, SRV_Q_NET_FILE_CLOSE *q_u, SRV_R_NET_FILE_CLOSE *r_u) +{ + return WERR_ACCESS_DENIED; +} + diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c index 6062dcee5ce..dd790691d36 100644 --- a/source3/rpc_server/srv_svcctl_nt.c +++ b/source3/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/source3/rpc_server/srv_unixinfo.c b/source3/rpc_server/srv_unixinfo.c new file mode 100644 index 00000000000..f21416dfabe --- /dev/null +++ b/source3/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/source3/rpc_server/srv_unixinfo_nt.c b/source3/rpc_server/srv_unixinfo_nt.c new file mode 100644 index 00000000000..79756f20a74 --- /dev/null +++ b/source3/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; icount; 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/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c index 1a204e70bc7..2aab35ea3c4 100644 --- a/source3/rpcclient/cmd_samr.c +++ b/source3/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/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c index ed5653eb704..d77c58ad959 100644 --- a/source3/rpcclient/cmd_spoolss.c +++ b/source3/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 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/source3/sam/idmap_ad.c b/source3/sam/idmap_ad.c index 5edfad487d7..f0adfa4028a 100644 --- a/source3/sam/idmap_ad.c +++ b/source3/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/source3/sam/idmap_ldap.c b/source3/sam/idmap_ldap.c index 6169c89b3b9..3fec3a142be 100644 --- a/source3/sam/idmap_ldap.c +++ b/source3/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/source3/sam/idmap_rid.c b/source3/sam/idmap_rid.c index 58838512a68..23496d69692 100644 --- a/source3/sam/idmap_rid.c +++ b/source3/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/source3/sam/idmap_smbldap.c b/source3/sam/idmap_smbldap.c index 4d80364437c..9850921fa39 100644 --- a/source3/sam/idmap_smbldap.c +++ b/source3/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/source3/sam/idmap_tdb.c b/source3/sam/idmap_tdb.c index 665c56d2f67..02a3178d61a 100644 --- a/source3/sam/idmap_tdb.c +++ b/source3/sam/idmap_tdb.c @@ -6,6 +6,7 @@ Copyright (C) Tim Potter 2000 Copyright (C) Jim McDonough 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/source3/sam/idmap_util.c b/source3/sam/idmap_util.c index f78d3bdc233..8320b294f8f 100644 --- a/source3/sam/idmap_util.c +++ b/source3/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/source3/script/mkproto.awk b/source3/script/mkproto.awk index a0f3096c842..30b5628b336 100644 --- a/source3/script/mkproto.awk +++ b/source3/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/source3/script/mkproto.sh b/source3/script/mkproto.sh index 62041c7e331..e46e73e3e90 100755 --- a/source3/script/mkproto.sh +++ b/source3/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/source3/script/tests/selftest.sh b/source3/script/tests/selftest.sh index fe943b87b5e..d7a2db5eb64 100755 --- a/source3/script/tests/selftest.sh +++ b/source3/script/tests/selftest.sh @@ -111,12 +111,22 @@ cat >$SERVERCONFFILE<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/source3/smbd/blocking.c b/source3/smbd/blocking.c index a8db498ef5a..04ab01eb664 100644 --- a/source3/smbd/blocking.c +++ b/source3/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/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 738d12151db..31f03cc7fad 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/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/source3/smbd/conn.c b/source3/smbd/conn.c index d857611c355..52182f31294 100644 --- a/source3/smbd/conn.c +++ b/source3/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/source3/smbd/connection.c b/source3/smbd/connection.c index 07d3181144f..0442a9441ad 100644 --- a/source3/smbd/connection.c +++ b/source3/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/source3/smbd/dir.c b/source3/smbd/dir.c index 5ba9e1ed575..96e0923dbd0 100644 --- a/source3/smbd/dir.c +++ b/source3/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/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 61145fde2f0..260a8dadbd6 100644 --- a/source3/smbd/dosmode.c +++ b/source3/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/source3/smbd/error.c b/source3/smbd/error.c index fa236f0de05..409781eaa94 100644 --- a/source3/smbd/error.c +++ b/source3/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/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index b4f1f02b724..7c5eeae5c7d 100644 --- a/source3/smbd/fake_file.c +++ b/source3/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/source3/smbd/filename.c b/source3/smbd/filename.c index 6c0f8b77585..1ea5228e919 100644 --- a/source3/smbd/filename.c +++ b/source3/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 . */ 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/source3/smbd/files.c b/source3/smbd/files.c index e020d8e13a6..7069818dee4 100644 --- a/source3/smbd/files.c +++ b/source3/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); } @@ -491,6 +481,29 @@ files_struct *file_fsp(char *buf, int where) return NULL; } +/**************************************************************************** + Get an fsp from a packet given the offset of a 16 bit fnum. +****************************************************************************/ + +files_struct *file_fsp(char *buf, int where) +{ + files_struct *fsp; + + if (chain_fsp) { + return chain_fsp; + } + + if (!buf) { + return NULL; + } + + fsp = file_fnum(SVAL(buf, where)); + if (fsp) { + chain_fsp = fsp; + } + return fsp; +} + /**************************************************************************** Reset the chained fsp - done at the start of a packet reply. ****************************************************************************/ @@ -504,15 +517,19 @@ void file_chain_reset(void) Duplicate the file handle part for a DOS or FCB open. ****************************************************************************/ -files_struct *dup_file_fsp(files_struct *fsp, +NTSTATUS dup_file_fsp(files_struct *fsp, uint32 access_mask, uint32 share_access, - uint32 create_options) + uint32 create_options, + files_struct **result) { - files_struct *dup_fsp = file_new(fsp->conn); + NTSTATUS status; + files_struct *dup_fsp; - if (!dup_fsp) { - return NULL; + status = file_new(fsp->conn, &dup_fsp); + + if (!NT_STATUS_IS_OK(status)) { + return status; } SAFE_FREE(dup_fsp->fh); @@ -547,5 +564,6 @@ files_struct *dup_file_fsp(files_struct *fsp, dup_fsp->aio_write_behind = fsp->aio_write_behind; string_set(&dup_fsp->fsp_name,fsp->fsp_name); - return dup_fsp; + *result = dup_fsp; + return NT_STATUS_OK; } diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index e4531d8ae98..2d6db8f2a30 100644 --- a/source3/smbd/lanman.c +++ b/source3/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/source3/smbd/mangle.c b/source3/smbd/mangle.c index ed69a6210e8..16f99636eb5 100644 --- a/source3/smbd/mangle.c +++ b/source3/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/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 2092f430c07..320e31ab679 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/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/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 0a161c9e769..d1ce1af9eac 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/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/source3/smbd/mangle_map.c b/source3/smbd/mangle_map.c index 9e798fd41b4..c5803786ec0 100644 --- a/source3/smbd/mangle_map.c +++ b/source3/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/source3/smbd/message.c b/source3/smbd/message.c index 31dab458443..fd53e60c141 100644 --- a/source3/smbd/message.c +++ b/source3/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/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index b22b5674d6f..69da4194fda 100644 --- a/source3/smbd/msdfs.c +++ b/source3/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/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index aa6f79e1657..0b1bdcadbb1 100644 --- a/source3/smbd/nttrans.c +++ b/source3/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/source3/smbd/open.c b/source3/smbd/open.c index 832a8df7559..7c04cdbe7cc 100644 --- a/source3/smbd/open.c +++ b/source3/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, ¤t_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/source3/smbd/password.c b/source3/smbd/password.c index 73b0ebb4b32..389086e9bf7 100644 --- a/source3/smbd/password.c +++ b/source3/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/source3/smbd/pipes.c b/source3/smbd/pipes.c index 2d90383706b..52660da2ffe 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -31,6 +31,21 @@ #define PIPE "\\PIPE\\" #define PIPELEN strlen(PIPE) +#define MAX_PIPE_NAME_LEN 24 + +/* PIPE/// */ +#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/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 6e403dba92a..73744cf26e7 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/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/source3/smbd/process.c b/source3/smbd/process.c index b3ce49360d8..ce352adfd7d 100644 --- a/source3/smbd/process.c +++ b/source3/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/source3/smbd/reply.c b/source3/smbd/reply.c index e68e8662d74..ff3c6832e4f 100644 --- a/source3/smbd/reply.c +++ b/source3/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 . */ - 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 . */ - 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 . */ - 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/source3/smbd/server.c b/source3/smbd/server.c index 2bfeae9f541..0fba6af6970 100644 --- a/source3/smbd/server.c +++ b/source3/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/source3/smbd/service.c b/source3/smbd/service.c index cb9bfcc27ae..9dcb8a354f4 100644 --- a/source3/smbd/service.c +++ b/source3/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/source3/smbd/session.c b/source3/smbd/session.c index 41f8fd0ed43..bcb840a3fe4 100644 --- a/source3/smbd/session.c +++ b/source3/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/source3/smbd/share_access.c b/source3/smbd/share_access.c index 468f61560b9..5334976d8dc 100644 --- a/source3/smbd/share_access.c +++ b/source3/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/source3/smbd/statcache.c b/source3/smbd/statcache.c index 548d7c4a487..b453fdd5447 100644 --- a/source3/smbd/statcache.c +++ b/source3/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/source3/smbd/statvfs.c b/source3/smbd/statvfs.c index 8f981a63288..300b14a7c08 100644 --- a/source3/smbd/statvfs.c +++ b/source3/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/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9030737b1b4..aca1fcd70e9 100644 --- a/source3/smbd/trans2.c +++ b/source3/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/source3/smbd/uid.c b/source3/smbd/uid.c index c62c9d928ab..48d7f590c39 100644 --- a/source3/smbd/uid.c +++ b/source3/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/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c deleted file mode 100644 index ee251c17d8d..00000000000 --- a/source3/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 - -**********************************************************/ - -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/source3/smbd/vfs.c b/source3/smbd/vfs.c index 2c9403a0790..7bb5f798f97 100644 --- a/source3/smbd/vfs.c +++ b/source3/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,24 +173,86 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) for(i=0; ops[i].op != NULL; i++) { DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer)); if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) { - /* Check whether this operation was already made opaque by different module */ - if(((void**)&conn->vfs_opaque.ops)[ops[i].type] == ((void**)&default_vfs.ops)[ops[i].type]) { - /* No, it isn't overloaded yet. Overload. */ - DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); - ((void**)&conn->vfs_opaque.ops)[ops[i].type] = ops[i].op; - ((vfs_handle_struct **)&conn->vfs_opaque.handles)[ops[i].type] = handle; - } + /* If this operation was already made opaque by different module, it + * will be overridded here. + */ + DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); + vfs_set_operation(&conn->vfs_opaque, ops[i].type, handle, ops[i].op); } /* Change current VFS disposition*/ DEBUGADD(5, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object)); - ((void**)&conn->vfs.ops)[ops[i].type] = ops[i].op; - ((vfs_handle_struct **)&conn->vfs.handles)[ops[i].type] = handle; + vfs_set_operation(&conn->vfs, ops[i].type, handle, ops[i].op); } SAFE_FREE(module_name); return True; } +/***************************************************************** + Allow VFS modules to extend files_struct with VFS-specific state. + This will be ok for small numbers of extensions, but might need to + be refactored if it becomes more widely used. +******************************************************************/ + +#define EXT_DATA_AREA(e) ((uint8 *)(e) + sizeof(struct vfs_fsp_data)) + +void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle, files_struct *fsp, size_t ext_size) +{ + struct vfs_fsp_data *ext; + void * ext_data; + + /* Prevent VFS modules adding multiple extensions. */ + if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) { + return ext_data; + } + + ext = TALLOC_ZERO(handle->conn->mem_ctx, + sizeof(struct vfs_fsp_data) + ext_size); + if (ext == NULL) { + return NULL; + } + + ext->owner = handle; + ext->next = fsp->vfs_extension; + fsp->vfs_extension = ext; + return EXT_DATA_AREA(ext); +} + +void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp) +{ + struct vfs_fsp_data *curr; + struct vfs_fsp_data *prev; + + for (curr = fsp->vfs_extension, prev = NULL; + curr; + prev = curr, curr = curr->next) { + if (curr->owner == handle) { + if (prev) { + prev->next = curr->next; + } else { + fsp->vfs_extension = curr->next; + } + TALLOC_FREE(curr); + return; + } + } +} + +void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp) +{ + struct vfs_fsp_data *head; + + for (head = fsp->vfs_extension; head; head = head->next) { + if (head->owner == handle) { + return EXT_DATA_AREA(head); + } + } + + return NULL; +} + +#undef EXT_DATA_AREA + /***************************************************************** Generic VFS init. ******************************************************************/ diff --git a/source3/smbwrapper/smbw.c b/source3/smbwrapper/smbw.c index d4a5b51af4e..89ae9396aaf 100644 --- a/source3/smbwrapper/smbw.c +++ b/source3/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/source3/smbwrapper/smbw.h b/source3/smbwrapper/smbw.h index 3f0b1cbb443..f64cb209649 100644 --- a/source3/smbwrapper/smbw.h +++ b/source3/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/source3/tdb/dump.c b/source3/tdb/dump.c new file mode 100644 index 00000000000..577f23aac68 --- /dev/null +++ b/source3/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;iheader.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/source3/tdb/error.c b/source3/tdb/error.c new file mode 100644 index 00000000000..4cf33a29ab2 --- /dev/null +++ b/source3/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/source3/tdb/freelist.c b/source3/tdb/freelist.c new file mode 100644 index 00000000000..34837511647 --- /dev/null +++ b/source3/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/source3/tdb/io.c b/source3/tdb/io.c new file mode 100644 index 00000000000..ac6f4cdf573 --- /dev/null +++ b/source3/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/source3/tdb/lock.c b/source3/tdb/lock.c new file mode 100644 index 00000000000..a96d77a229a --- /dev/null +++ b/source3/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/source3/tdb/open.c b/source3/tdb/open.c new file mode 100644 index 00000000000..cb4a9cd9945 --- /dev/null +++ b/source3/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/source3/tdb/spinlock.c b/source3/tdb/spinlock.c deleted file mode 100644 index e42a6901c71..00000000000 --- a/source3/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 -#endif - -#ifdef STANDALONE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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/source3/tdb/spinlock.h b/source3/tdb/spinlock.h deleted file mode 100644 index 967fe37457f..00000000000 --- a/source3/tdb/spinlock.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef __SPINLOCK_H__ -#define __SPINLOCK_H__ - -#ifdef HAVE_CONFIG_H -#include -#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/source3/tdb/tdb.c b/source3/tdb/tdb.c index ad73a1d9aa0..1fae6b6de1d 100644 --- a/source3/tdb/tdb.c +++ b/source3/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 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tdb.h" -#include "spinlock.h" -#else -#include "includes.h" - -#if defined(PARANOID_MALLOC_CHECKER) -#ifdef malloc -#undef malloc -#endif - -#ifdef realloc -#undef realloc -#endif - -#ifdef calloc -#undef calloc -#endif - -#ifdef strdup -#undef strdup -#endif - -#ifdef strndup -#undef strndup -#endif - -#endif - -#endif - -#define TDB_MAGIC_FOOD "TDB file\n" -#define TDB_VERSION (0x26011967 + 6) -#define TDB_MAGIC (0x26011999U) -#define TDB_FREE_MAGIC (~TDB_MAGIC) -#define TDB_DEAD_MAGIC (0xFEE1DEAD) -#define TDB_ALIGNMENT 4 -#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT) -#define DEFAULT_HASH_SIZE 131 -#define TDB_PAGE_SIZE 0x2000 -#define FREELIST_TOP (sizeof(struct tdb_header)) -#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) -#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24)) -#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) -#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) -#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off)) -#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + TDB_SPINLOCK_SIZE(hash_size)) - - -/* NB assumes there is a local variable called "tdb" that is the - * current context, also takes doubly-parenthesized print-style - * argument. */ -#define TDB_LOG(x) (tdb->log_fn?((tdb->log_fn x),0) : 0) - -/* lock offsets */ -#define GLOBAL_LOCK 0 -#define ACTIVE_LOCK 4 - -#ifndef MAP_FILE -#define MAP_FILE 0 -#endif - -#ifndef MAP_FAILED -#define MAP_FAILED ((void *)-1) -#endif - -/* free memory if the pointer is valid and zero the pointer */ -#ifndef SAFE_FREE -#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0) -#endif - -#define BUCKET(hash) ((hash) % tdb->header.hash_size) TDB_DATA tdb_null; -/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */ -static TDB_CONTEXT *tdbs = NULL; - -static int tdb_munmap(TDB_CONTEXT *tdb) +/* + increment the tdb sequence number if the tdb has been opened using + the TDB_SEQNUM flag +*/ +static void tdb_increment_seqnum(struct tdb_context *tdb) { - if (tdb->flags & TDB_INTERNAL) - return 0; - -#ifdef HAVE_MMAP - if (tdb->map_ptr) { - int ret = munmap(tdb->map_ptr, tdb->map_size); - if (ret != 0) - return ret; + tdb_off_t seqnum=0; + + if (!(tdb->flags & TDB_SEQNUM)) { + return; } -#endif - tdb->map_ptr = NULL; - return 0; -} -static void tdb_mmap(TDB_CONTEXT *tdb) -{ - if (tdb->flags & TDB_INTERNAL) + if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1) != 0) { return; - -#ifdef HAVE_MMAP - if (!(tdb->flags & TDB_NOMMAP)) { - tdb->map_ptr = mmap(NULL, tdb->map_size, - PROT_READ|(tdb->read_only? 0:PROT_WRITE), - MAP_SHARED|MAP_FILE, tdb->fd, 0); - - /* - * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!! - */ - - if (tdb->map_ptr == MAP_FAILED) { - tdb->map_ptr = NULL; - TDB_LOG((tdb, 2, "tdb_mmap failed for size %d (%s)\n", - tdb->map_size, strerror(errno))); - } - } else { - tdb->map_ptr = NULL; } -#else - tdb->map_ptr = NULL; -#endif -} -/* Endian conversion: we only ever deal with 4 byte quantities */ -static void *convert(void *buf, u32 size) -{ - u32 i, *p = buf; - for (i = 0; i < size / 4; i++) - p[i] = TDB_BYTEREV(p[i]); - return buf; -} -#define DOCONV() (tdb->flags & TDB_CONVERT) -#define CONVERT(x) (DOCONV() ? convert(&x, sizeof(x)) : &x) - -/* the body of the database is made of one list_struct for the free space - plus a separate data list for each hash value */ -struct list_struct { - tdb_off next; /* offset of the next record in the list */ - tdb_len rec_len; /* total byte length of record */ - tdb_len key_len; /* byte length of key */ - tdb_len data_len; /* byte length of data */ - u32 full_hash; /* the full 32 bit hash of the key */ - u32 magic; /* try to catch errors */ - /* the following union is implied: - union { - char record[rec_len]; - struct { - char key[key_len]; - char data[data_len]; - } - u32 totalsize; (tailer) - } + /* we ignore errors from this, as we have no sane way of + dealing with them. */ -}; - -/*************************************************************** - Allow a caller to set a "alarm" flag that tdb can check to abort - a blocking lock on SIGALRM. -***************************************************************/ - -static sig_atomic_t *palarm_fired; - -void tdb_set_lock_alarm(sig_atomic_t *palarm) -{ - palarm_fired = palarm; -} - -/* a byte range locking function - return 0 on success - this functions locks/unlocks 1 byte at the specified offset. - - On error, errno is also set so that errors are passed back properly - through tdb_open(). */ -static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, - int rw_type, int lck_type, int probe) -{ - struct flock fl; - int ret; - - if (tdb->flags & TDB_NOLOCK) - return 0; - if ((rw_type == F_WRLCK) && (tdb->read_only)) { - errno = EACCES; - return -1; - } - - fl.l_type = rw_type; - fl.l_whence = SEEK_SET; - fl.l_start = offset; - fl.l_len = 1; - fl.l_pid = 0; - - do { - ret = fcntl(tdb->fd,lck_type,&fl); - if (ret == -1 && errno == EINTR && palarm_fired && *palarm_fired) - break; - } while (ret == -1 && errno == EINTR); - - if (ret == -1) { - if (!probe && lck_type != F_SETLK) { - /* Ensure error code is set for log fun to examine. */ - if (errno == EINTR && palarm_fired && *palarm_fired) - tdb->ecode = TDB_ERR_LOCK_TIMEOUT; - else - tdb->ecode = TDB_ERR_LOCK; - TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", - tdb->fd, offset, rw_type, lck_type)); - } - /* Was it an alarm timeout ? */ - if (errno == EINTR && palarm_fired && *palarm_fired) { - TDB_LOG((tdb, 5, "tdb_brlock timed out (fd=%d) at offset %d rw_type=%d lck_type=%d\n", - tdb->fd, offset, rw_type, lck_type)); - return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1); - } - /* Otherwise - generic lock error. errno set by fcntl. - * EAGAIN is an expected return from non-blocking - * locks. */ - if (errno != EAGAIN) { - TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n", - tdb->fd, offset, rw_type, lck_type, - strerror(errno))); - } - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - return 0; -} - -/* lock a list in the database. list -1 is the alloc list */ -static int tdb_lock(TDB_CONTEXT *tdb, int list, int ltype) -{ - if (list < -1 || list >= (int)tdb->header.hash_size) { - TDB_LOG((tdb, 0,"tdb_lock: invalid list %d for ltype=%d\n", - list, ltype)); - return -1; - } - if (tdb->flags & TDB_NOLOCK) - return 0; - - /* Since fcntl locks don't nest, we do a lock for the first one, - and simply bump the count for future ones */ - if (tdb->locked[list+1].count == 0) { - if (!tdb->read_only && tdb->header.rwlocks) { - if (tdb_spinlock(tdb, list, ltype)) { - TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list %d ltype=%d\n", - list, ltype)); - return -1; - } - } else if (tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) { - TDB_LOG((tdb, 0,"tdb_lock failed on list %d ltype=%d (%s)\n", - list, ltype, strerror(errno))); - return -1; - } - tdb->locked[list+1].ltype = ltype; - } - tdb->locked[list+1].count++; - return 0; -} - -/* unlock the database: returns void because it's too late for errors. */ - /* changed to return int it may be interesting to know there - has been an error --simo */ -static int tdb_unlock(TDB_CONTEXT *tdb, int list, int ltype) -{ - int ret = -1; - - if (tdb->flags & TDB_NOLOCK) - return 0; - - /* Sanity checks */ - if (list < -1 || list >= (int)tdb->header.hash_size) { - TDB_LOG((tdb, 0, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size)); - return ret; - } - - if (tdb->locked[list+1].count==0) { - TDB_LOG((tdb, 0, "tdb_unlock: count is 0\n")); - return ret; - } - - if (tdb->locked[list+1].count == 1) { - /* Down to last nested lock: unlock underneath */ - if (!tdb->read_only && tdb->header.rwlocks) { - ret = tdb_spinunlock(tdb, list, ltype); - } else { - ret = tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, F_SETLKW, 0); - } - } else { - ret = 0; - } - tdb->locked[list+1].count--; - - if (ret) - TDB_LOG((tdb, 0,"tdb_unlock: An error occurred unlocking!\n")); - return ret; -} - -/* check for an out of bounds access - if it is out of bounds then - see if the database has been expanded by someone else and expand - if necessary - note that "len" is the minimum length needed for the db -*/ -static int tdb_oob(TDB_CONTEXT *tdb, tdb_off len, int probe) -{ - struct stat st; - if (len <= tdb->map_size) - return 0; - if (tdb->flags & TDB_INTERNAL) { - if (!probe) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_oob len %d beyond internal malloc size %d\n", - (int)len, (int)tdb->map_size)); - } - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - - if (fstat(tdb->fd, &st) == -1) - return TDB_ERRCODE(TDB_ERR_IO, -1); - - if (st.st_size < (size_t)len) { - if (!probe) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_oob len %d beyond eof at %d\n", - (int)len, (int)st.st_size)); - } - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - - /* Unmap, update size, remap */ - if (tdb_munmap(tdb) == -1) - return TDB_ERRCODE(TDB_ERR_IO, -1); - tdb->map_size = st.st_size; - tdb_mmap(tdb); - return 0; -} - -/* write a lump of data at a specified offset */ -static int tdb_write(TDB_CONTEXT *tdb, tdb_off off, void *buf, tdb_len len) -{ - if (tdb_oob(tdb, off + len, 0) != 0) - return -1; - - if (tdb->map_ptr) - memcpy(off + (char *)tdb->map_ptr, buf, len); -#ifdef HAVE_PWRITE - else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) { -#else - else if (lseek(tdb->fd, off, SEEK_SET) != off - || write(tdb->fd, buf, len) != (ssize_t)len) { -#endif - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_write failed at %d len=%d (%s)\n", - off, len, strerror(errno))); - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - return 0; -} - -/* read a lump of data at a specified offset, maybe convert */ -static int tdb_read(TDB_CONTEXT *tdb,tdb_off off,void *buf,tdb_len len,int cv) -{ - if (tdb_oob(tdb, off + len, 0) != 0) - return -1; - - if (tdb->map_ptr) - memcpy(buf, off + (char *)tdb->map_ptr, len); -#ifdef HAVE_PREAD - else if (pread(tdb->fd, buf, len, off) != (ssize_t)len) { -#else - else if (lseek(tdb->fd, off, SEEK_SET) != off - || read(tdb->fd, buf, len) != (ssize_t)len) { -#endif - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_read failed at %d len=%d (%s)\n", - off, len, strerror(errno))); - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - if (cv) - convert(buf, len); - return 0; -} - -/* read a lump of data, allocating the space for it */ -static char *tdb_alloc_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_len len) -{ - char *buf; + tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); + seqnum++; + tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum); - if (!(buf = malloc(len))) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_OOM; - TDB_LOG((tdb, 0,"tdb_alloc_read malloc failed len=%d (%s)\n", - len, strerror(errno))); - return TDB_ERRCODE(TDB_ERR_OOM, buf); - } - if (tdb_read(tdb, offset, buf, len, 0) == -1) { - SAFE_FREE(buf); - return NULL; - } - return buf; -} - -/* read/write a tdb_off */ -static int ofs_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d) -{ - return tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); -} -static int ofs_write(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d) -{ - tdb_off off = *d; - return tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); -} - -/* read/write a record */ -static int rec_read(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) -{ - if (tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) - return -1; - if (TDB_BAD_MAGIC(rec)) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_CORRUPT; - TDB_LOG((tdb, 0,"rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); - } - return tdb_oob(tdb, rec->next+sizeof(*rec), 0); -} -static int rec_write(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) -{ - struct list_struct r = *rec; - return tdb_write(tdb, offset, CONVERT(r), sizeof(r)); + tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1); } -/* read a freelist record and check for simple errors */ -static int rec_free_read(TDB_CONTEXT *tdb, tdb_off off, struct list_struct *rec) -{ - if (tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) - return -1; - - if (rec->magic == TDB_MAGIC) { - /* this happens when a app is showdown while deleting a record - we should - not completely fail when this happens */ - TDB_LOG((tdb, 0,"rec_free_read non-free magic 0x%x at offset=%d - fixing\n", - rec->magic, off)); - rec->magic = TDB_FREE_MAGIC; - if (tdb_write(tdb, off, rec, sizeof(*rec)) == -1) - return -1; - } - - if (rec->magic != TDB_FREE_MAGIC) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_CORRUPT; - TDB_LOG((tdb, 0,"rec_free_read bad magic 0x%x at offset=%d\n", - rec->magic, off)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); - } - if (tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0) - return -1; - return 0; -} - -/* update a record tailer (must hold allocation lock) */ -static int update_tailer(TDB_CONTEXT *tdb, tdb_off offset, - const struct list_struct *rec) -{ - tdb_off totalsize; - - /* Offset of tailer from record header */ - totalsize = sizeof(*rec) + rec->rec_len; - return ofs_write(tdb, offset + totalsize - sizeof(tdb_off), - &totalsize); -} - -static tdb_off tdb_dump_record(TDB_CONTEXT *tdb, tdb_off offset) -{ - struct list_struct rec; - tdb_off tailer_ofs, tailer; - - if (tdb_read(tdb, offset, (char *)&rec, sizeof(rec), DOCONV()) == -1) { - printf("ERROR: failed to read record at %u\n", offset); - return 0; - } - - printf(" rec: offset=%u next=%d rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n", - offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, rec.full_hash, rec.magic); - - tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off); - if (ofs_read(tdb, tailer_ofs, &tailer) == -1) { - printf("ERROR: failed to read tailer at %u\n", tailer_ofs); - return rec.next; - } - - if (tailer != rec.rec_len + sizeof(rec)) { - printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", - (unsigned)tailer, (unsigned)(rec.rec_len + sizeof(rec))); - } - return rec.next; -} - -static int tdb_dump_chain(TDB_CONTEXT *tdb, int i) -{ - tdb_off rec_ptr, top; - int hash_length = 0; - - top = TDB_HASH_TOP(i); - - if (tdb_lock(tdb, i, F_WRLCK) != 0) - return -1; - - if (ofs_read(tdb, top, &rec_ptr) == -1) - return tdb_unlock(tdb, i, F_WRLCK); - - if (rec_ptr) - printf("hash=%d\n", i); - - while (rec_ptr) { - rec_ptr = tdb_dump_record(tdb, rec_ptr); - hash_length += 1; - } - - printf("chain %d length %d\n", i, hash_length); - - return tdb_unlock(tdb, i, F_WRLCK); -} - -void tdb_dump_all(TDB_CONTEXT *tdb) -{ - int i; - for (i=0;iheader.hash_size;i++) { - tdb_dump_chain(tdb, i); - } - tdb_printfreelist(tdb); -} - -int tdb_printfreelist(TDB_CONTEXT *tdb) -{ - int ret; - long total_free = 0; - tdb_off offset, rec_ptr; - struct list_struct rec; - - if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0) - return ret; - - offset = FREELIST_TOP; - - /* read in the freelist top */ - if (ofs_read(tdb, offset, &rec_ptr) == -1) { - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - } - - printf("freelist top=[0x%08x]\n", rec_ptr ); - while (rec_ptr) { - if (tdb_read(tdb, rec_ptr, (char *)&rec, sizeof(rec), DOCONV()) == -1) { - tdb_unlock(tdb, -1, F_WRLCK); - return -1; - } - - if (rec.magic != TDB_FREE_MAGIC) { - printf("bad magic 0x%08x in free list\n", rec.magic); - tdb_unlock(tdb, -1, F_WRLCK); - return -1; - } - - printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)]\n", rec.next, rec.rec_len, rec.rec_len ); - total_free += rec.rec_len; - - /* move to the next record */ - rec_ptr = rec.next; - } - printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, - (int)total_free); - - return tdb_unlock(tdb, -1, F_WRLCK); -} - -/* Remove an element from the freelist. Must have alloc lock. */ -static int remove_from_freelist(TDB_CONTEXT *tdb, tdb_off off, tdb_off next) -{ - tdb_off last_ptr, i; - - /* read in the freelist top */ - last_ptr = FREELIST_TOP; - while (ofs_read(tdb, last_ptr, &i) != -1 && i != 0) { - if (i == off) { - /* We've found it! */ - return ofs_write(tdb, last_ptr, &next); - } - /* Follow chain (next offset is at start of record) */ - last_ptr = i; - } - TDB_LOG((tdb, 0,"remove_from_freelist: not on list at off=%d\n", off)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); -} - -/* Add an element into the freelist. Merge adjacent records if - neccessary. */ -static int tdb_free(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) -{ - tdb_off right, left; - - /* Allocation and tailer lock */ - if (tdb_lock(tdb, -1, F_WRLCK) != 0) - return -1; - - /* set an initial tailer, so if we fail we don't leave a bogus record */ - if (update_tailer(tdb, offset, rec) != 0) { - TDB_LOG((tdb, 0, "tdb_free: upfate_tailer failed!\n")); - goto fail; - } - - /* Look right first (I'm an Australian, dammit) */ - right = offset + sizeof(*rec) + rec->rec_len; - if (right + sizeof(*rec) <= tdb->map_size) { - struct list_struct r; - - if (tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { - TDB_LOG((tdb, 0, "tdb_free: right read failed at %u\n", right)); - goto left; - } - - /* If it's free, expand to include it. */ - if (r.magic == TDB_FREE_MAGIC) { - if (remove_from_freelist(tdb, right, r.next) == -1) { - TDB_LOG((tdb, 0, "tdb_free: right free failed at %u\n", right)); - goto left; - } - rec->rec_len += sizeof(r) + r.rec_len; - } - } - -left: - /* Look left */ - left = offset - sizeof(tdb_off); - if (left > TDB_DATA_START(tdb->header.hash_size)) { - struct list_struct l; - tdb_off leftsize; - - /* Read in tailer and jump back to header */ - if (ofs_read(tdb, left, &leftsize) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left)); - goto update; - } - left = offset - leftsize; - - /* Now read in record */ - if (tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); - goto update; - } - - /* If it's free, expand to include it. */ - if (l.magic == TDB_FREE_MAGIC) { - if (remove_from_freelist(tdb, left, l.next) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left free failed at %u\n", left)); - goto update; - } else { - offset = left; - rec->rec_len += leftsize; - } - } - } - -update: - if (update_tailer(tdb, offset, rec) == -1) { - TDB_LOG((tdb, 0, "tdb_free: update_tailer failed at %u\n", offset)); - goto fail; - } - - /* Now, prepend to free list */ - rec->magic = TDB_FREE_MAGIC; - - if (ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || - rec_write(tdb, offset, rec) == -1 || - ofs_write(tdb, FREELIST_TOP, &offset) == -1) { - TDB_LOG((tdb, 0, "tdb_free record write failed at offset=%d\n", offset)); - goto fail; - } - - /* And we're done. */ - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return -1; -} - - -/* expand a file. we prefer to use ftruncate, as that is what posix - says to use for mmap expansion */ -static int expand_file(TDB_CONTEXT *tdb, tdb_off size, tdb_off addition) -{ - char buf[1024]; -#if HAVE_FTRUNCATE_EXTEND - if (ftruncate(tdb->fd, size+addition) != 0) { - TDB_LOG((tdb, 0, "expand_file ftruncate to %d failed (%s)\n", - size+addition, strerror(errno))); - return -1; - } -#else - char b = 0; - -#ifdef HAVE_PWRITE - if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) { -#else - if (lseek(tdb->fd, (size+addition) - 1, SEEK_SET) != (size+addition) - 1 || - write(tdb->fd, &b, 1) != 1) { -#endif - TDB_LOG((tdb, 0, "expand_file to %d failed (%s)\n", - size+addition, strerror(errno))); - return -1; - } -#endif - - /* now fill the file with something. This ensures that the file isn't sparse, which would be - very bad if we ran out of disk. This must be done with write, not via mmap */ - memset(buf, 0x42, sizeof(buf)); - while (addition) { - int n = addition>sizeof(buf)?sizeof(buf):addition; -#ifdef HAVE_PWRITE - int ret = pwrite(tdb->fd, buf, n, size); -#else - int ret; - if (lseek(tdb->fd, size, SEEK_SET) != size) - return -1; - ret = write(tdb->fd, buf, n); -#endif - if (ret != n) { - TDB_LOG((tdb, 0, "expand_file write of %d failed (%s)\n", - n, strerror(errno))); - return -1; - } - addition -= n; - size += n; - } - return 0; -} - - -/* expand the database at least size bytes by expanding the underlying - file and doing the mmap again if necessary */ -static int tdb_expand(TDB_CONTEXT *tdb, tdb_off size) -{ - struct list_struct rec; - tdb_off offset; - - if (tdb_lock(tdb, -1, F_WRLCK) == -1) { - TDB_LOG((tdb, 0, "lock failed in tdb_expand\n")); - return -1; - } - - /* must know about any previous expansions by another process */ - tdb_oob(tdb, tdb->map_size + 1, 1); - - /* always make room for at least 10 more records, and round - the database up to a multiple of TDB_PAGE_SIZE */ - size = TDB_ALIGN(tdb->map_size + size*10, TDB_PAGE_SIZE) - tdb->map_size; - - if (!(tdb->flags & TDB_INTERNAL)) - tdb_munmap(tdb); - - /* - * We must ensure the file is unmapped before doing this - * to ensure consistency with systems like OpenBSD where - * writes and mmaps are not consistent. - */ - - /* expand the file itself */ - if (!(tdb->flags & TDB_INTERNAL)) { - if (expand_file(tdb, tdb->map_size, size) != 0) - goto fail; - } - - tdb->map_size += size; - - if (tdb->flags & TDB_INTERNAL) { - char *new_map_ptr = realloc(tdb->map_ptr, tdb->map_size); - if (!new_map_ptr) { - tdb->map_size -= size; - goto fail; - } - tdb->map_ptr = new_map_ptr; - } else { - /* - * We must ensure the file is remapped before adding the space - * to ensure consistency with systems like OpenBSD where - * writes and mmaps are not consistent. - */ - - /* We're ok if the mmap fails as we'll fallback to read/write */ - tdb_mmap(tdb); - } - - /* form a new freelist record */ - memset(&rec,'\0',sizeof(rec)); - rec.rec_len = size - sizeof(rec); - - /* link it into the free list */ - offset = tdb->map_size - size; - if (tdb_free(tdb, offset, &rec) == -1) - goto fail; - - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return -1; -} - -/* allocate some space from the free list. The offset returned points - to a unconnected list_struct within the database with room for at - least length bytes of total data - - 0 is returned if the space could not be allocated - */ -static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length, - struct list_struct *rec) -{ - tdb_off rec_ptr, last_ptr, newrec_ptr; - struct list_struct newrec; - - memset(&newrec, '\0', sizeof(newrec)); - - if (tdb_lock(tdb, -1, F_WRLCK) == -1) - return 0; - - /* Extra bytes required for tailer */ - length += sizeof(tdb_off); - - again: - last_ptr = FREELIST_TOP; - - /* read in the freelist top */ - if (ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) - goto fail; - - /* keep looking until we find a freelist record big enough */ - while (rec_ptr) { - if (rec_free_read(tdb, rec_ptr, rec) == -1) - goto fail; - - if (rec->rec_len >= length) { - /* found it - now possibly split it up */ - if (rec->rec_len > length + MIN_REC_SIZE) { - /* Length of left piece */ - length = TDB_ALIGN(length, TDB_ALIGNMENT); - - /* Right piece to go on free list */ - newrec.rec_len = rec->rec_len - - (sizeof(*rec) + length); - newrec_ptr = rec_ptr + sizeof(*rec) + length; - - /* And left record is shortened */ - rec->rec_len = length; - } else - newrec_ptr = 0; - - /* Remove allocated record from the free list */ - if (ofs_write(tdb, last_ptr, &rec->next) == -1) - goto fail; - - /* Update header: do this before we drop alloc - lock, otherwise tdb_free() might try to - merge with us, thinking we're free. - (Thanks Jeremy Allison). */ - rec->magic = TDB_MAGIC; - if (rec_write(tdb, rec_ptr, rec) == -1) - goto fail; - - /* Did we create new block? */ - if (newrec_ptr) { - /* Update allocated record tailer (we - shortened it). */ - if (update_tailer(tdb, rec_ptr, rec) == -1) - goto fail; - - /* Free new record */ - if (tdb_free(tdb, newrec_ptr, &newrec) == -1) - goto fail; - } - - /* all done - return the new record offset */ - tdb_unlock(tdb, -1, F_WRLCK); - return rec_ptr; - } - /* move to the next record */ - last_ptr = rec_ptr; - rec_ptr = rec->next; - } - /* we didn't find enough space. See if we can expand the - database and if we can then try again */ - if (tdb_expand(tdb, length + sizeof(*rec)) == 0) - goto again; - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return 0; -} - -/* initialise a new database with a specified hash size */ -static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size) -{ - struct tdb_header *newdb; - int size, ret = -1; - - /* We make it up in memory, then write it out if not internal */ - size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off); - if (!(newdb = calloc(size, 1))) - return TDB_ERRCODE(TDB_ERR_OOM, -1); - - /* Fill in the header */ - newdb->version = TDB_VERSION; - newdb->hash_size = hash_size; -#ifdef USE_SPINLOCKS - newdb->rwlocks = size; -#endif - if (tdb->flags & TDB_INTERNAL) { - tdb->map_size = size; - tdb->map_ptr = (char *)newdb; - memcpy(&tdb->header, newdb, sizeof(tdb->header)); - /* Convert the `ondisk' version if asked. */ - CONVERT(*newdb); - return 0; - } - if (lseek(tdb->fd, 0, SEEK_SET) == -1) - goto fail; - - if (ftruncate(tdb->fd, 0) == -1) - goto fail; - - /* This creates an endian-converted header, as if read from disk */ - CONVERT(*newdb); - memcpy(&tdb->header, newdb, sizeof(tdb->header)); - /* Don't endian-convert the magic food! */ - memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1); - if (write(tdb->fd, newdb, size) != size) - ret = -1; - else - ret = tdb_create_rwlocks(tdb->fd, hash_size); - - fail: - SAFE_FREE(newdb); - return ret; -} /* Returns 0 on fail. On success, return offset of record, and fills in rec */ -static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, +static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, u32 hash, struct list_struct *r) { - tdb_off rec_ptr; + tdb_off_t rec_ptr; /* read in the hash top */ - if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) return 0; /* keep looking until we find the right record */ while (rec_ptr) { - if (rec_read(tdb, rec_ptr, r) == -1) + if (tdb_rec_read(tdb, rec_ptr, r) == -1) return 0; if (!TDB_DEAD(r) && hash==r->full_hash && key.dsize==r->key_len) { @@ -1040,8 +93,8 @@ static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, } /* As tdb_find, but if you succeed, keep the lock */ -static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype, - struct list_struct *rec) +tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype, + struct list_struct *rec) { u32 rec_ptr; @@ -1052,60 +105,34 @@ static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int return rec_ptr; } -enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb) -{ - return tdb->ecode; -} - -static struct tdb_errname { - enum TDB_ERROR ecode; const char *estring; -} emap[] = { {TDB_SUCCESS, "Success"}, - {TDB_ERR_CORRUPT, "Corrupt database"}, - {TDB_ERR_IO, "IO Error"}, - {TDB_ERR_LOCK, "Locking error"}, - {TDB_ERR_OOM, "Out of memory"}, - {TDB_ERR_EXISTS, "Record exists"}, - {TDB_ERR_NOLOCK, "Lock exists on other keys"}, - {TDB_ERR_NOEXIST, "Record does not exist"} }; - -/* Error string for the last tdb error */ -const char *tdb_errorstr(TDB_CONTEXT *tdb) -{ - u32 i; - for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++) - if (tdb->ecode == emap[i].ecode) - return emap[i].estring; - return "Invalid error code"; -} /* update an entry in place - this only works if the new data size is <= the old data size and the key exists. on failure return -1. */ - -static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf) +static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf) { struct list_struct rec; - tdb_off rec_ptr; + tdb_off_t rec_ptr; /* find entry */ if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) return -1; /* must be long enough key, data and tailer */ - if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off)) { + if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off_t)) { tdb->ecode = TDB_SUCCESS; /* Not really an error */ return -1; } - if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len, + if (tdb->methods->tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len, dbuf.dptr, dbuf.dsize) == -1) return -1; if (dbuf.dsize != rec.data_len) { /* update size */ rec.data_len = dbuf.dsize; - return rec_write(tdb, rec_ptr, &rec); + return tdb_rec_write(tdb, rec_ptr, &rec); } return 0; @@ -1114,13 +141,12 @@ static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA db /* find an entry in the database given a key */ /* If an entry doesn't exist tdb_err will be set to * TDB_ERR_NOEXIST. If a key has no data attached - * tdb_err will not be set. Both will return a - * zero pptr and zero dsize. + * then the TDB_DATA will have zero length but + * a non-zero pointer */ - -TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) +TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key) { - tdb_off rec_ptr; + tdb_off_t rec_ptr; struct list_struct rec; TDB_DATA ret; u32 hash; @@ -1130,11 +156,8 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) return tdb_null; - if (rec.data_len) - ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, - rec.data_len); - else - ret.dptr = NULL; + ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, + rec.data_len); ret.dsize = rec.data_len; tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); return ret; @@ -1146,7 +169,7 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) this doesn't match the conventions in the rest of this module, but is compatible with gdbm */ -static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) +static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash) { struct list_struct rec; @@ -1156,82 +179,39 @@ static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) return 1; } -int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key) -{ - u32 hash = tdb->hash_fn(&key); - return tdb_exists_hash(tdb, key, hash); -} - -/* record lock stops delete underneath */ -static int lock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - return off ? tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0) : 0; -} -/* - Write locks override our own fcntl readlocks, so check it here. - Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not - an error to fail to get the lock here. -*/ - -static int write_lock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - struct tdb_traverse_lock *i; - for (i = &tdb->travlocks; i; i = i->next) - if (i->off == off) - return -1; - return tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1); -} - -/* - Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not - an error to fail to get the lock here. -*/ - -static int write_unlock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - return tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0); -} -/* fcntl locks don't stack: avoid unlocking someone else's */ -static int unlock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - struct tdb_traverse_lock *i; - u32 count = 0; - - if (off == 0) - return 0; - for (i = &tdb->travlocks; i; i = i->next) - if (i->off == off) - count++; - return (count == 1 ? tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0) : 0); +int tdb_exists(struct tdb_context *tdb, TDB_DATA key) +{ + u32 hash = tdb->hash_fn(&key); + return tdb_exists_hash(tdb, key, hash); } /* actually delete an entry in the database given the offset */ -static int do_delete(TDB_CONTEXT *tdb, tdb_off rec_ptr, struct list_struct*rec) +int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct*rec) { - tdb_off last_ptr, i; + tdb_off_t last_ptr, i; struct list_struct lastrec; - if (tdb->read_only) return -1; + if (tdb->read_only || tdb->traverse_read) return -1; - if (write_lock_record(tdb, rec_ptr) == -1) { + if (tdb_write_lock_record(tdb, rec_ptr) == -1) { /* Someone traversing here: mark it as dead */ rec->magic = TDB_DEAD_MAGIC; - return rec_write(tdb, rec_ptr, rec); + return tdb_rec_write(tdb, rec_ptr, rec); } - if (write_unlock_record(tdb, rec_ptr) != 0) + if (tdb_write_unlock_record(tdb, rec_ptr) != 0) return -1; /* find previous record in hash chain */ - if (ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1) + if (tdb_ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1) return -1; for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next) - if (rec_read(tdb, i, &lastrec) == -1) + if (tdb_rec_read(tdb, i, &lastrec) == -1) return -1; /* unlink it: next ptr is at start of record. */ if (last_ptr == 0) last_ptr = TDB_HASH_TOP(rec->full_hash); - if (ofs_write(tdb, last_ptr, &rec->next) == -1) + if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) return -1; /* recover the space */ @@ -1240,283 +220,27 @@ static int do_delete(TDB_CONTEXT *tdb, tdb_off rec_ptr, struct list_struct*rec) return 0; } -/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */ -static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, - struct list_struct *rec) -{ - int want_next = (tlock->off != 0); - - /* Lock each chain from the start one. */ - for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { - - /* this is an optimisation for the common case where - the hash chain is empty, which is particularly - common for the use of tdb with ldb, where large - hashes are used. In that case we spend most of our - time in tdb_brlock(), locking empty hash chains. - - To avoid this, we do an unlocked pre-check to see - if the hash chain is empty before starting to look - inside it. If it is empty then we can avoid that - hash chain. If it isn't empty then we can't believe - the value we get back, as we read it without a - lock, so instead we get the lock and re-fetch the - value below. - - Notice that not doing this optimisation on the - first hash chain is critical. We must guarantee - that we have done at least one fcntl lock at the - start of a search to guarantee that memory is - coherent on SMP systems. If records are added by - others during the search then thats OK, and we - could possibly miss those with this trick, but we - could miss them anyway without this trick, so the - semantics don't change. - - With a non-indexed ldb search this trick gains us a - factor of around 80 in speed on a linux 2.6.x - system (testing using ldbtest). - */ - if (!tlock->off && tlock->hash != 0) { - u32 off; - if (tdb->map_ptr) { - for (;tlock->hash < tdb->header.hash_size;tlock->hash++) { - if (0 != *(u32 *)(TDB_HASH_TOP(tlock->hash) + (unsigned char *)tdb->map_ptr)) { - break; - } - } - if (tlock->hash == tdb->header.hash_size) { - continue; - } - } else { - if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), &off) == 0 && - off == 0) { - continue; - } - } - } - - if (tdb_lock(tdb, tlock->hash, F_WRLCK) == -1) - return -1; - - /* No previous record? Start at top of chain. */ - if (!tlock->off) { - if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), - &tlock->off) == -1) - goto fail; - } else { - /* Otherwise unlock the previous record. */ - if (unlock_record(tdb, tlock->off) != 0) - goto fail; - } - - if (want_next) { - /* We have offset of old record: grab next */ - if (rec_read(tdb, tlock->off, rec) == -1) - goto fail; - tlock->off = rec->next; - } - - /* Iterate through chain */ - while( tlock->off) { - tdb_off current; - if (rec_read(tdb, tlock->off, rec) == -1) - goto fail; - - /* Detect infinite loops. From "Shlomi Yaakobovich" . */ - if (tlock->off == rec->next) { - TDB_LOG((tdb, 0, "tdb_next_lock: loop detected.\n")); - goto fail; - } - - if (!TDB_DEAD(rec)) { - /* Woohoo: we found one! */ - if (lock_record(tdb, tlock->off) != 0) - goto fail; - return tlock->off; - } - - /* Try to clean dead ones from old traverses */ - current = tlock->off; - tlock->off = rec->next; - if (!tdb->read_only && - do_delete(tdb, current, rec) != 0) - goto fail; - } - tdb_unlock(tdb, tlock->hash, F_WRLCK); - want_next = 0; - } - /* We finished iteration without finding anything */ - return TDB_ERRCODE(TDB_SUCCESS, 0); - - fail: - tlock->off = 0; - if (tdb_unlock(tdb, tlock->hash, F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_next_lock: On error unlock failed!\n")); - return -1; -} - -/* traverse the entire database - calling fn(tdb, key, data) on each element. - return -1 on error or the record count traversed - if fn is NULL then it is not called - a non-zero return value from fn() indicates that the traversal should stop - */ -int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *private_val) -{ - TDB_DATA key, dbuf; - struct list_struct rec; - struct tdb_traverse_lock tl = { NULL, 0, 0 }; - int ret, count = 0; - - /* This was in the initializaton, above, but the IRIX compiler - * did not like it. crh - */ - tl.next = tdb->travlocks.next; - - /* fcntl locks don't stack: beware traverse inside traverse */ - tdb->travlocks.next = &tl; - - /* tdb_next_lock places locks on the record returned, and its chain */ - while ((ret = tdb_next_lock(tdb, &tl, &rec)) > 0) { - count++; - /* now read the full record */ - key.dptr = tdb_alloc_read(tdb, tl.off + sizeof(rec), - rec.key_len + rec.data_len); - if (!key.dptr) { - ret = -1; - if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) - goto out; - if (unlock_record(tdb, tl.off) != 0) - TDB_LOG((tdb, 0, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); - goto out; - } - key.dsize = rec.key_len; - dbuf.dptr = key.dptr + rec.key_len; - dbuf.dsize = rec.data_len; - - /* Drop chain lock, call out */ - if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) { - ret = -1; - SAFE_FREE(key.dptr); - goto out; - } - if (fn && fn(tdb, key, dbuf, private_val)) { - /* They want us to terminate traversal */ - ret = count; - if (unlock_record(tdb, tl.off) != 0) { - TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));; - ret = -1; - } - SAFE_FREE(key.dptr); - goto out; - } - SAFE_FREE(key.dptr); - } -out: - tdb->travlocks.next = tl.next; - if (ret < 0) - return -1; - else - return count; -} - -/* find the first entry in the database and return its key */ -TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb) -{ - TDB_DATA key; - struct list_struct rec; - - /* release any old lock */ - if (unlock_record(tdb, tdb->travlocks.off) != 0) - return tdb_null; - tdb->travlocks.off = tdb->travlocks.hash = 0; - - if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0) - return tdb_null; - /* now read the key */ - key.dsize = rec.key_len; - key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); - if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_firstkey: error occurred while tdb_unlocking!\n")); - return key; -} - -/* find the next entry in the database, returning its key */ -TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey) -{ - u32 oldhash; - TDB_DATA key = tdb_null; - struct list_struct rec; - char *k = NULL; - - /* Is locked key the old key? If so, traverse will be reliable. */ - if (tdb->travlocks.off) { - if (tdb_lock(tdb,tdb->travlocks.hash,F_WRLCK)) - return tdb_null; - if (rec_read(tdb, tdb->travlocks.off, &rec) == -1 - || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec), - rec.key_len)) - || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) { - /* No, it wasn't: unlock it and start from scratch */ - if (unlock_record(tdb, tdb->travlocks.off) != 0) { - SAFE_FREE(k); - return tdb_null; - } - if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) { - SAFE_FREE(k); - return tdb_null; - } - tdb->travlocks.off = 0; - } - - SAFE_FREE(k); - } - - if (!tdb->travlocks.off) { - /* No previous element: do normal find, and lock record */ - tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), F_WRLCK, &rec); - if (!tdb->travlocks.off) - return tdb_null; - tdb->travlocks.hash = BUCKET(rec.full_hash); - if (lock_record(tdb, tdb->travlocks.off) != 0) { - TDB_LOG((tdb, 0, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); - return tdb_null; - } - } - oldhash = tdb->travlocks.hash; - - /* Grab next record: locks chain and returned record, - unlocks old record */ - if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) { - key.dsize = rec.key_len; - key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec), - key.dsize); - /* Unlock the chain of this new record */ - if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); - } - /* Unlock the chain of old record */ - if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); - return key; -} - /* delete an entry in the database given a key */ -static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) +static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash) { - tdb_off rec_ptr; + tdb_off_t rec_ptr; struct list_struct rec; int ret; if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec))) return -1; - ret = do_delete(tdb, rec_ptr, &rec); + ret = tdb_do_delete(tdb, rec_ptr, &rec); + + if (ret == 0) { + tdb_increment_seqnum(tdb); + } + if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0) TDB_LOG((tdb, 0, "tdb_delete: WARNING tdb_unlock failed!\n")); return ret; } -int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) +int tdb_delete(struct tdb_context *tdb, TDB_DATA key) { u32 hash = tdb->hash_fn(&key); return tdb_delete_hash(tdb, key, hash); @@ -1527,14 +251,19 @@ int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) return 0 on success, -1 on failure */ -int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) +int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) { struct list_struct rec; u32 hash; - tdb_off rec_ptr; + tdb_off_t rec_ptr; char *p = NULL; int ret = 0; + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + /* find which hash bucket it is in */ hash = tdb->hash_fn(&key); if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) @@ -1555,7 +284,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) /* if the record doesn't exist and we are in TDB_MODIFY mode then we should fail the store */ goto fail; - } + } } /* reset the error code potentially set by the tdb_update() */ tdb->ecode = TDB_SUCCESS; @@ -1583,7 +312,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) goto fail; /* Read hash top into next ptr */ - if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) goto fail; rec.key_len = key.dsize; @@ -1592,12 +321,15 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) rec.magic = TDB_MAGIC; /* write out and point the top of the hash chain at it */ - if (rec_write(tdb, rec_ptr, &rec) == -1 - || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 - || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { + if (tdb_rec_write(tdb, rec_ptr, &rec) == -1 + || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 + || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { /* Need to tdb_unallocate() here */ goto fail; } + + tdb_increment_seqnum(tdb); + out: SAFE_FREE(p); tdb_unlock(tdb, BUCKET(hash), F_WRLCK); @@ -1607,521 +339,92 @@ fail: goto out; } -/* Attempt to append data to an entry in place - this only works if the new data size - is <= the old data size and the key exists. - on failure return -1. Record must be locked before calling. -*/ -static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA new_dbuf) -{ - struct list_struct rec; - tdb_off rec_ptr; - - /* find entry */ - if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) - return -1; - - /* Append of 0 is always ok. */ - if (new_dbuf.dsize == 0) - return 0; - - /* must be long enough for key, old data + new data and tailer */ - if (rec.rec_len < key.dsize + rec.data_len + new_dbuf.dsize + sizeof(tdb_off)) { - /* No room. */ - tdb->ecode = TDB_SUCCESS; /* Not really an error */ - return -1; - } - - if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len + rec.data_len, - new_dbuf.dptr, new_dbuf.dsize) == -1) - return -1; - - /* update size */ - rec.data_len += new_dbuf.dsize; - return rec_write(tdb, rec_ptr, &rec); -} /* Append to an entry. Create if not exist. */ - -int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) +int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf) { - struct list_struct rec; u32 hash; - tdb_off rec_ptr; - char *p = NULL; - int ret = 0; - size_t new_data_size = 0; + TDB_DATA dbuf; + int ret = -1; /* find which hash bucket it is in */ hash = tdb->hash_fn(&key); if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) return -1; - /* first try in-place. */ - if (tdb_append_inplace(tdb, key, hash, new_dbuf) == 0) - goto out; - - /* reset the error code potentially set by the tdb_append_inplace() */ - tdb->ecode = TDB_SUCCESS; - - /* find entry */ - if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) { - if (tdb->ecode != TDB_ERR_NOEXIST) - goto fail; - - /* Not found - create. */ + dbuf = tdb_fetch(tdb, key); - ret = tdb_store(tdb, key, new_dbuf, TDB_INSERT); - goto out; + if (dbuf.dptr == NULL) { + dbuf.dptr = malloc(new_dbuf.dsize); + } else { + dbuf.dptr = realloc(dbuf.dptr, dbuf.dsize + new_dbuf.dsize); } - new_data_size = rec.data_len + new_dbuf.dsize; - - /* Copy key+old_value+value *before* allocating free space in case malloc - fails and we are left with a dead spot in the tdb. */ - - if (!(p = (char *)malloc(key.dsize + new_data_size))) { + if (dbuf.dptr == NULL) { tdb->ecode = TDB_ERR_OOM; - goto fail; - } - - /* Copy the key in place. */ - memcpy(p, key.dptr, key.dsize); - - /* Now read the old data into place. */ - if (rec.data_len && - tdb_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, p + key.dsize, rec.data_len, 0) == -1) - goto fail; - - /* Finally append the new data. */ - if (new_dbuf.dsize) - memcpy(p+key.dsize+rec.data_len, new_dbuf.dptr, new_dbuf.dsize); - - /* delete any existing record - if it doesn't exist we don't - care. Doing this first reduces fragmentation, and avoids - coalescing with `allocated' block before it's updated. */ - - tdb_delete_hash(tdb, key, hash); - - if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec))) - goto fail; - - /* Read hash top into next ptr */ - if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) - goto fail; - - rec.key_len = key.dsize; - rec.data_len = new_data_size; - rec.full_hash = hash; - rec.magic = TDB_MAGIC; - - /* write out and point the top of the hash chain at it */ - if (rec_write(tdb, rec_ptr, &rec) == -1 - || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+new_data_size)==-1 - || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { - /* Need to tdb_unallocate() here */ - goto fail; - } - - out: - SAFE_FREE(p); - tdb_unlock(tdb, BUCKET(hash), F_WRLCK); - return ret; - -fail: - ret = -1; - goto out; -} - -static int tdb_already_open(dev_t device, - ino_t ino) -{ - TDB_CONTEXT *i; - - for (i = tdbs; i; i = i->next) { - if (i->device == device && i->inode == ino) { - return 1; - } - } - - return 0; -} - -/* This is based on the hash algorithm from gdbm */ -static u32 default_tdb_hash(TDB_DATA *key) -{ - u32 value; /* Used to compute the hash value. */ - u32 i; /* Used to cycle through random values. */ - - /* Set the initial value from the key size. */ - for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++) - value = (value + (key->dptr[i] << (i*5 % 24))); - - return (1103515243 * value + 12345); -} - -/* open the database, creating it if necessary - - The open_flags and mode are passed straight to the open call on the - database file. A flags value of O_WRONLY is invalid. The hash size - is advisory, use zero for a default value. - - Return is NULL on error, in which case errno is also set. Don't - try to call tdb_error or tdb_errname, just do strerror(errno). - - @param name may be NULL for internal databases. */ -TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode) -{ - return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL); -} - - -TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode, - tdb_log_func log_fn, - tdb_hash_func hash_fn) -{ - TDB_CONTEXT *tdb; - struct stat st; - int rev = 0, locked = 0; - unsigned char *vp; - u32 vertest; - - if (!(tdb = calloc(1, sizeof *tdb))) { - /* Can't log this */ - errno = ENOMEM; - goto fail; - } - tdb->fd = -1; - tdb->name = NULL; - tdb->map_ptr = NULL; - tdb->flags = tdb_flags; - tdb->open_flags = open_flags; - tdb->log_fn = log_fn; - tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; - - if ((open_flags & O_ACCMODE) == O_WRONLY) { - TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n", - name)); - errno = EINVAL; - goto fail; - } - - if (hash_size == 0) - hash_size = DEFAULT_HASH_SIZE; - if ((open_flags & O_ACCMODE) == O_RDONLY) { - tdb->read_only = 1; - /* read only databases don't do locking or clear if first */ - tdb->flags |= TDB_NOLOCK; - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - } - - /* internal databases don't mmap or lock, and start off cleared */ - if (tdb->flags & TDB_INTERNAL) { - tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - if (tdb_new_database(tdb, hash_size) != 0) { - TDB_LOG((tdb, 0, "tdb_open_ex: tdb_new_database failed!")); - goto fail; - } - goto internal; - } - - if ((tdb->fd = open(name, open_flags, mode)) == -1) { - TDB_LOG((tdb, 5, "tdb_open_ex: could not open file %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by open(2) */ - } - - /* ensure there is only one process initialising at once */ - if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: failed to get global lock on %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by tdb_brlock */ - } - - /* we need to zero database if we are the only one with it open */ - if ((tdb_flags & TDB_CLEAR_IF_FIRST) && - (locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) { - open_flags |= O_CREAT; - if (ftruncate(tdb->fd, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: " - "failed to truncate %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by ftruncate */ - } - } - - if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) - || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0 - || (tdb->header.version != TDB_VERSION - && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) { - /* its not a valid database - possibly initialise it */ - if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) { - errno = EIO; /* ie bad format or something */ - goto fail; - } - rev = (tdb->flags & TDB_CONVERT); - } - vp = (unsigned char *)&tdb->header.version; - vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) | - (((u32)vp[2]) << 8) | (u32)vp[3]; - tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; - if (!rev) - tdb->flags &= ~TDB_CONVERT; - else { - tdb->flags |= TDB_CONVERT; - convert(&tdb->header, sizeof(tdb->header)); - } - if (fstat(tdb->fd, &st) == -1) - goto fail; - - /* Is it already in the open list? If so, fail. */ - if (tdb_already_open(st.st_dev, st.st_ino)) { - TDB_LOG((tdb, 2, "tdb_open_ex: " - "%s (%d,%d) is already open in this process\n", - name, (int)st.st_dev, (int)st.st_ino)); - errno = EBUSY; - goto fail; - } - - if (!(tdb->name = (char *)strdup(name))) { - errno = ENOMEM; - goto fail; - } - - tdb->map_size = st.st_size; - tdb->device = st.st_dev; - tdb->inode = st.st_ino; - tdb->locked = calloc(tdb->header.hash_size+1, sizeof(tdb->locked[0])); - if (!tdb->locked) { - TDB_LOG((tdb, 2, "tdb_open_ex: " - "failed to allocate lock structure for %s\n", - name)); - errno = ENOMEM; - goto fail; - } - tdb_mmap(tdb); - if (locked) { - if (!tdb->read_only) - if (tdb_clear_spinlocks(tdb) != 0) { - TDB_LOG((tdb, 0, "tdb_open_ex: " - "failed to clear spinlock\n")); - goto fail; - } - if (tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: " - "failed to take ACTIVE_LOCK on %s: %s\n", - name, strerror(errno))); - goto fail; - } - - } - - /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if - we didn't get the initial exclusive lock as we need to let all other - users know we're using it. */ - - if (tdb_flags & TDB_CLEAR_IF_FIRST) { - /* leave this lock in place to indicate it's in use */ - if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) - goto fail; + goto failed; } + memcpy(dbuf.dptr + dbuf.dsize, new_dbuf.dptr, new_dbuf.dsize); + dbuf.dsize += new_dbuf.dsize; - internal: - /* Internal (memory-only) databases skip all the code above to - * do with disk files, and resume here by releasing their - * global lock and hooking into the active list. */ - if (tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1) - goto fail; - tdb->next = tdbs; - tdbs = tdb; - return tdb; - - fail: - { int save_errno = errno; - - if (!tdb) - return NULL; + ret = tdb_store(tdb, key, dbuf, 0); - if (tdb->map_ptr) { - if (tdb->flags & TDB_INTERNAL) - SAFE_FREE(tdb->map_ptr); - else - tdb_munmap(tdb); - } - SAFE_FREE(tdb->name); - if (tdb->fd != -1) - if (close(tdb->fd) != 0) - TDB_LOG((tdb, 5, "tdb_open_ex: failed to close tdb->fd on error!\n")); - SAFE_FREE(tdb->locked); - SAFE_FREE(tdb); - errno = save_errno; - return NULL; - } -} - -/** - * Close a database. - * - * @returns -1 for error; 0 for success. - **/ -int tdb_close(TDB_CONTEXT *tdb) -{ - TDB_CONTEXT **i; - int ret = 0; - - if (tdb->map_ptr) { - if (tdb->flags & TDB_INTERNAL) - SAFE_FREE(tdb->map_ptr); - else - tdb_munmap(tdb); - } - SAFE_FREE(tdb->name); - if (tdb->fd != -1) - ret = close(tdb->fd); - SAFE_FREE(tdb->locked); - - /* Remove from contexts list */ - for (i = &tdbs; *i; i = &(*i)->next) { - if (*i == tdb) { - *i = tdb->next; - break; - } - } - - memset(tdb, 0, sizeof(*tdb)); - SAFE_FREE(tdb); - +failed: + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + SAFE_FREE(dbuf.dptr); return ret; } -/* lock/unlock entire database */ -int tdb_lockall(TDB_CONTEXT *tdb) -{ - u32 i; - - /* There are no locks on read-only dbs */ - if (tdb->read_only) - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - for (i = 0; i < tdb->header.hash_size; i++) - if (tdb_lock(tdb, i, F_WRLCK)) - break; - - /* If error, release locks we have... */ - if (i < tdb->header.hash_size) { - u32 j; - - for ( j = 0; j < i; j++) - tdb_unlock(tdb, j, F_WRLCK); - return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); - } - - return 0; -} -void tdb_unlockall(TDB_CONTEXT *tdb) -{ - u32 i; - for (i=0; i < tdb->header.hash_size; i++) - tdb_unlock(tdb, i, F_WRLCK); -} - -/* lock/unlock one hash chain. This is meant to be used to reduce - contention - it cannot guarantee how many records will be locked */ -int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key) -{ - return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); -} -int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key) +/* + return the name of the current tdb file + useful for external logging functions +*/ +const char *tdb_name(struct tdb_context *tdb) { - return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); + return tdb->name; } -int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key) +/* + return the underlying file descriptor being used by tdb, or -1 + useful for external routines that want to check the device/inode + of the fd +*/ +int tdb_fd(struct tdb_context *tdb) { - return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); + return tdb->fd; } -int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key) +/* + return the current logging function + useful for external tdb routines that wish to log tdb errors +*/ +tdb_log_func tdb_log_fn(struct tdb_context *tdb) { - return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); + return tdb->log_fn; } -/* register a loging function */ -void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , const char *, ...)) -{ - tdb->log_fn = fn; -} - -/* reopen a tdb - this can be used after a fork to ensure that we have an independent - seek pointer from our parent and to re-establish locks */ -int tdb_reopen(TDB_CONTEXT *tdb) +/* + get the tdb sequence number. Only makes sense if the writers opened + with TDB_SEQNUM set. Note that this sequence number will wrap quite + quickly, so it should only be used for a 'has something changed' + test, not for code that relies on the count of the number of changes + made. If you want a counter then use a tdb record. + + The aim of this sequence number is to allow for a very lightweight + test of a possible tdb change. +*/ +int tdb_get_seqnum(struct tdb_context *tdb) { - struct stat st; - - if (tdb->flags & TDB_INTERNAL) - return 0; /* Nothing to do. */ - if (tdb_munmap(tdb) != 0) { - TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); - goto fail; - } - if (close(tdb->fd) != 0) - TDB_LOG((tdb, 0, "tdb_reopen: WARNING closing tdb->fd failed!\n")); - tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); - if (tdb->fd == -1) { - TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno))); - goto fail; - } - if ((tdb->flags & TDB_CLEAR_IF_FIRST) && - (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) { - TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n")); - goto fail; - } - if (fstat(tdb->fd, &st) != 0) { - TDB_LOG((tdb, 0, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); - goto fail; - } - if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { - TDB_LOG((tdb, 0, "tdb_reopen: file dev/inode has changed!\n")); - goto fail; - } - tdb_mmap(tdb); - - return 0; + tdb_off_t seqnum=0; -fail: - tdb_close(tdb); - return -1; + tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); + return seqnum; } -/* reopen all tdb's */ -int tdb_reopen_all(int parent_longlived) +int tdb_hash_size(struct tdb_context *tdb) { - TDB_CONTEXT *tdb; - - for (tdb=tdbs; tdb; tdb = tdb->next) { - /* - * If the parent is longlived (ie. a - * parent daemon architecture), we know - * it will keep it's active lock on a - * tdb opened with CLEAR_IF_FIRST. Thus - * for child processes we don't have to - * add an active lock. This is essential - * to improve performance on systems that - * keep POSIX locks as a non-scalable data - * structure in the kernel. - */ - if (parent_longlived) { - /* Ensure no clear-if-first. */ - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - } - - if (tdb_reopen(tdb) != 0) - return -1; - } - - return 0; + return tdb->header.hash_size; } diff --git a/source3/tdb/tdb.h b/source3/tdb/tdb.h index b5b87ee5a54..82f8828c89d 100644 --- a/source3/tdb/tdb.h +++ b/source3/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/source3/tdb/tdb_private.h b/source3/tdb/tdb_private.h new file mode 100644 index 00000000000..d10c1c46bf6 --- /dev/null +++ b/source3/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 +#include +#ifdef HAVE_STDINT_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#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/source3/tdb/tdbback.c b/source3/tdb/tdbback.c index 7967a6bbf54..c337924d6cf 100644 --- a/source3/tdb/tdbback.c +++ b/source3/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/source3/tdb/tdbutil.c b/source3/tdb/tdbutil.c index fc45fa93606..e13f7e3e678 100644 --- a/source3/tdb/tdbutil.c +++ b/source3/tdb/tdbutil.c @@ -19,9 +19,21 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "includes.h" +#include "tdb_private.h" #include +/*************************************************************** + Allow a caller to set a "alarm" flag that tdb can check to abort + a blocking lock on SIGALRM. +***************************************************************/ + +static sig_atomic_t *palarm_fired; + +static void tdb_set_lock_alarm(sig_atomic_t *palarm) +{ + palarm_fired = palarm; +} + /* these are little tdb utility functions that are meant to make dealing with a tdb database a little less cumbersome in Samba */ @@ -641,129 +653,6 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) } -/** - * Pack SID passed by pointer - * - * @param pack_buf pointer to buffer which is to be filled with packed data - * @param bufsize size of packing buffer - * @param sid pointer to sid to be packed - * - * @return length of the packed representation of the whole structure - **/ -size_t tdb_sid_pack(char* pack_buf, int bufsize, DOM_SID* sid) -{ - int idx; - size_t len = 0; - - if (!sid || !pack_buf) return -1; - - len += tdb_pack(pack_buf + len, bufsize - len, "bb", sid->sid_rev_num, - sid->num_auths); - - for (idx = 0; idx < 6; idx++) { - len += tdb_pack(pack_buf + len, bufsize - len, "b", sid->id_auth[idx]); - } - - for (idx = 0; idx < MAXSUBAUTHS; idx++) { - len += tdb_pack(pack_buf + len, bufsize - len, "d", sid->sub_auths[idx]); - } - - return len; -} - - -/** - * Unpack SID into a pointer - * - * @param pack_buf pointer to buffer with packed representation - * @param bufsize size of the buffer - * @param sid pointer to sid structure to be filled with unpacked data - * - * @return size of structure unpacked from buffer - **/ -size_t tdb_sid_unpack(char* pack_buf, int bufsize, DOM_SID* sid) -{ - int idx, len = 0; - - if (!sid || !pack_buf) return -1; - - len += tdb_unpack(pack_buf + len, bufsize - len, "bb", - &sid->sid_rev_num, &sid->num_auths); - - for (idx = 0; idx < 6; idx++) { - len += tdb_unpack(pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]); - } - - for (idx = 0; idx < MAXSUBAUTHS; idx++) { - len += tdb_unpack(pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]); - } - - return len; -} - - -/** - * Pack TRUSTED_DOM_PASS passed by pointer - * - * @param pack_buf pointer to buffer which is to be filled with packed data - * @param bufsize size of the buffer - * @param pass pointer to trusted domain password to be packed - * - * @return length of the packed representation of the whole structure - **/ -size_t tdb_trusted_dom_pass_pack(char* pack_buf, int bufsize, TRUSTED_DOM_PASS* pass) -{ - int idx, len = 0; - - if (!pack_buf || !pass) return -1; - - /* packing unicode domain name and password */ - len += tdb_pack(pack_buf + len, bufsize - len, "d", pass->uni_name_len); - - for (idx = 0; idx < 32; idx++) - len += tdb_pack(pack_buf + len, bufsize - len, "w", pass->uni_name[idx]); - - len += tdb_pack(pack_buf + len, bufsize - len, "dPd", pass->pass_len, - pass->pass, pass->mod_time); - - /* packing SID structure */ - len += tdb_sid_pack(pack_buf + len, bufsize - len, &pass->domain_sid); - - return len; -} - - -/** - * Unpack TRUSTED_DOM_PASS passed by pointer - * - * @param pack_buf pointer to buffer with packed representation - * @param bufsize size of the buffer - * @param pass pointer to trusted domain password to be filled with unpacked data - * - * @return size of structure unpacked from buffer - **/ -size_t tdb_trusted_dom_pass_unpack(char* pack_buf, int bufsize, TRUSTED_DOM_PASS* pass) -{ - int idx, len = 0; - - if (!pack_buf || !pass) return -1; - - /* unpack unicode domain name and plaintext password */ - len += tdb_unpack(pack_buf, bufsize - len, "d", &pass->uni_name_len); - - for (idx = 0; idx < 32; idx++) - len += tdb_unpack(pack_buf + len, bufsize - len, "w", &pass->uni_name[idx]); - - len += tdb_unpack(pack_buf + len, bufsize - len, "dPd", &pass->pass_len, &pass->pass, - &pass->mod_time); - - /* unpack domain sid */ - len += tdb_sid_unpack(pack_buf + len, bufsize - len, &pass->domain_sid); - - return len; -} - - /**************************************************************************** Log tdb messages via DEBUG(). ****************************************************************************/ @@ -805,15 +694,6 @@ TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, return tdb; } -/**************************************************************************** - return the name of the current tdb file useful for external logging - functions -****************************************************************************/ -const char *tdb_name(struct tdb_context *tdb) -{ - return tdb->name; -} - /**************************************************************************** Allow tdb_delete to be used as a tdb_traversal_fn. ****************************************************************************/ @@ -893,3 +773,43 @@ void tdb_search_list_free(TDB_LIST_NODE* node) node = next_node; }; } + +size_t tdb_map_size(struct tdb_context *tdb) +{ + return tdb->map_size; +} + +int tdb_get_flags(struct tdb_context *tdb) +{ + return tdb->flags; +} + +/**************************************************************************** + tdb_store, wrapped in a transaction. This way we make sure that a process + that dies within writing does not leave a corrupt tdb behind. +****************************************************************************/ + +int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, + int flag) +{ + int res; + + if ((res = tdb_transaction_start(tdb)) != 0) { + DEBUG(5, ("tdb_transaction_start failed\n")); + return res; + } + + if ((res = tdb_store(tdb, key, dbuf, flag)) != 0) { + DEBUG(10, ("tdb_store failed\n")); + if (tdb_transaction_cancel(tdb) != 0) { + smb_panic("Cancelling transaction failed\n"); + } + return res; + } + + if ((res = tdb_transaction_commit(tdb)) != 0) { + DEBUG(5, ("tdb_transaction_commit failed\n")); + } + + return res; +} diff --git a/source3/tdb/tdbutil.h b/source3/tdb/tdbutil.h index 1a181a962f2..44351619f45 100644 --- a/source3/tdb/tdbutil.h +++ b/source3/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/source3/tdb/transaction.c b/source3/tdb/transaction.c new file mode 100644 index 00000000000..aa54c4ae3c8 --- /dev/null +++ b/source3/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;hheader.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/source3/tdb/traverse.c b/source3/tdb/traverse.c new file mode 100644 index 00000000000..d070e0a7662 --- /dev/null +++ b/source3/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" . */ + 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/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index cc683977e8c..6cecd693f83 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/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/source3/torture/locktest.c b/source3/torture/locktest.c index b946e48666e..3559a55a467 100644 --- a/source3/torture/locktest.c +++ b/source3/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/source3/torture/locktest2.c b/source3/torture/locktest2.c index 519acebe8e8..5f2f2499acd 100644 --- a/source3/torture/locktest2.c +++ b/source3/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/source3/torture/masktest.c b/source3/torture/masktest.c index ffc9a20e71c..44d26cdc5ad 100644 --- a/source3/torture/masktest.c +++ b/source3/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/source3/torture/nsstest.c b/source3/torture/nsstest.c index d2b17f0f635..7673f922090 100644 --- a/source3/torture/nsstest.c +++ b/source3/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/source3/torture/pdbtest.c b/source3/torture/pdbtest.c new file mode 100644 index 00000000000..e1a35b79127 --- /dev/null +++ b/source3/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/source3/torture/rpctorture.c b/source3/torture/rpctorture.c index d69cc8eb8df..98f2dc105fa 100644 --- a/source3/torture/rpctorture.c +++ b/source3/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/source3/torture/scanner.c b/source3/torture/scanner.c index 1893be83699..1510cd70f4c 100644 --- a/source3/torture/scanner.c +++ b/source3/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/source3/torture/torture.c b/source3/torture/torture.c index 0b3bfc18f4a..25e249ed2e1 100644 --- a/source3/torture/torture.c +++ b/source3/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/source3/torture/vfstest.c b/source3/torture/vfstest.c index 61bb4b0bf65..fa0545988e9 100644 --- a/source3/torture/vfstest.c +++ b/source3/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/source3/utils/debug2html.c b/source3/utils/debug2html.c index bec4d81ae2b..6d1b2b25352 100644 --- a/source3/utils/debug2html.c +++ b/source3/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/source3/utils/net.c b/source3/utils/net.c index bef2a0a83c2..8b4fb042fcf 100644 --- a/source3/utils/net.c +++ b/source3/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/source3/utils/net_ads.c b/source3/utils/net_ads.c index 9d122a466bb..bfbc80759aa 100644 --- a/source3/utils/net_ads.c +++ b/source3/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/source3/utils/net_idmap.c b/source3/utils/net_idmap.c index 47e1f93b69f..87da952247a 100644 --- a/source3/utils/net_idmap.c +++ b/source3/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/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index f32348935fc..f2cd4adb176 100644 --- a/source3/utils/net_rpc.c +++ b/source3/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/source3/utils/net_rpc_printer.c b/source3/utils/net_rpc_printer.c index 8808d549ac5..50ab50bace3 100644 --- a/source3/utils/net_rpc_printer.c +++ b/source3/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; ibuffer, 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; ibuffer, 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; inum_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/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index 4f99c3035c8..861040533c6 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/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/source3/utils/net_time.c b/source3/utils/net_time.c index f6486286a65..f6269627dab 100644 --- a/source3/utils/net_time.c +++ b/source3/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/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index ef24f9f1611..fc9e3e9546a 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/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/source3/utils/ntlm_auth_diagnostics.c b/source3/utils/ntlm_auth_diagnostics.c index c8ea966a558..e69715affd0 100644 --- a/source3/utils/ntlm_auth_diagnostics.c +++ b/source3/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/source3/utils/sharesec.c b/source3/utils/sharesec.c new file mode 100644 index 00000000000..aa4210b51dc --- /dev/null +++ b/source3/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; iecode = 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/source3/utils/status.c b/source3/utils/status.c index 163d99a2f69..58349f1f9a5 100644 --- a/source3/utils/status.c +++ b/source3/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/source3/utils/status_profile.c b/source3/utils/status_profile.c new file mode 100644 index 00000000000..fc5b5e10ffd --- /dev/null +++ b/source3/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/source3/web/diagnose.c b/source3/web/diagnose.c index d259717da0b..b53e139ca94 100644 --- a/source3/web/diagnose.c +++ b/source3/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/source3/web/neg_lang.c b/source3/web/neg_lang.c index fb79f41f13c..207614655db 100644 --- a/source3/web/neg_lang.c +++ b/source3/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/source3/web/swat.c b/source3/web/swat.c index d1fd0b4f9bc..d43f8941bc1 100644 --- a/source3/web/swat.c +++ b/source3/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); } -- cgit v1.2.1