diff options
author | Jeremy Allison <jra@samba.org> | 2006-07-11 18:01:26 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:19:14 -0500 |
commit | 9dafb7f48ca3e7af956b0a7d1720c2546fc4cfb8 (patch) | |
tree | 8e6f198af4605246bd3681c25826d8efe5c0d08b /source | |
parent | f131bf8f16fd8b7c49e6065ecbf6f8686b2f4269 (diff) | |
download | samba-9dafb7f48ca3e7af956b0a7d1720c2546fc4cfb8.tar.gz |
r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need
to do the upper layer directories but this is what
everyone is waiting for....
Jeremy.
Diffstat (limited to 'source')
259 files changed, 19090 insertions, 9042 deletions
diff --git a/source/Doxyfile b/source/Doxyfile index c1040781d84..cdcb658908a 100644 --- a/source/Doxyfile +++ b/source/Doxyfile @@ -168,9 +168,3 @@ DOT_CLEANUP = YES # configuration::additions related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO -CGI_NAME = search.cgi -CGI_URL = -DOC_URL = -DOC_ABSPATH = -BIN_ABSPATH = /usr/local/bin/ -EXT_DOC_PATHS = diff --git a/source/Makefile.in b/source/Makefile.in index 127936125bf..3f586180f04 100644 --- a/source/Makefile.in +++ b/source/Makefile.in @@ -145,11 +145,12 @@ BIN_PROGS2 = bin/smbcontrol@EXEEXT@ bin/smbtree@EXEEXT@ bin/tdbbackup@EXEEXT@ \ bin/tdbtool@EXEEXT@ BIN_PROGS3 = bin/smbpasswd@EXEEXT@ bin/rpcclient@EXEEXT@ bin/smbcacls@EXEEXT@ \ bin/profiles@EXEEXT@ bin/ntlm_auth@EXEEXT@ \ - bin/smbcquotas@EXEEXT@ bin/eventlogadm@EXEEXT@ + bin/smbcquotas@EXEEXT@ bin/eventlogadm@EXEEXT@ bin/sharesec@EXEEXT@ TORTURE_PROGS = bin/smbtorture@EXEEXT@ bin/msgtest@EXEEXT@ \ bin/masktest@EXEEXT@ bin/locktest@EXEEXT@ \ - bin/locktest2@EXEEXT@ bin/nsstest@EXEEXT@ bin/vfstest@EXEEXT@ + bin/locktest2@EXEEXT@ bin/nsstest@EXEEXT@ bin/vfstest@EXEEXT@ \ + bin/pdbtest@EXEEXT@ BIN_PROGS = $(BIN_PROGS1) $(BIN_PROGS2) $(BIN_PROGS3) @EXTRA_BIN_PROGS@ @@ -174,7 +175,8 @@ MODULES = $(VFS_MODULES) $(PDB_MODULES) $(RPC_MODULES) $(IDMAP_MODULES) $(CHARSE # object file lists ###################################################################### -TDBBASE_OBJ = tdb/tdb.o tdb/spinlock.o +TDBBASE_OBJ = tdb/tdb.o tdb/dump.o tdb/error.o tdb/freelist.o tdb/io.o \ + tdb/lock.o tdb/open.o tdb/transaction.o tdb/traverse.o TDB_OBJ = $(TDBBASE_OBJ) tdb/tdbutil.o tdb/tdbback.o @@ -200,6 +202,9 @@ PASSCHANGE_OBJ = libsmb/passchange.o SOCKET_WRAPPER_OBJ = lib/socket_wrapper.o +LIBNDR_OBJ = libndr/ndr_basic.o libndr/ndr.o libndr/ndr_misc.o \ + libndr/ndr_sec_helper.o libndr/ndr_string.o libndr/sid.o + RPC_PARSE_OBJ0 = rpc_parse/parse_prs.o rpc_parse/parse_misc.o LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \ @@ -209,7 +214,7 @@ LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \ lib/ufc.o lib/genrand.o lib/username.o \ lib/util_pw.o lib/access.o lib/smbrun.o \ lib/bitmap.o lib/crc32.o $(SNPRINTF_OBJ) lib/dprintf.o \ - lib/xfile.o lib/wins_srv.o \ + lib/xfile.o lib/wins_srv.o lib/util_reg.o \ lib/util_str.o lib/clobber.o lib/util_sid.o lib/util_uuid.o \ lib/util_unistr.o lib/util_file.o lib/data_blob.o \ lib/util.o lib/util_sock.o lib/sock_exec.o lib/util_sec.o \ @@ -272,7 +277,8 @@ LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \ rpc_client/cli_reg.o $(RPC_CLIENT_OBJ) \ rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o \ rpc_client/cli_ds.o rpc_client/cli_echo.o \ - rpc_client/cli_shutdown.o rpc_client/cli_svcctl.o + rpc_client/cli_shutdown.o rpc_client/cli_svcctl.o \ + rpc_client/cli_unixinfo.o REGOBJS_OBJ = registry/reg_objects.o @@ -287,6 +293,7 @@ RPC_NETLOG_OBJ = rpc_server/srv_netlog.o rpc_server/srv_netlog_nt.o RPC_SAMR_OBJ = rpc_server/srv_samr.o rpc_server/srv_samr_nt.o \ rpc_server/srv_samr_util.o +RPC_UNIXINFO_OBJ = rpc_server/srv_unixinfo.o rpc_server/srv_unixinfo_nt.o REGFIO_OBJ = registry/regfio.o RPC_REG_OBJ = rpc_server/srv_reg.o rpc_server/srv_reg_nt.o $(REGFIO_OBJ) @@ -327,9 +334,9 @@ RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_net.o \ rpc_parse/parse_wks.o rpc_parse/parse_ds.o \ rpc_parse/parse_spoolss.o rpc_parse/parse_dfs.o \ rpc_parse/parse_echo.o rpc_parse/parse_shutdown.o \ - rpc_parse/parse_svcctl.o \ + rpc_parse/parse_svcctl.o rpc_parse/parse_unixinfo.o \ rpc_parse/parse_eventlog.o rpc_parse/parse_buffer.o \ - rpc_parse/parse_ntsvcs.o $(REGOBJS_OBJ) + rpc_parse/parse_ntsvcs.o $(REGOBJS_OBJ) $(LIBNDR_OBJ) RPC_CLIENT_OBJ = rpc_client/cli_pipe.o @@ -361,6 +368,7 @@ OPLOCK_OBJ = smbd/oplock.o smbd/oplock_irix.o smbd/oplock_linux.o NOTIFY_OBJ = smbd/notify.o smbd/notify_hash.o smbd/notify_kernel.o smbd/notify_fam.o +VFS_DEFAULT_OBJ = modules/vfs_default.o VFS_AUDIT_OBJ = modules/vfs_audit.o VFS_EXTD_AUDIT_OBJ = modules/vfs_extd_audit.o VFS_FULL_AUDIT_OBJ = modules/vfs_full_audit.o @@ -374,6 +382,9 @@ VFS_EXPAND_MSDFS_OBJ = modules/vfs_expand_msdfs.o VFS_SHADOW_COPY_OBJ = modules/vfs_shadow_copy.o VFS_AFSACL_OBJ = modules/vfs_afsacl.o VFS_CATIA_OBJ = modules/vfs_catia.o +VFS_CACHEPRIME_OBJ = modules/vfs_cacheprime.o +VFS_PREALLOC_OBJ = modules/vfs_prealloc.o +VFS_COMMIT_OBJ = modules/vfs_commit.o PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o @@ -408,7 +419,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \ smbd/reply.o smbd/sesssetup.o smbd/trans2.o smbd/uid.o \ smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o \ smbd/blocking.o smbd/sec_ctx.o smbd/srvstr.o \ - smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \ + smbd/vfs.o smbd/statcache.o \ smbd/posix_acls.o lib/sysacls.o $(SERVER_MUTEX_OBJ) \ smbd/process.o smbd/service.o smbd/error.o \ printing/printfsp.o lib/sysquotas.o lib/sysquotas_linux.o \ @@ -453,6 +464,13 @@ NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \ NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) +WREPL_OBJ1 = wrepld/server.o wrepld/process.o wrepld/parser.o wrepld/socket.o \ + wrepld/partners.o + +WREPL_OBJ = $(WREPL_OBJ1) $(PARAM_OBJ) \ + $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) \ + $(LIBSAMBA_OBJ) + SWAT_OBJ1 = web/cgi.o web/diagnose.o web/startstop.o web/statuspage.o \ web/swat.o web/neg_lang.o @@ -466,7 +484,8 @@ SMBSH_OBJ = smbwrapper/smbsh.o smbwrapper/shared.o \ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) \ $(DOSERR_OBJ) $(SECRETS_OBJ) -STATUS_OBJ = utils/status.o $(LOCKING_OBJ) $(PARAM_OBJ) \ +STATUS_OBJ = utils/status.o utils/status_profile.o \ + $(LOCKING_OBJ) $(PARAM_OBJ) \ $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \ $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(ERRORMAP_OBJ) $(RPC_PARSE_OBJ1) \ $(DOSERR_OBJ) @@ -496,7 +515,7 @@ SMBPASSWD_OBJ = utils/smbpasswd.o utils/passwd_util.o $(PASSCHANGE_OBJ) \ PDBEDIT_OBJ = utils/pdbedit.o utils/passwd_util.o $(PARAM_OBJ) $(PASSDB_OBJ) \ $(LIBSAMBA_OBJ) $(LIB_NONSMBD_OBJ) $(GROUPDB_OBJ) \ $(SECRETS_OBJ) $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) libsmb/asn1.o \ - $(RPC_PARSE_OBJ1) $(DOSERR_OBJ) + $(RPC_PARSE_OBJ1) $(DOSERR_OBJ) libsmb/errormap.o SMBGET_OBJ = utils/smbget.o $(POPT_LIB_OBJ) $(LIBSMBCLIENT_OBJ) @@ -506,7 +525,7 @@ RPCCLIENT_OBJ1 = rpcclient/rpcclient.o rpcclient/cmd_lsarpc.o \ rpcclient/cmd_dfs.o rpcclient/cmd_reg.o \ rpcclient/cmd_ds.o rpcclient/cmd_echo.o \ rpcclient/cmd_shutdown.o rpcclient/cmd_test.o \ - lib/display_sec.o + rpcclient/cmd_unixinfo.o lib/display_sec.o RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \ $(PARAM_OBJ) $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) \ @@ -542,7 +561,7 @@ CAC_OBJ = $(LIBSMBCLIENT_OBJ) \ libmsrpc/cac_lsarpc.o libmsrpc/cac_winreg.o libmsrpc/cac_samr.o \ libmsrpc/cac_svcctl.o -LIBSMBSHAREMODES_OBJ = libsmb/smb_share_modes.o tdb/tdb.o tdb/spinlock.o +LIBSMBSHAREMODES_OBJ = libsmb/smb_share_modes.o tdb/tdb.o # This shared library is intended for linking with unit test programs # to test Samba internals. It's called libbigballofmud.so to @@ -595,7 +614,7 @@ MOUNT_OBJ = client/smbmount.o \ MNT_OBJ = client/smbmnt.o lib/replace.o lib/timegm.o $(VERSION_OBJ) $(SNPRINTF_OBJ) @SOCKWRAP@ -UMOUNT_OBJ = client/smbumount.o @SOCKWRAP@ +UMOUNT_OBJ = client/smbumount.o @SOCKWRAP@ CIFS_MOUNT_OBJ = client/mount.cifs.o @@ -622,6 +641,11 @@ LOCKTEST_OBJ = torture/locktest.o $(PARAM_OBJ) $(LOCKING_OBJ) $(KRBCLIENT_OBJ) \ NSSTEST_OBJ = torture/nsstest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) +PDBTEST_OBJ = torture/pdbtest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ + $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ + $(SMBLDAP_OBJ) $(POPT_LIB_OBJ) + + VFSTEST_OBJ = torture/cmd_vfs.o torture/vfstest.o $(SMBD_OBJ_BASE) $(READLINE_OBJ) SMBICONV_OBJ = $(PARAM_OBJ) torture/smbiconv.o $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) $(LIBSAMBA_OBJ) @@ -650,6 +674,11 @@ EVTLOGADM_OBJ = $(EVTLOGADM_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(REGOBJS_OBJ) registry/reg_eventlog.o rpc_server/srv_eventlog_lib.o registry/reg_util.o \ registry/reg_db.o +SHARESEC_OBJ0 = utils/sharesec.o +SHARESEC_OBJ = $(SHARESEC_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(REGOBJS_OBJ) \ + $(ERRORMAP_OBJ) $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(DOSERR_OBJ) \ + $(POPT_LIB_OBJ) $(SECRETS_OBJ) + TALLOCTORT_OBJ = lib/talloctort.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ $(RPC_PARSE_OBJ1) $(DOSERR_OBJ) $(LIBSAMBA_OBJ) $(SECRETS_OBJ) @@ -668,7 +697,7 @@ DEBUG2HTML_OBJ = utils/debug2html.o utils/debugparse.o SMBFILTER_OBJ = utils/smbfilter.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(SECRETS_OBJ) \ $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) -PROTO_OBJ = $(SMBD_OBJ_MAIN) \ +PROTO_OBJ = $(SMBD_OBJ_MAIN) $(LIBNDR_OBJ) \ $(SMBD_OBJ_SRV) $(NMBD_OBJ1) $(SWAT_OBJ1) $(LIB_OBJ) $(LIBSMB_OBJ) \ $(SMBTORTURE_OBJ1) $(RPCCLIENT_OBJ1) \ $(LIBMSRPC_OBJ) @SMBWRAP_OBJS@ \ @@ -681,7 +710,7 @@ PROTO_OBJ = $(SMBD_OBJ_MAIN) \ $(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) $(RPC_LSA_DS_OBJ) \ $(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) $(RPC_SPOOLSS_OBJ) \ $(RPC_ECHO_OBJ) $(RPC_SVCCTL_OBJ) $(RPC_EVENTLOG_OBJ) $(SMBLDAP_OBJ) \ - $(IDMAP_OBJ) libsmb/spnego.o $(PASSCHANGE_OBJ) \ + $(IDMAP_OBJ) libsmb/spnego.o $(PASSCHANGE_OBJ) $(RPC_UNIXINFO_OBJ) \ $(RPC_NTSVCS_OBJ) utils/passwd_util.o WINBIND_WINS_NSS_OBJ = nsswitch/wins.o $(PARAM_OBJ) \ @@ -760,7 +789,8 @@ NTLM_AUTH_OBJ = ${NTLM_AUTH_OBJ1} $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \ libsmb/asn1.o libsmb/spnego.o libsmb/clikrb5.o libads/kerberos.o \ libads/kerberos_verify.o $(SECRETS_OBJ) $(SERVER_MUTEX_OBJ) \ libads/authdata.o $(RPC_PARSE_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ - $(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o $(LIBNMB_OBJ) + $(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o $(LIBNMB_OBJ) \ + libsmb/errormap.o ###################################################################### # now the rules... @@ -802,6 +832,8 @@ smbfilter : SHOWFLAGS bin/smbfilter@EXEEXT@ eventlogadm: SHOWFLAGS bin/eventlogadm@EXEEXT@ +sharesec: SHOWFLAGS bin/sharesec@EXEEXT@ + talloctort : SHOWFLAGS bin/talloctort@EXEEXT@ timelimit : SHOWFLAGS bin/timelimit@EXEEXT@ @@ -916,6 +948,10 @@ bin/nmbd@EXEEXT@: $(NMBD_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) +bin/wrepld@EXEEXT@: $(WREPL_OBJ) @BUILD_POPT@ bin/.dummy + @echo Linking $@ + @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(WREPL_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ + bin/swat@EXEEXT@: $(SWAT_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINT_LIBS) \ @@ -1035,6 +1071,10 @@ bin/eventlogadm@EXEEXT@: $(EVTLOGADM_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ +bin/sharesec@EXEEXT@: $(SHARESEC_OBJ) @BUILD_POPT@ bin/.dummy + @echo Linking $@ + @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SHARESEC_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ + bin/locktest@EXEEXT@: $(LOCKTEST_OBJ) bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) @@ -1043,6 +1083,10 @@ bin/nsstest@EXEEXT@: $(NSSTEST_OBJ) bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) +bin/pdbtest@EXEEXT@: $(PDBTEST_OBJ) bin/.dummy + @echo Linking $@ + @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(PDBTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@ + bin/vfstest@EXEEXT@: $(VFSTEST_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(ACL_LIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) @SMBD_LIBS@ @@ -1141,6 +1185,11 @@ bin/librpc_samr.@SHLIBEXT@: $(RPC_SAMR_OBJ) @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_SAMR_OBJ) -lc \ @SONAMEFLAG@`basename $@` +bin/librpc_unixinfo.@SHLIBEXT@: $(RPC_UNIXINFO_OBJ) + @echo "Linking $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_UNIXINFO_OBJ) -lc \ + @SONAMEFLAG@`basename $@` + bin/librpc_srvsvc.@SHLIBEXT@: $(RPC_SVC_OBJ) @echo "Linking $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_SVC_OBJ) -lc \ @@ -1293,6 +1342,9 @@ bin/macosxfs.@SHLIBEXT@: $(CHARSET_MACOSXFS_OBJ:.o=.@PICSUFFIX@) @$(SHLD) $(LDSHFLAGS) -o $@ $(CHARSET_MACOSXFS_OBJ:.o=.@PICSUFFIX@) \ -framework CoreFoundation @SONAMEFLAG@`basename $@` +# NOTE, there is no build rule for a dynamic default VFS module because +# this one MUST MUST MUST be built statically. + bin/audit.@SHLIBEXT@: $(VFS_AUDIT_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AUDIT_OBJ:.o=.@PICSUFFIX@) \ @@ -1358,6 +1410,20 @@ bin/catia.@SHLIBEXT@: $(VFS_CATIA_OBJ:.o=.@PICSUFFIX@) @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CATIA_OBJ:.o=.@PICSUFFIX@) \ @SONAMEFLAG@`basename $@` +bin/cacheprime.@SHLIBEXT@: $(VFS_CACHEPRIME_OBJ:.o=.@PICSUFFIX@) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CACHEPRIME_OBJ:.o=.@PICSUFFIX@) \ + @SONAMEFLAG@`basename $@` + +bin/prealloc.@SHLIBEXT@: $(VFS_PREALLOC_OBJ:.o=.@PICSUFFIX@) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_PREALLOC_OBJ:.o=.@PICSUFFIX@) \ + @SONAMEFLAG@`basename $@` + +bin/commit.@SHLIBEXT@: $(VFS_COMMIT_OBJ:.o=.@PICSUFFIX@) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_COMMIT_OBJ:.o=.@PICSUFFIX@) \ + @SONAMEFLAG@`basename $@` bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @@ -1605,13 +1671,13 @@ clean: delheaders python_clean # exist, not necessarily that they are up to date. Since they're # removed by "make clean" this will always be run when you do anything # afterwards. -proto_exists: include/proto.h include/build_env.h \ +proto_exists: include/proto.h include/wrepld_proto.h include/build_env.h \ nsswitch/winbindd_proto.h web/swat_proto.h \ client/client_proto.h utils/net_proto.h utils/ntlm_auth_proto.h smbd/build_options.c delheaders: @echo Removing prototype headers - @rm -f include/proto.h include/build_env.h \ + @rm -f include/proto.h include/build_env.h include/wrepld_proto.h \ nsswitch/winbindd_proto.h web/swat_proto.h \ client/client_proto.h utils/net_proto.h \ smbd/build_options.c utils/ntlm_auth_proto.h \ @@ -1630,6 +1696,12 @@ include/build_env.h: script/build_env.sh @$(SHELL) $(srcdir)/script/build_env.sh $(srcdir) $(builddir) $(CC) \ > $(builddir)/include/build_env.h +include/wrepld_proto.h: + @echo Building include/wrepld_proto.h + @cd $(srcdir) && $(SHELL) $(MKPROTO_SH) $(AWK) \ + -h _WREPLD_PROTO_H_ $(builddir)/include/wrepld_proto.h \ + $(WREPL_OBJ1) + nsswitch/winbindd_proto.h: @cd $(srcdir) && $(SHELL) $(MKPROTO_SH) $(AWK) \ -h _WINBINDD_PROTO_H_ $(builddir)/nsswitch/winbindd_proto.h \ @@ -1668,6 +1740,7 @@ headers: $(MAKE) smbd/build_options.c; \ $(MAKE) include/proto.h; \ $(MAKE) include/build_env.h; \ + $(MAKE) include/wrepld_proto.h; \ $(MAKE) nsswitch/winbindd_proto.h; \ $(MAKE) web/swat_proto.h; \ $(MAKE) client/client_proto.h; \ diff --git a/source/aclocal.m4 b/source/aclocal.m4 index af7ed7b4068..1f2120c68b3 100644 --- a/source/aclocal.m4 +++ b/source/aclocal.m4 @@ -981,3 +981,97 @@ clockid_t clk = $1; AC_MSG_RESULT(no) ]) ]) + +dnl SMB_IF_RTSIGNAL_BUG([actions if true], +dnl [actions if false], +dnl [actions if cross compiling]) +dnl Test whether we can call sigaction with RT_SIGNAL_NOTIFY and +dnl RT_SIGNAL_LEASE (also RT_SIGNAL_AIO for good measure, though +dnl I don't believe that triggers any bug. +dnl +dnl See the samba-technical thread titled "Failed to setup +dnl RT_SIGNAL_NOTIFY handler" for details on the bug in question. +AC_DEFUN([SMB_IF_RTSIGNAL_BUG], +[ + rt_signal_notify_works=yes + rt_signal_lease_works=yes + rt_signal_aio_works=yes + + AC_MSG_CHECKING(if sigaction works with realtime signals) + AC_TRY_RUN( + [ +#include <sys/types.h> +#include <fcntl.h> +#include <signal.h> + +/* from smbd/notify_kernel.c */ +#ifndef RT_SIGNAL_NOTIFY +#define RT_SIGNAL_NOTIFY (SIGRTMIN+2) +#endif + +/* from smbd/aio.c */ +#ifndef RT_SIGNAL_AIO +#define RT_SIGNAL_AIO (SIGRTMIN+3) +#endif + +/* from smbd/oplock_linux.c */ +#ifndef RT_SIGNAL_LEASE +#define RT_SIGNAL_LEASE (SIGRTMIN+1) +#endif + +static void signal_handler(int sig, siginfo_t *info, void *unused) +{ + int do_nothing = 0; +} + +int main(void) +{ + int result = 0; + struct sigaction act = {0}; + + act.sa_sigaction = signal_handler; + act.sa_flags = SA_SIGINFO; + sigemptyset( &act.sa_mask ); + + if (sigaction(RT_SIGNAL_LEASE, &act, 0) != 0) { + /* Failed to setup RT_SIGNAL_LEASE handler */ + result += 1; + } + + if (sigaction(RT_SIGNAL_NOTIFY, &act, 0) != 0) { + /* Failed to setup RT_SIGNAL_NOTIFY handler */ + result += 10; + } + + if (sigaction(RT_SIGNAL_AIO, &act, 0) != 0) { + /* Failed to setup RT_SIGNAL_AIO handler */ + result += 100; + } + + /* zero on success */ + return result; +} + ], + [ + AC_MSG_RESULT(yes) + $2 + ], + [ + AC_MSG_RESULT(no) + case "$ac_status" in + 1|11|101|111) rt_signal_lease_ok=no ;; + esac + case "$ac_status" in + 10|11|110|111) rt_signal_notify_ok=no ;; + esac + case "$ac_status" in + 100|110|101|111) rt_signal_aio_ok=no ;; + esac + $2 + ], + [ + AC_MSG_RESULT(cross) + $3 + ]) +]) + diff --git a/source/auth/auth_domain.c b/source/auth/auth_domain.c index bedd318c3c3..8ad6329da98 100644 --- a/source/auth/auth_domain.c +++ b/source/auth/auth_domain.c @@ -50,6 +50,8 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, NTSTATUS result; struct rpc_pipe_client *netlogon_pipe = NULL; + *cli = NULL; + *pipe_ret = NULL; /* TODO: Send a SAMLOGON request to determine whether this is a valid @@ -81,6 +83,11 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, result = NT_STATUS_NO_LOGON_SERVERS; } + if (*cli) { + cli_shutdown(*cli); + *cli = NULL; + } + release_server_mutex(); return result; } @@ -111,6 +118,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); cli_shutdown(*cli); + *cli = NULL; release_server_mutex(); return result; } @@ -126,6 +134,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); "trust account password for domain '%s'\n", domain)); cli_shutdown(*cli); + *cli = NULL; release_server_mutex(); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } @@ -141,6 +150,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); if (!NT_STATUS_IS_OK(result)) { cli_shutdown(*cli); + *cli = NULL; release_server_mutex(); return result; } @@ -150,6 +160,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli))); cli_shutdown(*cli); + *cli = NULL; release_server_mutex(); return NT_STATUS_NO_LOGON_SERVERS; } diff --git a/source/auth/auth_server.c b/source/auth/auth_server.c index 7bec1b4128d..6e4dba0be2d 100644 --- a/source/auth/auth_server.c +++ b/source/auth/auth_server.c @@ -39,7 +39,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx) char *pserver; BOOL connected_ok = False; - if (!(cli = cli_initialise(cli))) + if (!(cli = cli_initialise())) return NULL; /* security = server just can't function with spnego */ @@ -49,7 +49,8 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx) p = pserver; while(next_token( &p, desthost, LIST_SEP, sizeof(desthost))) { - standard_sub_basic(current_user_info.smb_name, desthost, sizeof(desthost)); + standard_sub_basic(current_user_info.smb_name, current_user_info.domain, + desthost, sizeof(desthost)); strupper_m(desthost); if(!resolve_name( desthost, &dest_ip, 0x20)) { @@ -85,7 +86,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx) return NULL; } - if (!attempt_netbios_session_request(cli, global_myname(), + if (!attempt_netbios_session_request(&cli, global_myname(), desthost, &dest_ip)) { release_server_mutex(); DEBUG(1,("password server fails session request\n")); @@ -129,7 +130,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx) } release_server_mutex(); - + DEBUG(3,("password server OK\n")); return cli; diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c index 493d7393d07..823bf8c3228 100644 --- a/source/auth/auth_util.c +++ b/source/auth/auth_util.c @@ -611,12 +611,17 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, * Add alias SIDs from memberships within the partially created token SID list */ -static NTSTATUS add_aliases(TALLOC_CTX *tmp_ctx, const DOM_SID *domain_sid, +static NTSTATUS add_aliases(const DOM_SID *domain_sid, struct nt_user_token *token) { uint32 *aliases; size_t i, num_aliases; NTSTATUS status; + TALLOC_CTX *tmp_ctx; + + if (!(tmp_ctx = talloc_init("add_aliases"))) { + return NT_STATUS_NO_MEMORY; + } aliases = NULL; num_aliases = 0; @@ -629,6 +634,7 @@ static NTSTATUS add_aliases(TALLOC_CTX *tmp_ctx, const DOM_SID *domain_sid, if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("pdb_enum_alias_memberships failed: %s\n", nt_errstr(status))); + TALLOC_FREE(tmp_ctx); return status; } @@ -640,10 +646,12 @@ static NTSTATUS add_aliases(TALLOC_CTX *tmp_ctx, const DOM_SID *domain_sid, &token->num_sids); if (token->user_sids == NULL) { DEBUG(0, ("add_sid_to_array failed\n")); + TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } } + TALLOC_FREE(tmp_ctx); return NT_STATUS_OK; } @@ -686,7 +694,7 @@ static NTSTATUS log_nt_token(TALLOC_CTX *tmp_ctx, NT_USER_TOKEN *token) /******************************************************************* *******************************************************************/ -static NTSTATUS add_builtin_administrators( TALLOC_CTX *ctx, struct nt_user_token *token ) +static NTSTATUS add_builtin_administrators( struct nt_user_token *token ) { DOM_SID domadm; @@ -808,22 +816,14 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx, int num_groupsids, const DOM_SID *groupsids) { - TALLOC_CTX *tmp_ctx; struct nt_user_token *result = NULL; int i; NTSTATUS status; gid_t gid; - tmp_ctx = talloc_new(mem_ctx); - if (tmp_ctx == NULL) { - DEBUG(0, ("talloc_new failed\n")); - return NULL; - } - - result = TALLOC_ZERO_P(tmp_ctx, NT_USER_TOKEN); - if (result == NULL) { + if (!(result = TALLOC_ZERO_P(mem_ctx, NT_USER_TOKEN))) { DEBUG(0, ("talloc failed\n")); - goto done; + return NULL; } /* Add the user and primary group sid */ @@ -875,7 +875,7 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx, unbecome_root(); } else { - status = add_builtin_administrators( tmp_ctx, result ); + status = add_builtin_administrators( result ); if ( !NT_STATUS_IS_OK(status) ) { /* just log a complaint but do not fail */ DEBUG(3,("create_local_nt_token: failed to check for local Administrators" @@ -896,7 +896,7 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx, become_root(); status = create_builtin_users( ); if ( !NT_STATUS_IS_OK(status) ) { - DEBUG(0,("create_local_nt_token: Failed to create BUILTIN\\Administrators group!\n")); + DEBUG(0,("create_local_nt_token: Failed to create BUILTIN\\Users group!\n")); /* don't fail, just log the message */ } unbecome_root(); @@ -909,31 +909,26 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx, /* Now add the aliases. First the one from our local SAM */ - status = add_aliases(tmp_ctx, get_global_sam_sid(), result); + status = add_aliases(get_global_sam_sid(), result); if (!NT_STATUS_IS_OK(status)) { - result = NULL; - goto done; + TALLOC_FREE(result); + return NULL; } /* Finally the builtin ones */ - status = add_aliases(tmp_ctx, &global_sid_Builtin, result); + status = add_aliases(&global_sid_Builtin, result); if (!NT_STATUS_IS_OK(status)) { - result = NULL; - goto done; + TALLOC_FREE(result); + return NULL; } } get_privileges_for_sids(&result->privileges, result->user_sids, result->num_sids); - - talloc_steal(mem_ctx, result); - - done: - TALLOC_FREE(tmp_ctx); return result; } @@ -1443,6 +1438,65 @@ NTSTATUS make_server_info_guest(auth_serversupplied_info **server_info) return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY; } +BOOL copy_current_user(struct current_user *dst, struct current_user *src) +{ + gid_t *groups; + NT_USER_TOKEN *nt_token; + + groups = memdup(src->ut.groups, sizeof(gid_t) * src->ut.ngroups); + if ((src->ut.ngroups != 0) && (groups == NULL)) { + return False; + } + + nt_token = dup_nt_token(NULL, src->nt_user_token); + if (nt_token == NULL) { + SAFE_FREE(groups); + return False; + } + + dst->conn = src->conn; + dst->vuid = src->vuid; + dst->ut.uid = src->ut.uid; + dst->ut.gid = src->ut.gid; + dst->ut.ngroups = src->ut.ngroups; + dst->ut.groups = groups; + dst->nt_user_token = nt_token; + return True; +} + +BOOL set_current_user_guest(struct current_user *dst) +{ + gid_t *groups; + NT_USER_TOKEN *nt_token; + + groups = memdup(guest_info->groups, + sizeof(gid_t) * guest_info->n_groups); + if (groups == NULL) { + return False; + } + + nt_token = dup_nt_token(NULL, guest_info->ptok); + if (nt_token == NULL) { + SAFE_FREE(groups); + return False; + } + + TALLOC_FREE(dst->nt_user_token); + SAFE_FREE(dst->ut.groups); + + /* dst->conn is never really dereferenced, it's only tested for + * equality in uid.c */ + dst->conn = NULL; + + dst->vuid = UID_FIELD_INVALID; + dst->ut.uid = guest_info->uid; + dst->ut.gid = guest_info->gid; + dst->ut.ngroups = guest_info->n_groups; + dst->ut.groups = groups; + dst->nt_user_token = nt_token; + return True; +} + /*************************************************************************** Purely internal function for make_server_info_info3 Fill the sam account from getpwnam diff --git a/source/client/client.c b/source/client/client.c index 3c2d7afe2d6..99fffa71232 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -3352,7 +3352,7 @@ static int do_message_op(void) msg_port = port ? port : 139; - if (!(cli=cli_initialise(NULL)) || (cli_set_port(cli, msg_port) != msg_port) || + if (!(cli=cli_initialise()) || (cli_set_port(cli, msg_port) != msg_port) || !cli_connect(cli, server_name, &ip)) { d_printf("Connection to %s failed\n", desthost); return 1; diff --git a/source/client/clitar.c b/source/client/clitar.c index 14c28acfc5a..f0d0ac595c2 100644 --- a/source/client/clitar.c +++ b/source/client/clitar.c @@ -201,7 +201,11 @@ static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t m oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.uid); oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.gid); oct_it((SMB_BIG_UINT) size, 13, hb.dbuf.size); +#ifdef HAVE_LONGLONG if (size > (SMB_BIG_UINT)077777777777LL) { +#else + if (size > (SMB_BIG_UINT)077777777777) { +#endif /* This is a non-POSIX compatible extention to store files greater than 8GB. */ diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c index ac98b992bb2..ab1f203412f 100755 --- a/source/client/mount.cifs.c +++ b/source/client/mount.cifs.c @@ -935,10 +935,20 @@ int main(int argc, char ** argv) ++nomtab; break; case 'b': +#ifdef MS_BIND flags |= MS_BIND; +#else + fprintf(stderr, + "option 'b' (MS_BIND) not supported\n"); +#endif break; case 'm': +#ifdef MS_MOVE flags |= MS_MOVE; +#else + fprintf(stderr, + "option 'm' (MS_MOVE) not supported\n"); +#endif break; case 'o': orgoptions = strdup(optarg); diff --git a/source/client/smbctool.c b/source/client/smbctool.c index fd385ee6817..b7042f99cb2 100644 --- a/source/client/smbctool.c +++ b/source/client/smbctool.c @@ -3494,7 +3494,7 @@ static int do_message_op(void) msg_port = port ? port : 139; - if (!(cli=cli_initialise(NULL)) || (cli_set_port(cli, msg_port) != msg_port) || + if (!(cli=cli_initialise()) || (cli_set_port(cli, msg_port) != msg_port) || !cli_connect(cli, server_name, &ip)) { d_printf("Connection to %s failed\n", desthost); return 1; diff --git a/source/client/smbmount.c b/source/client/smbmount.c index 7a3ccb7630d..f1cd81198f0 100644 --- a/source/client/smbmount.c +++ b/source/client/smbmount.c @@ -149,7 +149,7 @@ static struct cli_state *do_connection(char *the_service) if (have_ip) ip = dest_ip; /* have to open a new connection */ - if (!(c=cli_initialise(NULL)) || (cli_set_port(c, smb_port) != smb_port) || + if (!(c=cli_initialise()) || (cli_set_port(c, smb_port) != smb_port) || !cli_connect(c, server_n, &ip)) { DEBUG(0,("%d: Connection to %s failed\n", sys_getpid(), server_n)); if (c) { diff --git a/source/configure.in b/source/configure.in index 884c2cea6ab..5359ff8bf41 100644 --- a/source/configure.in +++ b/source/configure.in @@ -579,7 +579,7 @@ DYNEXP= dnl Add modules that have to be built by default here dnl These have to be built static: -default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_svcctl rpc_ntsvcs rpc_net rpc_netdfs rpc_srv rpc_spoolss rpc_eventlog auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin" +default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_svcctl rpc_ntsvcs rpc_net rpc_netdfs rpc_srv rpc_spoolss rpc_eventlog rpc_unixinfo auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin vfs_default" dnl These are preferably build shared, and static if dlopen() is not available default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy charset_CP850 charset_CP437 auth_script" @@ -864,6 +864,7 @@ AC_CHECK_HEADERS(sys/termio.h sys/statfs.h sys/dustat.h sys/statvfs.h stdarg.h s AC_CHECK_HEADERS(sys/sysmacros.h security/_pam_macros.h dlfcn.h) AC_CHECK_HEADERS(sys/syslog.h syslog.h) AC_CHECK_HEADERS(langinfo.h locale.h) +AC_CHECK_HEADERS(xfs/libxfs.h) AC_CHECK_HEADERS(rpcsvc/yp_prot.h,,,[[ #if HAVE_RPC_RPC_H @@ -969,6 +970,8 @@ AC_CHECK_TYPE(loff_t,off_t) AC_CHECK_TYPE(offset_t,loff_t) AC_CHECK_TYPE(ssize_t, int) AC_CHECK_TYPE(wchar_t, unsigned short) +AC_CHECK_TYPE(comparison_fn_t, +[AC_DEFINE(HAVE_COMPARISON_FN_T, 1,[Whether or not we have comparison_fn_t])]) ############################################ # for cups support we need libcups, and a handful of header files @@ -1263,7 +1266,8 @@ if test x"$ac_cv_func_execl" = x"no"; then EXTRA_BIN_PROGS="$EXTRA_BIN_PROGS bin/smbrun\$(EXEEXT)" fi -AC_CHECK_FUNCS(dlopen dlclose dlsym dlerror waitpid getcwd strdup strndup strnlen strtoul strerror chown fchown chmod fchmod chroot link mknod mknod64) +AC_CHECK_FUNCS(dlopen dlclose dlsym dlerror waitpid getcwd strdup strndup strnlen strerror chown fchown chmod fchmod chroot link mknod mknod64) +AC_CHECK_FUNCS(strtol strtoll strtoul strtoull) AC_CHECK_FUNCS(fstat strchr utime utimes getrlimit fsync memset strlcpy strlcat setpgid) AC_CHECK_FUNCS(memmove vsnprintf snprintf asprintf vasprintf setsid glob strpbrk pipe crypt16 getauthuid) AC_CHECK_FUNCS(strftime sigprocmask sigblock sigaction sigset innetgr setnetgrent getnetgrent endnetgrent) @@ -2072,15 +2076,11 @@ if test x"$samba_cv_WITH_PROFILE" = x"yes"; then AC_LIBTESTFUNC(rt, clock_gettime, [ - SMB_IS_LIBPTHREAD_LINKED( - [ SMB_REMOVELIB(rt) ], - [ - AC_DEFINE(HAVE_CLOCK_GETTIME, 1, - [Whether clock_gettime is available]) - SMB_CHECK_CLOCK_ID(CLOCK_MONOTONIC) - SMB_CHECK_CLOCK_ID(CLOCK_PROCESS_CPUTIME_ID) - SMB_CHECK_CLOCK_ID(CLOCK_REALTIME) - ]) + AC_DEFINE(HAVE_CLOCK_GETTIME, 1, + [Whether clock_gettime is available]) + SMB_CHECK_CLOCK_ID(CLOCK_MONOTONIC) + SMB_CHECK_CLOCK_ID(CLOCK_PROCESS_CPUTIME_ID) + SMB_CHECK_CLOCK_ID(CLOCK_REALTIME) ]) fi @@ -3169,6 +3169,18 @@ if test x"$with_ldap_support" != x"no"; then with_ldap_support=no fi + + ################################################################## + # HP/UX does not have ber_tag_t, disable LDAP there + AC_CHECK_TYPE(ber_tag_t,,,[#include <lber.h>]) + if test x"$ac_cv_type_ber_tag_t" != x"yes"; then + if test x"$with_ldap_support" = x"yes"; then + AC_MSG_ERROR(ber_tag_t is needed for LDAP support) + else + AC_MSG_WARN(ber_tag_t is needed for LDAP support) + fi + with_ldap_support=no + fi fi if test x"$with_ldap_support" != x"no"; then @@ -4569,6 +4581,16 @@ if test $space = no; then fi fi +# smbd/statvfs.c assumes that statvfs.f_fsid is an integer. +# This is not the case on ancient Linux systems. + +AC_CACHE_CHECK([that statvfs.f_fsid is an integer],samba_cv_fsid_int, [ + AC_TRY_COMPILE([#include <sys/statvfs.h>],[struct statvfs buf; buf.f_fsid = 0], + samba_cv_fsid_int=yes,samba_cv_fsid_int=no)]) +if test x"$samba_cv_fsid_int" = x"yes"; then + AC_DEFINE(HAVE_FSID_INT, 1, [Whether statvfs.f_fsid is an integer]) +fi + if test $space = no; then # DEC Alpha running OSF/1 AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)]) @@ -5545,6 +5567,7 @@ SMB_MODULE(rpc_spoolss, \$(RPC_SPOOLSS_OBJ), "bin/librpc_spoolss.$SHLIBEXT", RPC SMB_MODULE(rpc_eventlog, \$(RPC_EVENTLOG_OBJ), "bin/librpc_eventlog.$SHLIBEXT", RPC) SMB_MODULE(rpc_samr, \$(RPC_SAMR_OBJ), "bin/librpc_samr.$SHLIBEXT", RPC) SMB_MODULE(rpc_echo, \$(RPC_ECHO_OBJ), "bin/librpc_echo.$SHLIBEXT", RPC) +SMB_MODULE(rpc_unixinfo, \$(RPC_UNIXINFO_OBJ), "bin/librpc_unixinfo.$SHLIBEXT", RPC) SMB_SUBSYSTEM(RPC,smbd/server.o) SMB_MODULE(idmap_ldap, sam/idmap_ldap.o, "bin/ldap.$SHLIBEXT", IDMAP) @@ -5568,6 +5591,7 @@ SMB_MODULE(auth_builtin, \$(AUTH_BUILTIN_OBJ), "bin/builtin.$SHLIBEXT", AUTH) SMB_MODULE(auth_script, \$(AUTH_SCRIPT_OBJ), "bin/script.$SHLIBEXT", AUTH) SMB_SUBSYSTEM(AUTH,auth/auth.o) +SMB_MODULE(vfs_default, \$(VFS_DEFAULT_OBJ), "bin/default.$SHLIBEXT", VFS) SMB_MODULE(vfs_recycle, \$(VFS_RECYCLE_OBJ), "bin/recycle.$SHLIBEXT", VFS) SMB_MODULE(vfs_audit, \$(VFS_AUDIT_OBJ), "bin/audit.$SHLIBEXT", VFS) SMB_MODULE(vfs_extd_audit, \$(VFS_EXTD_AUDIT_OBJ), "bin/extd_audit.$SHLIBEXT", VFS) @@ -5581,6 +5605,10 @@ SMB_MODULE(vfs_expand_msdfs, \$(VFS_EXPAND_MSDFS_OBJ), "bin/expand_msdfs.$SHLIBE SMB_MODULE(vfs_shadow_copy, \$(VFS_SHADOW_COPY_OBJ), "bin/shadow_copy.$SHLIBEXT", VFS) SMB_MODULE(vfs_afsacl, \$(VFS_AFSACL_OBJ), "bin/afsacl.$SHLIBEXT", VFS) SMB_MODULE(vfs_catia, \$(VFS_CATIA_OBJ), "bin/catia.$SHLIBEXT", VFS) +SMB_MODULE(vfs_cacheprime, \$(VFS_CACHEPRIME_OBJ), "bin/cacheprime.$SHLIBEXT", VFS) +SMB_MODULE(vfs_prealloc, \$(VFS_PREALLOC_OBJ), "bin/prealloc.$SHLIBEXT", VFS) +SMB_MODULE(vfs_commit, \$(VFS_COMMIT_OBJ), "bin/commit.$SHLIBEXT", VFS) + SMB_SUBSYSTEM(VFS,smbd/vfs.o) AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules]) @@ -5593,6 +5621,89 @@ if test "${ac_cv_prog_CC}" = "insure"; then fi ################################################# +# If run from the build farm, enable NASTY hacks +################################################# +AC_MSG_CHECKING(whether to enable build farm hacks) +if test x"$RUN_FROM_BUILD_FARM" = x"yes"; then + AC_MSG_RESULT(yes) + AC_DEFINE(ENABLE_BUILD_FARM_HACKS, 1, [Defined if running in the build farm]) +else + AC_MSG_RESULT(no) +fi + +################################################# +# check for bad librt/libpthread interactions + +if test x"$samba_cv_HAVE_KERNEL_OPLOCKS_LINUX" = x"yes" -o \ + x"$samba_cv_HAVE_KERNEL_CHANGE_NOTIFY" = x"yes" -o \ + x"$samba_cv_HAVE_AIO64" = x"yes" -o \ + x"$samba_cv_HAVE_AIO" = x"yes" ; then + +SMB_IF_RTSIGNAL_BUG( + [ + # Have RT_SIGNAL bug, need to check whether the problem will + # affect anything we have configured. + + rt_do_error=no + if test x"$samba_cv_HAVE_KERNEL_OPLOCKS_LINUX" = x"yes"; then + if test x"$rt_signal_lease_ok" = x"no" ; then + rt_do_error=yes + fi + fi + + if test x"$samba_cv_HAVE_KERNEL_CHANGE_NOTIFY" = x"yes"; then + if test x"$rt_signal_notify_ok" = x"no" ; then + rt_do_error=yes + fi + fi + + if test x"$samba_cv_HAVE_AIO64" = x"yes" -o \ + x"$samba_cv_HAVE_AIO" = x"yes" ; then + if test x"$rt_signal_aio_ok" = x"no" ; then + rt_do_error=yes + fi + fi + + if test x"$rt_do_error" = x"yes" ; then + SMB_IS_LIBPTHREAD_LINKED( + [ + cat<<MSG + +*** On this platforms, linking Samba against pthreads causes problems +*** with the oplock and change notification mechanisms. You may be +*** using pthreads as a side-effect of using the --with-aio-support +*** or --with-profiling-data options. Please remove these and try again. + +MSG + ], + [ + cat<<MSG + +*** On this platform, the oplock and change notification mechanisms do not +*** appear to work. Please report this problem to samba-technical@samba.org +*** and attach the config.log file from this directory. + +MSG + ]) + AC_MSG_ERROR(unable to use realtime signals on this platform) + fi + ], + [ + # no RT_SIGNAL bug, we are golden + SMB_IS_LIBPTHREAD_LINKED( + [ + AC_MSG_WARN(using libpthreads - this may degrade performance) + ]) + + ], + [ + # cross compiling, I hope you know what you are doing + true + ]) + +fi + +################################################# # Display summary of libraries detected AC_MSG_RESULT([Using libraries:]) diff --git a/source/include/client.h b/source/include/client.h index c6d7b162fcd..d11d198e1a5 100644 --- a/source/include/client.h +++ b/source/include/client.h @@ -171,10 +171,6 @@ struct cli_state { BOOL force_dos_errors; BOOL case_sensitive; /* False by default. */ - - /* was this structure allocated by cli_initialise? If so, then - free in cli_shutdown() */ - BOOL allocated; }; #define CLI_FULL_CONNECTION_DONT_SPNEGO 0x0001 diff --git a/source/include/idmap.h b/source/include/idmap.h index 474982f2926..ee248ef26f2 100644 --- a/source/include/idmap.h +++ b/source/include/idmap.h @@ -24,32 +24,32 @@ Boston, MA 02111-1307, USA. */ -/* idmap version determines auto-conversion */ -#define IDMAP_VERSION 2 +/* idmap version determines auto-conversion - this is the database + structure version specifier. */ -#define SMB_IDMAP_INTERFACE_VERSION 2 +#define IDMAP_VERSION 2 +/* The interface version specifier. + Updated to 3 for enum types by JRA. */ -#define ID_EMPTY 0x00 -#define ID_USERID 0x01 -#define ID_GROUPID 0x02 -#define ID_OTHER 0x04 +#define SMB_IDMAP_INTERFACE_VERSION 3 -#define ID_TYPEMASK 0x0f +enum idmap_type { ID_USERID, ID_GROUPID }; -#define ID_QUERY_ONLY 0x10 -#define ID_CACHE_ONLY 0x20 +#define IDMAP_FLAG_NONE 0x0 +#define IDMAP_FLAG_QUERY_ONLY 0x1 /* Don't ever allocate, just query. */ +#define IDMAP_FLAG_CACHE_ONLY 0x2 /* Only look in our local cache, not remote. */ /* Filled out by IDMAP backends */ struct idmap_methods { /* Called when backend is first loaded */ - NTSTATUS (*init)( char *params ); + NTSTATUS (*init)( const char *params ); - NTSTATUS (*allocate_id)(unid_t *id, int id_type); - NTSTATUS (*get_sid_from_id)(DOM_SID *sid, unid_t id, int id_type); - NTSTATUS (*get_id_from_sid)(unid_t *id, int *id_type, const DOM_SID *sid); - NTSTATUS (*set_mapping)(const DOM_SID *sid, unid_t id, int id_type); + NTSTATUS (*allocate_id)(unid_t *id, enum idmap_type id_type); + NTSTATUS (*get_sid_from_id)(DOM_SID *sid, unid_t id, enum idmap_type id_type, int flags); + NTSTATUS (*get_id_from_sid)(unid_t *id, enum idmap_type *id_type, const DOM_SID *sid, int flags); + NTSTATUS (*set_mapping)(const DOM_SID *sid, unid_t id, enum idmap_type id_type); /* Called when backend is unloaded */ NTSTATUS (*close_fn)(void); diff --git a/source/include/includes.h b/source/include/includes.h index 59e8e5cd0fb..ab2f6a96410 100644 --- a/source/include/includes.h +++ b/source/include/includes.h @@ -101,6 +101,10 @@ #include <stdint.h> #endif +#if HAVE_INTTYPES_H +#include <inttypes.h> +#endif + #ifdef TIME_WITH_SYS_TIME #include <sys/time.h> #include <time.h> @@ -873,6 +877,11 @@ struct timespec { #define MAX(a,b) ((a)>(b)?(a):(b)) #endif +#ifndef _BOOL +typedef int BOOL; +#define _BOOL /* So we don't typedef BOOL again in vfs.h */ +#endif + #ifndef HAVE_STRERROR extern char *sys_errlist[]; #define strerror(i) sys_errlist[i] @@ -905,8 +914,8 @@ extern int errno; #include "intl.h" #include "dlinklist.h" #include "tdb/tdb.h" -#include "tdb/spinlock.h" #include "tdb/tdbutil.h" +#include "tdb/tdbback.h" #include "talloc.h" /* And a little extension. Abort on type mismatch */ @@ -961,6 +970,7 @@ extern int errno; #include "rpc_ds.h" #include "rpc_echo.h" #include "rpc_shutdown.h" +#include "rpc_unixinfo.h" #include "rpc_perfcount.h" #include "rpc_perfcount_defs.h" #include "nt_printing.h" @@ -981,6 +991,8 @@ extern int errno; #include "rpc_client.h" #include "event.h" +#include "libndr/libndr.h" + /* * Type for wide character dirent structure. * Only d_name is defined by POSIX. @@ -1054,6 +1066,10 @@ enum flush_reason_enum { /* NUM_FLUSH_REASONS must remain the last value in the enumeration. */ NUM_FLUSH_REASONS}; +#ifndef HAVE_COMPARISON_FN_T +typedef int (*comparison_fn_t)(const void *, const void *); +#endif + /***** automatically generated prototypes *****/ #ifndef NO_PROTO_H #include "proto.h" diff --git a/source/include/libsmb_internal.h b/source/include/libsmb_internal.h index 5aca12554f3..42bf2373c1b 100644 --- a/source/include/libsmb_internal.h +++ b/source/include/libsmb_internal.h @@ -10,7 +10,7 @@ struct _SMBCSRV { - struct cli_state cli; + struct cli_state *cli; dev_t dev; BOOL no_pathinfo; BOOL no_pathinfo2; diff --git a/source/include/locking.h b/source/include/locking.h new file mode 100644 index 00000000000..983d59a853f --- /dev/null +++ b/source/include/locking.h @@ -0,0 +1,88 @@ +/* + Unix SMB/CIFS implementation. + SMB parameters and setup, plus a whole lot more. + + Copyright (C) Jeremy Allison 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _LOCKING_H +#define _LOCKING_H + +/* passed to br lock code - the UNLOCK_LOCK should never be stored into the tdb + and is used in calculating POSIX unlock ranges only. */ + +enum brl_type {READ_LOCK, WRITE_LOCK, PENDING_LOCK, UNLOCK_LOCK}; +enum brl_flavour {WINDOWS_LOCK = 0, POSIX_LOCK = 1}; + +/* This contains elements that differentiate locks. The smbpid is a + client supplied pid, and is essentially the locking context for + this client */ + +struct lock_context { + uint32 smbpid; + uint16 tid; + struct process_id pid; +}; + +/* The key used in the brlock database. */ + +struct lock_key { + SMB_DEV_T device; + SMB_INO_T inode; +}; + +struct byte_range_lock { + files_struct *fsp; + unsigned int num_locks; + BOOL modified; + struct lock_key key; + void *lock_data; +}; + +#define BRLOCK_FN_CAST() \ + void (*)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \ + enum brl_type lock_type, \ + enum brl_flavour lock_flav, \ + br_off start, br_off size) + +#define BRLOCK_FN(fn) \ + void (*fn)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \ + enum brl_type lock_type, \ + enum brl_flavour lock_flav, \ + br_off start, br_off size) + +#define LOCKING_FN_CAST() \ + void (*)(struct share_mode_entry *, const char *, const char *) + +#define LOCKING_FN(fn) \ + void (*fn)(struct share_mode_entry *, const char *, const char *) + +/* Internal structure in brlock.tdb. + The data in brlock records is an unsorted linear array of these + records. It is unnecessary to store the count as tdb provides the + size of the record */ + +struct lock_struct { + struct lock_context context; + br_off start; + br_off size; + uint16 fnum; + enum brl_type lock_type; + enum brl_flavour lock_flav; +}; + +#endif /* _LOCKING_H_ */ diff --git a/source/include/mangle.h b/source/include/mangle.h index 2bdef4ad646..3d19ef9ed4f 100644 --- a/source/include/mangle.h +++ b/source/include/mangle.h @@ -6,9 +6,13 @@ struct mangle_fns { void (*reset)(void); - BOOL (*is_mangled)(const char *s, int snum); - BOOL (*is_8_3)(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum); - BOOL (*check_cache)(char *s, size_t maxlen, int snum); - void (*name_map)(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum); + BOOL (*is_mangled)(const char *s, const struct share_params *p); + BOOL (*is_8_3)(const char *fname, BOOL check_case, BOOL allow_wildcards, + const struct share_params *p); + BOOL (*check_cache)(char *s, size_t maxlen, + const struct share_params *p); + void (*name_map)(char *OutName, BOOL need83, BOOL cache83, + int default_case, + const struct share_params *p); }; #endif /* _MANGLE_H_ */ diff --git a/source/include/nt_status.h b/source/include/nt_status.h index 14c83eba4b3..c48beafb6e7 100644 --- a/source/include/nt_status.h +++ b/source/include/nt_status.h @@ -56,7 +56,6 @@ typedef uint32 WERROR; #define NT_STATUS_IS_OK(x) (NT_STATUS_V(x) == 0) #define NT_STATUS_IS_ERR(x) ((NT_STATUS_V(x) & 0xc0000000) == 0xc0000000) -#define NT_STATUS_IS_INVALID(x) (NT_STATUS_V(x) == 0xFFFFFFFF) #define NT_STATUS_EQUAL(x,y) (NT_STATUS_V(x) == NT_STATUS_V(y)) #define W_ERROR_IS_OK(x) (W_ERROR_V(x) == 0) #define W_ERROR_EQUAL(x,y) (W_ERROR_V(x) == W_ERROR_V(y)) @@ -67,4 +66,12 @@ typedef uint32 WERROR; }\ } while (0) +/* this defines special NTSTATUS codes to represent DOS errors. I + have chosen this macro to produce status codes in the invalid + NTSTATUS range */ +#define NT_STATUS_DOS(class, code) NT_STATUS(0xF1000000 | ((class)<<16) | code) +#define NT_STATUS_IS_DOS(status) ((NT_STATUS_V(status) & 0xFF000000) == 0xF1000000) +#define NT_STATUS_DOS_CLASS(status) ((NT_STATUS_V(status) >> 16) & 0xFF) +#define NT_STATUS_DOS_CODE(status) (NT_STATUS_V(status) & 0xFFFF) + #endif diff --git a/source/include/ntdomain.h b/source/include/ntdomain.h index c27ec3675b4..0114df0e2d0 100644 --- a/source/include/ntdomain.h +++ b/source/include/ntdomain.h @@ -234,17 +234,9 @@ typedef struct pipes_struct { struct dcinfo *dc; /* Keeps the creds data from netlogon. */ /* - * Windows user info. - */ - fstring user_name; - fstring domain; - fstring wks; - - /* - * Unix user name and credentials used when a pipe is authenticated. + * Credentials used for the pipe operations */ - fstring pipe_user_name; struct current_user pipe_user; DATA_BLOB session_key; diff --git a/source/include/nterr.h b/source/include/nterr.h index 417719625e7..6cf5a756d29 100644 --- a/source/include/nterr.h +++ b/source/include/nterr.h @@ -37,9 +37,6 @@ #define STATUS_NOTIFY_ENUM_DIR NT_STATUS(0x010c) #define ERROR_INVALID_DATATYPE NT_STATUS(0x070c) -/* Special "invalid" NT status code. */ -#define NT_STATUS_INVALID NT_STATUS(0xFFFFFFFF) - /* Win32 Error codes extracted using a loop in smbclient then printing a netmon sniff to a file. */ diff --git a/source/include/passdb.h b/source/include/passdb.h index 74063d0fff1..35bb93aa31c 100644 --- a/source/include/passdb.h +++ b/source/include/passdb.h @@ -34,8 +34,8 @@ #define ACCT_FULL_NAME 0x00000002 #define ACCT_RID 0x00000004 #define ACCT_PRIMARY_GID 0x00000008 -#define ACCT_ADMIN_DESC 0x00000010 -#define ACCT_DESCRIPTION 0x00000020 +#define ACCT_DESCRIPTION 0x00000010 +#define ACCT_COMMENT 0x00000020 #define ACCT_HOME_DIR 0x00000040 #define ACCT_HOME_DRIVE 0x00000080 #define ACCT_LOGON_SCRIPT 0x00000100 @@ -90,7 +90,7 @@ enum pdb_elements { PDB_UNIXHOMEDIR, PDB_ACCTDESC, PDB_WORKSTATIONS, - PDB_UNKNOWNSTR, + PDB_COMMENT, PDB_MUNGEDDIAL, PDB_HOURS, PDB_FIELDS_PRESENT, @@ -160,7 +160,7 @@ struct samu { const char *profile_path; /* profile path string */ const char *acct_desc; /* user description string */ const char *workstations; /* login from workstations string */ - const char *unknown_str; /* don't know what this is, yet. */ + const char *comment; const char *munged_dial; /* munged path name and dial-back tel number */ DOM_SID user_sid; diff --git a/source/include/rpc_netlogon.h b/source/include/rpc_netlogon.h index 9df7701de41..f80dc3121d1 100644 --- a/source/include/rpc_netlogon.h +++ b/source/include/rpc_netlogon.h @@ -43,11 +43,6 @@ #define NET_DSR_GETSITENAME 0x1c #define NET_SAMLOGON_EX 0x27 -/* Secure Channel types. used in NetrServerAuthenticate negotiation */ -#define SEC_CHAN_WKSTA 2 -#define SEC_CHAN_DOMAIN 4 -#define SEC_CHAN_BDC 6 - /* Returned delta types */ #define SAM_DELTA_DOMAIN_INFO 0x01 #define SAM_DELTA_GROUP_INFO 0x02 @@ -66,11 +61,6 @@ #define SAM_DELTA_DELETE_USER 0x15 #define SAM_DELTA_MODIFIED_COUNT 0x16 -/* SAM database types */ -#define SAM_DATABASE_DOMAIN 0x00 /* Domain users and groups */ -#define SAM_DATABASE_BUILTIN 0x01 /* BUILTIN users and groups */ -#define SAM_DATABASE_PRIVS 0x02 /* Privileges */ - /* flags use when sending a NETLOGON_CONTROL request */ #define NETLOGON_CONTROL_SYNC 0x2 diff --git a/source/include/rpc_reg.h b/source/include/rpc_reg.h index c454a1d6f94..883e2a8146a 100644 --- a/source/include/rpc_reg.h +++ b/source/include/rpc_reg.h @@ -86,6 +86,7 @@ #define REG_RESOURCE_LIST 8 #define REG_FULL_RESOURCE_DESCRIPTOR 9 #define REG_RESOURCE_REQUIREMENTS_LIST 10 +#define REG_QWORD 11 /* * Registry key types diff --git a/source/include/rpc_samr.h b/source/include/rpc_samr.h index 910ccee1135..ed4e51837f7 100644 --- a/source/include/rpc_samr.h +++ b/source/include/rpc_samr.h @@ -174,7 +174,7 @@ typedef struct sam_user_info_23 UNIHDR hdr_profile_path; /* profile path unicode string header */ UNIHDR hdr_acct_desc ; /* user description */ UNIHDR hdr_workstations; /* comma-separated workstations user can log in from */ - UNIHDR hdr_unknown_str ; /* don't know what this is, yet. */ + UNIHDR hdr_comment; UNIHDR hdr_munged_dial ; /* munged path name and dial-back tel number */ uint8 lm_pwd[16]; /* lm user passwords */ @@ -211,7 +211,7 @@ typedef struct sam_user_info_23 UNISTR2 uni_profile_path; /* profile path unicode string */ UNISTR2 uni_acct_desc ; /* user description unicode string */ UNISTR2 uni_workstations; /* login from workstations unicode string */ - UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */ + UNISTR2 uni_comment; UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel no */ LOGON_HRS logon_hrs; @@ -250,7 +250,7 @@ typedef struct sam_user_info_25 UNIHDR hdr_profile_path; /* profile path unicode string header */ UNIHDR hdr_acct_desc ; /* user description */ UNIHDR hdr_workstations; /* comma-separated workstations user can log in from */ - UNIHDR hdr_unknown_str ; /* don't know what this is, yet. */ + UNIHDR hdr_comment; UNIHDR hdr_munged_dial ; /* munged path name and dial-back tel number */ uint8 lm_pwd[16]; /* lm user passwords */ @@ -274,7 +274,7 @@ typedef struct sam_user_info_25 UNISTR2 uni_profile_path; /* profile path unicode string */ UNISTR2 uni_acct_desc ; /* user description unicode string */ UNISTR2 uni_workstations; /* login from workstations unicode string */ - UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */ + UNISTR2 uni_comment; UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel no */ } SAM_USER_INFO_25; @@ -304,7 +304,7 @@ typedef struct sam_user_info_21 UNIHDR hdr_profile_path; /* profile path unicode string header */ UNIHDR hdr_acct_desc ; /* user description */ UNIHDR hdr_workstations; /* comma-separated workstations user can log in from */ - UNIHDR hdr_unknown_str ; /* don't know what this is, yet. */ + UNIHDR hdr_comment; UNIHDR hdr_munged_dial ; /* munged path name and dial-back tel number */ uint8 lm_pwd[16]; /* lm user passwords */ @@ -340,7 +340,7 @@ typedef struct sam_user_info_21 UNISTR2 uni_profile_path; /* profile path unicode string */ UNISTR2 uni_acct_desc ; /* user description unicode string */ UNISTR2 uni_workstations; /* login from workstations unicode string */ - UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */ + UNISTR2 uni_comment; UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel number */ LOGON_HRS logon_hrs; diff --git a/source/include/rpc_secdes.h b/source/include/rpc_secdes.h index c385e41fd30..2ac60bd9b12 100644 --- a/source/include/rpc_secdes.h +++ b/source/include/rpc_secdes.h @@ -43,33 +43,6 @@ #define SEC_ACE_OBJECT_PRESENT 0x00000001 /* thanks for Jim McDonough <jmcd@us.ibm.com> */ #define SEC_ACE_OBJECT_INHERITED_PRESENT 0x00000002 -#define SEC_ACE_FLAG_OBJECT_INHERIT 0x1 -#define SEC_ACE_FLAG_CONTAINER_INHERIT 0x2 -#define SEC_ACE_FLAG_NO_PROPAGATE_INHERIT 0x4 -#define SEC_ACE_FLAG_INHERIT_ONLY 0x8 -#define SEC_ACE_FLAG_INHERITED_ACE 0x10 /* New for Windows 2000 */ -#define SEC_ACE_FLAG_VALID_INHERIT 0xf -#define SEC_ACE_FLAG_SUCCESSFUL_ACCESS 0x40 -#define SEC_ACE_FLAG_FAILED_ACCESS 0x80 - -#define SEC_ACE_TYPE_ACCESS_ALLOWED 0x0 -#define SEC_ACE_TYPE_ACCESS_DENIED 0x1 -#define SEC_ACE_TYPE_SYSTEM_AUDIT 0x2 -#define SEC_ACE_TYPE_SYSTEM_ALARM 0x3 -#define SEC_ACE_TYPE_ALLOWED_COMPOUND 0x4 -#define SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT 0x5 -#define SEC_ACE_TYPE_ACCESS_DENIED_OBJECT 0x6 -#define SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT 0x7 -#define SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT 0x8 - -#define SEC_DESC_OWNER_DEFAULTED 0x0001 -#define SEC_DESC_GROUP_DEFAULTED 0x0002 -#define SEC_DESC_DACL_PRESENT 0x0004 -#define SEC_DESC_DACL_DEFAULTED 0x0008 -#define SEC_DESC_SACL_PRESENT 0x0010 -#define SEC_DESC_SACL_DEFAULTED 0x0020 -#define SEC_DESC_DACL_TRUSTED 0x0040 -#define SEC_DESC_SERVER_SECURITY 0x0080 /* * New Windows 2000 bits. */ @@ -80,11 +53,6 @@ #define SE_DESC_DACL_PROTECTED 0x1000 #define SE_DESC_SACL_PROTECTED 0x2000 -/* Don't know what this means. */ -#define SEC_DESC_RM_CONTROL_VALID 0x4000 - -#define SEC_DESC_SELF_RELATIVE 0x8000 - /* security information */ #define OWNER_SECURITY_INFORMATION 0x00000001 #define GROUP_SECURITY_INFORMATION 0x00000002 @@ -134,10 +102,6 @@ typedef struct security_ace_info #define ACL_REVISION 0x3 #endif -#ifndef NT4_ACL_REVISION -#define NT4_ACL_REVISION 0x2 -#endif - #ifndef _SEC_ACL /* SEC_ACL */ typedef struct security_acl_info diff --git a/source/include/rpc_srvsvc.h b/source/include/rpc_srvsvc.h index f84054b878b..31032f64a4d 100644 --- a/source/include/rpc_srvsvc.h +++ b/source/include/rpc_srvsvc.h @@ -5,6 +5,8 @@ Copyright (C) Luke Kenneth Casson Leighton 1996-1997 Copyright (C) Paul Ashton 1997 Copyright (C) Nigel Williams 2001 + Copyright (C) Gerald (Jerry) Carter 2006. + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -72,128 +74,84 @@ typedef struct net_srv_disk_enum { WERROR status; /* return status */ } SRV_Q_NET_DISK_ENUM, SRV_R_NET_DISK_ENUM; -typedef struct net_name_validate { - uint32 ptr_srv_name; - UNISTR2 uni_srv_name; - UNISTR2 uni_name; /*name to validate*/ +/***************************/ + +typedef struct { + UNISTR2 *servername; + UNISTR2 sharename; uint32 type; uint32 flags; WERROR status; -} SRV_Q_NET_NAME_VALIDATE, SRV_R_NET_NAME_VALIDATE; - -/* SESS_INFO_0 (pointers to level 0 session info strings) */ -typedef struct ptr_sess_info0 -{ - uint32 ptr_name; /* pointer to name. */ - -} SESS_INFO_0; +} SRV_Q_NET_NAME_VALIDATE; -/* SESS_INFO_0_STR (level 0 session info strings) */ -typedef struct str_sess_info0 -{ - UNISTR2 uni_name; /* unicode string of name */ +typedef struct { + WERROR status; +} SRV_R_NET_NAME_VALIDATE; -} SESS_INFO_0_STR; +/***************************/ /* oops - this is going to take up a *massive* amount of stack. */ /* the UNISTR2s already have 1024 uint16 chars in them... */ -#define MAX_SESS_ENTRIES 32 -/* SRV_SESS_INFO_0 */ -typedef struct srv_sess_info_0_info -{ - uint32 num_entries_read; /* EntriesRead */ - uint32 ptr_sess_info; /* Buffer */ - uint32 num_entries_read2; /* EntriesRead */ +#define MAX_SESS_ENTRIES 32 - SESS_INFO_0 info_0 [MAX_SESS_ENTRIES]; /* session entry pointers */ - SESS_INFO_0_STR info_0_str[MAX_SESS_ENTRIES]; /* session entry strings */ +typedef struct { + UNISTR2 *sharename; +} SESS_INFO_0; +typedef struct { + uint32 num_entries_read; + uint32 ptr_sess_info; + uint32 num_entries_read2; + SESS_INFO_0 info_0[MAX_SESS_ENTRIES]; } SRV_SESS_INFO_0; -/* SESS_INFO_1 (pointers to level 1 session info strings) */ -typedef struct ptr_sess_info1 -{ - uint32 ptr_name; /* pointer to name. */ - uint32 ptr_user; /* pointer to user name. */ - +typedef struct { + UNISTR2 *sharename; + UNISTR2 *username; uint32 num_opens; uint32 open_time; uint32 idle_time; uint32 user_flags; - } SESS_INFO_1; -/* SESS_INFO_1_STR (level 1 session info strings) */ -typedef struct str_sess_info1 -{ - UNISTR2 uni_name; /* unicode string of name */ - UNISTR2 uni_user; /* unicode string of user */ - -} SESS_INFO_1_STR; - -/* SRV_SESS_INFO_1 */ -typedef struct srv_sess_info_1_info -{ - uint32 num_entries_read; /* EntriesRead */ - uint32 ptr_sess_info; /* Buffer */ - uint32 num_entries_read2; /* EntriesRead */ - - SESS_INFO_1 info_1 [MAX_SESS_ENTRIES]; /* session entry pointers */ - SESS_INFO_1_STR info_1_str[MAX_SESS_ENTRIES]; /* session entry strings */ - +typedef struct { + uint32 num_entries_read; + uint32 ptr_sess_info; + uint32 num_entries_read2; + SESS_INFO_1 info_1[MAX_SESS_ENTRIES]; } SRV_SESS_INFO_1; -/* SRV_SESS_INFO_CTR */ -typedef struct srv_sess_info_ctr_info -{ - uint32 switch_value; /* switch value */ - uint32 ptr_sess_ctr; /* pointer to sess info union */ - union - { - SRV_SESS_INFO_0 info0; /* session info level 0 */ - SRV_SESS_INFO_1 info1; /* session info level 1 */ - - } sess; +typedef struct { + uint32 switch_value; + uint32 ptr_sess_ctr; + union { + SRV_SESS_INFO_0 info0; + SRV_SESS_INFO_1 info1; + } sess; } SRV_SESS_INFO_CTR; - -/* SRV_Q_NET_SESS_ENUM */ -typedef struct q_net_sess_enum_info -{ - uint32 ptr_srv_name; /* pointer (to server name?) */ - UNISTR2 uni_srv_name; /* server name */ - - uint32 ptr_qual_name; /* pointer (to qualifier name) */ - UNISTR2 uni_qual_name; /* qualifier name "\\qualifier" */ - - uint32 ptr_user_name; /* pointer (to user name */ - UNISTR2 uni_user_name; /* user name */ - - uint32 sess_level; /* session level */ - +typedef struct { + UNISTR2 *servername; + UNISTR2 *qualifier; + UNISTR2 *username; + uint32 sess_level; SRV_SESS_INFO_CTR *ctr; - - uint32 preferred_len; /* preferred maximum length (0xffff ffff) */ + uint32 preferred_len; ENUM_HND enum_hnd; - } SRV_Q_NET_SESS_ENUM; -/* SRV_R_NET_SESS_ENUM */ -typedef struct r_net_sess_enum_info -{ - uint32 sess_level; /* share level */ - +typedef struct { + uint32 sess_level; SRV_SESS_INFO_CTR *ctr; - - uint32 total_entries; /* total number of entries */ + uint32 total_entries; ENUM_HND enum_hnd; - - WERROR status; /* return status */ - + WERROR status; } SRV_R_NET_SESS_ENUM; +/***************************/ + /* SRV_Q_NET_SESS_DEL */ typedef struct q_net_sess_del { @@ -691,104 +649,47 @@ typedef struct r_net_share_del } SRV_R_NET_SHARE_DEL; -/* FILE_INFO_3 (level 3 file info strings) */ -typedef struct file_info3_info -{ +/***************************/ + +typedef struct { uint32 id; /* file index */ uint32 perms; /* file permissions. don't know what format */ uint32 num_locks; /* file locks */ - uint32 ptr_path_name; /* file name */ - uint32 ptr_user_name; /* file owner */ - + UNISTR2 *path; /* file name */ + UNISTR2 *user; /* file owner */ } FILE_INFO_3; -/* FILE_INFO_3_STR (level 3 file info strings) */ -typedef struct str_file_info3_info -{ - UNISTR2 uni_path_name; /* unicode string of file name */ - UNISTR2 uni_user_name; /* unicode string of file owner. */ - -} FILE_INFO_3_STR; - -/* SRV_FILE_INFO_3 */ -typedef struct srv_file_info_3 -{ - uint32 num_entries_read; /* EntriesRead */ - uint32 ptr_file_info; /* Buffer */ - - uint32 num_entries_read2; /* EntriesRead */ - FILE_INFO_3 info_3; /* file entry details */ - FILE_INFO_3_STR info_3_str; /* file entry strings */ -} SRV_FILE_INFO_3; - -/* SRV_FILE_INFO_CTR */ -typedef struct srv_file_info_3_info -{ - uint32 switch_value; /* switch value */ +typedef struct { + uint32 level; /* switch value */ uint32 ptr_file_info; /* pointer to file info union */ uint32 num_entries; uint32 ptr_entries; uint32 num_entries2; - union - { - SRV_FILE_INFO_3 *info3; + union { + FILE_INFO_3 *info3; } file; } SRV_FILE_INFO_CTR; - -/* SRV_Q_NET_FILE_ENUM */ -typedef struct q_net_file_enum_info -{ - uint32 ptr_srv_name; /* pointer (to server name?) */ - UNISTR2 uni_srv_name; /* server name */ - - uint32 ptr_qual_name; /* pointer (to qualifier name) */ - UNISTR2 uni_qual_name; /* qualifier name "\\qualifier" */ - - uint32 ptr_user_name; /* pointer (to user name) */ - UNISTR2 uni_user_name; /* user name */ - - uint32 file_level; /* file level */ - +typedef struct { + UNISTR2 *servername; + UNISTR2 *qualifier; + UNISTR2 *username; + uint32 level; SRV_FILE_INFO_CTR ctr; - - uint32 preferred_len; /* preferred maximum length (0xffff ffff) */ + uint32 preferred_len; /* preferred maximum length (0xffff ffff) */ ENUM_HND enum_hnd; - } SRV_Q_NET_FILE_ENUM; - -/* SRV_R_NET_FILE_ENUM */ -typedef struct r_net_file_enum_info -{ - uint32 file_level; /* file level */ - +typedef struct { + uint32 level; SRV_FILE_INFO_CTR ctr; - - uint32 total_entries; /* total number of files */ + uint32 total_entries; ENUM_HND enum_hnd; - - WERROR status; /* return status */ - + WERROR status; } SRV_R_NET_FILE_ENUM; -/* SRV_Q_NET_FILE_CLOSE */ -typedef struct q_net_file_close -{ - uint32 ptr_srv_name; /* pointer to server name */ - UNISTR2 uni_srv_name; /* server name */ - - uint32 file_id; -} SRV_Q_NET_FILE_CLOSE; - -/* SRV_R_NET_FILE_CLOSE */ -typedef struct r_net_file_close -{ - WERROR status; /* return status */ -} SRV_R_NET_FILE_CLOSE; - /* SRV_INFO_100 */ typedef struct srv_info_100_info { @@ -973,4 +874,17 @@ typedef struct r_net_file_set_secdesc WERROR status; } SRV_R_NET_FILE_SET_SECDESC; +/***************************/ + +typedef struct { + UNISTR2 *servername; + uint32 file_id; +} SRV_Q_NET_FILE_CLOSE; + +typedef struct { + WERROR status; +} SRV_R_NET_FILE_CLOSE; + +/***************************/ + #endif /* _RPC_SRVSVC_H */ diff --git a/source/include/rpc_unixinfo.h b/source/include/rpc_unixinfo.h new file mode 100644 index 00000000000..f2f4382fc47 --- /dev/null +++ b/source/include/rpc_unixinfo.h @@ -0,0 +1,172 @@ +/* + Unix SMB/CIFS implementation. + + Unixinfo definitions. + + Copyright (C) Volker Lendecke 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _RPC_UNIXINFO_H +#define _RPC_UNIXINFO_H + +#define UNIXINFO_SID_TO_UID 0x00 +#define UNIXINFO_UID_TO_SID 0x01 +#define UNIXINFO_SID_TO_GID 0x02 +#define UNIXINFO_GID_TO_SID 0x03 +#define UNIXINFO_GETPWUID 0x04 + +typedef struct unixinfo_q_sid_to_uid { + DOM_SID sid; +} UNIXINFO_Q_SID_TO_UID; + +typedef struct unixinfo_r_sid_to_uid { + UINT64_S uid; + NTSTATUS status; +} UNIXINFO_R_SID_TO_UID; + +typedef struct unixinfo_q_uid_to_sid { + UINT64_S uid; +} UNIXINFO_Q_UID_TO_SID; + +typedef struct unixinfo_r_uid_to_sid { + uint32 sidptr; + DOM_SID sid; + NTSTATUS status; +} UNIXINFO_R_UID_TO_SID; + +typedef struct unixinfo_q_sid_to_gid { + DOM_SID sid; +} UNIXINFO_Q_SID_TO_GID; + +typedef struct unixinfo_r_sid_to_gid { + UINT64_S gid; + NTSTATUS status; +} UNIXINFO_R_SID_TO_GID; + +typedef struct unixinfo_q_gid_to_sid { + UINT64_S gid; +} UNIXINFO_Q_GID_TO_SID; + +typedef struct unixinfo_r_gid_to_sid { + uint32 sidptr; + DOM_SID sid; + NTSTATUS status; +} UNIXINFO_R_GID_TO_SID; + +typedef struct unixinfo_q_getpwuid { + uint32 count; + UINT64_S *uid; +} UNIXINFO_Q_GETPWUID; + +struct unixinfo_getpwuid { + /* name, gid and gecos explicitly excluded, these values can be + retrieved via other means */ + NTSTATUS status; + const char *homedir; + const char *shell; +}; + +typedef struct unixinfo_r_getpwuid { + uint32 count; + struct unixinfo_getpwuid *info; + NTSTATUS status; +} UNIXINFO_R_GETPWUID; + +#endif +/* + Unix SMB/CIFS implementation. + + Unixinfo definitions. + + Copyright (C) Volker Lendecke 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _RPC_UNIXINFO_H +#define _RPC_UNIXINFO_H + +#define UNIXINFO_SID_TO_UID 0x00 +#define UNIXINFO_UID_TO_SID 0x01 +#define UNIXINFO_SID_TO_GID 0x02 +#define UNIXINFO_GID_TO_SID 0x03 +#define UNIXINFO_GETPWUID 0x04 + +typedef struct unixinfo_q_sid_to_uid { + DOM_SID sid; +} UNIXINFO_Q_SID_TO_UID; + +typedef struct unixinfo_r_sid_to_uid { + UINT64_S uid; + NTSTATUS status; +} UNIXINFO_R_SID_TO_UID; + +typedef struct unixinfo_q_uid_to_sid { + UINT64_S uid; +} UNIXINFO_Q_UID_TO_SID; + +typedef struct unixinfo_r_uid_to_sid { + uint32 sidptr; + DOM_SID sid; + NTSTATUS status; +} UNIXINFO_R_UID_TO_SID; + +typedef struct unixinfo_q_sid_to_gid { + DOM_SID sid; +} UNIXINFO_Q_SID_TO_GID; + +typedef struct unixinfo_r_sid_to_gid { + UINT64_S gid; + NTSTATUS status; +} UNIXINFO_R_SID_TO_GID; + +typedef struct unixinfo_q_gid_to_sid { + UINT64_S gid; +} UNIXINFO_Q_GID_TO_SID; + +typedef struct unixinfo_r_gid_to_sid { + uint32 sidptr; + DOM_SID sid; + NTSTATUS status; +} UNIXINFO_R_GID_TO_SID; + +typedef struct unixinfo_q_getpwuid { + UINT64_S uid; +} UNIXINFO_Q_GETPWUID; + +typedef struct unixinfo_r_getpwuid { + /* name and gid explicitly excluded, these values can be retrieved via + other means */ + const char *gecos; + const char *homedir; + const char *shell; + NTSTATUS status; +} UNIXINFO_R_GETPWUID; + +#endif diff --git a/source/include/session.h b/source/include/session.h index f613afee09a..8c8faab5325 100644 --- a/source/include/session.h +++ b/source/include/session.h @@ -1,8 +1,10 @@ /* Unix SMB/CIFS implementation. session handling for recording currently vailid vuids + Copyright (C) tridge@samba.org 2001 Copyright (C) Andew Bartlett <abartlet@samba.org> 2001 + Copyright (C) Gerald (Jerry) Carter 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,5 +38,6 @@ struct sessionid { uint32 id_num; uint32 pid; fstring ip_addr; + time_t connect_start; }; diff --git a/source/include/smb.h b/source/include/smb.h index e0f2e8483cb..3109948f59e 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -52,11 +52,6 @@ #define Auto (2) #define Required (3) -#ifndef _BOOL -typedef int BOOL; -#define _BOOL /* So we don't typedef BOOL again in vfs.h */ -#endif - #define SIZEOFWORD 2 #ifndef DEF_CREATE_MASK @@ -197,6 +192,7 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN]; #define PIPE_EPM "\\PIPE\\epmapper" #define PIPE_SVCCTL "\\PIPE\\svcctl" #define PIPE_EVENTLOG "\\PIPE\\eventlog" +#define PIPE_UNIXINFO "\\PIPE\\unixinfo" #define PIPE_NETLOGON_PLAIN "\\NETLOGON" @@ -213,8 +209,9 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN]; #define PI_SHUTDOWN 10 #define PI_SVCCTL 11 #define PI_EVENTLOG 12 -#define PI_NTSVCS 13 -#define PI_MAX_PIPES 14 +#define PI_UNIXINFO 13 +#define PI_NTSVCS 14 +#define PI_MAX_PIPES 15 /* 64 bit time (100usec) since ????? - cifs6.txt, section 3.5, page 30 */ typedef struct nttime_info { @@ -411,6 +408,14 @@ struct timed_event; struct idle_event; struct share_mode_entry; +struct vfs_fsp_data { + struct vfs_fsp_data *next; + struct vfs_handle_struct *owner; + /* NOTE: This structure contains two pointers so that we can guarantee + * that the end of the structure is always both 4-byte and 8-byte aligned. + */ +}; + typedef struct files_struct { struct files_struct *next, *prev; int fnum; @@ -449,6 +454,8 @@ typedef struct files_struct { BOOL aio_write_behind; BOOL lockdb_clean; char *fsp_name; + + struct vfs_fsp_data *vfs_extension; FAKE_FILE_HANDLE *fake_file_handle; } files_struct; @@ -533,11 +540,15 @@ struct dfree_cached_info { struct dptr_struct; +struct share_params { + int service; +}; + typedef struct connection_struct { struct connection_struct *next, *prev; TALLOC_CTX *mem_ctx; unsigned cnum; /* an index passed over the wire */ - int service; + struct share_params *params; BOOL force_user; BOOL force_group; struct vuid_cache vuid_cache; @@ -733,6 +744,16 @@ struct locking_data { */ }; +/* Used to store pipe open records for NetFileEnum() */ + +struct pipe_open_rec { + struct process_id pid; + uid_t uid; + int pnum; + fstring name; +}; + + #define NT_HASH_LEN 16 #define LM_HASH_LEN 16 @@ -836,54 +857,13 @@ struct parm_struct { #define FLAG_HIDE 0x2000 /* options that should be hidden in SWAT */ #define FLAG_DOS_STRING 0x4000 /* convert from UNIX to DOS codepage when reading this string. */ -/* passed to br lock code - the UNLOCK_LOCK should never be stored into the tdb - and is used in calculating POSIX unlock ranges only. */ - -enum brl_type {READ_LOCK, WRITE_LOCK, PENDING_LOCK, UNLOCK_LOCK}; -enum brl_flavour {WINDOWS_LOCK = 0, POSIX_LOCK = 1}; - -/* The key used in the brlock database. */ - -struct lock_key { - SMB_DEV_T device; - SMB_INO_T inode; -}; - -struct byte_range_lock { - files_struct *fsp; - unsigned int num_locks; - BOOL modified; - struct lock_key key; - void *lock_data; -}; - -#define BRLOCK_FN_CAST() \ - void (*)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \ - enum brl_type lock_type, \ - enum brl_flavour lock_flav, \ - br_off start, br_off size) - -#define BRLOCK_FN(fn) \ - void (*fn)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \ - enum brl_type lock_type, \ - enum brl_flavour lock_flav, \ - br_off start, br_off size) - -#define LOCKING_FN_CAST() \ - void (*)(struct share_mode_entry *, const char *, const char *) - -#define LOCKING_FN(fn) \ - void (*fn)(struct share_mode_entry *, const char *, const char *) +#include "locking.h" struct bitmap { uint32 *b; unsigned int n; }; -#ifndef LOCKING_VERSION -#define LOCKING_VERSION 4 -#endif /* LOCKING_VERSION */ - /* the basic packet size, assuming no words or bytes */ #define smb_size 39 diff --git a/source/include/smb_macros.h b/source/include/smb_macros.h index 554dbbc0878..e296ddd1403 100644 --- a/source/include/smb_macros.h +++ b/source/include/smb_macros.h @@ -83,8 +83,6 @@ #define SMB_ASSERT_ARRAY(a,n) SMB_ASSERT((sizeof(a)/sizeof((a)[0])) >= (n)) /* these are useful macros for checking validity of handles */ -#define OPEN_FSP(fsp) ((fsp) && !(fsp)->is_directory) -#define OPEN_CONN(conn) ((conn) && (conn)->open) #define IS_IPC(conn) ((conn) && (conn)->ipc) #define IS_PRINT(conn) ((conn) && (conn)->printer) /* you must add the following extern declaration to files using this macro @@ -93,20 +91,24 @@ #define FSP_BELONGS_CONN(fsp,conn) do {\ extern struct current_user current_user;\ if (!((fsp) && (conn) && ((conn)==(fsp)->conn) && (current_user.vuid==(fsp)->vuid))) \ - return(ERROR_DOS(ERRDOS,ERRbadfid));\ + return ERROR_NT(NT_STATUS_INVALID_HANDLE); \ } while(0) -#define FNUM_OK(fsp,c) (OPEN_FSP(fsp) && (c)==(fsp)->conn && current_user.vuid==(fsp)->vuid) +#define FNUM_OK(fsp,c) ((fsp) && !(fsp)->is_directory && (c)==(fsp)->conn && current_user.vuid==(fsp)->vuid) /* you must add the following extern declaration to files using this macro * extern struct current_user current_user; */ #define CHECK_FSP(fsp,conn) do {\ extern struct current_user current_user;\ - if (!FNUM_OK(fsp,conn)) \ - return(ERROR_DOS(ERRDOS,ERRbadfid)); \ - else if((fsp)->fh->fd == -1) \ - return(ERROR_DOS(ERRDOS,ERRbadaccess));\ + if (!(fsp) || !(conn)) \ + return ERROR_NT(NT_STATUS_INVALID_HANDLE); \ + else if (((conn) != (fsp)->conn) || current_user.vuid != (fsp)->vuid) \ + return ERROR_NT(NT_STATUS_INVALID_HANDLE); \ + else if ((fsp)->is_directory) \ + return ERROR_NT(NT_STATUS_INVALID_DEVICE_REQUEST); \ + else if ((fsp)->fh->fd == -1) \ + return ERROR_NT(NT_STATUS_ACCESS_DENIED); \ (fsp)->num_smb_operations++;\ } while(0) @@ -122,7 +124,7 @@ /* the service number for the [globals] defaults */ #define GLOBAL_SECTION_SNUM (-1) /* translates a connection number into a service number */ -#define SNUM(conn) ((conn)?(conn)->service:GLOBAL_SECTION_SNUM) +#define SNUM(conn) ((conn)?(conn)->params->service:GLOBAL_SECTION_SNUM) /* access various service details */ @@ -133,10 +135,10 @@ #define GUEST_OK(snum) (VALID_SNUM(snum) && lp_guest_ok(snum)) #define GUEST_ONLY(snum) (VALID_SNUM(snum) && lp_guest_only(snum)) #define CAN_SETDIR(snum) (!lp_no_set_dir(snum)) -#define CAN_PRINT(conn) ((conn) && lp_print_ok((conn)->service)) -#define MAP_HIDDEN(conn) ((conn) && lp_map_hidden((conn)->service)) -#define MAP_SYSTEM(conn) ((conn) && lp_map_system((conn)->service)) -#define MAP_ARCHIVE(conn) ((conn) && lp_map_archive((conn)->service)) +#define CAN_PRINT(conn) ((conn) && lp_print_ok(SNUM(conn))) +#define MAP_HIDDEN(conn) ((conn) && lp_map_hidden(SNUM(conn))) +#define MAP_SYSTEM(conn) ((conn) && lp_map_system(SNUM(conn))) +#define MAP_ARCHIVE(conn) ((conn) && lp_map_archive(SNUM(conn))) #define IS_HIDDEN_PATH(conn,path) ((conn) && is_in_path((path),(conn)->hide_list,(conn)->case_sensitive)) #define IS_VETO_PATH(conn,path) ((conn) && is_in_path((path),(conn)->veto_list,(conn)->case_sensitive)) #define IS_VETO_OPLOCK_PATH(conn,path) ((conn) && is_in_path((path),(conn)->veto_oplock_list,(conn)->case_sensitive)) @@ -182,7 +184,6 @@ #define CACHED_ERROR(fsp) cached_error_packet(outbuf,fsp,__LINE__,__FILE__) #define ERROR_DOS(class,code) error_packet(outbuf,class,code,NT_STATUS_OK,__LINE__,__FILE__) -#define ERROR_FORCE_DOS(class,code) error_packet(outbuf,class,code,NT_STATUS_INVALID,__LINE__,__FILE__) #define ERROR_NT(status) error_packet(outbuf,0,0,status,__LINE__,__FILE__) #define ERROR_FORCE_NT(status) error_packet(outbuf,-1,-1,status,__LINE__,__FILE__) #define ERROR_BOTH(status,class,code) error_packet(outbuf,class,code,status,__LINE__,__FILE__) @@ -377,6 +378,6 @@ do { \ } while (0) #define ADD_TO_LARGE_ARRAY(mem_ctx, type, elem, array, num, size) \ - add_to_large_array((mem_ctx), sizeof(type), &(elem), (void **)(array), (num), (size)); + add_to_large_array((mem_ctx), sizeof(type), &(elem), (void *)(array), (num), (size)); #endif /* _SMB_MACROS_H */ diff --git a/source/include/smbprofile.h b/source/include/smbprofile.h index b8a9a49be1a..d29f066796b 100644 --- a/source/include/smbprofile.h +++ b/source/include/smbprofile.h @@ -4,7 +4,8 @@ Unix SMB/CIFS implementation. store smbd profiling information in shared memory Copyright (C) Andrew Tridgell 1999 - + Copyright (C) James Peach 2006 + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -26,102 +27,711 @@ #define PROF_SHMEM_KEY ((key_t)0x07021999) #define PROF_SHM_MAGIC 0x6349985 -#define PROF_SHM_VERSION 10 +#define PROF_SHM_VERSION 11 /* time values in the following structure are in microseconds */ +#define __profile_stats_value(which, domain) domain[which] + +enum profile_stats_values +{ + PR_VALUE_SMBD_IDLE = 0, +#define smbd_idle_count __profile_stats_value(PR_VALUE_SMBD_IDLE, count) +#define smbd_idle_time __profile_stats_value(PR_VALUE_SMBD_IDLE, time) + +/* system call counters */ + PR_VALUE_SYSCALL_OPENDIR, +#define syscall_opendir_count __profile_stats_value(PR_VALUE_SYSCALL_OPENDIR, count) +#define syscall_opendir_time __profile_stats_value(PR_VALUE_SYSCALL_OPENDIR, time) + + PR_VALUE_SYSCALL_READDIR, +#define syscall_readdir_count __profile_stats_value(PR_VALUE_SYSCALL_READDIR, count) +#define syscall_readdir_time __profile_stats_value(PR_VALUE_SYSCALL_READDIR, time) + + PR_VALUE_SYSCALL_SEEKDIR, +#define syscall_seekdir_count __profile_stats_value(PR_VALUE_SYSCALL_SEEKDIR, count) +#define syscall_seekdir_time __profile_stats_value(PR_VALUE_SYSCALL_SEEKDIR, time) + + PR_VALUE_SYSCALL_TELLDIR, +#define syscall_telldir_count __profile_stats_value(PR_VALUE_SYSCALL_TELLDIR, count) +#define syscall_telldir_time __profile_stats_value(PR_VALUE_SYSCALL_TELLDIR, time) + + PR_VALUE_SYSCALL_REWINDDIR, +#define syscall_rewinddir_count __profile_stats_value(PR_VALUE_SYSCALL_REWINDDIR, count) +#define syscall_rewinddir_time __profile_stats_value(PR_VALUE_SYSCALL_REWINDDIR, time) + + PR_VALUE_SYSCALL_MKDIR, +#define syscall_mkdir_count __profile_stats_value(PR_VALUE_SYSCALL_MKDIR, count) +#define syscall_mkdir_time __profile_stats_value(PR_VALUE_SYSCALL_MKDIR, time) + + PR_VALUE_SYSCALL_RMDIR, +#define syscall_rmdir_count __profile_stats_value(PR_VALUE_SYSCALL_RMDIR, count) +#define syscall_rmdir_time __profile_stats_value(PR_VALUE_SYSCALL_RMDIR, time) + + PR_VALUE_SYSCALL_CLOSEDIR, +#define syscall_closedir_count __profile_stats_value(PR_VALUE_SYSCALL_CLOSEDIR, count) +#define syscall_closedir_time __profile_stats_value(PR_VALUE_SYSCALL_CLOSEDIR, time) + + PR_VALUE_SYSCALL_OPEN, +#define syscall_open_count __profile_stats_value(PR_VALUE_SYSCALL_OPEN, count) +#define syscall_open_time __profile_stats_value(PR_VALUE_SYSCALL_OPEN, time) + + PR_VALUE_SYSCALL_CLOSE, +#define syscall_close_count __profile_stats_value(PR_VALUE_SYSCALL_CLOSE, count) +#define syscall_close_time __profile_stats_value(PR_VALUE_SYSCALL_CLOSE, time) + + PR_VALUE_SYSCALL_READ, +#define syscall_read_count __profile_stats_value(PR_VALUE_SYSCALL_READ, count) +#define syscall_read_time __profile_stats_value(PR_VALUE_SYSCALL_READ, time) + + PR_VALUE_SYSCALL_PREAD, +#define syscall_pread_count __profile_stats_value(PR_VALUE_SYSCALL_PREAD, count) +#define syscall_pread_time __profile_stats_value(PR_VALUE_SYSCALL_PREAD, time) + + PR_VALUE_SYSCALL_WRITE, +#define syscall_write_count __profile_stats_value(PR_VALUE_SYSCALL_WRITE, count) +#define syscall_write_time __profile_stats_value(PR_VALUE_SYSCALL_WRITE, time) + + PR_VALUE_SYSCALL_PWRITE, +#define syscall_pwrite_count __profile_stats_value(PR_VALUE_SYSCALL_PWRITE, count) +#define syscall_pwrite_time __profile_stats_value(PR_VALUE_SYSCALL_PWRITE, time) + + PR_VALUE_SYSCALL_LSEEK, +#define syscall_lseek_count __profile_stats_value(PR_VALUE_SYSCALL_LSEEK, count) +#define syscall_lseek_time __profile_stats_value(PR_VALUE_SYSCALL_LSEEK, time) + + PR_VALUE_SYSCALL_SENDFILE, +#define syscall_sendfile_count __profile_stats_value(PR_VALUE_SYSCALL_SENDFILE, count) +#define syscall_sendfile_time __profile_stats_value(PR_VALUE_SYSCALL_SENDFILE, time) + + PR_VALUE_SYSCALL_RENAME, +#define syscall_rename_count __profile_stats_value(PR_VALUE_SYSCALL_RENAME, count) +#define syscall_rename_time __profile_stats_value(PR_VALUE_SYSCALL_RENAME, time) + + PR_VALUE_SYSCALL_FSYNC, +#define syscall_fsync_count __profile_stats_value(PR_VALUE_SYSCALL_FSYNC, count) +#define syscall_fsync_time __profile_stats_value(PR_VALUE_SYSCALL_FSYNC, time) + + PR_VALUE_SYSCALL_STAT, +#define syscall_stat_count __profile_stats_value(PR_VALUE_SYSCALL_STAT, count) +#define syscall_stat_time __profile_stats_value(PR_VALUE_SYSCALL_STAT, time) + + PR_VALUE_SYSCALL_FSTAT, +#define syscall_fstat_count __profile_stats_value(PR_VALUE_SYSCALL_FSTAT, count) +#define syscall_fstat_time __profile_stats_value(PR_VALUE_SYSCALL_FSTAT, time) + + PR_VALUE_SYSCALL_LSTAT, +#define syscall_lstat_count __profile_stats_value(PR_VALUE_SYSCALL_LSTAT, count) +#define syscall_lstat_time __profile_stats_value(PR_VALUE_SYSCALL_LSTAT, time) + + PR_VALUE_SYSCALL_UNLINK, +#define syscall_unlink_count __profile_stats_value(PR_VALUE_SYSCALL_UNLINK, count) +#define syscall_unlink_time __profile_stats_value(PR_VALUE_SYSCALL_UNLINK, time) + + PR_VALUE_SYSCALL_CHMOD, +#define syscall_chmod_count __profile_stats_value(PR_VALUE_SYSCALL_CHMOD, count) +#define syscall_chmod_time __profile_stats_value(PR_VALUE_SYSCALL_CHMOD, time) + + PR_VALUE_SYSCALL_FCHMOD, +#define syscall_fchmod_count __profile_stats_value(PR_VALUE_SYSCALL_FCHMOD, count) +#define syscall_fchmod_time __profile_stats_value(PR_VALUE_SYSCALL_FCHMOD, time) + + PR_VALUE_SYSCALL_CHOWN, +#define syscall_chown_count __profile_stats_value(PR_VALUE_SYSCALL_CHOWN, count) +#define syscall_chown_time __profile_stats_value(PR_VALUE_SYSCALL_CHOWN, time) + + PR_VALUE_SYSCALL_FCHOWN, +#define syscall_fchown_count __profile_stats_value(PR_VALUE_SYSCALL_FCHOWN, count) +#define syscall_fchown_time __profile_stats_value(PR_VALUE_SYSCALL_FCHOWN, time) + + PR_VALUE_SYSCALL_CHDIR, +#define syscall_chdir_count __profile_stats_value(PR_VALUE_SYSCALL_CHDIR, count) +#define syscall_chdir_time __profile_stats_value(PR_VALUE_SYSCALL_CHDIR, time) + + PR_VALUE_SYSCALL_GETWD, +#define syscall_getwd_count __profile_stats_value(PR_VALUE_SYSCALL_GETWD, count) +#define syscall_getwd_time __profile_stats_value(PR_VALUE_SYSCALL_GETWD, time) + + PR_VALUE_SYSCALL_UTIME, +#define syscall_utime_count __profile_stats_value(PR_VALUE_SYSCALL_UTIME, count) +#define syscall_utime_time __profile_stats_value(PR_VALUE_SYSCALL_UTIME, time) + + PR_VALUE_SYSCALL_FTRUNCATE, +#define syscall_ftruncate_count __profile_stats_value(PR_VALUE_SYSCALL_FTRUNCATE, count) +#define syscall_ftruncate_time __profile_stats_value(PR_VALUE_SYSCALL_FTRUNCATE, time) + + PR_VALUE_SYSCALL_FCNTL_LOCK, +#define syscall_fcntl_lock_count __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_LOCK, count) +#define syscall_fcntl_lock_time __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_LOCK, time) + + PR_VALUE_SYSCALL_FCNTL_GETLOCK, +#define syscall_fcntl_getlock_count __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_GETLOCK, count) +#define syscall_fcntl_getlock_time __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_GETLOCK, time) + + PR_VALUE_SYSCALL_READLINK, +#define syscall_readlink_count __profile_stats_value(PR_VALUE_SYSCALL_READLINK, count) +#define syscall_readlink_time __profile_stats_value(PR_VALUE_SYSCALL_READLINK, time) + + PR_VALUE_SYSCALL_SYMLINK, +#define syscall_symlink_count __profile_stats_value(PR_VALUE_SYSCALL_SYMLINK, count) +#define syscall_symlink_time __profile_stats_value(PR_VALUE_SYSCALL_SYMLINK, time) + + PR_VALUE_SYSCALL_LINK, +#define syscall_link_count __profile_stats_value(PR_VALUE_SYSCALL_LINK, count) +#define syscall_link_time __profile_stats_value(PR_VALUE_SYSCALL_LINK, time) + + PR_VALUE_SYSCALL_MKNOD, +#define syscall_mknod_count __profile_stats_value(PR_VALUE_SYSCALL_MKNOD, count) +#define syscall_mknod_time __profile_stats_value(PR_VALUE_SYSCALL_MKNOD, time) + + PR_VALUE_SYSCALL_REALPATH, +#define syscall_realpath_count __profile_stats_value(PR_VALUE_SYSCALL_REALPATH, count) +#define syscall_realpath_time __profile_stats_value(PR_VALUE_SYSCALL_REALPATH, time) + + PR_VALUE_SYSCALL_GET_QUOTA, +#define syscall_get_quota_count __profile_stats_value(PR_VALUE_SYSCALL_GET_QUOTA, count) +#define syscall_get_quota_time __profile_stats_value(PR_VALUE_SYSCALL_GET_QUOTA, time) + + PR_VALUE_SYSCALL_SET_QUOTA, +#define syscall_set_quota_count __profile_stats_value(PR_VALUE_SYSCALL_SET_QUOTA, count) +#define syscall_set_quota_time __profile_stats_value(PR_VALUE_SYSCALL_SET_QUOTA, time) + +/* counters for individual SMB types */ + PR_VALUE_SMBMKDIR, +#define SMBmkdir_count __profile_stats_value(PR_VALUE_SMBMKDIR, count) +#define SMBmkdir_time __profile_stats_value(PR_VALUE_SMBMKDIR, time) + + PR_VALUE_SMBRMDIR, +#define SMBrmdir_count __profile_stats_value(PR_VALUE_SMBRMDIR, count) +#define SMBrmdir_time __profile_stats_value(PR_VALUE_SMBRMDIR, time) + + PR_VALUE_SMBOPEN, +#define SMBopen_count __profile_stats_value(PR_VALUE_SMBOPEN, count) +#define SMBopen_time __profile_stats_value(PR_VALUE_SMBOPEN, time) + + PR_VALUE_SMBCREATE, +#define SMBcreate_count __profile_stats_value(PR_VALUE_SMBCREATE, count) +#define SMBcreate_time __profile_stats_value(PR_VALUE_SMBCREATE, time) + + PR_VALUE_SMBCLOSE, +#define SMBclose_count __profile_stats_value(PR_VALUE_SMBCLOSE, count) +#define SMBclose_time __profile_stats_value(PR_VALUE_SMBCLOSE, time) + + PR_VALUE_SMBFLUSH, +#define SMBflush_count __profile_stats_value(PR_VALUE_SMBFLUSH, count) +#define SMBflush_time __profile_stats_value(PR_VALUE_SMBFLUSH, time) + + PR_VALUE_SMBUNLINK, +#define SMBunlink_count __profile_stats_value(PR_VALUE_SMBUNLINK, count) +#define SMBunlink_time __profile_stats_value(PR_VALUE_SMBUNLINK, time) + + PR_VALUE_SMBMV, +#define SMBmv_count __profile_stats_value(PR_VALUE_SMBMV, count) +#define SMBmv_time __profile_stats_value(PR_VALUE_SMBMV, time) + + PR_VALUE_SMBGETATR, +#define SMBgetatr_count __profile_stats_value(PR_VALUE_SMBGETATR, count) +#define SMBgetatr_time __profile_stats_value(PR_VALUE_SMBGETATR, time) + + PR_VALUE_SMBSETATR, +#define SMBsetatr_count __profile_stats_value(PR_VALUE_SMBSETATR, count) +#define SMBsetatr_time __profile_stats_value(PR_VALUE_SMBSETATR, time) + + PR_VALUE_SMBREAD, +#define SMBread_count __profile_stats_value(PR_VALUE_SMBREAD, count) +#define SMBread_time __profile_stats_value(PR_VALUE_SMBREAD, time) + + PR_VALUE_SMBWRITE, +#define SMBwrite_count __profile_stats_value(PR_VALUE_SMBWRITE, count) +#define SMBwrite_time __profile_stats_value(PR_VALUE_SMBWRITE, time) + + PR_VALUE_SMBLOCK, +#define SMBlock_count __profile_stats_value(PR_VALUE_SMBLOCK, count) +#define SMBlock_time __profile_stats_value(PR_VALUE_SMBLOCK, time) + + PR_VALUE_SMBUNLOCK, +#define SMBunlock_count __profile_stats_value(PR_VALUE_SMBUNLOCK, count) +#define SMBunlock_time __profile_stats_value(PR_VALUE_SMBUNLOCK, time) + + PR_VALUE_SMBCTEMP, +#define SMBctemp_count __profile_stats_value(PR_VALUE_SMBCTEMP, count) +#define SMBctemp_time __profile_stats_value(PR_VALUE_SMBCTEMP, time) + + /* SMBmknew stats are currently combined with SMBcreate */ + PR_VALUE_SMBMKNEW, +#define SMBmknew_count __profile_stats_value(PR_VALUE_SMBMKNEW, count) +#define SMBmknew_time __profile_stats_value(PR_VALUE_SMBMKNEW, time) + + PR_VALUE_SMBCHKPTH, +#define SMBchkpth_count __profile_stats_value(PR_VALUE_SMBCHKPTH, count) +#define SMBchkpth_time __profile_stats_value(PR_VALUE_SMBCHKPTH, time) + + PR_VALUE_SMBEXIT, +#define SMBexit_count __profile_stats_value(PR_VALUE_SMBEXIT, count) +#define SMBexit_time __profile_stats_value(PR_VALUE_SMBEXIT, time) + + PR_VALUE_SMBLSEEK, +#define SMBlseek_count __profile_stats_value(PR_VALUE_SMBLSEEK, count) +#define SMBlseek_time __profile_stats_value(PR_VALUE_SMBLSEEK, time) + + PR_VALUE_SMBLOCKREAD, +#define SMBlockread_count __profile_stats_value(PR_VALUE_SMBLOCKREAD, count) +#define SMBlockread_time __profile_stats_value(PR_VALUE_SMBLOCKREAD, time) + + PR_VALUE_SMBWRITEUNLOCK, +#define SMBwriteunlock_count __profile_stats_value(PR_VALUE_SMBWRITEUNLOCK, count) +#define SMBwriteunlock_time __profile_stats_value(PR_VALUE_SMBWRITEUNLOCK, time) + + PR_VALUE_SMBREADBRAW, +#define SMBreadbraw_count __profile_stats_value(PR_VALUE_SMBREADBRAW, count) +#define SMBreadbraw_time __profile_stats_value(PR_VALUE_SMBREADBRAW, time) + + PR_VALUE_SMBREADBMPX, +#define SMBreadBmpx_count __profile_stats_value(PR_VALUE_SMBREADBMPX, count) +#define SMBreadBmpx_time __profile_stats_value(PR_VALUE_SMBREADBMPX, time) + + PR_VALUE_SMBREADBS, +#define SMBreadBs_count __profile_stats_value(PR_VALUE_SMBREADBS, count) +#define SMBreadBs_time __profile_stats_value(PR_VALUE_SMBREADBS, time) + + PR_VALUE_SMBWRITEBRAW, +#define SMBwritebraw_count __profile_stats_value(PR_VALUE_SMBWRITEBRAW, count) +#define SMBwritebraw_time __profile_stats_value(PR_VALUE_SMBWRITEBRAW, time) + + PR_VALUE_SMBWRITEBMPX, +#define SMBwriteBmpx_count __profile_stats_value(PR_VALUE_SMBWRITEBMPX, count) +#define SMBwriteBmpx_time __profile_stats_value(PR_VALUE_SMBWRITEBMPX, time) + + PR_VALUE_SMBWRITEBS, +#define SMBwriteBs_count __profile_stats_value(PR_VALUE_SMBWRITEBS, count) +#define SMBwriteBs_time __profile_stats_value(PR_VALUE_SMBWRITEBS, time) + + PR_VALUE_SMBWRITEC, +#define SMBwritec_count __profile_stats_value(PR_VALUE_SMBWRITEC, count) +#define SMBwritec_time __profile_stats_value(PR_VALUE_SMBWRITEC, time) + + PR_VALUE_SMBSETATTRE, +#define SMBsetattrE_count __profile_stats_value(PR_VALUE_SMBSETATTRE, count) +#define SMBsetattrE_time __profile_stats_value(PR_VALUE_SMBSETATTRE, time) + + PR_VALUE_SMBGETATTRE, +#define SMBgetattrE_count __profile_stats_value(PR_VALUE_SMBGETATTRE, count) +#define SMBgetattrE_time __profile_stats_value(PR_VALUE_SMBGETATTRE, time) + + PR_VALUE_SMBLOCKINGX, +#define SMBlockingX_count __profile_stats_value(PR_VALUE_SMBLOCKINGX, count) +#define SMBlockingX_time __profile_stats_value(PR_VALUE_SMBLOCKINGX, time) + + PR_VALUE_SMBTRANS, +#define SMBtrans_count __profile_stats_value(PR_VALUE_SMBTRANS, count) +#define SMBtrans_time __profile_stats_value(PR_VALUE_SMBTRANS, time) + + PR_VALUE_SMBTRANSS, +#define SMBtranss_count __profile_stats_value(PR_VALUE_SMBTRANSS, count) +#define SMBtranss_time __profile_stats_value(PR_VALUE_SMBTRANSS, time) + + PR_VALUE_SMBIOCTL, +#define SMBioctl_count __profile_stats_value(PR_VALUE_SMBIOCTL, count) +#define SMBioctl_time __profile_stats_value(PR_VALUE_SMBIOCTL, time) + + PR_VALUE_SMBIOCTLS, +#define SMBioctls_count __profile_stats_value(PR_VALUE_SMBIOCTLS, count) +#define SMBioctls_time __profile_stats_value(PR_VALUE_SMBIOCTLS, time) + + PR_VALUE_SMBCOPY, +#define SMBcopy_count __profile_stats_value(PR_VALUE_SMBCOPY, count) +#define SMBcopy_time __profile_stats_value(PR_VALUE_SMBCOPY, time) + + PR_VALUE_SMBMOVE, +#define SMBmove_count __profile_stats_value(PR_VALUE_SMBMOVE, count) +#define SMBmove_time __profile_stats_value(PR_VALUE_SMBMOVE, time) + + PR_VALUE_SMBECHO, +#define SMBecho_count __profile_stats_value(PR_VALUE_SMBECHO, count) +#define SMBecho_time __profile_stats_value(PR_VALUE_SMBECHO, time) + + PR_VALUE_SMBWRITECLOSE, +#define SMBwriteclose_count __profile_stats_value(PR_VALUE_SMBWRITECLOSE, count) +#define SMBwriteclose_time __profile_stats_value(PR_VALUE_SMBWRITECLOSE, time) + + PR_VALUE_SMBOPENX, +#define SMBopenX_count __profile_stats_value(PR_VALUE_SMBOPENX, count) +#define SMBopenX_time __profile_stats_value(PR_VALUE_SMBOPENX, time) + + PR_VALUE_SMBREADX, +#define SMBreadX_count __profile_stats_value(PR_VALUE_SMBREADX, count) +#define SMBreadX_time __profile_stats_value(PR_VALUE_SMBREADX, time) + + PR_VALUE_SMBWRITEX, +#define SMBwriteX_count __profile_stats_value(PR_VALUE_SMBWRITEX, count) +#define SMBwriteX_time __profile_stats_value(PR_VALUE_SMBWRITEX, time) + + PR_VALUE_SMBTRANS2, +#define SMBtrans2_count __profile_stats_value(PR_VALUE_SMBTRANS2, count) +#define SMBtrans2_time __profile_stats_value(PR_VALUE_SMBTRANS2, time) + + PR_VALUE_SMBTRANSS2, +#define SMBtranss2_count __profile_stats_value(PR_VALUE_SMBTRANSS2, count) +#define SMBtranss2_time __profile_stats_value(PR_VALUE_SMBTRANSS2, time) + + PR_VALUE_SMBFINDCLOSE, +#define SMBfindclose_count __profile_stats_value(PR_VALUE_SMBFINDCLOSE, count) +#define SMBfindclose_time __profile_stats_value(PR_VALUE_SMBFINDCLOSE, time) + + PR_VALUE_SMBFINDNCLOSE, +#define SMBfindnclose_count __profile_stats_value(PR_VALUE_SMBFINDNCLOSE, count) +#define SMBfindnclose_time __profile_stats_value(PR_VALUE_SMBFINDNCLOSE, time) + + PR_VALUE_SMBTCON, +#define SMBtcon_count __profile_stats_value(PR_VALUE_SMBTCON, count) +#define SMBtcon_time __profile_stats_value(PR_VALUE_SMBTCON, time) + + PR_VALUE_SMBTDIS, +#define SMBtdis_count __profile_stats_value(PR_VALUE_SMBTDIS, count) +#define SMBtdis_time __profile_stats_value(PR_VALUE_SMBTDIS, time) + + PR_VALUE_SMBNEGPROT, +#define SMBnegprot_count __profile_stats_value(PR_VALUE_SMBNEGPROT, count) +#define SMBnegprot_time __profile_stats_value(PR_VALUE_SMBNEGPROT, time) + + PR_VALUE_SMBSESSSETUPX, +#define SMBsesssetupX_count __profile_stats_value(PR_VALUE_SMBSESSSETUPX, count) +#define SMBsesssetupX_time __profile_stats_value(PR_VALUE_SMBSESSSETUPX, time) + + PR_VALUE_SMBULOGOFFX, +#define SMBulogoffX_count __profile_stats_value(PR_VALUE_SMBULOGOFFX, count) +#define SMBulogoffX_time __profile_stats_value(PR_VALUE_SMBULOGOFFX, time) + + PR_VALUE_SMBTCONX, +#define SMBtconX_count __profile_stats_value(PR_VALUE_SMBTCONX, count) +#define SMBtconX_time __profile_stats_value(PR_VALUE_SMBTCONX, time) + + PR_VALUE_SMBDSKATTR, +#define SMBdskattr_count __profile_stats_value(PR_VALUE_SMBDSKATTR, count) +#define SMBdskattr_time __profile_stats_value(PR_VALUE_SMBDSKATTR, time) + + PR_VALUE_SMBSEARCH, +#define SMBsearch_count __profile_stats_value(PR_VALUE_SMBSEARCH, count) +#define SMBsearch_time __profile_stats_value(PR_VALUE_SMBSEARCH, time) + + /* SBMffirst stats combined with SMBsearch */ + PR_VALUE_SMBFFIRST, +#define SMBffirst_count __profile_stats_value(PR_VALUE_SMBFFIRST, count) +#define SMBffirst_time __profile_stats_value(PR_VALUE_SMBFFIRST, time) + + /* SBMfunique stats combined with SMBsearch */ + PR_VALUE_SMBFUNIQUE, +#define SMBfunique_count __profile_stats_value(PR_VALUE_SMBFUNIQUE, count) +#define SMBfunique_time __profile_stats_value(PR_VALUE_SMBFUNIQUE, time) + + PR_VALUE_SMBFCLOSE, +#define SMBfclose_count __profile_stats_value(PR_VALUE_SMBFCLOSE, count) +#define SMBfclose_time __profile_stats_value(PR_VALUE_SMBFCLOSE, time) + + PR_VALUE_SMBNTTRANS, +#define SMBnttrans_count __profile_stats_value(PR_VALUE_SMBNTTRANS, count) +#define SMBnttrans_time __profile_stats_value(PR_VALUE_SMBNTTRANS, time) + + PR_VALUE_SMBNTTRANSS, +#define SMBnttranss_count __profile_stats_value(PR_VALUE_SMBNTTRANSS, count) +#define SMBnttranss_time __profile_stats_value(PR_VALUE_SMBNTTRANSS, time) + + PR_VALUE_SMBNTCREATEX, +#define SMBntcreateX_count __profile_stats_value(PR_VALUE_SMBNTCREATEX, count) +#define SMBntcreateX_time __profile_stats_value(PR_VALUE_SMBNTCREATEX, time) + + PR_VALUE_SMBNTCANCEL, +#define SMBntcancel_count __profile_stats_value(PR_VALUE_SMBNTCANCEL, count) +#define SMBntcancel_time __profile_stats_value(PR_VALUE_SMBNTCANCEL, time) + + PR_VALUE_SMBNTRENAME, +#define SMBntrename_count __profile_stats_value(PR_VALUE_SMBNTRENAME, count) +#define SMBntrename_time __profile_stats_value(PR_VALUE_SMBNTRENAME, time) + + PR_VALUE_SMBSPLOPEN, +#define SMBsplopen_count __profile_stats_value(PR_VALUE_SMBSPLOPEN, count) +#define SMBsplopen_time __profile_stats_value(PR_VALUE_SMBSPLOPEN, time) + + PR_VALUE_SMBSPLWR, +#define SMBsplwr_count __profile_stats_value(PR_VALUE_SMBSPLWR, count) +#define SMBsplwr_time __profile_stats_value(PR_VALUE_SMBSPLWR, time) + + PR_VALUE_SMBSPLCLOSE, +#define SMBsplclose_count __profile_stats_value(PR_VALUE_SMBSPLCLOSE, count) +#define SMBsplclose_time __profile_stats_value(PR_VALUE_SMBSPLCLOSE, time) + + PR_VALUE_SMBSPLRETQ, +#define SMBsplretq_count __profile_stats_value(PR_VALUE_SMBSPLRETQ, count) +#define SMBsplretq_time __profile_stats_value(PR_VALUE_SMBSPLRETQ, time) + + PR_VALUE_SMBSENDS, +#define SMBsends_count __profile_stats_value(PR_VALUE_SMBSENDS, count) +#define SMBsends_time __profile_stats_value(PR_VALUE_SMBSENDS, time) + + PR_VALUE_SMBSENDB, +#define SMBsendb_count __profile_stats_value(PR_VALUE_SMBSENDB, count) +#define SMBsendb_time __profile_stats_value(PR_VALUE_SMBSENDB, time) + + PR_VALUE_SMBFWDNAME, +#define SMBfwdname_count __profile_stats_value(PR_VALUE_SMBFWDNAME, count) +#define SMBfwdname_time __profile_stats_value(PR_VALUE_SMBFWDNAME, time) + + PR_VALUE_SMBCANCELF, +#define SMBcancelf_count __profile_stats_value(PR_VALUE_SMBCANCELF, count) +#define SMBcancelf_time __profile_stats_value(PR_VALUE_SMBCANCELF, time) + + PR_VALUE_SMBGETMAC, +#define SMBgetmac_count __profile_stats_value(PR_VALUE_SMBGETMAC, count) +#define SMBgetmac_time __profile_stats_value(PR_VALUE_SMBGETMAC, time) + + PR_VALUE_SMBSENDSTRT, +#define SMBsendstrt_count __profile_stats_value(PR_VALUE_SMBSENDSTRT, count) +#define SMBsendstrt_time __profile_stats_value(PR_VALUE_SMBSENDSTRT, time) + + PR_VALUE_SMBSENDEND, +#define SMBsendend_count __profile_stats_value(PR_VALUE_SMBSENDEND, count) +#define SMBsendend_time __profile_stats_value(PR_VALUE_SMBSENDEND, time) + + PR_VALUE_SMBSENDTXT, +#define SMBsendtxt_count __profile_stats_value(PR_VALUE_SMBSENDTXT, count) +#define SMBsendtxt_time __profile_stats_value(PR_VALUE_SMBSENDTXT, time) + + PR_VALUE_SMBINVALID, +#define SMBinvalid_count __profile_stats_value(PR_VALUE_SMBINVALID, count) +#define SMBinvalid_time __profile_stats_value(PR_VALUE_SMBINVALID, time) + +/* Pathworks setdir command */ + PR_VALUE_PATHWORKS_SETDIR, +#define pathworks_setdir_count __profile_stats_value(PR_VALUE_PATHWORKS_SETDIR, count) +#define pathworks_setdir_time __profile_stats_value(PR_VALUE_PATHWORKS_SETDIR, time) + +/* These are the TRANS2 sub commands */ + PR_VALUE_TRANS2_OPEN, +#define Trans2_open_count __profile_stats_value(PR_VALUE_TRANS2_OPEN, count) +#define Trans2_open_time __profile_stats_value(PR_VALUE_TRANS2_OPEN, time) + + PR_VALUE_TRANS2_FINDFIRST, +#define Trans2_findfirst_count __profile_stats_value(PR_VALUE_TRANS2_FINDFIRST, count) +#define Trans2_findfirst_time __profile_stats_value(PR_VALUE_TRANS2_FINDFIRST, time) + + PR_VALUE_TRANS2_FINDNEXT, +#define Trans2_findnext_count __profile_stats_value(PR_VALUE_TRANS2_FINDNEXT, count) +#define Trans2_findnext_time __profile_stats_value(PR_VALUE_TRANS2_FINDNEXT, time) + + PR_VALUE_TRANS2_QFSINFO, +#define Trans2_qfsinfo_count __profile_stats_value(PR_VALUE_TRANS2_QFSINFO, count) +#define Trans2_qfsinfo_time __profile_stats_value(PR_VALUE_TRANS2_QFSINFO, time) + + PR_VALUE_TRANS2_SETFSINFO, +#define Trans2_setfsinfo_count __profile_stats_value(PR_VALUE_TRANS2_SETFSINFO, count) +#define Trans2_setfsinfo_time __profile_stats_value(PR_VALUE_TRANS2_SETFSINFO, time) + + PR_VALUE_TRANS2_QPATHINFO, +#define Trans2_qpathinfo_count __profile_stats_value(PR_VALUE_TRANS2_QPATHINFO, count) +#define Trans2_qpathinfo_time __profile_stats_value(PR_VALUE_TRANS2_QPATHINFO, time) + + PR_VALUE_TRANS2_SETPATHINFO, +#define Trans2_setpathinfo_count __profile_stats_value(PR_VALUE_TRANS2_SETPATHINFO, count) +#define Trans2_setpathinfo_time __profile_stats_value(PR_VALUE_TRANS2_SETPATHINFO, time) + + PR_VALUE_TRANS2_QFILEINFO, +#define Trans2_qfileinfo_count __profile_stats_value(PR_VALUE_TRANS2_QFILEINFO, count) +#define Trans2_qfileinfo_time __profile_stats_value(PR_VALUE_TRANS2_QFILEINFO, time) + + PR_VALUE_TRANS2_SETFILEINFO, +#define Trans2_setfileinfo_count __profile_stats_value(PR_VALUE_TRANS2_SETFILEINFO, count) +#define Trans2_setfileinfo_time __profile_stats_value(PR_VALUE_TRANS2_SETFILEINFO, time) + + PR_VALUE_TRANS2_FSCTL, +#define Trans2_fsctl_count __profile_stats_value(PR_VALUE_TRANS2_FSCTL, count) +#define Trans2_fsctl_time __profile_stats_value(PR_VALUE_TRANS2_FSCTL, time) + + PR_VALUE_TRANS2_IOCTL, +#define Trans2_ioctl_count __profile_stats_value(PR_VALUE_TRANS2_IOCTL, count) +#define Trans2_ioctl_time __profile_stats_value(PR_VALUE_TRANS2_IOCTL, time) + + PR_VALUE_TRANS2_FINDNOTIFYFIRST, +#define Trans2_findnotifyfirst_count __profile_stats_value(PR_VALUE_TRANS2_FINDNOTIFYFIRST, count) +#define Trans2_findnotifyfirst_time __profile_stats_value(PR_VALUE_TRANS2_FINDNOTIFYFIRST, time) + + PR_VALUE_TRANS2_FINDNOTIFYNEXT, +#define Trans2_findnotifynext_count __profile_stats_value(PR_VALUE_TRANS2_FINDNOTIFYNEXT, count) +#define Trans2_findnotifynext_time __profile_stats_value(PR_VALUE_TRANS2_FINDNOTIFYNEXT, time) + + PR_VALUE_TRANS2_MKDIR, +#define Trans2_mkdir_count __profile_stats_value(PR_VALUE_TRANS2_MKDIR, count) +#define Trans2_mkdir_time __profile_stats_value(PR_VALUE_TRANS2_MKDIR, time) + + PR_VALUE_TRANS2_SESSION_SETUP, +#define Trans2_session_setup_count __profile_stats_value(PR_VALUE_TRANS2_SESSION_SETUP, count) +#define Trans2_session_setup_time __profile_stats_value(PR_VALUE_TRANS2_SESSION_SETUP, time) + + PR_VALUE_TRANS2_GET_DFS_REFERRAL, +#define Trans2_get_dfs_referral_count __profile_stats_value(PR_VALUE_TRANS2_GET_DFS_REFERRAL, count) +#define Trans2_get_dfs_referral_time __profile_stats_value(PR_VALUE_TRANS2_GET_DFS_REFERRAL, time) + + PR_VALUE_TRANS2_REPORT_DFS_INCONSISTANCY, +#define Trans2_report_dfs_inconsistancy_count __profile_stats_value(PR_VALUE_TRANS2_REPORT_DFS_INCONSISTANCY, count) +#define Trans2_report_dfs_inconsistancy_time __profile_stats_value(PR_VALUE_TRANS2_REPORT_DFS_INCONSISTANCY, time) + +/* These are the NT transact sub commands. */ + PR_VALUE_NT_TRANSACT_CREATE, +#define NT_transact_create_count __profile_stats_value(PR_VALUE_NT_TRANSACT_CREATE, count) +#define NT_transact_create_time __profile_stats_value(PR_VALUE_NT_TRANSACT_CREATE, time) + + PR_VALUE_NT_TRANSACT_IOCTL, +#define NT_transact_ioctl_count __profile_stats_value(PR_VALUE_NT_TRANSACT_IOCTL, count) +#define NT_transact_ioctl_time __profile_stats_value(PR_VALUE_NT_TRANSACT_IOCTL, time) + + PR_VALUE_NT_TRANSACT_SET_SECURITY_DESC, +#define NT_transact_set_security_desc_count __profile_stats_value(PR_VALUE_NT_TRANSACT_SET_SECURITY_DESC, count) +#define NT_transact_set_security_desc_time __profile_stats_value(PR_VALUE_NT_TRANSACT_SET_SECURITY_DESC, time) + + PR_VALUE_NT_TRANSACT_NOTIFY_CHANGE, +#define NT_transact_notify_change_count __profile_stats_value(PR_VALUE_NT_TRANSACT_NOTIFY_CHANGE, count) +#define NT_transact_notify_change_time __profile_stats_value(PR_VALUE_NT_TRANSACT_NOTIFY_CHANGE, time) + + PR_VALUE_NT_TRANSACT_RENAME, +#define NT_transact_rename_count __profile_stats_value(PR_VALUE_NT_TRANSACT_RENAME, count) +#define NT_transact_rename_time __profile_stats_value(PR_VALUE_NT_TRANSACT_RENAME, time) + + PR_VALUE_NT_TRANSACT_QUERY_SECURITY_DESC, +#define NT_transact_query_security_desc_count __profile_stats_value(PR_VALUE_NT_TRANSACT_QUERY_SECURITY_DESC, count) +#define NT_transact_query_security_desc_time __profile_stats_value(PR_VALUE_NT_TRANSACT_QUERY_SECURITY_DESC, time) + + PR_VALUE_NT_TRANSACT_GET_USER_QUOTA, +#define NT_transact_get_user_quota_count __profile_stats_value(PR_VALUE_NT_TRANSACT_GET_USER_QUOTA, count) +#define NT_transact_get_user_quota_time __profile_stats_value(PR_VALUE_NT_TRANSACT_GET_USER_QUOTA, time) + + PR_VALUE_NT_TRANSACT_SET_USER_QUOTA, +#define NT_transact_set_user_quota_count __profile_stats_value(PR_VALUE_NT_TRANSACT_SET_USER_QUOTA, count) +#define NT_transact_set_user_quota_time __profile_stats_value(PR_VALUE_NT_TRANSACT_SET_USER_QUOTA, time) + +/* These are ACL manipulation calls */ + PR_VALUE_GET_NT_ACL, +#define get_nt_acl_count __profile_stats_value(PR_VALUE_GET_NT_ACL, count) +#define get_nt_acl_time __profile_stats_value(PR_VALUE_GET_NT_ACL, time) + + PR_VALUE_FGET_NT_ACL, +#define fget_nt_acl_count __profile_stats_value(PR_VALUE_FGET_NT_ACL, count) +#define fget_nt_acl_time __profile_stats_value(PR_VALUE_FGET_NT_ACL, time) + + PR_VALUE_SET_NT_ACL, +#define set_nt_acl_count __profile_stats_value(PR_VALUE_SET_NT_ACL, count) +#define set_nt_acl_time __profile_stats_value(PR_VALUE_SET_NT_ACL, time) + + PR_VALUE_FSET_NT_ACL, +#define fset_nt_acl_count __profile_stats_value(PR_VALUE_FSET_NT_ACL, count) +#define fset_nt_acl_time __profile_stats_value(PR_VALUE_FSET_NT_ACL, time) + + PR_VALUE_CHMOD_ACL, +#define chmod_acl_count __profile_stats_value(PR_VALUE_CHMOD_ACL, count) +#define chmod_acl_time __profile_stats_value(PR_VALUE_CHMOD_ACL, time) + + PR_VALUE_FCHMOD_ACL, +#define fchmod_acl_count __profile_stats_value(PR_VALUE_FCHMOD_ACL, count) +#define fchmod_acl_time __profile_stats_value(PR_VALUE_FCHMOD_ACL, time) + +/* These are nmbd stats */ + PR_VALUE_NAME_RELEASE, +#define name_release_count __profile_stats_value(PR_VALUE_NAME_RELEASE, count) +#define name_release_time __profile_stats_value(PR_VALUE_NAME_RELEASE, time) + + PR_VALUE_NAME_REFRESH, +#define name_refresh_count __profile_stats_value(PR_VALUE_NAME_REFRESH, count) +#define name_refresh_time __profile_stats_value(PR_VALUE_NAME_REFRESH, time) + + PR_VALUE_NAME_REGISTRATION, +#define name_registration_count __profile_stats_value(PR_VALUE_NAME_REGISTRATION, count) +#define name_registration_time __profile_stats_value(PR_VALUE_NAME_REGISTRATION, time) + + PR_VALUE_NODE_STATUS, +#define node_status_count __profile_stats_value(PR_VALUE_NODE_STATUS, count) +#define node_status_time __profile_stats_value(PR_VALUE_NODE_STATUS, time) + + PR_VALUE_NAME_QUERY, +#define name_query_count __profile_stats_value(PR_VALUE_NAME_QUERY, count) +#define name_query_time __profile_stats_value(PR_VALUE_NAME_QUERY, time) + + PR_VALUE_HOST_ANNOUNCE, +#define host_announce_count __profile_stats_value(PR_VALUE_HOST_ANNOUNCE, count) +#define host_announce_time __profile_stats_value(PR_VALUE_HOST_ANNOUNCE, time) + + PR_VALUE_WORKGROUP_ANNOUNCE, +#define workgroup_announce_count __profile_stats_value(PR_VALUE_WORKGROUP_ANNOUNCE, count) +#define workgroup_announce_time __profile_stats_value(PR_VALUE_WORKGROUP_ANNOUNCE, time) + + PR_VALUE_LOCAL_MASTER_ANNOUNCE, +#define local_master_announce_count __profile_stats_value(PR_VALUE_LOCAL_MASTER_ANNOUNCE, count) +#define local_master_announce_time __profile_stats_value(PR_VALUE_LOCAL_MASTER_ANNOUNCE, time) + + PR_VALUE_MASTER_BROWSER_ANNOUNCE, +#define master_browser_announce_count __profile_stats_value(PR_VALUE_MASTER_BROWSER_ANNOUNCE, count) +#define master_browser_announce_time __profile_stats_value(PR_VALUE_MASTER_BROWSER_ANNOUNCE, time) + + PR_VALUE_LM_HOST_ANNOUNCE, +#define lm_host_announce_count __profile_stats_value(PR_VALUE_LM_HOST_ANNOUNCE, count) +#define lm_host_announce_time __profile_stats_value(PR_VALUE_LM_HOST_ANNOUNCE, time) + + PR_VALUE_GET_BACKUP_LIST, +#define get_backup_list_count __profile_stats_value(PR_VALUE_GET_BACKUP_LIST, count) +#define get_backup_list_time __profile_stats_value(PR_VALUE_GET_BACKUP_LIST, time) + + PR_VALUE_RESET_BROWSER, +#define reset_browser_count __profile_stats_value(PR_VALUE_RESET_BROWSER, count) +#define reset_browser_time __profile_stats_value(PR_VALUE_RESET_BROWSER, time) + + PR_VALUE_ANNOUNCE_REQUEST, +#define announce_request_count __profile_stats_value(PR_VALUE_ANNOUNCE_REQUEST, count) +#define announce_request_time __profile_stats_value(PR_VALUE_ANNOUNCE_REQUEST, time) + + PR_VALUE_LM_ANNOUNCE_REQUEST, +#define lm_announce_request_count __profile_stats_value(PR_VALUE_LM_ANNOUNCE_REQUEST, count) +#define lm_announce_request_time __profile_stats_value(PR_VALUE_LM_ANNOUNCE_REQUEST, time) + + PR_VALUE_DOMAIN_LOGON, +#define domain_logon_count __profile_stats_value(PR_VALUE_DOMAIN_LOGON, count) +#define domain_logon_time __profile_stats_value(PR_VALUE_DOMAIN_LOGON, time) + + PR_VALUE_SYNC_BROWSE_LISTS, +#define sync_browse_lists_count __profile_stats_value(PR_VALUE_SYNC_BROWSE_LISTS, count) +#define sync_browse_lists_time __profile_stats_value(PR_VALUE_SYNC_BROWSE_LISTS, time) + + PR_VALUE_RUN_ELECTIONS, +#define run_elections_count __profile_stats_value(PR_VALUE_RUN_ELECTIONS, count) +#define run_elections_time __profile_stats_value(PR_VALUE_RUN_ELECTIONS, time) + + PR_VALUE_ELECTION, +#define election_count __profile_stats_value(PR_VALUE_ELECTION, count) +#define election_time __profile_stats_value(PR_VALUE_ELECTION, time) + + /* This mist remain the last value. */ + PR_VALUE_MAX +}; /* enum profile_stats_values */ + +const char * profile_value_name(enum profile_stats_values val); + struct profile_stats { /* general counters */ unsigned smb_count; /* how many SMB packets we have processed */ unsigned uid_changes; /* how many times we change our effective uid */ -/* system call counters */ - unsigned syscall_opendir_count; - unsigned syscall_opendir_time; - unsigned syscall_readdir_count; - unsigned syscall_readdir_time; - unsigned syscall_seekdir_count; - unsigned syscall_seekdir_time; - unsigned syscall_telldir_count; - unsigned syscall_telldir_time; - unsigned syscall_rewinddir_count; - unsigned syscall_rewinddir_time; - unsigned syscall_mkdir_count; - unsigned syscall_mkdir_time; - unsigned syscall_rmdir_count; - unsigned syscall_rmdir_time; - unsigned syscall_closedir_count; - unsigned syscall_closedir_time; - unsigned syscall_open_count; - unsigned syscall_open_time; - unsigned syscall_close_count; - unsigned syscall_close_time; - unsigned syscall_read_count; - unsigned syscall_read_time; - unsigned syscall_read_bytes; /* bytes read with read syscall */ - unsigned syscall_pread_count; - unsigned syscall_pread_time; - unsigned syscall_pread_bytes; /* bytes read with pread syscall */ - unsigned syscall_write_count; - unsigned syscall_write_time; - unsigned syscall_write_bytes; /* bytes written with write syscall */ - unsigned syscall_pwrite_count; - unsigned syscall_pwrite_time; - unsigned syscall_pwrite_bytes; /* bytes written with pwrite syscall */ - unsigned syscall_lseek_count; - unsigned syscall_lseek_time; - unsigned syscall_sendfile_count; - unsigned syscall_sendfile_time; - unsigned syscall_sendfile_bytes; /* bytes read with sendfile syscall */ - unsigned syscall_rename_count; - unsigned syscall_rename_time; - unsigned syscall_fsync_count; - unsigned syscall_fsync_time; - unsigned syscall_stat_count; - unsigned syscall_stat_time; - unsigned syscall_fstat_count; - unsigned syscall_fstat_time; - unsigned syscall_lstat_count; - unsigned syscall_lstat_time; - unsigned syscall_unlink_count; - unsigned syscall_unlink_time; - unsigned syscall_chmod_count; - unsigned syscall_chmod_time; - unsigned syscall_fchmod_count; - unsigned syscall_fchmod_time; - unsigned syscall_chown_count; - unsigned syscall_chown_time; - unsigned syscall_fchown_count; - unsigned syscall_fchown_time; - unsigned syscall_chdir_count; - unsigned syscall_chdir_time; - unsigned syscall_getwd_count; - unsigned syscall_getwd_time; - unsigned syscall_utime_count; - unsigned syscall_utime_time; - unsigned syscall_ftruncate_count; - unsigned syscall_ftruncate_time; - unsigned syscall_fcntl_lock_count; - unsigned syscall_fcntl_lock_time; - unsigned syscall_fcntl_getlock_count; - unsigned syscall_fcntl_getlock_time; - unsigned syscall_readlink_count; - unsigned syscall_readlink_time; - unsigned syscall_symlink_count; - unsigned syscall_symlink_time; - unsigned syscall_link_count; - unsigned syscall_link_time; - unsigned syscall_mknod_count; - unsigned syscall_mknod_time; - unsigned syscall_realpath_count; - unsigned syscall_realpath_time; - unsigned syscall_get_quota_count; - unsigned syscall_get_quota_time; - unsigned syscall_set_quota_count; - unsigned syscall_set_quota_time; + +/* system call and protocol operation counters and cumulative times */ + unsigned count[PR_VALUE_MAX]; + unsigned time[PR_VALUE_MAX]; + +/* cumulative byte counts */ + unsigned syscall_pread_bytes; + unsigned syscall_pwrite_bytes; + unsigned syscall_read_bytes; + unsigned syscall_write_bytes; + unsigned syscall_sendfile_bytes; + /* stat cache counters */ unsigned statcache_lookups; unsigned statcache_misses; unsigned statcache_hits; + /* write cache counters */ unsigned writecache_read_hits; unsigned writecache_abutted_writes; @@ -133,265 +743,6 @@ struct profile_stats { unsigned writecache_num_perfect_writes; unsigned writecache_num_write_caches; unsigned writecache_allocated_write_caches; -/* counters for individual SMB types */ - unsigned SMBmkdir_count; /* create directory */ - unsigned SMBmkdir_time; - unsigned SMBrmdir_count; /* delete directory */ - unsigned SMBrmdir_time; - unsigned SMBopen_count; /* open file */ - unsigned SMBopen_time; - unsigned SMBcreate_count; /* create file */ - unsigned SMBcreate_time; - unsigned SMBclose_count; /* close file */ - unsigned SMBclose_time; - unsigned SMBflush_count; /* flush file */ - unsigned SMBflush_time; - unsigned SMBunlink_count; /* delete file */ - unsigned SMBunlink_time; - unsigned SMBmv_count; /* rename file */ - unsigned SMBmv_time; - unsigned SMBgetatr_count; /* get file attributes */ - unsigned SMBgetatr_time; - unsigned SMBsetatr_count; /* set file attributes */ - unsigned SMBsetatr_time; - unsigned SMBread_count; /* read from file */ - unsigned SMBread_time; - unsigned SMBwrite_count; /* write to file */ - unsigned SMBwrite_time; - unsigned SMBlock_count; /* lock byte range */ - unsigned SMBlock_time; - unsigned SMBunlock_count; /* unlock byte range */ - unsigned SMBunlock_time; - unsigned SMBctemp_count; /* create temporary file */ - unsigned SMBctemp_time; - /* SMBmknew stats are currently combined with SMBcreate */ - unsigned SMBmknew_count; /* make new file */ - unsigned SMBmknew_time; - unsigned SMBchkpth_count; /* check directory path */ - unsigned SMBchkpth_time; - unsigned SMBexit_count; /* process exit */ - unsigned SMBexit_time; - unsigned SMBlseek_count; /* seek */ - unsigned SMBlseek_time; - unsigned SMBlockread_count; /* Lock a range and read */ - unsigned SMBlockread_time; - unsigned SMBwriteunlock_count; /* Unlock a range then write */ - unsigned SMBwriteunlock_time; - unsigned SMBreadbraw_count; /* read a block of data with no smb header */ - unsigned SMBreadbraw_time; - unsigned SMBreadBmpx_count; /* read block multiplexed */ - unsigned SMBreadBmpx_time; - unsigned SMBreadBs_count; /* read block (secondary response) */ - unsigned SMBreadBs_time; - unsigned SMBwritebraw_count; /* write a block of data with no smb header */ - unsigned SMBwritebraw_time; - unsigned SMBwriteBmpx_count; /* write block multiplexed */ - unsigned SMBwriteBmpx_time; - unsigned SMBwriteBs_count; /* write block (secondary request) */ - unsigned SMBwriteBs_time; - unsigned SMBwritec_count; /* secondary write request */ - unsigned SMBwritec_time; - unsigned SMBsetattrE_count; /* set file attributes expanded */ - unsigned SMBsetattrE_time; - unsigned SMBgetattrE_count; /* get file attributes expanded */ - unsigned SMBgetattrE_time; - unsigned SMBlockingX_count; /* lock/unlock byte ranges and X */ - unsigned SMBlockingX_time; - unsigned SMBtrans_count; /* transaction - name, bytes in/out */ - unsigned SMBtrans_time; - unsigned SMBtranss_count; /* transaction (secondary request/response) */ - unsigned SMBtranss_time; - unsigned SMBioctl_count; /* IOCTL */ - unsigned SMBioctl_time; - unsigned SMBioctls_count; /* IOCTL (secondary request/response) */ - unsigned SMBioctls_time; - unsigned SMBcopy_count; /* copy */ - unsigned SMBcopy_time; - unsigned SMBmove_count; /* move */ - unsigned SMBmove_time; - unsigned SMBecho_count; /* echo */ - unsigned SMBecho_time; - unsigned SMBwriteclose_count; /* write a file then close it */ - unsigned SMBwriteclose_time; - unsigned SMBopenX_count; /* open and X */ - unsigned SMBopenX_time; - unsigned SMBreadX_count; /* read and X */ - unsigned SMBreadX_time; - unsigned SMBwriteX_count; /* write and X */ - unsigned SMBwriteX_time; - unsigned SMBtrans2_count; /* TRANS2 protocol set */ - unsigned SMBtrans2_time; - unsigned SMBtranss2_count; /* TRANS2 protocol set, secondary command */ - unsigned SMBtranss2_time; - unsigned SMBfindclose_count; /* Terminate a TRANSACT2_FINDFIRST */ - unsigned SMBfindclose_time; - unsigned SMBfindnclose_count; /* Terminate a TRANSACT2_FINDNOTIFYFIRST */ - unsigned SMBfindnclose_time; - unsigned SMBtcon_count; /* tree connect */ - unsigned SMBtcon_time; - unsigned SMBtdis_count; /* tree disconnect */ - unsigned SMBtdis_time; - unsigned SMBnegprot_count; /* negotiate protocol */ - unsigned SMBnegprot_time; - unsigned SMBsesssetupX_count; /* Session Set Up & X (including User Logon) */ - unsigned SMBsesssetupX_time; - unsigned SMBulogoffX_count; /* user logoff */ - unsigned SMBulogoffX_time; - unsigned SMBtconX_count; /* tree connect and X*/ - unsigned SMBtconX_time; - unsigned SMBdskattr_count; /* get disk attributes */ - unsigned SMBdskattr_time; - unsigned SMBsearch_count; /* search directory */ - unsigned SMBsearch_time; - /* SBMffirst stats combined with SMBsearch */ - unsigned SMBffirst_count; /* find first */ - unsigned SMBffirst_time; - /* SBMfunique stats combined with SMBsearch */ - unsigned SMBfunique_count; /* find unique */ - unsigned SMBfunique_time; - unsigned SMBfclose_count; /* find close */ - unsigned SMBfclose_time; - unsigned SMBnttrans_count; /* NT transact */ - unsigned SMBnttrans_time; - unsigned SMBnttranss_count; /* NT transact secondary */ - unsigned SMBnttranss_time; - unsigned SMBntcreateX_count; /* NT create and X */ - unsigned SMBntcreateX_time; - unsigned SMBntcancel_count; /* NT cancel */ - unsigned SMBntcancel_time; - unsigned SMBntrename_count; /* NT rename file */ - unsigned SMBntrename_time; - unsigned SMBsplopen_count; /* open print spool file */ - unsigned SMBsplopen_time; - unsigned SMBsplwr_count; /* write to print spool file */ - unsigned SMBsplwr_time; - unsigned SMBsplclose_count; /* close print spool file */ - unsigned SMBsplclose_time; - unsigned SMBsplretq_count; /* return print queue */ - unsigned SMBsplretq_time; - unsigned SMBsends_count; /* send single block message */ - unsigned SMBsends_time; - unsigned SMBsendb_count; /* send broadcast message */ - unsigned SMBsendb_time; - unsigned SMBfwdname_count; /* forward user name */ - unsigned SMBfwdname_time; - unsigned SMBcancelf_count; /* cancel forward */ - unsigned SMBcancelf_time; - unsigned SMBgetmac_count; /* get machine name */ - unsigned SMBgetmac_time; - unsigned SMBsendstrt_count; /* send start of multi-block message */ - unsigned SMBsendstrt_time; - unsigned SMBsendend_count; /* send end of multi-block message */ - unsigned SMBsendend_time; - unsigned SMBsendtxt_count; /* send text of multi-block message */ - unsigned SMBsendtxt_time; - unsigned SMBinvalid_count; /* invalid command */ - unsigned SMBinvalid_time; -/* Pathworks setdir command */ - unsigned pathworks_setdir_count; - unsigned pathworks_setdir_time; -/* These are the TRANS2 sub commands */ - unsigned Trans2_open_count; - unsigned Trans2_open_time; - unsigned Trans2_findfirst_count; - unsigned Trans2_findfirst_time; - unsigned Trans2_findnext_count; - unsigned Trans2_findnext_time; - unsigned Trans2_qfsinfo_count; - unsigned Trans2_qfsinfo_time; - unsigned Trans2_setfsinfo_count; - unsigned Trans2_setfsinfo_time; - unsigned Trans2_qpathinfo_count; - unsigned Trans2_qpathinfo_time; - unsigned Trans2_setpathinfo_count; - unsigned Trans2_setpathinfo_time; - unsigned Trans2_qfileinfo_count; - unsigned Trans2_qfileinfo_time; - unsigned Trans2_setfileinfo_count; - unsigned Trans2_setfileinfo_time; - unsigned Trans2_fsctl_count; - unsigned Trans2_fsctl_time; - unsigned Trans2_ioctl_count; - unsigned Trans2_ioctl_time; - unsigned Trans2_findnotifyfirst_count; - unsigned Trans2_findnotifyfirst_time; - unsigned Trans2_findnotifynext_count; - unsigned Trans2_findnotifynext_time; - unsigned Trans2_mkdir_count; - unsigned Trans2_mkdir_time; - unsigned Trans2_session_setup_count; - unsigned Trans2_session_setup_time; - unsigned Trans2_get_dfs_referral_count; - unsigned Trans2_get_dfs_referral_time; - unsigned Trans2_report_dfs_inconsistancy_count; - unsigned Trans2_report_dfs_inconsistancy_time; -/* These are the NT transact sub commands. */ - unsigned NT_transact_create_count; - unsigned NT_transact_create_time; - unsigned NT_transact_ioctl_count; - unsigned NT_transact_ioctl_time; - unsigned NT_transact_set_security_desc_count; - unsigned NT_transact_set_security_desc_time; - unsigned NT_transact_notify_change_count; - unsigned NT_transact_notify_change_time; - unsigned NT_transact_rename_count; - unsigned NT_transact_rename_time; - unsigned NT_transact_query_security_desc_count; - unsigned NT_transact_query_security_desc_time; - unsigned NT_transact_get_user_quota_count; - unsigned NT_transact_get_user_quota_time; - unsigned NT_transact_set_user_quota_count; - unsigned NT_transact_set_user_quota_time; -/* These are ACL manipulation calls */ - unsigned get_nt_acl_count; - unsigned get_nt_acl_time; - unsigned fget_nt_acl_count; - unsigned fget_nt_acl_time; - unsigned set_nt_acl_count; - unsigned set_nt_acl_time; - unsigned fset_nt_acl_count; - unsigned fset_nt_acl_time; - unsigned chmod_acl_count; - unsigned chmod_acl_time; - unsigned fchmod_acl_count; - unsigned fchmod_acl_time; -/* These are nmbd stats */ - unsigned name_release_count; - unsigned name_release_time; - unsigned name_refresh_count; - unsigned name_refresh_time; - unsigned name_registration_count; - unsigned name_registration_time; - unsigned node_status_count; - unsigned node_status_time; - unsigned name_query_count; - unsigned name_query_time; - unsigned host_announce_count; - unsigned host_announce_time; - unsigned workgroup_announce_count; - unsigned workgroup_announce_time; - unsigned local_master_announce_count; - unsigned local_master_announce_time; - unsigned master_browser_announce_count; - unsigned master_browser_announce_time; - unsigned lm_host_announce_count; - unsigned lm_host_announce_time; - unsigned get_backup_list_count; - unsigned get_backup_list_time; - unsigned reset_browser_count; - unsigned reset_browser_time; - unsigned announce_request_count; - unsigned announce_request_time; - unsigned lm_announce_request_count; - unsigned lm_announce_request_time; - unsigned domain_logon_count; - unsigned domain_logon_time; - unsigned sync_browse_lists_count; - unsigned sync_browse_lists_time; - unsigned run_elections_count; - unsigned run_elections_time; - unsigned election_count; - unsigned election_time; }; struct profile_header { diff --git a/source/include/talloc.h b/source/include/talloc.h index 17032ac7acc..db88ce6ed56 100644 --- a/source/include/talloc.h +++ b/source/include/talloc.h @@ -114,7 +114,7 @@ void *talloc_parent(const void *ptr); void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); int talloc_free(void *ptr); void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); -void *talloc_steal(const void *new_ctx, const void *ptr); +/* void *talloc_steal(const void *new_ctx, const void *ptr); */ off_t talloc_total_size(const void *ptr); off_t talloc_total_blocks(const void *ptr); void talloc_report_full(const void *ptr, FILE *f); @@ -128,6 +128,7 @@ char *talloc_strdup(const void *t, const char *p); char *talloc_strndup(const void *t, const char *p, size_t n); char *talloc_append_string(const void *t, char *orig, const char *append); char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); diff --git a/source/include/vfs.h b/source/include/vfs.h index fb99d824125..6ef9e829bcc 100644 --- a/source/include/vfs.h +++ b/source/include/vfs.h @@ -62,7 +62,9 @@ /* Changed to version 14 as we had to change DIR to SMB_STRUCT_DIR. JRA */ /* Changed to version 15 as we added the statvfs call. JRA */ /* Changed to version 16 as we added the getlock call. JRA */ -#define SMB_VFS_INTERFACE_VERSION 16 +/* Changed to version 17 as we removed redundant connection_struct parameters. --jpeach */ +/* Changed to version 18 to add fsp parameter to the open call -- jpeach */ +#define SMB_VFS_INTERFACE_VERSION 18 /* to bug old modules which are trying to compile with the old functions */ @@ -219,29 +221,29 @@ struct vfs_ops { struct vfs_fn_pointers { /* Disk operations */ - int (*connect_fn)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *service, const char *user); - void (*disconnect)(struct vfs_handle_struct *handle, struct connection_struct *conn); - SMB_BIG_UINT (*disk_free)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, + int (*connect_fn)(struct vfs_handle_struct *handle, const char *service, const char *user); + void (*disconnect)(struct vfs_handle_struct *handle); + SMB_BIG_UINT (*disk_free)(struct vfs_handle_struct *handle, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); - int (*get_quota)(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt); - int (*set_quota)(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt); + int (*get_quota)(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt); + int (*set_quota)(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt); int (*get_shadow_copy_data)(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels); - int (*statvfs)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, struct vfs_statvfs_struct *statbuf); + int (*statvfs)(struct vfs_handle_struct *handle, const char *path, struct vfs_statvfs_struct *statbuf); /* Directory operations */ - SMB_STRUCT_DIR *(*opendir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, const char *mask, uint32 attributes); - SMB_STRUCT_DIRENT *(*readdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dirp); - void (*seekdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dirp, long offset); - long (*telldir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dirp); - void (*rewind_dir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dirp); - int (*mkdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode); - int (*rmdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path); - int (*closedir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dir); + SMB_STRUCT_DIR *(*opendir)(struct vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attributes); + SMB_STRUCT_DIRENT *(*readdir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp); + void (*seekdir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp, long offset); + long (*telldir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp); + void (*rewind_dir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp); + int (*mkdir)(struct vfs_handle_struct *handle, const char *path, mode_t mode); + int (*rmdir)(struct vfs_handle_struct *handle, const char *path); + int (*closedir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dir); /* File operations */ - int (*open)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, int flags, mode_t mode); + int (*open)(struct vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode); int (*close_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd); ssize_t (*read)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, void *data, size_t n); ssize_t (*pread)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, void *data, size_t n, SMB_OFF_T offset); @@ -249,27 +251,27 @@ struct vfs_ops { ssize_t (*pwrite)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, const void *data, size_t n, SMB_OFF_T offset); SMB_OFF_T (*lseek)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset, int whence); ssize_t (*sendfile)(struct vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count); - int (*rename)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldname, const char *newname); + int (*rename)(struct vfs_handle_struct *handle, const char *oldname, const char *newname); int (*fsync)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd); - int (*stat)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf); + int (*stat)(struct vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf); int (*fstat)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf); - int (*lstat)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf); - int (*unlink)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path); - int (*chmod)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode); + int (*lstat)(struct vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf); + int (*unlink)(struct vfs_handle_struct *handle, const char *path); + int (*chmod)(struct vfs_handle_struct *handle, const char *path, mode_t mode); int (*fchmod)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, mode_t mode); - int (*chown)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, uid_t uid, gid_t gid); + int (*chown)(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid); int (*fchown)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uid_t uid, gid_t gid); - int (*chdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path); - char *(*getwd)(struct vfs_handle_struct *handle, struct connection_struct *conn, char *buf); - int (*utime)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, struct utimbuf *times); + int (*chdir)(struct vfs_handle_struct *handle, const char *path); + char *(*getwd)(struct vfs_handle_struct *handle, char *buf); + int (*utime)(struct vfs_handle_struct *handle, const char *path, struct utimbuf *times); int (*ftruncate)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset); BOOL (*lock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type); BOOL (*getlock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid); - int (*symlink)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldpath, const char *newpath); - int (*readlink)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, char *buf, size_t bufsiz); - int (*link)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldpath, const char *newpath); - int (*mknod)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev); - char *(*realpath)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, char *resolved_path); + int (*symlink)(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath); + int (*readlink)(struct vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz); + int (*link)(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath); + int (*mknod)(struct vfs_handle_struct *handle, const char *path, mode_t mode, SMB_DEV_T dev); + char *(*realpath)(struct vfs_handle_struct *handle, const char *path, char *resolved_path); /* NT ACL operations. */ @@ -280,44 +282,44 @@ struct vfs_ops { /* POSIX ACL operations. */ - int (*chmod_acl)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *name, mode_t mode); + int (*chmod_acl)(struct vfs_handle_struct *handle, const char *name, mode_t mode); int (*fchmod_acl)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, mode_t mode); - int (*sys_acl_get_entry)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p); - int (*sys_acl_get_tag_type)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p); - int (*sys_acl_get_permset)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p); - void * (*sys_acl_get_qualifier)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d); - SMB_ACL_T (*sys_acl_get_file)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type); + int (*sys_acl_get_entry)(struct vfs_handle_struct *handle, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p); + int (*sys_acl_get_tag_type)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p); + int (*sys_acl_get_permset)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p); + void * (*sys_acl_get_qualifier)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d); + SMB_ACL_T (*sys_acl_get_file)(struct vfs_handle_struct *handle, const char *path_p, SMB_ACL_TYPE_T type); SMB_ACL_T (*sys_acl_get_fd)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd); - int (*sys_acl_clear_perms)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_PERMSET_T permset); - int (*sys_acl_add_perm)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm); - char * (*sys_acl_to_text)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen); - SMB_ACL_T (*sys_acl_init)(struct vfs_handle_struct *handle, struct connection_struct *conn, int count); - int (*sys_acl_create_entry)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry); - int (*sys_acl_set_tag_type)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype); - int (*sys_acl_set_qualifier)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual); - int (*sys_acl_set_permset)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset); - int (*sys_acl_valid)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T theacl ); - int (*sys_acl_set_file)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl); + int (*sys_acl_clear_perms)(struct vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset); + int (*sys_acl_add_perm)(struct vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm); + char * (*sys_acl_to_text)(struct vfs_handle_struct *handle, SMB_ACL_T theacl, ssize_t *plen); + SMB_ACL_T (*sys_acl_init)(struct vfs_handle_struct *handle, int count); + int (*sys_acl_create_entry)(struct vfs_handle_struct *handle, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry); + int (*sys_acl_set_tag_type)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype); + int (*sys_acl_set_qualifier)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, void *qual); + int (*sys_acl_set_permset)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset); + int (*sys_acl_valid)(struct vfs_handle_struct *handle, SMB_ACL_T theacl ); + int (*sys_acl_set_file)(struct vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl); int (*sys_acl_set_fd)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_ACL_T theacl); - int (*sys_acl_delete_def_file)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path); - int (*sys_acl_get_perm)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm); - int (*sys_acl_free_text)(struct vfs_handle_struct *handle, struct connection_struct *conn, char *text); - int (*sys_acl_free_acl)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T posix_acl); - int (*sys_acl_free_qualifier)(struct vfs_handle_struct *handle, struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype); + int (*sys_acl_delete_def_file)(struct vfs_handle_struct *handle, const char *path); + int (*sys_acl_get_perm)(struct vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm); + int (*sys_acl_free_text)(struct vfs_handle_struct *handle, char *text); + int (*sys_acl_free_acl)(struct vfs_handle_struct *handle, SMB_ACL_T posix_acl); + int (*sys_acl_free_qualifier)(struct vfs_handle_struct *handle, void *qualifier, SMB_ACL_TAG_T tagtype); /* EA operations. */ - ssize_t (*getxattr)(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size); - ssize_t (*lgetxattr)(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size); + ssize_t (*getxattr)(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size); + ssize_t (*lgetxattr)(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size); ssize_t (*fgetxattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size); - ssize_t (*listxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size); - ssize_t (*llistxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size); + ssize_t (*listxattr)(struct vfs_handle_struct *handle, const char *path, char *list, size_t size); + ssize_t (*llistxattr)(struct vfs_handle_struct *handle, const char *path, char *list, size_t size); ssize_t (*flistxattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size); - int (*removexattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name); - int (*lremovexattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name); + int (*removexattr)(struct vfs_handle_struct *handle, const char *path, const char *name); + int (*lremovexattr)(struct vfs_handle_struct *handle, const char *path, const char *name); int (*fremovexattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int filedes, const char *name); - int (*setxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags); - int (*lsetxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags); + int (*setxattr)(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags); + int (*lsetxattr)(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags); int (*fsetxattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int filedes, const char *name, const void *value, size_t size, int flags); /* aio operations */ @@ -530,6 +532,14 @@ typedef struct vfs_statvfs_struct { /* NB flags can come from FILE_SYSTEM_DEVICE_INFO call */ } vfs_statvfs_struct; +#define VFS_ADD_FSP_EXTENSION(handle, fsp, type) \ + vfs_add_fsp_extension_notype(handle, (fsp), sizeof(type)) + +#define VFS_FETCH_FSP_EXTENSION(handle, fsp) \ + vfs_fetch_fsp_extension(handle, (fsp)) + +#define VFS_REMOVE_FSP_EXTENSION(handle, fsp) \ + vfs_remove_fsp_extension((handle), (fsp)) #define SMB_VFS_HANDLE_GET_DATA(handle, datap, type, ret) { \ if (!(handle)||((datap=(type *)(handle)->data)==NULL)) { \ @@ -562,6 +572,7 @@ typedef struct vfs_statvfs_struct { #define SMB_VFS_OP(x) ((void *) x) +#define DEFAULT_VFS_MODULE_NAME "/[Default VFS]/" #include "vfs_macros.h" diff --git a/source/include/vfs_macros.h b/source/include/vfs_macros.h index e08b386a6ac..2d6f8580f68 100644 --- a/source/include/vfs_macros.h +++ b/source/include/vfs_macros.h @@ -28,26 +28,26 @@ ********************************************************************/ /* Disk operations */ -#define SMB_VFS_CONNECT(conn, service, user) ((conn)->vfs.ops.connect_fn((conn)->vfs.handles.connect_hnd, (conn), (service), (user))) -#define SMB_VFS_DISCONNECT(conn) ((conn)->vfs.ops.disconnect((conn)->vfs.handles.disconnect, (conn))) -#define SMB_VFS_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs.ops.disk_free((conn)->vfs.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize))) -#define SMB_VFS_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.get_quota((conn)->vfs.handles.get_quota, (conn), (qtype), (id), (qt))) -#define SMB_VFS_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.set_quota((conn)->vfs.handles.set_quota, (conn), (qtype), (id), (qt))) +#define SMB_VFS_CONNECT(conn, service, user) ((conn)->vfs.ops.connect_fn((conn)->vfs.handles.connect_hnd, (service), (user))) +#define SMB_VFS_DISCONNECT(conn) ((conn)->vfs.ops.disconnect((conn)->vfs.handles.disconnect)) +#define SMB_VFS_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs.ops.disk_free((conn)->vfs.handles.disk_free, (path), (small_query), (bsize), (dfree), (dsize))) +#define SMB_VFS_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.get_quota((conn)->vfs.handles.get_quota, (qtype), (id), (qt))) +#define SMB_VFS_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.set_quota((conn)->vfs.handles.set_quota, (qtype), (id), (qt))) #define SMB_VFS_GET_SHADOW_COPY_DATA(fsp,shadow_copy_data,labels) ((fsp)->conn->vfs.ops.get_shadow_copy_data((fsp)->conn->vfs.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels))) -#define SMB_VFS_STATVFS(conn, path, statbuf) ((conn)->vfs.ops.statvfs((conn)->vfs.handles.statvfs, (conn), (path), (statbuf))) +#define SMB_VFS_STATVFS(conn, path, statbuf) ((conn)->vfs.ops.statvfs((conn)->vfs.handles.statvfs, (path), (statbuf))) /* Directory operations */ -#define SMB_VFS_OPENDIR(conn, fname, mask, attr) ((conn)->vfs.ops.opendir((conn)->vfs.handles.opendir, (conn), (fname), (mask), (attr))) -#define SMB_VFS_READDIR(conn, dirp) ((conn)->vfs.ops.readdir((conn)->vfs.handles.readdir, (conn), (dirp))) -#define SMB_VFS_SEEKDIR(conn, dirp, offset) ((conn)->vfs.ops.seekdir((conn)->vfs.handles.seekdir, (conn), (dirp), (offset))) -#define SMB_VFS_TELLDIR(conn, dirp) ((conn)->vfs.ops.telldir((conn)->vfs.handles.telldir, (conn), (dirp))) -#define SMB_VFS_REWINDDIR(conn, dirp) ((conn)->vfs.ops.rewind_dir((conn)->vfs.handles.rewind_dir, (conn), (dirp))) -#define SMB_VFS_MKDIR(conn, path, mode) ((conn)->vfs.ops.mkdir((conn)->vfs.handles.mkdir,(conn), (path), (mode))) -#define SMB_VFS_RMDIR(conn, path) ((conn)->vfs.ops.rmdir((conn)->vfs.handles.rmdir, (conn), (path))) -#define SMB_VFS_CLOSEDIR(conn, dir) ((conn)->vfs.ops.closedir((conn)->vfs.handles.closedir, (conn), dir)) +#define SMB_VFS_OPENDIR(conn, fname, mask, attr) ((conn)->vfs.ops.opendir((conn)->vfs.handles.opendir, (fname), (mask), (attr))) +#define SMB_VFS_READDIR(conn, dirp) ((conn)->vfs.ops.readdir((conn)->vfs.handles.readdir, (dirp))) +#define SMB_VFS_SEEKDIR(conn, dirp, offset) ((conn)->vfs.ops.seekdir((conn)->vfs.handles.seekdir, (dirp), (offset))) +#define SMB_VFS_TELLDIR(conn, dirp) ((conn)->vfs.ops.telldir((conn)->vfs.handles.telldir, (dirp))) +#define SMB_VFS_REWINDDIR(conn, dirp) ((conn)->vfs.ops.rewind_dir((conn)->vfs.handles.rewind_dir, (dirp))) +#define SMB_VFS_MKDIR(conn, path, mode) ((conn)->vfs.ops.mkdir((conn)->vfs.handles.mkdir,(path), (mode))) +#define SMB_VFS_RMDIR(conn, path) ((conn)->vfs.ops.rmdir((conn)->vfs.handles.rmdir, (path))) +#define SMB_VFS_CLOSEDIR(conn, dir) ((conn)->vfs.ops.closedir((conn)->vfs.handles.closedir, dir)) /* File operations */ -#define SMB_VFS_OPEN(conn, fname, flags, mode) ((conn)->vfs.ops.open((conn)->vfs.handles.open, (conn), (fname), (flags), (mode))) +#define SMB_VFS_OPEN(conn, fname, fsp, flags, mode) ((conn)->vfs.ops.open((conn)->vfs.handles.open, (fname), (fsp), (flags), (mode))) #define SMB_VFS_CLOSE(fsp, fd) ((fsp)->conn->vfs.ops.close_fn((fsp)->conn->vfs.handles.close_hnd, (fsp), (fd))) #define SMB_VFS_READ(fsp, fd, data, n) ((fsp)->conn->vfs.ops.read((fsp)->conn->vfs.handles.read, (fsp), (fd), (data), (n))) #define SMB_VFS_PREAD(fsp, fd, data, n, off) ((fsp)->conn->vfs.ops.pread((fsp)->conn->vfs.handles.pread, (fsp), (fd), (data), (n), (off))) @@ -55,27 +55,27 @@ #define SMB_VFS_PWRITE(fsp, fd, data, n, off) ((fsp)->conn->vfs.ops.pwrite((fsp)->conn->vfs.handles.pwrite, (fsp), (fd), (data), (n), (off))) #define SMB_VFS_LSEEK(fsp, fd, offset, whence) ((fsp)->conn->vfs.ops.lseek((fsp)->conn->vfs.handles.lseek, (fsp), (fd), (offset), (whence))) #define SMB_VFS_SENDFILE(tofd, fsp, fromfd, header, offset, count) ((fsp)->conn->vfs.ops.sendfile((fsp)->conn->vfs.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count))) -#define SMB_VFS_RENAME(conn, old, new) ((conn)->vfs.ops.rename((conn)->vfs.handles.rename, (conn), (old), (new))) +#define SMB_VFS_RENAME(conn, old, new) ((conn)->vfs.ops.rename((conn)->vfs.handles.rename, (old), (new))) #define SMB_VFS_FSYNC(fsp, fd) ((fsp)->conn->vfs.ops.fsync((fsp)->conn->vfs.handles.fsync, (fsp), (fd))) -#define SMB_VFS_STAT(conn, fname, sbuf) ((conn)->vfs.ops.stat((conn)->vfs.handles.stat, (conn), (fname), (sbuf))) +#define SMB_VFS_STAT(conn, fname, sbuf) ((conn)->vfs.ops.stat((conn)->vfs.handles.stat, (fname), (sbuf))) #define SMB_VFS_FSTAT(fsp, fd, sbuf) ((fsp)->conn->vfs.ops.fstat((fsp)->conn->vfs.handles.fstat, (fsp) ,(fd) ,(sbuf))) -#define SMB_VFS_LSTAT(conn, path, sbuf) ((conn)->vfs.ops.lstat((conn)->vfs.handles.lstat, (conn), (path), (sbuf))) -#define SMB_VFS_UNLINK(conn, path) ((conn)->vfs.ops.unlink((conn)->vfs.handles.unlink, (conn), (path))) -#define SMB_VFS_CHMOD(conn, path, mode) ((conn)->vfs.ops.chmod((conn)->vfs.handles.chmod, (conn), (path), (mode))) +#define SMB_VFS_LSTAT(conn, path, sbuf) ((conn)->vfs.ops.lstat((conn)->vfs.handles.lstat, (path), (sbuf))) +#define SMB_VFS_UNLINK(conn, path) ((conn)->vfs.ops.unlink((conn)->vfs.handles.unlink, (path))) +#define SMB_VFS_CHMOD(conn, path, mode) ((conn)->vfs.ops.chmod((conn)->vfs.handles.chmod, (path), (mode))) #define SMB_VFS_FCHMOD(fsp, fd, mode) ((fsp)->conn->vfs.ops.fchmod((fsp)->conn->vfs.handles.fchmod, (fsp), (fd), (mode))) -#define SMB_VFS_CHOWN(conn, path, uid, gid) ((conn)->vfs.ops.chown((conn)->vfs.handles.chown, (conn), (path), (uid), (gid))) +#define SMB_VFS_CHOWN(conn, path, uid, gid) ((conn)->vfs.ops.chown((conn)->vfs.handles.chown, (path), (uid), (gid))) #define SMB_VFS_FCHOWN(fsp, fd, uid, gid) ((fsp)->conn->vfs.ops.fchown((fsp)->conn->vfs.handles.fchown, (fsp), (fd), (uid), (gid))) -#define SMB_VFS_CHDIR(conn, path) ((conn)->vfs.ops.chdir((conn)->vfs.handles.chdir, (conn), (path))) -#define SMB_VFS_GETWD(conn, buf) ((conn)->vfs.ops.getwd((conn)->vfs.handles.getwd, (conn), (buf))) -#define SMB_VFS_UTIME(conn, path, times) ((conn)->vfs.ops.utime((conn)->vfs.handles.utime, (conn), (path), (times))) +#define SMB_VFS_CHDIR(conn, path) ((conn)->vfs.ops.chdir((conn)->vfs.handles.chdir, (path))) +#define SMB_VFS_GETWD(conn, buf) ((conn)->vfs.ops.getwd((conn)->vfs.handles.getwd, (buf))) +#define SMB_VFS_UTIME(conn, path, times) ((conn)->vfs.ops.utime((conn)->vfs.handles.utime, (path), (times))) #define SMB_VFS_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs.ops.ftruncate((fsp)->conn->vfs.handles.ftruncate, (fsp), (fd), (offset))) #define SMB_VFS_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs.ops.lock((fsp)->conn->vfs.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type))) #define SMB_VFS_GETLOCK(fsp, fd, poffset, pcount, ptype, ppid) ((fsp)->conn->vfs.ops.getlock((fsp)->conn->vfs.handles.getlock, (fsp), (fd) ,(poffset), (pcount), (ptype), (ppid))) -#define SMB_VFS_SYMLINK(conn, oldpath, newpath) ((conn)->vfs.ops.symlink((conn)->vfs.handles.symlink, (conn), (oldpath), (newpath))) -#define SMB_VFS_READLINK(conn, path, buf, bufsiz) ((conn)->vfs.ops.readlink((conn)->vfs.handles.readlink, (conn), (path), (buf), (bufsiz))) -#define SMB_VFS_LINK(conn, oldpath, newpath) ((conn)->vfs.ops.link((conn)->vfs.handles.link, (conn), (oldpath), (newpath))) -#define SMB_VFS_MKNOD(conn, path, mode, dev) ((conn)->vfs.ops.mknod((conn)->vfs.handles.mknod, (conn), (path), (mode), (dev))) -#define SMB_VFS_REALPATH(conn, path, resolved_path) ((conn)->vfs.ops.realpath((conn)->vfs.handles.realpath, (conn), (path), (resolved_path))) +#define SMB_VFS_SYMLINK(conn, oldpath, newpath) ((conn)->vfs.ops.symlink((conn)->vfs.handles.symlink, (oldpath), (newpath))) +#define SMB_VFS_READLINK(conn, path, buf, bufsiz) ((conn)->vfs.ops.readlink((conn)->vfs.handles.readlink, (path), (buf), (bufsiz))) +#define SMB_VFS_LINK(conn, oldpath, newpath) ((conn)->vfs.ops.link((conn)->vfs.handles.link, (oldpath), (newpath))) +#define SMB_VFS_MKNOD(conn, path, mode, dev) ((conn)->vfs.ops.mknod((conn)->vfs.handles.mknod, (path), (mode), (dev))) +#define SMB_VFS_REALPATH(conn, path, resolved_path) ((conn)->vfs.ops.realpath((conn)->vfs.handles.realpath, (path), (resolved_path))) /* NT ACL operations. */ #define SMB_VFS_FGET_NT_ACL(fsp, fd, security_info, ppdesc) ((fsp)->conn->vfs.ops.fget_nt_acl((fsp)->conn->vfs.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc))) @@ -84,44 +84,44 @@ #define SMB_VFS_SET_NT_ACL(fsp, name, security_info_sent, psd) ((fsp)->conn->vfs.ops.set_nt_acl((fsp)->conn->vfs.handles.set_nt_acl, (fsp), (name), (security_info_sent), (psd))) /* POSIX ACL operations. */ -#define SMB_VFS_CHMOD_ACL(conn, name, mode) ((conn)->vfs.ops.chmod_acl((conn)->vfs.handles.chmod_acl, (conn), (name), (mode))) +#define SMB_VFS_CHMOD_ACL(conn, name, mode) ((conn)->vfs.ops.chmod_acl((conn)->vfs.handles.chmod_acl, (name), (mode))) #define SMB_VFS_FCHMOD_ACL(fsp, fd, mode) ((fsp)->conn->vfs.ops.fchmod_acl((fsp)->conn->vfs.handles.chmod_acl, (fsp), (fd), (mode))) -#define SMB_VFS_SYS_ACL_GET_ENTRY(conn, theacl, entry_id, entry_p) ((conn)->vfs.ops.sys_acl_get_entry((conn)->vfs.handles.sys_acl_get_entry, (conn), (theacl), (entry_id), (entry_p))) -#define SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry_d, tag_type_p) ((conn)->vfs.ops.sys_acl_get_tag_type((conn)->vfs.handles.sys_acl_get_tag_type, (conn), (entry_d), (tag_type_p))) -#define SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry_d, permset_p) ((conn)->vfs.ops.sys_acl_get_permset((conn)->vfs.handles.sys_acl_get_permset, (conn), (entry_d), (permset_p))) -#define SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry_d) ((conn)->vfs.ops.sys_acl_get_qualifier((conn)->vfs.handles.sys_acl_get_qualifier, (conn), (entry_d))) -#define SMB_VFS_SYS_ACL_GET_FILE(conn, path_p, type) ((conn)->vfs.ops.sys_acl_get_file((conn)->vfs.handles.sys_acl_get_file, (conn), (path_p), (type))) +#define SMB_VFS_SYS_ACL_GET_ENTRY(conn, theacl, entry_id, entry_p) ((conn)->vfs.ops.sys_acl_get_entry((conn)->vfs.handles.sys_acl_get_entry, (theacl), (entry_id), (entry_p))) +#define SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry_d, tag_type_p) ((conn)->vfs.ops.sys_acl_get_tag_type((conn)->vfs.handles.sys_acl_get_tag_type, (entry_d), (tag_type_p))) +#define SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry_d, permset_p) ((conn)->vfs.ops.sys_acl_get_permset((conn)->vfs.handles.sys_acl_get_permset, (entry_d), (permset_p))) +#define SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry_d) ((conn)->vfs.ops.sys_acl_get_qualifier((conn)->vfs.handles.sys_acl_get_qualifier, (entry_d))) +#define SMB_VFS_SYS_ACL_GET_FILE(conn, path_p, type) ((conn)->vfs.ops.sys_acl_get_file((conn)->vfs.handles.sys_acl_get_file, (path_p), (type))) #define SMB_VFS_SYS_ACL_GET_FD(fsp, fd) ((fsp)->conn->vfs.ops.sys_acl_get_fd((fsp)->conn->vfs.handles.sys_acl_get_fd, (fsp), (fd))) -#define SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, permset) ((conn)->vfs.ops.sys_acl_clear_perms((conn)->vfs.handles.sys_acl_clear_perms, (conn), (permset))) -#define SMB_VFS_SYS_ACL_ADD_PERM(conn, permset, perm) ((conn)->vfs.ops.sys_acl_add_perm((conn)->vfs.handles.sys_acl_add_perm, (conn), (permset), (perm))) -#define SMB_VFS_SYS_ACL_TO_TEXT(conn, theacl, plen) ((conn)->vfs.ops.sys_acl_to_text((conn)->vfs.handles.sys_acl_to_text, (conn), (theacl), (plen))) -#define SMB_VFS_SYS_ACL_INIT(conn, count) ((conn)->vfs.ops.sys_acl_init((conn)->vfs.handles.sys_acl_init, (conn), (count))) -#define SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, pacl, pentry) ((conn)->vfs.ops.sys_acl_create_entry((conn)->vfs.handles.sys_acl_create_entry, (conn), (pacl), (pentry))) -#define SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, entry, tagtype) ((conn)->vfs.ops.sys_acl_set_tag_type((conn)->vfs.handles.sys_acl_set_tag_type, (conn), (entry), (tagtype))) -#define SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, entry, qual) ((conn)->vfs.ops.sys_acl_set_qualifier((conn)->vfs.handles.sys_acl_set_qualifier, (conn), (entry), (qual))) -#define SMB_VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) ((conn)->vfs.ops.sys_acl_set_permset((conn)->vfs.handles.sys_acl_set_permset, (conn), (entry), (permset))) -#define SMB_VFS_SYS_ACL_VALID(conn, theacl) ((conn)->vfs.ops.sys_acl_valid((conn)->vfs.handles.sys_acl_valid, (conn), (theacl))) -#define SMB_VFS_SYS_ACL_SET_FILE(conn, name, acltype, theacl) ((conn)->vfs.ops.sys_acl_set_file((conn)->vfs.handles.sys_acl_set_file, (conn), (name), (acltype), (theacl))) +#define SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, permset) ((conn)->vfs.ops.sys_acl_clear_perms((conn)->vfs.handles.sys_acl_clear_perms, (permset))) +#define SMB_VFS_SYS_ACL_ADD_PERM(conn, permset, perm) ((conn)->vfs.ops.sys_acl_add_perm((conn)->vfs.handles.sys_acl_add_perm, (permset), (perm))) +#define SMB_VFS_SYS_ACL_TO_TEXT(conn, theacl, plen) ((conn)->vfs.ops.sys_acl_to_text((conn)->vfs.handles.sys_acl_to_text, (theacl), (plen))) +#define SMB_VFS_SYS_ACL_INIT(conn, count) ((conn)->vfs.ops.sys_acl_init((conn)->vfs.handles.sys_acl_init, (count))) +#define SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, pacl, pentry) ((conn)->vfs.ops.sys_acl_create_entry((conn)->vfs.handles.sys_acl_create_entry, (pacl), (pentry))) +#define SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, entry, tagtype) ((conn)->vfs.ops.sys_acl_set_tag_type((conn)->vfs.handles.sys_acl_set_tag_type, (entry), (tagtype))) +#define SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, entry, qual) ((conn)->vfs.ops.sys_acl_set_qualifier((conn)->vfs.handles.sys_acl_set_qualifier, (entry), (qual))) +#define SMB_VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) ((conn)->vfs.ops.sys_acl_set_permset((conn)->vfs.handles.sys_acl_set_permset, (entry), (permset))) +#define SMB_VFS_SYS_ACL_VALID(conn, theacl) ((conn)->vfs.ops.sys_acl_valid((conn)->vfs.handles.sys_acl_valid, (theacl))) +#define SMB_VFS_SYS_ACL_SET_FILE(conn, name, acltype, theacl) ((conn)->vfs.ops.sys_acl_set_file((conn)->vfs.handles.sys_acl_set_file, (name), (acltype), (theacl))) #define SMB_VFS_SYS_ACL_SET_FD(fsp, fd, theacl) ((fsp)->conn->vfs.ops.sys_acl_set_fd((fsp)->conn->vfs.handles.sys_acl_set_fd, (fsp), (fd), (theacl))) -#define SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, path) ((conn)->vfs.ops.sys_acl_delete_def_file((conn)->vfs.handles.sys_acl_delete_def_file, (conn), (path))) -#define SMB_VFS_SYS_ACL_GET_PERM(conn, permset, perm) ((conn)->vfs.ops.sys_acl_get_perm((conn)->vfs.handles.sys_acl_get_perm, (conn), (permset), (perm))) -#define SMB_VFS_SYS_ACL_FREE_TEXT(conn, text) ((conn)->vfs.ops.sys_acl_free_text((conn)->vfs.handles.sys_acl_free_text, (conn), (text))) -#define SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl) ((conn)->vfs.ops.sys_acl_free_acl((conn)->vfs.handles.sys_acl_free_acl, (conn), (posix_acl))) -#define SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, qualifier, tagtype) ((conn)->vfs.ops.sys_acl_free_qualifier((conn)->vfs.handles.sys_acl_free_qualifier, (conn), (qualifier), (tagtype))) +#define SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, path) ((conn)->vfs.ops.sys_acl_delete_def_file((conn)->vfs.handles.sys_acl_delete_def_file, (path))) +#define SMB_VFS_SYS_ACL_GET_PERM(conn, permset, perm) ((conn)->vfs.ops.sys_acl_get_perm((conn)->vfs.handles.sys_acl_get_perm, (permset), (perm))) +#define SMB_VFS_SYS_ACL_FREE_TEXT(conn, text) ((conn)->vfs.ops.sys_acl_free_text((conn)->vfs.handles.sys_acl_free_text, (text))) +#define SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl) ((conn)->vfs.ops.sys_acl_free_acl((conn)->vfs.handles.sys_acl_free_acl, (posix_acl))) +#define SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, qualifier, tagtype) ((conn)->vfs.ops.sys_acl_free_qualifier((conn)->vfs.handles.sys_acl_free_qualifier, (qualifier), (tagtype))) /* EA operations. */ -#define SMB_VFS_GETXATTR(conn,path,name,value,size) ((conn)->vfs.ops.getxattr((conn)->vfs.handles.getxattr,(conn),(path),(name),(value),(size))) -#define SMB_VFS_LGETXATTR(conn,path,name,value,size) ((conn)->vfs.ops.lgetxattr((conn)->vfs.handles.lgetxattr,(conn),(path),(name),(value),(size))) +#define SMB_VFS_GETXATTR(conn,path,name,value,size) ((conn)->vfs.ops.getxattr((conn)->vfs.handles.getxattr,(path),(name),(value),(size))) +#define SMB_VFS_LGETXATTR(conn,path,name,value,size) ((conn)->vfs.ops.lgetxattr((conn)->vfs.handles.lgetxattr,(path),(name),(value),(size))) #define SMB_VFS_FGETXATTR(fsp,fd,name,value,size) ((fsp)->conn->vfs.ops.fgetxattr((fsp)->conn->vfs.handles.fgetxattr,(fsp),(fd),(name),(value),(size))) -#define SMB_VFS_LISTXATTR(conn,path,list,size) ((conn)->vfs.ops.listxattr((conn)->vfs.handles.listxattr,(conn),(path),(list),(size))) -#define SMB_VFS_LLISTXATTR(conn,path,list,size) ((conn)->vfs.ops.llistxattr((conn)->vfs.handles.llistxattr,(conn),(path),(list),(size))) +#define SMB_VFS_LISTXATTR(conn,path,list,size) ((conn)->vfs.ops.listxattr((conn)->vfs.handles.listxattr,(path),(list),(size))) +#define SMB_VFS_LLISTXATTR(conn,path,list,size) ((conn)->vfs.ops.llistxattr((conn)->vfs.handles.llistxattr,(path),(list),(size))) #define SMB_VFS_FLISTXATTR(fsp,fd,list,size) ((fsp)->conn->vfs.ops.flistxattr((fsp)->conn->vfs.handles.flistxattr,(fsp),(fd),(list),(size))) -#define SMB_VFS_REMOVEXATTR(conn,path,name) ((conn)->vfs.ops.removexattr((conn)->vfs.handles.removexattr,(conn),(path),(name))) -#define SMB_VFS_LREMOVEXATTR(conn,path,name) ((conn)->vfs.ops.lremovexattr((conn)->vfs.handles.lremovexattr,(conn),(path),(name))) +#define SMB_VFS_REMOVEXATTR(conn,path,name) ((conn)->vfs.ops.removexattr((conn)->vfs.handles.removexattr,(path),(name))) +#define SMB_VFS_LREMOVEXATTR(conn,path,name) ((conn)->vfs.ops.lremovexattr((conn)->vfs.handles.lremovexattr,(path),(name))) #define SMB_VFS_FREMOVEXATTR(fsp,fd,name) ((fsp)->conn->vfs.ops.fremovexattr((fsp)->conn->vfs.handles.fremovexattr,(fsp),(fd),(name))) -#define SMB_VFS_SETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.setxattr((conn)->vfs.handles.setxattr,(conn),(path),(name),(value),(size),(flags))) -#define SMB_VFS_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.lsetxattr((conn)->vfs.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags))) +#define SMB_VFS_SETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.setxattr((conn)->vfs.handles.setxattr,(path),(name),(value),(size),(flags))) +#define SMB_VFS_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.lsetxattr((conn)->vfs.handles.lsetxattr,(path),(name),(value),(size),(flags))) #define SMB_VFS_FSETXATTR(fsp,fd,name,value,size,flags) ((fsp)->conn->vfs.ops.fsetxattr((fsp)->conn->vfs.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags))) /* AIO operations. */ @@ -140,26 +140,26 @@ ********************************************************************/ /* Disk operations */ -#define SMB_VFS_OPAQUE_CONNECT(conn, service, user) ((conn)->vfs_opaque.ops.connect_fn((conn)->vfs_opaque.handles.connect_hnd, (conn), (service), (user))) -#define SMB_VFS_OPAQUE_DISCONNECT(conn) ((conn)->vfs_opaque.ops.disconnect((conn)->vfs_opaque.handles.disconnect, (conn))) -#define SMB_VFS_OPAQUE_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs_opaque.ops.disk_free((conn)->vfs_opaque.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize))) -#define SMB_VFS_OPAQUE_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.get_quota((conn)->vfs_opaque.handles.get_quota, (conn), (qtype), (id), (qt))) -#define SMB_VFS_OPAQUE_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.set_quota((conn)->vfs_opaque.handles.set_quota, (conn), (qtype), (id), (qt))) +#define SMB_VFS_OPAQUE_CONNECT(conn, service, user) ((conn)->vfs_opaque.ops.connect_fn((conn)->vfs_opaque.handles.connect_hnd, (service), (user))) +#define SMB_VFS_OPAQUE_DISCONNECT(conn) ((conn)->vfs_opaque.ops.disconnect((conn)->vfs_opaque.handles.disconnect)) +#define SMB_VFS_OPAQUE_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs_opaque.ops.disk_free((conn)->vfs_opaque.handles.disk_free, (path), (small_query), (bsize), (dfree), (dsize))) +#define SMB_VFS_OPAQUE_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.get_quota((conn)->vfs_opaque.handles.get_quota, (qtype), (id), (qt))) +#define SMB_VFS_OPAQUE_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.set_quota((conn)->vfs_opaque.handles.set_quota, (qtype), (id), (qt))) #define SMB_VFS_OPAQUE_GET_SHADOW_COPY_DATA(fsp,shadow_copy_data,labels) ((fsp)->conn->vfs_opaque.ops.get_shadow_copy_data((fsp)->conn->vfs_opaque.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels))) -#define SMB_VFS_OPAQUE_STATVFS(conn, path, statbuf) ((conn)->vfs_opaque.ops.statvfs((conn)->vfs_opaque.handles.statvfs, (conn), (path), (statbuf))) +#define SMB_VFS_OPAQUE_STATVFS(conn, path, statbuf) ((conn)->vfs_opaque.ops.statvfs((conn)->vfs_opaque.handles.statvfs, (path), (statbuf))) /* Directory operations */ -#define SMB_VFS_OPAQUE_OPENDIR(conn, fname, mask, attr) ((conn)->vfs_opaque.ops.opendir((conn)->vfs_opaque.handles.opendir, (conn), (fname), (mask), (attr))) -#define SMB_VFS_OPAQUE_READDIR(conn, dirp) ((conn)->vfs_opaque.ops.readdir((conn)->vfs_opaque.handles.readdir, (conn), (dirp))) -#define SMB_VFS_OPAQUE_SEEKDIR(conn, dirp, offset) ((conn)->vfs_opaque.ops.seekdir((conn)->vfs_opaque.handles.seekdir, (conn), (dirp), (offset))) -#define SMB_VFS_OPAQUE_TELLDIR(conn, dirp) ((conn)->vfs_opaque.ops.telldir((conn)->vfs_opaque.handles.telldir, (conn), (dirp))) -#define SMB_VFS_OPAQUE_REWINDDIR(conn, dirp) ((conn)->vfs_opaque.ops.rewind_dir((conn)->vfs_opaque.handles.rewind_dir, (conn), (dirp))) -#define SMB_VFS_OPAQUE_MKDIR(conn, path, mode) ((conn)->vfs_opaque.ops.mkdir((conn)->vfs_opaque.handles.mkdir,(conn), (path), (mode))) -#define SMB_VFS_OPAQUE_RMDIR(conn, path) ((conn)->vfs_opaque.ops.rmdir((conn)->vfs_opaque.handles.rmdir, (conn), (path))) -#define SMB_VFS_OPAQUE_CLOSEDIR(conn, dir) ((conn)->vfs_opaque.ops.closedir((conn)->vfs_opaque.handles.closedir, (conn), dir)) +#define SMB_VFS_OPAQUE_OPENDIR(conn, fname, mask, attr) ((conn)->vfs_opaque.ops.opendir((conn)->vfs_opaque.handles.opendir, (fname), (mask), (attr))) +#define SMB_VFS_OPAQUE_READDIR(conn, dirp) ((conn)->vfs_opaque.ops.readdir((conn)->vfs_opaque.handles.readdir, (dirp))) +#define SMB_VFS_OPAQUE_SEEKDIR(conn, dirp, offset) ((conn)->vfs_opaque.ops.seekdir((conn)->vfs_opaque.handles.seekdir, (dirp), (offset))) +#define SMB_VFS_OPAQUE_TELLDIR(conn, dirp) ((conn)->vfs_opaque.ops.telldir((conn)->vfs_opaque.handles.telldir, (dirp))) +#define SMB_VFS_OPAQUE_REWINDDIR(conn, dirp) ((conn)->vfs_opaque.ops.rewind_dir((conn)->vfs_opaque.handles.rewind_dir, (dirp))) +#define SMB_VFS_OPAQUE_MKDIR(conn, path, mode) ((conn)->vfs_opaque.ops.mkdir((conn)->vfs_opaque.handles.mkdir,(path), (mode))) +#define SMB_VFS_OPAQUE_RMDIR(conn, path) ((conn)->vfs_opaque.ops.rmdir((conn)->vfs_opaque.handles.rmdir, (path))) +#define SMB_VFS_OPAQUE_CLOSEDIR(conn, dir) ((conn)->vfs_opaque.ops.closedir((conn)->vfs_opaque.handles.closedir, dir)) /* File operations */ -#define SMB_VFS_OPAQUE_OPEN(conn, fname, flags, mode) ((conn)->vfs_opaque.ops.open((conn)->vfs_opaque.handles.open, (conn), (fname), (flags), (mode))) +#define SMB_VFS_OPAQUE_OPEN(conn, fname, fsp, flags, mode) ((conn)->vfs_opaque.ops.open((conn)->vfs_opaque.handles.open, (fname), (fsp), (flags), (mode))) #define SMB_VFS_OPAQUE_CLOSE(fsp, fd) ((fsp)->conn->vfs_opaque.ops.close_fn((fsp)->conn->vfs_opaque.handles.close_hnd, (fsp), (fd))) #define SMB_VFS_OPAQUE_READ(fsp, fd, data, n) ((fsp)->conn->vfs_opaque.ops.read((fsp)->conn->vfs_opaque.handles.read, (fsp), (fd), (data), (n))) #define SMB_VFS_OPAQUE_PREAD(fsp, fd, data, n, off) ((fsp)->conn->vfs_opaque.ops.pread((fsp)->conn->vfs_opaque.handles.pread, (fsp), (fd), (data), (n), (off))) @@ -167,27 +167,27 @@ #define SMB_VFS_OPAQUE_PWRITE(fsp, fd, data, n, off) ((fsp)->conn->vfs_opaque.ops.pwrite((fsp)->conn->vfs_opaque.handles.pwrite, (fsp), (fd), (data), (n), (off))) #define SMB_VFS_OPAQUE_LSEEK(fsp, fd, offset, whence) ((fsp)->conn->vfs_opaque.ops.lseek((fsp)->conn->vfs_opaque.handles.lseek, (fsp), (fd), (offset), (whence))) #define SMB_VFS_OPAQUE_SENDFILE(tofd, fsp, fromfd, header, offset, count) ((fsp)->conn->vfs_opaque.ops.sendfile((fsp)->conn->vfs_opaque.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count))) -#define SMB_VFS_OPAQUE_RENAME(conn, old, new) ((conn)->vfs_opaque.ops.rename((conn)->vfs_opaque.handles.rename, (conn), (old), (new))) +#define SMB_VFS_OPAQUE_RENAME(conn, old, new) ((conn)->vfs_opaque.ops.rename((conn)->vfs_opaque.handles.rename, (old), (new))) #define SMB_VFS_OPAQUE_FSYNC(fsp, fd) ((fsp)->conn->vfs_opaque.ops.fsync((fsp)->conn->vfs_opaque.handles.fsync, (fsp), (fd))) -#define SMB_VFS_OPAQUE_STAT(conn, fname, sbuf) ((conn)->vfs_opaque.ops.stat((conn)->vfs_opaque.handles.stat, (conn), (fname), (sbuf))) +#define SMB_VFS_OPAQUE_STAT(conn, fname, sbuf) ((conn)->vfs_opaque.ops.stat((conn)->vfs_opaque.handles.stat, (fname), (sbuf))) #define SMB_VFS_OPAQUE_FSTAT(fsp, fd, sbuf) ((fsp)->conn->vfs_opaque.ops.fstat((fsp)->conn->vfs_opaque.handles.fstat, (fsp) ,(fd) ,(sbuf))) -#define SMB_VFS_OPAQUE_LSTAT(conn, path, sbuf) ((conn)->vfs_opaque.ops.lstat((conn)->vfs_opaque.handles.lstat, (conn), (path), (sbuf))) -#define SMB_VFS_OPAQUE_UNLINK(conn, path) ((conn)->vfs_opaque.ops.unlink((conn)->vfs_opaque.handles.unlink, (conn), (path))) -#define SMB_VFS_OPAQUE_CHMOD(conn, path, mode) ((conn)->vfs_opaque.ops.chmod((conn)->vfs_opaque.handles.chmod, (conn), (path), (mode))) +#define SMB_VFS_OPAQUE_LSTAT(conn, path, sbuf) ((conn)->vfs_opaque.ops.lstat((conn)->vfs_opaque.handles.lstat, (path), (sbuf))) +#define SMB_VFS_OPAQUE_UNLINK(conn, path) ((conn)->vfs_opaque.ops.unlink((conn)->vfs_opaque.handles.unlink, (path))) +#define SMB_VFS_OPAQUE_CHMOD(conn, path, mode) ((conn)->vfs_opaque.ops.chmod((conn)->vfs_opaque.handles.chmod, (path), (mode))) #define SMB_VFS_OPAQUE_FCHMOD(fsp, fd, mode) ((fsp)->conn->vfs_opaque.ops.fchmod((fsp)->conn->vfs_opaque.handles.fchmod, (fsp), (fd), (mode))) -#define SMB_VFS_OPAQUE_CHOWN(conn, path, uid, gid) ((conn)->vfs_opaque.ops.chown((conn)->vfs_opaque.handles.chown, (conn), (path), (uid), (gid))) +#define SMB_VFS_OPAQUE_CHOWN(conn, path, uid, gid) ((conn)->vfs_opaque.ops.chown((conn)->vfs_opaque.handles.chown, (path), (uid), (gid))) #define SMB_VFS_OPAQUE_FCHOWN(fsp, fd, uid, gid) ((fsp)->conn->vfs_opaque.ops.fchown((fsp)->conn->vfs_opaque.handles.fchown, (fsp), (fd), (uid), (gid))) -#define SMB_VFS_OPAQUE_CHDIR(conn, path) ((conn)->vfs_opaque.ops.chdir((conn)->vfs_opaque.handles.chdir, (conn), (path))) -#define SMB_VFS_OPAQUE_GETWD(conn, buf) ((conn)->vfs_opaque.ops.getwd((conn)->vfs_opaque.handles.getwd, (conn), (buf))) -#define SMB_VFS_OPAQUE_UTIME(conn, path, times) ((conn)->vfs_opaque.ops.utime((conn)->vfs_opaque.handles.utime, (conn), (path), (times))) +#define SMB_VFS_OPAQUE_CHDIR(conn, path) ((conn)->vfs_opaque.ops.chdir((conn)->vfs_opaque.handles.chdir, (path))) +#define SMB_VFS_OPAQUE_GETWD(conn, buf) ((conn)->vfs_opaque.ops.getwd((conn)->vfs_opaque.handles.getwd, (buf))) +#define SMB_VFS_OPAQUE_UTIME(conn, path, times) ((conn)->vfs_opaque.ops.utime((conn)->vfs_opaque.handles.utime, (path), (times))) #define SMB_VFS_OPAQUE_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs_opaque.ops.ftruncate((fsp)->conn->vfs_opaque.handles.ftruncate, (fsp), (fd), (offset))) #define SMB_VFS_OPAQUE_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type))) #define SMB_VFS_OPAQUE_GETLOCK(fsp, fd, poffset, pcount, ptype, ppid) ((fsp)->conn->vfs_opaque.ops.getlock((fsp)->conn->vfs_opaque.handles.getlock, (fsp), (fd), (poffset), (pcount), (ptype), (ppid))) -#define SMB_VFS_OPAQUE_SYMLINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.symlink((conn)->vfs_opaque.handles.symlink, (conn), (oldpath), (newpath))) -#define SMB_VFS_OPAQUE_READLINK(conn, path, buf, bufsiz) ((conn)->vfs_opaque.ops.readlink((conn)->vfs_opaque.handles.readlink, (conn), (path), (buf), (bufsiz))) -#define SMB_VFS_OPAQUE_LINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.link((conn)->vfs_opaque.handles.link, (conn), (oldpath), (newpath))) -#define SMB_VFS_OPAQUE_MKNOD(conn, path, mode, dev) ((conn)->vfs_opaque.ops.mknod((conn)->vfs_opaque.handles.mknod, (conn), (path), (mode), (dev))) -#define SMB_VFS_OPAQUE_REALPATH(conn, path, resolved_path) ((conn)->vfs_opaque.ops.realpath((conn)->vfs_opaque.handles.realpath, (conn), (path), (resolved_path))) +#define SMB_VFS_OPAQUE_SYMLINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.symlink((conn)->vfs_opaque.handles.symlink, (oldpath), (newpath))) +#define SMB_VFS_OPAQUE_READLINK(conn, path, buf, bufsiz) ((conn)->vfs_opaque.ops.readlink((conn)->vfs_opaque.handles.readlink, (path), (buf), (bufsiz))) +#define SMB_VFS_OPAQUE_LINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.link((conn)->vfs_opaque.handles.link, (oldpath), (newpath))) +#define SMB_VFS_OPAQUE_MKNOD(conn, path, mode, dev) ((conn)->vfs_opaque.ops.mknod((conn)->vfs_opaque.handles.mknod, (path), (mode), (dev))) +#define SMB_VFS_OPAQUE_REALPATH(conn, path, resolved_path) ((conn)->vfs_opaque.ops.realpath((conn)->vfs_opaque.handles.realpath, (path), (resolved_path))) /* NT ACL operations. */ #define SMB_VFS_OPAQUE_FGET_NT_ACL(fsp, fd, security_info, ppdesc) ((fsp)->conn->vfs_opaque.ops.fget_nt_acl((fsp)->conn->vfs_opaque.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc))) @@ -196,44 +196,44 @@ #define SMB_VFS_OPAQUE_SET_NT_ACL(fsp, name, security_info_sent, psd) ((fsp)->conn->vfs_opaque.ops.set_nt_acl((fsp)->conn->vfs_opaque.handles.set_nt_acl, (fsp), (name), (security_info_sent), (psd))) /* POSIX ACL operations. */ -#define SMB_VFS_OPAQUE_CHMOD_ACL(conn, name, mode) ((conn)->vfs_opaque.ops.chmod_acl((conn)->vfs_opaque.handles.chmod_acl, (conn), (name), (mode))) +#define SMB_VFS_OPAQUE_CHMOD_ACL(conn, name, mode) ((conn)->vfs_opaque.ops.chmod_acl((conn)->vfs_opaque.handles.chmod_acl, (name), (mode))) #define SMB_VFS_OPAQUE_FCHMOD_ACL(fsp, fd, mode) ((fsp)->conn->vfs_opaque.ops.fchmod_acl((fsp)->conn->vfs_opaque.handles.chmod_acl, (fsp), (fd), (mode))) -#define SMB_VFS_OPAQUE_SYS_ACL_GET_ENTRY(conn, theacl, entry_id, entry_p) ((conn)->vfs_opaque.ops.sys_acl_get_entry((conn)->vfs_opaque.handles.sys_acl_get_entry, (conn), (theacl), (entry_id), (entry_p))) -#define SMB_VFS_OPAQUE_SYS_ACL_GET_TAG_TYPE(conn, entry_d, tag_type_p) ((conn)->vfs_opaque.ops.sys_acl_get_tag_type((conn)->vfs_opaque.handles.sys_acl_get_tag_type, (conn), (entry_d), (tag_type_p))) -#define SMB_VFS_OPAQUE_SYS_ACL_GET_PERMSET(conn, entry_d, permset_p) ((conn)->vfs_opaque.ops.sys_acl_get_permset((conn)->vfs_opaque.handles.sys_acl_get_permset, (conn), (entry_d), (permset_p))) -#define SMB_VFS_OPAQUE_SYS_ACL_GET_QUALIFIER(conn, entry_d) ((conn)->vfs_opaque.ops.sys_acl_get_qualifier((conn)->vfs_opaque.handles.sys_acl_get_qualifier, (conn), (entry_d))) -#define SMB_VFS_OPAQUE_SYS_ACL_GET_FILE(conn, path_p, type) ((conn)->vfs_opaque.ops.sys_acl_get_file((conn)->vfs_opaque.handles.sys_acl_get_file, (conn), (path_p), (type))) +#define SMB_VFS_OPAQUE_SYS_ACL_GET_ENTRY(conn, theacl, entry_id, entry_p) ((conn)->vfs_opaque.ops.sys_acl_get_entry((conn)->vfs_opaque.handles.sys_acl_get_entry, (theacl), (entry_id), (entry_p))) +#define SMB_VFS_OPAQUE_SYS_ACL_GET_TAG_TYPE(conn, entry_d, tag_type_p) ((conn)->vfs_opaque.ops.sys_acl_get_tag_type((conn)->vfs_opaque.handles.sys_acl_get_tag_type, (entry_d), (tag_type_p))) +#define SMB_VFS_OPAQUE_SYS_ACL_GET_PERMSET(conn, entry_d, permset_p) ((conn)->vfs_opaque.ops.sys_acl_get_permset((conn)->vfs_opaque.handles.sys_acl_get_permset, (entry_d), (permset_p))) +#define SMB_VFS_OPAQUE_SYS_ACL_GET_QUALIFIER(conn, entry_d) ((conn)->vfs_opaque.ops.sys_acl_get_qualifier((conn)->vfs_opaque.handles.sys_acl_get_qualifier, (entry_d))) +#define SMB_VFS_OPAQUE_SYS_ACL_GET_FILE(conn, path_p, type) ((conn)->vfs_opaque.ops.sys_acl_get_file((conn)->vfs_opaque.handles.sys_acl_get_file, (path_p), (type))) #define SMB_VFS_OPAQUE_SYS_ACL_GET_FD(fsp, fd) ((fsp)->conn->vfs_opaque.ops.sys_acl_get_fd((fsp)->conn->vfs_opaque.handles.sys_acl_get_fd, (fsp), (fd))) -#define SMB_VFS_OPAQUE_SYS_ACL_CLEAR_PERMS(conn, permset) ((conn)->vfs_opaque.ops.sys_acl_clear_perms((conn)->vfs_opaque.handles.sys_acl_clear_perms, (conn), (permset))) -#define SMB_VFS_OPAQUE_SYS_ACL_ADD_PERM(conn, permset, perm) ((conn)->vfs_opaque.ops.sys_acl_add_perm((conn)->vfs_opaque.handles.sys_acl_add_perm, (conn), (permset), (perm))) -#define SMB_VFS_OPAQUE_SYS_ACL_TO_TEXT(conn, theacl, plen) ((conn)->vfs_opaque.ops.sys_acl_to_text((conn)->vfs_opaque.handles.sys_acl_to_text, (conn), (theacl), (plen))) -#define SMB_VFS_OPAQUE_SYS_ACL_INIT(conn, count) ((conn)->vfs_opaque.ops.sys_acl_init((conn)->vfs_opaque.handles.sys_acl_init, (conn), (count))) -#define SMB_VFS_OPAQUE_SYS_ACL_CREATE_ENTRY(conn, pacl, pentry) ((conn)->vfs_opaque.ops.sys_acl_create_entry((conn)->vfs_opaque.handles.sys_acl_create_entry, (conn), (pacl), (pentry))) -#define SMB_VFS_OPAQUE_SYS_ACL_SET_TAG_TYPE(conn, entry, tagtype) ((conn)->vfs_opaque.ops.sys_acl_set_tag_type((conn)->vfs_opaque.handles.sys_acl_set_tag_type, (conn), (entry), (tagtype))) -#define SMB_VFS_OPAQUE_SYS_ACL_SET_QUALIFIER(conn, entry, qual) ((conn)->vfs_opaque.ops.sys_acl_set_qualifier((conn)->vfs_opaque.handles.sys_acl_set_qualifier, (conn), (entry), (qual))) -#define SMB_VFS_OPAQUE_SYS_ACL_SET_PERMSET(conn, entry, permset) ((conn)->vfs_opaque.ops.sys_acl_set_permset((conn)->vfs_opaque.handles.sys_acl_set_permset, (conn), (entry), (permset))) -#define SMB_VFS_OPAQUE_SYS_ACL_VALID(conn, theacl) ((conn)->vfs_opaque.ops.sys_acl_valid((conn)->vfs_opaque.handles.sys_acl_valid, (conn), (theacl))) -#define SMB_VFS_OPAQUE_SYS_ACL_SET_FILE(conn, name, acltype, theacl) ((conn)->vfs_opaque.ops.sys_acl_set_file((conn)->vfs_opaque.handles.sys_acl_set_file, (conn), (name), (acltype), (theacl))) +#define SMB_VFS_OPAQUE_SYS_ACL_CLEAR_PERMS(conn, permset) ((conn)->vfs_opaque.ops.sys_acl_clear_perms((conn)->vfs_opaque.handles.sys_acl_clear_perms, (permset))) +#define SMB_VFS_OPAQUE_SYS_ACL_ADD_PERM(conn, permset, perm) ((conn)->vfs_opaque.ops.sys_acl_add_perm((conn)->vfs_opaque.handles.sys_acl_add_perm, (permset), (perm))) +#define SMB_VFS_OPAQUE_SYS_ACL_TO_TEXT(conn, theacl, plen) ((conn)->vfs_opaque.ops.sys_acl_to_text((conn)->vfs_opaque.handles.sys_acl_to_text, (theacl), (plen))) +#define SMB_VFS_OPAQUE_SYS_ACL_INIT(conn, count) ((conn)->vfs_opaque.ops.sys_acl_init((conn)->vfs_opaque.handles.sys_acl_init, (count))) +#define SMB_VFS_OPAQUE_SYS_ACL_CREATE_ENTRY(conn, pacl, pentry) ((conn)->vfs_opaque.ops.sys_acl_create_entry((conn)->vfs_opaque.handles.sys_acl_create_entry, (pacl), (pentry))) +#define SMB_VFS_OPAQUE_SYS_ACL_SET_TAG_TYPE(conn, entry, tagtype) ((conn)->vfs_opaque.ops.sys_acl_set_tag_type((conn)->vfs_opaque.handles.sys_acl_set_tag_type, (entry), (tagtype))) +#define SMB_VFS_OPAQUE_SYS_ACL_SET_QUALIFIER(conn, entry, qual) ((conn)->vfs_opaque.ops.sys_acl_set_qualifier((conn)->vfs_opaque.handles.sys_acl_set_qualifier, (entry), (qual))) +#define SMB_VFS_OPAQUE_SYS_ACL_SET_PERMSET(conn, entry, permset) ((conn)->vfs_opaque.ops.sys_acl_set_permset((conn)->vfs_opaque.handles.sys_acl_set_permset, (entry), (permset))) +#define SMB_VFS_OPAQUE_SYS_ACL_VALID(conn, theacl) ((conn)->vfs_opaque.ops.sys_acl_valid((conn)->vfs_opaque.handles.sys_acl_valid, (theacl))) +#define SMB_VFS_OPAQUE_SYS_ACL_SET_FILE(conn, name, acltype, theacl) ((conn)->vfs_opaque.ops.sys_acl_set_file((conn)->vfs_opaque.handles.sys_acl_set_file, (name), (acltype), (theacl))) #define SMB_VFS_OPAQUE_SYS_ACL_SET_FD(fsp, fd, theacl) ((fsp)->conn->vfs_opaque.ops.sys_acl_set_fd((fsp)->conn->vfs_opaque.handles.sys_acl_set_fd, (fsp), (fd), (theacl))) -#define SMB_VFS_OPAQUE_SYS_ACL_DELETE_DEF_FILE(conn, path) ((conn)->vfs_opaque.ops.sys_acl_delete_def_file((conn)->vfs_opaque.handles.sys_acl_delete_def_file, (conn), (path))) -#define SMB_VFS_OPAQUE_SYS_ACL_GET_PERM(conn, permset, perm) ((conn)->vfs_opaque.ops.sys_acl_get_perm((conn)->vfs_opaque.handles.sys_acl_get_perm, (conn), (permset), (perm))) -#define SMB_VFS_OPAQUE_SYS_ACL_FREE_TEXT(conn, text) ((conn)->vfs_opaque.ops.sys_acl_free_text((conn)->vfs_opaque.handles.sys_acl_free_text, (conn), (text))) -#define SMB_VFS_OPAQUE_SYS_ACL_FREE_ACL(conn, posix_acl) ((conn)->vfs_opaque.ops.sys_acl_free_acl((conn)->vfs_opaque.handles.sys_acl_free_acl, (conn), (posix_acl))) -#define SMB_VFS_OPAQUE_SYS_ACL_FREE_QUALIFIER(conn, qualifier, tagtype) ((conn)->vfs_opaque.ops.sys_acl_free_qualifier((conn)->vfs_opaque.handles.sys_acl_free_qualifier, (conn), (qualifier), (tagtype))) +#define SMB_VFS_OPAQUE_SYS_ACL_DELETE_DEF_FILE(conn, path) ((conn)->vfs_opaque.ops.sys_acl_delete_def_file((conn)->vfs_opaque.handles.sys_acl_delete_def_file, (path))) +#define SMB_VFS_OPAQUE_SYS_ACL_GET_PERM(conn, permset, perm) ((conn)->vfs_opaque.ops.sys_acl_get_perm((conn)->vfs_opaque.handles.sys_acl_get_perm, (permset), (perm))) +#define SMB_VFS_OPAQUE_SYS_ACL_FREE_TEXT(conn, text) ((conn)->vfs_opaque.ops.sys_acl_free_text((conn)->vfs_opaque.handles.sys_acl_free_text, (text))) +#define SMB_VFS_OPAQUE_SYS_ACL_FREE_ACL(conn, posix_acl) ((conn)->vfs_opaque.ops.sys_acl_free_acl((conn)->vfs_opaque.handles.sys_acl_free_acl, (posix_acl))) +#define SMB_VFS_OPAQUE_SYS_ACL_FREE_QUALIFIER(conn, qualifier, tagtype) ((conn)->vfs_opaque.ops.sys_acl_free_qualifier((conn)->vfs_opaque.handles.sys_acl_free_qualifier, (qualifier), (tagtype))) /* EA operations. */ -#define SMB_VFS_OPAQUE_GETXATTR(conn,path,name,value,size) ((conn)->vfs_opaque.ops.getxattr((conn)->vfs_opaque.handles.getxattr,(conn),(path),(name),(value),(size))) -#define SMB_VFS_OPAQUE_LGETXATTR(conn,path,name,value,size) ((conn)->vfs_opaque.ops.lgetxattr((conn)->vfs_opaque.handles.lgetxattr,(conn),(path),(name),(value),(size))) +#define SMB_VFS_OPAQUE_GETXATTR(conn,path,name,value,size) ((conn)->vfs_opaque.ops.getxattr((conn)->vfs_opaque.handles.getxattr,(path),(name),(value),(size))) +#define SMB_VFS_OPAQUE_LGETXATTR(conn,path,name,value,size) ((conn)->vfs_opaque.ops.lgetxattr((conn)->vfs_opaque.handles.lgetxattr,(path),(name),(value),(size))) #define SMB_VFS_OPAQUE_FGETXATTR(fsp,fd,name,value,size) ((fsp)->conn->vfs_opaque.ops.fgetxattr((fsp)->conn->vfs_opaque.handles.fgetxattr,(fsp),(fd),(name),(value),(size))) -#define SMB_VFS_OPAQUE_LISTXATTR(conn,path,list,size) ((conn)->vfs_opaque.ops.listxattr((conn)->vfs_opaque.handles.listxattr,(conn),(path),(list),(size))) -#define SMB_VFS_OPAQUE_LLISTXATTR(conn,path,list,size) ((conn)->vfs_opaque.ops.llistxattr((conn)->vfs_opaque.handles.llistxattr,(conn),(path),(list),(size))) +#define SMB_VFS_OPAQUE_LISTXATTR(conn,path,list,size) ((conn)->vfs_opaque.ops.listxattr((conn)->vfs_opaque.handles.listxattr,(path),(list),(size))) +#define SMB_VFS_OPAQUE_LLISTXATTR(conn,path,list,size) ((conn)->vfs_opaque.ops.llistxattr((conn)->vfs_opaque.handles.llistxattr,(path),(list),(size))) #define SMB_VFS_OPAQUE_FLISTXATTR(fsp,fd,list,size) ((fsp)->conn->vfs_opaque.ops.flistxattr((fsp)->conn->vfs_opaque.handles.flistxattr,(fsp),(fd),(list),(size))) -#define SMB_VFS_OPAQUE_REMOVEXATTR(conn,path,name) ((conn)->vfs_opaque.ops.removexattr((conn)->vfs_opaque.handles.removexattr,(conn),(path),(name))) -#define SMB_VFS_OPAQUE_LREMOVEXATTR(conn,path,name) ((conn)->vfs_opaque.ops.lremovexattr((conn)->vfs_opaque.handles.lremovexattr,(conn),(path),(name))) +#define SMB_VFS_OPAQUE_REMOVEXATTR(conn,path,name) ((conn)->vfs_opaque.ops.removexattr((conn)->vfs_opaque.handles.removexattr,(path),(name))) +#define SMB_VFS_OPAQUE_LREMOVEXATTR(conn,path,name) ((conn)->vfs_opaque.ops.lremovexattr((conn)->vfs_opaque.handles.lremovexattr,(path),(name))) #define SMB_VFS_OPAQUE_FREMOVEXATTR(fsp,fd,name) ((fsp)->conn->vfs_opaque.ops.fremovexattr((fsp)->conn->vfs_opaque.handles.fremovexattr,(fsp),(fd),(name))) -#define SMB_VFS_OPAQUE_SETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.setxattr((conn)->vfs_opaque.handles.setxattr,(conn),(path),(name),(value),(size),(flags))) -#define SMB_VFS_OPAQUE_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.lsetxattr((conn)->vfs_opaque.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags))) +#define SMB_VFS_OPAQUE_SETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.setxattr((conn)->vfs_opaque.handles.setxattr,(path),(name),(value),(size),(flags))) +#define SMB_VFS_OPAQUE_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.lsetxattr((conn)->vfs_opaque.handles.lsetxattr,(path),(name),(value),(size),(flags))) #define SMB_VFS_OPAQUE_FSETXATTR(fsp,fd,name,value,size,flags) ((fsp)->conn->vfs_opaque.ops.fsetxattr((fsp)->conn->vfs_opaque.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags))) /* AIO operations. */ @@ -252,27 +252,27 @@ ********************************************************************/ /* Disk operations */ -#define SMB_VFS_NEXT_CONNECT(handle, conn, service, user) ((handle)->vfs_next.ops.connect_fn((handle)->vfs_next.handles.connect_hnd, (conn), (service), (user))) -#define SMB_VFS_NEXT_DISCONNECT(handle, conn) ((handle)->vfs_next.ops.disconnect((handle)->vfs_next.handles.disconnect, (conn))) -#define SMB_VFS_NEXT_DISK_FREE(handle, conn, path, small_query, bsize, dfree ,dsize) ((handle)->vfs_next.ops.disk_free((handle)->vfs_next.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize))) -#define SMB_VFS_NEXT_GET_QUOTA(handle, conn, qtype, id, qt) ((handle)->vfs_next.ops.get_quota((handle)->vfs_next.handles.get_quota, (conn), (qtype), (id), (qt))) -#define SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, qt) ((handle)->vfs_next.ops.set_quota((handle)->vfs_next.handles.set_quota, (conn), (qtype), (id), (qt))) +#define SMB_VFS_NEXT_CONNECT(handle, service, user) ((handle)->vfs_next.ops.connect_fn((handle)->vfs_next.handles.connect_hnd, (service), (user))) +#define SMB_VFS_NEXT_DISCONNECT(handle) ((handle)->vfs_next.ops.disconnect((handle)->vfs_next.handles.disconnect)) +#define SMB_VFS_NEXT_DISK_FREE(handle, path, small_query, bsize, dfree ,dsize) ((handle)->vfs_next.ops.disk_free((handle)->vfs_next.handles.disk_free, (path), (small_query), (bsize), (dfree), (dsize))) +#define SMB_VFS_NEXT_GET_QUOTA(handle, qtype, id, qt) ((handle)->vfs_next.ops.get_quota((handle)->vfs_next.handles.get_quota, (qtype), (id), (qt))) +#define SMB_VFS_NEXT_SET_QUOTA(handle, qtype, id, qt) ((handle)->vfs_next.ops.set_quota((handle)->vfs_next.handles.set_quota, (qtype), (id), (qt))) #define SMB_VFS_NEXT_GET_SHADOW_COPY_DATA(handle, fsp, shadow_copy_data ,labels) ((handle)->vfs_next.ops.get_shadow_copy_data((handle)->vfs_next.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels))) -#define SMB_VFS_NEXT_STATVFS(handle, conn, path, statbuf) ((handle)->vfs_next.ops.statvfs((handle)->vfs_next.handles.statvfs, (conn), (path), (statbuf))) +#define SMB_VFS_NEXT_STATVFS(handle, path, statbuf) ((handle)->vfs_next.ops.statvfs((handle)->vfs_next.handles.statvfs, (path), (statbuf))) /* Directory operations */ -#define SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr) ((handle)->vfs_next.ops.opendir((handle)->vfs_next.handles.opendir, (conn), (fname), (mask), (attr))) -#define SMB_VFS_NEXT_READDIR(handle, conn, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (conn), (dirp))) -#define SMB_VFS_NEXT_SEEKDIR(handle, conn, dirp, offset) ((handle)->vfs_next.ops.seekdir((handle)->vfs_next.handles.seekdir, (conn), (dirp), (offset))) -#define SMB_VFS_NEXT_TELLDIR(handle, conn, dirp) ((handle)->vfs_next.ops.telldir((handle)->vfs_next.handles.telldir, (conn), (dirp))) -#define SMB_VFS_NEXT_REWINDDIR(handle, conn, dirp) ((handle)->vfs_next.ops.rewind_dir((handle)->vfs_next.handles.rewind_dir, (conn), (dirp))) -#define SMB_VFS_NEXT_DIR(handle, conn, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (conn), (dirp))) -#define SMB_VFS_NEXT_MKDIR(handle, conn, path, mode) ((handle)->vfs_next.ops.mkdir((handle)->vfs_next.handles.mkdir,(conn), (path), (mode))) -#define SMB_VFS_NEXT_RMDIR(handle, conn, path) ((handle)->vfs_next.ops.rmdir((handle)->vfs_next.handles.rmdir, (conn), (path))) -#define SMB_VFS_NEXT_CLOSEDIR(handle, conn, dir) ((handle)->vfs_next.ops.closedir((handle)->vfs_next.handles.closedir, (conn), dir)) +#define SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr) ((handle)->vfs_next.ops.opendir((handle)->vfs_next.handles.opendir, (fname), (mask), (attr))) +#define SMB_VFS_NEXT_READDIR(handle, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (dirp))) +#define SMB_VFS_NEXT_SEEKDIR(handle, dirp, offset) ((handle)->vfs_next.ops.seekdir((handle)->vfs_next.handles.seekdir, (dirp), (offset))) +#define SMB_VFS_NEXT_TELLDIR(handle, dirp) ((handle)->vfs_next.ops.telldir((handle)->vfs_next.handles.telldir, (dirp))) +#define SMB_VFS_NEXT_REWINDDIR(handle, dirp) ((handle)->vfs_next.ops.rewind_dir((handle)->vfs_next.handles.rewind_dir, (dirp))) +#define SMB_VFS_NEXT_DIR(handle, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (dirp))) +#define SMB_VFS_NEXT_MKDIR(handle, path, mode) ((handle)->vfs_next.ops.mkdir((handle)->vfs_next.handles.mkdir,(path), (mode))) +#define SMB_VFS_NEXT_RMDIR(handle, path) ((handle)->vfs_next.ops.rmdir((handle)->vfs_next.handles.rmdir, (path))) +#define SMB_VFS_NEXT_CLOSEDIR(handle, dir) ((handle)->vfs_next.ops.closedir((handle)->vfs_next.handles.closedir, dir)) /* File operations */ -#define SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode) ((handle)->vfs_next.ops.open((handle)->vfs_next.handles.open, (conn), (fname), (flags), (mode))) +#define SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode) ((handle)->vfs_next.ops.open((handle)->vfs_next.handles.open, (fname), (fsp), (flags), (mode))) #define SMB_VFS_NEXT_CLOSE(handle, fsp, fd) ((handle)->vfs_next.ops.close_fn((handle)->vfs_next.handles.close_hnd, (fsp), (fd))) #define SMB_VFS_NEXT_READ(handle, fsp, fd, data, n) ((handle)->vfs_next.ops.read((handle)->vfs_next.handles.read, (fsp), (fd), (data), (n))) #define SMB_VFS_NEXT_PREAD(handle, fsp, fd, data, n, off) ((handle)->vfs_next.ops.pread((handle)->vfs_next.handles.pread, (fsp), (fd), (data), (n), (off))) @@ -280,27 +280,27 @@ #define SMB_VFS_NEXT_PWRITE(handle, fsp, fd, data, n, off) ((handle)->vfs_next.ops.pwrite((handle)->vfs_next.handles.pwrite, (fsp), (fd), (data), (n), (off))) #define SMB_VFS_NEXT_LSEEK(handle, fsp, fd, offset, whence) ((handle)->vfs_next.ops.lseek((handle)->vfs_next.handles.lseek, (fsp), (fd), (offset), (whence))) #define SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd, header, offset, count) ((handle)->vfs_next.ops.sendfile((handle)->vfs_next.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count))) -#define SMB_VFS_NEXT_RENAME(handle, conn, old, new) ((handle)->vfs_next.ops.rename((handle)->vfs_next.handles.rename, (conn), (old), (new))) +#define SMB_VFS_NEXT_RENAME(handle, old, new) ((handle)->vfs_next.ops.rename((handle)->vfs_next.handles.rename, (old), (new))) #define SMB_VFS_NEXT_FSYNC(handle, fsp, fd) ((handle)->vfs_next.ops.fsync((handle)->vfs_next.handles.fsync, (fsp), (fd))) -#define SMB_VFS_NEXT_STAT(handle, conn, fname, sbuf) ((handle)->vfs_next.ops.stat((handle)->vfs_next.handles.stat, (conn), (fname), (sbuf))) +#define SMB_VFS_NEXT_STAT(handle, fname, sbuf) ((handle)->vfs_next.ops.stat((handle)->vfs_next.handles.stat, (fname), (sbuf))) #define SMB_VFS_NEXT_FSTAT(handle, fsp, fd, sbuf) ((handle)->vfs_next.ops.fstat((handle)->vfs_next.handles.fstat, (fsp) ,(fd) ,(sbuf))) -#define SMB_VFS_NEXT_LSTAT(handle, conn, path, sbuf) ((handle)->vfs_next.ops.lstat((handle)->vfs_next.handles.lstat, (conn), (path), (sbuf))) -#define SMB_VFS_NEXT_UNLINK(handle, conn, path) ((handle)->vfs_next.ops.unlink((handle)->vfs_next.handles.unlink, (conn), (path))) -#define SMB_VFS_NEXT_CHMOD(handle, conn, path, mode) ((handle)->vfs_next.ops.chmod((handle)->vfs_next.handles.chmod, (conn), (path), (mode))) +#define SMB_VFS_NEXT_LSTAT(handle, path, sbuf) ((handle)->vfs_next.ops.lstat((handle)->vfs_next.handles.lstat, (path), (sbuf))) +#define SMB_VFS_NEXT_UNLINK(handle, path) ((handle)->vfs_next.ops.unlink((handle)->vfs_next.handles.unlink, (path))) +#define SMB_VFS_NEXT_CHMOD(handle, path, mode) ((handle)->vfs_next.ops.chmod((handle)->vfs_next.handles.chmod, (path), (mode))) #define SMB_VFS_NEXT_FCHMOD(handle, fsp, fd, mode) ((handle)->vfs_next.ops.fchmod((handle)->vfs_next.handles.fchmod, (fsp), (fd), (mode))) -#define SMB_VFS_NEXT_CHOWN(handle, conn, path, uid, gid) ((handle)->vfs_next.ops.chown((handle)->vfs_next.handles.chown, (conn), (path), (uid), (gid))) +#define SMB_VFS_NEXT_CHOWN(handle, path, uid, gid) ((handle)->vfs_next.ops.chown((handle)->vfs_next.handles.chown, (path), (uid), (gid))) #define SMB_VFS_NEXT_FCHOWN(handle, fsp, fd, uid, gid) ((handle)->vfs_next.ops.fchown((handle)->vfs_next.handles.fchown, (fsp), (fd), (uid), (gid))) -#define SMB_VFS_NEXT_CHDIR(handle, conn, path) ((handle)->vfs_next.ops.chdir((handle)->vfs_next.handles.chdir, (conn), (path))) -#define SMB_VFS_NEXT_GETWD(handle, conn, buf) ((handle)->vfs_next.ops.getwd((handle)->vfs_next.handles.getwd, (conn), (buf))) -#define SMB_VFS_NEXT_UTIME(handle, conn, path, times) ((handle)->vfs_next.ops.utime((handle)->vfs_next.handles.utime, (conn), (path), (times))) +#define SMB_VFS_NEXT_CHDIR(handle, path) ((handle)->vfs_next.ops.chdir((handle)->vfs_next.handles.chdir, (path))) +#define SMB_VFS_NEXT_GETWD(handle, buf) ((handle)->vfs_next.ops.getwd((handle)->vfs_next.handles.getwd, (buf))) +#define SMB_VFS_NEXT_UTIME(handle, path, times) ((handle)->vfs_next.ops.utime((handle)->vfs_next.handles.utime, (path), (times))) #define SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset) ((handle)->vfs_next.ops.ftruncate((handle)->vfs_next.handles.ftruncate, (fsp), (fd), (offset))) #define SMB_VFS_NEXT_LOCK(handle, fsp, fd, op, offset, count, type) ((handle)->vfs_next.ops.lock((handle)->vfs_next.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type))) #define SMB_VFS_NEXT_GETLOCK(handle, fsp, fd, poffset, pcount, ptype, ppid) ((handle)->vfs_next.ops.getlock((handle)->vfs_next.handles.getlock, (fsp), (fd), (poffset), (pcount), (ptype), (ppid))) -#define SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath) ((handle)->vfs_next.ops.symlink((handle)->vfs_next.handles.symlink, (conn), (oldpath), (newpath))) -#define SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz) ((handle)->vfs_next.ops.readlink((handle)->vfs_next.handles.readlink, (conn), (path), (buf), (bufsiz))) -#define SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath) ((handle)->vfs_next.ops.link((handle)->vfs_next.handles.link, (conn), (oldpath), (newpath))) -#define SMB_VFS_NEXT_MKNOD(handle, conn, path, mode, dev) ((handle)->vfs_next.ops.mknod((handle)->vfs_next.handles.mknod, (conn), (path), (mode), (dev))) -#define SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path) ((handle)->vfs_next.ops.realpath((handle)->vfs_next.handles.realpath, (conn), (path), (resolved_path))) +#define SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath) ((handle)->vfs_next.ops.symlink((handle)->vfs_next.handles.symlink, (oldpath), (newpath))) +#define SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz) ((handle)->vfs_next.ops.readlink((handle)->vfs_next.handles.readlink, (path), (buf), (bufsiz))) +#define SMB_VFS_NEXT_LINK(handle, oldpath, newpath) ((handle)->vfs_next.ops.link((handle)->vfs_next.handles.link, (oldpath), (newpath))) +#define SMB_VFS_NEXT_MKNOD(handle, path, mode, dev) ((handle)->vfs_next.ops.mknod((handle)->vfs_next.handles.mknod, (path), (mode), (dev))) +#define SMB_VFS_NEXT_REALPATH(handle, path, resolved_path) ((handle)->vfs_next.ops.realpath((handle)->vfs_next.handles.realpath, (path), (resolved_path))) /* NT ACL operations. */ #define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, fd, security_info, ppdesc) ((handle)->vfs_next.ops.fget_nt_acl((handle)->vfs_next.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc))) @@ -309,44 +309,44 @@ #define SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, name, security_info_sent, psd) ((handle)->vfs_next.ops.set_nt_acl((handle)->vfs_next.handles.set_nt_acl, (fsp), (name), (security_info_sent), (psd))) /* POSIX ACL operations. */ -#define SMB_VFS_NEXT_CHMOD_ACL(handle, conn, name, mode) ((handle)->vfs_next.ops.chmod_acl((handle)->vfs_next.handles.chmod_acl, (conn), (name), (mode))) +#define SMB_VFS_NEXT_CHMOD_ACL(handle, name, mode) ((handle)->vfs_next.ops.chmod_acl((handle)->vfs_next.handles.chmod_acl, (name), (mode))) #define SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, fd, mode) ((handle)->vfs_next.ops.fchmod_acl((handle)->vfs_next.handles.chmod_acl, (fsp), (fd), (mode))) -#define SMB_VFS_NEXT_SYS_ACL_GET_ENTRY(handle, conn, theacl, entry_id, entry_p) ((handle)->vfs_next.ops.sys_acl_get_entry((handle)->vfs_next.handles.sys_acl_get_entry, (conn), (theacl), (entry_id), (entry_p))) -#define SMB_VFS_NEXT_SYS_ACL_GET_TAG_TYPE(handle, conn, entry_d, tag_type_p) ((handle)->vfs_next.ops.sys_acl_get_tag_type((handle)->vfs_next.handles.sys_acl_get_tag_type, (conn), (entry_d), (tag_type_p))) -#define SMB_VFS_NEXT_SYS_ACL_GET_PERMSET(handle, conn, entry_d, permset_p) ((handle)->vfs_next.ops.sys_acl_get_permset((handle)->vfs_next.handles.sys_acl_get_permset, (conn), (entry_d), (permset_p))) -#define SMB_VFS_NEXT_SYS_ACL_GET_QUALIFIER(handle, conn, entry_d) ((handle)->vfs_next.ops.sys_acl_get_qualifier((handle)->vfs_next.handles.sys_acl_get_qualifier, (conn), (entry_d))) -#define SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, path_p, type) ((handle)->vfs_next.ops.sys_acl_get_file((handle)->vfs_next.handles.sys_acl_get_file, (conn), (path_p), (type))) +#define SMB_VFS_NEXT_SYS_ACL_GET_ENTRY(handle, theacl, entry_id, entry_p) ((handle)->vfs_next.ops.sys_acl_get_entry((handle)->vfs_next.handles.sys_acl_get_entry, (theacl), (entry_id), (entry_p))) +#define SMB_VFS_NEXT_SYS_ACL_GET_TAG_TYPE(handle, entry_d, tag_type_p) ((handle)->vfs_next.ops.sys_acl_get_tag_type((handle)->vfs_next.handles.sys_acl_get_tag_type, (entry_d), (tag_type_p))) +#define SMB_VFS_NEXT_SYS_ACL_GET_PERMSET(handle, entry_d, permset_p) ((handle)->vfs_next.ops.sys_acl_get_permset((handle)->vfs_next.handles.sys_acl_get_permset, (entry_d), (permset_p))) +#define SMB_VFS_NEXT_SYS_ACL_GET_QUALIFIER(handle, entry_d) ((handle)->vfs_next.ops.sys_acl_get_qualifier((handle)->vfs_next.handles.sys_acl_get_qualifier, (entry_d))) +#define SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, path_p, type) ((handle)->vfs_next.ops.sys_acl_get_file((handle)->vfs_next.handles.sys_acl_get_file, (path_p), (type))) #define SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, fd) ((handle)->vfs_next.ops.sys_acl_get_fd((handle)->vfs_next.handles.sys_acl_get_fd, (fsp), (fd))) -#define SMB_VFS_NEXT_SYS_ACL_CLEAR_PERMS(handle, conn, permset) ((handle)->vfs_next.ops.sys_acl_clear_perms((handle)->vfs_next.handles.sys_acl_clear_perms, (conn), (permset))) -#define SMB_VFS_NEXT_SYS_ACL_ADD_PERM(handle, conn, permset, perm) ((handle)->vfs_next.ops.sys_acl_add_perm((handle)->vfs_next.handles.sys_acl_add_perm, (conn), (permset), (perm))) -#define SMB_VFS_NEXT_SYS_ACL_TO_TEXT(handle, conn, theacl, plen) ((handle)->vfs_next.ops.sys_acl_to_text((handle)->vfs_next.handles.sys_acl_to_text, (conn), (theacl), (plen))) -#define SMB_VFS_NEXT_SYS_ACL_INIT(handle, conn, count) ((handle)->vfs_next.ops.sys_acl_init((handle)->vfs_next.handles.sys_acl_init, (conn), (count))) -#define SMB_VFS_NEXT_SYS_ACL_CREATE_ENTRY(handle, conn, pacl, pentry) ((handle)->vfs_next.ops.sys_acl_create_entry((handle)->vfs_next.handles.sys_acl_create_entry, (conn), (pacl), (pentry))) -#define SMB_VFS_NEXT_SYS_ACL_SET_TAG_TYPE(handle, conn, entry, tagtype) ((handle)->vfs_next.ops.sys_acl_set_tag_type((handle)->vfs_next.handles.sys_acl_set_tag_type, (conn), (entry), (tagtype))) -#define SMB_VFS_NEXT_SYS_ACL_SET_QUALIFIER(handle, conn, entry, qual) ((handle)->vfs_next.ops.sys_acl_set_qualifier((handle)->vfs_next.handles.sys_acl_set_qualifier, (conn), (entry), (qual))) -#define SMB_VFS_NEXT_SYS_ACL_SET_PERMSET(handle, conn, entry, permset) ((handle)->vfs_next.ops.sys_acl_set_permset((handle)->vfs_next.handles.sys_acl_set_permset, (conn), (entry), (permset))) -#define SMB_VFS_NEXT_SYS_ACL_VALID(handle, conn, theacl) ((handle)->vfs_next.ops.sys_acl_valid((handle)->vfs_next.handles.sys_acl_valid, (conn), (theacl))) -#define SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, name, acltype, theacl) ((handle)->vfs_next.ops.sys_acl_set_file((handle)->vfs_next.handles.sys_acl_set_file, (conn), (name), (acltype), (theacl))) +#define SMB_VFS_NEXT_SYS_ACL_CLEAR_PERMS(handle, permset) ((handle)->vfs_next.ops.sys_acl_clear_perms((handle)->vfs_next.handles.sys_acl_clear_perms, (permset))) +#define SMB_VFS_NEXT_SYS_ACL_ADD_PERM(handle, permset, perm) ((handle)->vfs_next.ops.sys_acl_add_perm((handle)->vfs_next.handles.sys_acl_add_perm, (permset), (perm))) +#define SMB_VFS_NEXT_SYS_ACL_TO_TEXT(handle, theacl, plen) ((handle)->vfs_next.ops.sys_acl_to_text((handle)->vfs_next.handles.sys_acl_to_text, (theacl), (plen))) +#define SMB_VFS_NEXT_SYS_ACL_INIT(handle, count) ((handle)->vfs_next.ops.sys_acl_init((handle)->vfs_next.handles.sys_acl_init, (count))) +#define SMB_VFS_NEXT_SYS_ACL_CREATE_ENTRY(handle, pacl, pentry) ((handle)->vfs_next.ops.sys_acl_create_entry((handle)->vfs_next.handles.sys_acl_create_entry, (pacl), (pentry))) +#define SMB_VFS_NEXT_SYS_ACL_SET_TAG_TYPE(handle, entry, tagtype) ((handle)->vfs_next.ops.sys_acl_set_tag_type((handle)->vfs_next.handles.sys_acl_set_tag_type, (entry), (tagtype))) +#define SMB_VFS_NEXT_SYS_ACL_SET_QUALIFIER(handle, entry, qual) ((handle)->vfs_next.ops.sys_acl_set_qualifier((handle)->vfs_next.handles.sys_acl_set_qualifier, (entry), (qual))) +#define SMB_VFS_NEXT_SYS_ACL_SET_PERMSET(handle, entry, permset) ((handle)->vfs_next.ops.sys_acl_set_permset((handle)->vfs_next.handles.sys_acl_set_permset, (entry), (permset))) +#define SMB_VFS_NEXT_SYS_ACL_VALID(handle, theacl) ((handle)->vfs_next.ops.sys_acl_valid((handle)->vfs_next.handles.sys_acl_valid, (theacl))) +#define SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, name, acltype, theacl) ((handle)->vfs_next.ops.sys_acl_set_file((handle)->vfs_next.handles.sys_acl_set_file, (name), (acltype), (theacl))) #define SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, fd, theacl) ((handle)->vfs_next.ops.sys_acl_set_fd((handle)->vfs_next.handles.sys_acl_set_fd, (fsp), (fd), (theacl))) -#define SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, path) ((handle)->vfs_next.ops.sys_acl_delete_def_file((handle)->vfs_next.handles.sys_acl_delete_def_file, (conn), (path))) -#define SMB_VFS_NEXT_SYS_ACL_GET_PERM(handle, conn, permset, perm) ((handle)->vfs_next.ops.sys_acl_get_perm((handle)->vfs_next.handles.sys_acl_get_perm, (conn), (permset), (perm))) -#define SMB_VFS_NEXT_SYS_ACL_FREE_TEXT(handle, conn, text) ((handle)->vfs_next.ops.sys_acl_free_text((handle)->vfs_next.handles.sys_acl_free_text, (conn), (text))) -#define SMB_VFS_NEXT_SYS_ACL_FREE_ACL(handle, conn, posix_acl) ((handle)->vfs_next.ops.sys_acl_free_acl((handle)->vfs_next.handles.sys_acl_free_acl, (conn), (posix_acl))) -#define SMB_VFS_NEXT_SYS_ACL_FREE_QUALIFIER(handle, conn, qualifier, tagtype) ((handle)->vfs_next.ops.sys_acl_free_qualifier((handle)->vfs_next.handles.sys_acl_free_qualifier, (conn), (qualifier), (tagtype))) +#define SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, path) ((handle)->vfs_next.ops.sys_acl_delete_def_file((handle)->vfs_next.handles.sys_acl_delete_def_file, (path))) +#define SMB_VFS_NEXT_SYS_ACL_GET_PERM(handle, permset, perm) ((handle)->vfs_next.ops.sys_acl_get_perm((handle)->vfs_next.handles.sys_acl_get_perm, (permset), (perm))) +#define SMB_VFS_NEXT_SYS_ACL_FREE_TEXT(handle, text) ((handle)->vfs_next.ops.sys_acl_free_text((handle)->vfs_next.handles.sys_acl_free_text, (text))) +#define SMB_VFS_NEXT_SYS_ACL_FREE_ACL(handle, posix_acl) ((handle)->vfs_next.ops.sys_acl_free_acl((handle)->vfs_next.handles.sys_acl_free_acl, (posix_acl))) +#define SMB_VFS_NEXT_SYS_ACL_FREE_QUALIFIER(handle, qualifier, tagtype) ((handle)->vfs_next.ops.sys_acl_free_qualifier((handle)->vfs_next.handles.sys_acl_free_qualifier, (qualifier), (tagtype))) /* EA operations. */ -#define SMB_VFS_NEXT_GETXATTR(handle,conn,path,name,value,size) ((handle)->vfs_next.ops.getxattr((handle)->vfs_next.handles.getxattr,(conn),(path),(name),(value),(size))) -#define SMB_VFS_NEXT_LGETXATTR(handle,conn,path,name,value,size) ((handle)->vfs_next.ops.lgetxattr((handle)->vfs_next.handles.lgetxattr,(conn),(path),(name),(value),(size))) +#define SMB_VFS_NEXT_GETXATTR(handle,path,name,value,size) ((handle)->vfs_next.ops.getxattr((handle)->vfs_next.handles.getxattr,(path),(name),(value),(size))) +#define SMB_VFS_NEXT_LGETXATTR(handle,path,name,value,size) ((handle)->vfs_next.ops.lgetxattr((handle)->vfs_next.handles.lgetxattr,(path),(name),(value),(size))) #define SMB_VFS_NEXT_FGETXATTR(handle,fsp,fd,name,value,size) ((handle)->vfs_next.ops.fgetxattr((handle)->vfs_next.handles.fgetxattr,(fsp),(fd),(name),(value),(size))) -#define SMB_VFS_NEXT_LISTXATTR(handle,conn,path,list,size) ((handle)->vfs_next.ops.listxattr((handle)->vfs_next.handles.listxattr,(conn),(path),(list),(size))) -#define SMB_VFS_NEXT_LLISTXATTR(handle,conn,path,list,size) ((handle)->vfs_next.ops.llistxattr((handle)->vfs_next.handles.llistxattr,(conn),(path),(list),(size))) +#define SMB_VFS_NEXT_LISTXATTR(handle,path,list,size) ((handle)->vfs_next.ops.listxattr((handle)->vfs_next.handles.listxattr,(path),(list),(size))) +#define SMB_VFS_NEXT_LLISTXATTR(handle,path,list,size) ((handle)->vfs_next.ops.llistxattr((handle)->vfs_next.handles.llistxattr,(path),(list),(size))) #define SMB_VFS_NEXT_FLISTXATTR(handle,fsp,fd,list,size) ((handle)->vfs_next.ops.flistxattr((handle)->vfs_next.handles.flistxattr,(fsp),(fd),(list),(size))) -#define SMB_VFS_NEXT_REMOVEXATTR(handle,conn,path,name) ((handle)->vfs_next.ops.removexattr((handle)->vfs_next.handles.removexattr,(conn),(path),(name))) -#define SMB_VFS_NEXT_LREMOVEXATTR(handle,conn,path,name) ((handle)->vfs_next.ops.lremovexattr((handle)->vfs_next.handles.lremovexattr,(conn),(path),(name))) +#define SMB_VFS_NEXT_REMOVEXATTR(handle,path,name) ((handle)->vfs_next.ops.removexattr((handle)->vfs_next.handles.removexattr,(path),(name))) +#define SMB_VFS_NEXT_LREMOVEXATTR(handle,path,name) ((handle)->vfs_next.ops.lremovexattr((handle)->vfs_next.handles.lremovexattr,(path),(name))) #define SMB_VFS_NEXT_FREMOVEXATTR(handle,fsp,fd,name) ((handle)->vfs_next.ops.fremovexattr((handle)->vfs_next.handles.fremovexattr,(fsp),(fd),(name))) -#define SMB_VFS_NEXT_SETXATTR(handle,conn,path,name,value,size,flags) ((handle)->vfs_next.ops.setxattr((handle)->vfs_next.handles.setxattr,(conn),(path),(name),(value),(size),(flags))) -#define SMB_VFS_NEXT_LSETXATTR(handle,conn,path,name,value,size,flags) ((handle)->vfs_next.ops.lsetxattr((handle)->vfs_next.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags))) +#define SMB_VFS_NEXT_SETXATTR(handle,path,name,value,size,flags) ((handle)->vfs_next.ops.setxattr((handle)->vfs_next.handles.setxattr,(path),(name),(value),(size),(flags))) +#define SMB_VFS_NEXT_LSETXATTR(handle,path,name,value,size,flags) ((handle)->vfs_next.ops.lsetxattr((handle)->vfs_next.handles.lsetxattr,(path),(name),(value),(size),(flags))) #define SMB_VFS_NEXT_FSETXATTR(handle,fsp,fd,name,value,size,flags) ((handle)->vfs_next.ops.fsetxattr((handle)->vfs_next.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags))) /* AIO operations. */ diff --git a/source/lib/account_pol.c b/source/lib/account_pol.c index 6bf7346fe7f..8d844741f5d 100644 --- a/source/lib/account_pol.c +++ b/source/lib/account_pol.c @@ -262,10 +262,18 @@ BOOL init_account_policy(void) return True; } - tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); - if (!tdb) { - DEBUG(0,("Failed to open account policy database\n")); - return False; + tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600); + if (!tdb) { /* the account policies files does not exist or open failed, try to create a new one */ + tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); + if (!tdb) { + DEBUG(0,("Failed to open account policy database\n")); + return False; + } + /* creation was successful */ + /* add AP_MIGRATED_TO_PASSDB speacial key */ + /* so that you do not need to migrate policies */ + /* on brand new servers as it does not make sense */ + account_policy_migrated(True); } /* handle a Samba upgrade */ diff --git a/source/lib/afs.c b/source/lib/afs.c index 8a304adcf0c..ea83fdebc25 100644 --- a/source/lib/afs.c +++ b/source/lib/afs.c @@ -211,6 +211,7 @@ char *afs_createtoken_str(const char *username, const char *cell) BOOL afs_login(connection_struct *conn) { + extern userdom_struct current_user_info; extern struct current_user current_user; DATA_BLOB ticket; pstring afs_username; @@ -222,7 +223,11 @@ BOOL afs_login(connection_struct *conn) struct ClearToken ct; pstrcpy(afs_username, lp_afs_username_map()); - standard_sub_conn(conn, afs_username, sizeof(afs_username)); + standard_sub_advanced(SNUM(conn), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + afs_username, sizeof(afs_username)); user_sid = ¤t_user.nt_user_token->user_sids[0]; pstring_sub(afs_username, "%s", sid_string_static(user_sid)); diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c index 097d746a638..fffdf010a05 100644 --- a/source/lib/charcnv.c +++ b/source/lib/charcnv.c @@ -516,13 +516,14 @@ size_t convert_string(charset_t from, charset_t to, **/ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, - void const *src, size_t srclen, void **dest, BOOL allow_bad_conv) + void const *src, size_t srclen, void *dst, BOOL allow_bad_conv) { size_t i_len, o_len, destlen = MAX(srclen, 512); size_t retval; const char *inbuf = (const char *)src; char *outbuf = NULL, *ob = NULL; smb_iconv_t descriptor; + void **dest = (void **)dst; *dest = NULL; @@ -702,9 +703,11 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, * * @returns Size in bytes of the converted string; or -1 in case of error. **/ -static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, - void const *src, size_t srclen, void **dest, BOOL allow_bad_conv) +size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, + void const *src, size_t srclen, void *dst, + BOOL allow_bad_conv) { + void **dest = (void **)dst; size_t dest_len; *dest = NULL; @@ -944,9 +947,9 @@ size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, if (flags & STR_TERMINATE) { if (src_len == (size_t)-1) { - src_len = strlen(src) + 1; + src_len = strlen((const char *)src) + 1; } else { - size_t len = strnlen(src, src_len); + size_t len = strnlen((const char *)src, src_len); if (len < src_len) len++; src_len = len; @@ -1034,7 +1037,7 @@ size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_ len += ret; if (flags & STR_UPPER) { - smb_ucs2_t *dest_ucs2 = dest; + smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest; size_t i; for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) { smb_ucs2_t v = toupper_w(dest_ucs2[i]); @@ -1178,7 +1181,8 @@ size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_ if (flags & STR_TERMINATE) { /* src_len -1 is the default for null terminated strings. */ if (src_len != (size_t)-1) { - size_t len = strnlen_w(src, src_len/2); + size_t len = strnlen_w((const smb_ucs2_t *)src, + src_len/2); if (len < src_len/2) len++; src_len = len*2; diff --git a/source/lib/data_blob.c b/source/lib/data_blob.c index ccd0d27f47b..860ef5ad10f 100644 --- a/source/lib/data_blob.c +++ b/source/lib/data_blob.c @@ -102,7 +102,7 @@ void data_blob_free(DATA_BLOB *d) Clear a DATA_BLOB's contents *******************************************************************/ -static void data_blob_clear(DATA_BLOB *d) +void data_blob_clear(DATA_BLOB *d) { if (d->data) { memset(d->data, 0, d->length); diff --git a/source/lib/debug.c b/source/lib/debug.c index 2b6c42b8eb0..bf75bdf3d3f 100644 --- a/source/lib/debug.c +++ b/source/lib/debug.c @@ -981,7 +981,7 @@ BOOL dbghdr( int level, const char *file, const char *func, int line ) /* Print it all out at once to prevent split syslog output. */ (void)Debug1( "[%s, %d%s] %s:%s(%d)\n", - timestring(lp_debug_hires_timestamp()), level, + current_timestring(lp_debug_hires_timestamp()), level, header_str, file, func, line ); } diff --git a/source/lib/popt_common.c b/source/lib/popt_common.c index d29e171be08..0c0ed86dd1f 100644 --- a/source/lib/popt_common.c +++ b/source/lib/popt_common.c @@ -123,7 +123,7 @@ static void popt_common_callback(poptContext con, } struct poptOption popt_common_connection[] = { - { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback }, + { NULL, 0, POPT_ARG_CALLBACK, (void *)popt_common_callback }, { "socket-options", 'O', POPT_ARG_STRING, NULL, 'O', "socket options to use", "SOCKETOPTIONS" }, { "netbiosname", 'n', POPT_ARG_STRING, NULL, 'n', "Primary netbios name", "NETBIOSNAME" }, @@ -134,7 +134,7 @@ struct poptOption popt_common_connection[] = { }; struct poptOption popt_common_samba[] = { - { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_callback }, + { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, (void *)popt_common_callback }, { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" }, { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternate configuration file", "CONFIGFILE" }, { "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Base name for log files", "LOGFILEBASE" }, @@ -143,7 +143,7 @@ struct poptOption popt_common_samba[] = { }; struct poptOption popt_common_version[] = { - { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback }, + { NULL, 0, POPT_ARG_CALLBACK, (void *)popt_common_callback }, { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version" }, POPT_TABLEEND }; @@ -248,7 +248,7 @@ static void popt_dynconfig_callback(poptContext con, const struct poptOption popt_common_dynconfig[] = { - { NULL, '\0', POPT_ARG_CALLBACK, popt_dynconfig_callback }, + { NULL, '\0', POPT_ARG_CALLBACK, (void *)popt_dynconfig_callback }, { "sbindir", '\0' , POPT_ARG_STRING, NULL, DYN_SBINDIR, "Path to sbin directory", "SBINDIR" }, @@ -515,7 +515,7 @@ static void popt_common_credentials_callback(poptContext con, struct poptOption popt_common_credentials[] = { - { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_credentials_callback }, + { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, (void *)popt_common_credentials_callback }, { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "USERNAME" }, { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, 0, "Don't ask for a password" }, { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" }, diff --git a/source/lib/socket_wrapper.c b/source/lib/socket_wrapper.c index e9c1404d113..04c337267fd 100644 --- a/source/lib/socket_wrapper.c +++ b/source/lib/socket_wrapper.c @@ -411,12 +411,16 @@ _PUBLIC_ int swrap_socket(int domain, int type, int protocol) return real_socket(domain, type, protocol); } + si = (struct socket_info *)calloc(1, sizeof(struct socket_info)); + if (si == NULL) { + errno = ENOMEM; + return -1; + } + fd = real_socket(AF_UNIX, type, 0); if (fd == -1) return -1; - si = calloc(1, sizeof(struct socket_info)); - si->domain = domain; si->type = type; si->protocol = protocol; @@ -457,7 +461,12 @@ _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) parent_si->domain, addr, addrlen); if (ret == -1) return ret; - child_si = malloc(sizeof(struct socket_info)); + child_si = (struct socket_info *)malloc(sizeof(struct socket_info)); + if (child_si == NULL) { + close(fd); + errno = ENOMEM; + return -1; + } memset(child_si, 0, sizeof(*child_si)); child_si->fd = fd; @@ -466,7 +475,7 @@ _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) child_si->protocol = parent_si->protocol; child_si->bound = 1; - ret = real_getsockname(fd, &un_my_addr, &un_my_addrlen); + ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen); if (ret == -1) return ret; ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen, diff --git a/source/lib/substitute.c b/source/lib/substitute.c index ff9deb8a5f0..430c8029b8f 100644 --- a/source/lib/substitute.c +++ b/source/lib/substitute.c @@ -415,11 +415,12 @@ static const char *automount_server(const char *user_name) don't allow expansions. ****************************************************************************/ -void standard_sub_basic(const char *smb_name, char *str, size_t len) +void standard_sub_basic(const char *smb_name, const char *domain_name, + char *str, size_t len) { char *s; - if ( (s = alloc_sub_basic( smb_name, str )) != NULL ) { + if ( (s = alloc_sub_basic( smb_name, domain_name, str )) != NULL ) { strncpy( str, s, len ); } @@ -432,11 +433,12 @@ void standard_sub_basic(const char *smb_name, char *str, size_t len) This function will return an allocated string that have to be freed. ****************************************************************************/ -char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *str) +char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, + const char *domain_name, const char *str) { char *a, *t; - if ( (a = alloc_sub_basic(smb_name, str)) == NULL ) { + if ( (a = alloc_sub_basic(smb_name, domain_name, str)) == NULL ) { return NULL; } t = talloc_strdup(mem_ctx, a); @@ -447,7 +449,8 @@ char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *st /**************************************************************************** ****************************************************************************/ -char *alloc_sub_basic(const char *smb_name, const char *str) +char *alloc_sub_basic(const char *smb_name, const char *domain_name, + const char *str) { char *b, *p, *s, *r, *a_string; fstring pidstr; @@ -463,7 +466,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str) a_string = SMB_STRDUP(str); if (a_string == NULL) { - DEBUG(0, ("alloc_sub_specified: Out of memory!\n")); + DEBUG(0, ("alloc_sub_basic: Out of memory!\n")); return NULL; } @@ -490,7 +493,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str) } break; case 'D' : - r = strdup_upper(current_user_info.domain); + r = strdup_upper(domain_name); if (r == NULL) { goto error; } @@ -522,7 +525,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str) a_string = realloc_string_sub(a_string, "%R", remote_proto); break; case 'T' : - a_string = realloc_string_sub(a_string, "%T", timestring(False)); + a_string = realloc_string_sub(a_string, "%T", current_timestring(False)); break; case 'a' : a_string = realloc_string_sub(a_string, "%a", remote_arch); @@ -580,32 +583,20 @@ char *talloc_sub_specified(TALLOC_CTX *mem_ctx, uid_t uid, gid_t gid) { - char *a, *t; - a = alloc_sub_specified(input_string, username, domain, uid, gid); - if (!a) { + char *a_string; + char *ret_string = NULL; + char *b, *p, *s; + TALLOC_CTX *tmp_ctx; + + if (!(tmp_ctx = talloc_new(mem_ctx))) { + DEBUG(0, ("talloc_new failed\n")); return NULL; } - t = talloc_strdup(mem_ctx, a); - SAFE_FREE(a); - return t; -} -/**************************************************************************** -****************************************************************************/ - -char *alloc_sub_specified(const char *input_string, - const char *username, - const char *domain, - uid_t uid, - gid_t gid) -{ - char *a_string, *ret_string; - char *b, *p, *s; - - a_string = SMB_STRDUP(input_string); + a_string = talloc_strdup(tmp_ctx, input_string); if (a_string == NULL) { - DEBUG(0, ("alloc_sub_specified: Out of memory!\n")); - return NULL; + DEBUG(0, ("talloc_sub_specified: Out of memory!\n")); + goto done; } for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) { @@ -614,30 +605,42 @@ char *alloc_sub_specified(const char *input_string, switch (*(p+1)) { case 'U' : - a_string = realloc_string_sub(a_string, "%U", username); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%U", username); break; case 'u' : - a_string = realloc_string_sub(a_string, "%u", username); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%u", username); break; case 'G' : if (gid != -1) { - a_string = realloc_string_sub(a_string, "%G", gidtoname(gid)); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%G", + gidtoname(gid)); } else { - a_string = realloc_string_sub(a_string, "%G", "NO_GROUP"); + a_string = talloc_string_sub( + tmp_ctx, a_string, + "%G", "NO_GROUP"); } break; case 'g' : if (gid != -1) { - a_string = realloc_string_sub(a_string, "%g", gidtoname(gid)); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%g", + gidtoname(gid)); } else { - a_string = realloc_string_sub(a_string, "%g", "NO_GROUP"); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%g", "NO_GROUP"); } break; case 'D' : - a_string = realloc_string_sub(a_string, "%D", domain); + a_string = talloc_string_sub(tmp_ctx, a_string, + "%D", domain); break; case 'N' : - a_string = realloc_string_sub(a_string, "%N", automount_server(username)); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%N", + automount_server(username)); break; default: break; @@ -645,42 +648,27 @@ char *alloc_sub_specified(const char *input_string, p++; if (a_string == NULL) { - return NULL; + goto done; } } - ret_string = alloc_sub_basic(username, a_string); - SAFE_FREE(a_string); - return ret_string; -} + /* Watch out, using "mem_ctx" here, so all intermediate stuff goes + * away with the TALLOC_FREE(tmp_ctx) further down. */ -/**************************************************************************** -****************************************************************************/ + ret_string = talloc_sub_basic(mem_ctx, username, domain, a_string); -char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, - int snum, - const char *user, - const char *connectpath, - gid_t gid, - const char *smb_name, - const char *str) -{ - char *a, *t; - a = alloc_sub_advanced(snum, user, connectpath, gid, smb_name, str); - if (!a) { - return NULL; - } - t = talloc_strdup(mem_ctx, a); - SAFE_FREE(a); - return t; + done: + TALLOC_FREE(tmp_ctx); + return ret_string; } /**************************************************************************** ****************************************************************************/ -char *alloc_sub_advanced(int snum, const char *user, - const char *connectpath, gid_t gid, - const char *smb_name, const char *str) +char *alloc_sub_advanced(const char *servicename, const char *user, + const char *connectpath, gid_t gid, + const char *smb_name, const char *domain_name, + const char *str) { char *a_string, *ret_string; char *b, *p, *s, *h; @@ -707,7 +695,7 @@ char *alloc_sub_advanced(int snum, const char *user, a_string = realloc_string_sub(a_string, "%P", connectpath); break; case 'S': - a_string = realloc_string_sub(a_string, "%S", lp_servicename(snum)); + a_string = realloc_string_sub(a_string, "%S", servicename); break; case 'g': a_string = realloc_string_sub(a_string, "%g", gidtoname(gid)); @@ -724,7 +712,8 @@ char *alloc_sub_advanced(int snum, const char *user, * "path =" string in [homes] and so needs the * service name, not the username. */ case 'p': - a_string = realloc_string_sub(a_string, "%p", automount_path(lp_servicename(snum))); + a_string = realloc_string_sub(a_string, "%p", + automount_path(servicename)); break; default: @@ -737,67 +726,20 @@ char *alloc_sub_advanced(int snum, const char *user, } } - ret_string = alloc_sub_basic(smb_name, a_string); + ret_string = alloc_sub_basic(smb_name, domain_name, a_string); SAFE_FREE(a_string); return ret_string; } -/**************************************************************************** - Do some standard substitutions in a string. -****************************************************************************/ - -void standard_sub_conn(connection_struct *conn, char *str, size_t len) -{ - char *s; - - s = alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath, - conn->gid, smb_user_name, str); - - if ( s ) { - strncpy( str, s, len ); - SAFE_FREE( s ); - } -} - -/**************************************************************************** -****************************************************************************/ - -char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *str) -{ - return talloc_sub_advanced(mem_ctx, SNUM(conn), conn->user, - conn->connectpath, conn->gid, - smb_user_name, str); -} - -/**************************************************************************** -****************************************************************************/ - -char *alloc_sub_conn(connection_struct *conn, const char *str) -{ - return alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath, - conn->gid, smb_user_name, str); -} - -/**************************************************************************** - Like standard_sub but by snum. -****************************************************************************/ - -void standard_sub_snum(int snum, char *str, size_t len) +void standard_sub_advanced(const char *servicename, const char *user, + const char *connectpath, gid_t gid, + const char *smb_name, const char *domain_name, + char *str, size_t len) { - static uid_t cached_uid = -1; - static fstring cached_user; char *s; - /* calling uidtoname() on every substitute would be too expensive, so - we cache the result here as nearly every call is for the same uid */ - - if (cached_uid != current_user.ut.uid) { - fstrcpy(cached_user, uidtoname(current_user.ut.uid)); - cached_uid = current_user.ut.uid; - } - - s = alloc_sub_advanced(snum, cached_user, "", current_user.ut.gid, - smb_user_name, str); + s = alloc_sub_advanced(servicename, user, connectpath, + gid, smb_name, domain_name, str); if ( s ) { strncpy( str, s, len ); diff --git a/source/lib/system.c b/source/lib/system.c index 2e5f42307bd..24c726b8f75 100644 --- a/source/lib/system.c +++ b/source/lib/system.c @@ -922,16 +922,94 @@ void sys_endpwent(void) Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid() ****************************************************************************/ +#ifdef ENABLE_BUILD_FARM_HACKS + +/* + * In the build farm we want to be able to join machines to the domain. As we + * don't have root access, we need to bypass direct access to /etc/passwd + * after a user has been created via samr. Fake those users. + */ + +static struct passwd *fake_pwd; +static int num_fake_pwd; + struct passwd *sys_getpwnam(const char *name) { + int i; + + for (i=0; i<num_fake_pwd; i++) { + if (strcmp(fake_pwd[i].pw_name, name) == 0) { + DEBUG(10, ("Returning fake user %s\n", name)); + return &fake_pwd[i]; + } + } + return getpwnam(name); } struct passwd *sys_getpwuid(uid_t uid) { + int i; + + for (i=0; i<num_fake_pwd; i++) { + if (fake_pwd[i].pw_uid == uid) { + DEBUG(10, ("Returning fake user %s\n", + fake_pwd[i].pw_name)); + return &fake_pwd[i]; + } + } + return getpwuid(uid); } +void faked_create_user(const char *name) +{ + int i; + uid_t uid; + struct passwd new_pwd; + + for (i=0; i<10; i++) { + generate_random_buffer((unsigned char *)&uid, + sizeof(uid)); + if (getpwuid(uid) == NULL) { + break; + } + } + + if (i==10) { + /* Weird. No free uid found... */ + return; + } + + new_pwd.pw_name = SMB_STRDUP(name); + new_pwd.pw_passwd = SMB_STRDUP("x"); + new_pwd.pw_uid = uid; + new_pwd.pw_gid = 100; + new_pwd.pw_gecos = SMB_STRDUP("faked user"); + new_pwd.pw_dir = SMB_STRDUP("/nodir"); + new_pwd.pw_shell = SMB_STRDUP("/bin/false"); + + ADD_TO_ARRAY(NULL, struct passwd, new_pwd, &fake_pwd, + &num_fake_pwd); + + DEBUG(10, ("Added fake user %s, have %d fake users\n", + name, num_fake_pwd)); +} + +#else + +struct passwd *sys_getpwnam(const char *name) +{ + return getpwnam(name); +} + +struct passwd *sys_getpwuid(uid_t uid) +{ + return getpwuid(uid); +} + +#endif + struct group *sys_getgrnam(const char *name) { return getgrnam(name); diff --git a/source/lib/talloc.c b/source/lib/talloc.c index 51087ef9791..9d824411379 100644 --- a/source/lib/talloc.c +++ b/source/lib/talloc.c @@ -85,6 +85,7 @@ static const void *null_context; static void *cleanup_context; +static void *talloc_steal(const void *new_ctx, const void *ptr); struct talloc_reference_handle { struct talloc_reference_handle *next, *prev; @@ -665,7 +666,7 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n ptr on success, or NULL if it could not be transferred. passing NULL as ptr will always return NULL with no side effects. */ -void *talloc_steal(const void *new_ctx, const void *ptr) +static void *talloc_steal(const void *new_ctx, const void *ptr) { struct talloc_chunk *tc, *new_tc; @@ -1138,9 +1139,7 @@ char *talloc_asprintf(const void *t, const char *fmt, ...) * accumulating output into a string buffer. **/ -static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); - -static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) +char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) { struct talloc_chunk *tc; int len, s_len; diff --git a/source/lib/talloctort.c b/source/lib/talloctort.c index 6504203a7ad..3ce45e20714 100644 --- a/source/lib/talloctort.c +++ b/source/lib/talloctort.c @@ -656,6 +656,7 @@ static BOOL test_type(void) return True; } +#if 0 /* test steal */ @@ -709,6 +710,7 @@ static BOOL test_steal(void) return True; } +#endif /* test talloc_realloc_fn @@ -819,7 +821,7 @@ BOOL torture_local_talloc(void) ret &= test_misc(); ret &= test_realloc(); ret &= test_realloc_child(); - ret &= test_steal(); +/* ret &= test_steal(); */ ret &= test_unref_reparent(); ret &= test_realloc_fn(); ret &= test_type(); diff --git a/source/lib/time.c b/source/lib/time.c index 9a539d415e8..0bfdfac856b 100644 --- a/source/lib/time.c +++ b/source/lib/time.c @@ -635,7 +635,7 @@ char *http_timestring(time_t t) Return the date and time as a string ****************************************************************************/ -char *timestring(BOOL hires) +char *current_timestring(BOOL hires) { static fstring TimeBuf; struct timeval tp; @@ -1056,6 +1056,51 @@ struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs) } #endif + +/** + Return the date and time as a string +**/ +char *timestring(TALLOC_CTX *mem_ctx, time_t t) +{ + char *TimeBuf; + char tempTime[80]; + struct tm *tm; + + tm = localtime(&t); + if (!tm) { + return talloc_asprintf(mem_ctx, + "%ld seconds since the Epoch", + (long)t); + } + +#ifdef HAVE_STRFTIME + /* some versions of gcc complain about using %c. This is a bug + in the gcc warning, not a bug in this code. See a recent + strftime() manual page for details. + */ + strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm); + TimeBuf = talloc_strdup(mem_ctx, tempTime); +#else + TimeBuf = talloc_strdup(mem_ctx, asctime(tm)); +#endif + + return TimeBuf; +} + + +/** + return a talloced string representing a NTTIME for human consumption +*/ +const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt) +{ + time_t t; + if (nt.low == 0 && nt.high == 0) { + return "NTTIME(0)"; + } + t = nt_time_to_unix(&nt); + return timestring(mem_ctx, t); +} + /**************************************************************************** Utility function that always returns a const string even if localtime and asctime fail. diff --git a/source/lib/util.c b/source/lib/util.c index a1efecfbbba..96263bf3947 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -753,7 +753,7 @@ ssize_t transfer_file_internal(int infd, int outfd, size_t n, ssize_t (*read_fn) size_t num_to_read_thistime; size_t num_written = 0; - if ((buf = SMB_MALLOC(TRANSFER_BUF_SIZE)) == NULL) + if ((buf = SMB_MALLOC_ARRAY(char, TRANSFER_BUF_SIZE)) == NULL) return -1; while (total < n) { @@ -1052,9 +1052,11 @@ void *realloc_array(void *p, size_t el_size, unsigned int count, BOOL free_old_o ****************************************************************************/ void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size, - void *element, void **array, uint32 *num_elements, + void *element, void *_array, uint32 *num_elements, ssize_t *array_size) { + void **array = (void **)_array; + if (*array_size < 0) { return; } diff --git a/source/lib/util_reg.c b/source/lib/util_reg.c new file mode 100644 index 00000000000..3f0b2d6a42c --- /dev/null +++ b/source/lib/util_reg.c @@ -0,0 +1,110 @@ +/* + * Unix SMB/CIFS implementation. + * Registry helper routines + * Copyright (C) Volker Lendecke 2006 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 675 + * Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +const char *reg_type_lookup(uint32 type) +{ + const char *result; + + switch(type) { + case REG_NONE: + result = "REG_NONE"; + break; + case REG_SZ: + result = "REG_SZ"; + break; + case REG_EXPAND_SZ: + result = "REG_EXPAND_SZ"; + break; + case REG_BINARY: + result = "REG_BINARY"; + break; + case REG_DWORD: + result = "REG_DWORD"; + break; + case REG_DWORD_BE: + result = "REG_DWORD_BE"; + break; + case REG_LINK: + result = "REG_LINK"; + break; + case REG_MULTI_SZ: + result = "REG_MULTI_SZ"; + break; + case REG_RESOURCE_LIST: + result = "REG_RESOURCE_LIST"; + break; + case REG_FULL_RESOURCE_DESCRIPTOR: + result = "REG_FULL_RESOURCE_DESCRIPTOR"; + break; + case REG_RESOURCE_REQUIREMENTS_LIST: + result = "REG_RESOURCE_REQUIREMENTS_LIST"; + break; + case REG_QWORD: + result = "REG_QWORD"; + break; + default: + result = "REG TYPE IS UNKNOWN"; + break; + } + return result; +} + +NTSTATUS reg_pull_multi_sz(TALLOC_CTX *mem_ctx, const void *buf, size_t len, + int *num_values, char ***values) +{ + const smb_ucs2_t *p = (const smb_ucs2_t *)buf; + *num_values = 0; + + /* + * Make sure that a talloc context for the strings retrieved exists + */ + + if (!(*values = TALLOC_ARRAY(mem_ctx, char *, 1))) { + return NT_STATUS_NO_MEMORY; + } + + len /= 2; /* buf is a set of UCS2 strings */ + + while (len > 0) { + char *val; + size_t dstlen, thislen; + + thislen = strnlen_w(p, len) + 1; + dstlen = convert_string_allocate(*values, CH_UCS2, CH_UNIX, + p, thislen*2, (void *)&val, + True); + if (dstlen == (size_t)-1) { + TALLOC_FREE(*values); + return NT_STATUS_NO_MEMORY; + } + + ADD_TO_ARRAY(*values, char *, val, values, num_values); + if (*values == NULL) { + return NT_STATUS_NO_MEMORY; + } + + p += thislen; + len -= thislen; + } + + return NT_STATUS_OK; +} diff --git a/source/lib/util_str.c b/source/lib/util_str.c index 938fb0f47b0..2580521c3b9 100644 --- a/source/lib/util_str.c +++ b/source/lib/util_str.c @@ -5,6 +5,7 @@ Copyright (C) Andrew Tridgell 1992-2001 Copyright (C) Simo Sorce 2001-2002 Copyright (C) Martin Pool 2003 + Copyright (C) James Peach 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1914,13 +1915,14 @@ int str_list_count( const char **list ) for the work *****************************************************************************/ -BOOL str_list_sub_basic( char **list, const char *smb_name ) +BOOL str_list_sub_basic( char **list, const char *smb_name, + const char *domain_name ) { char *s, *tmpstr; while ( *list ) { s = *list; - tmpstr = alloc_sub_basic(smb_name, s); + tmpstr = alloc_sub_basic(smb_name, domain_name, s); if ( !tmpstr ) { DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n")); return False; @@ -2302,6 +2304,73 @@ SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr) return val; } +/* Convert a size specification to a count of bytes. We accept the following + * suffixes: + * bytes if there is no suffix + * kK kibibytes + * mM mebibytes + * gG gibibytes + * tT tibibytes + * pP whatever the ISO name for petabytes is + * + * Returns 0 if the string can't be converted. + */ +SMB_OFF_T conv_str_size(const char * str) +{ + SMB_OFF_T lval; + char * end; + + if (str == NULL || *str == '\0') { + return 0; + } + +#ifdef HAVE_STRTOULL + if (sizeof(SMB_OFF_T) == 8) { + lval = strtoull(str, &end, 10 /* base */); + } else { + lval = strtoul(str, &end, 10 /* base */); + } +#else + lval = strtoul(str, &end, 10 /* base */); +#endif + + if (end == NULL || end == str) { + return 0; + } + + if (*end) { + SMB_OFF_T lval_orig = lval; + + if (strwicmp(end, "K") == 0) { + lval *= (SMB_OFF_T)1024; + } else if (strwicmp(end, "M") == 0) { + lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024); + } else if (strwicmp(end, "G") == 0) { + lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 * + (SMB_OFF_T)1024); + } else if (strwicmp(end, "T") == 0) { + lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 * + (SMB_OFF_T)1024 * (SMB_OFF_T)1024); + } else if (strwicmp(end, "P") == 0) { + lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 * + (SMB_OFF_T)1024 * (SMB_OFF_T)1024 * + (SMB_OFF_T)1024); + } else { + return 0; + } + + /* Primitive attempt to detect wrapping on platforms with + * 4-byte SMB_OFF_T. It's better to let the caller handle + * a failure than some random number. + */ + if (lval_orig <= lval) { + return 0; + } + } + + return lval; +} + void string_append(char **left, const char *right) { int new_len = strlen(right) + 1; @@ -2454,3 +2523,52 @@ BOOL validate_net_name( const char *name, const char *invalid_chars, int max_len return True; } + +/** +return the number of bytes occupied by a buffer in ASCII format +the result includes the null termination +limited by 'n' bytes +**/ +size_t ascii_len_n(const char *src, size_t n) +{ + size_t len; + + len = strnlen(src, n); + if (len+1 <= n) { + len += 1; + } + + return len; +} + +/** +return the number of bytes occupied by a buffer in CH_UTF16 format +the result includes the null termination +**/ +size_t utf16_len(const void *buf) +{ + size_t len; + + for (len = 0; SVAL(buf,len); len += 2) ; + + return len + 2; +} + +/** +return the number of bytes occupied by a buffer in CH_UTF16 format +the result includes the null termination +limited by 'n' bytes +**/ +size_t utf16_len_n(const void *src, size_t n) +{ + size_t len; + + for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ; + + if (len+2 <= n) { + len += 2; + } + + return len; +} + diff --git a/source/libads/dns.c b/source/libads/dns.c index d2e263a9d1b..321b4355277 100644 --- a/source/libads/dns.c +++ b/source/libads/dns.c @@ -39,8 +39,12 @@ #define MAX_DNS_PACKET_SIZE 0xffff #ifdef NS_HFIXEDSZ /* Bind 8/9 interface */ +#if !defined(C_IN) /* AIX 5.3 already defines C_IN */ # define C_IN ns_c_in +#endif +#if !defined(T_A) /* AIX 5.3 already defines T_A */ # define T_A ns_t_a +#endif # define T_SRV ns_t_srv #else # ifdef HFIXEDSZ diff --git a/source/libads/ldap.c b/source/libads/ldap.c index b017ff941b9..58eca99f9e1 100644 --- a/source/libads/ldap.c +++ b/source/libads/ldap.c @@ -831,10 +831,11 @@ ADS_STATUS ads_search(ADS_STRUCT *ads, void **res, * @param attrs Attributes to retrieve * @return status of search **/ -ADS_STATUS ads_search_dn(ADS_STRUCT *ads, void **res, +ADS_STATUS ads_search_dn(ADS_STRUCT *ads, void *_res, const char *dn, const char **attrs) { + void **res = (void **)_res; return ads_do_search(ads, dn, LDAP_SCOPE_BASE, "(objectclass=*)", attrs, res); } @@ -973,8 +974,9 @@ ADS_MODLIST ads_init_mods(TALLOC_CTX *ctx) */ static ADS_STATUS ads_modlist_add(TALLOC_CTX *ctx, ADS_MODLIST *mods, int mod_op, const char *name, - const void **invals) + const void *_invals) { + const void **invals = (const void **)_invals; int curmod; LDAPMod **modlist = (LDAPMod **) *mods; struct berval **ber_values = NULL; @@ -1037,8 +1039,7 @@ ADS_STATUS ads_mod_str(TALLOC_CTX *ctx, ADS_MODLIST *mods, if (!val) return ads_modlist_add(ctx, mods, LDAP_MOD_DELETE, name, NULL); - return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE, name, - (const void **) values); + return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE, name, values); } /** diff --git a/source/libads/sasl.c b/source/libads/sasl.c index a12af43eb37..3c0bea93d6c 100644 --- a/source/libads/sasl.c +++ b/source/libads/sasl.c @@ -278,7 +278,6 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads) uint8 *p; uint32 max_msg_size; char *sname; - unsigned sec_layer; ADS_STATUS status; krb5_principal principal; krb5_context ctx = NULL; @@ -391,7 +390,6 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads) file_save("sasl_gssapi.dat", output_token.value, output_token.length); #endif max_msg_size = (p[1]<<16) | (p[2]<<8) | p[3]; - sec_layer = *p; gss_release_buffer(&minor_status, &output_token); diff --git a/source/libmsrpc/cac_lsarpc.c b/source/libmsrpc/cac_lsarpc.c index 7b62b4d4627..72c429e7247 100644 --- a/source/libmsrpc/cac_lsarpc.c +++ b/source/libmsrpc/cac_lsarpc.c @@ -49,7 +49,7 @@ int cac_LsaOpenPolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenP /*see if there is already an active session on this pipe, if not then open one*/ if(!hnd->_internal.pipes[PI_LSARPC]) { - pipe_hnd = cli_rpc_pipe_open_noauth(&(srv->cli), PI_LSARPC, &(hnd->status)); + pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_LSARPC, &hnd->status); if(!pipe_hnd) { hnd->status = NT_STATUS_UNSUCCESSFUL; diff --git a/source/libmsrpc/cac_samr.c b/source/libmsrpc/cac_samr.c index 60c6562988e..a29ee7a41eb 100644 --- a/source/libmsrpc/cac_samr.c +++ b/source/libmsrpc/cac_samr.c @@ -55,7 +55,7 @@ int cac_SamConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamConnect /*initialize for samr pipe if we have to*/ if(!hnd->_internal.pipes[PI_SAMR]) { - if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SAMR, &(hnd->status)))) { + if(!(pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_SAMR, &hnd->status))) { return CAC_FAILURE; } @@ -1507,7 +1507,7 @@ int cac_SamUserChangePasswd(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Sa /*open a session on SAMR if we don't have one*/ if(!hnd->_internal.pipes[PI_SAMR]) { - if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SAMR, &(hnd->status)))) { + if(!(pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_SAMR, &hnd->status))) { return CAC_FAILURE; } @@ -1576,7 +1576,7 @@ int cac_SamEnableUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *use } /*now set the userinfo*/ - hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10, &(srv->cli.user_session_key), ctr); + hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10, &srv->cli->user_session_key, ctr); /*this will only work properly if we use set_userinfo2 - fail if it is not supported*/ if(!NT_STATUS_IS_OK(hnd->status)) @@ -1630,7 +1630,7 @@ int cac_SamDisableUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *us ctr->info.id16->acb_info ^= ACB_DISABLED; /*this will only work properly if we use set_userinfo2*/ - hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10, &(srv->cli.user_session_key), ctr); + hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10, &srv->cli->user_session_key, ctr); /*this will only work properly if we use set_userinfo2 fail if it is not supported*/ if(!NT_STATUS_IS_OK(hnd->status)) @@ -1682,7 +1682,7 @@ int cac_SamSetPassword(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetP ctr.switch_value = 24; ctr.info.id24 = &info24; - hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 24, &(srv->cli.user_session_key), &ctr); + hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 24, &srv->cli->user_session_key, &ctr); if(!NT_STATUS_IS_OK(hnd->status)) return CAC_FAILURE; @@ -1767,11 +1767,11 @@ int cac_SamSetUserInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetU } if(hnd->_internal.srv_level >= SRV_WIN_NT4) { - hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, op->in.user_hnd, 21, &(srv->cli.user_session_key), ctr); + hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, op->in.user_hnd, 21, &srv->cli->user_session_key, ctr); } if(hnd->_internal.srv_level < SRV_WIN_NT4 || !NT_STATUS_IS_OK(hnd->status)) { - hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 21, &(srv->cli.user_session_key), ctr); + hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 21, &srv->cli->user_session_key, ctr); if(NT_STATUS_IS_OK(hnd->status) && hnd->_internal.srv_level > SRV_WIN_NT4) { hnd->_internal.srv_level = SRV_WIN_NT4; @@ -1850,7 +1850,7 @@ int cac_SamSetUserInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamS } - hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, op->in.ctr->switch_value, &(srv->cli.user_session_key), op->in.ctr); + hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, op->in.ctr->switch_value, &srv->cli->user_session_key, op->in.ctr); if(!NT_STATUS_IS_OK(hnd->status)) return CAC_FAILURE; @@ -1899,7 +1899,7 @@ int cac_SamRenameUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRenam ctr.switch_value = 7; ctr.info.id7 = &info7; - hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 7, &(srv->cli.user_session_key), &ctr); + hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 7, &srv->cli->user_session_key, &ctr); if(!NT_STATUS_IS_OK(hnd->status)) return CAC_FAILURE; diff --git a/source/libmsrpc/cac_svcctl.c b/source/libmsrpc/cac_svcctl.c index 83dc0364930..51a5b5d2dd9 100644 --- a/source/libmsrpc/cac_svcctl.c +++ b/source/libmsrpc/cac_svcctl.c @@ -51,7 +51,7 @@ int cac_SvcOpenScm(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenScm /*initialize for samr pipe if we have to*/ if(!hnd->_internal.pipes[PI_SVCCTL]) { - if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SVCCTL, &(hnd->status)))) { + if(!(pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_SVCCTL, &(hnd->status)))) { hnd->status = NT_STATUS_UNSUCCESSFUL; return CAC_FAILURE; } diff --git a/source/libmsrpc/cac_winreg.c b/source/libmsrpc/cac_winreg.c index 6ef898eb16d..91db33d2953 100644 --- a/source/libmsrpc/cac_winreg.c +++ b/source/libmsrpc/cac_winreg.c @@ -49,7 +49,7 @@ int cac_RegConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegConnect /*initialize for winreg pipe if we have to*/ if(!hnd->_internal.pipes[PI_WINREG]) { - if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_WINREG, &(hnd->status)))) { + if(!(pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_WINREG, &hnd->status))) { return CAC_FAILURE; } @@ -966,7 +966,7 @@ int cac_Shutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Shutdown *op) /*initialize for winreg pipe if we have to*/ if(!hnd->_internal.pipes[PI_SHUTDOWN]) { - if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SHUTDOWN, &(hnd->status)))) { + if(!(pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_SHUTDOWN, &(hnd->status)))) { return CAC_FAILURE; } diff --git a/source/libmsrpc/libmsrpc_internal.c b/source/libmsrpc/libmsrpc_internal.c index 3a47361db29..a097bc181ce 100644 --- a/source/libmsrpc/libmsrpc_internal.c +++ b/source/libmsrpc/libmsrpc_internal.c @@ -23,30 +23,33 @@ #include "libmsrpc_internal.h" /*used to get a struct rpc_pipe_client* to be passed into rpccli* calls*/ -struct rpc_pipe_client *cac_GetPipe(CacServerHandle *hnd, int pi_idx) { - SMBCSRV *srv = NULL; - struct rpc_pipe_client *pipe_hnd = NULL; +struct rpc_pipe_client *cac_GetPipe(CacServerHandle *hnd, int pi_idx) +{ + SMBCSRV *srv = NULL; + struct rpc_pipe_client *pipe_hnd = NULL; - if(!hnd) - return NULL; + if(!hnd) { + return NULL; + } - if(hnd->_internal.pipes[pi_idx] == False) { - hnd->status = NT_STATUS_INVALID_HANDLE; - return NULL; - } + if(hnd->_internal.pipes[pi_idx] == False) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return NULL; + } - srv = cac_GetServer(hnd); - if(!srv) { - hnd->status = NT_STATUS_INVALID_CONNECTION; - return NULL; - } + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return NULL; + } - pipe_hnd = srv->cli.pipe_list; + pipe_hnd = srv->cli->pipe_list; - while(pipe_hnd != NULL && pipe_hnd->pipe_idx != pi_idx) - pipe_hnd = pipe_hnd->next; + while(pipe_hnd != NULL && pipe_hnd->pipe_idx != pi_idx) { + pipe_hnd = pipe_hnd->next; + } - return pipe_hnd; + return pipe_hnd; } /*takes a string like HKEY_LOCAL_MACHINE\HARDWARE\ACPI and returns the reg_type code and then a pointer to the start of the path (HARDWARE)*/ @@ -324,7 +327,7 @@ SAM_USERINFO_CTR *cac_MakeUserInfoCtr(TALLOC_CTX *mem_ctx, CacUserInfo *info) { SAM_USERINFO_CTR *ctr = NULL; /*the flags we are 'setting'- include/passdb.h*/ - uint32 flags = ACCT_USERNAME | ACCT_FULL_NAME | ACCT_PRIMARY_GID | ACCT_ADMIN_DESC | ACCT_DESCRIPTION | + uint32 flags = ACCT_USERNAME | ACCT_FULL_NAME | ACCT_PRIMARY_GID | ACCT_DESCRIPTION | ACCT_COMMENT | ACCT_HOME_DIR | ACCT_HOME_DRIVE | ACCT_LOGON_SCRIPT | ACCT_PROFILE | ACCT_WORKSTATIONS | ACCT_FLAGS; diff --git a/source/libndr/libndr.h b/source/libndr/libndr.h new file mode 100644 index 00000000000..817c4610751 --- /dev/null +++ b/source/libndr/libndr.h @@ -0,0 +1,296 @@ +/* + Unix SMB/CIFS implementation. + rpc interface definitions + Copyright (C) Andrew Tridgell 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __LIBNDR_H__ +#define __LIBNDR_H__ + +#define _PRINTF_ATTRIBUTE(a,b) + +#include "libndr/misc.h" +#include "libndr/security.h" + +struct dcerpc_syntax_id { + struct GUID uuid; + uint32_t if_version; +}/* [public] */; + +/* + this provides definitions for the libcli/rpc/ MSRPC library +*/ + + +/* + this is used by the token store/retrieve code +*/ +struct ndr_token_list { + struct ndr_token_list *next, *prev; + const void *key; + uint32_t value; +}; + +/* this is the base structure passed to routines that + parse MSRPC formatted data + + note that in Samba4 we use separate routines and structures for + MSRPC marshalling and unmarshalling. Also note that these routines + are being kept deliberately very simple, and are not tied to a + particular transport +*/ +struct ndr_pull { + uint32_t flags; /* LIBNDR_FLAG_* */ + uint8_t *data; + uint32_t data_size; + uint32_t offset; + + uint32_t relative_base_offset; + struct ndr_token_list *relative_base_list; + + struct ndr_token_list *relative_list; + struct ndr_token_list *array_size_list; + struct ndr_token_list *array_length_list; + struct ndr_token_list *switch_list; + + TALLOC_CTX *current_mem_ctx; + + /* this is used to ensure we generate unique reference IDs + between request and reply */ + uint32_t ptr_count; +}; + +struct ndr_pull_save { + uint32_t data_size; + uint32_t offset; + struct ndr_pull_save *next; +}; + +/* structure passed to functions that generate NDR formatted data */ +struct ndr_push { + uint32_t flags; /* LIBNDR_FLAG_* */ + uint8_t *data; + uint32_t alloc_size; + uint32_t offset; + + uint32_t relative_base_offset; + struct ndr_token_list *relative_base_list; + + struct ndr_token_list *switch_list; + struct ndr_token_list *relative_list; + struct ndr_token_list *nbt_string_list; + + /* this is used to ensure we generate unique reference IDs */ + uint32_t ptr_count; +}; + +struct ndr_push_save { + uint32_t offset; + struct ndr_push_save *next; +}; + + +/* structure passed to functions that print IDL structures */ +struct ndr_print { + uint32_t flags; /* LIBNDR_FLAG_* */ + uint32_t depth; + struct ndr_token_list *switch_list; + void (*print)(struct ndr_print *, const char *, ...); + void *private_data; +}; + +#define LIBNDR_FLAG_BIGENDIAN (1<<0) +#define LIBNDR_FLAG_NOALIGN (1<<1) + +#define LIBNDR_FLAG_STR_ASCII (1<<2) +#define LIBNDR_FLAG_STR_LEN4 (1<<3) +#define LIBNDR_FLAG_STR_SIZE4 (1<<4) +#define LIBNDR_FLAG_STR_NOTERM (1<<5) +#define LIBNDR_FLAG_STR_NULLTERM (1<<6) +#define LIBNDR_FLAG_STR_SIZE2 (1<<7) +#define LIBNDR_FLAG_STR_BYTESIZE (1<<8) +#define LIBNDR_FLAG_STR_FIXLEN32 (1<<9) +#define LIBNDR_FLAG_STR_CONFORMANT (1<<10) +#define LIBNDR_FLAG_STR_CHARLEN (1<<11) +#define LIBNDR_FLAG_STR_UTF8 (1<<12) +#define LIBNDR_FLAG_STR_FIXLEN15 (1<<13) +#define LIBNDR_STRING_FLAGS (0x7FFC) + + +#define LIBNDR_FLAG_REF_ALLOC (1<<20) +#define LIBNDR_FLAG_REMAINING (1<<21) +#define LIBNDR_FLAG_ALIGN2 (1<<22) +#define LIBNDR_FLAG_ALIGN4 (1<<23) +#define LIBNDR_FLAG_ALIGN8 (1<<24) + +#define LIBNDR_ALIGN_FLAGS (LIBNDR_FLAG_ALIGN2|LIBNDR_FLAG_ALIGN4|LIBNDR_FLAG_ALIGN8) + +#define LIBNDR_PRINT_ARRAY_HEX (1<<25) +#define LIBNDR_PRINT_SET_VALUES (1<<26) + +/* used to force a section of IDL to be little-endian */ +#define LIBNDR_FLAG_LITTLE_ENDIAN (1<<27) + +/* used to check if alignment padding is zero */ +#define LIBNDR_FLAG_PAD_CHECK (1<<28) + +/* set if an object uuid will be present */ +#define LIBNDR_FLAG_OBJECT_PRESENT (1<<30) + +/* set to avoid recursion in ndr_size_*() calculation */ +#define LIBNDR_FLAG_NO_NDR_SIZE (1<<31) + +/* useful macro for debugging */ +#define NDR_PRINT_DEBUG(type, p) ndr_print_debug((ndr_print_fn_t)ndr_print_ ##type, #p, p) +#define NDR_PRINT_UNION_DEBUG(type, level, p) ndr_print_union_debug((ndr_print_fn_t)ndr_print_ ##type, #p, level, p) +#define NDR_PRINT_FUNCTION_DEBUG(type, flags, p) ndr_print_function_debug((ndr_print_function_t)ndr_print_ ##type, #type, flags, p) +#define NDR_PRINT_BOTH_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_BOTH, p) +#define NDR_PRINT_OUT_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_OUT, p) +#define NDR_PRINT_IN_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_IN | NDR_SET_VALUES, p) + +#define NDR_BE(ndr) (((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == LIBNDR_FLAG_BIGENDIAN) + +enum ndr_err_code { + NDR_ERR_ARRAY_SIZE, + NDR_ERR_BAD_SWITCH, + NDR_ERR_OFFSET, + NDR_ERR_RELATIVE, + NDR_ERR_CHARCNV, + NDR_ERR_LENGTH, + NDR_ERR_SUBCONTEXT, + NDR_ERR_COMPRESSION, + NDR_ERR_STRING, + NDR_ERR_VALIDATE, + NDR_ERR_BUFSIZE, + NDR_ERR_ALLOC, + NDR_ERR_RANGE, + NDR_ERR_TOKEN, + NDR_ERR_IPV4ADDRESS +}; + +enum ndr_compression_alg { + NDR_COMPRESSION_MSZIP = 2, + NDR_COMPRESSION_XPRESS = 3 +}; + +/* + flags passed to control parse flow +*/ +#define NDR_SCALARS 1 +#define NDR_BUFFERS 2 + +/* + flags passed to ndr_print_*() +*/ +#define NDR_IN 1 +#define NDR_OUT 2 +#define NDR_BOTH 3 +#define NDR_SET_VALUES 4 + +#define NDR_PULL_NEED_BYTES(ndr, n) do { \ + if ((n) > ndr->data_size || ndr->offset + (n) > ndr->data_size) { \ + return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "Pull bytes %u", (unsigned)n); \ + } \ +} while(0) + +#define NDR_ALIGN(ndr, n) ndr_align_size(ndr->offset, n) + +#define NDR_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1)) + +#define NDR_PULL_ALIGN(ndr, n) do { \ + if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \ + if (ndr->flags & LIBNDR_FLAG_PAD_CHECK) { \ + ndr_check_padding(ndr, n); \ + } \ + ndr->offset = (ndr->offset + (n-1)) & ~(n-1); \ + } \ + if (ndr->offset > ndr->data_size) { \ + return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "Pull align %u", (unsigned)n); \ + } \ +} while(0) + +#define NDR_PUSH_NEED_BYTES(ndr, n) NDR_CHECK(ndr_push_expand(ndr, ndr->offset+(n))) + +#define NDR_PUSH_ALIGN(ndr, n) do { \ + if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \ + uint32_t _pad = ((ndr->offset + (n-1)) & ~(n-1)) - ndr->offset; \ + while (_pad--) NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 0)); \ + } \ +} while(0) + +/* these are used to make the error checking on each element in libndr + less tedious, hopefully making the code more readable */ +#define NDR_CHECK(call) do { NTSTATUS _status; \ + _status = call; \ + if (!NT_STATUS_IS_OK(_status)) \ + return _status; \ + } while (0) + +#define NDR_PULL_GET_MEM_CTX(ndr) (ndr->current_mem_ctx) + +#define NDR_PULL_SET_MEM_CTX(ndr, mem_ctx, flgs) do {\ + if ( !(flgs) || (ndr->flags & flgs) ) {\ + if (!(mem_ctx)) {\ + return ndr_pull_error(ndr, NDR_ERR_ALLOC, "NDR_PULL_SET_MEM_CTX(NULL): %s\n", __location__); \ + }\ + ndr->current_mem_ctx = mem_ctx;\ + }\ +} while(0) + +#define _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr) do {\ + if (!ndr->current_mem_ctx) {\ + ndr->current_mem_ctx = talloc_new(ndr);\ + if (!ndr->current_mem_ctx) {\ + return ndr_pull_error(ndr, NDR_ERR_ALLOC, "_NDR_PULL_FIX_CURRENT_MEM_CTX() failed: %s\n", __location__); \ + }\ + }\ +} while(0) + +#define NDR_PULL_ALLOC_SIZE(ndr, s, size) do { \ + _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\ + (s) = talloc_size(ndr->current_mem_ctx, size); \ + if (!(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %u failed: %s\n",(unsigned)size, __location__); \ +} while (0) + +#define NDR_PULL_ALLOC(ndr, s) NDR_PULL_ALLOC_SIZE(ndr, s, sizeof(*(s))) + +#define NDR_PULL_ALLOC_N_SIZE(ndr, s, n, elsize) do { \ + _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\ + (s) = talloc_array_size(ndr->current_mem_ctx, elsize, n); \ + if (!(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %u * %u failed: %s\n", (unsigned)n, (unsigned)elsize, __location__); \ +} while (0) + +#define NDR_PULL_ALLOC_N(ndr, s, n) NDR_PULL_ALLOC_N_SIZE(ndr, s, n, sizeof(*(s))) + + +#define NDR_PUSH_ALLOC_SIZE(ndr, s, size) do { \ + (s) = talloc_size(ndr, size); \ + if (!(s)) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %u failed: %s\n", (unsigned)size, __location__); \ +} while (0) + +#define NDR_PUSH_ALLOC(ndr, s) NDR_PUSH_ALLOC_SIZE(ndr, s, sizeof(*(s))) + +/* these are used when generic fn pointers are needed for ndr push/pull fns */ +typedef NTSTATUS (*ndr_push_flags_fn_t)(struct ndr_push *, int ndr_flags, const void *); +typedef NTSTATUS (*ndr_pull_flags_fn_t)(struct ndr_pull *, int ndr_flags, void *); +typedef void (*ndr_print_fn_t)(struct ndr_print *, const char *, const void *); +typedef void (*ndr_print_function_t)(struct ndr_print *, const char *, int, const void *); + +extern const struct dcerpc_syntax_id ndr_transfer_syntax; +extern const struct dcerpc_syntax_id ndr64_transfer_syntax; + +#endif /* __LIBNDR_H__ */ diff --git a/source/libndr/misc.h b/source/libndr/misc.h new file mode 100644 index 00000000000..d929379870f --- /dev/null +++ b/source/libndr/misc.h @@ -0,0 +1,37 @@ +/* header auto-generated by pidl */ + +#ifndef _HEADER_misc +#define _HEADER_misc + +struct GUID { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq[2]; + uint8_t node[6]; +}/* [noprint,gensize,public,noejs] */; + +struct policy_handle { + uint32_t handle_type; + struct GUID uuid; +}/* [public] */; + +enum netr_SchannelType { + SEC_CHAN_WKSTA=2, + SEC_CHAN_DOMAIN=4, + SEC_CHAN_BDC=6 +}; + +enum netr_SamDatabaseID { + SAM_DATABASE_DOMAIN=0, + SAM_DATABASE_BUILTIN=1, + SAM_DATABASE_PRIVS=2 +}; + +enum samr_RejectReason { + SAMR_REJECT_OTHER=0, + SAMR_REJECT_TOO_SHORT=1, + SAMR_REJECT_COMPLEXITY=2 +}; + +#endif /* _HEADER_misc */ diff --git a/source/libndr/ndr.c b/source/libndr/ndr.c new file mode 100644 index 00000000000..2aff7a88f0a --- /dev/null +++ b/source/libndr/ndr.c @@ -0,0 +1,961 @@ +/* + Unix SMB/CIFS implementation. + + libndr interface + + Copyright (C) Andrew Tridgell 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + this provides the core routines for NDR parsing functions + + see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details + of NDR encoding rules +*/ + +#include "includes.h" + +#define NDR_BASE_MARSHALL_SIZE 1024 + +/* this guid indicates NDR encoding in a protocol tower */ +const struct dcerpc_syntax_id ndr_transfer_syntax = { + { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} }, + 2 +}; + +const struct dcerpc_syntax_id ndr64_transfer_syntax = { + { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} }, + 1 +}; + +/* + work out the number of bytes needed to align on a n byte boundary +*/ +size_t ndr_align_size(uint32_t offset, size_t n) +{ + if ((offset & (n-1)) == 0) return 0; + return n - (offset & (n-1)); +} + +/* + initialise a ndr parse structure from a data blob +*/ +struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx) +{ + struct ndr_pull *ndr; + + ndr = talloc_zero(mem_ctx, struct ndr_pull); + if (!ndr) return NULL; + ndr->current_mem_ctx = mem_ctx; + + ndr->data = blob->data; + ndr->data_size = blob->length; + + return ndr; +} + +/* + advance by 'size' bytes +*/ +NTSTATUS ndr_pull_advance(struct ndr_pull *ndr, uint32_t size) +{ + ndr->offset += size; + if (ndr->offset > ndr->data_size) { + return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, + "ndr_pull_advance by %u failed", + size); + } + return NT_STATUS_OK; +} + +/* + set the parse offset to 'ofs' +*/ +static NTSTATUS ndr_pull_set_offset(struct ndr_pull *ndr, uint32_t ofs) +{ + ndr->offset = ofs; + if (ndr->offset > ndr->data_size) { + return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, + "ndr_pull_set_offset %u failed", + ofs); + } + return NT_STATUS_OK; +} + +/* save the offset/size of the current ndr state */ +void ndr_pull_save(struct ndr_pull *ndr, struct ndr_pull_save *save) +{ + save->offset = ndr->offset; + save->data_size = ndr->data_size; +} + +/* restore the size/offset of a ndr structure */ +void ndr_pull_restore(struct ndr_pull *ndr, struct ndr_pull_save *save) +{ + ndr->offset = save->offset; + ndr->data_size = save->data_size; +} + + +/* create a ndr_push structure, ready for some marshalling */ +struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx) +{ + struct ndr_push *ndr; + + ndr = talloc_zero(mem_ctx, struct ndr_push); + if (!ndr) { + return NULL; + } + + ndr->flags = 0; + ndr->alloc_size = NDR_BASE_MARSHALL_SIZE; + ndr->data = talloc_array(ndr, uint8_t, ndr->alloc_size); + if (!ndr->data) { + return NULL; + } + + return ndr; +} + + +/* create a ndr_push structure, ready for some marshalling */ +struct ndr_push *ndr_push_init(void) +{ + return ndr_push_init_ctx(NULL); +} + +/* free a ndr_push structure */ +void ndr_push_free(struct ndr_push *ndr) +{ + talloc_free(ndr); +} + + +/* return a DATA_BLOB structure for the current ndr_push marshalled data */ +DATA_BLOB ndr_push_blob(struct ndr_push *ndr) +{ + DATA_BLOB blob; + blob.data = ndr->data; + blob.length = ndr->offset; + blob.free = NULL; + if (ndr->alloc_size > ndr->offset) { + ndr->data[ndr->offset] = 0; + } + return blob; +} + + +/* + expand the available space in the buffer to 'size' +*/ +NTSTATUS ndr_push_expand(struct ndr_push *ndr, uint32_t size) +{ + if (ndr->alloc_size > size) { + return NT_STATUS_OK; + } + + ndr->alloc_size += NDR_BASE_MARSHALL_SIZE; + if (size+1 > ndr->alloc_size) { + ndr->alloc_size = size+1; + } + ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->alloc_size); + if (!ndr->data) { + return ndr_push_error(ndr, NDR_ERR_ALLOC, "Failed to push_expand to %u", + ndr->alloc_size); + } + + return NT_STATUS_OK; +} + +void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3) +{ + va_list ap; + char *s = NULL; + int i; + + va_start(ap, format); + vasprintf(&s, format, ap); + va_end(ap); + + for (i=0;i<ndr->depth;i++) { + DEBUG(0,(" ")); + } + + DEBUG(0,("%s\n", s)); + free(s); +} + +static void ndr_print_string_helper(struct ndr_print *ndr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3) +{ + va_list ap; + int i; + + for (i=0;i<ndr->depth;i++) { + ndr->private_data = talloc_asprintf_append(ndr->private_data, " "); + } + + va_start(ap, format); + ndr->private_data = talloc_vasprintf_append(ndr->private_data, format, ap); + va_end(ap); + ndr->private_data = talloc_asprintf_append(ndr->private_data, "\n"); +} + +/* + a useful helper function for printing idl structures via DEBUG() +*/ +void ndr_print_debug(ndr_print_fn_t fn, const char *name, void *ptr) +{ + struct ndr_print *ndr; + + ndr = talloc_zero(NULL, struct ndr_print); + if (!ndr) return; + ndr->print = ndr_print_debug_helper; + ndr->depth = 1; + ndr->flags = 0; + fn(ndr, name, ptr); + talloc_free(ndr); +} + +/* + a useful helper function for printing idl unions via DEBUG() +*/ +void ndr_print_union_debug(ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr) +{ + struct ndr_print *ndr; + + ndr = talloc_zero(NULL, struct ndr_print); + if (!ndr) return; + ndr->print = ndr_print_debug_helper; + ndr->depth = 1; + ndr->flags = 0; + ndr_print_set_switch_value(ndr, ptr, level); + fn(ndr, name, ptr); + talloc_free(ndr); +} + +/* + a useful helper function for printing idl function calls via DEBUG() +*/ +void ndr_print_function_debug(ndr_print_function_t fn, const char *name, int flags, void *ptr) +{ + struct ndr_print *ndr; + + ndr = talloc_zero(NULL, struct ndr_print); + if (!ndr) return; + ndr->print = ndr_print_debug_helper; + ndr->depth = 1; + ndr->flags = 0; + fn(ndr, name, flags, ptr); + talloc_free(ndr); +} + + +/* + a useful helper function for printing idl function calls to a string +*/ +char *ndr_print_function_string(TALLOC_CTX *mem_ctx, + ndr_print_function_t fn, const char *name, + int flags, void *ptr) +{ + struct ndr_print *ndr; + char *ret = NULL; + + ndr = talloc_zero(mem_ctx, struct ndr_print); + if (!ndr) return NULL; + if (!(ndr->private_data = talloc_strdup(mem_ctx, ""))) { + TALLOC_FREE(ndr); + return NULL; + } + ndr->print = ndr_print_string_helper; + ndr->depth = 1; + ndr->flags = 0; + fn(ndr, name, flags, ptr); + ret = ndr->private_data; + talloc_free(ndr); + return ret; +} + +void ndr_set_flags(uint32_t *pflags, uint32_t new_flags) +{ + /* the big/little endian flags are inter-dependent */ + if (new_flags & LIBNDR_FLAG_LITTLE_ENDIAN) { + (*pflags) &= ~LIBNDR_FLAG_BIGENDIAN; + } + if (new_flags & LIBNDR_FLAG_BIGENDIAN) { + (*pflags) &= ~LIBNDR_FLAG_LITTLE_ENDIAN; + } + if (new_flags & LIBNDR_FLAG_REMAINING) { + (*pflags) &= ~LIBNDR_ALIGN_FLAGS; + } + if (new_flags & LIBNDR_ALIGN_FLAGS) { + (*pflags) &= ~LIBNDR_FLAG_REMAINING; + } + (*pflags) |= new_flags; +} + +static NTSTATUS ndr_map_error(enum ndr_err_code ndr_err) +{ + switch (ndr_err) { + case NDR_ERR_BUFSIZE: + return NT_STATUS_BUFFER_TOO_SMALL; + case NDR_ERR_TOKEN: + return NT_STATUS_INTERNAL_ERROR; + case NDR_ERR_ALLOC: + return NT_STATUS_NO_MEMORY; + case NDR_ERR_ARRAY_SIZE: + return NT_STATUS_ARRAY_BOUNDS_EXCEEDED; + default: + break; + } + + /* we should map all error codes to different status codes */ + return NT_STATUS_INVALID_PARAMETER; +} + +/* + return and possibly log an NDR error +*/ +NTSTATUS ndr_pull_error(struct ndr_pull *ndr, + enum ndr_err_code ndr_err, + const char *format, ...) _PRINTF_ATTRIBUTE(3,4) +{ + char *s=NULL; + va_list ap; + + va_start(ap, format); + vasprintf(&s, format, ap); + va_end(ap); + + DEBUG(3,("ndr_pull_error(%u): %s\n", ndr_err, s)); + + free(s); + + return ndr_map_error(ndr_err); +} + +/* + return and possibly log an NDR error +*/ +NTSTATUS ndr_push_error(struct ndr_push *ndr, + enum ndr_err_code ndr_err, + const char *format, ...) _PRINTF_ATTRIBUTE(3,4) +{ + char *s=NULL; + va_list ap; + + va_start(ap, format); + vasprintf(&s, format, ap); + va_end(ap); + + DEBUG(3,("ndr_push_error(%u): %s\n", ndr_err, s)); + + free(s); + + return ndr_map_error(ndr_err); +} + +/* + handle subcontext buffers, which in midl land are user-marshalled, but + we use magic in pidl to make them easier to cope with +*/ +NTSTATUS ndr_pull_subcontext_start(struct ndr_pull *ndr, + struct ndr_pull **_subndr, + size_t header_size, + ssize_t size_is) +{ + struct ndr_pull *subndr; + uint32_t r_content_size; + + switch (header_size) { + case 0: { + uint32_t content_size = ndr->data_size - ndr->offset; + if (size_is >= 0) { + content_size = size_is; + } + r_content_size = content_size; + break; + } + + case 2: { + uint16_t content_size; + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &content_size)); + if (size_is >= 0 && size_is != content_size) { + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d", + (int)size_is, (int)content_size); + } + r_content_size = content_size; + break; + } + + case 4: { + uint32_t content_size; + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &content_size)); + if (size_is >= 0 && size_is != content_size) { + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d", + (int)size_is, (int)content_size); + } + r_content_size = content_size; + break; + } + default: + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %d", + (int)header_size); + } + + NDR_PULL_NEED_BYTES(ndr, r_content_size); + + subndr = talloc_zero(ndr, struct ndr_pull); + NT_STATUS_HAVE_NO_MEMORY(subndr); + subndr->flags = ndr->flags; + subndr->current_mem_ctx = ndr->current_mem_ctx; + + subndr->data = ndr->data + ndr->offset; + subndr->offset = 0; + subndr->data_size = r_content_size; + + *_subndr = subndr; + return NT_STATUS_OK; +} + +NTSTATUS ndr_pull_subcontext_end(struct ndr_pull *ndr, + struct ndr_pull *subndr, + size_t header_size, + ssize_t size_is) +{ + uint32_t advance; + if (size_is >= 0) { + advance = size_is; + } else if (header_size > 0) { + advance = subndr->data_size; + } else { + advance = subndr->offset; + } + NDR_CHECK(ndr_pull_advance(ndr, advance)); + return NT_STATUS_OK; +} + +NTSTATUS ndr_push_subcontext_start(struct ndr_push *ndr, + struct ndr_push **_subndr, + size_t header_size, + ssize_t size_is) +{ + struct ndr_push *subndr; + + subndr = ndr_push_init_ctx(ndr); + NT_STATUS_HAVE_NO_MEMORY(subndr); + subndr->flags = ndr->flags; + + *_subndr = subndr; + return NT_STATUS_OK; +} + +/* + push a subcontext header +*/ +NTSTATUS ndr_push_subcontext_end(struct ndr_push *ndr, + struct ndr_push *subndr, + size_t header_size, + ssize_t size_is) +{ + if (size_is >= 0) { + ssize_t padding_len = size_is - subndr->offset; + if (padding_len > 0) { + NDR_CHECK(ndr_push_zero(subndr, padding_len)); + } else if (padding_len < 0) { + return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)", + (int)subndr->offset, (int)size_is); + } + } + + switch (header_size) { + case 0: + break; + + case 2: + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, subndr->offset)); + break; + + case 4: + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset)); + break; + + default: + return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %d", + (int)header_size); + } + + NDR_CHECK(ndr_push_bytes(ndr, subndr->data, subndr->offset)); + return NT_STATUS_OK; +} + +/* + store a token in the ndr context, for later retrieval +*/ +NTSTATUS ndr_token_store(TALLOC_CTX *mem_ctx, + struct ndr_token_list **list, + const void *key, + uint32_t value) +{ + struct ndr_token_list *tok; + tok = talloc(mem_ctx, struct ndr_token_list); + if (tok == NULL) { + return NT_STATUS_NO_MEMORY; + } + tok->key = key; + tok->value = value; + DLIST_ADD((*list), tok); + return NT_STATUS_OK; +} + +/* + retrieve a token from a ndr context, using cmp_fn to match the tokens +*/ +NTSTATUS ndr_token_retrieve_cmp_fn(struct ndr_token_list **list, const void *key, uint32_t *v, + comparison_fn_t _cmp_fn, BOOL _remove_tok) +{ + struct ndr_token_list *tok; + for (tok=*list;tok;tok=tok->next) { + if (_cmp_fn && _cmp_fn(tok->key,key)==0) goto found; + else if (!_cmp_fn && tok->key == key) goto found; + } + return ndr_map_error(NDR_ERR_TOKEN); +found: + *v = tok->value; + if (_remove_tok) { + DLIST_REMOVE((*list), tok); + talloc_free(tok); + } + return NT_STATUS_OK; +} + +/* + retrieve a token from a ndr context +*/ +NTSTATUS ndr_token_retrieve(struct ndr_token_list **list, const void *key, uint32_t *v) +{ + return ndr_token_retrieve_cmp_fn(list, key, v, NULL, True); +} + +/* + peek at but don't removed a token from a ndr context +*/ +uint32_t ndr_token_peek(struct ndr_token_list **list, const void *key) +{ + NTSTATUS status; + uint32_t v; + status = ndr_token_retrieve_cmp_fn(list, key, &v, NULL, False); + if (NT_STATUS_IS_OK(status)) return v; + return 0; +} + +/* + pull an array size field and add it to the array_size_list token list +*/ +NTSTATUS ndr_pull_array_size(struct ndr_pull *ndr, const void *p) +{ + uint32_t size; + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &size)); + return ndr_token_store(ndr, &ndr->array_size_list, p, size); +} + +/* + get the stored array size field +*/ +uint32_t ndr_get_array_size(struct ndr_pull *ndr, const void *p) +{ + return ndr_token_peek(&ndr->array_size_list, p); +} + +/* + check the stored array size field +*/ +NTSTATUS ndr_check_array_size(struct ndr_pull *ndr, void *p, uint32_t size) +{ + uint32_t stored; + stored = ndr_token_peek(&ndr->array_size_list, p); + if (stored != size) { + return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, + "Bad array size - got %u expected %u\n", + stored, size); + } + return NT_STATUS_OK; +} + +/* + pull an array length field and add it to the array_length_list token list +*/ +NTSTATUS ndr_pull_array_length(struct ndr_pull *ndr, const void *p) +{ + uint32_t length, offset; + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &offset)); + if (offset != 0) { + return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, + "non-zero array offset %u\n", offset); + } + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length)); + return ndr_token_store(ndr, &ndr->array_length_list, p, length); +} + +/* + get the stored array length field +*/ +uint32_t ndr_get_array_length(struct ndr_pull *ndr, const void *p) +{ + return ndr_token_peek(&ndr->array_length_list, p); +} + +/* + check the stored array length field +*/ +NTSTATUS ndr_check_array_length(struct ndr_pull *ndr, void *p, uint32_t length) +{ + uint32_t stored; + stored = ndr_token_peek(&ndr->array_length_list, p); + if (stored != length) { + return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, + "Bad array length - got %u expected %u\n", + stored, length); + } + return NT_STATUS_OK; +} + +/* + store a switch value + */ +NTSTATUS ndr_push_set_switch_value(struct ndr_push *ndr, const void *p, uint32_t val) +{ + return ndr_token_store(ndr, &ndr->switch_list, p, val); +} + +NTSTATUS ndr_pull_set_switch_value(struct ndr_pull *ndr, const void *p, uint32_t val) +{ + return ndr_token_store(ndr, &ndr->switch_list, p, val); +} + +NTSTATUS ndr_print_set_switch_value(struct ndr_print *ndr, const void *p, uint32_t val) +{ + return ndr_token_store(ndr, &ndr->switch_list, p, val); +} + +/* + retrieve a switch value + */ +uint32_t ndr_push_get_switch_value(struct ndr_push *ndr, const void *p) +{ + return ndr_token_peek(&ndr->switch_list, p); +} + +uint32_t ndr_pull_get_switch_value(struct ndr_pull *ndr, const void *p) +{ + return ndr_token_peek(&ndr->switch_list, p); +} + +uint32_t ndr_print_get_switch_value(struct ndr_print *ndr, const void *p) +{ + return ndr_token_peek(&ndr->switch_list, p); +} + +/* + pull a struct from a blob using NDR +*/ +NTSTATUS ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, + ndr_pull_flags_fn_t fn) +{ + struct ndr_pull *ndr; + ndr = ndr_pull_init_blob(blob, mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + return fn(ndr, NDR_SCALARS|NDR_BUFFERS, p); +} + +/* + pull a struct from a blob using NDR - failing if all bytes are not consumed +*/ +NTSTATUS ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, + ndr_pull_flags_fn_t fn) +{ + struct ndr_pull *ndr; + NTSTATUS status; + + ndr = ndr_pull_init_blob(blob, mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p); + if (!NT_STATUS_IS_OK(status)) return status; + if (ndr->offset != ndr->data_size) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + return status; +} + +/* + pull a union from a blob using NDR, given the union discriminator +*/ +NTSTATUS ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, + uint32_t level, ndr_pull_flags_fn_t fn) +{ + struct ndr_pull *ndr; + NTSTATUS status; + + ndr = ndr_pull_init_blob(blob, mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + ndr_pull_set_switch_value(ndr, p, level); + status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p); + if (!NT_STATUS_IS_OK(status)) return status; + if (ndr->offset != ndr->data_size) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + return status; +} + +/* + push a struct to a blob using NDR +*/ +NTSTATUS ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, const void *p, + ndr_push_flags_fn_t fn) +{ + NTSTATUS status; + struct ndr_push *ndr; + ndr = ndr_push_init_ctx(mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + *blob = ndr_push_blob(ndr); + + return NT_STATUS_OK; +} + +/* + push a union to a blob using NDR +*/ +NTSTATUS ndr_push_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, + uint32_t level, ndr_push_flags_fn_t fn) +{ + NTSTATUS status; + struct ndr_push *ndr; + ndr = ndr_push_init_ctx(mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + ndr_push_set_switch_value(ndr, p, level); + status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + *blob = ndr_push_blob(ndr); + + return NT_STATUS_OK; +} + +/* + generic ndr_size_*() handler for structures +*/ +size_t ndr_size_struct(const void *p, int flags, ndr_push_flags_fn_t push) +{ + struct ndr_push *ndr; + NTSTATUS status; + size_t ret; + + /* avoid recursion */ + if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0; + + ndr = ndr_push_init_ctx(NULL); + if (!ndr) return 0; + ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE; + status = push(ndr, NDR_SCALARS|NDR_BUFFERS, p); + if (!NT_STATUS_IS_OK(status)) { + return 0; + } + ret = ndr->offset; + talloc_free(ndr); + return ret; +} + +/* + generic ndr_size_*() handler for unions +*/ +size_t ndr_size_union(const void *p, int flags, uint32_t level, ndr_push_flags_fn_t push) +{ + struct ndr_push *ndr; + NTSTATUS status; + size_t ret; + + /* avoid recursion */ + if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0; + + ndr = ndr_push_init_ctx(NULL); + if (!ndr) return 0; + ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE; + ndr_push_set_switch_value(ndr, p, level); + status = push(ndr, NDR_SCALARS|NDR_BUFFERS, p); + if (!NT_STATUS_IS_OK(status)) { + return 0; + } + ret = ndr->offset; + talloc_free(ndr); + return ret; +} + +/* + get the current base for relative pointers for the push +*/ +uint32_t ndr_push_get_relative_base_offset(struct ndr_push *ndr) +{ + return ndr->relative_base_offset; +} + +/* + restore the old base for relative pointers for the push +*/ +void ndr_push_restore_relative_base_offset(struct ndr_push *ndr, uint32_t offset) +{ + ndr->relative_base_offset = offset; +} + +/* + setup the current base for relative pointers for the push + called in the NDR_SCALAR stage +*/ +NTSTATUS ndr_push_setup_relative_base_offset1(struct ndr_push *ndr, const void *p, uint32_t offset) +{ + ndr->relative_base_offset = offset; + return ndr_token_store(ndr, &ndr->relative_base_list, p, offset); +} + +/* + setup the current base for relative pointers for the push + called in the NDR_BUFFERS stage +*/ +NTSTATUS ndr_push_setup_relative_base_offset2(struct ndr_push *ndr, const void *p) +{ + return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset); +} + +/* + push a relative object - stage1 + this is called during SCALARS processing +*/ +NTSTATUS ndr_push_relative_ptr1(struct ndr_push *ndr, const void *p) +{ + if (p == NULL) { + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0)); + return NT_STATUS_OK; + } + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset)); + return ndr_push_uint32(ndr, NDR_SCALARS, 0xFFFFFFFF); +} + +/* + push a relative object - stage2 + this is called during buffers processing +*/ +NTSTATUS ndr_push_relative_ptr2(struct ndr_push *ndr, const void *p) +{ + struct ndr_push_save save; + uint32_t ptr_offset = 0xFFFFFFFF; + if (p == NULL) { + return NT_STATUS_OK; + } + ndr_push_save(ndr, &save); + NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset)); + if (ptr_offset > ndr->offset) { + return ndr_push_error(ndr, NDR_ERR_BUFSIZE, + "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)", + ptr_offset, ndr->offset); + } + ndr->offset = ptr_offset; + if (save.offset < ndr->relative_base_offset) { + return ndr_push_error(ndr, NDR_ERR_BUFSIZE, + "ndr_push_relative_ptr2 save.offset(%u) < ndr->relative_base_offset(%u)", + save.offset, ndr->relative_base_offset); + } + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, save.offset - ndr->relative_base_offset)); + ndr_push_restore(ndr, &save); + return NT_STATUS_OK; +} + +/* + get the current base for relative pointers for the pull +*/ +uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull *ndr) +{ + return ndr->relative_base_offset; +} + +/* + restore the old base for relative pointers for the pull +*/ +void ndr_pull_restore_relative_base_offset(struct ndr_pull *ndr, uint32_t offset) +{ + ndr->relative_base_offset = offset; +} + +/* + setup the current base for relative pointers for the pull + called in the NDR_SCALAR stage +*/ +NTSTATUS ndr_pull_setup_relative_base_offset1(struct ndr_pull *ndr, const void *p, uint32_t offset) +{ + ndr->relative_base_offset = offset; + return ndr_token_store(ndr, &ndr->relative_base_list, p, offset); +} + +/* + setup the current base for relative pointers for the pull + called in the NDR_BUFFERS stage +*/ +NTSTATUS ndr_pull_setup_relative_base_offset2(struct ndr_pull *ndr, const void *p) +{ + return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset); +} + +/* + pull a relative object - stage1 + called during SCALARS processing +*/ +NTSTATUS ndr_pull_relative_ptr1(struct ndr_pull *ndr, const void *p, uint32_t rel_offset) +{ + rel_offset += ndr->relative_base_offset; + if (rel_offset > ndr->data_size) { + return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, + "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)", + rel_offset, ndr->data_size); + } + return ndr_token_store(ndr, &ndr->relative_list, p, rel_offset); +} + +/* + pull a relative object - stage2 + called during BUFFERS processing +*/ +NTSTATUS ndr_pull_relative_ptr2(struct ndr_pull *ndr, const void *p) +{ + uint32_t rel_offset; + NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &rel_offset)); + return ndr_pull_set_offset(ndr, rel_offset); +} diff --git a/source/libndr/ndr_basic.c b/source/libndr/ndr_basic.c new file mode 100644 index 00000000000..31a48f67c45 --- /dev/null +++ b/source/libndr/ndr_basic.c @@ -0,0 +1,826 @@ +/* + Unix SMB/CIFS implementation. + + routines for marshalling/unmarshalling basic types + + Copyright (C) Andrew Tridgell 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* Evil hack to convert Samba3 NTTIME's to Samba4 NTTIME's */ + +union NTTIME_big { + NTTIME s3; + uint64_t s4; +}; + + + +#define NDR_SVAL(ndr, ofs) (NDR_BE(ndr)?RSVAL(ndr->data,ofs):SVAL(ndr->data,ofs)) +#define NDR_IVAL(ndr, ofs) (NDR_BE(ndr)?RIVAL(ndr->data,ofs):IVAL(ndr->data,ofs)) +#define NDR_IVALS(ndr, ofs) (NDR_BE(ndr)?RIVALS(ndr->data,ofs):IVALS(ndr->data,ofs)) +#define NDR_SSVAL(ndr, ofs, v) do { if (NDR_BE(ndr)) { RSSVAL(ndr->data,ofs,v); } else SSVAL(ndr->data,ofs,v); } while (0) +#define NDR_SIVAL(ndr, ofs, v) do { if (NDR_BE(ndr)) { RSIVAL(ndr->data,ofs,v); } else SIVAL(ndr->data,ofs,v); } while (0) +#define NDR_SIVALS(ndr, ofs, v) do { if (NDR_BE(ndr)) { RSIVALS(ndr->data,ofs,v); } else SIVALS(ndr->data,ofs,v); } while (0) + + +/* + check for data leaks from the server by looking for non-zero pad bytes + these could also indicate that real structure elements have been + mistaken for padding in the IDL +*/ +void ndr_check_padding(struct ndr_pull *ndr, size_t n) +{ + size_t ofs2 = (ndr->offset + (n-1)) & ~(n-1); + int i; + for (i=ndr->offset;i<ofs2;i++) { + if (ndr->data[i] != 0) { + break; + } + } + if (i<ofs2) { + DEBUG(0,("WARNING: Non-zero padding to %d: ", (int)n)); + for (i=ndr->offset;i<ofs2;i++) { + DEBUG(0,("%02x ", ndr->data[i])); + } + DEBUG(0,("\n")); + } + +} + +/* + parse a int8_t +*/ +NTSTATUS ndr_pull_int8(struct ndr_pull *ndr, int ndr_flags, int8_t *v) +{ + NDR_PULL_NEED_BYTES(ndr, 1); + *v = (int8_t)CVAL(ndr->data, ndr->offset); + ndr->offset += 1; + return NT_STATUS_OK; +} + +/* + parse a uint8_t +*/ +NTSTATUS ndr_pull_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v) +{ + NDR_PULL_NEED_BYTES(ndr, 1); + *v = CVAL(ndr->data, ndr->offset); + ndr->offset += 1; + return NT_STATUS_OK; +} + +/* + parse a int16_t +*/ +NTSTATUS ndr_pull_int16(struct ndr_pull *ndr, int ndr_flags, int16_t *v) +{ + NDR_PULL_ALIGN(ndr, 2); + NDR_PULL_NEED_BYTES(ndr, 2); + *v = (uint16_t)NDR_SVAL(ndr, ndr->offset); + ndr->offset += 2; + return NT_STATUS_OK; +} + +/* + parse a uint16_t +*/ +NTSTATUS ndr_pull_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v) +{ + NDR_PULL_ALIGN(ndr, 2); + NDR_PULL_NEED_BYTES(ndr, 2); + *v = NDR_SVAL(ndr, ndr->offset); + ndr->offset += 2; + return NT_STATUS_OK; +} + +/* + parse a int32_t +*/ +NTSTATUS ndr_pull_int32(struct ndr_pull *ndr, int ndr_flags, int32_t *v) +{ + NDR_PULL_ALIGN(ndr, 4); + NDR_PULL_NEED_BYTES(ndr, 4); + *v = NDR_IVALS(ndr, ndr->offset); + ndr->offset += 4; + return NT_STATUS_OK; +} + +/* + parse a uint32_t +*/ +NTSTATUS ndr_pull_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v) +{ + NDR_PULL_ALIGN(ndr, 4); + NDR_PULL_NEED_BYTES(ndr, 4); + *v = NDR_IVAL(ndr, ndr->offset); + ndr->offset += 4; + return NT_STATUS_OK; +} + +/* + parse a pointer referent identifier +*/ +NTSTATUS ndr_pull_generic_ptr(struct ndr_pull *ndr, uint32_t *v) +{ + NTSTATUS status; + status = ndr_pull_uint32(ndr, NDR_SCALARS, v); + if (NT_STATUS_IS_OK(status) && *v != 0) { + ndr->ptr_count++; + } + return status; +} + +/* + parse a ref pointer referent identifier +*/ +NTSTATUS ndr_pull_ref_ptr(struct ndr_pull *ndr, uint32_t *v) +{ + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, v)); + /* ref pointers always point to data */ + *v = 1; + return NT_STATUS_OK; +} + +/* + parse a udlong +*/ +NTSTATUS ndr_pull_udlong(struct ndr_pull *ndr, int ndr_flags, uint64_t *v) +{ + NDR_PULL_ALIGN(ndr, 4); + NDR_PULL_NEED_BYTES(ndr, 8); + *v = NDR_IVAL(ndr, ndr->offset); + *v |= (uint64_t)(NDR_IVAL(ndr, ndr->offset+4)) << 32; + ndr->offset += 8; + return NT_STATUS_OK; +} + +/* + parse a udlongr +*/ +NTSTATUS ndr_pull_udlongr(struct ndr_pull *ndr, int ndr_flags, uint64_t *v) +{ + NDR_PULL_ALIGN(ndr, 4); + NDR_PULL_NEED_BYTES(ndr, 8); + *v = ((uint64_t)NDR_IVAL(ndr, ndr->offset)) << 32; + *v |= NDR_IVAL(ndr, ndr->offset+4); + ndr->offset += 8; + return NT_STATUS_OK; +} + +/* + parse a dlong +*/ +NTSTATUS ndr_pull_dlong(struct ndr_pull *ndr, int ndr_flags, int64_t *v) +{ + return ndr_pull_udlong(ndr, ndr_flags, (uint64_t *)v); +} + +/* + parse a hyper +*/ +NTSTATUS ndr_pull_hyper(struct ndr_pull *ndr, int ndr_flags, uint64_t *v) +{ + NDR_PULL_ALIGN(ndr, 8); + return ndr_pull_udlong(ndr, ndr_flags, v); +} + +/* + parse a pointer +*/ +NTSTATUS ndr_pull_pointer(struct ndr_pull *ndr, int ndr_flags, void* *v) +{ + intptr_t h; + NDR_PULL_ALIGN(ndr, sizeof(h)); + NDR_PULL_NEED_BYTES(ndr, sizeof(h)); + memcpy(&h, ndr->data+ndr->offset, sizeof(h)); + ndr->offset += sizeof(h); + *v = (void *)h; + return NT_STATUS_OK; +} + +/* + pull a NTSTATUS +*/ +NTSTATUS ndr_pull_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, NTSTATUS *status) +{ + uint32_t v; + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v)); + *status = NT_STATUS(v); + return NT_STATUS_OK; +} + +/* + push a NTSTATUS +*/ +NTSTATUS ndr_push_NTSTATUS(struct ndr_push *ndr, int ndr_flags, NTSTATUS status) +{ + return ndr_push_uint32(ndr, ndr_flags, NT_STATUS_V(status)); +} + +void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTATUS r) +{ + ndr->print(ndr, "%-25s: %s", name, nt_errstr(r)); +} + +/* + pull a WERROR +*/ +NTSTATUS ndr_pull_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *status) +{ + uint32_t v; + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v)); + *status = W_ERROR(v); + return NT_STATUS_OK; +} + +/* + push a WERROR +*/ +NTSTATUS ndr_push_WERROR(struct ndr_push *ndr, int ndr_flags, WERROR status) +{ + return ndr_push_uint32(ndr, NDR_SCALARS, W_ERROR_V(status)); +} + +void ndr_print_WERROR(struct ndr_print *ndr, const char *name, WERROR r) +{ + ndr->print(ndr, "%-25s: %d", name, W_ERROR_V(r)); +} + +/* + parse a set of bytes +*/ +NTSTATUS ndr_pull_bytes(struct ndr_pull *ndr, uint8_t *data, uint32_t n) +{ + NDR_PULL_NEED_BYTES(ndr, n); + memcpy(data, ndr->data + ndr->offset, n); + ndr->offset += n; + return NT_STATUS_OK; +} + +/* + pull an array of uint8 +*/ +NTSTATUS ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *data, uint32_t n) +{ + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + return ndr_pull_bytes(ndr, data, n); +} + +/* + push a int8_t +*/ +NTSTATUS ndr_push_int8(struct ndr_push *ndr, int ndr_flags, int8_t v) +{ + NDR_PUSH_NEED_BYTES(ndr, 1); + SCVAL(ndr->data, ndr->offset, (uint8_t)v); + ndr->offset += 1; + return NT_STATUS_OK; +} + +/* + push a uint8_t +*/ +NTSTATUS ndr_push_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v) +{ + NDR_PUSH_NEED_BYTES(ndr, 1); + SCVAL(ndr->data, ndr->offset, v); + ndr->offset += 1; + return NT_STATUS_OK; +} + +/* + push a int16_t +*/ +NTSTATUS ndr_push_int16(struct ndr_push *ndr, int ndr_flags, int16_t v) +{ + NDR_PUSH_ALIGN(ndr, 2); + NDR_PUSH_NEED_BYTES(ndr, 2); + NDR_SSVAL(ndr, ndr->offset, (uint16_t)v); + ndr->offset += 2; + return NT_STATUS_OK; +} + +/* + push a uint16_t +*/ +NTSTATUS ndr_push_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v) +{ + NDR_PUSH_ALIGN(ndr, 2); + NDR_PUSH_NEED_BYTES(ndr, 2); + NDR_SSVAL(ndr, ndr->offset, v); + ndr->offset += 2; + return NT_STATUS_OK; +} + +/* + push a int32_t +*/ +NTSTATUS ndr_push_int32(struct ndr_push *ndr, int ndr_flags, int32_t v) +{ + NDR_PUSH_ALIGN(ndr, 4); + NDR_PUSH_NEED_BYTES(ndr, 4); + NDR_SIVALS(ndr, ndr->offset, v); + ndr->offset += 4; + return NT_STATUS_OK; +} + +/* + push a uint32_t +*/ +NTSTATUS ndr_push_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v) +{ + NDR_PUSH_ALIGN(ndr, 4); + NDR_PUSH_NEED_BYTES(ndr, 4); + NDR_SIVAL(ndr, ndr->offset, v); + ndr->offset += 4; + return NT_STATUS_OK; +} + +/* + push a udlong +*/ +NTSTATUS ndr_push_udlong(struct ndr_push *ndr, int ndr_flags, uint64_t v) +{ + NDR_PUSH_ALIGN(ndr, 4); + NDR_PUSH_NEED_BYTES(ndr, 8); + NDR_SIVAL(ndr, ndr->offset, (v & 0xFFFFFFFF)); + NDR_SIVAL(ndr, ndr->offset+4, (v>>32)); + ndr->offset += 8; + return NT_STATUS_OK; +} + +/* + push a udlongr +*/ +NTSTATUS ndr_push_udlongr(struct ndr_push *ndr, int ndr_flags, uint64_t v) +{ + NDR_PUSH_ALIGN(ndr, 4); + NDR_PUSH_NEED_BYTES(ndr, 8); + NDR_SIVAL(ndr, ndr->offset, (v>>32)); + NDR_SIVAL(ndr, ndr->offset+4, (v & 0xFFFFFFFF)); + ndr->offset += 8; + return NT_STATUS_OK; +} + +/* + push a dlong +*/ +NTSTATUS ndr_push_dlong(struct ndr_push *ndr, int ndr_flags, int64_t v) +{ + return ndr_push_udlong(ndr, NDR_SCALARS, (uint64_t)v); +} + +/* + push a hyper +*/ +NTSTATUS ndr_push_hyper(struct ndr_push *ndr, int ndr_flags, uint64_t v) +{ + NDR_PUSH_ALIGN(ndr, 8); + return ndr_push_udlong(ndr, NDR_SCALARS, v); +} + +/* + push a pointer +*/ +NTSTATUS ndr_push_pointer(struct ndr_push *ndr, int ndr_flags, void* v) +{ + intptr_t h = (intptr_t)v; + NDR_PUSH_ALIGN(ndr, sizeof(h)); + NDR_PUSH_NEED_BYTES(ndr, sizeof(h)); + memcpy(ndr->data+ndr->offset, &h, sizeof(h)); + ndr->offset += sizeof(h); + return NT_STATUS_OK; +} + +NTSTATUS ndr_push_align(struct ndr_push *ndr, size_t size) +{ + NDR_PUSH_ALIGN(ndr, size); + return NT_STATUS_OK; +} + +NTSTATUS ndr_pull_align(struct ndr_pull *ndr, size_t size) +{ + NDR_PULL_ALIGN(ndr, size); + return NT_STATUS_OK; +} + +/* + push some bytes +*/ +NTSTATUS ndr_push_bytes(struct ndr_push *ndr, const uint8_t *data, uint32_t n) +{ + NDR_PUSH_NEED_BYTES(ndr, n); + memcpy(ndr->data + ndr->offset, data, n); + ndr->offset += n; + return NT_STATUS_OK; +} + +/* + push some zero bytes +*/ +NTSTATUS ndr_push_zero(struct ndr_push *ndr, uint32_t n) +{ + NDR_PUSH_NEED_BYTES(ndr, n); + memset(ndr->data + ndr->offset, 0, n); + ndr->offset += n; + return NT_STATUS_OK; +} + +/* + push an array of uint8 +*/ +NTSTATUS ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n) +{ + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + return ndr_push_bytes(ndr, data, n); +} + +/* + save the current position + */ +void ndr_push_save(struct ndr_push *ndr, struct ndr_push_save *save) +{ + save->offset = ndr->offset; +} + +/* + restore the position + */ +void ndr_push_restore(struct ndr_push *ndr, struct ndr_push_save *save) +{ + ndr->offset = save->offset; +} + +/* + push a unique non-zero value if a pointer is non-NULL, otherwise 0 +*/ +NTSTATUS ndr_push_unique_ptr(struct ndr_push *ndr, const void *p) +{ + uint32_t ptr = 0; + if (p) { + ptr = ndr->ptr_count * 4; + ptr |= 0x00020000; + ndr->ptr_count++; + } + return ndr_push_uint32(ndr, NDR_SCALARS, ptr); +} + +/* + push a 'simple' full non-zero value if a pointer is non-NULL, otherwise 0 +*/ +NTSTATUS ndr_push_sptr_ptr(struct ndr_push *ndr, const void *p) +{ + uint32_t ptr = 0; + if (p) { + ndr->ptr_count++; + ptr = ndr->ptr_count; + } + return ndr_push_uint32(ndr, NDR_SCALARS, ptr); +} + +/* + push always a 0, if a pointer is NULL it's a fatal error +*/ +NTSTATUS ndr_push_ref_ptr(struct ndr_push *ndr, const void *p) +{ + if (p == NULL) { + return NT_STATUS_INVALID_PARAMETER_MIX; + } + return ndr_push_uint32(ndr, NDR_SCALARS, 0xAEF1AEF1); +} + +/* + push a NTTIME +*/ +NTSTATUS ndr_push_NTTIME(struct ndr_push *ndr, int ndr_flags, NTTIME t) +{ + union NTTIME_big b; b.s3 = t; + NDR_CHECK(ndr_push_udlong(ndr, ndr_flags, b.s4)); + return NT_STATUS_OK; +} + +/* + pull a NTTIME +*/ +NTSTATUS ndr_pull_NTTIME(struct ndr_pull *ndr, int ndr_flags, NTTIME *t) +{ + union NTTIME_big b; + NDR_CHECK(ndr_pull_udlong(ndr, ndr_flags, &b.s4)); + + *t = b.s3; + return NT_STATUS_OK; +} + +/* + push a NTTIME +*/ +NTSTATUS ndr_push_NTTIME_1sec(struct ndr_push *ndr, int ndr_flags, NTTIME t) +{ + union NTTIME_big b; b.s3 = t; + + b.s4 /= 10000000; + NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, b.s4)); + return NT_STATUS_OK; +} + +/* + pull a NTTIME_1sec +*/ +NTSTATUS ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, int ndr_flags, NTTIME *t) +{ + union NTTIME_big b; + NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &b.s4)); + b.s4 *= 10000000; + *t = b.s3; + return NT_STATUS_OK; +} + +/* + pull a NTTIME_hyper +*/ +NTSTATUS ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, int ndr_flags, NTTIME *t) +{ + union NTTIME_big b; + NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &b.s4)); + *t = b.s3; + return NT_STATUS_OK; +} + +/* + push a NTTIME_hyper +*/ +NTSTATUS ndr_push_NTTIME_hyper(struct ndr_push *ndr, int ndr_flags, NTTIME t) +{ + union NTTIME_big b; b.s3 = t; + NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, b.s4)); + return NT_STATUS_OK; +} + +/* + push a time_t +*/ +NTSTATUS ndr_push_time_t(struct ndr_push *ndr, int ndr_flags, time_t t) +{ + return ndr_push_uint32(ndr, ndr_flags, t); +} + +/* + pull a time_t +*/ +NTSTATUS ndr_pull_time_t(struct ndr_pull *ndr, int ndr_flags, time_t *t) +{ + uint32_t tt; + NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &tt)); + *t = tt; + return NT_STATUS_OK; +} + + +void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type) +{ + ndr->print(ndr, "%s: struct %s", name, type); +} + +void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type, + const char *val, uint32_t value) +{ + if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) { + ndr->print(ndr, "%-25s: %s (0x%X)", name, val?val:"UNKNOWN_ENUM_VALUE", value); + } else { + ndr->print(ndr, "%-25s: %s (%d)", name, val?val:"UNKNOWN_ENUM_VALUE", value); + } +} + +void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint32_t flag, uint32_t value) +{ + /* this is an attempt to support multi-bit bitmap masks */ + value &= flag; + + while (!(flag & 1)) { + flag >>= 1; + value >>= 1; + } + if (flag == 1) { + ndr->print(ndr, " %d: %-25s", value, flag_name); + } else { + ndr->print(ndr, "0x%02x: %-25s (%d)", value, flag_name, value); + } +} + +void ndr_print_int8(struct ndr_print *ndr, const char *name, int8_t v) +{ + ndr->print(ndr, "%-25s: %d", name, v); +} + +void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v) +{ + ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v); +} + +void ndr_print_int16(struct ndr_print *ndr, const char *name, int16_t v) +{ + ndr->print(ndr, "%-25s: %d", name, v); +} + +void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16_t v) +{ + ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v); +} + +void ndr_print_int32(struct ndr_print *ndr, const char *name, int32_t v) +{ + ndr->print(ndr, "%-25s: %d", name, v); +} + +void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t v) +{ + ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v); +} + +void ndr_print_udlong(struct ndr_print *ndr, const char *name, uint64_t v) +{ + ndr->print(ndr, "%-25s: 0x%016llx (%llu)", name, v, v); +} + +void ndr_print_udlongr(struct ndr_print *ndr, const char *name, uint64_t v) +{ + ndr_print_udlong(ndr, name, v); +} + +void ndr_print_dlong(struct ndr_print *ndr, const char *name, int64_t v) +{ + ndr->print(ndr, "%-25s: 0x%016llx (%lld)", name, v, v); +} + +void ndr_print_hyper(struct ndr_print *ndr, const char *name, uint64_t v) +{ + ndr_print_dlong(ndr, name, v); +} + +void ndr_print_pointer(struct ndr_print *ndr, const char *name, void *v) +{ + ndr->print(ndr, "%-25s: %p", name, v); +} + +void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p) +{ + if (p) { + ndr->print(ndr, "%-25s: *", name); + } else { + ndr->print(ndr, "%-25s: NULL", name); + } +} + +void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t) +{ + ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr, t)); +} + +void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME t) +{ + /* this is a standard NTTIME here + * as it's already converted in the pull/push code + */ + ndr_print_NTTIME(ndr, name, t); +} + +void ndr_print_NTTIME_hyper(struct ndr_print *ndr, const char *name, NTTIME t) +{ + ndr_print_NTTIME(ndr, name, t); +} + +void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t) +{ + if (t == (time_t)-1 || t == 0) { + ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t); + } else { + ndr->print(ndr, "%-25s: %s", name, timestring(ndr, t)); + } +} + +void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type) +{ + if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) { + ndr->print(ndr, "%-25s: union %s(case 0x%X)", name, type, level); + } else { + ndr->print(ndr, "%-25s: union %s(case %d)", name, type, level); + } +} + +void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16_t level) +{ + ndr->print(ndr, "UNKNOWN LEVEL %u", level); +} + +void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, + const uint8_t *data, uint32_t count) +{ + int i; + + if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) { + char s[1202]; + for (i=0;i<count;i++) { + snprintf(&s[i*2], 3, "%02x", data[i]); + } + s[i*2] = 0; + ndr->print(ndr, "%-25s: %s", name, s); + return; + } + + ndr->print(ndr, "%s: ARRAY(%d)", name, count); + ndr->depth++; + for (i=0;i<count;i++) { + char *idx=NULL; + asprintf(&idx, "[%d]", i); + if (idx) { + ndr_print_uint8(ndr, idx, data[i]); + free(idx); + } + } + ndr->depth--; +} + +void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r) +{ + ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, r.length); + if (r.length) { + dump_data(10, (const char *)r.data, r.length); + } +} + + +/* + push a DATA_BLOB onto the wire. +*/ +NTSTATUS ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flags, DATA_BLOB blob) +{ + if (ndr->flags & LIBNDR_ALIGN_FLAGS) { + if (ndr->flags & LIBNDR_FLAG_ALIGN2) { + blob.length = NDR_ALIGN(ndr, 2); + } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) { + blob.length = NDR_ALIGN(ndr, 4); + } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) { + blob.length = NDR_ALIGN(ndr, 8); + } + NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length); + data_blob_clear(&blob); + } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) { + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, blob.length)); + } + NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length)); + return NT_STATUS_OK; +} + +/* + pull a DATA_BLOB from the wire. +*/ +NTSTATUS ndr_pull_DATA_BLOB(struct ndr_pull *ndr, int ndr_flags, DATA_BLOB *blob) +{ + uint32_t length = 0; + + if (ndr->flags & LIBNDR_ALIGN_FLAGS) { + if (ndr->flags & LIBNDR_FLAG_ALIGN2) { + length = NDR_ALIGN(ndr, 2); + } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) { + length = NDR_ALIGN(ndr, 4); + } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) { + length = NDR_ALIGN(ndr, 8); + } + if (ndr->data_size - ndr->offset < length) { + length = ndr->data_size - ndr->offset; + } + } else if (ndr->flags & LIBNDR_FLAG_REMAINING) { + length = ndr->data_size - ndr->offset; + } else { + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length)); + } + NDR_PULL_NEED_BYTES(ndr, length); + *blob = data_blob_talloc(ndr->current_mem_ctx, ndr->data+ndr->offset, length); + ndr->offset += length; + return NT_STATUS_OK; +} + +uint32_t ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags) +{ + return ret + data->length; +} diff --git a/source/libndr/ndr_misc.c b/source/libndr/ndr_misc.c new file mode 100644 index 00000000000..2f9004ae666 --- /dev/null +++ b/source/libndr/ndr_misc.c @@ -0,0 +1,171 @@ +/* + Unix SMB/CIFS implementation. + + UUID/GUID/policy_handle functions + + Copyright (C) Theodore Ts'o 1996, 1997, + Copyright (C) Jim McDonough 2002. + Copyright (C) Andrew Tridgell 2003. + Copyright (C) Stefan (metze) Metzmacher 2004. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/** + build a GUID from a string +*/ +NTSTATUS GUID_from_string(const char *s, struct GUID *guid) +{ + NTSTATUS status = NT_STATUS_INVALID_PARAMETER; + uint32_t time_low; + uint32_t time_mid, time_hi_and_version; + uint32_t clock_seq[2]; + uint32_t node[6]; + int i; + + if (s == NULL) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (11 == sscanf(s, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + &time_low, &time_mid, &time_hi_and_version, + &clock_seq[0], &clock_seq[1], + &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) { + status = NT_STATUS_OK; + } else if (11 == sscanf(s, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + &time_low, &time_mid, &time_hi_and_version, + &clock_seq[0], &clock_seq[1], + &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) { + status = NT_STATUS_OK; + } + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + guid->time_low = time_low; + guid->time_mid = time_mid; + guid->time_hi_and_version = time_hi_and_version; + guid->clock_seq[0] = clock_seq[0]; + guid->clock_seq[1] = clock_seq[1]; + for (i=0;i<6;i++) { + guid->node[i] = node[i]; + } + + return NT_STATUS_OK; +} + +/** + * generate a random GUID + */ +struct GUID GUID_random(void) +{ + struct GUID guid; + + generate_random_buffer((uint8_t *)&guid, sizeof(guid)); + guid.clock_seq[0] = (guid.clock_seq[0] & 0x3F) | 0x80; + guid.time_hi_and_version = (guid.time_hi_and_version & 0x0FFF) | 0x4000; + + return guid; +} + +/** + * generate an empty GUID + */ +struct GUID GUID_zero(void) +{ + struct GUID guid; + + ZERO_STRUCT(guid); + + return guid; +} + +/** + * see if a range of memory is all zero. A NULL pointer is considered + * to be all zero + */ +BOOL all_zero(const uint8_t *ptr, size_t size) +{ + int i; + if (!ptr) return True; + for (i=0;i<size;i++) { + if (ptr[i]) return False; + } + return True; +} + + +BOOL GUID_all_zero(const struct GUID *u) +{ + if (u->time_low != 0 || + u->time_mid != 0 || + u->time_hi_and_version != 0 || + u->clock_seq[0] != 0 || + u->clock_seq[1] != 0 || + !all_zero(u->node, 6)) { + return False; + } + return True; +} + +BOOL GUID_equal(const struct GUID *u1, const struct GUID *u2) +{ + if (u1->time_low != u2->time_low || + u1->time_mid != u2->time_mid || + u1->time_hi_and_version != u2->time_hi_and_version || + u1->clock_seq[0] != u2->clock_seq[0] || + u1->clock_seq[1] != u2->clock_seq[1] || + memcmp(u1->node, u2->node, 6) != 0) { + return False; + } + return True; +} + +/** + its useful to be able to display these in debugging messages +*/ +char *GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid) +{ + return talloc_asprintf(mem_ctx, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + guid->time_low, guid->time_mid, + guid->time_hi_and_version, + guid->clock_seq[0], + guid->clock_seq[1], + guid->node[0], guid->node[1], + guid->node[2], guid->node[3], + guid->node[4], guid->node[5]); +} + +char *GUID_string2(TALLOC_CTX *mem_ctx, const struct GUID *guid) +{ + char *ret, *s = GUID_string(mem_ctx, guid); + ret = talloc_asprintf(mem_ctx, "{%s}", s); + talloc_free(s); + return ret; +} + +void ndr_print_GUID(struct ndr_print *ndr, const char *name, const struct GUID *guid) +{ + ndr->print(ndr, "%-25s: %s", name, GUID_string(ndr, guid)); +} + +BOOL policy_handle_empty(struct policy_handle *h) +{ + return (h->handle_type == 0 && GUID_all_zero(&h->uuid)); +} diff --git a/source/libndr/ndr_sec.h b/source/libndr/ndr_sec.h new file mode 100644 index 00000000000..0858eac72c5 --- /dev/null +++ b/source/libndr/ndr_sec.h @@ -0,0 +1,35 @@ +#ifndef __LIBRPC_NDR_NDR_SEC_H__ +#define __LIBRPC_NDR_NDR_SEC_H__ + +#undef _PRINTF_ATTRIBUTE +#define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2) +/* This file was automatically generated by mkproto.pl. DO NOT EDIT */ + +#ifndef _PUBLIC_ +#define _PUBLIC_ +#endif + + +/* The following definitions come from librpc/ndr/ndr_sec_helper.c */ + +size_t ndr_size_dom_sid(const struct dom_sid *sid); +size_t ndr_length_dom_sid(const struct dom_sid *sid); +size_t ndr_size_security_ace(const struct security_ace *ace); +size_t ndr_size_security_acl(const struct security_acl *acl); +size_t ndr_size_security_descriptor(const struct security_descriptor *sd); +void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, const struct dom_sid *sid); +void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, const struct dom_sid *sid); +void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct dom_sid *sid); +char *dom_sid_string(TALLOC_CTX *mem_ctx, const struct dom_sid *sid); + +/* The following definitions come from librpc/ndr/ndr_sec.c */ + +NTSTATUS ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid); +NTSTATUS ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid); +NTSTATUS ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid); +NTSTATUS ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid); +#undef _PRINTF_ATTRIBUTE +#define _PRINTF_ATTRIBUTE(a1, a2) + +#endif /* __LIBRPC_NDR_NDR_SEC_H__ */ + diff --git a/source/libndr/ndr_sec_helper.c b/source/libndr/ndr_sec_helper.c new file mode 100644 index 00000000000..edbdd9a40eb --- /dev/null +++ b/source/libndr/ndr_sec_helper.c @@ -0,0 +1,187 @@ +/* + Unix SMB/CIFS implementation. + + fast routines for getting the wire size of security objects + + Copyright (C) Andrew Tridgell 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include "includes.h" + +/* + return the wire size of a dom_sid +*/ +size_t ndr_size_dom_sid(const struct dom_sid *sid, int flags) +{ + if (!sid) return 0; + return 8 + 4*sid->num_auths; +} + +/* + return the wire size of a security_ace +*/ +size_t ndr_size_security_ace(const struct security_ace *ace, int flags) +{ + if (!ace) return 0; + return 8 + ndr_size_dom_sid(&ace->trustee, flags); +} + + +/* + return the wire size of a security_acl +*/ +size_t ndr_size_security_acl(const struct security_acl *acl, int flags) +{ + size_t ret; + int i; + if (!acl) return 0; + ret = 8; + for (i=0;i<acl->num_aces;i++) { + ret += ndr_size_security_ace(&acl->aces[i], flags); + } + return ret; +} + +/* + return the wire size of a security descriptor +*/ +size_t ndr_size_security_descriptor(const struct security_descriptor *sd, int flags) +{ + size_t ret; + if (!sd) return 0; + + ret = 20; + ret += ndr_size_dom_sid(sd->owner_sid, flags); + ret += ndr_size_dom_sid(sd->group_sid, flags); + ret += ndr_size_security_acl(sd->dacl, flags); + ret += ndr_size_security_acl(sd->sacl, flags); + return ret; +} + +/* + print a dom_sid +*/ +void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, const struct dom_sid *sid) +{ + ndr->print(ndr, "%-25s: %s", name, dom_sid_string(ndr, sid)); +} + +void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, const struct dom_sid *sid) +{ + ndr_print_dom_sid(ndr, name, sid); +} + +void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct dom_sid *sid) +{ + ndr_print_dom_sid(ndr, name, sid); +} + + +/* + parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field +*/ +NTSTATUS ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid) +{ + uint32_t num_auths; + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &num_auths)); + NDR_CHECK(ndr_pull_dom_sid(ndr, ndr_flags, sid)); + if (sid->num_auths != num_auths) { + return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, + "Bad array size %u should exceed %u", + num_auths, sid->num_auths); + } + return NT_STATUS_OK; +} + +/* + parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field +*/ +NTSTATUS ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid) +{ + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, sid->num_auths)); + return ndr_push_dom_sid(ndr, ndr_flags, sid); +} + +/* + parse a dom_sid28 - this is a dom_sid in a fixed 28 byte buffer, so we need to ensure there are only upto 5 sub_auth +*/ +NTSTATUS ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid) +{ + NTSTATUS status; + struct ndr_pull *subndr; + + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + + subndr = talloc_zero(ndr, struct ndr_pull); + NT_STATUS_HAVE_NO_MEMORY(subndr); + subndr->flags = ndr->flags; + subndr->current_mem_ctx = ndr->current_mem_ctx; + + subndr->data = ndr->data + ndr->offset; + subndr->data_size = 28; + subndr->offset = 0; + + NDR_CHECK(ndr_pull_advance(ndr, 28)); + + status = ndr_pull_dom_sid(subndr, ndr_flags, sid); + if (!NT_STATUS_IS_OK(status)) { + /* handle a w2k bug which send random data in the buffer */ + ZERO_STRUCTP(sid); + } + + return NT_STATUS_OK; +} + +/* + push a dom_sid28 - this is a dom_sid in a 28 byte fixed buffer +*/ +NTSTATUS ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid) +{ + uint32_t old_offset; + uint32_t padding; + + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + + if (sid->num_auths > 5) { + return ndr_push_error(ndr, NDR_ERR_RANGE, + "dom_sid28 allows only upto 5 sub auth [%u]", + sid->num_auths); + } + + old_offset = ndr->offset; + NDR_CHECK(ndr_push_dom_sid(ndr, ndr_flags, sid)); + + padding = 28 - (ndr->offset - old_offset); + + if (padding > 0) { + NDR_CHECK(ndr_push_zero(ndr, padding)); + } + + return NT_STATUS_OK; +} + diff --git a/source/libndr/ndr_string.c b/source/libndr/ndr_string.c new file mode 100644 index 00000000000..d6c842a6537 --- /dev/null +++ b/source/libndr/ndr_string.c @@ -0,0 +1,612 @@ +/* + Unix SMB/CIFS implementation. + + routines for marshalling/unmarshalling string types + + Copyright (C) Andrew Tridgell 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/** + pull a general string from the wire +*/ +NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s) +{ + char *as=NULL; + uint32_t len1, ofs, len2; + uint16_t len3; + int ret; + charset_t chset = CH_UCS2; + unsigned byte_mul = 2; + unsigned flags = ndr->flags; + unsigned c_len_term = 0; + + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + + SMB_ASSERT(!NDR_BE(ndr)); + + if (flags & LIBNDR_FLAG_STR_ASCII) { + chset = CH_DOS; + byte_mul = 1; + flags &= ~LIBNDR_FLAG_STR_ASCII; + } + + if (flags & LIBNDR_FLAG_STR_UTF8) { + chset = CH_UTF8; + byte_mul = 1; + flags &= ~LIBNDR_FLAG_STR_UTF8; + } + + flags &= ~LIBNDR_FLAG_STR_CONFORMANT; + if (flags & LIBNDR_FLAG_STR_CHARLEN) { + c_len_term = 1; + flags &= ~LIBNDR_FLAG_STR_CHARLEN; + } + + switch (flags & LIBNDR_STRING_FLAGS) { + case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4: + case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM: + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs)); + if (ofs != 0) { + return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n", + ndr->flags & LIBNDR_STRING_FLAGS); + } + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2)); + if (len2 > len1) { + return ndr_pull_error(ndr, NDR_ERR_STRING, + "Bad string lengths len1=%u ofs=%u len2=%u\n", + len1, ofs, len2); + } + NDR_PULL_NEED_BYTES(ndr, (len2 + c_len_term)*byte_mul); + if (len2 == 0) { + as = talloc_strdup(ndr->current_mem_ctx, ""); + } else { + ret = convert_string_talloc(ndr->current_mem_ctx, + chset, CH_UNIX, + ndr->data+ndr->offset, + (len2 + c_len_term)*byte_mul, + &as, True); + if (ret == -1) { + return ndr_pull_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + } + NDR_CHECK(ndr_pull_advance(ndr, (len2 + c_len_term)*byte_mul)); + + if (len1 != len2) { + DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1, len2, as)); + } + + /* this is a way of detecting if a string is sent with the wrong + termination */ + if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) { + if (strlen(as) < (len2 + c_len_term)) { + DEBUG(6,("short string '%s'\n", as)); + } + } else { + if (strlen(as) == (len2 + c_len_term)) { + DEBUG(6,("long string '%s'\n", as)); + } + } + *s = as; + break; + + case LIBNDR_FLAG_STR_SIZE4: + case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM: + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1)); + NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul); + if (len1 == 0) { + as = talloc_strdup(ndr->current_mem_ctx, ""); + } else { + ret = convert_string_talloc(ndr->current_mem_ctx, + chset, CH_UNIX, + ndr->data+ndr->offset, + (len1 + c_len_term)*byte_mul, + &as, False); + if (ret == -1) { + return ndr_pull_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + } + NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul)); + + /* this is a way of detecting if a string is sent with the wrong + termination */ + if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) { + if (strlen(as) < (len1 + c_len_term)) { + DEBUG(6,("short string '%s'\n", as)); + } + } else { + if (strlen(as) == (len1 + c_len_term)) { + DEBUG(6,("long string '%s'\n", as)); + } + } + *s = as; + break; + + case LIBNDR_FLAG_STR_LEN4: + case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM: + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs)); + if (ofs != 0) { + return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n", + ndr->flags & LIBNDR_STRING_FLAGS); + } + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1)); + NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul); + if (len1 == 0) { + as = talloc_strdup(ndr->current_mem_ctx, ""); + } else { + ret = convert_string_talloc(ndr->current_mem_ctx, + chset, CH_UNIX, + ndr->data+ndr->offset, + (len1 + c_len_term)*byte_mul, + &as, False); + if (ret == -1) { + return ndr_pull_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + } + NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul)); + + /* this is a way of detecting if a string is sent with the wrong + termination */ + if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) { + if (strlen(as) < (len1 + c_len_term)) { + DEBUG(6,("short string '%s'\n", as)); + } + } else { + if (strlen(as) == (len1 + c_len_term)) { + DEBUG(6,("long string '%s'\n", as)); + } + } + *s = as; + break; + + + case LIBNDR_FLAG_STR_SIZE2: + case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM: + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3)); + NDR_PULL_NEED_BYTES(ndr, (len3 + c_len_term)*byte_mul); + if (len3 == 0) { + as = talloc_strdup(ndr->current_mem_ctx, ""); + } else { + ret = convert_string_talloc(ndr->current_mem_ctx, + chset, CH_UNIX, + ndr->data+ndr->offset, + (len3 + c_len_term)*byte_mul, + &as, False); + if (ret == -1) { + return ndr_pull_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + } + NDR_CHECK(ndr_pull_advance(ndr, (len3 + c_len_term)*byte_mul)); + + /* this is a way of detecting if a string is sent with the wrong + termination */ + if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) { + if (strlen(as) < (len3 + c_len_term)) { + DEBUG(6,("short string '%s'\n", as)); + } + } else { + if (strlen(as) == (len3 + c_len_term)) { + DEBUG(6,("long string '%s'\n", as)); + } + } + *s = as; + break; + + case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE: + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3)); + NDR_PULL_NEED_BYTES(ndr, len3); + if (len3 == 0) { + as = talloc_strdup(ndr->current_mem_ctx, ""); + } else { + ret = convert_string_talloc(ndr->current_mem_ctx, + chset, CH_UNIX, + ndr->data+ndr->offset, + len3, &as, False); + if (ret == -1) { + return ndr_pull_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + } + NDR_CHECK(ndr_pull_advance(ndr, len3)); + *s = as; + break; + + case LIBNDR_FLAG_STR_NULLTERM: + if (byte_mul == 1) { + len1 = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset); + } else { + len1 = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset); + } + ret = convert_string_talloc(ndr->current_mem_ctx, + chset, CH_UNIX, + ndr->data+ndr->offset, + len1, &as, False); + if (ret == -1) { + return ndr_pull_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + NDR_CHECK(ndr_pull_advance(ndr, len1)); + *s = as; + break; + + case LIBNDR_FLAG_STR_FIXLEN15: + case LIBNDR_FLAG_STR_FIXLEN32: + len1 = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15; + NDR_PULL_NEED_BYTES(ndr, len1*byte_mul); + ret = convert_string_talloc(ndr->current_mem_ctx, + chset, CH_UNIX, + ndr->data+ndr->offset, + len1*byte_mul, &as, False); + if (ret == -1) { + return ndr_pull_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + NDR_CHECK(ndr_pull_advance(ndr, len1*byte_mul)); + *s = as; + break; + + default: + return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n", + ndr->flags & LIBNDR_STRING_FLAGS); + } + + return NT_STATUS_OK; +} + + +/** + push a general string onto the wire +*/ +NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s) +{ + ssize_t s_len, c_len, d_len; + charset_t chset = CH_UCS2; + unsigned flags = ndr->flags; + unsigned byte_mul = 2; + uint8_t *dest = NULL; + + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + + SMB_ASSERT(!NDR_BE(ndr)); + + s_len = s?strlen(s):0; + + if (flags & LIBNDR_FLAG_STR_ASCII) { + chset = CH_DOS; + byte_mul = 1; + flags &= ~LIBNDR_FLAG_STR_ASCII; + } + + if (flags & LIBNDR_FLAG_STR_UTF8) { + chset = CH_UTF8; + byte_mul = 1; + flags &= ~LIBNDR_FLAG_STR_UTF8; + } + + flags &= ~LIBNDR_FLAG_STR_CONFORMANT; + + if (!(flags & + (LIBNDR_FLAG_STR_NOTERM | + LIBNDR_FLAG_STR_FIXLEN15 | + LIBNDR_FLAG_STR_FIXLEN32))) { + s_len++; + } + d_len = convert_string_talloc(ndr, CH_UNIX, chset, s, s_len, &dest, + False); + if (d_len == -1) { + return ndr_push_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + + if (flags & LIBNDR_FLAG_STR_BYTESIZE) { + c_len = d_len; + flags &= ~LIBNDR_FLAG_STR_BYTESIZE; + } else if (flags & LIBNDR_FLAG_STR_CHARLEN) { + c_len = (d_len / byte_mul)-1; + flags &= ~LIBNDR_FLAG_STR_CHARLEN; + } else { + c_len = d_len / byte_mul; + } + + switch ((flags & LIBNDR_STRING_FLAGS) & ~LIBNDR_FLAG_STR_NOTERM) { + case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4: + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len)); + NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); + break; + + case LIBNDR_FLAG_STR_LEN4: + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len)); + NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); + break; + + case LIBNDR_FLAG_STR_SIZE4: + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len)); + NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); + break; + + case LIBNDR_FLAG_STR_SIZE2: + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len)); + NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); + break; + + case LIBNDR_FLAG_STR_NULLTERM: + NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); + break; + + case LIBNDR_FLAG_STR_FIXLEN15: + case LIBNDR_FLAG_STR_FIXLEN32: { + ssize_t fix_len = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15; + uint32_t pad_len = fix_len - d_len; + if (d_len > fix_len) { + return ndr_push_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); + if (pad_len != 0) { + NDR_CHECK(ndr_push_zero(ndr, pad_len)); + } + break; + } + + default: + return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n", + ndr->flags & LIBNDR_STRING_FLAGS); + } + + talloc_free(dest); + + return NT_STATUS_OK; +} + +/** + push a general string onto the wire +*/ +size_t ndr_string_array_size(struct ndr_push *ndr, const char *s) +{ + size_t c_len; + unsigned flags = ndr->flags; + unsigned byte_mul = 2; + unsigned c_len_term = 1; + + if (flags & LIBNDR_FLAG_STR_FIXLEN32) { + return 32; + } + if (flags & LIBNDR_FLAG_STR_FIXLEN15) { + return 15; + } + + c_len = s?strlen(s):0; + + if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) { + byte_mul = 1; + } + + if (flags & LIBNDR_FLAG_STR_NOTERM) { + c_len_term = 0; + } + + c_len = c_len + c_len_term; + + if (flags & LIBNDR_FLAG_STR_BYTESIZE) { + c_len = c_len * byte_mul; + } + + return c_len; +} + +void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s) +{ + if (s) { + ndr->print(ndr, "%-25s: '%s'", name, s); + } else { + ndr->print(ndr, "%-25s: NULL", name); + } +} + +uint32_t ndr_size_string(int ret, const char * const* string, int flags) +{ + /* FIXME: Is this correct for all strings ? */ + if(!(*string)) return ret; + return ret+strlen(*string)+1; +} + +/** + pull a general string array from the wire +*/ +NTSTATUS ndr_pull_string_array(struct ndr_pull *ndr, int ndr_flags, const char ***_a) +{ + const char **a = *_a; + uint32_t count; + + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + + for (count = 0;; count++) { + TALLOC_CTX *tmp_ctx; + const char *s = NULL; + a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2); + NT_STATUS_HAVE_NO_MEMORY(a); + a[count] = NULL; + a[count+1] = NULL; + + tmp_ctx = ndr->current_mem_ctx; + ndr->current_mem_ctx = a; + NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s)); + ndr->current_mem_ctx = tmp_ctx; + if (strcmp("", s)==0) { + a[count] = NULL; + break; + } else { + a[count] = s; + } + } + + *_a =a; + return NT_STATUS_OK; +} + +/** + push a general string array onto the wire +*/ +NTSTATUS ndr_push_string_array(struct ndr_push *ndr, int ndr_flags, const char **a) +{ + uint32_t count; + + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + + for (count = 0; a && a[count]; count++) { + NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count])); + } + + NDR_CHECK(ndr_push_string(ndr, ndr_flags, "")); + + return NT_STATUS_OK; +} + +void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a) +{ + uint32_t count; + uint32_t i; + + for (count = 0; a && a[count]; count++) {} + + ndr->print(ndr, "%s: ARRAY(%d)", name, count); + ndr->depth++; + for (i=0;i<count;i++) { + char *idx=NULL; + asprintf(&idx, "[%d]", i); + if (idx) { + ndr_print_string(ndr, idx, a[i]); + free(idx); + } + } + ndr->depth--; +} + +/** + * Return number of elements in a string including the last (zeroed) element + */ +uint32_t ndr_string_length(const void *_var, uint32_t element_size) +{ + uint32_t i; + uint8_t zero[4] = {0,0,0,0}; + const char *var = (const char *)_var; + + for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++); + + return i+1; +} + +NTSTATUS ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size) +{ + uint32_t i; + struct ndr_pull_save save_offset; + + ndr_pull_save(ndr, &save_offset); + ndr_pull_advance(ndr, (count - 1) * element_size); + NDR_PULL_NEED_BYTES(ndr, element_size); + + for (i = 0; i < element_size; i++) { + if (ndr->data[ndr->offset+i] != 0) { + ndr_pull_restore(ndr, &save_offset); + + return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries"); + } + } + + ndr_pull_restore(ndr, &save_offset); + + return NT_STATUS_OK; +} + +NTSTATUS ndr_pull_charset(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, int chset) +{ + int ret; + if (length == 0) { + *var = talloc_strdup(ndr->current_mem_ctx, ""); + return NT_STATUS_OK; + } + + SMB_ASSERT (!NDR_BE(ndr) || chset != CH_UCS2); + + NDR_PULL_NEED_BYTES(ndr, length*byte_mul); + + ret = convert_string_talloc(ndr->current_mem_ctx, + chset, CH_UNIX, + ndr->data+ndr->offset, + length*byte_mul, + var, False); + if (ret == -1) { + return ndr_pull_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul)); + + return NT_STATUS_OK; +} + +NTSTATUS ndr_push_charset(struct ndr_push *ndr, int ndr_flags, const char *var, + uint32_t length, uint8_t byte_mul, charset_t chset) +{ + ssize_t ret, required; + + SMB_ASSERT(!NDR_BE(ndr) || chset != CH_UCS2); + + required = byte_mul * length; + + NDR_PUSH_NEED_BYTES(ndr, required); + ret = convert_string(CH_UNIX, chset, + var, strlen(var), + ndr->data+ndr->offset, required, False); + if (ret == -1) { + return ndr_push_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + + /* Make sure the remaining part of the string is filled with zeroes */ + if (ret < required) { + memset(ndr->data+ndr->offset+ret, 0, required-ret); + } + + ndr->offset += required; + + return NT_STATUS_OK; +} + +/* Return number of elements in a string in the specified charset */ +uint32_t ndr_charset_length(const void *var, int chset) +{ + /* FIXME: Treat special chars special here, taking chset into account */ + /* Also include 0 byte */ + return strlen((const char *)var)+1; +} diff --git a/source/libndr/security.h b/source/libndr/security.h new file mode 100644 index 00000000000..8f790f387ed --- /dev/null +++ b/source/libndr/security.h @@ -0,0 +1,260 @@ +/* header auto-generated by pidl */ + +#ifndef _HEADER_security +#define _HEADER_security + +#define SEC_MASK_GENERIC ( 0xF0000000 ) +#define SEC_MASK_FLAGS ( 0x0F000000 ) +#define SEC_MASK_STANDARD ( 0x00FF0000 ) +#define SEC_MASK_SPECIFIC ( 0x0000FFFF ) +#define SEC_GENERIC_ALL ( 0x10000000 ) +#define SEC_GENERIC_EXECUTE ( 0x20000000 ) +#define SEC_GENERIC_WRITE ( 0x40000000 ) +#define SEC_GENERIC_READ ( 0x80000000 ) +#define SEC_FLAG_SYSTEM_SECURITY ( 0x01000000 ) +#define SEC_FLAG_MAXIMUM_ALLOWED ( 0x02000000 ) +#define SEC_STD_DELETE ( 0x00010000 ) +#define SEC_STD_READ_CONTROL ( 0x00020000 ) +#define SEC_STD_WRITE_DAC ( 0x00040000 ) +#define SEC_STD_WRITE_OWNER ( 0x00080000 ) +#define SEC_STD_SYNCHRONIZE ( 0x00100000 ) +#define SEC_STD_REQUIRED ( 0x000F0000 ) +#define SEC_STD_ALL ( 0x001F0000 ) +#define SEC_FILE_READ_DATA ( 0x00000001 ) +#define SEC_FILE_WRITE_DATA ( 0x00000002 ) +#define SEC_FILE_APPEND_DATA ( 0x00000004 ) +#define SEC_FILE_READ_EA ( 0x00000008 ) +#define SEC_FILE_WRITE_EA ( 0x00000010 ) +#define SEC_FILE_EXECUTE ( 0x00000020 ) +#define SEC_FILE_READ_ATTRIBUTE ( 0x00000080 ) +#define SEC_FILE_WRITE_ATTRIBUTE ( 0x00000100 ) +#define SEC_FILE_ALL ( 0x000001ff ) +#define SEC_DIR_LIST ( 0x00000001 ) +#define SEC_DIR_ADD_FILE ( 0x00000002 ) +#define SEC_DIR_ADD_SUBDIR ( 0x00000004 ) +#define SEC_DIR_READ_EA ( 0x00000008 ) +#define SEC_DIR_WRITE_EA ( 0x00000010 ) +#define SEC_DIR_TRAVERSE ( 0x00000020 ) +#define SEC_DIR_DELETE_CHILD ( 0x00000040 ) +#define SEC_DIR_READ_ATTRIBUTE ( 0x00000080 ) +#define SEC_DIR_WRITE_ATTRIBUTE ( 0x00000100 ) +#define SEC_REG_QUERY_VALUE ( 0x00000001 ) +#define SEC_REG_SET_VALUE ( 0x00000002 ) +#define SEC_REG_CREATE_SUBKEY ( 0x00000004 ) +#define SEC_REG_ENUM_SUBKEYS ( 0x00000008 ) +#define SEC_REG_NOTIFY ( 0x00000010 ) +#define SEC_REG_CREATE_LINK ( 0x00000020 ) +#define SEC_ADS_CREATE_CHILD ( 0x00000001 ) +#define SEC_ADS_DELETE_CHILD ( 0x00000002 ) +#define SEC_ADS_LIST ( 0x00000004 ) +#define SEC_ADS_SELF_WRITE ( 0x00000008 ) +#define SEC_ADS_READ_PROP ( 0x00000010 ) +#define SEC_ADS_WRITE_PROP ( 0x00000020 ) +#define SEC_ADS_DELETE_TREE ( 0x00000040 ) +#define SEC_ADS_LIST_OBJECT ( 0x00000080 ) +#define SEC_ADS_CONTROL_ACCESS ( 0x00000100 ) +#define SEC_RIGHTS_FILE_READ ( SEC_STD_READ_CONTROL|SEC_STD_SYNCHRONIZE|SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_READ_EA ) +#define SEC_RIGHTS_FILE_WRITE ( SEC_STD_READ_CONTROL|SEC_STD_SYNCHRONIZE|SEC_FILE_WRITE_DATA|SEC_FILE_WRITE_ATTRIBUTE|SEC_FILE_WRITE_EA|SEC_FILE_APPEND_DATA ) +#define SEC_RIGHTS_FILE_EXECUTE ( SEC_STD_SYNCHRONIZE|SEC_STD_READ_CONTROL|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_EXECUTE ) +#define SEC_RIGHTS_FILE_ALL ( SEC_STD_ALL|SEC_FILE_ALL ) +#define SEC_RIGHTS_DIR_READ ( SEC_RIGHTS_FILE_READ ) +#define SEC_RIGHTS_DIR_WRITE ( SEC_RIGHTS_FILE_WRITE ) +#define SEC_RIGHTS_DIR_EXECUTE ( SEC_RIGHTS_FILE_EXECUTE ) +#define SEC_RIGHTS_DIR_ALL ( SEC_RIGHTS_FILE_ALL ) +#define SID_NULL ( "S-1-0-0" ) +#define SID_WORLD_DOMAIN ( "S-1-1" ) +#define SID_WORLD ( "S-1-1-0" ) +#define SID_CREATOR_OWNER_DOMAIN ( "S-1-3" ) +#define SID_CREATOR_OWNER ( "S-1-3-0" ) +#define SID_CREATOR_GROUP ( "S-1-3-1" ) +#define SID_NT_AUTHORITY ( "S-1-5" ) +#define SID_NT_DIALUP ( "S-1-5-1" ) +#define SID_NT_NETWORK ( "S-1-5-2" ) +#define SID_NT_BATCH ( "S-1-5-3" ) +#define SID_NT_INTERACTIVE ( "S-1-5-4" ) +#define SID_NT_SERVICE ( "S-1-5-6" ) +#define SID_NT_ANONYMOUS ( "S-1-5-7" ) +#define SID_NT_PROXY ( "S-1-5-8" ) +#define SID_NT_ENTERPRISE_DCS ( "S-1-5-9" ) +#define SID_NT_SELF ( "S-1-5-10" ) +#define SID_NT_AUTHENTICATED_USERS ( "S-1-5-11" ) +#define SID_NT_RESTRICTED ( "S-1-5-12" ) +#define SID_NT_TERMINAL_SERVER_USERS ( "S-1-5-13" ) +#define SID_NT_REMOTE_INTERACTIVE ( "S-1-5-14" ) +#define SID_NT_THIS_ORGANISATION ( "S-1-5-15" ) +#define SID_NT_SYSTEM ( "S-1-5-18" ) +#define SID_NT_LOCAL_SERVICE ( "S-1-5-19" ) +#define SID_NT_NETWORK_SERVICE ( "S-1-5-20" ) +#define SID_BUILTIN ( "S-1-5-32" ) +#define SID_BUILTIN_ADMINISTRATORS ( "S-1-5-32-544" ) +#define SID_BUILTIN_USERS ( "S-1-5-32-545" ) +#define SID_BUILTIN_GUESTS ( "S-1-5-32-546" ) +#define SID_BUILTIN_POWER_USERS ( "S-1-5-32-547" ) +#define SID_BUILTIN_ACCOUNT_OPERATORS ( "S-1-5-32-548" ) +#define SID_BUILTIN_SERVER_OPERATORS ( "S-1-5-32-549" ) +#define SID_BUILTIN_PRINT_OPERATORS ( "S-1-5-32-550" ) +#define SID_BUILTIN_BACKUP_OPERATORS ( "S-1-5-32-551" ) +#define SID_BUILTIN_REPLICATOR ( "S-1-5-32-552" ) +#define SID_BUILTIN_RAS_SERVERS ( "S-1-5-32-553" ) +#define SID_BUILTIN_PREW2K ( "S-1-5-32-554" ) +#define DOMAIN_RID_LOGON ( 9 ) +#define DOMAIN_RID_ADMINISTRATOR ( 500 ) +#define DOMAIN_RID_GUEST ( 501 ) +#define DOMAIN_RID_ADMINS ( 512 ) +#define DOMAIN_RID_USERS ( 513 ) +#define DOMAIN_RID_DCS ( 516 ) +#define DOMAIN_RID_CERT_ADMINS ( 517 ) +#define DOMAIN_RID_SCHEMA_ADMINS ( 518 ) +#define DOMAIN_RID_ENTERPRISE_ADMINS ( 519 ) +#define NT4_ACL_REVISION ( SECURITY_ACL_REVISION_NT4 ) +#define SD_REVISION ( SECURITY_DESCRIPTOR_REVISION_1 ) +enum sec_privilege { + SEC_PRIV_SECURITY=1, + SEC_PRIV_BACKUP=2, + SEC_PRIV_RESTORE=3, + SEC_PRIV_SYSTEMTIME=4, + SEC_PRIV_SHUTDOWN=5, + SEC_PRIV_REMOTE_SHUTDOWN=6, + SEC_PRIV_TAKE_OWNERSHIP=7, + SEC_PRIV_DEBUG=8, + SEC_PRIV_SYSTEM_ENVIRONMENT=9, + SEC_PRIV_SYSTEM_PROFILE=10, + SEC_PRIV_PROFILE_SINGLE_PROCESS=11, + SEC_PRIV_INCREASE_BASE_PRIORITY=12, + SEC_PRIV_LOAD_DRIVER=13, + SEC_PRIV_CREATE_PAGEFILE=14, + SEC_PRIV_INCREASE_QUOTA=15, + SEC_PRIV_CHANGE_NOTIFY=16, + SEC_PRIV_UNDOCK=17, + SEC_PRIV_MANAGE_VOLUME=18, + SEC_PRIV_IMPERSONATE=19, + SEC_PRIV_CREATE_GLOBAL=20, + SEC_PRIV_ENABLE_DELEGATION=21, + SEC_PRIV_INTERACTIVE_LOGON=22, + SEC_PRIV_NETWORK_LOGON=23, + SEC_PRIV_REMOTE_INTERACTIVE_LOGON=24 +}; + +struct dom_sid { + uint8_t sid_rev_num; + int8_t num_auths;/* [range(0 15)] */ + uint8_t id_auth[6]; + uint32_t *sub_auths; +}/* [noprint,gensize,noejs,public,nosize] */; + +/* bitmap security_ace_flags */ +#define SEC_ACE_FLAG_OBJECT_INHERIT ( 0x01 ) +#define SEC_ACE_FLAG_CONTAINER_INHERIT ( 0x02 ) +#define SEC_ACE_FLAG_NO_PROPAGATE_INHERIT ( 0x04 ) +#define SEC_ACE_FLAG_INHERIT_ONLY ( 0x08 ) +#define SEC_ACE_FLAG_INHERITED_ACE ( 0x10 ) +#define SEC_ACE_FLAG_VALID_INHERIT ( 0x0f ) +#define SEC_ACE_FLAG_SUCCESSFUL_ACCESS ( 0x40 ) +#define SEC_ACE_FLAG_FAILED_ACCESS ( 0x80 ) + +enum security_ace_type { + SEC_ACE_TYPE_ACCESS_ALLOWED=0, + SEC_ACE_TYPE_ACCESS_DENIED=1, + SEC_ACE_TYPE_SYSTEM_AUDIT=2, + SEC_ACE_TYPE_SYSTEM_ALARM=3, + SEC_ACE_TYPE_ALLOWED_COMPOUND=4, + SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT=5, + SEC_ACE_TYPE_ACCESS_DENIED_OBJECT=6, + SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT=7, + SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT=8 +}; + +/* bitmap security_ace_object_flags */ +#define SEC_ACE_OBJECT_TYPE_PRESENT ( 0x00000001 ) +#define SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT ( 0x00000002 ) + +union security_ace_object_type { + struct GUID type;/* [case(SEC_ACE_OBJECT_TYPE_PRESENT)] */ +}/* [nodiscriminant] */; + +union security_ace_object_inherited_type { + struct GUID inherited_type;/* [case(SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)] */ +}/* [nodiscriminant] */; + +struct security_ace_object { + uint32_t flags; + union security_ace_object_type type;/* [switch_is(flags&SEC_ACE_OBJECT_TYPE_PRESENT)] */ + union security_ace_object_inherited_type inherited_type;/* [switch_is(flags&SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)] */ +}; + +union security_ace_object_ctr { + struct security_ace_object object;/* [case(SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT)] */ +}/* [nodiscriminant] */; + +struct security_ace { + enum security_ace_type type; + uint8_t flags; + uint16_t size;/* [value(ndr_size_security_ace(r,ndr->flags))] */ + uint32_t access_mask; + union security_ace_object_ctr object;/* [switch_is(type)] */ + struct dom_sid trustee; +}/* [gensize,public,nosize] */; + +enum security_acl_revision { + SECURITY_ACL_REVISION_NT4=2, + SECURITY_ACL_REVISION_ADS=4 +}; + +struct security_acl { + enum security_acl_revision revision; + uint16_t size;/* [value(ndr_size_security_acl(r,ndr->flags))] */ + uint32_t num_aces;/* [range(0 1000)] */ + struct security_ace *aces; +}/* [gensize,public,nosize] */; + +enum security_descriptor_revision { + SECURITY_DESCRIPTOR_REVISION_1=1 +}; + +/* bitmap security_descriptor_type */ +#define SEC_DESC_OWNER_DEFAULTED ( 0x0001 ) +#define SEC_DESC_GROUP_DEFAULTED ( 0x0002 ) +#define SEC_DESC_DACL_PRESENT ( 0x0004 ) +#define SEC_DESC_DACL_DEFAULTED ( 0x0008 ) +#define SEC_DESC_SACL_PRESENT ( 0x0010 ) +#define SEC_DESC_SACL_DEFAULTED ( 0x0020 ) +#define SEC_DESC_DACL_TRUSTED ( 0x0040 ) +#define SEC_DESC_SERVER_SECURITY ( 0x0080 ) +#define SEC_DESC_DACL_AUTO_INHERIT_REQ ( 0x0100 ) +#define SEC_DESC_SACL_AUTO_INHERIT_REQ ( 0x0200 ) +#define SEC_DESC_DACL_AUTO_INHERITED ( 0x0400 ) +#define SEC_DESC_SACL_AUTO_INHERITED ( 0x0800 ) +#define SEC_DESC_DACL_PROTECTED ( 0x1000 ) +#define SEC_DESC_SACL_PROTECTED ( 0x2000 ) +#define SEC_DESC_RM_CONTROL_VALID ( 0x4000 ) +#define SEC_DESC_SELF_RELATIVE ( 0x8000 ) + +struct security_descriptor { + enum security_descriptor_revision revision; + uint16_t type; + struct dom_sid *owner_sid;/* [relative] */ + struct dom_sid *group_sid;/* [relative] */ + struct security_acl *sacl;/* [relative] */ + struct security_acl *dacl;/* [relative] */ +}/* [gensize,public,flag(LIBNDR_FLAG_LITTLE_ENDIAN),nosize] */; + +struct sec_desc_buf { + uint32_t sd_size;/* [value(ndr_size_security_descriptor(sd,ndr->flags)),range(0 0x40000)] */ + struct security_descriptor *sd;/* [unique,subcontext(4)] */ +}/* [public] */; + +struct security_token { + struct dom_sid *user_sid;/* [unique] */ + struct dom_sid *group_sid;/* [unique] */ + uint32_t num_sids; + struct dom_sid **sids;/* [unique,size_is(num_sids)] */ + uint64_t privilege_mask; +}/* [public] */; + +/* bitmap security_secinfo */ +#define SECINFO_OWNER ( 0x00000001 ) +#define SECINFO_GROUP ( 0x00000002 ) +#define SECINFO_DACL ( 0x00000004 ) +#define SECINFO_SACL ( 0x00000008 ) + +#endif /* _HEADER_security */ diff --git a/source/libndr/sid.c b/source/libndr/sid.c new file mode 100644 index 00000000000..0bb42a3683b --- /dev/null +++ b/source/libndr/sid.c @@ -0,0 +1,97 @@ +/* + Unix SMB/CIFS implementation. + + libndr interface + + Copyright (C) Andrew Tridgell 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +NTSTATUS ndr_push_dom_sid(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *r) +{ + uint32_t cntr_sub_auths_0; + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->sid_rev_num)); + NDR_CHECK(ndr_push_int8(ndr, NDR_SCALARS, r->num_auths)); + NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6)); + for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) { + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->sub_auths[cntr_sub_auths_0])); + } + } + if (ndr_flags & NDR_BUFFERS) { + } + return NT_STATUS_OK; +} + +NTSTATUS ndr_pull_dom_sid(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *r) +{ + uint32_t cntr_sub_auths_0; + TALLOC_CTX *_mem_save_sub_auths_0; + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->sid_rev_num)); + NDR_CHECK(ndr_pull_int8(ndr, NDR_SCALARS, &r->num_auths)); + if (r->num_auths < 0 || r->num_auths > 15) { + return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range"); + } + NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6)); + NDR_PULL_ALLOC_N(ndr, r->sub_auths, r->num_auths); + _mem_save_sub_auths_0 = NDR_PULL_GET_MEM_CTX(ndr); + NDR_PULL_SET_MEM_CTX(ndr, r->sub_auths, 0); + for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) { + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sub_auths[cntr_sub_auths_0])); + } + NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sub_auths_0, 0); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NT_STATUS_OK; +} + +/* + convert a dom_sid to a string +*/ +char *dom_sid_string(TALLOC_CTX *mem_ctx, const struct dom_sid *sid) +{ + int i, ofs, maxlen; + uint32_t ia; + char *ret; + + if (!sid) { + return talloc_strdup(mem_ctx, "(NULL SID)"); + } + + maxlen = sid->num_auths * 11 + 25; + ret = talloc_size(mem_ctx, maxlen); + if (!ret) return talloc_strdup(mem_ctx, "(SID ERR)"); + + ia = (sid->id_auth[5]) + + (sid->id_auth[4] << 8 ) + + (sid->id_auth[3] << 16) + + (sid->id_auth[2] << 24); + + ofs = snprintf(ret, maxlen, "S-%u-%lu", + (unsigned int)sid->sid_rev_num, (unsigned long)ia); + + for (i = 0; i < sid->num_auths; i++) { + ofs += snprintf(ret + ofs, maxlen - ofs, "-%lu", (unsigned long)sid->sub_auths[i]); + } + + return ret; +} diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c index 7f5b5d7fa57..4c3c4f45650 100644 --- a/source/libsmb/cliconnect.c +++ b/source/libsmb/cliconnect.c @@ -1394,8 +1394,9 @@ NTSTATUS cli_start_connection(struct cli_state **output_cli, if (!my_name) my_name = global_myname(); - if (!(cli = cli_initialise(NULL))) + if (!(cli = cli_initialise())) { return NT_STATUS_NO_MEMORY; + } make_nmb_name(&calling, my_name, 0x0); make_nmb_name(&called , dest_host, 0x20); @@ -1495,6 +1496,8 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli, struct cli_state *cli = NULL; int pw_len = password ? strlen(password)+1 : 0; + *output_cli = NULL; + if (password == NULL) { password = ""; } @@ -1513,8 +1516,9 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli, nt_status = cli_nt_error(cli); DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status))); cli_shutdown(cli); - if (NT_STATUS_IS_OK(nt_status)) + if (NT_STATUS_IS_OK(nt_status)) { nt_status = NT_STATUS_UNSUCCESSFUL; + } return nt_status; } } @@ -1541,7 +1545,7 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli, Attempt a NetBIOS session request, falling back to *SMBSERVER if needed. ****************************************************************************/ -BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost, +BOOL attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost, struct in_addr *pdest_ip) { struct nmb_name calling, called; @@ -1553,12 +1557,13 @@ BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, * then use *SMBSERVER immediately. */ - if(is_ipaddress(desthost)) + if(is_ipaddress(desthost)) { make_nmb_name(&called, "*SMBSERVER", 0x20); - else + } else { make_nmb_name(&called, desthost, 0x20); + } - if (!cli_session_request(cli, &calling, &called)) { + if (!cli_session_request(*ppcli, &calling, &called)) { struct nmb_name smbservername; make_nmb_name(&smbservername , "*SMBSERVER", 0x20); @@ -1575,23 +1580,23 @@ BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, */ DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \ -with error %s.\n", desthost, cli_errstr(cli) )); +with error %s.\n", desthost, cli_errstr(*ppcli) )); return False; } - /* - * We need to close the connection here but can't call cli_shutdown as - * will free an allocated cli struct. cli_close_connection was invented - * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>. - */ + /* Try again... */ + cli_shutdown(*ppcli); - cli_close_connection(cli); + *ppcli = cli_initialise(); + if (!*ppcli) { + /* Out of memory... */ + return False; + } - if (!cli_initialise(cli) || - !cli_connect(cli, desthost, pdest_ip) || - !cli_session_request(cli, &calling, &smbservername)) { + if (!cli_connect(*ppcli, desthost, pdest_ip) || + !cli_session_request(*ppcli, &calling, &smbservername)) { DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \ -name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) )); +name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) )); return False; } } diff --git a/source/libsmb/clidfs.c b/source/libsmb/clidfs.c index e564bc42957..4280b0628eb 100644 --- a/source/libsmb/clidfs.c +++ b/source/libsmb/clidfs.c @@ -51,7 +51,7 @@ static struct client_connection *connections; static struct cli_state *do_connect( const char *server, const char *share, BOOL show_sessetup ) { - struct cli_state *c; + struct cli_state *c = NULL; struct nmb_name called, calling; const char *server_n; struct in_addr ip; @@ -83,7 +83,7 @@ static struct cli_state *do_connect( const char *server, const char *share, ip = dest_ip; /* have to open a new connection */ - if (!(c=cli_initialise(NULL)) || (cli_set_port(c, port) != port) || + if (!(c=cli_initialise()) || (cli_set_port(c, port) != port) || !cli_connect(c, server_n, &ip)) { d_printf("Connection to %s failed\n", server_n); return NULL; @@ -99,6 +99,7 @@ static struct cli_state *do_connect( const char *server, const char *share, d_printf("session request to %s failed (%s)\n", called.name, cli_errstr(c)); cli_shutdown(c); + c = NULL; if ((p=strchr_m(called.name, '.'))) { *p = 0; goto again; diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c index 8342df0f1d1..4608d40d462 100644 --- a/source/libsmb/clientgen.c +++ b/source/libsmb/clientgen.c @@ -255,12 +255,12 @@ void cli_setup_signing_state(struct cli_state *cli, int signing_state) } /**************************************************************************** - Initialise a client structure. + Initialise a client structure. Always returns a malloc'ed struct. ****************************************************************************/ -struct cli_state *cli_initialise(struct cli_state *cli) +struct cli_state *cli_initialise(void) { - BOOL alloced_cli = False; + struct cli_state *cli = NULL; /* Check the effective uid - make sure we are not setuid */ if (is_setuid_root()) { @@ -268,17 +268,11 @@ struct cli_state *cli_initialise(struct cli_state *cli) return NULL; } + cli = SMB_MALLOC_P(struct cli_state); if (!cli) { - cli = SMB_MALLOC_P(struct cli_state); - if (!cli) - return NULL; - ZERO_STRUCTP(cli); - alloced_cli = True; + return NULL; } - if (cli->initialised) - cli_close_connection(cli); - ZERO_STRUCTP(cli); cli->port = 0; @@ -333,7 +327,6 @@ struct cli_state *cli_initialise(struct cli_state *cli) cli_null_set_signing(cli); cli->initialised = 1; - cli->allocated = alloced_cli; return cli; @@ -343,10 +336,7 @@ struct cli_state *cli_initialise(struct cli_state *cli) SAFE_FREE(cli->inbuf); SAFE_FREE(cli->outbuf); - - if (alloced_cli) - SAFE_FREE(cli); - + SAFE_FREE(cli); return NULL; } @@ -403,10 +393,10 @@ void cli_nt_pipes_close(struct cli_state *cli) } /**************************************************************************** - Close a client connection and free the memory without destroying cli itself. + Shutdown a client structure. ****************************************************************************/ -void cli_close_connection(struct cli_state *cli) +void cli_shutdown(struct cli_state *cli) { cli_nt_pipes_close(cli); @@ -443,20 +433,8 @@ void cli_close_connection(struct cli_state *cli) } cli->fd = -1; cli->smb_rw_error = 0; -} -/**************************************************************************** - Shutdown a client structure. -****************************************************************************/ - -void cli_shutdown(struct cli_state *cli) -{ - BOOL allocated = cli->allocated; - cli_close_connection(cli); - ZERO_STRUCTP(cli); - if (allocated) { - free(cli); - } + SAFE_FREE(cli); } /**************************************************************************** diff --git a/source/libsmb/clikrb5.c b/source/libsmb/clikrb5.c index abb3843bacb..d40fc31dc44 100644 --- a/source/libsmb/clikrb5.c +++ b/source/libsmb/clikrb5.c @@ -112,7 +112,7 @@ static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context, #ifndef HAVE_KRB5_SET_REAL_TIME /* - * This function is not in the Heimdal mainline. + * Thir function is not in the Heimdal mainline. */ krb5_error_code krb5_set_real_time(krb5_context context, int32_t seconds, int32_t microseconds) { diff --git a/source/libsmb/clirap2.c b/source/libsmb/clirap2.c index 147683689d6..3c23310f66c 100644 --- a/source/libsmb/clirap2.c +++ b/source/libsmb/clirap2.c @@ -220,7 +220,7 @@ int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 * grinfo ) /* Allocate data. */ data_size = MAX(soffset + strlen(grinfo->comment) + 1, 1024); - data = SMB_MALLOC(data_size); + data = SMB_MALLOC_ARRAY(char, data_size); if (!data) { DEBUG (1, ("Malloc fail\n")); return -1; diff --git a/source/libsmb/libsmb_cache.c b/source/libsmb/libsmb_cache.c index 5d948ea5e25..8c4fd7c89f7 100644 --- a/source/libsmb/libsmb_cache.c +++ b/source/libsmb/libsmb_cache.c @@ -150,9 +150,10 @@ static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, const char * server, * doesn't match the requested share, so * disconnect from the current share. */ - if (! cli_tdis(&srv->server->cli)) { + if (! cli_tdis(srv->server->cli)) { /* Sigh. Couldn't disconnect. */ - cli_shutdown(&srv->server->cli); + cli_shutdown(srv->server->cli); + srv->server->cli = NULL; context->callbacks.remove_cached_srv_fn(context, srv->server); continue; } @@ -166,7 +167,8 @@ static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, const char * server, srv->share_name = SMB_STRDUP(share); if (!srv->share_name) { /* Out of memory. */ - cli_shutdown(&srv->server->cli); + cli_shutdown(srv->server->cli); + srv->server->cli = NULL; context->callbacks.remove_cached_srv_fn(context, srv->server); continue; } diff --git a/source/libsmb/libsmbclient.c b/source/libsmb/libsmbclient.c index ca2624305e6..db788f46e9b 100644 --- a/source/libsmb/libsmbclient.c +++ b/source/libsmb/libsmbclient.c @@ -487,7 +487,7 @@ static int smbc_check_server(SMBCCTX * context, SMBCSRV * server) { - if ( send_keepalive(server->cli.fd) == False ) + if ( send_keepalive(server->cli->fd) == False ) return 1; /* connection is ok */ @@ -524,7 +524,8 @@ smbc_remove_unused_server(SMBCCTX * context, DLIST_REMOVE(context->internal->_servers, srv); - cli_shutdown(&srv->cli); + cli_shutdown(srv->cli); + srv->cli = NULL; DEBUG(3, ("smbc_remove_usused_server: %p removed.\n", srv)); @@ -630,7 +631,7 @@ smbc_server(SMBCCTX *context, fstring password) { SMBCSRV *srv=NULL; - struct cli_state c; + struct cli_state *c; struct nmb_name called, calling; const char *server_n = server; pstring ipenv; @@ -666,7 +667,7 @@ smbc_server(SMBCCTX *context, * disconnect if the requested share is not the same as the * one that was already connected. */ - if (srv->cli.cnum == (uint16) -1) { + if (srv->cli->cnum == (uint16) -1) { /* Ensure we have accurate auth info */ if (context->internal->_auth_fn_with_context != NULL) { context->internal->_auth_fn_with_context( @@ -683,11 +684,12 @@ smbc_server(SMBCCTX *context, password, sizeof(fstring)); } - if (! cli_send_tconX(&srv->cli, share, "?????", + if (! cli_send_tconX(srv->cli, share, "?????", password, strlen(password)+1)) { - errno = smbc_errno(context, &srv->cli); - cli_shutdown(&srv->cli); + errno = smbc_errno(context, srv->cli); + cli_shutdown(srv->cli); + srv->cli = NULL; context->callbacks.remove_cached_srv_fn(context, srv); srv = NULL; @@ -730,19 +732,19 @@ smbc_server(SMBCCTX *context, zero_ip(&ip); /* have to open a new connection */ - if (!cli_initialise(&c)) { + if ((c = cli_initialise()) == NULL) { errno = ENOMEM; return NULL; } if (context->flags & SMB_CTX_FLAG_USE_KERBEROS) { - c.use_kerberos = True; + c->use_kerberos = True; } if (context->flags & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS) { - c.fallback_after_kerberos = True; + c->fallback_after_kerberos = True; } - c.timeout = context->timeout; + c->timeout = context->timeout; /* * Force use of port 139 for first try if share is $IPC, empty, or @@ -756,49 +758,47 @@ smbc_server(SMBCCTX *context, port_try_next = 139; } - c.port = port_try_first; + c->port = port_try_first; - if (!cli_connect(&c, server_n, &ip)) { + if (!cli_connect(c, server_n, &ip)) { /* First connection attempt failed. Try alternate port. */ - c.port = port_try_next; + c->port = port_try_next; - if (!cli_connect(&c, server_n, &ip)) { - cli_shutdown(&c); + if (!cli_connect(c, server_n, &ip)) { + cli_shutdown(c); errno = ETIMEDOUT; return NULL; } } - if (!cli_session_request(&c, &calling, &called)) { - cli_shutdown(&c); + if (!cli_session_request(c, &calling, &called)) { + cli_shutdown(c); if (strcmp(called.name, "*SMBSERVER")) { make_nmb_name(&called , "*SMBSERVER", 0x20); goto again; - } - else { /* Try one more time, but ensure we don't loop */ - - /* Only try this if server is an IP address ... */ - - if (is_ipaddress(server) && !tried_reverse) { - fstring remote_name; - struct in_addr rem_ip; + } else { /* Try one more time, but ensure we don't loop */ - if ((rem_ip.s_addr=inet_addr(server)) == INADDR_NONE) { - DEBUG(4, ("Could not convert IP address %s to struct in_addr\n", server)); - errno = ETIMEDOUT; - return NULL; - } + /* Only try this if server is an IP address ... */ - tried_reverse++; /* Yuck */ + if (is_ipaddress(server) && !tried_reverse) { + fstring remote_name; + struct in_addr rem_ip; - if (name_status_find("*", 0, 0, rem_ip, remote_name)) { - make_nmb_name(&called, remote_name, 0x20); - goto again; - } + if ((rem_ip.s_addr=inet_addr(server)) == INADDR_NONE) { + DEBUG(4, ("Could not convert IP address " + "%s to struct in_addr\n", server)); + errno = ETIMEDOUT; + return NULL; + } + tried_reverse++; /* Yuck */ - } + if (name_status_find("*", 0, 0, rem_ip, remote_name)) { + make_nmb_name(&called, remote_name, 0x20); + goto again; + } + } } errno = ETIMEDOUT; return NULL; @@ -806,15 +806,15 @@ smbc_server(SMBCCTX *context, DEBUG(4,(" session request ok\n")); - if (!cli_negprot(&c)) { - cli_shutdown(&c); + if (!cli_negprot(c)) { + cli_shutdown(c); errno = ETIMEDOUT; return NULL; } username_used = username; - if (!cli_session_setup(&c, username_used, + if (!cli_session_setup(c, username_used, password, strlen(password), password, strlen(password), workgroup)) { @@ -823,12 +823,12 @@ smbc_server(SMBCCTX *context, username_used = ""; if ((context->flags & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON) || - !cli_session_setup(&c, username_used, + !cli_session_setup(c, username_used, password, 1, password, 0, workgroup)) { - cli_shutdown(&c); + cli_shutdown(c); errno = EPERM; return NULL; } @@ -836,10 +836,10 @@ smbc_server(SMBCCTX *context, DEBUG(4,(" session setup ok\n")); - if (!cli_send_tconX(&c, share, "?????", + if (!cli_send_tconX(c, share, "?????", password, strlen(password)+1)) { - errno = smbc_errno(context, &c); - cli_shutdown(&c); + errno = smbc_errno(context, c); + cli_shutdown(c); return NULL; } @@ -858,7 +858,6 @@ smbc_server(SMBCCTX *context, ZERO_STRUCTP(srv); srv->cli = c; - srv->cli.allocated = False; srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share)); srv->no_pathinfo = False; srv->no_pathinfo2 = False; @@ -884,8 +883,10 @@ smbc_server(SMBCCTX *context, return srv; failed: - cli_shutdown(&c); - if (!srv) return NULL; + cli_shutdown(c); + if (!srv) { + return NULL; + } SAFE_FREE(srv); return NULL; @@ -960,19 +961,16 @@ smbc_attr_server(SMBCCTX *context, } ZERO_STRUCTP(ipc_srv); - ipc_srv->cli = *ipc_cli; - ipc_srv->cli.allocated = False; - - free(ipc_cli); + ipc_srv->cli = ipc_cli; if (pol) { - pipe_hnd = cli_rpc_pipe_open_noauth(&ipc_srv->cli, + pipe_hnd = cli_rpc_pipe_open_noauth(ipc_srv->cli, PI_LSARPC, &nt_status); if (!pipe_hnd) { DEBUG(1, ("cli_nt_session_open fail!\n")); errno = ENOTSUP; - cli_shutdown(&ipc_srv->cli); + cli_shutdown(ipc_srv->cli); free(ipc_srv); return NULL; } @@ -985,14 +983,14 @@ smbc_attr_server(SMBCCTX *context, nt_status = rpccli_lsa_open_policy( pipe_hnd, - ipc_srv->cli.mem_ctx, + ipc_srv->cli->mem_ctx, True, GENERIC_EXECUTE_ACCESS, pol); if (!NT_STATUS_IS_OK(nt_status)) { - errno = smbc_errno(context, &ipc_srv->cli); - cli_shutdown(&ipc_srv->cli); + errno = smbc_errno(context, ipc_srv->cli); + cli_shutdown(ipc_srv->cli); return NULL; } } @@ -1009,7 +1007,7 @@ smbc_attr_server(SMBCCTX *context, if (errno == 0) { errno = ENOMEM; } - cli_shutdown(&ipc_srv->cli); + cli_shutdown(ipc_srv->cli); free(ipc_srv); return NULL; } @@ -1098,7 +1096,7 @@ smbc_open_ctx(SMBCCTX *context, ZERO_STRUCTP(file); /*d_printf(">>>open: resolving %s\n", path);*/ - if (!cli_resolve_path( "", &srv->cli, path, &targetcli, targetpath)) + if (!cli_resolve_path( "", srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); SAFE_FREE(file); @@ -1172,7 +1170,7 @@ smbc_open_ctx(SMBCCTX *context, if (fd == -1) { int eno = 0; - eno = smbc_errno(context, &srv->cli); + eno = smbc_errno(context, srv->cli); file = context->opendir(context, fname); if (!file) errno = eno; return file; @@ -1275,7 +1273,7 @@ smbc_read_ctx(SMBCCTX *context, } /*d_printf(">>>read: resolving %s\n", path);*/ - if (!cli_resolve_path("", &file->srv->cli, path, + if (!cli_resolve_path("", file->srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); @@ -1358,7 +1356,7 @@ smbc_write_ctx(SMBCCTX *context, } /*d_printf(">>>write: resolving %s\n", path);*/ - if (!cli_resolve_path("", &file->srv->cli, path, + if (!cli_resolve_path("", file->srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); @@ -1430,7 +1428,7 @@ smbc_close_ctx(SMBCCTX *context, } /*d_printf(">>>close: resolving %s\n", path);*/ - if (!cli_resolve_path("", &file->srv->cli, path, + if (!cli_resolve_path("", file->srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); @@ -1500,7 +1498,7 @@ smbc_getatr(SMBCCTX * context, } DEBUG(4,("smbc_getatr: sending qpathinfo\n")); - if (!cli_resolve_path( "", &srv->cli, fixedpath, &targetcli, targetpath)) + if (!cli_resolve_path( "", srv->cli, fixedpath, &targetcli, targetpath)) { d_printf("Couldn't resolve %s\n", path); return False; @@ -1565,7 +1563,7 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, * attributes manipulated. */ if (srv->no_pathinfo || - ! cli_setpathinfo(&srv->cli, path, c_time, a_time, m_time, mode)) { + ! cli_setpathinfo(srv->cli, path, c_time, a_time, m_time, mode)) { /* * setpathinfo is not supported; go to plan B. @@ -1581,9 +1579,9 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, srv->no_pathinfo = True; /* Open the file */ - if ((fd = cli_open(&srv->cli, path, O_RDWR, DENY_NONE)) < 0) { + if ((fd = cli_open(srv->cli, path, O_RDWR, DENY_NONE)) < 0) { - errno = smbc_errno(context, &srv->cli); + errno = smbc_errno(context, srv->cli); return -1; } @@ -1592,7 +1590,7 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, * We'll need it in the set call */ if (c_time == 0) { - ret = cli_getattrE(&srv->cli, fd, + ret = cli_getattrE(srv->cli, fd, NULL, NULL, &c_time, NULL, NULL); } else { @@ -1619,9 +1617,9 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, if (c_time > m_time) c_time = m_time; /* Set the new attributes */ - ret = cli_setattrE(&srv->cli, fd, + ret = cli_setattrE(srv->cli, fd, c_time, a_time, m_time); - cli_close(&srv->cli, fd); + cli_close(srv->cli, fd); } /* @@ -1631,11 +1629,11 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, * seems to work on win98. */ if (ret && mode != (uint16) -1) { - ret = cli_setatr(&srv->cli, path, mode, 0); + ret = cli_setatr(srv->cli, path, mode, 0); } if (! ret) { - errno = smbc_errno(context, &srv->cli); + errno = smbc_errno(context, srv->cli); return False; } } @@ -1695,7 +1693,7 @@ smbc_unlink_ctx(SMBCCTX *context, } /*d_printf(">>>unlink: resolving %s\n", path);*/ - if (!cli_resolve_path( "", &srv->cli, path, &targetcli, targetpath)) + if (!cli_resolve_path( "", srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); return -1; @@ -1828,14 +1826,14 @@ smbc_rename_ctx(SMBCCTX *ocontext, } /*d_printf(">>>rename: resolving %s\n", path1);*/ - if (!cli_resolve_path( "", &srv->cli, path1, &targetcli1, targetpath1)) + if (!cli_resolve_path( "", srv->cli, path1, &targetcli1, targetpath1)) { d_printf("Could not resolve %s\n", path1); return -1; } /*d_printf(">>>rename: resolved path as %s\n", targetpath1);*/ /*d_printf(">>>rename: resolving %s\n", path2);*/ - if (!cli_resolve_path( "", &srv->cli, path2, &targetcli2, targetpath2)) + if (!cli_resolve_path( "", srv->cli, path2, &targetcli2, targetpath2)) { d_printf("Could not resolve %s\n", path2); return -1; @@ -1930,7 +1928,7 @@ smbc_lseek_ctx(SMBCCTX *context, } /*d_printf(">>>lseek: resolving %s\n", path);*/ - if (!cli_resolve_path("", &file->srv->cli, path, + if (!cli_resolve_path("", file->srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); @@ -2099,7 +2097,7 @@ smbc_stat_ctx(SMBCCTX *context, if (!smbc_getatr(context, srv, path, &mode, &size, &c_time, &a_time, &m_time, &ino)) { - errno = smbc_errno(context, &srv->cli); + errno = smbc_errno(context, srv->cli); return -1; } @@ -2175,7 +2173,7 @@ smbc_fstat_ctx(SMBCCTX *context, } /*d_printf(">>>fstat: resolving %s\n", path);*/ - if (!cli_resolve_path("", &file->srv->cli, path, + if (!cli_resolve_path("", file->srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); @@ -2676,7 +2674,7 @@ smbc_opendir_ctx(SMBCCTX *context, /* Now, list the stuff ... */ - if (!cli_NetServerEnum(&srv->cli, + if (!cli_NetServerEnum(srv->cli, workgroup, SV_TYPE_DOMAIN_ENUM, list_unique_wg_fn, @@ -2772,7 +2770,7 @@ smbc_opendir_ctx(SMBCCTX *context, dir->srv = srv; /* Now, list the servers ... */ - if (!cli_NetServerEnum(&srv->cli, server, + if (!cli_NetServerEnum(srv->cli, server, 0x0000FFFE, list_fn, (void *)dir)) { @@ -2808,15 +2806,15 @@ smbc_opendir_ctx(SMBCCTX *context, /* List the shares ... */ if (net_share_enum_rpc( - &srv->cli, + srv->cli, list_fn, (void *) dir) < 0 && cli_RNetShareEnum( - &srv->cli, + srv->cli, list_fn, (void *)dir) < 0) { - errno = cli_errno(&srv->cli); + errno = cli_errno(srv->cli); if (dir) { SAFE_FREE(dir->fname); SAFE_FREE(dir); @@ -2866,7 +2864,7 @@ smbc_opendir_ctx(SMBCCTX *context, p = path + strlen(path); pstrcat(path, "\\*"); - if (!cli_resolve_path("", &srv->cli, path, + if (!cli_resolve_path("", srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); @@ -3215,7 +3213,7 @@ smbc_mkdir_ctx(SMBCCTX *context, } /*d_printf(">>>mkdir: resolving %s\n", path);*/ - if (!cli_resolve_path( "", &srv->cli, path, &targetcli, targetpath)) + if (!cli_resolve_path( "", srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); return -1; @@ -3312,7 +3310,7 @@ smbc_rmdir_ctx(SMBCCTX *context, } /*d_printf(">>>rmdir: resolving %s\n", path);*/ - if (!cli_resolve_path( "", &srv->cli, path, &targetcli, targetpath)) + if (!cli_resolve_path( "", srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); return -1; @@ -3568,8 +3566,8 @@ smbc_chmod_ctx(SMBCCTX *context, if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM; if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN; - if (!cli_setatr(&srv->cli, path, mode, 0)) { - errno = smbc_errno(context, &srv->cli); + if (!cli_setatr(srv->cli, path, mode, 0)) { + errno = smbc_errno(context, srv->cli); return -1; } @@ -4098,7 +4096,7 @@ dos_attr_query(SMBCCTX *context, &mode, &size, &c_time, &a_time, &m_time, &inode)) { - errno = smbc_errno(context, &srv->cli); + errno = smbc_errno(context, srv->cli); DEBUG(5, ("dos_attr_query Failed to query old attributes\n")); return NULL; @@ -4206,7 +4204,7 @@ cacl_get(SMBCCTX *context, SMB_OFF_T size = 0; uint16 mode = 0; SMB_INO_T ino = 0; - struct cli_state *cli = &srv->cli; + struct cli_state *cli = srv->cli; /* Copy name so we can strip off exclusions (if any are specified) */ strncpy(name_sandbox, attr_name, sizeof(name_sandbox) - 1); @@ -4551,7 +4549,7 @@ cacl_get(SMBCCTX *context, if (!smbc_getatr(context, srv, filename, &mode, &size, &c_time, &a_time, &m_time, &ino)) { - errno = smbc_errno(context, &srv->cli); + errno = smbc_errno(context, srv->cli); return -1; } @@ -5108,8 +5106,8 @@ smbc_setxattr_ctx(SMBCCTX *context, } if (ipc_srv) { - ret = cacl_set(ctx, &srv->cli, - &ipc_srv->cli, &pol, path, + ret = cacl_set(ctx, srv->cli, + ipc_srv->cli, &pol, path, namevalue, (*namevalue == '*' ? SMBC_XATTR_MODE_SET @@ -5171,8 +5169,8 @@ smbc_setxattr_ctx(SMBCCTX *context, errno = ENOMEM; ret = -1; } else { - ret = cacl_set(ctx, &srv->cli, - &ipc_srv->cli, &pol, path, + ret = cacl_set(ctx, srv->cli, + ipc_srv->cli, &pol, path, namevalue, (*namevalue == '*' ? SMBC_XATTR_MODE_SET @@ -5202,8 +5200,8 @@ smbc_setxattr_ctx(SMBCCTX *context, errno = ENOMEM; ret = -1; } else { - ret = cacl_set(ctx, &srv->cli, - &ipc_srv->cli, &pol, path, + ret = cacl_set(ctx, srv->cli, + ipc_srv->cli, &pol, path, namevalue, SMBC_XATTR_MODE_CHOWN, 0); } talloc_destroy(ctx); @@ -5229,8 +5227,8 @@ smbc_setxattr_ctx(SMBCCTX *context, errno = ENOMEM; ret = -1; } else { - ret = cacl_set(ctx, &srv->cli, - &ipc_srv->cli, &pol, path, + ret = cacl_set(ctx, srv->cli, + ipc_srv->cli, &pol, path, namevalue, SMBC_XATTR_MODE_CHOWN, 0); } talloc_destroy(ctx); @@ -5388,12 +5386,12 @@ smbc_getxattr_ctx(SMBCCTX *context, /* Yup. */ ret = cacl_get(context, ctx, srv, - ipc_srv == NULL ? NULL : &ipc_srv->cli, + ipc_srv == NULL ? NULL : ipc_srv->cli, &pol, path, CONST_DISCARD(char *, name), CONST_DISCARD(char *, value), size); if (ret < 0 && errno == 0) { - errno = smbc_errno(context, &srv->cli); + errno = smbc_errno(context, srv->cli); } talloc_destroy(ctx); return ret; @@ -5484,8 +5482,8 @@ smbc_removexattr_ctx(SMBCCTX *context, StrCaseCmp(name, "system.nt_sec_desc.*+") == 0) { /* Yup. */ - ret = cacl_set(ctx, &srv->cli, - &ipc_srv->cli, &pol, path, + ret = cacl_set(ctx, srv->cli, + ipc_srv->cli, &pol, path, NULL, SMBC_XATTR_MODE_REMOVE_ALL, 0); talloc_destroy(ctx); return ret; @@ -5504,8 +5502,8 @@ smbc_removexattr_ctx(SMBCCTX *context, StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) { /* Yup. */ - ret = cacl_set(ctx, &srv->cli, - &ipc_srv->cli, &pol, path, + ret = cacl_set(ctx, srv->cli, + ipc_srv->cli, &pol, path, name + 19, SMBC_XATTR_MODE_REMOVE, 0); talloc_destroy(ctx); return ret; @@ -5755,10 +5753,10 @@ smbc_list_print_jobs_ctx(SMBCCTX *context, } - if (cli_print_queue(&srv->cli, + if (cli_print_queue(srv->cli, (void (*)(struct print_job_info *))fn) < 0) { - errno = smbc_errno(context, &srv->cli); + errno = smbc_errno(context, srv->cli); return -1; } @@ -5825,10 +5823,10 @@ smbc_unlink_print_job_ctx(SMBCCTX *context, } - if ((err = cli_printjob_del(&srv->cli, id)) != 0) { + if ((err = cli_printjob_del(srv->cli, id)) != 0) { if (err < 0) - errno = smbc_errno(context, &srv->cli); + errno = smbc_errno(context, srv->cli); else if (err == ERRnosuchprintjob) errno = EINVAL; return -1; @@ -5947,8 +5945,8 @@ smbc_free_context(SMBCCTX *context, s = context->internal->_servers; while (s) { DEBUG(1, ("Forced shutdown: %p (fd=%d)\n", - s, s->cli.fd)); - cli_shutdown(&s->cli); + s, s->cli->fd)); + cli_shutdown(s->cli); context->callbacks.remove_cached_srv_fn(context, s); next = s->next; @@ -6074,9 +6072,9 @@ smbc_option_get(SMBCCTX *context, * Log to standard error instead of standard output. */ #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) - return (void *) (intptr_t) context->internal->_debug_stderr; + return (void *) (intptr_t) context->internal->_debug_stderr; #else - return (void *) context->internal->_debug_stderr; + return (void *) context->internal->_debug_stderr; #endif } else if (strcmp(option_name, "auth_function") == 0) { /* diff --git a/source/libsmb/passchange.c b/source/libsmb/passchange.c index 673671d28db..0d3dcf4d755 100644 --- a/source/libsmb/passchange.c +++ b/source/libsmb/passchange.c @@ -29,7 +29,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam char *err_str, size_t err_str_len) { struct nmb_name calling, called; - struct cli_state cli; + struct cli_state *cli; struct rpc_pipe_client *pipe_hnd; struct in_addr ip; @@ -44,39 +44,45 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam return NT_STATUS_UNSUCCESSFUL; } - ZERO_STRUCT(cli); - - if (!cli_initialise(&cli) || !cli_connect(&cli, remote_machine, &ip)) { + cli = cli_initialise(); + if (!cli) { + return NT_STATUS_NO_MEMORY; + } + + if (!cli_connect(cli, remote_machine, &ip)) { slprintf(err_str, err_str_len-1, "unable to connect to SMB server on machine %s. Error was : %s.\n", - remote_machine, cli_errstr(&cli) ); - return NT_STATUS_UNSUCCESSFUL; + remote_machine, cli_errstr(cli) ); + result = cli_nt_error(cli); + cli_shutdown(cli); + return result; } make_nmb_name(&calling, global_myname() , 0x0); make_nmb_name(&called , remote_machine, 0x20); - if (!cli_session_request(&cli, &calling, &called)) { + if (!cli_session_request(cli, &calling, &called)) { slprintf(err_str, err_str_len-1, "machine %s rejected the session setup. Error was : %s.\n", - remote_machine, cli_errstr(&cli) ); - cli_shutdown(&cli); - return NT_STATUS_UNSUCCESSFUL; + remote_machine, cli_errstr(cli) ); + result = cli_nt_error(cli); + cli_shutdown(cli); + return result; } - cli.protocol = PROTOCOL_NT1; + cli->protocol = PROTOCOL_NT1; - if (!cli_negprot(&cli)) { + if (!cli_negprot(cli)) { slprintf(err_str, err_str_len-1, "machine %s rejected the negotiate protocol. Error was : %s.\n", - remote_machine, cli_errstr(&cli) ); - result = cli_nt_error(&cli); - cli_shutdown(&cli); + remote_machine, cli_errstr(cli) ); + result = cli_nt_error(cli); + cli_shutdown(cli); return result; } /* Given things like SMB signing, restrict anonymous and the like, try an authenticated connection first */ - if (!cli_session_setup(&cli, user_name, old_passwd, strlen(old_passwd)+1, old_passwd, strlen(old_passwd)+1, "")) { + if (!cli_session_setup(cli, user_name, old_passwd, strlen(old_passwd)+1, old_passwd, strlen(old_passwd)+1, "")) { - result = cli_nt_error(&cli); + result = cli_nt_error(cli); if (!NT_STATUS_IS_OK(result)) { @@ -89,8 +95,8 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam NT_STATUS_PASSWORD_MUST_CHANGE)) { slprintf(err_str, err_str_len-1, "Could not " "connect to machine %s: %s\n", - remote_machine, cli_errstr(&cli)); - cli_shutdown(&cli); + remote_machine, cli_errstr(cli)); + cli_shutdown(cli); return result; } @@ -103,31 +109,31 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam * Thanks to <Nicholas.S.Jenkins@cdc.com> for this fix. */ - if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) { + if (!cli_session_setup(cli, "", "", 0, "", 0, "")) { slprintf(err_str, err_str_len-1, "machine %s rejected the session setup. Error was : %s.\n", - remote_machine, cli_errstr(&cli) ); - result = cli_nt_error(&cli); - cli_shutdown(&cli); + remote_machine, cli_errstr(cli) ); + result = cli_nt_error(cli); + cli_shutdown(cli); return result; } - cli_init_creds(&cli, "", "", NULL); + cli_init_creds(cli, "", "", NULL); } else { - cli_init_creds(&cli, user_name, "", old_passwd); + cli_init_creds(cli, user_name, "", old_passwd); } - if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { + if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) { slprintf(err_str, err_str_len-1, "machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", - remote_machine, cli_errstr(&cli) ); - result = cli_nt_error(&cli); - cli_shutdown(&cli); + remote_machine, cli_errstr(cli) ); + result = cli_nt_error(cli); + cli_shutdown(cli); return result; } /* Try not to give the password away too easily */ if (!pass_must_change) { - pipe_hnd = cli_rpc_pipe_open_ntlmssp(&cli, + pipe_hnd = cli_rpc_pipe_open_ntlmssp(cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY, "", /* what domain... ? */ @@ -143,17 +149,17 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam * will just fail. So we do it anonymously, there's no other * way. */ - pipe_hnd = cli_rpc_pipe_open_noauth(&cli, PI_SAMR, &result); + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result); } if (!pipe_hnd) { if (lp_client_lanman_auth()) { /* Use the old RAP method. */ - if (!cli_oem_change_password(&cli, user_name, new_passwd, old_passwd)) { + if (!cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) { slprintf(err_str, err_str_len-1, "machine %s rejected the password change: Error was : %s.\n", - remote_machine, cli_errstr(&cli) ); - result = cli_nt_error(&cli); - cli_shutdown(&cli); + remote_machine, cli_errstr(cli) ); + result = cli_nt_error(cli); + cli_shutdown(cli); return result; } } else { @@ -161,16 +167,16 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam "SAMR connection to machine %s failed. Error was %s, " "but LANMAN password changed are disabled\n", nt_errstr(result), remote_machine); - result = cli_nt_error(&cli); - cli_shutdown(&cli); + result = cli_nt_error(cli); + cli_shutdown(cli); return result; } } - if (NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd, cli.mem_ctx, user_name, + if (NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd, cli->mem_ctx, user_name, new_passwd, old_passwd))) { /* Great - it all worked! */ - cli_shutdown(&cli); + cli_shutdown(cli); return NT_STATUS_OK; } else if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) @@ -179,7 +185,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam slprintf(err_str, err_str_len-1, "machine %s rejected the password change: Error was : %s.\n", remote_machine, get_friendly_nt_error_msg(result)); - cli_shutdown(&cli); + cli_shutdown(cli); return result; } @@ -187,21 +193,21 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam cli_rpc_pipe_close(pipe_hnd); /* Try anonymous NTLMSSP... */ - cli_init_creds(&cli, "", "", NULL); + cli_init_creds(cli, "", "", NULL); result = NT_STATUS_UNSUCCESSFUL; /* OK, this is ugly, but... try an anonymous pipe. */ - pipe_hnd = cli_rpc_pipe_open_noauth(&cli, PI_SAMR, &result); + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result); if ( pipe_hnd && (NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd, - cli.mem_ctx, + cli->mem_ctx, user_name, new_passwd, old_passwd)))) { /* Great - it all worked! */ - cli_shutdown(&cli); + cli_shutdown(cli); return NT_STATUS_OK; } else { if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) @@ -211,7 +217,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam slprintf(err_str, err_str_len-1, "machine %s rejected the (anonymous) password change: Error was : %s.\n", remote_machine, get_friendly_nt_error_msg(result)); - cli_shutdown(&cli); + cli_shutdown(cli); return result; } @@ -220,24 +226,24 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam if (lp_client_lanman_auth()) { /* Use the old RAP method. */ - if (cli_oem_change_password(&cli, user_name, new_passwd, old_passwd)) { + if (cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) { /* SAMR failed, but the old LanMan protocol worked! */ - cli_shutdown(&cli); + cli_shutdown(cli); return NT_STATUS_OK; } slprintf(err_str, err_str_len-1, "machine %s rejected the password change: Error was : %s.\n", - remote_machine, cli_errstr(&cli) ); - result = cli_nt_error(&cli); - cli_shutdown(&cli); + remote_machine, cli_errstr(cli) ); + result = cli_nt_error(cli); + cli_shutdown(cli); return result; } else { slprintf(err_str, err_str_len-1, "SAMR connection to machine %s failed. Error was %s, " "but LANMAN password changed are disabled\n", nt_errstr(result), remote_machine); - cli_shutdown(&cli); + cli_shutdown(cli); return NT_STATUS_UNSUCCESSFUL; } } diff --git a/source/libsmb/trusts_util.c b/source/libsmb/trusts_util.c index 55108bf72f2..e4061883eb1 100644 --- a/source/libsmb/trusts_util.c +++ b/source/libsmb/trusts_util.c @@ -99,7 +99,7 @@ NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *m if (NT_STATUS_IS_OK(nt_status)) { DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n", - timestring(False))); + current_timestring(False))); /* * Return the result of trying to write the new password * back into the trust account file. diff --git a/source/locking/brlock.c b/source/locking/brlock.c index 574552e9e21..9c8a7a17ee6 100644 --- a/source/locking/brlock.c +++ b/source/locking/brlock.c @@ -32,29 +32,6 @@ #define ZERO_ZERO 0 -/* This contains elements that differentiate locks. The smbpid is a - client supplied pid, and is essentially the locking context for - this client */ - -struct lock_context { - uint16 smbpid; - uint16 tid; - struct process_id pid; -}; - -/* The data in brlock records is an unsorted linear array of these - records. It is unnecessary to store the count as tdb provides the - size of the record */ - -struct lock_struct { - struct lock_context context; - br_off start; - br_off size; - int fnum; - enum brl_type lock_type; - enum brl_flavour lock_flav; -}; - /* The open brlock.tdb database. */ static TDB_CONTEXT *tdb; @@ -83,7 +60,7 @@ static void print_lock_struct(unsigned int i, struct lock_struct *pls) See if two locking contexts are equal. ****************************************************************************/ -static BOOL brl_same_context(const struct lock_context *ctx1, +BOOL brl_same_context(const struct lock_context *ctx1, const struct lock_context *ctx2) { return (procid_equal(&ctx1->pid, &ctx2->pid) && @@ -343,13 +320,19 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, /* We can get the Windows lock, now see if it needs to be mapped into a lower level POSIX one, and if so can - we get it ? We tell the lower lock layer about the - lock type so it can cope with the difference between - Windows "stacking" locks and POSIX "flat" ones. */ + we get it ? */ if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) { - if (!set_posix_lock(fsp, plock->start, plock->size, plock->lock_type, WINDOWS_LOCK)) { - if (errno == EACCES || errno == EAGAIN) { + int errno_ret; + if (!set_posix_lock_windows_flavour(fsp, + plock->start, + plock->size, + plock->lock_type, + &plock->context, + locks, + br_lck->num_locks, + &errno_ret)) { + if (errno_ret == EACCES || errno_ret == EAGAIN) { return NT_STATUS_FILE_LOCK_CONFLICT; } else { return map_nt_error_from_unix(errno); @@ -375,9 +358,9 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, Cope with POSIX range splits and merges. ****************************************************************************/ -static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr, - const struct lock_struct *ex, - const struct lock_struct *plock, +static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr, /* Output array. */ + const struct lock_struct *ex, /* existing lock. */ + const struct lock_struct *plock, /* proposed lock. */ BOOL *lock_was_added) { BOOL lock_types_differ = (ex->lock_type != plock->lock_type); @@ -398,26 +381,26 @@ static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr, +---------+ | ex | +---------+ - +-------+ - | plock | - +-------+ + +-------+ + | plock | + +-------+ OR.... +---------+ | ex | +---------+ **********************************************/ - if ( (ex->start >= (plock->start + plock->size)) || - (plock->start >= (ex->start + ex->size))) { + if ( (ex->start > (plock->start + plock->size)) || + (plock->start > (ex->start + ex->size))) { /* No overlap with this lock - copy existing. */ memcpy(&lck_arr[0], ex, sizeof(struct lock_struct)); return 1; } /********************************************* - +---------+ - | ex | - +---------+ + +---------------------------+ + | ex | + +---------------------------+ +---------------------------+ | plock | -> replace with plock. +---------------------------+ @@ -431,24 +414,32 @@ OR.... } /********************************************* - +---------------+ - | ex | - +---------------+ + +-----------------------+ + | ex | + +-----------------------+ +---------------+ | plock | +---------------+ +OR.... + +-------+ + | ex | + +-------+ + +---------------+ + | plock | + +---------------+ + BECOMES.... +---------------+-------+ | plock | ex | - different lock types. +---------------+-------+ -OR.... +OR.... (merge) +-----------------------+ | ex | - same lock type. +-----------------------+ **********************************************/ if ( (ex->start >= plock->start) && - (ex->start < plock->start + plock->size) && + (ex->start <= plock->start + plock->size) && (ex->start + ex->size > plock->start + plock->size) ) { *lock_was_added = True; @@ -475,9 +466,16 @@ OR.... } /********************************************* - +---------------+ - | ex | - +---------------+ + +-----------------------+ + | ex | + +-----------------------+ + +---------------+ + | plock | + +---------------+ +OR.... + +-------+ + | ex | + +-------+ +---------------+ | plock | +---------------+ @@ -486,7 +484,7 @@ BECOMES.... | ex | plock | - different lock types +-------+---------------+ -OR +OR.... (merge) +-----------------------+ | ex | - same lock type. +-----------------------+ @@ -494,7 +492,7 @@ OR **********************************************/ if ( (ex->start < plock->start) && - (ex->start + ex->size > plock->start) && + (ex->start + ex->size >= plock->start) && (ex->start + ex->size <= plock->start + plock->size) ) { *lock_was_added = True; @@ -631,20 +629,28 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, } } + if (!lock_was_added) { + memcpy(&tp[count], plock, sizeof(struct lock_struct)); + count++; + } + /* We can get the POSIX lock, now see if it needs to be mapped into a lower level POSIX one, and if so can - we get it ? We well the lower lock layer about the - lock type so it can cope with the difference between - Windows "stacking" locks and POSIX "flat" ones. */ + we get it ? */ -#if 0 - /* FIXME - this call doesn't work correctly yet for POSIX locks... */ + if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(br_lck->fsp->conn))) { + int errno_ret; - if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) { - files_struct *fsp = br_lck->fsp; + /* The lower layer just needs to attempt to + get the system POSIX lock. We've weeded out + any conflicts above. */ - if (!set_posix_lock(fsp, plock->start, plock->size, plock->lock_type, POSIX_LOCK)) { - if (errno == EACCES || errno == EAGAIN) { + if (!set_posix_lock_posix_flavour(br_lck->fsp, + plock->start, + plock->size, + plock->lock_type, + &errno_ret)) { + if (errno_ret == EACCES || errno_ret == EAGAIN) { SAFE_FREE(tp); return NT_STATUS_FILE_LOCK_CONFLICT; } else { @@ -653,12 +659,6 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, } } } -#endif - - if (!lock_was_added) { - memcpy(&tp[count], plock, sizeof(struct lock_struct)); - count++; - } /* Realloc so we don't leak entries per lock call. */ tp = (struct lock_struct *)SMB_REALLOC(tp, count * sizeof(*locks)); @@ -676,7 +676,7 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, ****************************************************************************/ NTSTATUS brl_lock(struct byte_range_lock *br_lck, - uint16 smbpid, + uint32 smbpid, struct process_id pid, br_off start, br_off size, @@ -740,8 +740,12 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock unsigned int i, j; struct lock_struct *lock = NULL; struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + enum brl_type deleted_lock_type = READ_LOCK; /* shut the compiler up.... */ #if ZERO_ZERO + /* Delete write locks by preference... The lock list + is sorted in the zero zero case. */ + for (i = 0; i < br_lck->num_locks; i++) { lock = &locks[i]; @@ -753,16 +757,15 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock lock->size == plock->size) { /* found it - delete it */ - if (i < br_lck->num_locks - 1) { - memmove(&locks[i], &locks[i+1], - sizeof(*locks)*((br_lck->num_locks-1) - i)); - } - - br_lck->num_locks -= 1; - br_lck->modified = True; - return True; + deleted_lock_type = lock->lock_type; + break; } } + + if (i != br_lck->num_locks) { + /* We found it - don't search again. */ + goto unlock_continue; + } #endif for (i = 0; i < br_lck->num_locks; i++) { @@ -774,6 +777,7 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock lock->lock_flav == WINDOWS_LOCK && lock->start == plock->start && lock->size == plock->size ) { + deleted_lock_type = lock->lock_type; break; } } @@ -783,9 +787,28 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock return False; } - /* Unlock any POSIX regions. */ +#if ZERO_ZERO + unlock_continue: +#endif + + /* Actually delete the lock. */ + if (i < br_lck->num_locks - 1) { + memmove(&locks[i], &locks[i+1], + sizeof(*locks)*((br_lck->num_locks-1) - i)); + } + + br_lck->num_locks -= 1; + br_lck->modified = True; + + /* Unlock the underlying POSIX regions. */ if(lp_posix_locking(br_lck->fsp->conn->cnum)) { - release_posix_lock(br_lck->fsp, plock->start, plock->size); + release_posix_lock_windows_flavour(br_lck->fsp, + plock->start, + plock->size, + deleted_lock_type, + &plock->context, + locks, + br_lck->num_locks); } /* Send unlock messages to any pending waiters that overlap. */ @@ -810,14 +833,6 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock } } - /* Actually delete the lock. */ - if (i < br_lck->num_locks - 1) { - memmove(&locks[i], &locks[i+1], - sizeof(*locks)*((br_lck->num_locks-1) - i)); - } - - br_lck->num_locks -= 1; - br_lck->modified = True; return True; } @@ -895,13 +910,18 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s SMB_ASSERT(tmp_lock[0].lock_type == locks[i].lock_type); SMB_ASSERT(tmp_lock[1].lock_type == UNLOCK_LOCK); memcpy(&tp[count], &tmp_lock[0], sizeof(struct lock_struct)); + if (tmp_lock[0].size != locks[i].size) { + overlap_found = True; + } } else { SMB_ASSERT(tmp_lock[0].lock_type == UNLOCK_LOCK); SMB_ASSERT(tmp_lock[1].lock_type == locks[i].lock_type); memcpy(&tp[count], &tmp_lock[1], sizeof(struct lock_struct)); + if (tmp_lock[1].start != locks[i].start) { + overlap_found = True; + } } count++; - overlap_found = True; continue; } else { /* tmp_count == 3 - (we split a lock range in two). */ @@ -933,14 +953,15 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s return True; } -#if 0 - /* FIXME - this call doesn't work correctly yet for POSIX locks... */ - /* Unlock any POSIX regions. */ if(lp_posix_locking(br_lck->fsp->conn->cnum)) { - release_posix_lock(br_lck->fsp, plock->start, plock->size); + release_posix_lock_posix_flavour(br_lck->fsp, + plock->start, + plock->size, + &plock->context, + tp, + count); } -#endif /* Realloc so we don't leak entries per unlock call. */ if (count) { @@ -991,7 +1012,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s ****************************************************************************/ BOOL brl_unlock(struct byte_range_lock *br_lck, - uint16 smbpid, + uint32 smbpid, struct process_id pid, br_off start, br_off size, @@ -1021,7 +1042,7 @@ BOOL brl_unlock(struct byte_range_lock *br_lck, ****************************************************************************/ BOOL brl_locktest(struct byte_range_lock *br_lck, - uint16 smbpid, + uint32 smbpid, struct process_id pid, br_off start, br_off size, @@ -1079,7 +1100,7 @@ BOOL brl_locktest(struct byte_range_lock *br_lck, ****************************************************************************/ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, - uint16 *psmbpid, + uint32 *psmbpid, struct process_id pid, br_off *pstart, br_off *psize, @@ -1148,7 +1169,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, ****************************************************************************/ BOOL brl_remove_pending_lock(struct byte_range_lock *br_lck, - uint16 smbpid, + uint32 smbpid, struct process_id pid, br_off start, br_off size, @@ -1192,18 +1213,75 @@ BOOL brl_remove_pending_lock(struct byte_range_lock *br_lck, return True; } - /**************************************************************************** Remove any locks associated with a open file. + We return True if this process owns any other Windows locks on this + fd and so we should not immediately close the fd. ****************************************************************************/ -void brl_close_fnum(struct byte_range_lock *br_lck, struct process_id pid) +void brl_close_fnum(struct byte_range_lock *br_lck) { files_struct *fsp = br_lck->fsp; uint16 tid = fsp->conn->cnum; int fnum = fsp->fnum; unsigned int i, j, dcount=0; struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; + struct process_id pid = procid_self(); + BOOL unlock_individually = False; + + if(lp_posix_locking(fsp->conn->cnum) && !lp_posix_cifsu_locktype()) { + + /* Check if there are any Windows locks associated with this dev/ino + pair that are not this fnum. If so we need to call unlock on each + one in order to release the system POSIX locks correctly. */ + + for (i=0; i < br_lck->num_locks; i++) { + struct lock_struct *lock = &locks[i]; + + if (!procid_equal(&lock->context.pid, &pid)) { + continue; + } + + if (lock->lock_type != READ_LOCK && lock->lock_type != WRITE_LOCK) { + continue; /* Ignore pending. */ + } + + if (lock->context.tid != tid || lock->fnum != fnum) { + unlock_individually = True; + break; + } + } + + if (unlock_individually) { + struct lock_struct *locks_copy; + + /* Copy the current lock array. */ + locks_copy = TALLOC_MEMDUP(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct)); + if (!locks_copy) { + DEBUG(0,("brl_close_fnum: talloc fail.\n")); + } + + for (i=0; i < br_lck->num_locks; i++) { + struct lock_struct *lock = &locks_copy[i]; + + if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid) && + (lock->fnum == fnum)) { + brl_unlock(br_lck, + lock->context.smbpid, + pid, + lock->start, + lock->size, + lock->lock_flav); + } + } + return; + } + } + + /* We can bulk delete - any POSIX locks will be removed when the fd closes. */ + + /* Zero any lock reference count on this dev/ino pair. */ + zero_windows_lock_ref_count(fsp); /* Remove any existing locks for this fnum (or any fnum if they're POSIX). */ @@ -1346,7 +1424,7 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st } if (orig_num_locks != num_locks) { - dbuf.dptr = (void *)locks; + dbuf.dptr = (char *)locks; dbuf.dsize = num_locks * sizeof(*locks); if (dbuf.dsize) { @@ -1388,8 +1466,10 @@ int brl_forall(BRLOCK_FN(fn)) Unlock the record. ********************************************************************/ -int byte_range_lock_destructor(struct byte_range_lock *br_lck) +static int byte_range_lock_destructor(void *p) { + struct byte_range_lock *br_lck = + talloc_get_type_abort(p, struct byte_range_lock); TDB_DATA key; key.dptr = (char *)&br_lck->key; @@ -1406,7 +1486,7 @@ int byte_range_lock_destructor(struct byte_range_lock *br_lck) } } else { TDB_DATA data; - data.dptr = br_lck->lock_data; + data.dptr = (char *)br_lck->lock_data; data.dsize = br_lck->num_locks * sizeof(struct lock_struct); if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) { @@ -1418,20 +1498,21 @@ int byte_range_lock_destructor(struct byte_range_lock *br_lck) tdb_chainunlock(tdb, key); SAFE_FREE(br_lck->lock_data); - SAFE_FREE(br_lck); return 0; } /******************************************************************* Fetch a set of byte range lock data from the database. Leave the record locked. + TALLOC_FREE(brl) will release the lock in the destructor. ********************************************************************/ -struct byte_range_lock *brl_get_locks(files_struct *fsp) +struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, + files_struct *fsp) { TDB_DATA key; TDB_DATA data; - struct byte_range_lock *br_lck = SMB_MALLOC_P(struct byte_range_lock); + struct byte_range_lock *br_lck = TALLOC_P(mem_ctx, struct byte_range_lock); if (br_lck == NULL) { return NULL; @@ -1449,10 +1530,12 @@ struct byte_range_lock *brl_get_locks(files_struct *fsp) if (tdb_chainlock(tdb, key) != 0) { DEBUG(3, ("Could not lock byte range lock entry\n")); - SAFE_FREE(br_lck); + TALLOC_FREE(br_lck); return NULL; } + talloc_set_destructor(br_lck, byte_range_lock_destructor); + data = tdb_fetch(tdb, key); br_lck->lock_data = (void *)data.dptr; br_lck->num_locks = data.dsize / sizeof(struct lock_struct); @@ -1463,13 +1546,22 @@ struct byte_range_lock *brl_get_locks(files_struct *fsp) /* Go through and ensure all entries exist - remove any that don't. */ /* Makes the lockdb self cleaning at low cost. */ - if (!validate_lock_entries(&br_lck->num_locks, (struct lock_struct **)&br_lck->lock_data)) { - tdb_chainunlock(tdb, key); + struct lock_struct *locks = + (struct lock_struct *)br_lck->lock_data; + + if (!validate_lock_entries(&br_lck->num_locks, &locks)) { SAFE_FREE(br_lck->lock_data); - SAFE_FREE(br_lck); + TALLOC_FREE(br_lck); return NULL; } + /* + * validate_lock_entries might have changed locks. We can't + * use a direct pointer here because otherwise gcc warnes + * about strict aliasing rules being violated. + */ + br_lck->lock_data = locks; + /* Mark the lockdb as "clean" as seen from this open file. */ fsp->lockdb_clean = True; } diff --git a/source/locking/locking.c b/source/locking/locking.c index 9d3ca956014..ac50c9b648f 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -37,7 +37,6 @@ */ #include "includes.h" -uint16 global_smbpid; #undef DBGC_CLASS #define DBGC_CLASS DBGC_LOCKING @@ -74,6 +73,7 @@ const char *lock_flav_name(enum brl_flavour lock_flav) ****************************************************************************/ BOOL is_locked(files_struct *fsp, + uint32 smbpid, SMB_BIG_UINT count, SMB_BIG_UINT offset, enum brl_type lock_type) @@ -100,32 +100,32 @@ BOOL is_locked(files_struct *fsp, DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name )); ret = False; } else { - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); if (!br_lck) { return False; } ret = !brl_locktest(br_lck, - global_smbpid, + smbpid, procid_self(), offset, count, lock_type, lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } } else { - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); if (!br_lck) { return False; } ret = !brl_locktest(br_lck, - global_smbpid, + smbpid, procid_self(), offset, count, lock_type, lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } DEBUG(10,("is_locked: flavour = %s brl start=%.0f len=%.0f %s for fnum %d file %s\n", @@ -141,7 +141,7 @@ BOOL is_locked(files_struct *fsp, ****************************************************************************/ NTSTATUS query_lock(files_struct *fsp, - uint16 *psmbpid, + uint32 *psmbpid, SMB_BIG_UINT *pcount, SMB_BIG_UINT *poffset, enum brl_type *plock_type, @@ -150,15 +150,15 @@ NTSTATUS query_lock(files_struct *fsp, struct byte_range_lock *br_lck = NULL; NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED; - if (!OPEN_FSP(fsp) || !fsp->can_lock) { - return NT_STATUS_INVALID_HANDLE; + if (!fsp->can_lock) { + return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; } if (!lp_locking(SNUM(fsp->conn))) { return NT_STATUS_OK; } - br_lck = brl_get_locks(fsp); + br_lck = brl_get_locks(NULL, fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } @@ -171,7 +171,7 @@ NTSTATUS query_lock(files_struct *fsp, plock_type, lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); return status; } @@ -180,7 +180,7 @@ NTSTATUS query_lock(files_struct *fsp, ****************************************************************************/ NTSTATUS do_lock(files_struct *fsp, - uint16 lock_pid, + uint32 lock_pid, SMB_BIG_UINT count, SMB_BIG_UINT offset, enum brl_type lock_type, @@ -190,8 +190,8 @@ NTSTATUS do_lock(files_struct *fsp, struct byte_range_lock *br_lck = NULL; NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED; - if (!OPEN_FSP(fsp) || !fsp->can_lock) { - return NT_STATUS_INVALID_HANDLE; + if (!fsp->can_lock) { + return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; } if (!lp_locking(SNUM(fsp->conn))) { @@ -204,7 +204,7 @@ NTSTATUS do_lock(files_struct *fsp, lock_flav_name(lock_flav), lock_type_name(lock_type), (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); - br_lck = brl_get_locks(fsp); + br_lck = brl_get_locks(NULL, fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } @@ -218,7 +218,7 @@ NTSTATUS do_lock(files_struct *fsp, lock_flav, my_lock_ctx); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); return status; } @@ -230,7 +230,7 @@ NTSTATUS do_lock(files_struct *fsp, ****************************************************************************/ NTSTATUS do_lock_spin(files_struct *fsp, - uint16 lock_pid, + uint32 lock_pid, SMB_BIG_UINT count, SMB_BIG_UINT offset, enum brl_type lock_type, @@ -286,7 +286,7 @@ NTSTATUS do_lock_spin(files_struct *fsp, ****************************************************************************/ NTSTATUS do_unlock(files_struct *fsp, - uint16 lock_pid, + uint32 lock_pid, SMB_BIG_UINT count, SMB_BIG_UINT offset, enum brl_flavour lock_flav) @@ -294,18 +294,18 @@ NTSTATUS do_unlock(files_struct *fsp, BOOL ok = False; struct byte_range_lock *br_lck = NULL; - if (!lp_locking(SNUM(fsp->conn))) { - return NT_STATUS_OK; + if (!fsp->can_lock) { + return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; } - if (!OPEN_FSP(fsp) || !fsp->can_lock) { - return NT_STATUS_INVALID_HANDLE; + if (!lp_locking(SNUM(fsp->conn))) { + return NT_STATUS_OK; } DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n", (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); - br_lck = brl_get_locks(fsp); + br_lck = brl_get_locks(NULL, fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } @@ -317,7 +317,7 @@ NTSTATUS do_unlock(files_struct *fsp, count, lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); @@ -334,25 +334,15 @@ NTSTATUS do_unlock(files_struct *fsp, void locking_close_file(files_struct *fsp) { struct byte_range_lock *br_lck; - struct process_id pid = procid_self(); - if (!lp_locking(SNUM(fsp->conn))) + if (!lp_locking(SNUM(fsp->conn))) { return; - - /* - * Just release all the brl locks, no need to release individually. - */ - - br_lck = brl_get_locks(fsp); - if (br_lck) { - brl_close_fnum(br_lck, pid); - byte_range_lock_destructor(br_lck); } - if(lp_posix_locking(SNUM(fsp->conn))) { - /* Release all the POSIX locks.*/ - posix_locking_close_file(fsp); - + br_lck = brl_get_locks(NULL,fsp); + if (br_lck) { + brl_close_fnum(br_lck); + TALLOC_FREE(br_lck); } } @@ -516,9 +506,10 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) smb_panic("PANIC: parse_share_modes: buffer too short.\n"); } - lck->share_modes = talloc_memdup(lck, dbuf.dptr+sizeof(*data), - lck->num_share_modes * - sizeof(struct share_mode_entry)); + lck->share_modes = (struct share_mode_entry *) + talloc_memdup(lck, dbuf.dptr+sizeof(*data), + lck->num_share_modes * + sizeof(struct share_mode_entry)); if (lck->share_modes == NULL) { smb_panic("talloc failed\n"); @@ -635,7 +626,7 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) delete_token_size + sp_len + 1 + strlen(lck->filename) + 1; - result.dptr = talloc_size(lck, result.dsize); + result.dptr = TALLOC_ARRAY(lck, char, result.dsize); if (result.dptr == NULL) { smb_panic("talloc failed\n"); @@ -838,7 +829,7 @@ BOOL rename_share_filename(struct share_mode_lock *lck, msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + fn_len + 1; /* Set up the name changed message. */ - frm = TALLOC(lck, msg_len); + frm = TALLOC_ARRAY(lck, char, msg_len); if (!frm) { return False; } @@ -862,9 +853,9 @@ BOOL rename_share_filename(struct share_mode_lock *lck, continue; } - DEBUG(10,("rename_share_filename: sending rename message to pid %u " + DEBUG(10,("rename_share_filename: sending rename message to pid %s " "dev %x, inode %.0f sharepath %s newname %s\n", - (unsigned int)procid_to_pid(&se->pid), + procid_str_static(&se->pid), (unsigned int)lck->dev, (double)lck->ino, lck->servicepath, lck->filename )); @@ -1305,5 +1296,5 @@ int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *, { if (tdb == NULL) return 0; - return tdb_traverse(tdb, traverse_fn, fn); + return tdb_traverse(tdb, traverse_fn, (void *)fn); } diff --git a/source/locking/posix.c b/source/locking/posix.c index 4a5f59b622d..59b62170e82 100644 --- a/source/locking/posix.c +++ b/source/locking/posix.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. Locking functions - Copyright (C) Jeremy Allison 1992-2000 + Copyright (C) Jeremy Allison 1992-2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,481 +28,17 @@ #define DBGC_CLASS DBGC_LOCKING /* - * The POSIX locking database handle. - */ - -static TDB_CONTEXT *posix_lock_tdb; - -/* * The pending close database handle. */ static TDB_CONTEXT *posix_pending_close_tdb; -/* - * The data in POSIX lock records is an unsorted linear array of these - * records. It is unnecessary to store the count as tdb provides the - * size of the record. - */ - -struct posix_lock { - int fd; - SMB_OFF_T start; - SMB_OFF_T size; - int lock_type; -}; - -/* - * The data in POSIX pending close records is an unsorted linear array of int - * records. It is unnecessary to store the count as tdb provides the - * size of the record. - */ - -/* The key used in both the POSIX databases. */ - -struct posix_lock_key { - SMB_DEV_T device; - SMB_INO_T inode; -}; - -/******************************************************************* - Form a static locking key for a dev/inode pair. -******************************************************************/ - -static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) -{ - static struct posix_lock_key key; - TDB_DATA kbuf; - - memset(&key, '\0', sizeof(key)); - key.device = dev; - key.inode = inode; - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); - return kbuf; -} - -/******************************************************************* - Convenience function to get a key from an fsp. -******************************************************************/ - -static TDB_DATA locking_key_fsp(files_struct *fsp) -{ - return locking_key(fsp->dev, fsp->inode); -} - -/**************************************************************************** - Add an fd to the pending close tdb. -****************************************************************************/ - -static BOOL add_fd_to_close_entry(files_struct *fsp) -{ - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - - dbuf.dptr = NULL; - dbuf.dsize = 0; - - dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - - dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); - if (!dbuf.dptr) { - DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n")); - return False; - } - - memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int)); - dbuf.dsize += sizeof(int); - - if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - DEBUG(0,("add_fd_to_close_entry: tdb_store fail !\n")); - } - - SAFE_FREE(dbuf.dptr); - return True; -} - -/**************************************************************************** - Remove all fd entries for a specific dev/inode pair from the tdb. -****************************************************************************/ - -static void delete_close_entries(files_struct *fsp) -{ - TDB_DATA kbuf = locking_key_fsp(fsp); - - if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) - DEBUG(0,("delete_close_entries: tdb_delete fail !\n")); -} - -/**************************************************************************** - Get the array of POSIX pending close records for an open fsp. Caller must - free. Returns number of entries. -****************************************************************************/ - -static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries) -{ - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - size_t count = 0; - - *entries = NULL; - dbuf.dptr = NULL; - - dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); - - if (!dbuf.dptr) { - return 0; - } - - *entries = (int *)dbuf.dptr; - count = (size_t)(dbuf.dsize / sizeof(int)); - - return count; -} - -/**************************************************************************** - Get the array of POSIX locks for an fsp. Caller must free. Returns - number of entries. -****************************************************************************/ - -static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entries) -{ - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - size_t count = 0; - - *entries = NULL; - - dbuf.dptr = NULL; - - dbuf = tdb_fetch(posix_lock_tdb, kbuf); - - if (!dbuf.dptr) { - return 0; - } - - *entries = (struct posix_lock *)dbuf.dptr; - count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); - - return count; -} - -/**************************************************************************** - Deal with pending closes needed by POSIX locking support. - Note that posix_locking_close_file() is expected to have been called - to delete all locks on this fsp before this function is called. -****************************************************************************/ - -int fd_close_posix(struct connection_struct *conn, files_struct *fsp) -{ - int saved_errno = 0; - int ret; - size_t count, i; - struct posix_lock *entries = NULL; - int *fd_array = NULL; - BOOL locks_on_other_fds = False; - - if (!lp_posix_locking(SNUM(conn))) { - /* - * No POSIX to worry about, just close. - */ - ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); - fsp->fh->fd = -1; - return ret; - } - - /* - * Get the number of outstanding POSIX locks on this dev/inode pair. - */ - - count = get_posix_lock_entries(fsp, &entries); - - /* - * Check if there are any outstanding locks belonging to - * other fd's. This should never be the case if posix_locking_close_file() - * has been called first, but it never hurts to be *sure*. - */ - - for (i = 0; i < count; i++) { - if (entries[i].fd != fsp->fh->fd) { - locks_on_other_fds = True; - break; - } - } - - if (locks_on_other_fds) { - - /* - * There are outstanding locks on this dev/inode pair on other fds. - * Add our fd to the pending close tdb and set fsp->fh->fd to -1. - */ - - if (!add_fd_to_close_entry(fsp)) { - SAFE_FREE(entries); - return -1; - } - - SAFE_FREE(entries); - fsp->fh->fd = -1; - return 0; - } - - SAFE_FREE(entries); - - /* - * No outstanding POSIX locks. Get the pending close fd's - * from the tdb and close them all. - */ - - count = get_posix_pending_close_entries(fsp, &fd_array); - - if (count) { - DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); - - for(i = 0; i < count; i++) { - if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) { - saved_errno = errno; - } - } - - /* - * Delete all fd's stored in the tdb - * for this dev/inode pair. - */ - - delete_close_entries(fsp); - } - - SAFE_FREE(fd_array); - - /* - * Finally close the fd associated with this fsp. - */ - - ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); - - if (saved_errno != 0) { - errno = saved_errno; - ret = -1; - } - - fsp->fh->fd = -1; - - return ret; -} - /**************************************************************************** - Debugging aid :-). + First - the functions that deal with the underlying system locks - these + functions are used no matter if we're mapping CIFS Windows locks or CIFS + POSIX locks onto POSIX. ****************************************************************************/ -static const char *posix_lock_type_name(int lock_type) -{ - return (lock_type == F_RDLCK) ? "READ" : "WRITE"; -} - -/**************************************************************************** - Delete a POSIX lock entry by index number. Used if the tdb add succeeds, but - then the POSIX fcntl lock fails. -****************************************************************************/ - -static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry) -{ - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - struct posix_lock *locks; - size_t count; - - dbuf.dptr = NULL; - - dbuf = tdb_fetch(posix_lock_tdb, kbuf); - - if (!dbuf.dptr) { - DEBUG(10,("delete_posix_lock_entry_by_index: tdb_fetch failed !\n")); - goto fail; - } - - count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); - locks = (struct posix_lock *)dbuf.dptr; - - if (count == 1) { - tdb_delete(posix_lock_tdb, kbuf); - } else { - if (entry < count-1) { - memmove(&locks[entry], &locks[entry+1], sizeof(struct posix_lock)*((count-1) - entry)); - } - dbuf.dsize -= sizeof(struct posix_lock); - tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); - } - - SAFE_FREE(dbuf.dptr); - - return True; - - fail: - - SAFE_FREE(dbuf.dptr); - return False; -} - -/**************************************************************************** - Add an entry into the POSIX locking tdb. We return the index number of the - added lock (used in case we need to delete *exactly* this entry). Returns - False on fail, True on success. -****************************************************************************/ - -static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type, size_t *pentry_num) -{ - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - struct posix_lock pl; - - dbuf.dptr = NULL; - dbuf.dsize = 0; - - dbuf = tdb_fetch(posix_lock_tdb, kbuf); - - *pentry_num = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); - - /* - * Add new record. - */ - - pl.fd = fsp->fh->fd; - pl.start = start; - pl.size = size; - pl.lock_type = lock_type; - - dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(struct posix_lock)); - if (!dbuf.dptr) { - DEBUG(0,("add_posix_lock_entry: Realloc fail !\n")); - goto fail; - } - - memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(struct posix_lock)); - dbuf.dsize += sizeof(struct posix_lock); - - if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { - DEBUG(0,("add_posix_lock: Failed to add lock entry on file %s\n", fsp->fsp_name)); - goto fail; - } - - SAFE_FREE(dbuf.dptr); - - DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: dev=%.0f inode=%.0f\n", - fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size, - (double)fsp->dev, (double)fsp->inode )); - - return True; - - fail: - - SAFE_FREE(dbuf.dptr); - return False; -} - -/**************************************************************************** - Calculate if locks have any overlap at all. -****************************************************************************/ - -static BOOL does_lock_overlap(SMB_OFF_T start1, SMB_OFF_T size1, SMB_OFF_T start2, SMB_OFF_T size2) -{ - if (start1 >= start2 && start1 <= start2 + size2) - return True; - - if (start1 < start2 && start1 + size1 > start2) - return True; - - return False; -} - -/**************************************************************************** - Delete an entry from the POSIX locking tdb. Returns a copy of the entry being - deleted and the number of records that are overlapped by this one, or -1 on error. -****************************************************************************/ - -static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, struct posix_lock *pl) -{ - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - struct posix_lock *locks; - size_t i, count; - BOOL found = False; - int num_overlapping_records = 0; - - dbuf.dptr = NULL; - - dbuf = tdb_fetch(posix_lock_tdb, kbuf); - - if (!dbuf.dptr) { - DEBUG(10,("delete_posix_lock_entry: tdb_fetch failed !\n")); - goto fail; - } - - /* There are existing locks - find a match. */ - locks = (struct posix_lock *)dbuf.dptr; - count = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); - - /* - * Search for and delete the first record that matches the - * unlock criteria. - */ - - for (i=0; i<count; i++) { - struct posix_lock *entry = &locks[i]; - - if (entry->fd == fsp->fh->fd && - entry->start == start && - entry->size == size) { - - /* Make a copy */ - *pl = *entry; - - /* Found it - delete it. */ - if (count == 1) { - tdb_delete(posix_lock_tdb, kbuf); - } else { - if (i < count-1) { - memmove(&locks[i], &locks[i+1], sizeof(struct posix_lock)*((count-1) - i)); - } - dbuf.dsize -= sizeof(struct posix_lock); - tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE); - } - count--; - found = True; - break; - } - } - - if (!found) - goto fail; - - /* - * Count the number of entries that are - * overlapped by this unlock request. - */ - - for (i = 0; i < count; i++) { - struct posix_lock *entry = &locks[i]; - - if (fsp->fh->fd == entry->fd && - does_lock_overlap( start, size, entry->start, entry->size)) - num_overlapping_records++; - } - - DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n", - posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size, - (unsigned int)num_overlapping_records )); - - SAFE_FREE(dbuf.dptr); - - return num_overlapping_records; - - fail: - - SAFE_FREE(dbuf.dptr); - return -1; -} - /**************************************************************************** Utility function to map a lock type correctly depending on the open mode of a file. @@ -519,16 +55,6 @@ static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type) DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n")); return F_RDLCK; } -#if 0 - /* We no longer open files write-only. */ - else if((lock_type == READ_LOCK) && !fsp->can_read) { - /* - * Ditto for read locks on write only files. - */ - DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n")); - return F_WRLCK; - } -#endif /* * This return should be the most normal, as we attempt @@ -539,6 +65,15 @@ static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type) } /**************************************************************************** + Debugging aid :-). +****************************************************************************/ + +static const char *posix_lock_type_name(int lock_type) +{ + return (lock_type == F_RDLCK) ? "READ" : "WRITE"; +} + +/**************************************************************************** Check to see if the given unsigned lock range is within the possible POSIX range. Modifies the given args to be in range if possible, just returns False if not. @@ -608,15 +143,17 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, * We must truncate the count to less than max_positive_lock_offset. */ - if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset)) + if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset)) { count = max_positive_lock_offset; + } /* * Truncate count to end at max lock offset. */ - if (offset + count < 0 || offset + count > max_positive_lock_offset) + if (offset + count < 0 || offset + count > max_positive_lock_offset) { count = max_positive_lock_offset - offset; + } /* * If we ate all the count, ignore this lock. @@ -729,7 +266,6 @@ static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T return ret; } - /**************************************************************************** POSIX function to see if a file region is locked. Returns True if the region is locked, False otherwise. @@ -774,6 +310,411 @@ BOOL is_posix_locked(files_struct *fsp, return True; } +/**************************************************************************** + Next - the functions that deal with in memory database storing representations + of either Windows CIFS locks or POSIX CIFS locks. +****************************************************************************/ + +/* The key used in the in-memory POSIX databases. */ + +struct lock_ref_count_key { + SMB_DEV_T device; + SMB_INO_T inode; + char r; +}; + +struct fd_key { + SMB_DEV_T device; + SMB_INO_T inode; +}; + +/******************************************************************* + Form a static locking key for a dev/inode pair for the fd array. +******************************************************************/ + +static TDB_DATA fd_array_key(SMB_DEV_T dev, SMB_INO_T inode) +{ + static struct fd_key key; + TDB_DATA kbuf; + + memset(&key, '\0', sizeof(key)); + key.device = dev; + key.inode = inode; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + return kbuf; +} + +/******************************************************************* + Form a static locking key for a dev/inode pair for the lock ref count +******************************************************************/ + +static TDB_DATA locking_ref_count_key(SMB_DEV_T dev, SMB_INO_T inode) +{ + static struct lock_ref_count_key key; + TDB_DATA kbuf; + + memset(&key, '\0', sizeof(key)); + key.device = dev; + key.inode = inode; + key.r = 'r'; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + return kbuf; +} + +/******************************************************************* + Convenience function to get an fd_array key from an fsp. +******************************************************************/ + +static TDB_DATA fd_array_key_fsp(files_struct *fsp) +{ + return fd_array_key(fsp->dev, fsp->inode); +} + +/******************************************************************* + Convenience function to get a lock ref count key from an fsp. +******************************************************************/ + +static TDB_DATA locking_ref_count_key_fsp(files_struct *fsp) +{ + return locking_ref_count_key(fsp->dev, fsp->inode); +} + +/******************************************************************* + Create the in-memory POSIX lock databases. +********************************************************************/ + +BOOL posix_locking_init(int read_only) +{ + if (posix_pending_close_tdb) { + return True; + } + + if (!posix_pending_close_tdb) { + posix_pending_close_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, + read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); + } + if (!posix_pending_close_tdb) { + DEBUG(0,("Failed to open POSIX pending close database.\n")); + return False; + } + + return True; +} + +/******************************************************************* + Delete the in-memory POSIX lock databases. +********************************************************************/ + +BOOL posix_locking_end(void) +{ + if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0) { + return False; + } + return True; +} + +/**************************************************************************** + Next - the functions that deal with storing fd's that have outstanding + POSIX locks when closed. +****************************************************************************/ + +/**************************************************************************** + The records in posix_pending_close_tdb are composed of an array of ints + keyed by dev/ino pair. + The first int is a reference count of the number of outstanding locks on + all open fd's on this dev/ino pair. Any subsequent ints are the fd's that + were open on this dev/ino pair that should have been closed, but can't as + the lock ref count is non zero. +****************************************************************************/ + +/**************************************************************************** + Keep a reference count of the number of Windows locks open on this dev/ino + pair. Creates entry if it doesn't exist. +****************************************************************************/ + +static void increment_windows_lock_ref_count(files_struct *fsp) +{ + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); + TDB_DATA dbuf; + int lock_ref_count; + + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + if (dbuf.dptr == NULL) { + dbuf.dptr = (char *)SMB_MALLOC_P(int); + if (!dbuf.dptr) { + smb_panic("increment_windows_lock_ref_count: malloc fail.\n"); + } + memset(dbuf.dptr, '\0', sizeof(int)); + dbuf.dsize = sizeof(int); + } + + memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); + lock_ref_count++; + memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); + + if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { + smb_panic("increment_windows_lock_ref_count: tdb_store_fail.\n"); + } + SAFE_FREE(dbuf.dptr); + + DEBUG(10,("increment_windows_lock_ref_count for file now %s = %d\n", + fsp->fsp_name, lock_ref_count )); +} + +static void decrement_windows_lock_ref_count(files_struct *fsp) +{ + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); + TDB_DATA dbuf; + int lock_ref_count; + + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + if (!dbuf.dptr) { + smb_panic("decrement_windows_lock_ref_count: logic error.\n"); + } + + memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); + lock_ref_count--; + memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); + + if (lock_ref_count < 0) { + smb_panic("decrement_windows_lock_ref_count: lock_count logic error.\n"); + } + + if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { + smb_panic("decrement_windows_lock_ref_count: tdb_store_fail.\n"); + } + SAFE_FREE(dbuf.dptr); + + DEBUG(10,("decrement_windows_lock_ref_count for file now %s = %d\n", + fsp->fsp_name, lock_ref_count )); +} + +/**************************************************************************** + Ensure the lock ref count is zero. +****************************************************************************/ + +void zero_windows_lock_ref_count(files_struct *fsp) +{ + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); + TDB_DATA dbuf; + int lock_ref_count; + + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + if (!dbuf.dptr) { + return; + } + + memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); + if (lock_ref_count < 0) { + smb_panic("zero_windows_lock_ref_count: lock_count logic error.\n"); + } + + lock_ref_count = 0; + memcpy(dbuf.dptr, &lock_ref_count, sizeof(int)); + + if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { + smb_panic("zero_windows_lock_ref_count: tdb_store_fail.\n"); + } + SAFE_FREE(dbuf.dptr); + + DEBUG(10,("zero_windows_lock_ref_count for file now %s = %d\n", + fsp->fsp_name, lock_ref_count )); +} + +/**************************************************************************** + Fetch the lock ref count. +****************************************************************************/ + +static int get_windows_lock_ref_count(files_struct *fsp) +{ + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); + TDB_DATA dbuf; + int lock_ref_count; + + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + if (!dbuf.dptr) { + lock_ref_count = 0; + } else { + memcpy(&lock_ref_count, dbuf.dptr, sizeof(int)); + } + + DEBUG(10,("get_windows_lock_count for file %s = %d\n", + fsp->fsp_name, lock_ref_count )); + return lock_ref_count; +} + +/**************************************************************************** + Delete a lock_ref_count entry. +****************************************************************************/ + +static void delete_windows_lock_ref_count(files_struct *fsp) +{ + TDB_DATA kbuf = locking_ref_count_key_fsp(fsp); + + /* Not a bug if it doesn't exist - no locks were ever granted. */ + tdb_delete(posix_pending_close_tdb, kbuf); + DEBUG(10,("delete_windows_lock_ref_count for file %s\n", fsp->fsp_name)); +} + +/**************************************************************************** + Add an fd to the pending close tdb. +****************************************************************************/ + +static void add_fd_to_close_entry(files_struct *fsp) +{ + TDB_DATA kbuf = fd_array_key_fsp(fsp); + TDB_DATA dbuf; + + dbuf.dptr = NULL; + dbuf.dsize = 0; + + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + + dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int)); + if (!dbuf.dptr) { + smb_panic("add_fd_to_close_entry: Realloc fail !\n"); + } + + memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int)); + dbuf.dsize += sizeof(int); + + if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) { + smb_panic("add_fd_to_close_entry: tdb_store_fail.\n"); + } + + DEBUG(10,("add_fd_to_close_entry: added fd %d file %s\n", + fsp->fh->fd, fsp->fsp_name )); + + SAFE_FREE(dbuf.dptr); +} + +/**************************************************************************** + Remove all fd entries for a specific dev/inode pair from the tdb. +****************************************************************************/ + +static void delete_close_entries(files_struct *fsp) +{ + TDB_DATA kbuf = fd_array_key_fsp(fsp); + + if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) { + smb_panic("delete_close_entries: tdb_delete fail !\n"); + } +} + +/**************************************************************************** + Get the array of POSIX pending close records for an open fsp. Caller must + free. Returns number of entries. +****************************************************************************/ + +static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries) +{ + TDB_DATA kbuf = fd_array_key_fsp(fsp); + TDB_DATA dbuf; + size_t count = 0; + + *entries = NULL; + dbuf.dptr = NULL; + + dbuf = tdb_fetch(posix_pending_close_tdb, kbuf); + + if (!dbuf.dptr) { + return 0; + } + + *entries = (int *)dbuf.dptr; + count = (size_t)(dbuf.dsize / sizeof(int)); + + return count; +} + +/**************************************************************************** + Deal with pending closes needed by POSIX locking support. + Note that posix_locking_close_file() is expected to have been called + to delete all locks on this fsp before this function is called. +****************************************************************************/ + +int fd_close_posix(struct connection_struct *conn, files_struct *fsp) +{ + int saved_errno = 0; + int ret; + int *fd_array = NULL; + size_t count, i; + + if (!lp_locking(SNUM(fsp->conn)) || !lp_posix_locking(SNUM(conn)) || lp_posix_cifsu_locktype()) { + /* + * No locking or POSIX to worry about or we want POSIX semantics + * which will lose all locks on all fd's open on this dev/inode, + * just close. + */ + ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); + fsp->fh->fd = -1; + return ret; + } + + if (get_windows_lock_ref_count(fsp)) { + + /* + * There are outstanding locks on this dev/inode pair on other fds. + * Add our fd to the pending close tdb and set fsp->fh->fd to -1. + */ + + add_fd_to_close_entry(fsp); + fsp->fh->fd = -1; + return 0; + } + + /* + * No outstanding locks. Get the pending close fd's + * from the tdb and close them all. + */ + + count = get_posix_pending_close_entries(fsp, &fd_array); + + if (count) { + DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); + + for(i = 0; i < count; i++) { + if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) { + saved_errno = errno; + } + } + + /* + * Delete all fd's stored in the tdb + * for this dev/inode pair. + */ + + delete_close_entries(fsp); + } + + SAFE_FREE(fd_array); + + /* Don't need a lock ref count on this dev/ino anymore. */ + delete_windows_lock_ref_count(fsp); + + /* + * Finally close the fd associated with this fsp. + */ + + ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd); + + if (saved_errno != 0) { + errno = saved_errno; + ret = -1; + } + + fsp->fh->fd = -1; + + return ret; +} + +/**************************************************************************** + Next - the functions that deal with the mapping CIFS Windows locks onto + the underlying system POSIX locks. +****************************************************************************/ + /* * Structure used when splitting a lock range * into a POSIX lock range. Doubly linked list. @@ -792,22 +733,14 @@ struct lock_list { understand it :-). ****************************************************************************/ -static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhead, files_struct *fsp) +static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, + struct lock_list *lhead, + const struct lock_context *lock_ctx, /* Lock context lhead belongs to. */ + files_struct *fsp, + const struct lock_struct *plocks, + int num_locks) { - TDB_DATA kbuf = locking_key_fsp(fsp); - TDB_DATA dbuf; - struct posix_lock *locks; - size_t num_locks, i; - - dbuf.dptr = NULL; - - dbuf = tdb_fetch(posix_lock_tdb, kbuf); - - if (!dbuf.dptr) - return lhead; - - locks = (struct posix_lock *)dbuf.dptr; - num_locks = (size_t)(dbuf.dsize / sizeof(struct posix_lock)); + int i; /* * Check the current lock list on this dev/inode pair. @@ -818,10 +751,19 @@ static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhea (double)lhead->start, (double)lhead->size )); for (i=0; i<num_locks && lhead; i++) { - - struct posix_lock *lock = &locks[i]; + const struct lock_struct *lock = &plocks[i]; struct lock_list *l_curr; + /* Ignore all but read/write locks. */ + if (lock->lock_type != READ_LOCK && lock->lock_type != WRITE_LOCK) { + continue; + } + + /* Ignore locks not owned by this process. */ + if (!procid_equal(&lock->context.pid, &lock_ctx->pid)) { + continue; + } + /* * Walk the lock list, checking for overlaps. Note that * the lock list can expand within this loop if the current @@ -830,13 +772,13 @@ static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhea for (l_curr = lhead; l_curr;) { - DEBUG(10,("posix_lock_list: lock: fd=%d: start=%.0f,size=%.0f:type=%s", lock->fd, + DEBUG(10,("posix_lock_list: lock: fnum=%d: start=%.0f,size=%.0f:type=%s", lock->fnum, (double)lock->start, (double)lock->size, posix_lock_type_name(lock->lock_type) )); if ( (l_curr->start >= (lock->start + lock->size)) || (lock->start >= (l_curr->start + l_curr->size))) { - /* No overlap with this lock - leave this range alone. */ + /* No overlap with existing lock - leave this range alone. */ /********************************************* +---------+ | l_curr | @@ -850,7 +792,7 @@ OR.... +---------+ **********************************************/ - DEBUG(10,("no overlap case.\n" )); + DEBUG(10,(" no overlap case.\n" )); l_curr = l_curr->next; @@ -858,8 +800,8 @@ OR.... (l_curr->start + l_curr->size <= lock->start + lock->size) ) { /* - * This unlock is completely overlapped by this existing lock range - * and thus should have no effect (not be unlocked). Delete it from the list. + * This range is completely overlapped by this existing lock range + * and thus should have no effect. Delete it from the list. */ /********************************************* +---------+ @@ -872,11 +814,12 @@ OR.... /* Save the next pointer */ struct lock_list *ul_next = l_curr->next; - DEBUG(10,("delete case.\n" )); + DEBUG(10,(" delete case.\n" )); DLIST_REMOVE(lhead, l_curr); - if(lhead == NULL) + if(lhead == NULL) { break; /* No more list... */ + } l_curr = ul_next; @@ -885,7 +828,7 @@ OR.... (l_curr->start + l_curr->size > lock->start + lock->size) ) { /* - * This unlock overlaps the existing lock range at the high end. + * This range overlaps the existing lock range at the high end. * Truncate by moving start to existing range end and reducing size. */ /********************************************* @@ -904,7 +847,7 @@ BECOMES.... l_curr->size = (l_curr->start + l_curr->size) - (lock->start + lock->size); l_curr->start = lock->start + lock->size; - DEBUG(10,("truncate high case: start=%.0f,size=%.0f\n", + DEBUG(10,(" truncate high case: start=%.0f,size=%.0f\n", (double)l_curr->start, (double)l_curr->size )); l_curr = l_curr->next; @@ -914,7 +857,7 @@ BECOMES.... (l_curr->start + l_curr->size <= lock->start + lock->size) ) { /* - * This unlock overlaps the existing lock range at the low end. + * This range overlaps the existing lock range at the low end. * Truncate by reducing size. */ /********************************************* @@ -932,7 +875,7 @@ BECOMES.... l_curr->size = lock->start - l_curr->start; - DEBUG(10,("truncate low case: start=%.0f,size=%.0f\n", + DEBUG(10,(" truncate low case: start=%.0f,size=%.0f\n", (double)l_curr->start, (double)l_curr->size )); l_curr = l_curr->next; @@ -940,10 +883,10 @@ BECOMES.... } else if ( (l_curr->start < lock->start) && (l_curr->start + l_curr->size > lock->start + lock->size) ) { /* - * Worst case scenario. Unlock request completely overlaps an existing + * Worst case scenario. Range completely overlaps an existing * lock range. Split the request into two, push the new (upper) request - * into the dlink list, and continue with the entry after ul_new (as we - * know that ul_new will not overlap with this lock). + * into the dlink list, and continue with the entry after l_new (as we + * know that l_new will not overlap with this lock). */ /********************************************* +---------------------------+ @@ -971,7 +914,7 @@ BECOMES..... /* Truncate the l_curr. */ l_curr->size = lock->start - l_curr->start; - DEBUG(10,("split case: curr: start=%.0f,size=%.0f \ + DEBUG(10,(" split case: curr: start=%.0f,size=%.0f \ new: start=%.0f,size=%.0f\n", (double)l_curr->start, (double)l_curr->size, (double)l_new->start, (double)l_new->size )); @@ -1003,34 +946,33 @@ lock: start = %.0f, size = %.0f\n", (double)l_curr->start, (double)l_curr->size, } /* end for ( l_curr = lhead; l_curr;) */ } /* end for (i=0; i<num_locks && ul_head; i++) */ - SAFE_FREE(dbuf.dptr); - return lhead; } /**************************************************************************** POSIX function to acquire a lock. Returns True if the lock could be granted, False if not. - TODO -- Fix POSIX lock flavour semantics. ****************************************************************************/ -BOOL set_posix_lock(files_struct *fsp, +BOOL set_posix_lock_windows_flavour(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type, - enum brl_flavour lock_flav) + const struct lock_context *lock_ctx, + const struct lock_struct *plocks, + int num_locks, + int *errno_ret) { SMB_OFF_T offset; SMB_OFF_T count; + int posix_lock_type = map_posix_lock_type(fsp,lock_type); BOOL ret = True; - size_t entry_num = 0; size_t lock_count; TALLOC_CTX *l_ctx = NULL; struct lock_list *llist = NULL; struct lock_list *ll = NULL; - int posix_lock_type = map_posix_lock_type(fsp,lock_type); - DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n", + DEBUG(5,("set_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f, type = %s\n", fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) )); /* @@ -1038,8 +980,9 @@ BOOL set_posix_lock(files_struct *fsp, * pretend it was successful. */ - if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) { return True; + } /* * Windows is very strange. It allows read locks to be overlayed @@ -1056,19 +999,16 @@ BOOL set_posix_lock(files_struct *fsp, * READ LOCK: start =0, len = 10 - OK * * Under POSIX, the same sequence in steps 1 and 2 would not be reference counted, but - * would leave a single read lock over the 0-14 region. In order to - * re-create Windows semantics mapped to POSIX locks, we create multiple TDB - * entries, one for each overlayed lock request. We are guarenteed by the brlock - * semantics that if a write lock is added, then it will be first in the array. + * would leave a single read lock over the 0-14 region. */ if ((l_ctx = talloc_init("set_posix_lock")) == NULL) { - DEBUG(0,("set_posix_lock: unable to init talloc context.\n")); + DEBUG(0,("set_posix_lock_windows_flavour: unable to init talloc context.\n")); return True; /* Not a fatal error. */ } if ((ll = TALLOC_P(l_ctx, struct lock_list)) == NULL) { - DEBUG(0,("set_posix_lock: unable to talloc unlock list.\n")); + DEBUG(0,("set_posix_lock_windows_flavour: unable to talloc unlock list.\n")); talloc_destroy(l_ctx); return True; /* Not a fatal error. */ } @@ -1092,19 +1032,12 @@ BOOL set_posix_lock(files_struct *fsp, * POSIX locks. */ - llist = posix_lock_list(l_ctx, llist, fsp); - - /* - * Now we have the list of ranges to lock it is safe to add the - * entry into the POSIX lock tdb. We take note of the entry we - * added here in case we have to remove it on POSIX lock fail. - */ - - if (!add_posix_lock_entry(fsp,offset,count,posix_lock_type,&entry_num)) { - DEBUG(0,("set_posix_lock: Unable to create posix lock entry !\n")); - talloc_destroy(l_ctx); - return False; - } + llist = posix_lock_list(l_ctx, + llist, + lock_ctx, /* Lock context llist belongs to. */ + fsp, + plocks, + num_locks); /* * Add the POSIX locks on the list of ranges returned. @@ -1116,11 +1049,12 @@ BOOL set_posix_lock(files_struct *fsp, offset = ll->start; count = ll->size; - DEBUG(5,("set_posix_lock: Real lock: Type = %s: offset = %.0f, count = %.0f\n", + DEBUG(5,("set_posix_lock_windows_flavour: Real lock: Type = %s: offset = %.0f, count = %.0f\n", posix_lock_type_name(posix_lock_type), (double)offset, (double)count )); if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) { - DEBUG(5,("set_posix_lock: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n", + *errno_ret = errno; + DEBUG(5,("set_posix_lock_windows_flavour: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n", posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) )); ret = False; break; @@ -1137,17 +1071,14 @@ BOOL set_posix_lock(files_struct *fsp, offset = ll->start; count = ll->size; - DEBUG(5,("set_posix_lock: Backing out locks: Type = %s: offset = %.0f, count = %.0f\n", + DEBUG(5,("set_posix_lock_windows_flavour: Backing out locks: Type = %s: offset = %.0f, count = %.0f\n", posix_lock_type_name(posix_lock_type), (double)offset, (double)count )); posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK); } - - /* - * Remove the tdb entry for this lock. - */ - - delete_posix_lock_entry_by_index(fsp,entry_num); + } else { + /* Remember the number of Windows locks we have on this dev/ino pair. */ + increment_windows_lock_ref_count(fsp); } talloc_destroy(l_ctx); @@ -1159,7 +1090,13 @@ BOOL set_posix_lock(files_struct *fsp, lock could be released, False if not. ****************************************************************************/ -BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count) +BOOL release_posix_lock_windows_flavour(files_struct *fsp, + SMB_BIG_UINT u_offset, + SMB_BIG_UINT u_count, + enum brl_type deleted_lock_type, + const struct lock_context *lock_ctx, + const struct lock_struct *plocks, + int num_locks) { SMB_OFF_T offset; SMB_OFF_T count; @@ -1167,10 +1104,8 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u TALLOC_CTX *ul_ctx = NULL; struct lock_list *ulist = NULL; struct lock_list *ul = NULL; - struct posix_lock deleted_lock; - int num_overlapped_entries; - DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n", + DEBUG(5,("release_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f\n", fsp->fsp_name, (double)u_offset, (double)u_count )); /* @@ -1178,43 +1113,20 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u * pretend it was successful. */ - if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) { return True; - - /* - * We treat this as one unlock request for POSIX accounting purposes even - * if it may later be split into multiple smaller POSIX unlock ranges. - * num_overlapped_entries is the number of existing locks that have any - * overlap with this unlock request. - */ - - num_overlapped_entries = delete_posix_lock_entry(fsp, offset, count, &deleted_lock); - - if (num_overlapped_entries == -1) { - smb_panic("release_posix_lock: unable find entry to delete !\n"); } - /* - * If num_overlapped_entries is > 0, and the lock_type we just deleted from the tdb was - * a POSIX write lock, then before doing the unlock we need to downgrade - * the POSIX lock to a read lock. This allows any overlapping read locks - * to be atomically maintained. - */ - - if (num_overlapped_entries > 0 && deleted_lock.lock_type == F_WRLCK) { - if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK)) { - DEBUG(0,("release_posix_lock: downgrade of lock failed with error %s !\n", strerror(errno) )); - return False; - } - } + /* Remember the number of Windows locks we have on this dev/ino pair. */ + decrement_windows_lock_ref_count(fsp); if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) { - DEBUG(0,("release_posix_lock: unable to init talloc context.\n")); + DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n")); return True; /* Not a fatal error. */ } if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) { - DEBUG(0,("release_posix_lock: unable to talloc unlock list.\n")); + DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n")); talloc_destroy(ul_ctx); return True; /* Not a fatal error. */ } @@ -1239,7 +1151,33 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u * unlocks are performed. */ - ulist = posix_lock_list(ul_ctx, ulist, fsp); + ulist = posix_lock_list(ul_ctx, + ulist, + lock_ctx, /* Lock context ulist belongs to. */ + fsp, + plocks, + num_locks); + + /* + * If there were any overlapped entries (list is > 1 or size or start have changed), + * and the lock_type we just deleted from + * the upper layer tdb was a write lock, then before doing the unlock we need to downgrade + * the POSIX lock to a read lock. This allows any overlapping read locks + * to be atomically maintained. + */ + + if (deleted_lock_type == WRITE_LOCK && + (!ulist || ulist->next != NULL || ulist->start != offset || ulist->size != count)) { + + DEBUG(5,("release_posix_lock_windows_flavour: downgrading lock to READ: offset = %.0f, count = %.0f\n", + (double)offset, (double)count )); + + if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK)) { + DEBUG(0,("release_posix_lock_windows_flavour: downgrade of lock failed with error %s !\n", strerror(errno) )); + talloc_destroy(ul_ctx); + return False; + } + } /* * Release the POSIX locks on the list of ranges returned. @@ -1249,129 +1187,148 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u offset = ulist->start; count = ulist->size; - DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n", + DEBUG(5,("release_posix_lock_windows_flavour: Real unlock: offset = %.0f, count = %.0f\n", (double)offset, (double)count )); - if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) + if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) { ret = False; + } } talloc_destroy(ul_ctx); - return ret; } /**************************************************************************** - Remove all lock entries for a specific dev/inode pair from the tdb. + Next - the functions that deal with mapping CIFS POSIX locks onto + the underlying system POSIX locks. ****************************************************************************/ -static void delete_posix_lock_entries(files_struct *fsp) -{ - TDB_DATA kbuf = locking_key_fsp(fsp); - - if (tdb_delete(posix_lock_tdb, kbuf) == -1) - DEBUG(0,("delete_close_entries: tdb_delete fail !\n")); -} - /**************************************************************************** - Debug function. + POSIX function to acquire a lock. Returns True if the + lock could be granted, False if not. + As POSIX locks don't stack or conflict (they just overwrite) + we can map the requested lock directly onto a system one. We + know it doesn't conflict with locks on other contexts as the + upper layer would have refused it. ****************************************************************************/ -static void dump_entry(struct posix_lock *pl) +BOOL set_posix_lock_posix_flavour(files_struct *fsp, + SMB_BIG_UINT u_offset, + SMB_BIG_UINT u_count, + enum brl_type lock_type, + int *errno_ret) { - DEBUG(10,("entry: start=%.0f, size=%.0f, type=%d, fd=%i\n", - (double)pl->start, (double)pl->size, (int)pl->lock_type, pl->fd )); + SMB_OFF_T offset; + SMB_OFF_T count; + int posix_lock_type = map_posix_lock_type(fsp,lock_type); + + DEBUG(5,("set_posix_lock_posix_flavour: File %s, offset = %.0f, count = %.0f, type = %s\n", + fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) )); + + /* + * If the requested lock won't fit in the POSIX range, we will + * pretend it was successful. + */ + + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) { + return True; + } + + if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) { + *errno_ret = errno; + DEBUG(5,("set_posix_lock_posix_flavour: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n", + posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) )); + return False; + } + return True; } /**************************************************************************** - Remove any locks on this fd. Called from file_close(). + POSIX function to release a lock. Returns True if the + lock could be released, False if not. + We are given a complete lock state from the upper layer which is what the lock + state should be after the unlock has already been done, so what + we do is punch out holes in the unlock range where locks owned by this process + have a different lock context. ****************************************************************************/ -void posix_locking_close_file(files_struct *fsp) +BOOL release_posix_lock_posix_flavour(files_struct *fsp, + SMB_BIG_UINT u_offset, + SMB_BIG_UINT u_count, + const struct lock_context *lock_ctx, + const struct lock_struct *plocks, + int num_locks) { - struct posix_lock *entries = NULL; - size_t count, i; + BOOL ret = True; + SMB_OFF_T offset; + SMB_OFF_T count; + TALLOC_CTX *ul_ctx = NULL; + struct lock_list *ulist = NULL; + struct lock_list *ul = NULL; + + DEBUG(5,("release_posix_lock_posix_flavour: File %s, offset = %.0f, count = %.0f\n", + fsp->fsp_name, (double)u_offset, (double)u_count )); /* - * Optimization for the common case where we are the only - * opener of a file. If all fd entries are our own, we don't - * need to explicitly release all the locks via the POSIX functions, - * we can just remove all the entries in the tdb and allow the - * close to remove the real locks. + * If the requested lock won't fit in the POSIX range, we will + * pretend it was successful. */ - count = get_posix_lock_entries(fsp, &entries); - - if (count == 0) { - DEBUG(10,("posix_locking_close_file: file %s has no outstanding locks.\n", fsp->fsp_name )); - return; + if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) { + return True; } - for (i = 0; i < count; i++) { - if (entries[i].fd != fsp->fh->fd ) - break; - - dump_entry(&entries[i]); + if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) { + DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n")); + return False; } - if (i == count) { - /* All locks are ours. */ - DEBUG(10,("posix_locking_close_file: file %s has %u outstanding locks, but all on one fd.\n", - fsp->fsp_name, (unsigned int)count )); - SAFE_FREE(entries); - delete_posix_lock_entries(fsp); - return; + if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) { + DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n")); + talloc_destroy(ul_ctx); + return False; } /* - * Difficult case. We need to delete all our locks, whilst leaving - * all other POSIX locks in place. + * Create the initial list entry containing the + * lock we want to remove. */ - for (i = 0; i < count; i++) { - struct posix_lock *pl = &entries[i]; - if (pl->fd == fsp->fh->fd) - release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size ); - } - SAFE_FREE(entries); -} + ZERO_STRUCTP(ul); + ul->start = offset; + ul->size = count; -/******************************************************************* - Create the in-memory POSIX lock databases. -********************************************************************/ + DLIST_ADD(ulist, ul); -BOOL posix_locking_init(int read_only) -{ - if (posix_lock_tdb && posix_pending_close_tdb) - return True; - - if (!posix_lock_tdb) - posix_lock_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, - read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); - if (!posix_lock_tdb) { - DEBUG(0,("Failed to open POSIX byte range locking database.\n")); - return False; - } - if (!posix_pending_close_tdb) - posix_pending_close_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, - read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); - if (!posix_pending_close_tdb) { - DEBUG(0,("Failed to open POSIX pending close database.\n")); - return False; - } + /* + * Walk the given array creating a linked list + * of unlock requests. + */ - return True; -} + ulist = posix_lock_list(ul_ctx, + ulist, + lock_ctx, /* Lock context ulist belongs to. */ + fsp, + plocks, + num_locks); -/******************************************************************* - Delete the in-memory POSIX lock databases. -********************************************************************/ + /* + * Release the POSIX locks on the list of ranges returned. + */ -BOOL posix_locking_end(void) -{ - if (posix_lock_tdb && tdb_close(posix_lock_tdb) != 0) - return False; - if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0) - return False; + for(; ulist; ulist = ulist->next) { + offset = ulist->start; + count = ulist->size; + + DEBUG(5,("release_posix_lock_posix_flavour: Real unlock: offset = %.0f, count = %.0f\n", + (double)offset, (double)count )); + + if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) { + ret = False; + } + } + + talloc_destroy(ul_ctx); return True; } diff --git a/source/modules/charset_macosxfs.c b/source/modules/charset_macosxfs.c index 6f50d879ba4..a9003c7a826 100644 --- a/source/modules/charset_macosxfs.c +++ b/source/modules/charset_macosxfs.c @@ -594,7 +594,7 @@ static struct charset_functions macosxfs_encoding_functions = { "MACOSXFS", macosxfs_encoding_pull, macosxfs_encoding_push }; -NTSTATUS init_module(void) +NTSTATUS charset_macosxfs_init(void) { return smb_register_charset(&macosxfs_encoding_functions); } diff --git a/source/modules/vfs_afsacl.c b/source/modules/vfs_afsacl.c index 53272ca06fe..11498fccf9e 100644 --- a/source/modules/vfs_afsacl.c +++ b/source/modules/vfs_afsacl.c @@ -1011,7 +1011,6 @@ BOOL afsacl_set_nt_acl(vfs_handle_struct *handle, } static int afsacl_connect(vfs_handle_struct *handle, - connection_struct *conn, const char *service, const char *user) { @@ -1022,7 +1021,7 @@ static int afsacl_connect(vfs_handle_struct *handle, if (spc != NULL) space_replacement = spc[0]; - return SMB_VFS_NEXT_CONNECT(handle, conn, service, user); + return SMB_VFS_NEXT_CONNECT(handle, service, user); } /* VFS operations structure */ diff --git a/source/modules/vfs_audit.c b/source/modules/vfs_audit.c index 9f5179a47ce..b240cafd29f 100644 --- a/source/modules/vfs_audit.c +++ b/source/modules/vfs_audit.c @@ -29,17 +29,17 @@ /* Function prototypes */ -static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user); -static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn); -static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr); -static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode); -static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path); -static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode); +static int audit_connect(vfs_handle_struct *handle, const char *svc, const char *user); +static void audit_disconnect(vfs_handle_struct *handle); +static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr); +static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode); +static int audit_rmdir(vfs_handle_struct *handle, const char *path); +static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode); static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd); -static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname); -static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path); -static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode); -static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode); +static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname); +static int audit_unlink(vfs_handle_struct *handle, const char *path); +static int audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode); +static int audit_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode); static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode); static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode); @@ -120,7 +120,7 @@ static int audit_syslog_priority(vfs_handle_struct *handle) /* Implementation of vfs_ops. Pass everything on to the default operation but log event first. */ -static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user) +static int audit_connect(vfs_handle_struct *handle, const char *svc, const char *user) { int result; @@ -129,24 +129,24 @@ static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, con syslog(audit_syslog_priority(handle), "connect to service %s by user %s\n", svc, user); - result = SMB_VFS_NEXT_CONNECT(handle, conn, svc, user); + result = SMB_VFS_NEXT_CONNECT(handle, svc, user); return result; } -static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn) +static void audit_disconnect(vfs_handle_struct *handle) { syslog(audit_syslog_priority(handle), "disconnected\n"); - SMB_VFS_NEXT_DISCONNECT(handle, conn); + SMB_VFS_NEXT_DISCONNECT(handle); return; } -static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr) +static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr) { SMB_STRUCT_DIR *result; - result = SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr); + result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); syslog(audit_syslog_priority(handle), "opendir %s %s%s\n", fname, @@ -156,11 +156,11 @@ static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struc return result; } -static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) +static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode) { int result; - result = SMB_VFS_NEXT_MKDIR(handle, conn, path, mode); + result = SMB_VFS_NEXT_MKDIR(handle, path, mode); syslog(audit_syslog_priority(handle), "mkdir %s %s%s\n", path, @@ -170,11 +170,11 @@ static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const return result; } -static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) +static int audit_rmdir(vfs_handle_struct *handle, const char *path) { int result; - result = SMB_VFS_NEXT_RMDIR(handle, conn, path); + result = SMB_VFS_NEXT_RMDIR(handle, path); syslog(audit_syslog_priority(handle), "rmdir %s %s%s\n", path, @@ -184,11 +184,11 @@ static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const return result; } -static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode) +static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode) { int result; - result = SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode); + result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); syslog(audit_syslog_priority(handle), "open %s (fd %d) %s%s%s\n", fname, result, @@ -213,11 +213,11 @@ static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd) return result; } -static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname) +static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname) { int result; - result = SMB_VFS_NEXT_RENAME(handle, conn, oldname, newname); + result = SMB_VFS_NEXT_RENAME(handle, oldname, newname); syslog(audit_syslog_priority(handle), "rename %s -> %s %s%s\n", oldname, newname, @@ -227,11 +227,11 @@ static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, cons return result; } -static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path) +static int audit_unlink(vfs_handle_struct *handle, const char *path) { int result; - result = SMB_VFS_NEXT_UNLINK(handle, conn, path); + result = SMB_VFS_NEXT_UNLINK(handle, path); syslog(audit_syslog_priority(handle), "unlink %s %s%s\n", path, @@ -241,11 +241,11 @@ static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, cons return result; } -static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) +static int audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode) { int result; - result = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode); + result = SMB_VFS_NEXT_CHMOD(handle, path, mode); syslog(audit_syslog_priority(handle), "chmod %s mode 0x%x %s%s\n", path, mode, @@ -255,11 +255,11 @@ static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const return result; } -static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) +static int audit_chmod_acl(vfs_handle_struct *handle, const char *path, mode_t mode) { int result; - result = SMB_VFS_NEXT_CHMOD_ACL(handle, conn, path, mode); + result = SMB_VFS_NEXT_CHMOD_ACL(handle, path, mode); syslog(audit_syslog_priority(handle), "chmod_acl %s mode 0x%x %s%s\n", path, mode, diff --git a/source/modules/vfs_cacheprime.c b/source/modules/vfs_cacheprime.c new file mode 100644 index 00000000000..196441c4dda --- /dev/null +++ b/source/modules/vfs_cacheprime.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) James Peach 2005-2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +/* Cache priming module. + * + * The purpose of this module is to do RAID stripe width reads to prime the + * buffer cache to do zero-copy I/O for subsequent sendfile calls. The idea is + * to do a single large read at the start of the file to make sure that most or + * all of the file is pulled into the buffer cache. Subsequent I/Os have + * reduced latency. + * + * Tunables. + * + * cacheprime:rsize Amount of readahead in bytes. This should be a + * multiple of the RAID stripe width. + * cacheprime:debug Debug level at which to emit messages. + */ + +#define READAHEAD_MIN (128 * 1024) /* min is 128 KiB */ +#define READAHEAD_MAX (100 * 1024 * 1024) /* max is 100 MiB */ + +#define MODULE "cacheprime" + +static int module_debug; +static ssize_t g_readsz = 0; +static void * g_readbuf = NULL; + +/* Prime the kernel buffer cache with data from the specified file. We use + * per-fsp data to make sure we only ever do this once. If pread is being + * emulated by seek/read/seek, when this will suck quite a lot. + */ +static BOOL prime_cache( + struct vfs_handle_struct * handle, + files_struct * fsp, + int fd, + SMB_OFF_T offset, + size_t count) +{ + SMB_OFF_T * last; + ssize_t nread; + + last = VFS_ADD_FSP_EXTENSION(handle, fsp, SMB_OFF_T); + if (!last) { + return False; + } + + if (*last == -1) { + /* Readahead disabled. */ + return False; + } + + if ((*last + g_readsz) > (offset + count)) { + /* Skip readahead ... we've already been here. */ + return False; + } + + DEBUG(module_debug, + ("%s: doing readahead of %lld bytes at %lld for %s\n", + MODULE, (long long)g_readsz, (long long)*last, + fsp->fsp_name)); + + nread = sys_pread(fd, g_readbuf, g_readsz, *last); + if (nread < 0) { + *last = -1; + return False; + } + + *last += nread; + return True; +} + +static int cprime_connect( + struct vfs_handle_struct * handle, + const char * service, + const char * user) +{ + module_debug = lp_parm_int(SNUM(handle->conn), MODULE, "debug", 100); + if (g_readbuf) { + /* Only allocate g_readbuf once. If the config changes and + * another client multiplexes onto this smbd, we don't want + * to risk memory corruption. + */ + return SMB_VFS_NEXT_CONNECT(handle, service, user); + } + + g_readsz = conv_str_size(lp_parm_const_string(SNUM(handle->conn), + MODULE, "rsize", NULL)); + + if (g_readsz < READAHEAD_MIN) { + DEBUG(module_debug, ("%s: %ld bytes of readahead " + "requested, using minimum of %u\n", + MODULE, (long)g_readsz, READAHEAD_MIN)); + g_readsz = READAHEAD_MIN; + } else if (g_readsz > READAHEAD_MAX) { + DEBUG(module_debug, ("%s: %ld bytes of readahead " + "requested, using maximum of %u\n", + MODULE, (long)g_readsz, READAHEAD_MAX)); + g_readsz = READAHEAD_MAX; + } + + if ((g_readbuf = SMB_MALLOC(g_readsz)) == NULL) { + /* Turn off readahead if we can't get a buffer. */ + g_readsz = 0; + } + + return SMB_VFS_NEXT_CONNECT(handle, service, user); +} + +static ssize_t cprime_sendfile( + struct vfs_handle_struct * handle, + int tofd, + files_struct * fsp, + int fromfd, + const DATA_BLOB * header, + SMB_OFF_T offset, + size_t count) +{ + if (g_readbuf && offset == 0) { + prime_cache(handle, fsp, fromfd, offset, count); + } + + return SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd, + header, offset, count); +} + +static ssize_t cprime_read( + vfs_handle_struct * handle, + files_struct * fsp, + int fd, + void * data, + size_t count) +{ + SMB_OFF_T offset; + + offset = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); + if (offset >= 0 && g_readbuf) { + prime_cache(handle, fsp, fd, offset, count); + SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET); + } + + return SMB_VFS_NEXT_READ(handle, fsp, fd, data, count); +} + +static ssize_t cprime_pread( + vfs_handle_struct * handle, + files_struct * fsp, + int fd, + void * data, + size_t count, + SMB_OFF_T offset) +{ + if (g_readbuf) { + prime_cache(handle, fsp, fd, offset, count); + } + + return SMB_VFS_NEXT_PREAD(handle, fsp, fd, data, count, offset); +} + +static vfs_op_tuple cprime_ops [] = +{ + {SMB_VFS_OP(cprime_sendfile), + SMB_VFS_OP_SENDFILE, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cprime_pread), + SMB_VFS_OP_PREAD, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cprime_read), + SMB_VFS_OP_READ, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cprime_connect), + SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} +}; + +/* ------------------------------------------------------------------------- + * Samba module initialisation entry point. + * ------------------------------------------------------------------------- + */ + +NTSTATUS vfs_cacheprime_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE, cprime_ops); +} + +/* vim: set sw=4 ts=4 tw=79 et: */ diff --git a/source/modules/vfs_cap.c b/source/modules/vfs_cap.c index b1bfcd75f2f..54f74dde678 100644 --- a/source/modules/vfs_cap.c +++ b/source/modules/vfs_cap.c @@ -28,28 +28,28 @@ static char *capencode(char *to, const char *from); static char *capdecode(char *to, const char *from); -static SMB_BIG_UINT cap_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path, +static SMB_BIG_UINT cap_disk_free(vfs_handle_struct *handle, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_DISK_FREE(handle, conn, cappath, small_query, bsize, + return SMB_VFS_NEXT_DISK_FREE(handle, cappath, small_query, bsize, dfree, dsize); } -static SMB_STRUCT_DIR *cap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr) +static SMB_STRUCT_DIR *cap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr) { pstring capname; capencode(capname, fname); - return SMB_VFS_NEXT_OPENDIR(handle, conn, capname, mask, attr); + return SMB_VFS_NEXT_OPENDIR(handle, capname, mask, attr); } -static SMB_STRUCT_DIRENT *cap_readdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp) +static SMB_STRUCT_DIRENT *cap_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp) { SMB_STRUCT_DIRENT *result; DEBUG(3,("cap: cap_readdir\n")); - result = SMB_VFS_NEXT_READDIR(handle, conn, dirp); + result = SMB_VFS_NEXT_READDIR(handle, dirp); if (result) { DEBUG(3,("cap: cap_readdir: %s\n", result->d_name)); capdecode(result->d_name, result->d_name); @@ -57,124 +57,124 @@ static SMB_STRUCT_DIRENT *cap_readdir(vfs_handle_struct *handle, connection_stru return result; } -static int cap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) +static int cap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode) { pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_MKDIR(handle, conn, cappath, mode); + return SMB_VFS_NEXT_MKDIR(handle, cappath, mode); } -static int cap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) +static int cap_rmdir(vfs_handle_struct *handle, const char *path) { pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_RMDIR(handle, conn, cappath); + return SMB_VFS_NEXT_RMDIR(handle, cappath); } -static int cap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode) +static int cap_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode) { pstring capname; DEBUG(3,("cap: cap_open for %s\n", fname)); capencode(capname, fname); - return SMB_VFS_NEXT_OPEN(handle, conn, capname, flags, mode); + return SMB_VFS_NEXT_OPEN(handle, capname, fsp, flags, mode); } -static int cap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname) +static int cap_rename(vfs_handle_struct *handle, const char *oldname, const char *newname) { pstring capold, capnew; capencode(capold, oldname); capencode(capnew, newname); - return SMB_VFS_NEXT_RENAME(handle, conn, capold, capnew); + return SMB_VFS_NEXT_RENAME(handle, capold, capnew); } -static int cap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf) +static int cap_stat(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf) { pstring capname; capencode(capname, fname); - return SMB_VFS_NEXT_STAT(handle, conn, capname, sbuf); + return SMB_VFS_NEXT_STAT(handle, capname, sbuf); } -static int cap_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) +static int cap_lstat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf) { pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_LSTAT(handle, conn, cappath, sbuf); + return SMB_VFS_NEXT_LSTAT(handle, cappath, sbuf); } -static int cap_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path) +static int cap_unlink(vfs_handle_struct *handle, const char *path) { pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_UNLINK(handle, conn, cappath); + return SMB_VFS_NEXT_UNLINK(handle, cappath); } -static int cap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) +static int cap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode) { pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_CHMOD(handle, conn, cappath, mode); + return SMB_VFS_NEXT_CHMOD(handle, cappath, mode); } -static int cap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid) +static int cap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid) { pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_CHOWN(handle, conn, cappath, uid, gid); + return SMB_VFS_NEXT_CHOWN(handle, cappath, uid, gid); } -static int cap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) +static int cap_chdir(vfs_handle_struct *handle, const char *path) { pstring cappath; DEBUG(3,("cap: cap_chdir for %s\n", path)); capencode(cappath, path); - return SMB_VFS_NEXT_CHDIR(handle, conn, cappath); + return SMB_VFS_NEXT_CHDIR(handle, cappath); } -static int cap_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times) +static int cap_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times) { pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_UTIME(handle, conn, cappath, times); + return SMB_VFS_NEXT_UTIME(handle, cappath, times); } -static BOOL cap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) +static BOOL cap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath) { pstring capoldpath, capnewpath; capencode(capoldpath, oldpath); capencode(capnewpath, newpath); - return SMB_VFS_NEXT_SYMLINK(handle, conn, capoldpath, capnewpath); + return SMB_VFS_NEXT_SYMLINK(handle, capoldpath, capnewpath); } -static BOOL cap_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz) +static BOOL cap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz) { pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_READLINK(handle, conn, cappath, buf, bufsiz); + return SMB_VFS_NEXT_READLINK(handle, cappath, buf, bufsiz); } -static int cap_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) +static int cap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath) { pstring capoldpath, capnewpath; capencode(capoldpath, oldpath); capencode(capnewpath, newpath); - return SMB_VFS_NEXT_LINK(handle, conn, capoldpath, capnewpath); + return SMB_VFS_NEXT_LINK(handle, capoldpath, capnewpath); } -static int cap_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev) +static int cap_mknod(vfs_handle_struct *handle, const char *path, mode_t mode, SMB_DEV_T dev) { pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_MKNOD(handle, conn, cappath, mode, dev); + return SMB_VFS_NEXT_MKNOD(handle, cappath, mode, dev); } -static char *cap_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path) +static char *cap_realpath(vfs_handle_struct *handle, const char *path, char *resolved_path) { /* monyo need capencode'ed and capdecode'ed? */ pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path); + return SMB_VFS_NEXT_REALPATH(handle, path, resolved_path); } static BOOL cap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd) @@ -184,7 +184,7 @@ static BOOL cap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const c return SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, capname, security_info_sent, psd); } -static int cap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode) +static int cap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode) { pstring capname; capencode(capname, name); @@ -194,45 +194,45 @@ static int cap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, con errno = ENOSYS; return -1; } - return SMB_VFS_NEXT_CHMOD_ACL(handle, conn, capname, mode); + return SMB_VFS_NEXT_CHMOD_ACL(handle, capname, mode); } -static SMB_ACL_T cap_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type) +static SMB_ACL_T cap_sys_acl_get_file(vfs_handle_struct *handle, const char *path_p, SMB_ACL_TYPE_T type) { pstring cappath_p; capencode(cappath_p, path_p); - return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, cappath_p, type); + return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, cappath_p, type); } -static int cap_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +static int cap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) { pstring capname; capencode(capname, name); - return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, capname, acltype, theacl); + return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, capname, acltype, theacl); } -static int cap_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path) +static int cap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path) { pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, cappath); + return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, cappath); } -static ssize_t cap_getxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t size) +static ssize_t cap_getxattr(vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t size) { pstring cappath, capname; capencode(cappath, path); capencode(capname, name); - return SMB_VFS_NEXT_GETXATTR(handle, conn, cappath, capname, value, size); + return SMB_VFS_NEXT_GETXATTR(handle, cappath, capname, value, size); } -static ssize_t cap_lgetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t +static ssize_t cap_lgetxattr(vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t size) { pstring cappath, capname; capencode(cappath, path); capencode(capname, name); - return SMB_VFS_NEXT_LGETXATTR(handle, conn, cappath, capname, value, size); + return SMB_VFS_NEXT_LGETXATTR(handle, cappath, capname, value, size); } static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size) @@ -242,34 +242,34 @@ static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp return SMB_VFS_NEXT_FGETXATTR(handle, fsp, fd, capname, value, size); } -static ssize_t cap_listxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size) +static ssize_t cap_listxattr(vfs_handle_struct *handle, const char *path, char *list, size_t size) { pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_LISTXATTR(handle, conn, cappath, list, size); + return SMB_VFS_NEXT_LISTXATTR(handle, cappath, list, size); } -static ssize_t cap_llistxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size) +static ssize_t cap_llistxattr(vfs_handle_struct *handle, const char *path, char *list, size_t size) { pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_LLISTXATTR(handle, conn, cappath, list, size); + return SMB_VFS_NEXT_LLISTXATTR(handle, cappath, list, size); } -static int cap_removexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name) +static int cap_removexattr(vfs_handle_struct *handle, const char *path, const char *name) { pstring cappath, capname; capencode(cappath, path); capencode(capname, name); - return SMB_VFS_NEXT_REMOVEXATTR(handle, conn, cappath, capname); + return SMB_VFS_NEXT_REMOVEXATTR(handle, cappath, capname); } -static int cap_lremovexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name) +static int cap_lremovexattr(vfs_handle_struct *handle, const char *path, const char *name) { pstring cappath, capname; capencode(cappath, path); capencode(capname, name); - return SMB_VFS_NEXT_LREMOVEXATTR(handle, conn, cappath, capname); + return SMB_VFS_NEXT_LREMOVEXATTR(handle, cappath, capname); } static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name) @@ -279,20 +279,20 @@ static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp, return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, fd, capname); } -static int cap_setxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags) +static int cap_setxattr(vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags) { pstring cappath, capname; capencode(cappath, path); capencode(capname, name); - return SMB_VFS_NEXT_SETXATTR(handle, conn, cappath, capname, value, size, flags); + return SMB_VFS_NEXT_SETXATTR(handle, cappath, capname, value, size, flags); } -static int cap_lsetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags) +static int cap_lsetxattr(vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags) { pstring cappath, capname; capencode(cappath, path); capencode(capname, name); - return SMB_VFS_NEXT_LSETXATTR(handle, conn, cappath, capname, value, size, flags); + return SMB_VFS_NEXT_LSETXATTR(handle, cappath, capname, value, size, flags); } static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags) diff --git a/source/modules/vfs_catia.c b/source/modules/vfs_catia.c index 69735de3f43..f5c7e95794f 100644 --- a/source/modules/vfs_catia.c +++ b/source/modules/vfs_catia.c @@ -71,20 +71,20 @@ static void to_unix(char *s) catia_string_replace(s, '\xb1', ' '); } -static SMB_STRUCT_DIR *catia_opendir(vfs_handle_struct *handle, connection_struct - *conn, const char *fname, const char *mask, uint32 attr) +static SMB_STRUCT_DIR *catia_opendir(vfs_handle_struct *handle, + const char *fname, const char *mask, uint32 attr) { pstring name; pstrcpy(name, fname); to_unix(name); - return SMB_VFS_NEXT_OPENDIR(handle, conn, name, mask, attr); + return SMB_VFS_NEXT_OPENDIR(handle, name, mask, attr); } static SMB_STRUCT_DIRENT *catia_readdir(vfs_handle_struct *handle, - connection_struct *conn, SMB_STRUCT_DIR *dirp) + SMB_STRUCT_DIR *dirp) { - SMB_STRUCT_DIRENT *result = SMB_VFS_NEXT_READDIR(handle, conn, dirp); + SMB_STRUCT_DIRENT *result = SMB_VFS_NEXT_READDIR(handle, dirp); if (result == NULL) return result; @@ -93,18 +93,18 @@ static SMB_STRUCT_DIRENT *catia_readdir(vfs_handle_struct *handle, return result; } -static int catia_open(vfs_handle_struct *handle, connection_struct *conn, - const char *fname, int flags, mode_t mode) +static int catia_open(vfs_handle_struct *handle, + const char *fname, files_struct *fsp, int flags, mode_t mode) { pstring name; pstrcpy(name, fname); to_unix(name); - return SMB_VFS_NEXT_OPEN(handle, conn, name, flags, mode); + return SMB_VFS_NEXT_OPEN(handle, name, fsp, flags, mode); } -static int catia_rename(vfs_handle_struct *handle, connection_struct *conn, +static int catia_rename(vfs_handle_struct *handle, const char *oldname, const char *newname) { pstring oname, nname; @@ -117,109 +117,107 @@ static int catia_rename(vfs_handle_struct *handle, connection_struct *conn, DEBUG(10, ("converted old name: %s\n", oname)); DEBUG(10, ("converted new name: %s\n", nname)); - return SMB_VFS_NEXT_RENAME(handle, conn, oname, nname); + return SMB_VFS_NEXT_RENAME(handle, oname, nname); } -static int catia_stat(vfs_handle_struct *handle, connection_struct *conn, +static int catia_stat(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf) { pstring name; pstrcpy(name, fname); to_unix(name); - return SMB_VFS_NEXT_STAT(handle, conn, name, sbuf); + return SMB_VFS_NEXT_STAT(handle, name, sbuf); } -static int catia_lstat(vfs_handle_struct *handle, connection_struct *conn, +static int catia_lstat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf) { pstring name; pstrcpy(name, path); to_unix(name); - return SMB_VFS_NEXT_LSTAT(handle, conn, name, sbuf); + return SMB_VFS_NEXT_LSTAT(handle, name, sbuf); } -static int catia_unlink(vfs_handle_struct *handle, connection_struct *conn, - const char *path) +static int catia_unlink(vfs_handle_struct *handle, const char *path) { pstring name; pstrcpy(name, path); to_unix(name); - return SMB_VFS_NEXT_UNLINK(handle, conn, name); + return SMB_VFS_NEXT_UNLINK(handle, name); } -static int catia_chmod(vfs_handle_struct *handle, connection_struct *conn, +static int catia_chmod(vfs_handle_struct *handle, const char *path, mode_t mode) { pstring name; pstrcpy(name, path); to_unix(name); - return SMB_VFS_NEXT_CHMOD(handle, conn, name, mode); + return SMB_VFS_NEXT_CHMOD(handle, name, mode); } -static int catia_chown(vfs_handle_struct *handle, connection_struct *conn, +static int catia_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid) { pstring name; pstrcpy(name, path); to_unix(name); - return SMB_VFS_NEXT_CHOWN(handle, conn, name, uid, gid); + return SMB_VFS_NEXT_CHOWN(handle, name, uid, gid); } -static int catia_chdir(vfs_handle_struct *handle, connection_struct *conn, +static int catia_chdir(vfs_handle_struct *handle, const char *path) { pstring name; pstrcpy(name, path); to_unix(name); - return SMB_VFS_NEXT_CHDIR(handle, conn, name); + return SMB_VFS_NEXT_CHDIR(handle, name); } -static char *catia_getwd(vfs_handle_struct *handle, connection_struct *conn, - char *buf) +static char *catia_getwd(vfs_handle_struct *handle, char *buf) { - return SMB_VFS_NEXT_GETWD(handle, conn, buf); + return SMB_VFS_NEXT_GETWD(handle, buf); } -static int catia_utime(vfs_handle_struct *handle, connection_struct *conn, +static int catia_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times) { - return SMB_VFS_NEXT_UTIME(handle, conn, path, times); + return SMB_VFS_NEXT_UTIME(handle, path, times); } -static BOOL catia_symlink(vfs_handle_struct *handle, connection_struct *conn, +static BOOL catia_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath) { - return SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath); + return SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath); } -static BOOL catia_readlink(vfs_handle_struct *handle, connection_struct *conn, +static BOOL catia_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz) { - return SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz); + return SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz); } -static int catia_link(vfs_handle_struct *handle, connection_struct *conn, +static int catia_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath) { - return SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath); + return SMB_VFS_NEXT_LINK(handle, oldpath, newpath); } -static int catia_mknod(vfs_handle_struct *handle, connection_struct *conn, +static int catia_mknod(vfs_handle_struct *handle, const char *path, mode_t mode, SMB_DEV_T dev) { - return SMB_VFS_NEXT_MKNOD(handle, conn, path, mode, dev); + return SMB_VFS_NEXT_MKNOD(handle, path, mode, dev); } -static char *catia_realpath(vfs_handle_struct *handle, connection_struct *conn, +static char *catia_realpath(vfs_handle_struct *handle, const char *path, char *resolved_path) { - return SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path); + return SMB_VFS_NEXT_REALPATH(handle, path, resolved_path); } static size_t catia_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, @@ -238,7 +236,7 @@ static BOOL catia_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, psd); } -static int catia_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, +static int catia_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode) { /* If the underlying VFS doesn't have ACL support... */ @@ -246,7 +244,7 @@ static int catia_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, errno = ENOSYS; return -1; } - return SMB_VFS_NEXT_CHMOD_ACL(handle, conn, name, mode); + return SMB_VFS_NEXT_CHMOD_ACL(handle, name, mode); } /* VFS operations structure */ @@ -310,7 +308,7 @@ SMB_VFS_LAYER_TRANSPARENT}, SMB_VFS_LAYER_NOOP} }; -NTSTATUS init_module(void) +NTSTATUS vfs_catia_init(void) { return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "catia", catia_op_tuples); diff --git a/source/modules/vfs_commit.c b/source/modules/vfs_commit.c new file mode 100644 index 00000000000..9d817c017d2 --- /dev/null +++ b/source/modules/vfs_commit.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) James Peach 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +/* Commit data module. + * + * The purpose of this module is to flush data to disk at regular intervals, + * just like the NFS commit operation. There's two rationales for this. First, + * it minimises the data loss in case of a power outage without incurring + * the poor performance of synchronous I/O. Second, a steady flush rate + * can produce better throughput than suddenly dumping massive amounts of + * writes onto a disk. + * + * Tunables: + * + * commit: dthresh Amount of dirty data that can accumulate + * before we commit (sync) it. + * + * commit: debug Debug level at which to emit messages. + * + */ + +#define MODULE "commit" + +static int module_debug; + +struct commit_info +{ + SMB_OFF_T dbytes; /* Dirty (uncommitted) bytes */ + SMB_OFF_T dthresh; /* Dirty data threshold */ +}; + +static void commit_all( + struct vfs_handle_struct * handle, + files_struct * fsp) +{ + struct commit_info *c; + + if ((c = VFS_FETCH_FSP_EXTENSION(handle, fsp))) { + if (c->dbytes) { + DEBUG(module_debug, + ("%s: flushing %lu dirty bytes\n", + MODULE, (unsigned long)c->dbytes)); + + fdatasync(fsp->fh->fd); + c->dbytes = 0; + } + } +} + +static void commit( + struct vfs_handle_struct * handle, + files_struct * fsp, + ssize_t last_write) +{ + struct commit_info *c; + + if ((c = VFS_FETCH_FSP_EXTENSION(handle, fsp))) { + + if (last_write > 0) { + c->dbytes += last_write; + } + + if (c->dbytes > c->dthresh) { + DEBUG(module_debug, + ("%s: flushing %lu dirty bytes\n", + MODULE, (unsigned long)c->dbytes)); + + fdatasync(fsp->fh->fd); + c->dbytes = 0; + } + } +} + +static int commit_connect( + struct vfs_handle_struct * handle, + const char * service, + const char * user) +{ + module_debug = lp_parm_int(SNUM(handle->conn), MODULE, "debug", 100); + return SMB_VFS_NEXT_CONNECT(handle, service, user); +} + +static int commit_open( + vfs_handle_struct * handle, + const char * fname, + files_struct * fsp, + int flags, + mode_t mode) +{ + SMB_OFF_T dthresh; + + /* Don't bother with read-only files. */ + if ((flags & O_ACCMODE) == O_RDONLY) { + return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + } + + dthresh = conv_str_size(lp_parm_const_string(SNUM(handle->conn), + MODULE, "dthresh", NULL)); + + if (dthresh > 0) { + struct commit_info * c; + c = VFS_ADD_FSP_EXTENSION(handle, fsp, struct commit_info); + if (c) { + c->dthresh = dthresh; + c->dbytes = 0; + } + } + + return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); +} + +static ssize_t commit_write( + vfs_handle_struct * handle, + files_struct * fsp, + int fd, + void * data, + size_t count) +{ + ssize_t ret; + + ret = SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, count); + commit(handle, fsp, ret); + + return ret; +} + +static ssize_t commit_pwrite( + vfs_handle_struct * handle, + files_struct * fsp, + int fd, + void * data, + size_t count, + SMB_OFF_T offset) +{ + ssize_t ret; + + ret = SMB_VFS_NEXT_PWRITE(handle, fsp, fd, data, count, offset); + commit(handle, fsp, ret); + + return ret; +} + +static ssize_t commit_close( + vfs_handle_struct * handle, + files_struct * fsp, + int fd) +{ + commit_all(handle, fsp); + return SMB_VFS_NEXT_CLOSE(handle, fsp, fd); +} + +static vfs_op_tuple commit_ops [] = +{ + {SMB_VFS_OP(commit_open), + SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(commit_close), + SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(commit_write), + SMB_VFS_OP_WRITE, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(commit_pwrite), + SMB_VFS_OP_PWRITE, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(commit_connect), + SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_commit_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE, commit_ops); +} + diff --git a/source/modules/vfs_default.c b/source/modules/vfs_default.c new file mode 100644 index 00000000000..82eec46d378 --- /dev/null +++ b/source/modules/vfs_default.c @@ -0,0 +1,1327 @@ +/* + Unix SMB/CIFS implementation. + Wrap disk only vfs functions to sidestep dodgy compilers. + Copyright (C) Tim Potter 1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS + +/* Check for NULL pointer parameters in vfswrap_* functions */ + +/* We don't want to have NULL function pointers lying around. Someone + is sure to try and execute them. These stubs are used to prevent + this possibility. */ + +static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user) +{ + return 0; /* Return >= 0 for success */ +} + +static void vfswrap_disconnect(vfs_handle_struct *handle) +{ +} + +/* Disk operations */ + +static SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, + SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +{ + SMB_BIG_UINT result; + + result = sys_disk_free(handle->conn, path, small_query, bsize, dfree, dsize); + return result; +} + +static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) +{ +#ifdef HAVE_SYS_QUOTAS + int result; + + START_PROFILE(syscall_get_quota); + result = sys_get_quota(handle->conn->connectpath, qtype, id, qt); + END_PROFILE(syscall_get_quota); + return result; +#else + errno = ENOSYS; + return -1; +#endif +} + +static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) +{ +#ifdef HAVE_SYS_QUOTAS + int result; + + START_PROFILE(syscall_set_quota); + result = sys_set_quota(handle->conn->connectpath, qtype, id, qt); + END_PROFILE(syscall_set_quota); + return result; +#else + errno = ENOSYS; + return -1; +#endif +} + +static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels) +{ + errno = ENOSYS; + return -1; /* Not implemented. */ +} + +static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf) +{ + return sys_statvfs(path, statbuf); +} + +/* Directory operations */ + +static SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr) +{ + SMB_STRUCT_DIR *result; + + START_PROFILE(syscall_opendir); + result = sys_opendir(fname); + END_PROFILE(syscall_opendir); + return result; +} + +static SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp) +{ + SMB_STRUCT_DIRENT *result; + + START_PROFILE(syscall_readdir); + result = sys_readdir(dirp); + END_PROFILE(syscall_readdir); + return result; +} + +static void vfswrap_seekdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp, long offset) +{ + START_PROFILE(syscall_seekdir); + sys_seekdir(dirp, offset); + END_PROFILE(syscall_seekdir); +} + +static long vfswrap_telldir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp) +{ + long result; + START_PROFILE(syscall_telldir); + result = sys_telldir(dirp); + END_PROFILE(syscall_telldir); + return result; +} + +static void vfswrap_rewinddir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp) +{ + START_PROFILE(syscall_rewinddir); + sys_rewinddir(dirp); + END_PROFILE(syscall_rewinddir); +} + +static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode) +{ + int result; + BOOL has_dacl = False; + + START_PROFILE(syscall_mkdir); + + if (lp_inherit_acls(SNUM(handle->conn)) && (has_dacl = directory_has_default_acl(handle->conn, parent_dirname(path)))) + mode = 0777; + + result = mkdir(path, mode); + + if (result == 0 && !has_dacl) { + /* + * We need to do this as the default behavior of POSIX ACLs + * is to set the mask to be the requested group permission + * bits, not the group permission bits to be the requested + * group permission bits. This is not what we want, as it will + * mess up any inherited ACL bits that were set. JRA. + */ + int saved_errno = errno; /* We may get ENOSYS */ + if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS)) + errno = saved_errno; + } + + END_PROFILE(syscall_mkdir); + return result; +} + +static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path) +{ + int result; + + START_PROFILE(syscall_rmdir); + result = rmdir(path); + END_PROFILE(syscall_rmdir); + return result; +} + +static int vfswrap_closedir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp) +{ + int result; + + START_PROFILE(syscall_closedir); + result = sys_closedir(dirp); + END_PROFILE(syscall_closedir); + return result; +} + +/* File operations */ + +static int vfswrap_open(vfs_handle_struct *handle, const char *fname, + files_struct *fsp, int flags, mode_t mode) +{ + int result; + + START_PROFILE(syscall_open); + result = sys_open(fname, flags, mode); + END_PROFILE(syscall_open); + return result; +} + +static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp, int fd) +{ + int result; + + START_PROFILE(syscall_close); + + result = close(fd); + END_PROFILE(syscall_close); + return result; +} + +static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n) +{ + ssize_t result; + + START_PROFILE_BYTES(syscall_read, n); + result = sys_read(fd, data, n); + END_PROFILE(syscall_read); + return result; +} + +static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, + size_t n, SMB_OFF_T offset) +{ + ssize_t result; + +#if defined(HAVE_PREAD) || defined(HAVE_PREAD64) + START_PROFILE_BYTES(syscall_pread, n); + result = sys_pread(fd, data, n, offset); + END_PROFILE(syscall_pread); + + if (result == -1 && errno == ESPIPE) { + /* Maintain the fiction that pipes can be seeked (sought?) on. */ + result = SMB_VFS_READ(fsp, fd, data, n); + fsp->fh->pos = 0; + } + +#else /* HAVE_PREAD */ + SMB_OFF_T curr; + int lerrno; + + curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); + if (curr == -1 && errno == ESPIPE) { + /* Maintain the fiction that pipes can be seeked (sought?) on. */ + result = SMB_VFS_READ(fsp, fd, data, n); + fsp->fh->pos = 0; + return result; + } + + if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) { + return -1; + } + + errno = 0; + result = SMB_VFS_READ(fsp, fd, data, n); + lerrno = errno; + + SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET); + errno = lerrno; + +#endif /* HAVE_PREAD */ + + return result; +} + +static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n) +{ + ssize_t result; + + START_PROFILE_BYTES(syscall_write, n); + result = sys_write(fd, data, n); + END_PROFILE(syscall_write); + return result; +} + +static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, + size_t n, SMB_OFF_T offset) +{ + ssize_t result; + +#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64) + START_PROFILE_BYTES(syscall_pwrite, n); + result = sys_pwrite(fd, data, n, offset); + END_PROFILE(syscall_pwrite); + + if (result == -1 && errno == ESPIPE) { + /* Maintain the fiction that pipes can be sought on. */ + result = SMB_VFS_WRITE(fsp, fd, data, n); + } + +#else /* HAVE_PWRITE */ + SMB_OFF_T curr; + int lerrno; + + curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); + if (curr == -1) { + return -1; + } + + if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) { + return -1; + } + + result = SMB_VFS_WRITE(fsp, fd, data, n); + lerrno = errno; + + SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET); + errno = lerrno; + +#endif /* HAVE_PWRITE */ + + return result; +} + +static SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) +{ + SMB_OFF_T result = 0; + + START_PROFILE(syscall_lseek); + + /* Cope with 'stat' file opens. */ + if (filedes != -1) + result = sys_lseek(filedes, offset, whence); + + /* + * We want to maintain the fiction that we can seek + * on a fifo for file system purposes. This allows + * people to set up UNIX fifo's that feed data to Windows + * applications. JRA. + */ + + if((result == -1) && (errno == ESPIPE)) { + result = 0; + errno = 0; + } + + END_PROFILE(syscall_lseek); + return result; +} + +static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *hdr, + SMB_OFF_T offset, size_t n) +{ + ssize_t result; + + START_PROFILE_BYTES(syscall_sendfile, n); + result = sys_sendfile(tofd, fromfd, hdr, offset, n); + END_PROFILE(syscall_sendfile); + return result; +} + +/********************************************************* + For rename across filesystems Patch from Warren Birnbaum + <warrenb@hpcvscdp.cv.hp.com> +**********************************************************/ + +static int copy_reg(const char *source, const char *dest) +{ + SMB_STRUCT_STAT source_stats; + int saved_errno; + int ifd = -1; + int ofd = -1; + + if (sys_lstat (source, &source_stats) == -1) + return -1; + + if (!S_ISREG (source_stats.st_mode)) + return -1; + + if((ifd = sys_open (source, O_RDONLY, 0)) < 0) + return -1; + + if (unlink (dest) && errno != ENOENT) + return -1; + +#ifdef O_NOFOLLOW + if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 ) +#else + if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 ) +#endif + goto err; + + if (transfer_file(ifd, ofd, (size_t)-1) == -1) + goto err; + + /* + * Try to preserve ownership. For non-root it might fail, but that's ok. + * But root probably wants to know, e.g. if NFS disallows it. + */ + +#ifdef HAVE_FCHOWN + if ((fchown(ofd, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM)) +#else + if ((chown(dest, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM)) +#endif + goto err; + + /* + * fchown turns off set[ug]id bits for non-root, + * so do the chmod last. + */ + +#if defined(HAVE_FCHMOD) + if (fchmod (ofd, source_stats.st_mode & 07777)) +#else + if (chmod (dest, source_stats.st_mode & 07777)) +#endif + goto err; + + if (close (ifd) == -1) + goto err; + + if (close (ofd) == -1) + return -1; + + /* Try to copy the old file's modtime and access time. */ + { + struct utimbuf tv; + + tv.actime = source_stats.st_atime; + tv.modtime = source_stats.st_mtime; + utime(dest, &tv); + } + + if (unlink (source) == -1) + return -1; + + return 0; + + err: + + saved_errno = errno; + if (ifd != -1) + close(ifd); + if (ofd != -1) + close(ofd); + errno = saved_errno; + return -1; +} + +static int vfswrap_rename(vfs_handle_struct *handle, const char *oldname, const char *newname) +{ + int result; + + START_PROFILE(syscall_rename); + result = rename(oldname, newname); + if (errno == EXDEV) { + /* Rename across filesystems needed. */ + result = copy_reg(oldname, newname); + } + + END_PROFILE(syscall_rename); + return result; +} + +static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd) +{ +#ifdef HAVE_FSYNC + int result; + + START_PROFILE(syscall_fsync); + result = fsync(fd); + END_PROFILE(syscall_fsync); + return result; +#else + return 0; +#endif +} + +static int vfswrap_stat(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf) +{ + int result; + + START_PROFILE(syscall_stat); + result = sys_stat(fname, sbuf); + END_PROFILE(syscall_stat); + return result; +} + +static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) +{ + int result; + + START_PROFILE(syscall_fstat); + result = sys_fstat(fd, sbuf); + END_PROFILE(syscall_fstat); + return result; +} + +int vfswrap_lstat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf) +{ + int result; + + START_PROFILE(syscall_lstat); + result = sys_lstat(path, sbuf); + END_PROFILE(syscall_lstat); + return result; +} + +static int vfswrap_unlink(vfs_handle_struct *handle, const char *path) +{ + int result; + + START_PROFILE(syscall_unlink); + result = unlink(path); + END_PROFILE(syscall_unlink); + return result; +} + +static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode) +{ + int result; + + START_PROFILE(syscall_chmod); + + /* + * We need to do this due to the fact that the default POSIX ACL + * chmod modifies the ACL *mask* for the group owner, not the + * group owner bits directly. JRA. + */ + + + { + int saved_errno = errno; /* We might get ENOSYS */ + if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) { + END_PROFILE(syscall_chmod); + return result; + } + /* Error - return the old errno. */ + errno = saved_errno; + } + + result = chmod(path, mode); + END_PROFILE(syscall_chmod); + return result; +} + +static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) +{ + int result; + + START_PROFILE(syscall_fchmod); + + /* + * We need to do this due to the fact that the default POSIX ACL + * chmod modifies the ACL *mask* for the group owner, not the + * group owner bits directly. JRA. + */ + + { + int saved_errno = errno; /* We might get ENOSYS */ + if ((result = SMB_VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) { + END_PROFILE(syscall_fchmod); + return result; + } + /* Error - return the old errno. */ + errno = saved_errno; + } + +#if defined(HAVE_FCHMOD) + result = fchmod(fd, mode); +#else + result = -1; + errno = ENOSYS; +#endif + + END_PROFILE(syscall_fchmod); + return result; +} + +static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid) +{ + int result; + + START_PROFILE(syscall_chown); + result = sys_chown(path, uid, gid); + END_PROFILE(syscall_chown); + return result; +} + +static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid) +{ +#ifdef HAVE_FCHOWN + int result; + + START_PROFILE(syscall_fchown); + result = fchown(fd, uid, gid); + END_PROFILE(syscall_fchown); + return result; +#else + errno = ENOSYS; + return -1; +#endif +} + +static int vfswrap_chdir(vfs_handle_struct *handle, const char *path) +{ + int result; + + START_PROFILE(syscall_chdir); + result = chdir(path); + END_PROFILE(syscall_chdir); + return result; +} + +static char *vfswrap_getwd(vfs_handle_struct *handle, char *path) +{ + char *result; + + START_PROFILE(syscall_getwd); + result = sys_getwd(path); + END_PROFILE(syscall_getwd); + return result; +} + +static int vfswrap_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times) +{ + int result; + + START_PROFILE(syscall_utime); + result = utime(path, times); + END_PROFILE(syscall_utime); + return result; +} + +/********************************************************************* + A version of ftruncate that will write the space on disk if strict + allocate is set. +**********************************************************************/ + +static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len) +{ + SMB_STRUCT_STAT st; + SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); + unsigned char zero_space[4096]; + SMB_OFF_T space_to_write; + + if (currpos == -1) + return -1; + + if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) + return -1; + + space_to_write = len - st.st_size; + +#ifdef S_ISFIFO + if (S_ISFIFO(st.st_mode)) + return 0; +#endif + + if (st.st_size == len) + return 0; + + /* Shrink - just ftruncate. */ + if (st.st_size > len) + return sys_ftruncate(fd, len); + + /* Write out the real space on disk. */ + if (SMB_VFS_LSEEK(fsp, fd, st.st_size, SEEK_SET) != st.st_size) + return -1; + + space_to_write = len - st.st_size; + + memset(zero_space, '\0', sizeof(zero_space)); + while ( space_to_write > 0) { + SMB_OFF_T retlen; + SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write); + + retlen = SMB_VFS_WRITE(fsp,fsp->fh->fd,(char *)zero_space,current_len_to_write); + if (retlen <= 0) + return -1; + + space_to_write -= retlen; + } + + /* Seek to where we were */ + if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) + return -1; + + return 0; +} + +static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len) +{ + int result = -1; + SMB_STRUCT_STAT st; + char c = 0; + SMB_OFF_T currpos; + + START_PROFILE(syscall_ftruncate); + + if (lp_strict_allocate(SNUM(fsp->conn))) { + result = strict_allocate_ftruncate(handle, fsp, fd, len); + END_PROFILE(syscall_ftruncate); + return result; + } + + /* we used to just check HAVE_FTRUNCATE_EXTEND and only use + sys_ftruncate if the system supports it. Then I discovered that + you can have some filesystems that support ftruncate + expansion and some that don't! On Linux fat can't do + ftruncate extend but ext2 can. */ + + result = sys_ftruncate(fd, len); + if (result == 0) + goto done; + + /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot + extend a file with ftruncate. Provide alternate implementation + for this */ + currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); + if (currpos == -1) { + goto done; + } + + /* Do an fstat to see if the file is longer than the requested + size in which case the ftruncate above should have + succeeded or shorter, in which case seek to len - 1 and + write 1 byte of zero */ + if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) { + goto done; + } + +#ifdef S_ISFIFO + if (S_ISFIFO(st.st_mode)) { + result = 0; + goto done; + } +#endif + + if (st.st_size == len) { + result = 0; + goto done; + } + + if (st.st_size > len) { + /* the sys_ftruncate should have worked */ + goto done; + } + + if (SMB_VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1) + goto done; + + if (SMB_VFS_WRITE(fsp, fd, &c, 1)!=1) + goto done; + + /* Seek to where we were */ + if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) + goto done; + result = 0; + + done: + + END_PROFILE(syscall_ftruncate); + return result; +} + +static BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) +{ + BOOL result; + + START_PROFILE(syscall_fcntl_lock); + result = fcntl_lock(fd, op, offset, count, type); + END_PROFILE(syscall_fcntl_lock); + return result; +} + +static BOOL vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid) +{ + BOOL result; + + START_PROFILE(syscall_fcntl_getlock); + result = fcntl_getlock(fd, poffset, pcount, ptype, ppid); + END_PROFILE(syscall_fcntl_getlock); + return result; +} + +static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath) +{ + int result; + + START_PROFILE(syscall_symlink); + result = sys_symlink(oldpath, newpath); + END_PROFILE(syscall_symlink); + return result; +} + +static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz) +{ + int result; + + START_PROFILE(syscall_readlink); + result = sys_readlink(path, buf, bufsiz); + END_PROFILE(syscall_readlink); + return result; +} + +static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath) +{ + int result; + + START_PROFILE(syscall_link); + result = sys_link(oldpath, newpath); + END_PROFILE(syscall_link); + return result; +} + +static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev) +{ + int result; + + START_PROFILE(syscall_mknod); + result = sys_mknod(pathname, mode, dev); + END_PROFILE(syscall_mknod); + return result; +} + +static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path, char *resolved_path) +{ + char *result; + + START_PROFILE(syscall_realpath); + result = sys_realpath(path, resolved_path); + END_PROFILE(syscall_realpath); + return result; +} + +static size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, SEC_DESC **ppdesc) +{ + size_t result; + + START_PROFILE(fget_nt_acl); + result = get_nt_acl(fsp, security_info, ppdesc); + END_PROFILE(fget_nt_acl); + return result; +} + +static size_t vfswrap_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, SEC_DESC **ppdesc) +{ + size_t result; + + START_PROFILE(get_nt_acl); + result = get_nt_acl(fsp, security_info, ppdesc); + END_PROFILE(get_nt_acl); + return result; +} + +static BOOL vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd) +{ + BOOL result; + + START_PROFILE(fset_nt_acl); + result = set_nt_acl(fsp, security_info_sent, psd); + END_PROFILE(fset_nt_acl); + return result; +} + +static BOOL vfswrap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd) +{ + BOOL result; + + START_PROFILE(set_nt_acl); + result = set_nt_acl(fsp, security_info_sent, psd); + END_PROFILE(set_nt_acl); + return result; +} + +static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode) +{ +#ifdef HAVE_NO_ACL + errno = ENOSYS; + return -1; +#else + int result; + + START_PROFILE(chmod_acl); + result = chmod_acl(handle->conn, name, mode); + END_PROFILE(chmod_acl); + return result; +#endif +} + +static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) +{ +#ifdef HAVE_NO_ACL + errno = ENOSYS; + return -1; +#else + int result; + + START_PROFILE(fchmod_acl); + result = fchmod_acl(fsp, fd, mode); + END_PROFILE(fchmod_acl); + return result; +#endif +} + +static int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) +{ + return sys_acl_get_entry(theacl, entry_id, entry_p); +} + +static int vfswrap_sys_acl_get_tag_type(vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) +{ + return sys_acl_get_tag_type(entry_d, tag_type_p); +} + +static int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +{ + return sys_acl_get_permset(entry_d, permset_p); +} + +static void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d) +{ + return sys_acl_get_qualifier(entry_d); +} + +static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle, const char *path_p, SMB_ACL_TYPE_T type) +{ + return sys_acl_get_file(path_p, type); +} + +static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) +{ + return sys_acl_get_fd(fd); +} + +static int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset) +{ + return sys_acl_clear_perms(permset); +} + +static int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +{ + return sys_acl_add_perm(permset, perm); +} + +static char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle, SMB_ACL_T theacl, ssize_t *plen) +{ + return sys_acl_to_text(theacl, plen); +} + +static SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle, int count) +{ + return sys_acl_init(count); +} + +static int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) +{ + return sys_acl_create_entry(pacl, pentry); +} + +static int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) +{ + return sys_acl_set_tag_type(entry, tagtype); +} + +static int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, void *qual) +{ + return sys_acl_set_qualifier(entry, qual); +} + +static int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) +{ + return sys_acl_set_permset(entry, permset); +} + +static int vfswrap_sys_acl_valid(vfs_handle_struct *handle, SMB_ACL_T theacl ) +{ + return sys_acl_valid(theacl ); +} + +static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +{ + return sys_acl_set_file(name, acltype, theacl); +} + +static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl) +{ + return sys_acl_set_fd(fd, theacl); +} + +static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path) +{ + return sys_acl_delete_def_file(path); +} + +static int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +{ + return sys_acl_get_perm(permset, perm); +} + +static int vfswrap_sys_acl_free_text(vfs_handle_struct *handle, char *text) +{ + return sys_acl_free_text(text); +} + +static int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle, SMB_ACL_T posix_acl) +{ + return sys_acl_free_acl(posix_acl); +} + +static int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, void *qualifier, SMB_ACL_TAG_T tagtype) +{ + return sys_acl_free_qualifier(qualifier, tagtype); +} + +/**************************************************************** + Extended attribute operations. +*****************************************************************/ + +static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size) +{ + return sys_getxattr(path, name, value, size); +} + +static ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size) +{ + return sys_lgetxattr(path, name, value, size); +} + +static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size) +{ + return sys_fgetxattr(fd, name, value, size); +} + +static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size) +{ + return sys_listxattr(path, list, size); +} + +ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size) +{ + return sys_llistxattr(path, list, size); +} + +ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size) +{ + return sys_flistxattr(fd, list, size); +} + +static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name) +{ + return sys_removexattr(path, name); +} + +static int vfswrap_lremovexattr(struct vfs_handle_struct *handle, const char *path, const char *name) +{ + return sys_lremovexattr(path, name); +} + +static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name) +{ + return sys_fremovexattr(fd, name); +} + +static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags) +{ + return sys_setxattr(path, name, value, size, flags); +} + +static int vfswrap_lsetxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags) +{ + return sys_lsetxattr(path, name, value, size, flags); +} + +static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags) +{ + return sys_fsetxattr(fd, name, value, size, flags); +} + +static int vfswrap_aio_read(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) +{ + return sys_aio_read(aiocb); +} + +static int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) +{ + return sys_aio_write(aiocb); +} + +static ssize_t vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) +{ + return sys_aio_return(aiocb); +} + +static int vfswrap_aio_cancel(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_STRUCT_AIOCB *aiocb) +{ + return sys_aio_cancel(fd, aiocb); +} + +static int vfswrap_aio_error(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) +{ + return sys_aio_error(aiocb); +} + +static int vfswrap_aio_fsync(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb) +{ + return sys_aio_fsync(op, aiocb); +} + +static int vfswrap_aio_suspend(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_AIOCB * const aiocb[], int n, const struct timespec *timeout) +{ + return sys_aio_suspend(aiocb, n, timeout); +} + +static vfs_op_tuple vfs_default_ops[] = { + + /* Disk operations */ + + {SMB_VFS_OP(vfswrap_connect), SMB_VFS_OP_CONNECT, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_disconnect), SMB_VFS_OP_DISCONNECT, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_disk_free), SMB_VFS_OP_DISK_FREE, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_get_quota), SMB_VFS_OP_GET_QUOTA, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_set_quota), SMB_VFS_OP_SET_QUOTA, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_get_shadow_copy_data), SMB_VFS_OP_GET_SHADOW_COPY_DATA, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_statvfs), SMB_VFS_OP_STATVFS, + SMB_VFS_LAYER_OPAQUE}, + + /* Directory operations */ + + {SMB_VFS_OP(vfswrap_opendir), SMB_VFS_OP_OPENDIR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_readdir), SMB_VFS_OP_READDIR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_seekdir), SMB_VFS_OP_SEEKDIR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_telldir), SMB_VFS_OP_TELLDIR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_rewinddir), SMB_VFS_OP_REWINDDIR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_mkdir), SMB_VFS_OP_MKDIR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_rmdir), SMB_VFS_OP_RMDIR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_closedir), SMB_VFS_OP_CLOSEDIR, + SMB_VFS_LAYER_OPAQUE}, + + /* File operations */ + + {SMB_VFS_OP(vfswrap_open), SMB_VFS_OP_OPEN, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_close), SMB_VFS_OP_CLOSE, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_read), SMB_VFS_OP_READ, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_pread), SMB_VFS_OP_PREAD, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_write), SMB_VFS_OP_WRITE, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_pwrite), SMB_VFS_OP_PWRITE, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_lseek), SMB_VFS_OP_LSEEK, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sendfile), SMB_VFS_OP_SENDFILE, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_rename), SMB_VFS_OP_RENAME, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_fsync), SMB_VFS_OP_FSYNC, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_stat), SMB_VFS_OP_STAT, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_fstat), SMB_VFS_OP_FSTAT, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_lstat), SMB_VFS_OP_LSTAT, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_unlink), SMB_VFS_OP_UNLINK, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_chmod), SMB_VFS_OP_CHMOD, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_fchmod), SMB_VFS_OP_FCHMOD, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_chown), SMB_VFS_OP_CHOWN, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_fchown), SMB_VFS_OP_FCHOWN, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_chdir), SMB_VFS_OP_CHDIR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_getwd), SMB_VFS_OP_GETWD, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_utime), SMB_VFS_OP_UTIME, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_ftruncate), SMB_VFS_OP_FTRUNCATE, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_lock), SMB_VFS_OP_LOCK, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_getlock), SMB_VFS_OP_GETLOCK, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_symlink), SMB_VFS_OP_SYMLINK, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_readlink), SMB_VFS_OP_READLINK, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_link), SMB_VFS_OP_LINK, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_mknod), SMB_VFS_OP_MKNOD, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_realpath), SMB_VFS_OP_REALPATH, + SMB_VFS_LAYER_OPAQUE}, + + /* NT ACL operations. */ + + {SMB_VFS_OP(vfswrap_fget_nt_acl), SMB_VFS_OP_FGET_NT_ACL, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_get_nt_acl), SMB_VFS_OP_GET_NT_ACL, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_fset_nt_acl), SMB_VFS_OP_FSET_NT_ACL, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_set_nt_acl), SMB_VFS_OP_SET_NT_ACL, + SMB_VFS_LAYER_OPAQUE}, + + /* POSIX ACL operations. */ + + {SMB_VFS_OP(vfswrap_chmod_acl), SMB_VFS_OP_CHMOD_ACL, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_fchmod_acl), SMB_VFS_OP_FCHMOD_ACL, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_get_entry), SMB_VFS_OP_SYS_ACL_GET_ENTRY, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_get_tag_type), SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_get_permset), SMB_VFS_OP_SYS_ACL_GET_PERMSET, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_get_qualifier), SMB_VFS_OP_SYS_ACL_GET_QUALIFIER, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_get_file), SMB_VFS_OP_SYS_ACL_GET_FILE, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_get_fd), SMB_VFS_OP_SYS_ACL_GET_FD, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_clear_perms), SMB_VFS_OP_SYS_ACL_CLEAR_PERMS, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_add_perm), SMB_VFS_OP_SYS_ACL_ADD_PERM, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_to_text), SMB_VFS_OP_SYS_ACL_TO_TEXT, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_init), SMB_VFS_OP_SYS_ACL_INIT, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_create_entry), SMB_VFS_OP_SYS_ACL_CREATE_ENTRY, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_set_tag_type), SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_set_qualifier), SMB_VFS_OP_SYS_ACL_SET_QUALIFIER, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_set_permset), SMB_VFS_OP_SYS_ACL_SET_PERMSET, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_valid), SMB_VFS_OP_SYS_ACL_VALID, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_set_file), SMB_VFS_OP_SYS_ACL_SET_FILE, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_set_fd), SMB_VFS_OP_SYS_ACL_SET_FD, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_delete_def_file), SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_get_perm), SMB_VFS_OP_SYS_ACL_GET_PERM, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_free_text), SMB_VFS_OP_SYS_ACL_FREE_TEXT, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_free_acl), SMB_VFS_OP_SYS_ACL_FREE_ACL, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_sys_acl_free_qualifier), SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER, + SMB_VFS_LAYER_OPAQUE}, + + /* EA operations. */ + + {SMB_VFS_OP(vfswrap_getxattr), SMB_VFS_OP_GETXATTR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_lgetxattr), SMB_VFS_OP_LGETXATTR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_fgetxattr), SMB_VFS_OP_FGETXATTR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_listxattr), SMB_VFS_OP_LISTXATTR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_llistxattr), SMB_VFS_OP_LLISTXATTR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_flistxattr), SMB_VFS_OP_FLISTXATTR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_removexattr), SMB_VFS_OP_REMOVEXATTR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_lremovexattr), SMB_VFS_OP_LREMOVEXATTR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_fremovexattr), SMB_VFS_OP_FREMOVEXATTR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_setxattr), SMB_VFS_OP_SETXATTR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_lsetxattr), SMB_VFS_OP_LSETXATTR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_fsetxattr), SMB_VFS_OP_FSETXATTR, + SMB_VFS_LAYER_OPAQUE}, + + {SMB_VFS_OP(vfswrap_aio_read), SMB_VFS_OP_AIO_READ, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_aio_write), SMB_VFS_OP_AIO_WRITE, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_aio_return), SMB_VFS_OP_AIO_RETURN, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_aio_cancel), SMB_VFS_OP_AIO_CANCEL, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_aio_error), SMB_VFS_OP_AIO_ERROR, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_aio_fsync), SMB_VFS_OP_AIO_FSYNC, + SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(vfswrap_aio_suspend),SMB_VFS_OP_AIO_SUSPEND, + SMB_VFS_LAYER_OPAQUE}, + + /* Finish VFS operations definition */ + + {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, + SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_default_init(void) +{ + unsigned int needed = SMB_VFS_OP_LAST + 1; /* convert from index to count */ + + if (ARRAY_SIZE(vfs_default_ops) != needed) { + DEBUG(0, ("%s: %u ops registered, but %u ops are required\n", + DEFAULT_VFS_MODULE_NAME, (unsigned int)ARRAY_SIZE(vfs_default_ops), needed)); + smb_panic("operation(s) missing from default VFS module"); + } + + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, + DEFAULT_VFS_MODULE_NAME, vfs_default_ops); +} diff --git a/source/modules/vfs_default_quota.c b/source/modules/vfs_default_quota.c index 9922a30315d..55dc287b88a 100644 --- a/source/modules/vfs_default_quota.c +++ b/source/modules/vfs_default_quota.c @@ -92,11 +92,11 @@ #define DEFAULT_QUOTA_GID_NOLIMIT(handle) \ lp_parm_bool(SNUM((handle)->conn),DEFAULT_QUOTA_NAME,"gid nolimit",DEFAULT_QUOTA_GID_NOLIMIT_DEFAULT) -static int default_quota_get_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq) +static int default_quota_get_quota(vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq) { int ret = -1; - if ((ret=SMB_VFS_NEXT_GET_QUOTA(handle, conn, qtype, id, dq))!=0) { + if ((ret=SMB_VFS_NEXT_GET_QUOTA(handle, qtype, id, dq))!=0) { return ret; } @@ -122,7 +122,7 @@ static int default_quota_get_quota(vfs_handle_struct *handle, connection_struct unid_t qid; uint32 qflags = dq->qflags; qid.uid = DEFAULT_QUOTA_UID(handle); - SMB_VFS_NEXT_GET_QUOTA(handle, conn, SMB_USER_QUOTA_TYPE, qid, dq); + SMB_VFS_NEXT_GET_QUOTA(handle, SMB_USER_QUOTA_TYPE, qid, dq); dq->qflags = qflags; } break; @@ -132,7 +132,7 @@ static int default_quota_get_quota(vfs_handle_struct *handle, connection_struct unid_t qid; uint32 qflags = dq->qflags; qid.gid = DEFAULT_QUOTA_GID(handle); - SMB_VFS_NEXT_GET_QUOTA(handle, conn, SMB_GROUP_QUOTA_TYPE, qid, dq); + SMB_VFS_NEXT_GET_QUOTA(handle, SMB_GROUP_QUOTA_TYPE, qid, dq); dq->qflags = qflags; } break; @@ -146,7 +146,7 @@ static int default_quota_get_quota(vfs_handle_struct *handle, connection_struct return ret; } -static int default_quota_set_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq) +static int default_quota_set_quota(vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq) { int ret = -1; @@ -179,7 +179,7 @@ static int default_quota_set_quota(vfs_handle_struct *handle, connection_struct break; } - if ((ret=SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, dq))!=0) { + if ((ret=SMB_VFS_NEXT_SET_QUOTA(handle, qtype, id, dq))!=0) { return ret; } @@ -194,7 +194,7 @@ static int default_quota_set_quota(vfs_handle_struct *handle, connection_struct { unid_t qid; qid.uid = DEFAULT_QUOTA_UID(handle); - ret = SMB_VFS_NEXT_SET_QUOTA(handle, conn, SMB_USER_QUOTA_TYPE, qid, dq); + ret = SMB_VFS_NEXT_SET_QUOTA(handle, SMB_USER_QUOTA_TYPE, qid, dq); } break; #ifdef HAVE_GROUP_QUOTA @@ -202,7 +202,7 @@ static int default_quota_set_quota(vfs_handle_struct *handle, connection_struct { unid_t qid; qid.gid = DEFAULT_QUOTA_GID(handle); - ret = SMB_VFS_NEXT_SET_QUOTA(handle, conn, SMB_GROUP_QUOTA_TYPE, qid, dq); + ret = SMB_VFS_NEXT_SET_QUOTA(handle, SMB_GROUP_QUOTA_TYPE, qid, dq); } break; #endif /* HAVE_GROUP_QUOTA */ diff --git a/source/modules/vfs_expand_msdfs.c b/source/modules/vfs_expand_msdfs.c index d22f6a7f98e..fdd9ac6fbd8 100644 --- a/source/modules/vfs_expand_msdfs.c +++ b/source/modules/vfs_expand_msdfs.c @@ -110,6 +110,7 @@ static BOOL expand_msdfs_target(connection_struct* conn, pstring target) int filename_len; pstring targethost; pstring new_target; + extern userdom_struct current_user_info; if (filename_start == NULL) { DEBUG(10, ("No filename start in %s\n", target)); @@ -135,7 +136,11 @@ static BOOL expand_msdfs_target(connection_struct* conn, pstring target) return False; } - standard_sub_conn(conn, mapfilename, sizeof(mapfilename)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + mapfilename, sizeof(mapfilename)); DEBUG(10, ("Expanded targethost to %s\n", targethost)); @@ -150,13 +155,12 @@ static BOOL expand_msdfs_target(connection_struct* conn, pstring target) } static int expand_msdfs_readlink(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, char *buf, size_t bufsiz) { pstring target; int result; - result = SMB_VFS_NEXT_READLINK(handle, conn, path, target, + result = SMB_VFS_NEXT_READLINK(handle, path, target, sizeof(target)); if (result < 0) @@ -166,7 +170,7 @@ static int expand_msdfs_readlink(struct vfs_handle_struct *handle, if ((strncmp(target, "msdfs:", strlen("msdfs:")) == 0) && (strchr_m(target, '@') != NULL)) { - if (!expand_msdfs_target(conn, target)) { + if (!expand_msdfs_target(handle->conn, target)) { errno = ENOENT; return -1; } diff --git a/source/modules/vfs_extd_audit.c b/source/modules/vfs_extd_audit.c index cb8c3ffd6ab..1c3b25103c8 100644 --- a/source/modules/vfs_extd_audit.c +++ b/source/modules/vfs_extd_audit.c @@ -32,17 +32,17 @@ static int vfs_extd_audit_debug_level = DBGC_VFS; /* Function prototypes */ -static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user); -static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn); -static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr); -static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode); -static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path); -static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode); +static int audit_connect(vfs_handle_struct *handle, const char *svc, const char *user); +static void audit_disconnect(vfs_handle_struct *handle); +static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr); +static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode); +static int audit_rmdir(vfs_handle_struct *handle, const char *path); +static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode); static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd); -static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname); -static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path); -static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode); -static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode); +static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname); +static int audit_unlink(vfs_handle_struct *handle, const char *path); +static int audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode); +static int audit_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode); static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode); static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode); @@ -123,7 +123,7 @@ static int audit_syslog_priority(vfs_handle_struct *handle) /* Implementation of vfs_ops. Pass everything on to the default operation but log event first. */ -static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user) +static int audit_connect(vfs_handle_struct *handle, const char *svc, const char *user) { int result; @@ -134,25 +134,25 @@ static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, con DEBUG(10, ("Connected to service %s as user %s\n", svc, user)); - result = SMB_VFS_NEXT_CONNECT(handle, conn, svc, user); + result = SMB_VFS_NEXT_CONNECT(handle, svc, user); return result; } -static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn) +static void audit_disconnect(vfs_handle_struct *handle) { syslog(audit_syslog_priority(handle), "disconnected\n"); DEBUG(10, ("Disconnected from VFS module extd_audit\n")); - SMB_VFS_NEXT_DISCONNECT(handle, conn); + SMB_VFS_NEXT_DISCONNECT(handle); return; } -static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr) +static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr) { SMB_STRUCT_DIR *result; - result = SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr); + result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); syslog(audit_syslog_priority(handle), "opendir %s %s%s\n", fname, @@ -166,11 +166,11 @@ static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struc return result; } -static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) +static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode) { int result; - result = SMB_VFS_NEXT_MKDIR(handle, conn, path, mode); + result = SMB_VFS_NEXT_MKDIR(handle, path, mode); syslog(audit_syslog_priority(handle), "mkdir %s %s%s\n", path, @@ -184,11 +184,11 @@ static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const return result; } -static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) +static int audit_rmdir(vfs_handle_struct *handle, const char *path) { int result; - result = SMB_VFS_NEXT_RMDIR(handle, conn, path); + result = SMB_VFS_NEXT_RMDIR(handle, path); syslog(audit_syslog_priority(handle), "rmdir %s %s%s\n", path, @@ -202,11 +202,11 @@ static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const return result; } -static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode) +static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode) { int result; - result = SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode); + result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); syslog(audit_syslog_priority(handle), "open %s (fd %d) %s%s%s\n", fname, result, @@ -239,11 +239,11 @@ static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd) return result; } -static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname) +static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname) { int result; - result = SMB_VFS_NEXT_RENAME(handle, conn, oldname, newname); + result = SMB_VFS_NEXT_RENAME(handle, oldname, newname); syslog(audit_syslog_priority(handle), "rename %s -> %s %s%s\n", oldname, newname, @@ -257,11 +257,11 @@ static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, cons return result; } -static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path) +static int audit_unlink(vfs_handle_struct *handle, const char *path) { int result; - result = SMB_VFS_NEXT_UNLINK(handle, conn, path); + result = SMB_VFS_NEXT_UNLINK(handle, path); syslog(audit_syslog_priority(handle), "unlink %s %s%s\n", path, @@ -275,11 +275,11 @@ static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, cons return result; } -static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) +static int audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode) { int result; - result = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode); + result = SMB_VFS_NEXT_CHMOD(handle, path, mode); syslog(audit_syslog_priority(handle), "chmod %s mode 0x%x %s%s\n", path, mode, @@ -293,11 +293,11 @@ static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const return result; } -static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) +static int audit_chmod_acl(vfs_handle_struct *handle, const char *path, mode_t mode) { int result; - result = SMB_VFS_NEXT_CHMOD_ACL(handle, conn, path, mode); + result = SMB_VFS_NEXT_CHMOD_ACL(handle, path, mode); syslog(audit_syslog_priority(handle), "chmod_acl %s mode 0x%x %s%s\n", path, mode, diff --git a/source/modules/vfs_fake_perms.c b/source/modules/vfs_fake_perms.c index decbe01d3ca..8bd8bbf5321 100644 --- a/source/modules/vfs_fake_perms.c +++ b/source/modules/vfs_fake_perms.c @@ -29,11 +29,11 @@ extern struct current_user current_user; #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS -static int fake_perms_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf) +static int fake_perms_stat(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf) { int ret = -1; - ret = SMB_VFS_NEXT_STAT(handle, conn, fname, sbuf); + ret = SMB_VFS_NEXT_STAT(handle, fname, sbuf); if (ret == 0) { if (S_ISDIR(sbuf->st_mode)) { sbuf->st_mode = S_IFDIR | S_IRWXU; diff --git a/source/modules/vfs_full_audit.c b/source/modules/vfs_full_audit.c index b9ffd6fc05f..fd15c5c3585 100644 --- a/source/modules/vfs_full_audit.c +++ b/source/modules/vfs_full_audit.c @@ -72,48 +72,44 @@ struct vfs_full_audit_private_data { /* Function prototypes */ -static int smb_full_audit_connect(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_connect(vfs_handle_struct *handle, const char *svc, const char *user); -static void smb_full_audit_disconnect(vfs_handle_struct *handle, - connection_struct *conn); +static void smb_full_audit_disconnect(vfs_handle_struct *handle); static SMB_BIG_UINT smb_full_audit_disk_free(vfs_handle_struct *handle, - connection_struct *conn, const char *path, + const char *path, BOOL small_query, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); static int smb_full_audit_get_quota(struct vfs_handle_struct *handle, - struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt); static int smb_full_audit_set_quota(struct vfs_handle_struct *handle, - struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt); static int smb_full_audit_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels); static int smb_full_audit_statvfs(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, struct vfs_statvfs_struct *statbuf); -static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle, connection_struct *conn, +static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr); static SMB_STRUCT_DIRENT *smb_full_audit_readdir(vfs_handle_struct *handle, - connection_struct *conn, SMB_STRUCT_DIR *dirp); -static void smb_full_audit_seekdir(vfs_handle_struct *handle, connection_struct *conn, + SMB_STRUCT_DIR *dirp); +static void smb_full_audit_seekdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp, long offset); -static long smb_full_audit_telldir(vfs_handle_struct *handle, connection_struct *conn, +static long smb_full_audit_telldir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp); -static void smb_full_audit_rewinddir(vfs_handle_struct *handle, connection_struct *conn, +static void smb_full_audit_rewinddir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp); -static int smb_full_audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode); -static int smb_full_audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_rmdir(vfs_handle_struct *handle, const char *path); -static int smb_full_audit_closedir(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_closedir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp); -static int smb_full_audit_open(vfs_handle_struct *handle, connection_struct *conn, - const char *fname, int flags, mode_t mode); +static int smb_full_audit_open(vfs_handle_struct *handle, + const char *fname, files_struct *fsp, int flags, mode_t mode); static int smb_full_audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd); static ssize_t smb_full_audit_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n); @@ -130,30 +126,30 @@ static ssize_t smb_full_audit_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *hdr, SMB_OFF_T offset, size_t n); -static int smb_full_audit_rename(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname); static int smb_full_audit_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd); -static int smb_full_audit_stat(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_stat(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf); static int smb_full_audit_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf); -static int smb_full_audit_lstat(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_lstat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf); -static int smb_full_audit_unlink(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_unlink(vfs_handle_struct *handle, const char *path); -static int smb_full_audit_chmod(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode); static int smb_full_audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode); -static int smb_full_audit_chown(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid); static int smb_full_audit_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid); -static int smb_full_audit_chdir(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_chdir(vfs_handle_struct *handle, const char *path); -static char *smb_full_audit_getwd(vfs_handle_struct *handle, connection_struct *conn, +static char *smb_full_audit_getwd(vfs_handle_struct *handle, char *path); -static int smb_full_audit_utime(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times); static int smb_full_audit_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len); @@ -161,15 +157,15 @@ static BOOL smb_full_audit_lock(vfs_handle_struct *handle, files_struct *fsp, in int op, SMB_OFF_T offset, SMB_OFF_T count, int type); static BOOL smb_full_audit_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid); -static int smb_full_audit_symlink(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath); -static int smb_full_audit_readlink(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz); -static int smb_full_audit_link(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath); -static int smb_full_audit_mknod(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev); -static char *smb_full_audit_realpath(vfs_handle_struct *handle, connection_struct *conn, +static char *smb_full_audit_realpath(vfs_handle_struct *handle, const char *path, char *resolved_path); static size_t smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, @@ -183,120 +179,99 @@ static BOOL smb_full_audit_fset_nt_acl(vfs_handle_struct *handle, files_struct * static BOOL smb_full_audit_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd); -static int smb_full_audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_chmod_acl(vfs_handle_struct *handle, const char *path, mode_t mode); static int smb_full_audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode); static int smb_full_audit_sys_acl_get_entry(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p); static int smb_full_audit_sys_acl_get_tag_type(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p); static int smb_full_audit_sys_acl_get_permset(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p); static void * smb_full_audit_sys_acl_get_qualifier(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_ENTRY_T entry_d); static SMB_ACL_T smb_full_audit_sys_acl_get_file(vfs_handle_struct *handle, - connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type); static SMB_ACL_T smb_full_audit_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd); static int smb_full_audit_sys_acl_clear_perms(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_PERMSET_T permset); static int smb_full_audit_sys_acl_add_perm(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm); static char * smb_full_audit_sys_acl_to_text(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_T theacl, + SMB_ACL_T theacl, ssize_t *plen); static SMB_ACL_T smb_full_audit_sys_acl_init(vfs_handle_struct *handle, - connection_struct *conn, int count); static int smb_full_audit_sys_acl_create_entry(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_T *pacl, + SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry); static int smb_full_audit_sys_acl_set_tag_type(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype); static int smb_full_audit_sys_acl_set_qualifier(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual); static int smb_full_audit_sys_acl_set_permset(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset); static int smb_full_audit_sys_acl_valid(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_T theacl ); static int smb_full_audit_sys_acl_set_file(vfs_handle_struct *handle, - connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl); static int smb_full_audit_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl); static int smb_full_audit_sys_acl_delete_def_file(vfs_handle_struct *handle, - connection_struct *conn, const char *path); static int smb_full_audit_sys_acl_get_perm(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm); static int smb_full_audit_sys_acl_free_text(vfs_handle_struct *handle, - connection_struct *conn, char *text); static int smb_full_audit_sys_acl_free_acl(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_T posix_acl); static int smb_full_audit_sys_acl_free_qualifier(vfs_handle_struct *handle, - connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype); static ssize_t smb_full_audit_getxattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, + const char *path, const char *name, void *value, size_t size); static ssize_t smb_full_audit_lgetxattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, const char *name, void *value, size_t size); static ssize_t smb_full_audit_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, const char *name, void *value, size_t size); static ssize_t smb_full_audit_listxattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, char *list, size_t size); static ssize_t smb_full_audit_llistxattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, char *list, size_t size); static ssize_t smb_full_audit_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, char *list, size_t size); static int smb_full_audit_removexattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, + const char *path, const char *name); static int smb_full_audit_lremovexattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, + const char *path, const char *name); static int smb_full_audit_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, const char *name); static int smb_full_audit_setxattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, + const char *path, const char *name, const void *value, size_t size, int flags); static int smb_full_audit_lsetxattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, + const char *path, const char *name, const void *value, size_t size, int flags); static int smb_full_audit_fsetxattr(struct vfs_handle_struct *handle, @@ -666,10 +641,15 @@ static int audit_syslog_priority(vfs_handle_struct *handle) static char *audit_prefix(connection_struct *conn) { static pstring prefix; + extern userdom_struct current_user_info; pstrcpy(prefix, lp_parm_const_string(SNUM(conn), "full_audit", "prefix", "%u|%I")); - standard_sub_snum(SNUM(conn), prefix, sizeof(prefix)-1); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + prefix, sizeof(prefix)); return prefix; } @@ -811,7 +791,7 @@ static void free_private_data(void **p_data) /* Implementation of vfs_ops. Pass everything on to the default operation but log event first. */ -static int smb_full_audit_connect(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_connect(vfs_handle_struct *handle, const char *svc, const char *user) { int result; @@ -832,17 +812,17 @@ static int smb_full_audit_connect(vfs_handle_struct *handle, connection_struct * openlog("smbd_audit", 0, audit_syslog_facility(handle)); init_bitmap(&pd->success_ops, - lp_parm_string_list(SNUM(conn), "full_audit", "success", + lp_parm_string_list(SNUM(handle->conn), "full_audit", "success", none)); init_bitmap(&pd->failure_ops, - lp_parm_string_list(SNUM(conn), "full_audit", "failure", + lp_parm_string_list(SNUM(handle->conn), "full_audit", "failure", all)); /* Store the private data. */ SMB_VFS_HANDLE_SET_DATA(handle, pd, free_private_data, struct vfs_full_audit_private_data, return -1); - result = SMB_VFS_NEXT_CONNECT(handle, conn, svc, user); + result = SMB_VFS_NEXT_CONNECT(handle, svc, user); do_log(SMB_VFS_OP_CONNECT, True, handle, "%s", svc); @@ -850,13 +830,12 @@ static int smb_full_audit_connect(vfs_handle_struct *handle, connection_struct * return result; } -static void smb_full_audit_disconnect(vfs_handle_struct *handle, - connection_struct *conn) +static void smb_full_audit_disconnect(vfs_handle_struct *handle) { - SMB_VFS_NEXT_DISCONNECT(handle, conn); + SMB_VFS_NEXT_DISCONNECT(handle); do_log(SMB_VFS_OP_DISCONNECT, True, handle, - "%s", lp_servicename(SNUM(conn))); + "%s", lp_servicename(SNUM(handle->conn))); /* The bitmaps will be disconnected when the private data is deleted. */ @@ -865,13 +844,13 @@ static void smb_full_audit_disconnect(vfs_handle_struct *handle, } static SMB_BIG_UINT smb_full_audit_disk_free(vfs_handle_struct *handle, - connection_struct *conn, const char *path, + const char *path, BOOL small_query, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { SMB_BIG_UINT result; - result = SMB_VFS_NEXT_DISK_FREE(handle, conn, path, small_query, bsize, + result = SMB_VFS_NEXT_DISK_FREE(handle, path, small_query, bsize, dfree, dsize); /* Don't have a reasonable notion of failure here */ @@ -882,13 +861,12 @@ static SMB_BIG_UINT smb_full_audit_disk_free(vfs_handle_struct *handle, } static int smb_full_audit_get_quota(struct vfs_handle_struct *handle, - struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) { int result; - result = SMB_VFS_NEXT_GET_QUOTA(handle, conn, qtype, id, qt); + result = SMB_VFS_NEXT_GET_QUOTA(handle, qtype, id, qt); do_log(SMB_VFS_OP_GET_QUOTA, (result >= 0), handle, ""); @@ -897,13 +875,12 @@ static int smb_full_audit_get_quota(struct vfs_handle_struct *handle, static int smb_full_audit_set_quota(struct vfs_handle_struct *handle, - struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) { int result; - result = SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, qt); + result = SMB_VFS_NEXT_SET_QUOTA(handle, qtype, id, qt); do_log(SMB_VFS_OP_SET_QUOTA, (result >= 0), handle, ""); @@ -924,25 +901,24 @@ static int smb_full_audit_get_shadow_copy_data(struct vfs_handle_struct *handle, } static int smb_full_audit_statvfs(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, struct vfs_statvfs_struct *statbuf) { int result; - result = SMB_VFS_NEXT_STATVFS(handle, conn, path, statbuf); + result = SMB_VFS_NEXT_STATVFS(handle, path, statbuf); do_log(SMB_VFS_OP_STATVFS, (result >= 0), handle, ""); return result; } -static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle, connection_struct *conn, +static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr) { SMB_STRUCT_DIR *result; - result = SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr); + result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); do_log(SMB_VFS_OP_OPENDIR, (result != NULL), handle, "%s", fname); @@ -950,11 +926,11 @@ static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle, connect } static SMB_STRUCT_DIRENT *smb_full_audit_readdir(vfs_handle_struct *handle, - connection_struct *conn, SMB_STRUCT_DIR *dirp) + SMB_STRUCT_DIR *dirp) { SMB_STRUCT_DIRENT *result; - result = SMB_VFS_NEXT_READDIR(handle, conn, dirp); + result = SMB_VFS_NEXT_READDIR(handle, dirp); /* This operation has no reasonable error condition * (End of dir is also failure), so always succeed. @@ -964,78 +940,78 @@ static SMB_STRUCT_DIRENT *smb_full_audit_readdir(vfs_handle_struct *handle, return result; } -static void smb_full_audit_seekdir(vfs_handle_struct *handle, connection_struct *conn, +static void smb_full_audit_seekdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp, long offset) { - SMB_VFS_NEXT_SEEKDIR(handle, conn, dirp, offset); + SMB_VFS_NEXT_SEEKDIR(handle, dirp, offset); do_log(SMB_VFS_OP_SEEKDIR, True, handle, ""); return; } -static long smb_full_audit_telldir(vfs_handle_struct *handle, connection_struct *conn, +static long smb_full_audit_telldir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp) { long result; - result = SMB_VFS_NEXT_TELLDIR(handle, conn, dirp); + result = SMB_VFS_NEXT_TELLDIR(handle, dirp); do_log(SMB_VFS_OP_TELLDIR, True, handle, ""); return result; } -static void smb_full_audit_rewinddir(vfs_handle_struct *handle, connection_struct *conn, +static void smb_full_audit_rewinddir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp) { - SMB_VFS_NEXT_REWINDDIR(handle, conn, dirp); + SMB_VFS_NEXT_REWINDDIR(handle, dirp); do_log(SMB_VFS_OP_REWINDDIR, True, handle, ""); return; } -static int smb_full_audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode) { int result; - result = SMB_VFS_NEXT_MKDIR(handle, conn, path, mode); + result = SMB_VFS_NEXT_MKDIR(handle, path, mode); do_log(SMB_VFS_OP_MKDIR, (result >= 0), handle, "%s", path); return result; } -static int smb_full_audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_rmdir(vfs_handle_struct *handle, const char *path) { int result; - result = SMB_VFS_NEXT_RMDIR(handle, conn, path); + result = SMB_VFS_NEXT_RMDIR(handle, path); do_log(SMB_VFS_OP_RMDIR, (result >= 0), handle, "%s", path); return result; } -static int smb_full_audit_closedir(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_closedir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp) { int result; - result = SMB_VFS_NEXT_CLOSEDIR(handle, conn, dirp); + result = SMB_VFS_NEXT_CLOSEDIR(handle, dirp); do_log(SMB_VFS_OP_CLOSEDIR, (result >= 0), handle, ""); return result; } -static int smb_full_audit_open(vfs_handle_struct *handle, connection_struct *conn, - const char *fname, int flags, mode_t mode) +static int smb_full_audit_open(vfs_handle_struct *handle, + const char *fname, files_struct *fsp, int flags, mode_t mode) { int result; - result = SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode); + result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); do_log(SMB_VFS_OP_OPEN, (result >= 0), handle, "%s|%s", ((flags & O_WRONLY) || (flags & O_RDWR))?"w":"r", @@ -1133,12 +1109,12 @@ static ssize_t smb_full_audit_sendfile(vfs_handle_struct *handle, int tofd, return result; } -static int smb_full_audit_rename(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname) { int result; - result = SMB_VFS_NEXT_RENAME(handle, conn, oldname, newname); + result = SMB_VFS_NEXT_RENAME(handle, oldname, newname); do_log(SMB_VFS_OP_RENAME, (result >= 0), handle, "%s|%s", oldname, newname); @@ -1156,12 +1132,12 @@ static int smb_full_audit_fsync(vfs_handle_struct *handle, files_struct *fsp, in return result; } -static int smb_full_audit_stat(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_stat(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf) { int result; - result = SMB_VFS_NEXT_STAT(handle, conn, fname, sbuf); + result = SMB_VFS_NEXT_STAT(handle, fname, sbuf); do_log(SMB_VFS_OP_STAT, (result >= 0), handle, "%s", fname); @@ -1180,36 +1156,36 @@ static int smb_full_audit_fstat(vfs_handle_struct *handle, files_struct *fsp, in return result; } -static int smb_full_audit_lstat(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_lstat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf) { int result; - result = SMB_VFS_NEXT_LSTAT(handle, conn, path, sbuf); + result = SMB_VFS_NEXT_LSTAT(handle, path, sbuf); do_log(SMB_VFS_OP_LSTAT, (result >= 0), handle, "%s", path); return result; } -static int smb_full_audit_unlink(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_unlink(vfs_handle_struct *handle, const char *path) { int result; - result = SMB_VFS_NEXT_UNLINK(handle, conn, path); + result = SMB_VFS_NEXT_UNLINK(handle, path); do_log(SMB_VFS_OP_UNLINK, (result >= 0), handle, "%s", path); return result; } -static int smb_full_audit_chmod(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode) { int result; - result = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode); + result = SMB_VFS_NEXT_CHMOD(handle, path, mode); do_log(SMB_VFS_OP_CHMOD, (result >= 0), handle, "%s|%o", path, mode); @@ -1229,12 +1205,12 @@ static int smb_full_audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, i return result; } -static int smb_full_audit_chown(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid) { int result; - result = SMB_VFS_NEXT_CHOWN(handle, conn, path, uid, gid); + result = SMB_VFS_NEXT_CHOWN(handle, path, uid, gid); do_log(SMB_VFS_OP_CHOWN, (result >= 0), handle, "%s|%ld|%ld", path, (long int)uid, (long int)gid); @@ -1255,36 +1231,36 @@ static int smb_full_audit_fchown(vfs_handle_struct *handle, files_struct *fsp, i return result; } -static int smb_full_audit_chdir(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_chdir(vfs_handle_struct *handle, const char *path) { int result; - result = SMB_VFS_NEXT_CHDIR(handle, conn, path); + result = SMB_VFS_NEXT_CHDIR(handle, path); do_log(SMB_VFS_OP_CHDIR, (result >= 0), handle, "chdir|%s", path); return result; } -static char *smb_full_audit_getwd(vfs_handle_struct *handle, connection_struct *conn, +static char *smb_full_audit_getwd(vfs_handle_struct *handle, char *path) { char *result; - result = SMB_VFS_NEXT_GETWD(handle, conn, path); + result = SMB_VFS_NEXT_GETWD(handle, path); do_log(SMB_VFS_OP_GETWD, (result != NULL), handle, "%s", path); return result; } -static int smb_full_audit_utime(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times) { int result; - result = SMB_VFS_NEXT_UTIME(handle, conn, path, times); + result = SMB_VFS_NEXT_UTIME(handle, path, times); do_log(SMB_VFS_OP_UTIME, (result >= 0), handle, "%s", path); @@ -1328,12 +1304,12 @@ static BOOL smb_full_audit_getlock(vfs_handle_struct *handle, files_struct *fsp, return result; } -static int smb_full_audit_symlink(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath) { int result; - result = SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath); + result = SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath); do_log(SMB_VFS_OP_SYMLINK, (result >= 0), handle, "%s|%s", oldpath, newpath); @@ -1341,24 +1317,24 @@ static int smb_full_audit_symlink(vfs_handle_struct *handle, connection_struct * return result; } -static int smb_full_audit_readlink(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz) { int result; - result = SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz); + result = SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz); do_log(SMB_VFS_OP_READLINK, (result >= 0), handle, "%s", path); return result; } -static int smb_full_audit_link(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath) { int result; - result = SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath); + result = SMB_VFS_NEXT_LINK(handle, oldpath, newpath); do_log(SMB_VFS_OP_LINK, (result >= 0), handle, "%s|%s", oldpath, newpath); @@ -1366,24 +1342,24 @@ static int smb_full_audit_link(vfs_handle_struct *handle, connection_struct *con return result; } -static int smb_full_audit_mknod(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev) { int result; - result = SMB_VFS_NEXT_MKNOD(handle, conn, pathname, mode, dev); + result = SMB_VFS_NEXT_MKNOD(handle, pathname, mode, dev); do_log(SMB_VFS_OP_MKNOD, (result >= 0), handle, "%s", pathname); return result; } -static char *smb_full_audit_realpath(vfs_handle_struct *handle, connection_struct *conn, +static char *smb_full_audit_realpath(vfs_handle_struct *handle, const char *path, char *resolved_path) { char *result; - result = SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path); + result = SMB_VFS_NEXT_REALPATH(handle, path, resolved_path); do_log(SMB_VFS_OP_REALPATH, (result != NULL), handle, "%s", path); @@ -1448,12 +1424,12 @@ static BOOL smb_full_audit_set_nt_acl(vfs_handle_struct *handle, files_struct *f return result; } -static int smb_full_audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, +static int smb_full_audit_chmod_acl(vfs_handle_struct *handle, const char *path, mode_t mode) { int result; - result = SMB_VFS_NEXT_CHMOD_ACL(handle, conn, path, mode); + result = SMB_VFS_NEXT_CHMOD_ACL(handle, path, mode); do_log(SMB_VFS_OP_CHMOD_ACL, (result >= 0), handle, "%s|%o", path, mode); @@ -1475,13 +1451,13 @@ static int smb_full_audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fs } static int smb_full_audit_sys_acl_get_entry(vfs_handle_struct *handle, - connection_struct *conn, + SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) { int result; - result = SMB_VFS_NEXT_SYS_ACL_GET_ENTRY(handle, conn, theacl, entry_id, + result = SMB_VFS_NEXT_SYS_ACL_GET_ENTRY(handle, theacl, entry_id, entry_p); do_log(SMB_VFS_OP_SYS_ACL_GET_ENTRY, (result >= 0), handle, @@ -1491,13 +1467,13 @@ static int smb_full_audit_sys_acl_get_entry(vfs_handle_struct *handle, } static int smb_full_audit_sys_acl_get_tag_type(vfs_handle_struct *handle, - connection_struct *conn, + SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) { int result; - result = SMB_VFS_NEXT_SYS_ACL_GET_TAG_TYPE(handle, conn, entry_d, + result = SMB_VFS_NEXT_SYS_ACL_GET_TAG_TYPE(handle, entry_d, tag_type_p); do_log(SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE, (result >= 0), handle, @@ -1507,13 +1483,13 @@ static int smb_full_audit_sys_acl_get_tag_type(vfs_handle_struct *handle, } static int smb_full_audit_sys_acl_get_permset(vfs_handle_struct *handle, - connection_struct *conn, + SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) { int result; - result = SMB_VFS_NEXT_SYS_ACL_GET_PERMSET(handle, conn, entry_d, + result = SMB_VFS_NEXT_SYS_ACL_GET_PERMSET(handle, entry_d, permset_p); do_log(SMB_VFS_OP_SYS_ACL_GET_PERMSET, (result >= 0), handle, @@ -1523,12 +1499,12 @@ static int smb_full_audit_sys_acl_get_permset(vfs_handle_struct *handle, } static void * smb_full_audit_sys_acl_get_qualifier(vfs_handle_struct *handle, - connection_struct *conn, + SMB_ACL_ENTRY_T entry_d) { void *result; - result = SMB_VFS_NEXT_SYS_ACL_GET_QUALIFIER(handle, conn, entry_d); + result = SMB_VFS_NEXT_SYS_ACL_GET_QUALIFIER(handle, entry_d); do_log(SMB_VFS_OP_SYS_ACL_GET_QUALIFIER, (result != NULL), handle, ""); @@ -1537,13 +1513,12 @@ static void * smb_full_audit_sys_acl_get_qualifier(vfs_handle_struct *handle, } static SMB_ACL_T smb_full_audit_sys_acl_get_file(vfs_handle_struct *handle, - connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type) { SMB_ACL_T result; - result = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, path_p, type); + result = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, path_p, type); do_log(SMB_VFS_OP_SYS_ACL_GET_FILE, (result != NULL), handle, "%s", path_p); @@ -1565,12 +1540,12 @@ static SMB_ACL_T smb_full_audit_sys_acl_get_fd(vfs_handle_struct *handle, } static int smb_full_audit_sys_acl_clear_perms(vfs_handle_struct *handle, - connection_struct *conn, + SMB_ACL_PERMSET_T permset) { int result; - result = SMB_VFS_NEXT_SYS_ACL_CLEAR_PERMS(handle, conn, permset); + result = SMB_VFS_NEXT_SYS_ACL_CLEAR_PERMS(handle, permset); do_log(SMB_VFS_OP_SYS_ACL_CLEAR_PERMS, (result >= 0), handle, ""); @@ -1579,13 +1554,13 @@ static int smb_full_audit_sys_acl_clear_perms(vfs_handle_struct *handle, } static int smb_full_audit_sys_acl_add_perm(vfs_handle_struct *handle, - connection_struct *conn, + SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) { int result; - result = SMB_VFS_NEXT_SYS_ACL_ADD_PERM(handle, conn, permset, perm); + result = SMB_VFS_NEXT_SYS_ACL_ADD_PERM(handle, permset, perm); do_log(SMB_VFS_OP_SYS_ACL_ADD_PERM, (result >= 0), handle, ""); @@ -1594,12 +1569,12 @@ static int smb_full_audit_sys_acl_add_perm(vfs_handle_struct *handle, } static char * smb_full_audit_sys_acl_to_text(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_T theacl, + SMB_ACL_T theacl, ssize_t *plen) { char * result; - result = SMB_VFS_NEXT_SYS_ACL_TO_TEXT(handle, conn, theacl, plen); + result = SMB_VFS_NEXT_SYS_ACL_TO_TEXT(handle, theacl, plen); do_log(SMB_VFS_OP_SYS_ACL_TO_TEXT, (result != NULL), handle, ""); @@ -1608,12 +1583,12 @@ static char * smb_full_audit_sys_acl_to_text(vfs_handle_struct *handle, } static SMB_ACL_T smb_full_audit_sys_acl_init(vfs_handle_struct *handle, - connection_struct *conn, + int count) { SMB_ACL_T result; - result = SMB_VFS_NEXT_SYS_ACL_INIT(handle, conn, count); + result = SMB_VFS_NEXT_SYS_ACL_INIT(handle, count); do_log(SMB_VFS_OP_SYS_ACL_INIT, (result != NULL), handle, ""); @@ -1622,12 +1597,12 @@ static SMB_ACL_T smb_full_audit_sys_acl_init(vfs_handle_struct *handle, } static int smb_full_audit_sys_acl_create_entry(vfs_handle_struct *handle, - connection_struct *conn, SMB_ACL_T *pacl, + SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) { int result; - result = SMB_VFS_NEXT_SYS_ACL_CREATE_ENTRY(handle, conn, pacl, pentry); + result = SMB_VFS_NEXT_SYS_ACL_CREATE_ENTRY(handle, pacl, pentry); do_log(SMB_VFS_OP_SYS_ACL_CREATE_ENTRY, (result >= 0), handle, ""); @@ -1636,13 +1611,13 @@ static int smb_full_audit_sys_acl_create_entry(vfs_handle_struct *handle, } static int smb_full_audit_sys_acl_set_tag_type(vfs_handle_struct *handle, - connection_struct *conn, + SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) { int result; - result = SMB_VFS_NEXT_SYS_ACL_SET_TAG_TYPE(handle, conn, entry, + result = SMB_VFS_NEXT_SYS_ACL_SET_TAG_TYPE(handle, entry, tagtype); do_log(SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE, (result >= 0), handle, @@ -1652,13 +1627,13 @@ static int smb_full_audit_sys_acl_set_tag_type(vfs_handle_struct *handle, } static int smb_full_audit_sys_acl_set_qualifier(vfs_handle_struct *handle, - connection_struct *conn, + SMB_ACL_ENTRY_T entry, void *qual) { int result; - result = SMB_VFS_NEXT_SYS_ACL_SET_QUALIFIER(handle, conn, entry, qual); + result = SMB_VFS_NEXT_SYS_ACL_SET_QUALIFIER(handle, entry, qual); do_log(SMB_VFS_OP_SYS_ACL_SET_QUALIFIER, (result >= 0), handle, ""); @@ -1667,13 +1642,13 @@ static int smb_full_audit_sys_acl_set_qualifier(vfs_handle_struct *handle, } static int smb_full_audit_sys_acl_set_permset(vfs_handle_struct *handle, - connection_struct *conn, + SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) { int result; - result = SMB_VFS_NEXT_SYS_ACL_SET_PERMSET(handle, conn, entry, permset); + result = SMB_VFS_NEXT_SYS_ACL_SET_PERMSET(handle, entry, permset); do_log(SMB_VFS_OP_SYS_ACL_SET_PERMSET, (result >= 0), handle, ""); @@ -1682,12 +1657,12 @@ static int smb_full_audit_sys_acl_set_permset(vfs_handle_struct *handle, } static int smb_full_audit_sys_acl_valid(vfs_handle_struct *handle, - connection_struct *conn, + SMB_ACL_T theacl ) { int result; - result = SMB_VFS_NEXT_SYS_ACL_VALID(handle, conn, theacl); + result = SMB_VFS_NEXT_SYS_ACL_VALID(handle, theacl); do_log(SMB_VFS_OP_SYS_ACL_VALID, (result >= 0), handle, ""); @@ -1696,13 +1671,13 @@ static int smb_full_audit_sys_acl_valid(vfs_handle_struct *handle, } static int smb_full_audit_sys_acl_set_file(vfs_handle_struct *handle, - connection_struct *conn, + const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) { int result; - result = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, name, acltype, + result = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, name, acltype, theacl); do_log(SMB_VFS_OP_SYS_ACL_SET_FILE, (result >= 0), handle, @@ -1725,12 +1700,12 @@ static int smb_full_audit_sys_acl_set_fd(vfs_handle_struct *handle, files_struct } static int smb_full_audit_sys_acl_delete_def_file(vfs_handle_struct *handle, - connection_struct *conn, + const char *path) { int result; - result = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, path); + result = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, path); do_log(SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, (result >= 0), handle, "%s", path); @@ -1739,13 +1714,13 @@ static int smb_full_audit_sys_acl_delete_def_file(vfs_handle_struct *handle, } static int smb_full_audit_sys_acl_get_perm(vfs_handle_struct *handle, - connection_struct *conn, + SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) { int result; - result = SMB_VFS_NEXT_SYS_ACL_GET_PERM(handle, conn, permset, perm); + result = SMB_VFS_NEXT_SYS_ACL_GET_PERM(handle, permset, perm); do_log(SMB_VFS_OP_SYS_ACL_GET_PERM, (result >= 0), handle, ""); @@ -1754,12 +1729,12 @@ static int smb_full_audit_sys_acl_get_perm(vfs_handle_struct *handle, } static int smb_full_audit_sys_acl_free_text(vfs_handle_struct *handle, - connection_struct *conn, + char *text) { int result; - result = SMB_VFS_NEXT_SYS_ACL_FREE_TEXT(handle, conn, text); + result = SMB_VFS_NEXT_SYS_ACL_FREE_TEXT(handle, text); do_log(SMB_VFS_OP_SYS_ACL_FREE_TEXT, (result >= 0), handle, ""); @@ -1768,12 +1743,12 @@ static int smb_full_audit_sys_acl_free_text(vfs_handle_struct *handle, } static int smb_full_audit_sys_acl_free_acl(vfs_handle_struct *handle, - connection_struct *conn, + SMB_ACL_T posix_acl) { int result; - result = SMB_VFS_NEXT_SYS_ACL_FREE_ACL(handle, conn, posix_acl); + result = SMB_VFS_NEXT_SYS_ACL_FREE_ACL(handle, posix_acl); do_log(SMB_VFS_OP_SYS_ACL_FREE_ACL, (result >= 0), handle, ""); @@ -1782,13 +1757,12 @@ static int smb_full_audit_sys_acl_free_acl(vfs_handle_struct *handle, } static int smb_full_audit_sys_acl_free_qualifier(vfs_handle_struct *handle, - connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype) { int result; - result = SMB_VFS_NEXT_SYS_ACL_FREE_QUALIFIER(handle, conn, qualifier, + result = SMB_VFS_NEXT_SYS_ACL_FREE_QUALIFIER(handle, qualifier, tagtype); do_log(SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER, (result >= 0), handle, @@ -1798,12 +1772,12 @@ static int smb_full_audit_sys_acl_free_qualifier(vfs_handle_struct *handle, } static ssize_t smb_full_audit_getxattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, + const char *path, const char *name, void *value, size_t size) { ssize_t result; - result = SMB_VFS_NEXT_GETXATTR(handle, conn, path, name, value, size); + result = SMB_VFS_NEXT_GETXATTR(handle, path, name, value, size); do_log(SMB_VFS_OP_GETXATTR, (result >= 0), handle, "%s|%s", path, name); @@ -1812,13 +1786,12 @@ static ssize_t smb_full_audit_getxattr(struct vfs_handle_struct *handle, } static ssize_t smb_full_audit_lgetxattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, const char *name, void *value, size_t size) { ssize_t result; - result = SMB_VFS_NEXT_LGETXATTR(handle, conn, path, name, value, size); + result = SMB_VFS_NEXT_LGETXATTR(handle, path, name, value, size); do_log(SMB_VFS_OP_LGETXATTR, (result >= 0), handle, "%s|%s", path, name); @@ -1841,12 +1814,11 @@ static ssize_t smb_full_audit_fgetxattr(struct vfs_handle_struct *handle, } static ssize_t smb_full_audit_listxattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, char *list, size_t size) { ssize_t result; - result = SMB_VFS_NEXT_LISTXATTR(handle, conn, path, list, size); + result = SMB_VFS_NEXT_LISTXATTR(handle, path, list, size); do_log(SMB_VFS_OP_LISTXATTR, (result >= 0), handle, "%s", path); @@ -1854,12 +1826,11 @@ static ssize_t smb_full_audit_listxattr(struct vfs_handle_struct *handle, } static ssize_t smb_full_audit_llistxattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, char *list, size_t size) { ssize_t result; - result = SMB_VFS_NEXT_LLISTXATTR(handle, conn, path, list, size); + result = SMB_VFS_NEXT_LLISTXATTR(handle, path, list, size); do_log(SMB_VFS_OP_LLISTXATTR, (result >= 0), handle, "%s", path); @@ -1881,12 +1852,12 @@ static ssize_t smb_full_audit_flistxattr(struct vfs_handle_struct *handle, } static int smb_full_audit_removexattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, + const char *path, const char *name) { int result; - result = SMB_VFS_NEXT_REMOVEXATTR(handle, conn, path, name); + result = SMB_VFS_NEXT_REMOVEXATTR(handle, path, name); do_log(SMB_VFS_OP_REMOVEXATTR, (result >= 0), handle, "%s|%s", path, name); @@ -1895,12 +1866,12 @@ static int smb_full_audit_removexattr(struct vfs_handle_struct *handle, } static int smb_full_audit_lremovexattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, + const char *path, const char *name) { int result; - result = SMB_VFS_NEXT_LREMOVEXATTR(handle, conn, path, name); + result = SMB_VFS_NEXT_LREMOVEXATTR(handle, path, name); do_log(SMB_VFS_OP_LREMOVEXATTR, (result >= 0), handle, "%s|%s", path, name); @@ -1923,13 +1894,13 @@ static int smb_full_audit_fremovexattr(struct vfs_handle_struct *handle, } static int smb_full_audit_setxattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, + const char *path, const char *name, const void *value, size_t size, int flags) { int result; - result = SMB_VFS_NEXT_SETXATTR(handle, conn, path, name, value, size, + result = SMB_VFS_NEXT_SETXATTR(handle, path, name, value, size, flags); do_log(SMB_VFS_OP_SETXATTR, (result >= 0), handle, @@ -1939,13 +1910,13 @@ static int smb_full_audit_setxattr(struct vfs_handle_struct *handle, } static int smb_full_audit_lsetxattr(struct vfs_handle_struct *handle, - struct connection_struct *conn, const char *path, + const char *path, const char *name, const void *value, size_t size, int flags) { int result; - result = SMB_VFS_NEXT_LSETXATTR(handle, conn, path, name, value, size, + result = SMB_VFS_NEXT_LSETXATTR(handle, path, name, value, size, flags); do_log(SMB_VFS_OP_LSETXATTR, (result >= 0), handle, diff --git a/source/modules/vfs_netatalk.c b/source/modules/vfs_netatalk.c index e9d4360cd80..279160d9665 100644 --- a/source/modules/vfs_netatalk.c +++ b/source/modules/vfs_netatalk.c @@ -172,11 +172,11 @@ static void atalk_rrmdir(TALLOC_CTX *ctx, char *path) /* Directory operations */ -SMB_STRUCT_DIR *atalk_opendir(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, const char *mask, uint32 attr) +SMB_STRUCT_DIR *atalk_opendir(struct vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr) { SMB_STRUCT_DIR *ret = 0; - ret = SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr); + ret = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); /* * when we try to perform delete operation upon file which has fork @@ -187,19 +187,19 @@ SMB_STRUCT_DIR *atalk_opendir(struct vfs_handle_struct *handle, struct connectio * list then it would be nice to add one. */ - atalk_add_to_list(&conn->hide_list); - atalk_add_to_list(&conn->veto_list); + atalk_add_to_list(&handle->conn->hide_list); + atalk_add_to_list(&handle->conn->veto_list); return ret; } -static int atalk_rmdir(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path) +static int atalk_rmdir(struct vfs_handle_struct *handle, const char *path) { BOOL add = False; TALLOC_CTX *ctx = 0; char *dpath; - if (!conn || !conn->origpath || !path) goto exit_rmdir; + if (!handle->conn->origpath || !path) goto exit_rmdir; /* due to there is no way to change bDeleteVetoFiles variable * from this module, gotta use talloc stuff.. @@ -211,19 +211,19 @@ static int atalk_rmdir(struct vfs_handle_struct *handle, struct connection_struc goto exit_rmdir; if (!(dpath = talloc_asprintf(ctx, "%s/%s%s", - conn->origpath, path, add ? "/"APPLEDOUBLE : ""))) + handle->conn->origpath, path, add ? "/"APPLEDOUBLE : ""))) goto exit_rmdir; atalk_rrmdir(ctx, dpath); exit_rmdir: talloc_destroy(ctx); - return SMB_VFS_NEXT_RMDIR(handle, conn, path); + return SMB_VFS_NEXT_RMDIR(handle, path); } /* File operations */ -static int atalk_rename(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldname, const char *newname) +static int atalk_rename(struct vfs_handle_struct *handle, const char *oldname, const char *newname) { int ret = 0; char *adbl_path = 0; @@ -232,14 +232,14 @@ static int atalk_rename(struct vfs_handle_struct *handle, struct connection_stru SMB_STRUCT_STAT orig_info; TALLOC_CTX *ctx; - ret = SMB_VFS_NEXT_RENAME(handle, conn, oldname, newname); + ret = SMB_VFS_NEXT_RENAME(handle, oldname, newname); - if (!conn || !oldname) return ret; + if (!oldname) return ret; if (!(ctx = talloc_init("rename_file"))) return ret; - if (atalk_build_paths(ctx, conn->origpath, oldname, &adbl_path, &orig_path, + if (atalk_build_paths(ctx, handle->conn->origpath, oldname, &adbl_path, &orig_path, &adbl_info, &orig_info) != 0) return ret; @@ -255,7 +255,7 @@ exit_rename: return ret; } -static int atalk_unlink(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path) +static int atalk_unlink(struct vfs_handle_struct *handle, const char *path) { int ret = 0, i; char *adbl_path = 0; @@ -264,25 +264,25 @@ static int atalk_unlink(struct vfs_handle_struct *handle, struct connection_stru SMB_STRUCT_STAT orig_info; TALLOC_CTX *ctx; - ret = SMB_VFS_NEXT_UNLINK(handle, conn, path); + ret = SMB_VFS_NEXT_UNLINK(handle, path); - if (!conn || !path) return ret; + if (!path) return ret; /* no .AppleDouble sync if veto or hide list is empty, * otherwise "Cannot find the specified file" error will be caused */ - if (!conn->veto_list) return ret; - if (!conn->hide_list) return ret; + if (!handle->conn->veto_list) return ret; + if (!handle->conn->hide_list) return ret; - for (i = 0; conn->veto_list[i].name; i ++) { - if (strstr(conn->veto_list[i].name, APPLEDOUBLE)) + for (i = 0; handle->conn->veto_list[i].name; i ++) { + if (strstr(handle->conn->veto_list[i].name, APPLEDOUBLE)) break; } - if (!conn->veto_list[i].name) { - for (i = 0; conn->hide_list[i].name; i ++) { - if (strstr(conn->hide_list[i].name, APPLEDOUBLE)) + if (!handle->conn->veto_list[i].name) { + for (i = 0; handle->conn->hide_list[i].name; i ++) { + if (strstr(handle->conn->hide_list[i].name, APPLEDOUBLE)) break; else { DEBUG(3, ("ATALK: %s is not hidden, skipped..\n", @@ -295,7 +295,7 @@ static int atalk_unlink(struct vfs_handle_struct *handle, struct connection_stru if (!(ctx = talloc_init("unlink_file"))) return ret; - if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, + if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path, &adbl_info, &orig_info) != 0) return ret; @@ -311,7 +311,7 @@ exit_unlink: return ret; } -static int atalk_chmod(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode) +static int atalk_chmod(struct vfs_handle_struct *handle, const char *path, mode_t mode) { int ret = 0; char *adbl_path = 0; @@ -320,14 +320,14 @@ static int atalk_chmod(struct vfs_handle_struct *handle, struct connection_struc SMB_STRUCT_STAT orig_info; TALLOC_CTX *ctx; - ret = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode); + ret = SMB_VFS_NEXT_CHMOD(handle, path, mode); - if (!conn || !path) return ret; + if (!path) return ret; if (!(ctx = talloc_init("chmod_file"))) return ret; - if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, + if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path, &adbl_info, &orig_info) != 0) return ret; @@ -343,7 +343,7 @@ exit_chmod: return ret; } -static int atalk_chown(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, uid_t uid, gid_t gid) +static int atalk_chown(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid) { int ret = 0; char *adbl_path = 0; @@ -352,14 +352,14 @@ static int atalk_chown(struct vfs_handle_struct *handle, struct connection_struc SMB_STRUCT_STAT orig_info; TALLOC_CTX *ctx; - ret = SMB_VFS_NEXT_CHOWN(handle, conn, path, uid, gid); + ret = SMB_VFS_NEXT_CHOWN(handle, path, uid, gid); - if (!conn || !path) return ret; + if (!path) return ret; if (!(ctx = talloc_init("chown_file"))) return ret; - if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, + if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path, &adbl_info, &orig_info) != 0) return ret; diff --git a/source/modules/vfs_prealloc.c b/source/modules/vfs_prealloc.c new file mode 100644 index 00000000000..94db6423700 --- /dev/null +++ b/source/modules/vfs_prealloc.c @@ -0,0 +1,214 @@ +/* + * XFS preallocation support module. + * + * Copyright (c) James Peach 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +/* Extent preallocation module. + * + * The purpose of this module is to preallocate space on the filesystem when + * we have a good idea of how large files are supposed to be. This lets writes + * proceed without having to allocate new extents and results in better file + * layouts on disk. + * + * Currently only implemented for XFS. This module is based on an original idea + * and implementation by Sebastian Brings. + * + * Tunables. + * + * prealloc: <ext> Number of bytes to preallocate for a file with + * the matching extension. + * prealloc:debug Debug level at which to emit messages. + * + * Example. + * + * prealloc:mpeg = 500M # Preallocate *.mpeg to 500 MiB. + */ + +#ifdef HAVE_XFS_LIBXFS_H +#include <xfs/libxfs.h> +#define lock_type xfs_flock64_t +#else +#define lock_type struct flock64 +#endif + +#define MODULE "prealloc" +static int module_debug; + +static int preallocate_space(int fd, SMB_OFF_T size) +{ + lock_type fl = {0}; + int err; + + if (size <= 0) { + return 0; + } + + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = size; + + /* IMPORTANT: We use RESVSP because we want the extents to be + * allocated, but we don't want the allocation to show up in + * st_size or persist after the close(2). + */ + +#if defined(XFS_IOC_RESVSP64) + /* On Linux this comes in via libxfs.h. */ + err = xfsctl(NULL, fd, XFS_IOC_RESVSP64, &fl); +#elif defined(F_RESVSP64) + /* On IRIX, this comes from fcntl.h. */ + err = fcntl(fd, F_RESVSP64, &fl); +#else + err = -1; + errno = ENOSYS; +#endif + + if (err) { + DEBUG(module_debug, + ("%s: preallocate failed on fd=%d size=%lld: %s\n", + MODULE, fd, (long long)size, strerror(errno))); + } + + return err; +} + +static int prealloc_connect( + struct vfs_handle_struct * handle, + const char * service, + const char * user) +{ + module_debug = lp_parm_int(SNUM(handle->conn), + MODULE, "debug", 100); + + return SMB_VFS_NEXT_CONNECT(handle, service, user); +} + +static int prealloc_open(vfs_handle_struct* handle, + const char * fname, + files_struct * fsp, + int flags, + mode_t mode) +{ + int fd; + off64_t size = 0; + + const char * dot; + char fext[10]; + + if (!(flags & (O_CREAT|O_TRUNC))) { + /* Caller is not intending to rewrite the file. Let's not mess + * with the allocation in this case. + */ + goto normal_open; + } + + *fext = '\0'; + dot = strrchr(fname, '.'); + if (dot && *++dot) { + if (strlen(dot) < sizeof(fext)) { + strncpy(fext, dot, sizeof(fext)); + strnorm(fext, CASE_LOWER); + } + } + + if (*fext == '\0') { + goto normal_open; + } + + /* Syntax for specifying preallocation size is: + * MODULE: <extension> = <size> + * where + * <extension> is the file extension in lower case + * <size> is a size like 10, 10K, 10M + */ + size = conv_str_size(lp_parm_const_string(SNUM(handle->conn), MODULE, + fext, NULL)); + if (size <= 0) { + /* No need to preallocate this file. */ + goto normal_open; + } + + fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + if (fd < 0) { + return fd; + } + + /* Prellocate only if the file is being created or replaced. Note that + * Samba won't ever pass down O_TRUNC, which is why we have to handle + * truncate calls specially. + */ + if ((flags & O_CREAT) || (flags & O_TRUNC)) { + SMB_OFF_T * psize; + + psize = VFS_ADD_FSP_EXTENSION(handle, fsp, SMB_OFF_T); + if (psize == NULL || *psize == -1) { + return fd; + } + + DEBUG(module_debug, + ("%s: preallocating %s (fd=%d) to %lld bytes\n", + MODULE, fname, fd, (long long)size)); + + *psize = size; + if (preallocate_space(fd, *psize) < 0) { + VFS_REMOVE_FSP_EXTENSION(handle, fsp); + } + } + + return fd; + +normal_open: + /* We are not creating or replacing a file. Skip the + * preallocation. + */ + DEBUG(module_debug, ("%s: skipping preallocation for %s\n", + MODULE, fname)); + return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); +} + +static int prealloc_ftruncate(vfs_handle_struct * handle, + files_struct * fsp, + int fd, + SMB_OFF_T offset) +{ + SMB_OFF_T *psize; + int ret = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset); + + /* Maintain the allocated space even in the face of truncates. */ + if ((psize = VFS_FETCH_FSP_EXTENSION(handle, fsp))) { + preallocate_space(fd, *psize); + } + + return ret; +} + +static vfs_op_tuple prealloc_op_tuples[] = { + {SMB_VFS_OP(prealloc_open), SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(prealloc_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(prealloc_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT}, + {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_prealloc_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, + MODULE, prealloc_op_tuples); +} + diff --git a/source/modules/vfs_readonly.c b/source/modules/vfs_readonly.c index ee9e40c2fca..e69f7dac016 100644 --- a/source/modules/vfs_readonly.c +++ b/source/modules/vfs_readonly.c @@ -55,7 +55,6 @@ #define MODULE_NAME "readonly" static int readonly_connect(vfs_handle_struct *handle, - connection_struct *conn, const char *service, const char *user) { @@ -71,10 +70,10 @@ static int readonly_connect(vfs_handle_struct *handle, time_t end_period = get_date(period[1], ¤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/source/modules/vfs_recycle.c b/source/modules/vfs_recycle.c index 42f2f51416e..cb5eaffa54d 100644 --- a/source/modules/vfs_recycle.c +++ b/source/modules/vfs_recycle.c @@ -32,9 +32,9 @@ static int vfs_recycle_debug_level = DBGC_VFS; #undef DBGC_CLASS #define DBGC_CLASS vfs_recycle_debug_level -static int recycle_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user); -static void recycle_disconnect(vfs_handle_struct *handle, connection_struct *conn); -static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *name); +static int recycle_connect(vfs_handle_struct *handle, const char *service, const char *user); +static void recycle_disconnect(vfs_handle_struct *handle); +static int recycle_unlink(vfs_handle_struct *handle, const char *name); static vfs_op_tuple recycle_ops[] = { @@ -48,20 +48,20 @@ static vfs_op_tuple recycle_ops[] = { {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} }; -static int recycle_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user) +static int recycle_connect(vfs_handle_struct *handle, const char *service, const char *user) { DEBUG(10,("recycle_connect() connect to service[%s] as user[%s].\n", service,user)); - return SMB_VFS_NEXT_CONNECT(handle, conn, service, user); + return SMB_VFS_NEXT_CONNECT(handle, service, user); } -static void recycle_disconnect(vfs_handle_struct *handle, connection_struct *conn) +static void recycle_disconnect(vfs_handle_struct *handle) { DEBUG(10,("recycle_disconnect() connect to service[%s].\n", - lp_servicename(SNUM(conn)))); + lp_servicename(SNUM(handle->conn)))); - SMB_VFS_NEXT_DISCONNECT(handle, conn); + SMB_VFS_NEXT_DISCONNECT(handle); } static const char *recycle_repository(vfs_handle_struct *handle) @@ -202,7 +202,7 @@ static BOOL recycle_directory_exist(vfs_handle_struct *handle, const char *dname { SMB_STRUCT_STAT st; - if (SMB_VFS_NEXT_STAT(handle, handle->conn, dname, &st) == 0) { + if (SMB_VFS_NEXT_STAT(handle, dname, &st) == 0) { if (S_ISDIR(st.st_mode)) { return True; } @@ -215,7 +215,7 @@ static BOOL recycle_file_exist(vfs_handle_struct *handle, const char *fname) { SMB_STRUCT_STAT st; - if (SMB_VFS_NEXT_STAT(handle, handle->conn, fname, &st) == 0) { + if (SMB_VFS_NEXT_STAT(handle, fname, &st) == 0) { if (S_ISREG(st.st_mode)) { return True; } @@ -234,7 +234,7 @@ static SMB_OFF_T recycle_get_file_size(vfs_handle_struct *handle, const char *fn { SMB_STRUCT_STAT st; - if (SMB_VFS_NEXT_STAT(handle, handle->conn, fname, &st) != 0) { + if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) { DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno))); return (SMB_OFF_T)0; } @@ -280,7 +280,7 @@ static BOOL recycle_create_dir(vfs_handle_struct *handle, const char *dname) DEBUG(10, ("recycle: dir %s already exists\n", new_dir)); else { DEBUG(5, ("recycle: creating new dir %s\n", new_dir)); - if (SMB_VFS_NEXT_MKDIR(handle, handle->conn, new_dir, mode) != 0) { + if (SMB_VFS_NEXT_MKDIR(handle, new_dir, mode) != 0) { DEBUG(1,("recycle: mkdir failed for %s with error: %s\n", new_dir, strerror(errno))); ret = False; goto done; @@ -354,7 +354,7 @@ static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, BOOL struct utimbuf tb; time_t currtime; - if (SMB_VFS_NEXT_STAT(handle, handle->conn, fname, &st) != 0) { + if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) { DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno))); return; } @@ -362,16 +362,19 @@ static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, BOOL tb.actime = currtime; tb.modtime = touch_mtime ? currtime : st.st_mtime; - if (SMB_VFS_NEXT_UTIME(handle, handle->conn, fname, &tb) == -1 ) { + if (SMB_VFS_NEXT_UTIME(handle, fname, &tb) == -1 ) { DEBUG(0, ("recycle: touching %s failed, reason = %s\n", fname, strerror(errno))); } } +extern userdom_struct current_user_info; + /** * Check if file should be recycled **/ -static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *file_name) +static int recycle_unlink(vfs_handle_struct *handle, const char *file_name) { + connection_struct *conn = handle->conn; char *path_name = NULL; char *temp_name = NULL; char *final_name = NULL; @@ -383,7 +386,12 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co BOOL exist; int rc = -1; - repository = alloc_sub_conn(conn, recycle_repository(handle)); + repository = alloc_sub_advanced(lp_servicename(SNUM(conn)), + conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + recycle_repository(handle)); ALLOC_CHECK(repository, done); /* shouldn't we allow absolute path names here? --metze */ /* Yes :-). JRA. */ @@ -391,14 +399,14 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co if(!repository || *(repository) == '\0') { DEBUG(3, ("recycle: repository path not set, purging %s...\n", file_name)); - rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); + rc = SMB_VFS_NEXT_UNLINK(handle, file_name); goto done; } /* we don't recycle the recycle bin... */ if (strncmp(file_name, repository, strlen(repository)) == 0) { DEBUG(3, ("recycle: File is within recycling bin, unlinking ...\n")); - rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); + rc = SMB_VFS_NEXT_UNLINK(handle, file_name); goto done; } @@ -408,7 +416,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co * if(fsize == 0) { DEBUG(3, ("recycle: File %s is empty, purging...\n", file_name)); - rc = SMB_VFS_NEXT_UNLINK(handle,conn,file_name); + rc = SMB_VFS_NEXT_UNLINK(handle,file_name); goto done; } */ @@ -420,18 +428,18 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co maxsize = recycle_maxsize(handle); if(maxsize > 0 && file_size > maxsize) { DEBUG(3, ("recycle: File %s exceeds maximum recycle size, purging... \n", file_name)); - rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); + rc = SMB_VFS_NEXT_UNLINK(handle, file_name); goto done; } /* FIXME: this is wrong: moving files with rename does not change the disk space * allocation * - space_avail = SMB_VFS_NEXT_DISK_FREE(handle, conn, ".", True, &bsize, &dfree, &dsize) * 1024L; + space_avail = SMB_VFS_NEXT_DISK_FREE(handle, ".", True, &bsize, &dfree, &dsize) * 1024L; DEBUG(5, ("space_avail = %Lu, file_size = %Lu\n", space_avail, file_size)); if(space_avail < file_size) { DEBUG(3, ("recycle: Not enough diskspace, purging file %s\n", file_name)); - rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); + rc = SMB_VFS_NEXT_UNLINK(handle, file_name); goto done; } */ @@ -456,7 +464,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co if (matchparam(recycle_exclude(handle), base)) { DEBUG(3, ("recycle: file %s is excluded \n", base)); - rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); + rc = SMB_VFS_NEXT_UNLINK(handle, file_name); goto done; } @@ -466,7 +474,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co */ if (checkparam(recycle_exclude_dir(handle), path_name)) { DEBUG(3, ("recycle: directory %s is excluded \n", path_name)); - rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); + rc = SMB_VFS_NEXT_UNLINK(handle, file_name); goto done; } @@ -484,7 +492,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co DEBUG(10, ("recycle: Creating directory %s\n", temp_name)); if (recycle_create_dir(handle, temp_name) == False) { DEBUG(3, ("recycle: Could not create directory, purging %s...\n", file_name)); - rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); + rc = SMB_VFS_NEXT_UNLINK(handle, file_name); goto done; } } @@ -497,7 +505,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co if (recycle_file_exist(handle, final_name)) { if (recycle_versions(handle) == False || matchparam(recycle_noversions(handle), base) == True) { DEBUG(3, ("recycle: Removing old file %s from recycle bin\n", final_name)); - if (SMB_VFS_NEXT_UNLINK(handle, conn, final_name) != 0) { + if (SMB_VFS_NEXT_UNLINK(handle, final_name) != 0) { DEBUG(1, ("recycle: Error deleting old file: %s\n", strerror(errno))); } } @@ -511,10 +519,10 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co } DEBUG(10, ("recycle: Moving %s to %s\n", file_name, final_name)); - rc = SMB_VFS_NEXT_RENAME(handle, conn, file_name, final_name); + rc = SMB_VFS_NEXT_RENAME(handle, file_name, final_name); if (rc != 0) { DEBUG(3, ("recycle: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name)); - rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); + rc = SMB_VFS_NEXT_UNLINK(handle, file_name); goto done; } diff --git a/source/modules/vfs_shadow_copy.c b/source/modules/vfs_shadow_copy.c index db1c8d007dc..447c53d773a 100644 --- a/source/modules/vfs_shadow_copy.c +++ b/source/modules/vfs_shadow_copy.c @@ -72,10 +72,10 @@ static BOOL shadow_copy_match_name(const char *name) return False; } -static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr) +static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr) { shadow_copy_Dir *dirp; - SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,conn,fname,mask,attr); + SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fname,mask,attr); if (!p) { DEBUG(0,("shadow_copy_opendir: SMB_VFS_NEXT_OPENDIR() failed for [%s]\n",fname)); @@ -85,7 +85,7 @@ static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection dirp = SMB_MALLOC_P(shadow_copy_Dir); if (!dirp) { DEBUG(0,("shadow_copy_opendir: Out of memory\n")); - SMB_VFS_NEXT_CLOSEDIR(handle,conn,p); + SMB_VFS_NEXT_CLOSEDIR(handle,p); return NULL; } @@ -94,7 +94,7 @@ static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection while (True) { SMB_STRUCT_DIRENT *d; - d = SMB_VFS_NEXT_READDIR(handle, conn, p); + d = SMB_VFS_NEXT_READDIR(handle, p); if (d == NULL) { break; } @@ -115,11 +115,11 @@ static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection dirp->dirs[dirp->num++] = *d; } - SMB_VFS_NEXT_CLOSEDIR(handle,conn,p); + SMB_VFS_NEXT_CLOSEDIR(handle,p); return((SMB_STRUCT_DIR *)dirp); } -SMB_STRUCT_DIRENT *shadow_copy_readdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *_dirp) +SMB_STRUCT_DIRENT *shadow_copy_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp) { shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp; @@ -130,7 +130,7 @@ SMB_STRUCT_DIRENT *shadow_copy_readdir(vfs_handle_struct *handle, connection_str return NULL; } -static void shadow_copy_seekdir(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *_dirp, long offset) +static void shadow_copy_seekdir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp, long offset) { shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp; @@ -139,19 +139,19 @@ static void shadow_copy_seekdir(struct vfs_handle_struct *handle, struct connect } } -static long shadow_copy_telldir(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *_dirp) +static long shadow_copy_telldir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp) { shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp; return( dirp->pos ) ; } -static void shadow_copy_rewinddir(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *_dirp) +static void shadow_copy_rewinddir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp) { shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp; dirp->pos = 0 ; } -int shadow_copy_closedir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *_dirp) +int shadow_copy_closedir(vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp) { shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp; @@ -163,7 +163,7 @@ int shadow_copy_closedir(vfs_handle_struct *handle, connection_struct *conn, SMB static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels) { - SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fsp->conn,fsp->conn->connectpath,NULL,0); + SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fsp->conn->connectpath,NULL,0); shadow_copy_data->num_volumes = 0; shadow_copy_data->labels = NULL; @@ -177,7 +177,7 @@ static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_str SHADOW_COPY_LABEL *tlabels; SMB_STRUCT_DIRENT *d; - d = SMB_VFS_NEXT_READDIR(handle, fsp->conn, p); + d = SMB_VFS_NEXT_READDIR(handle, p); if (d == NULL) { break; } @@ -200,7 +200,7 @@ static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_str (shadow_copy_data->num_volumes+1)*sizeof(SHADOW_COPY_LABEL)); if (tlabels == NULL) { DEBUG(0,("shadow_copy_get_shadow_copy_data: Out of memory\n")); - SMB_VFS_NEXT_CLOSEDIR(handle,fsp->conn,p); + SMB_VFS_NEXT_CLOSEDIR(handle,p); return -1; } @@ -209,7 +209,7 @@ static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_str shadow_copy_data->labels = tlabels; } - SMB_VFS_NEXT_CLOSEDIR(handle,fsp->conn,p); + SMB_VFS_NEXT_CLOSEDIR(handle,p); return 0; } diff --git a/source/nmbd/nmbd_synclists.c b/source/nmbd/nmbd_synclists.c index 28ad92ed108..0e67c3f69c0 100644 --- a/source/nmbd/nmbd_synclists.c +++ b/source/nmbd/nmbd_synclists.c @@ -68,7 +68,7 @@ static void sync_child(char *name, int nm_type, char *fname) { fstring unix_workgroup; - static struct cli_state cli; + struct cli_state *cli; uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0; struct nmb_name called, calling; @@ -76,50 +76,55 @@ static void sync_child(char *name, int nm_type, * Patch from Andy Levine andyl@epicrealm.com. */ - if (!cli_initialise(&cli) || !cli_set_port(&cli, 139) || !cli_connect(&cli, name, &ip)) { + cli = cli_initialise(); + if (!cli) { + return; + } + + if (!cli_set_port(cli, 139) || !cli_connect(cli, name, &ip)) { return; } make_nmb_name(&calling, local_machine, 0x0); make_nmb_name(&called , name, nm_type); - if (!cli_session_request(&cli, &calling, &called)) { - cli_shutdown(&cli); + if (!cli_session_request(cli, &calling, &called)) { + cli_shutdown(cli); return; } - if (!cli_negprot(&cli)) { - cli_shutdown(&cli); + if (!cli_negprot(cli)) { + cli_shutdown(cli); return; } - if (!cli_session_setup(&cli, "", "", 1, "", 0, workgroup)) { - cli_shutdown(&cli); + if (!cli_session_setup(cli, "", "", 1, "", 0, workgroup)) { + cli_shutdown(cli); return; } - if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { - cli_shutdown(&cli); + if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) { + cli_shutdown(cli); return; } /* All the cli_XX functions take UNIX character set. */ - fstrcpy(unix_workgroup, cli.server_domain?cli.server_domain:workgroup); + fstrcpy(unix_workgroup, cli->server_domain ? cli->server_domain : workgroup); /* Fetch a workgroup list. */ - cli_NetServerEnum(&cli, unix_workgroup, + cli_NetServerEnum(cli, unix_workgroup, local_type|SV_TYPE_DOMAIN_ENUM, callback, NULL); /* Now fetch a server list. */ if (servers) { fstrcpy(unix_workgroup, workgroup); - cli_NetServerEnum(&cli, unix_workgroup, + cli_NetServerEnum(cli, unix_workgroup, local?SV_TYPE_LOCAL_LIST_ONLY:SV_TYPE_ALL, callback, NULL); } - cli_shutdown(&cli); + cli_shutdown(cli); } /******************************************************************* diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c index 78776256e99..118ba358e16 100644 --- a/source/nsswitch/pam_winbind.c +++ b/source/nsswitch/pam_winbind.c @@ -128,6 +128,24 @@ static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int error_ SAFE_FREE(data); } +/* + * Work around the pam API that has functions with void ** as parameters. + * These lead to strict aliasing warnings with gcc. + */ +static int _pam_get_item(const pam_handle_t *pamh, int item_type, + const void *_item) +{ + const void **item = (const void **)_item; + return pam_get_item(pamh, item_type, item); +} +static int _pam_get_data(const pam_handle_t *pamh, + const char *module_data_name, const void *_data) +{ + const void **data = (const void **)_data; + return pam_get_data(pamh, module_data_name, data); +} + + static const struct ntstatus_errors { const char *ntstatus_string; const char *error_string; @@ -173,7 +191,7 @@ static int converse(pam_handle_t *pamh, int nargs, int retval; struct pam_conv *conv; - retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv ); + retval = _pam_get_item(pamh, PAM_CONV, &conv ); if (retval == PAM_SUCCESS) { retval = conv->conv(nargs, (const struct pam_message **)message, response, conv->appdata_ptr); @@ -676,7 +694,7 @@ static int _winbind_read_password(pam_handle_t * pamh, */ if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { - retval = pam_get_item(pamh, authtok_flag, (const void **) &item); + retval = _pam_get_item(pamh, authtok_flag, &item); if (retval != PAM_SUCCESS) { /* very strange. */ _pam_log(LOG_ALERT, @@ -778,7 +796,7 @@ static int _winbind_read_password(pam_handle_t * pamh, retval = pam_set_item(pamh, authtok_flag, token); _pam_delete(token); /* clean it up */ if (retval != PAM_SUCCESS || - (retval = pam_get_item(pamh, authtok_flag, (const void **) &item)) != PAM_SUCCESS) { + (retval = _pam_get_item(pamh, authtok_flag, &item)) != PAM_SUCCESS) { _pam_log(LOG_CRIT, "error manipulating password"); return retval; @@ -1251,8 +1269,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * get the old token back. */ - retval = pam_get_item(pamh, PAM_OLDAUTHTOK, - (const void **) &pass_old); + retval = _pam_get_item(pamh, PAM_OLDAUTHTOK, &pass_old); if (retval != PAM_SUCCESS) { _pam_log(LOG_NOTICE, "user not authenticated"); @@ -1300,7 +1317,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * By reaching here we have approved the passwords and must now * rebuild the password database file. */ - pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET, (const void **)&pwdlastset_update); + _pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET, + &pwdlastset_update); retval = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new, pwdlastset_update); if (retval) { diff --git a/source/nsswitch/wb_client.c b/source/nsswitch/wb_client.c index de1edf054d1..b1a79471375 100644 --- a/source/nsswitch/wb_client.c +++ b/source/nsswitch/wb_client.c @@ -113,6 +113,116 @@ BOOL winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, return True; } +BOOL winbind_lookup_rids(TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + int num_rids, uint32 *rids, + const char **domain_name, + const char ***names, enum SID_NAME_USE **types) +{ + size_t i, buflen; + ssize_t len; + char *ridlist; + char *p; + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + if (num_rids == 0) { + return False; + } + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + fstrcpy(request.data.sid, sid_string_static(domain_sid)); + + len = 0; + buflen = 0; + ridlist = NULL; + + for (i=0; i<num_rids; i++) { + sprintf_append(mem_ctx, &ridlist, &len, &buflen, + "%ld\n", rids[i]); + } + + if ((num_rids != 0) && (ridlist == NULL)) { + return False; + } + + request.extra_data.data = ridlist; + request.extra_len = strlen(ridlist)+1; + + result = winbindd_request_response(WINBINDD_LOOKUPRIDS, + &request, &response); + + TALLOC_FREE(ridlist); + + if (result != NSS_STATUS_SUCCESS) { + return False; + } + + *domain_name = talloc_strdup(mem_ctx, response.data.domain_name); + + *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids); + *types = TALLOC_ARRAY(mem_ctx, enum SID_NAME_USE, num_rids); + + if ((*names == NULL) || (*types == NULL)) { + goto fail; + } + + p = response.extra_data.data; + + for (i=0; i<num_rids; i++) { + char *q; + + if (*p == '\0') { + DEBUG(10, ("Got invalid reply: %s\n", + (char *)response.extra_data.data)); + goto fail; + } + + (*types)[i] = (enum SID_NAME_USE)strtoul(p, &q, 10); + + if (*q != ' ') { + DEBUG(10, ("Got invalid reply: %s\n", + (char *)response.extra_data.data)); + goto fail; + } + + p = q+1; + + q = strchr(p, '\n'); + if (q == NULL) { + DEBUG(10, ("Got invalid reply: %s\n", + (char *)response.extra_data.data)); + goto fail; + } + + *q = '\0'; + + (*names)[i] = talloc_strdup(*names, p); + + p = q+1; + } + + if (*p != '\0') { + DEBUG(10, ("Got invalid reply: %s\n", + (char *)response.extra_data.data)); + goto fail; + } + + SAFE_FREE(response.extra_data.data); + + return True; + + fail: + TALLOC_FREE(*names); + TALLOC_FREE(*types); + return False; +} + /* Call winbindd to convert SID to uid */ BOOL winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid) diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c index 27ec27d0be5..a393855f026 100644 --- a/source/nsswitch/wbinfo.c +++ b/source/nsswitch/wbinfo.c @@ -151,6 +151,34 @@ static BOOL wbinfo_get_userinfo(char *user) return True; } +/* pull grent for a given group */ +static BOOL wbinfo_get_groupinfo(char *group) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + + fstrcpy(request.data.groupname, group); + + result = winbindd_request_response(WINBINDD_GETGRNAM, &request, + &response); + + if ( result != NSS_STATUS_SUCCESS) + return False; + + d_printf( "%s:%s:%d\n", + response.data.gr.gr_name, + response.data.gr.gr_passwd, + response.data.gr.gr_gid ); + + return True; +} + /* List groups a user is a member of */ static BOOL wbinfo_get_usergroups(char *user) @@ -201,7 +229,7 @@ static BOOL wbinfo_get_usersids(char *user_sid) if (result != NSS_STATUS_SUCCESS) return False; - s = response.extra_data.data; + s = (const char *)response.extra_data.data; for (i = 0; i < response.data.num_entries; i++) { d_printf("%s\n", s); s += strlen(s) + 1; @@ -608,6 +636,64 @@ static BOOL wbinfo_lookupsid(char *sid) return True; } +/* Lookup a list of RIDs */ + +static BOOL wbinfo_lookuprids(char *domain_sid, char *arg) +{ + size_t i; + DOM_SID sid; + int num_rids; + uint32 *rids; + const char *p; + char ridstr[32]; + const char **names; + enum SID_NAME_USE *types; + const char *domain_name; + TALLOC_CTX *mem_ctx; + + if (!string_to_sid(&sid, domain_sid)) { + d_printf("Could not convert %s to sid\n", domain_sid); + return False; + } + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + d_printf("talloc_new failed\n"); + return False; + } + + num_rids = 0; + rids = NULL; + p = arg; + + while (next_token(&p, ridstr, " ,\n", sizeof(ridstr))) { + uint32 rid = strtoul(ridstr, NULL, 10); + ADD_TO_ARRAY(mem_ctx, uint32, rid, &rids, &num_rids); + } + + if (rids == NULL) { + TALLOC_FREE(mem_ctx); + return False; + } + + if (!winbind_lookup_rids(mem_ctx, &sid, num_rids, rids, + &domain_name, &names, &types)) { + d_printf("winbind_lookup_rids failed\n"); + TALLOC_FREE(mem_ctx); + return False; + } + + d_printf("Domain: %s\n", domain_name); + + for (i=0; i<num_rids; i++) { + d_printf("%8d: %s (%s)\n", rids[i], names[i], + sid_type_lookup(types[i])); + } + + TALLOC_FREE(mem_ctx); + return True; +} + /* Convert string to sid */ static BOOL wbinfo_lookupname(char *name) @@ -1092,7 +1178,8 @@ enum { OPT_ALLOCATE_GID, OPT_SEPARATOR, OPT_LIST_ALL_DOMAINS, - OPT_LIST_OWN_DOMAIN + OPT_LIST_OWN_DOMAIN, + OPT_GROUP_INFO, }; int main(int argc, char **argv) @@ -1117,6 +1204,7 @@ int main(int argc, char **argv) { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name", "IP" }, { "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n', "Converts name to sid", "NAME" }, { "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's', "Converts sid to name", "SID" }, + { "lookup-rids", 'R', POPT_ARG_STRING, &string_arg, 'R', "Converts RIDs to names", "RIDs" }, { "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U', "Converts uid to sid" , "UID" }, { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" }, { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" }, @@ -1132,6 +1220,7 @@ int main(int argc, char **argv) { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" }, { "domain-info", 'D', POPT_ARG_STRING, &string_arg, 'D', "Show most of the info we have about the domain" }, { "user-info", 'i', POPT_ARG_STRING, &string_arg, 'i', "Get user info", "USER" }, + { "group-info", 0, POPT_ARG_STRING, &string_arg, OPT_GROUP_INFO, "Get group info", "GROUP" }, { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" }, { "user-domgroups", 0, POPT_ARG_STRING, &string_arg, OPT_USERDOMGROUPS, "Get user domain groups", "SID" }, @@ -1210,6 +1299,12 @@ int main(int argc, char **argv) goto done; } break; + case 'R': + if (!wbinfo_lookuprids(opt_domain_name, string_arg)) { + d_fprintf(stderr, "Could not lookup RIDs %s\n", string_arg); + goto done; + } + break; case 'n': if (!wbinfo_lookupname(string_arg)) { d_fprintf(stderr, "Could not lookup name %s\n", string_arg); @@ -1298,6 +1393,13 @@ int main(int argc, char **argv) goto done; } break; + case OPT_GROUP_INFO: + if ( !wbinfo_get_groupinfo(string_arg)) { + d_fprintf(stderr, "Could not get info for " + "group %s\n", string_arg); + goto done; + } + break; case 'r': if (!wbinfo_get_usergroups(string_arg)) { d_fprintf(stderr, "Could not get groups for user %s\n", diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c index 046ea40f59a..e5582915b2f 100644 --- a/source/nsswitch/winbindd.c +++ b/source/nsswitch/winbindd.c @@ -227,6 +227,7 @@ static struct winbindd_dispatch_table { { WINBINDD_LOOKUPSID, winbindd_lookupsid, "LOOKUPSID" }, { WINBINDD_LOOKUPNAME, winbindd_lookupname, "LOOKUPNAME" }, + { WINBINDD_LOOKUPRIDS, winbindd_lookuprids, "LOOKUPRIDS" }, /* Lookup related functions */ diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h index 7d5330dccb2..a16613258b1 100644 --- a/source/nsswitch/winbindd.h +++ b/source/nsswitch/winbindd.h @@ -245,6 +245,15 @@ struct winbindd_methods { char **name, enum SID_NAME_USE *type); + NTSTATUS (*rids_to_names)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + uint32 *rids, + size_t num_rids, + char **domain_name, + char ***names, + enum SID_NAME_USE **types); + /* lookup user info for a given SID */ NTSTATUS (*query_user)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, diff --git a/source/nsswitch/winbindd_ads.c b/source/nsswitch/winbindd_ads.c index 250b5f3b8c2..07127a63166 100644 --- a/source/nsswitch/winbindd_ads.c +++ b/source/nsswitch/winbindd_ads.c @@ -1119,6 +1119,7 @@ struct winbindd_methods ads_methods = { enum_local_groups, msrpc_name_to_sid, msrpc_sid_to_name, + msrpc_rids_to_names, query_user, lookup_usergroups, msrpc_lookup_useraliases, diff --git a/source/nsswitch/winbindd_async.c b/source/nsswitch/winbindd_async.c index 7f282df929d..6169b8299ec 100644 --- a/source/nsswitch/winbindd_async.c +++ b/source/nsswitch/winbindd_async.c @@ -116,7 +116,7 @@ static void idmap_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ) = c; + void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c; if (!success) { DEBUG(5, ("Could not trigger idmap_set_mapping\n")); @@ -149,7 +149,7 @@ void idmap_set_mapping_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, sid_to_string(request.data.dual_idmapset.sid, sid); do_async(mem_ctx, idmap_child(), &request, idmap_set_mapping_recv, - cont, private_data); + (void *)cont, private_data); } enum winbindd_result winbindd_dual_idmapset(struct winbindd_domain *domain, @@ -188,7 +188,7 @@ void idmap_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc, sid_to_string(request.data.dual_sid2id.sid, sid); request.data.dual_sid2id.alloc = alloc; do_async(mem_ctx, idmap_child(), &request, idmap_sid2uid_recv, - cont, private_data); + (void *)cont, private_data); } enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain, @@ -211,7 +211,7 @@ enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain, result = idmap_sid_to_uid(&sid, &(state->response.data.uid), state->request.data.dual_sid2id.alloc ? - 0 : ID_QUERY_ONLY); + 0 : IDMAP_FLAG_QUERY_ONLY); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } @@ -220,7 +220,8 @@ static void idmap_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, uid_t uid) = c; + void (*cont)(void *priv, BOOL succ, uid_t uid) = + (void (*)(void *, BOOL, uid_t))c; if (!success) { DEBUG(5, ("Could not trigger sid2uid\n")); @@ -251,7 +252,7 @@ void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid, request.cmd = WINBINDD_DUAL_UID2NAME; request.data.uid = uid; do_async(mem_ctx, idmap_child(), &request, uid2name_recv, - cont, private_data); + (void *)cont, private_data); } enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain, @@ -277,7 +278,8 @@ static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, const char *name) = c; + void (*cont)(void *priv, BOOL succ, const char *name) = + (void (*)(void *, BOOL, const char *))c; if (!success) { DEBUG(5, ("Could not trigger uid2name\n")); @@ -308,7 +310,7 @@ static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name, request.cmd = WINBINDD_DUAL_NAME2UID; fstrcpy(request.data.username, name); do_async(mem_ctx, idmap_child(), &request, name2uid_recv, - cont, private_data); + (void *)cont, private_data); } enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain, @@ -336,7 +338,8 @@ static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, uid_t uid) = c; + void (*cont)(void *priv, BOOL succ, uid_t uid) = + (void (*)(void *, BOOL, uid_t))c; if (!success) { DEBUG(5, ("Could not trigger name2uid\n")); @@ -371,7 +374,7 @@ void idmap_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc, request.data.dual_sid2id.alloc = alloc; do_async(mem_ctx, idmap_child(), &request, idmap_sid2gid_recv, - cont, private_data); + (void *)cont, private_data); } enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain, @@ -392,9 +395,9 @@ enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain, /* Find gid for this sid and return it, possibly ask the slow remote * idmap */ - result = idmap_sid_to_gid(&sid, &(state->response.data.gid), + result = idmap_sid_to_gid(&sid, &state->response.data.gid, state->request.data.dual_sid2id.alloc ? - 0 : ID_QUERY_ONLY); + 0 : IDMAP_FLAG_QUERY_ONLY); /* If the lookup failed, the perhaps we need to look at the passdb for local groups */ @@ -412,7 +415,8 @@ static void idmap_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, gid_t gid) = c; + void (*cont)(void *priv, BOOL succ, gid_t gid) = + (void (*)(void *, BOOL, gid_t))c; if (!success) { DEBUG(5, ("Could not trigger sid2gid\n")); @@ -433,7 +437,8 @@ static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, const char *name) = c; + void (*cont)(void *priv, BOOL succ, const char *name) = + (void (*)(void *, BOOL, const char *))c; if (!success) { DEBUG(5, ("Could not trigger gid2name\n")); @@ -460,7 +465,7 @@ void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid, request.cmd = WINBINDD_DUAL_GID2NAME; request.data.gid = gid; do_async(mem_ctx, idmap_child(), &request, gid2name_recv, - cont, private_data); + (void *)cont, private_data); } enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain, @@ -493,7 +498,7 @@ static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name, request.cmd = WINBINDD_DUAL_NAME2GID; fstrcpy(request.data.groupname, name); do_async(mem_ctx, idmap_child(), &request, name2gid_recv, - cont, private_data); + (void *)cont, private_data); } enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain, @@ -521,7 +526,8 @@ static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success, struct winbindd_response *response, void *c, void *private_data) { - void (*cont)(void *priv, BOOL succ, gid_t gid) = c; + void (*cont)(void *priv, BOOL succ, gid_t gid) = + (void (*)(void *, BOOL, gid_t))c; if (!success) { DEBUG(5, ("Could not trigger name2gid\n")); @@ -544,7 +550,9 @@ static void lookupsid_recv(TALLOC_CTX *mem_ctx, BOOL success, void *c, void *private_data) { void (*cont)(void *priv, BOOL succ, const char *dom_name, - const char *name, enum SID_NAME_USE type) = c; + const char *name, enum SID_NAME_USE type) = + (void (*)(void *, BOOL, const char *, const char *, + enum SID_NAME_USE))c; if (!success) { DEBUG(5, ("Could not trigger lookupsid\n")); @@ -559,7 +567,8 @@ static void lookupsid_recv(TALLOC_CTX *mem_ctx, BOOL success, } cont(private_data, True, response->data.name.dom_name, - response->data.name.name, response->data.name.type); + response->data.name.name, + (enum SID_NAME_USE)response->data.name.type); } void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, @@ -585,7 +594,7 @@ void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, fstrcpy(request.data.sid, sid_string_static(sid)); do_async_domain(mem_ctx, domain, &request, lookupsid_recv, - cont, private_data); + (void *)cont, private_data); } enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain, @@ -628,7 +637,8 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success, void *c, void *private_data) { void (*cont)(void *priv, BOOL succ, const DOM_SID *sid, - enum SID_NAME_USE type) = c; + enum SID_NAME_USE type) = + (void (*)(void *, BOOL, const DOM_SID *, enum SID_NAME_USE))c; DOM_SID sid; if (!success) { @@ -650,7 +660,8 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success, return; } - cont(private_data, True, &sid, response->data.sid.type); + cont(private_data, True, &sid, + (enum SID_NAME_USE)response->data.sid.type); } void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, const char *dom_name, @@ -677,7 +688,7 @@ void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, const char *dom_name, fstrcpy(request.data.name.name, name); do_async_domain(mem_ctx, domain, &request, lookupname_recv, - cont, private_data); + (void *)cont, private_data); } enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain, @@ -740,8 +751,8 @@ BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, return True; } -BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr, - DOM_SID **sids, size_t *num_sids) +static BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr, + DOM_SID **sids, size_t *num_sids) { char *p, *q; @@ -768,28 +779,8 @@ BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr, return True; } -BOOL print_ridlist(TALLOC_CTX *mem_ctx, uint32 *rids, size_t num_rids, - char **result, ssize_t *len) -{ - size_t i; - size_t buflen = 0; - - *len = 0; - *result = NULL; - for (i=0; i<num_rids; i++) { - sprintf_append(mem_ctx, result, len, &buflen, - "%ld\n", rids[i]); - } - - if ((num_rids != 0) && (*result == NULL)) { - return False; - } - - return True; -} - -BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr, - uint32 **sids, size_t *num_rids) +static BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr, + uint32 **rids, size_t *num_rids) { char *p; @@ -806,17 +797,76 @@ BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr, return False; } p = q+1; - ADD_TO_ARRAY(mem_ctx, uint32, rid, sids, num_rids); + ADD_TO_ARRAY(mem_ctx, uint32, rid, rids, num_rids); } return True; } +enum winbindd_result winbindd_dual_lookuprids(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + uint32 *rids = NULL; + size_t i, buflen, num_rids = 0; + ssize_t len; + DOM_SID domain_sid; + char *domain_name; + char **names; + enum SID_NAME_USE *types; + NTSTATUS status; + char *result; + + DEBUG(10, ("Looking up RIDs for domain %s (%s)\n", + state->request.domain_name, + state->request.data.sid)); + + if (!parse_ridlist(state->mem_ctx, state->request.extra_data.data, + &rids, &num_rids)) { + DEBUG(5, ("Could not parse ridlist\n")); + return WINBINDD_ERROR; + } + + if (!string_to_sid(&domain_sid, state->request.data.sid)) { + DEBUG(5, ("Could not parse domain sid %s\n", + state->request.data.sid)); + return WINBINDD_ERROR; + } + + status = domain->methods->rids_to_names(domain, state->mem_ctx, + &domain_sid, rids, num_rids, + &domain_name, + &names, &types); + + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) { + return WINBINDD_ERROR; + } + + len = 0; + buflen = 0; + result = NULL; + + for (i=0; i<num_rids; i++) { + sprintf_append(state->mem_ctx, &result, &len, &buflen, + "%d %s\n", types[i], names[i]); + } + + fstrcpy(state->response.data.domain_name, domain_name); + + if (result != NULL) { + state->response.extra_data.data = SMB_STRDUP(result); + state->response.length += len+1; + } + + return WINBINDD_OK; +} + static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success, struct winbindd_response *response, void *c, void *private_data) { void (*cont)(void *priv, BOOL succ, - DOM_SID *aliases, size_t num_aliases) = c; + DOM_SID *aliases, size_t num_aliases) = + (void (*)(void *, BOOL, DOM_SID *, size_t))c; char *aliases_str; DOM_SID *sids = NULL; size_t num_sids = 0; @@ -833,7 +883,7 @@ static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success, return; } - aliases_str = response->extra_data.data; + aliases_str = (char *)response->extra_data.data; if (aliases_str == NULL) { DEBUG(10, ("getsidaliases return 0 SIDs\n")); @@ -881,7 +931,7 @@ void winbindd_getsidaliases_async(struct winbindd_domain *domain, request.extra_data.data = sidstr; do_async_domain(mem_ctx, domain, &request, getsidaliases_recv, - cont, private_data); + (void *)cont, private_data); } enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain, @@ -937,12 +987,15 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain, add_sid_to_array(state->mem_ctx, &sid, &sids, &num_sids); } - if (!print_sidlist(NULL, sids, num_sids, - (char **)&state->response.extra_data.data, &len)) { + + if (!print_sidlist(NULL, sids, num_sids, &sidstr, &len)) { DEBUG(0, ("Could not print_sidlist\n")); + state->response.extra_data.data = NULL; return WINBINDD_ERROR; } + state->response.extra_data.data = sidstr; + if (state->response.extra_data.data != NULL) { DEBUG(10, ("aliases_list: %s\n", (char *)state->response.extra_data.data)); @@ -1026,7 +1079,7 @@ static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success, return; } - sids_str = response->extra_data.data; + sids_str = (char *)response->extra_data.data; if (sids_str == NULL) { /* This could be normal if we are dealing with a @@ -1070,7 +1123,7 @@ static void gettoken_recvaliases(void *private_data, BOOL success, const DOM_SID *aliases, size_t num_aliases) { - struct gettoken_state *state = private_data; + struct gettoken_state *state = (struct gettoken_state *)private_data; size_t i; if (!success) { @@ -1140,7 +1193,7 @@ void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, /* Query only the local tdb, everything else might possibly block */ - result = idmap_sid_to_uid(sid, &uid, ID_QUERY_ONLY|ID_CACHE_ONLY); + result = idmap_sid_to_uid(sid, &uid, IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY); if (NT_STATUS_IS_OK(result)) { cont(private_data, True, uid); @@ -1302,7 +1355,7 @@ void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, /* Query only the local tdb, everything else might possibly block */ - result = idmap_sid_to_gid(sid, &gid, ID_QUERY_ONLY|ID_CACHE_ONLY); + result = idmap_sid_to_gid(sid, &gid, IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY); if (NT_STATUS_IS_OK(result)) { cont(private_data, True, gid); @@ -1437,7 +1490,9 @@ static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success, { void (*cont)(void *priv, BOOL succ, const char *acct_name, const char *full_name, const char *homedir, - const char *shell, uint32 group_rid) = c; + const char *shell, uint32 group_rid) = + (void (*)(void *, BOOL, const char *, const char *, + const char *, const char *, uint32))c; if (!success) { DEBUG(5, ("Could not trigger query_user\n")); @@ -1467,5 +1522,5 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, request.cmd = WINBINDD_DUAL_USERINFO; sid_to_string(request.data.sid, sid); do_async_domain(mem_ctx, domain, &request, query_user_recv, - cont, private_data); + (void *)cont, private_data); } diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c index b267a3f7705..95a66420c59 100644 --- a/source/nsswitch/winbindd_cache.c +++ b/source/nsswitch/winbindd_cache.c @@ -66,7 +66,7 @@ void winbindd_check_cache_size(time_t t) return; } - if (fstat(wcache->tdb->fd, &st) == -1) { + if (fstat(tdb_fd(wcache->tdb), &st) == -1) { DEBUG(0, ("Unable to check size of tdb cache %s!\n", strerror(errno) )); return; } @@ -259,7 +259,7 @@ static char *centry_string(struct cache_entry *centry, TALLOC_CTX *mem_ctx) smb_panic("centry_string"); } - ret = TALLOC(mem_ctx, len+1); + ret = TALLOC_ARRAY(mem_ctx, char, len+1); if (!ret) { smb_panic("centry_string out of memory\n"); } @@ -567,7 +567,8 @@ static void centry_expand(struct cache_entry *centry, uint32 len) if (centry->len - centry->ofs >= len) return; centry->len *= 2; - centry->data = SMB_REALLOC(centry->data, centry->len); + centry->data = SMB_REALLOC_ARRAY(centry->data, unsigned char, + centry->len); if (!centry->data) { DEBUG(0,("out of memory: needed %d bytes in centry_expand\n", centry->len)); smb_panic("out of memory in centry_expand"); @@ -1316,6 +1317,128 @@ do_query: return status; } +static NTSTATUS rids_to_names(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + uint32 *rids, + size_t num_rids, + char **domain_name, + char ***names, + enum SID_NAME_USE **types) +{ + struct winbind_cache *cache = get_cache(domain); + size_t i; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + BOOL have_mapped; + BOOL have_unmapped; + + *domain_name = NULL; + *names = NULL; + *types = NULL; + + if (!cache->tdb) { + goto do_query; + } + + if (num_rids == 0) { + return NT_STATUS_OK; + } + + *names = TALLOC_ARRAY(mem_ctx, char *, num_rids); + *types = TALLOC_ARRAY(mem_ctx, enum SID_NAME_USE, num_rids); + + if ((*names == NULL) || (*types == NULL)) { + result = NT_STATUS_NO_MEMORY; + goto error; + } + + have_mapped = have_unmapped = False; + + for (i=0; i<num_rids; i++) { + DOM_SID sid; + struct cache_entry *centry; + + if (!sid_compose(&sid, domain_sid, rids[i])) { + result = NT_STATUS_INTERNAL_ERROR; + goto error; + } + + centry = wcache_fetch(cache, domain, "SN/%s", + sid_string_static(&sid)); + if (!centry) { + goto do_query; + } + + (*types)[i] = SID_NAME_UNKNOWN; + (*names)[i] = talloc_strdup(*names, ""); + + if (NT_STATUS_IS_OK(centry->status)) { + char *dom; + have_mapped = True; + (*types)[i] = (enum SID_NAME_USE)centry_uint32(centry); + dom = centry_string(centry, mem_ctx); + if (*domain_name == NULL) { + *domain_name = dom; + } else { + talloc_free(dom); + } + (*names)[i] = centry_string(centry, *names); + } else { + have_unmapped = True; + } + + centry_free(centry); + } + + if (!have_mapped) { + return NT_STATUS_NONE_MAPPED; + } + if (!have_unmapped) { + return NT_STATUS_OK; + } + return STATUS_SOME_UNMAPPED; + + do_query: + + TALLOC_FREE(*names); + TALLOC_FREE(*types); + + result = domain->backend->rids_to_names(domain, mem_ctx, domain_sid, + rids, num_rids, domain_name, + names, types); + + if (!NT_STATUS_IS_OK(result) && + !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) { + return result; + } + + refresh_sequence_number(domain, False); + + for (i=0; i<num_rids; i++) { + DOM_SID sid; + NTSTATUS status; + + if (!sid_compose(&sid, domain_sid, rids[i])) { + result = NT_STATUS_INTERNAL_ERROR; + goto error; + } + + status = (*types)[i] == SID_NAME_UNKNOWN ? + NT_STATUS_NONE_MAPPED : NT_STATUS_OK; + + wcache_save_sid_to_name(domain, status, &sid, *domain_name, + (*names)[i], (*types)[i]); + } + + return result; + + error: + + TALLOC_FREE(*names); + TALLOC_FREE(*types); + return result; +} + /* Lookup user information from a rid */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -1914,7 +2037,7 @@ void cache_store_response(pid_t pid, struct winbindd_response *response) fstr_sprintf(key_str, "DR/%d", pid); if (tdb_store(wcache->tdb, string_tdb_data(key_str), - make_tdb_data((void *)response, sizeof(*response)), + make_tdb_data((const char *)response, sizeof(*response)), TDB_REPLACE) == -1) return; @@ -1928,7 +2051,7 @@ void cache_store_response(pid_t pid, struct winbindd_response *response) fstr_sprintf(key_str, "DE/%d", pid); if (tdb_store(wcache->tdb, string_tdb_data(key_str), - make_tdb_data(response->extra_data.data, + make_tdb_data((const char *)response->extra_data.data, response->length - sizeof(*response)), TDB_REPLACE) == 0) return; @@ -2313,7 +2436,7 @@ BOOL set_global_winbindd_state_offline(void) return True; } - wcache->tdb->ecode = 0; +/* wcache->tdb->ecode = 0; */ data = tdb_fetch_bystring( wcache->tdb, "WINBINDD_OFFLINE" ); @@ -2368,6 +2491,7 @@ struct winbindd_methods cache_methods = { enum_local_groups, name_to_sid, sid_to_name, + rids_to_names, query_user, lookup_usergroups, lookup_useraliases, diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c index c1276bd9612..2b8a8898ac6 100644 --- a/source/nsswitch/winbindd_cm.c +++ b/source/nsswitch/winbindd_cm.c @@ -214,7 +214,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, goto done; } - if ((*cli = cli_initialise(NULL)) == NULL) { + if ((*cli = cli_initialise()) == NULL) { DEBUG(1, ("Could not cli_initialize\n")); result = NT_STATUS_NO_MEMORY; goto done; diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c index 0cc35277b05..5908c78d9a8 100644 --- a/source/nsswitch/winbindd_dual.c +++ b/source/nsswitch/winbindd_dual.c @@ -345,6 +345,7 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = { { WINBINDD_LOOKUPSID, winbindd_dual_lookupsid, "LOOKUPSID" }, { WINBINDD_LOOKUPNAME, winbindd_dual_lookupname, "LOOKUPNAME" }, + { WINBINDD_LOOKUPRIDS, winbindd_dual_lookuprids, "LOOKUPRIDS" }, { WINBINDD_LIST_TRUSTDOM, winbindd_dual_list_trusted_domains, "LIST_TRUSTDOM" }, { WINBINDD_INIT_CONNECTION, winbindd_dual_init_connection, "INIT_CONNECTION" }, { WINBINDD_GETDCNAME, winbindd_dual_getdcname, "GETDCNAME" }, diff --git a/source/nsswitch/winbindd_nss.h b/source/nsswitch/winbindd_nss.h index 2afefcc12ca..6167a10c464 100644 --- a/source/nsswitch/winbindd_nss.h +++ b/source/nsswitch/winbindd_nss.h @@ -34,7 +34,7 @@ /* Update this when you change the interface. */ -#define WINBIND_INTERFACE_VERSION 14 +#define WINBIND_INTERFACE_VERSION 15 /* Socket commands */ @@ -76,6 +76,7 @@ enum winbindd_cmd { WINBINDD_LOOKUPSID, WINBINDD_LOOKUPNAME, + WINBINDD_LOOKUPRIDS, /* Lookup functions */ diff --git a/source/nsswitch/winbindd_passdb.c b/source/nsswitch/winbindd_passdb.c index b949ea08085..d73917ef830 100644 --- a/source/nsswitch/winbindd_passdb.c +++ b/source/nsswitch/winbindd_passdb.c @@ -286,6 +286,18 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, return NT_STATUS_OK; } +static NTSTATUS rids_to_names(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + uint32 *rids, + size_t num_rids, + char **domain_name, + char ***names, + enum SID_NAME_USE **types) +{ + return NT_STATUS_UNSUCCESSFUL; +} + /* Lookup user information from a rid or username. */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -353,15 +365,21 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, const DOM_SID **sids; struct lsa_dom_info *lsa_domains; struct lsa_name_info *lsa_names; + TALLOC_CTX *tmp_ctx; if (!sid_check_is_in_our_domain(group_sid)) { /* There's no groups, only aliases in BUILTIN */ return NT_STATUS_NO_SUCH_GROUP; } - result = pdb_enum_group_members(mem_ctx, group_sid, &rids, + if (!(tmp_ctx = talloc_init("lookup_groupmem"))) { + return NT_STATUS_NO_MEMORY; + } + + result = pdb_enum_group_members(tmp_ctx, group_sid, &rids, &num_members); if (!NT_STATUS_IS_OK(result)) { + TALLOC_FREE(tmp_ctx); return result; } @@ -370,29 +388,39 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, *sid_mem = NULL; *names = NULL; *name_types = NULL; + TALLOC_FREE(tmp_ctx); return NT_STATUS_OK; } *sid_mem = TALLOC_ARRAY(mem_ctx, DOM_SID, num_members); *names = TALLOC_ARRAY(mem_ctx, char *, num_members); *name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members); - sids = TALLOC_ARRAY(mem_ctx, const DOM_SID *, num_members); + sids = TALLOC_ARRAY(tmp_ctx, const DOM_SID *, num_members); if (((*sid_mem) == NULL) || ((*names) == NULL) || ((*name_types) == NULL) || (sids == NULL)) { + TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } + /* + * Prepare an array of sid pointers for the lookup_sids calling + * convention. + */ + for (i=0; i<num_members; i++) { DOM_SID *sid = &((*sid_mem)[i]); - sid_copy(sid, &domain->sid); - sid_append_rid(sid, rids[i]); + if (!sid_compose(sid, &domain->sid, rids[i])) { + TALLOC_FREE(tmp_ctx); + return NT_STATUS_INTERNAL_ERROR; + } sids[i] = sid; } - result = lookup_sids(mem_ctx, num_members, sids, 1, + result = lookup_sids(tmp_ctx, num_members, sids, 1, &lsa_domains, &lsa_names); if (!NT_STATUS_IS_OK(result)) { + TALLOC_FREE(tmp_ctx); return result; } @@ -403,8 +431,12 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, sid_type_lookup(lsa_names[i].type))); continue; } - (*names)[i] = talloc_steal((*names), - lsa_names[i].name); + if (!((*names)[i] = talloc_strdup((*names), + lsa_names[i].name))) { + TALLOC_FREE(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + (*name_types)[i] = lsa_names[i].type; num_mapped += 1; @@ -412,6 +444,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, *num_names = num_mapped; + TALLOC_FREE(tmp_ctx); return NT_STATUS_OK; } @@ -497,15 +530,21 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, NTSTATUS nt_status; struct trustdom_info **domains; int i; + TALLOC_CTX *tmp_ctx; *num_domains = 0; *names = NULL; *alt_names = NULL; *dom_sids = NULL; - nt_status = secrets_trusted_domains(mem_ctx, num_domains, + if (!(tmp_ctx = talloc_init("trusted_domains"))) { + return NT_STATUS_NO_MEMORY; + } + + nt_status = secrets_trusted_domains(tmp_ctx, num_domains, &domains); if (!NT_STATUS_IS_OK(nt_status)) { + TALLOC_FREE(tmp_ctx); return nt_status; } @@ -514,15 +553,21 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, *dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains); if ((*alt_names == NULL) || (*names == NULL) || (*dom_sids == NULL)) { + TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } for (i=0; i<*num_domains; i++) { (*alt_names)[i] = NULL; - (*names)[i] = talloc_steal((*names), domains[i]->name); + if (!((*names)[i] = talloc_strdup((*names), + domains[i]->name))) { + TALLOC_FREE(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } sid_copy(&(*dom_sids)[i], &domains[i]->sid); } + TALLOC_FREE(tmp_ctx); return NT_STATUS_OK; } @@ -534,6 +579,7 @@ struct winbindd_methods passdb_methods = { enum_local_groups, name_to_sid, sid_to_name, + rids_to_names, query_user, lookup_usergroups, lookup_useraliases, diff --git a/source/nsswitch/winbindd_reconnect.c b/source/nsswitch/winbindd_reconnect.c index 7bc8be12131..8c5d59f9af0 100644 --- a/source/nsswitch/winbindd_reconnect.c +++ b/source/nsswitch/winbindd_reconnect.c @@ -125,6 +125,30 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, return result; } +static NTSTATUS rids_to_names(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + uint32 *rids, + size_t num_rids, + char **domain_name, + char ***names, + enum SID_NAME_USE **types) +{ + NTSTATUS result; + + result = msrpc_methods.rids_to_names(domain, mem_ctx, sid, + rids, num_rids, + domain_name, names, types); + if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { + result = msrpc_methods.rids_to_names(domain, mem_ctx, sid, + rids, num_rids, + domain_name, names, + types); + } + + return result; +} + /* Lookup user information from a rid or username. */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -280,6 +304,7 @@ struct winbindd_methods reconnect_methods = { enum_local_groups, name_to_sid, sid_to_name, + rids_to_names, query_user, lookup_usergroups, lookup_useraliases, diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c index 27feea2f671..d8797ee2bc6 100644 --- a/source/nsswitch/winbindd_rpc.c +++ b/source/nsswitch/winbindd_rpc.c @@ -318,6 +318,58 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain, return NT_STATUS_OK; } +NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, + uint32 *rids, + size_t num_rids, + char **domain_name, + char ***names, + enum SID_NAME_USE **types) +{ + char **domains; + NTSTATUS result; + struct rpc_pipe_client *cli; + POLICY_HND lsa_policy; + DOM_SID *sids; + size_t i; + + DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name )); + + sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids); + if (sids == NULL) { + return NT_STATUS_NO_MEMORY; + } + + for (i=0; i<num_rids; i++) { + if (!sid_compose(&sids[i], sid, rids[i])) { + return NT_STATUS_INTERNAL_ERROR; + } + } + + result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy); + if (!NT_STATUS_IS_OK(result)) { + return result; + } + + result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy, + num_rids, sids, &domains, + names, types); + if (!NT_STATUS_IS_OK(result) && + !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) { + return result; + } + + for (i=0; i<num_rids; i++) { + if ((*types)[i] != SID_NAME_UNKNOWN) { + *domain_name = domains[i]; + break; + } + } + + return result; +} + /* Lookup user information from a rid or username. */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -772,7 +824,6 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) NTSTATUS result; POLICY_HND dom_pol; BOOL got_seq_num = False; - int retry; struct rpc_pipe_client *cli; DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name)); @@ -782,8 +833,6 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) if (!(mem_ctx = talloc_init("sequence_number[rpc]"))) return NT_STATUS_NO_MEMORY; - retry = 0; - #ifdef HAVE_LDAP if ( domain->native_mode ) { @@ -985,6 +1034,7 @@ struct winbindd_methods msrpc_methods = { enum_local_groups, msrpc_name_to_sid, msrpc_sid_to_name, + msrpc_rids_to_names, query_user, lookup_usergroups, msrpc_lookup_useraliases, diff --git a/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c index d489e267cb2..4a9e17e4c70 100644 --- a/source/nsswitch/winbindd_sid.c +++ b/source/nsswitch/winbindd_sid.c @@ -124,6 +124,34 @@ static void lookupname_recv(void *private_data, BOOL success, return; } +void winbindd_lookuprids(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + DOM_SID domain_sid; + + /* Ensure null termination */ + state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; + + DEBUG(10, ("lookup_rids: %s\n", state->request.data.sid)); + + if (!string_to_sid(&domain_sid, state->request.data.sid)) { + DEBUG(5, ("Could not convert %s to SID\n", + state->request.data.sid)); + request_error(state); + return; + } + + domain = find_lookup_domain_from_sid(&domain_sid); + if (domain == NULL) { + DEBUG(10, ("Could not find domain for name %s\n", + state->request.domain_name)); + request_error(state); + return; + } + + sendto_domain(state, domain); +} + static struct winbindd_child static_idmap_child; void init_idmap_child(void) @@ -167,8 +195,8 @@ void winbindd_sid_to_uid(struct winbindd_cli_state *state) /* Query only the local tdb, everything else might possibly block */ - result = idmap_sid_to_uid(&sid, &(state->response.data.uid), - ID_QUERY_ONLY|ID_CACHE_ONLY); + result = idmap_sid_to_uid(&sid, &state->response.data.uid, + IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY); if (NT_STATUS_IS_OK(result)) { request_ok(state); @@ -225,8 +253,8 @@ void winbindd_sid_to_gid(struct winbindd_cli_state *state) /* Query only the local tdb, everything else might possibly block */ - result = idmap_sid_to_gid(&sid, &(state->response.data.gid), - ID_QUERY_ONLY|ID_CACHE_ONLY); + result = idmap_sid_to_gid(&sid, &state->response.data.gid, + IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY); if (NT_STATUS_IS_OK(result)) { request_ok(state); @@ -285,7 +313,7 @@ void winbindd_uid_to_sid(struct winbindd_cli_state *state) } status = idmap_uid_to_sid(&sid, state->request.data.uid, - ID_QUERY_ONLY | ID_CACHE_ONLY); + IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY); if (NT_STATUS_IS_OK(status)) { sid_to_string(state->response.data.sid.sid, &sid); @@ -412,7 +440,7 @@ void winbindd_gid_to_sid(struct winbindd_cli_state *state) } status = idmap_gid_to_sid(&sid, state->request.data.gid, - ID_QUERY_ONLY | ID_CACHE_ONLY); + IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY); if (NT_STATUS_IS_OK(status)) { sid_to_string(state->response.data.sid.sid, &sid); diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c index a73b5c394cd..8a0ebbafa50 100644 --- a/source/nsswitch/winbindd_user.c +++ b/source/nsswitch/winbindd_user.c @@ -28,8 +28,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND -extern userdom_struct current_user_info; - static BOOL fillup_pw_field(const char *lp_template, const char *username, const char *domname, @@ -53,15 +51,16 @@ static BOOL fillup_pw_field(const char *lp_template, shell. */ /* The substitution of %U and %D in the 'template homedir' is done - by alloc_sub_specified() below. */ + by talloc_sub_specified() below. */ - templ = alloc_sub_specified(lp_template, username, domname, uid, gid); + templ = talloc_sub_specified(NULL, lp_template, username, domname, + uid, gid); if (!templ) return False; safe_strcpy(out, templ, sizeof(fstring) - 1); - SAFE_FREE(templ); + TALLOC_FREE(templ); return True; @@ -109,11 +108,6 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, defaults are /tmp for the home directory and /bin/false for shell. */ - /* The substitution of %U and %D in the 'template homedir' is done - by alloc_sub_specified() below. */ - - fstrcpy(current_user_info.domain, dom_name); - if (!fillup_pw_field(lp_template_homedir(), user_name, dom_name, pw->pw_uid, pw->pw_gid, homedir, pw->pw_dir)) return False; @@ -293,8 +287,6 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid) safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1); safe_strcpy(pw->pw_gecos, s->fullname, sizeof(pw->pw_gecos) - 1); - fstrcpy(current_user_info.domain, s->domain->name); - if (!fillup_pw_field(lp_template_homedir(), s->username, s->domain->name, pw->pw_uid, pw->pw_gid, s->homedir, pw->pw_dir)) { DEBUG(5, ("Could not compose homedir\n")); @@ -407,7 +399,7 @@ void winbindd_getpwuid(struct winbindd_cli_state *state) (unsigned long)state->request.data.uid)); status = idmap_uid_to_sid(&user_sid, state->request.data.uid, - ID_QUERY_ONLY | ID_CACHE_ONLY); + IDMAP_FLAG_QUERY_ONLY | IDMAP_FLAG_CACHE_ONLY); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("Could not find SID for uid %lu\n", diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c index 67b94817adb..25ba20bb9f3 100644 --- a/source/nsswitch/winbindd_util.c +++ b/source/nsswitch/winbindd_util.c @@ -1096,7 +1096,7 @@ static BOOL idmap_convert(const char *idmap_name) return False; } - bigendianheader = (idmap_tdb->flags & TDB_BIGENDIAN) ? True : False; + bigendianheader = (tdb_get_flags(idmap_tdb) & TDB_BIGENDIAN) ? True : False; vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION"); diff --git a/source/param/loadparm.c b/source/param/loadparm.c index b6c027f8714..c308378a227 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -58,6 +58,7 @@ BOOL bLoaded = False; extern pstring user_socket_options; extern enum protocol_types Protocol; +extern userdom_struct current_user_info; #ifndef GLOBAL_NAME #define GLOBAL_NAME "global" @@ -1702,11 +1703,13 @@ static char *lp_string(const char *s) if (!lp_talloc) lp_talloc = talloc_init("lp_talloc"); - tmpstr = alloc_sub_basic(get_current_username(), s); + tmpstr = alloc_sub_basic(get_current_username(), + current_user_info.domain, s); if (trim_char(tmpstr, '\"', '\"')) { if (strchr(tmpstr,'\"') != NULL) { SAFE_FREE(tmpstr); - tmpstr = alloc_sub_basic(get_current_username(),s); + tmpstr = alloc_sub_basic(get_current_username(), + current_user_info.domain, s); } } ret = talloc_strdup(lp_talloc, tmpstr); @@ -1741,11 +1744,16 @@ static char *lp_string(const char *s) const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);} #define FN_LOCAL_BOOL(fn_name,val) \ BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);} -#define FN_LOCAL_CHAR(fn_name,val) \ - char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);} #define FN_LOCAL_INTEGER(fn_name,val) \ int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);} +#define FN_LOCAL_PARM_BOOL(fn_name,val) \ + BOOL fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);} +#define FN_LOCAL_PARM_STRING(fn_name,val) \ + char *fn_name(const struct share_params *p) {return(lp_string((LP_SNUM_OK(p->service) && ServicePtrs[(p->service)]->val) ? ServicePtrs[(p->service)]->val : sDefault.val));} +#define FN_LOCAL_CHAR(fn_name,val) \ + char fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);} + FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports) FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset) FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset) @@ -1981,7 +1989,7 @@ FN_LOCAL_STRING(lp_fstype, fstype) FN_LOCAL_LIST(lp_vfs_objects, szVfsObjects) FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy) static FN_LOCAL_STRING(lp_volume, volume) -FN_LOCAL_STRING(lp_mangled_map, szMangledMap) +FN_LOCAL_PARM_STRING(lp_mangled_map, szMangledMap) FN_LOCAL_STRING(lp_veto_files, szVetoFiles) FN_LOCAL_STRING(lp_hide_files, szHideFiles) FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles) @@ -2015,7 +2023,7 @@ FN_LOCAL_BOOL(lp_share_modes, bShareModes) FN_LOCAL_BOOL(lp_oplocks, bOpLocks) FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks) FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser) -FN_LOCAL_BOOL(lp_manglednames, bMangledNames) +FN_LOCAL_PARM_BOOL(lp_manglednames, bMangledNames) FN_LOCAL_BOOL(lp_widelinks, bWidelinks) FN_LOCAL_BOOL(lp_symlinks, bSymlinks) FN_LOCAL_BOOL(lp_syncalways, bSyncAlways) @@ -3002,7 +3010,9 @@ BOOL lp_file_list_changed(void) time_t mod_time; pstrcpy(n2, f->name); - standard_sub_basic( get_current_username(), n2, sizeof(n2) ); + standard_sub_basic( get_current_username(), + current_user_info.domain, + n2, sizeof(n2) ); DEBUGADD(6, ("file %s -> %s last mod_time: %s\n", f->name, n2, ctime(&f->modtime))); @@ -3036,7 +3046,8 @@ static BOOL handle_netbios_name(int snum, const char *pszParmValue, char **ptr) pstrcpy(netbios_name, pszParmValue); - standard_sub_basic(get_current_username(), netbios_name,sizeof(netbios_name)); + standard_sub_basic(get_current_username(), current_user_info.domain, + netbios_name, sizeof(netbios_name)); ret = set_global_myname(netbios_name); string_set(&Globals.szNetbiosName,global_myname()); @@ -3094,7 +3105,8 @@ static BOOL handle_include(int snum, const char *pszParmValue, char **ptr) pstring fname; pstrcpy(fname, pszParmValue); - standard_sub_basic(get_current_username(), fname,sizeof(fname)); + standard_sub_basic(get_current_username(), current_user_info.domain, + fname,sizeof(fname)); add_to_file_list(pszParmValue, fname); @@ -4936,7 +4948,8 @@ BOOL lp_load(const char *pszFname, pstrcpy(n2, pszFname); - standard_sub_basic( get_current_username(), n2,sizeof(n2) ); + standard_sub_basic( get_current_username(), current_user_info.domain, + n2,sizeof(n2) ); add_to_file_list(pszFname, n2); @@ -5080,7 +5093,9 @@ int lp_servicenumber(const char *pszServiceName) * service names */ fstrcpy(serviceName, ServicePtrs[iService]->szService); - standard_sub_basic(get_current_username(), serviceName,sizeof(serviceName)); + standard_sub_basic(get_current_username(), + current_user_info.domain, + serviceName,sizeof(serviceName)); if (strequal(serviceName, pszServiceName)) { break; } @@ -5116,6 +5131,11 @@ int lp_servicenumber(const char *pszServiceName) return (iService); } +BOOL share_defined(const char *service_name) +{ + return (lp_servicenumber(service_name) != -1); +} + /******************************************************************* A useful volume label function. ********************************************************************/ diff --git a/source/passdb/login_cache.c b/source/passdb/login_cache.c index 9a19dcf437a..7fd3b47826f 100644 --- a/source/passdb/login_cache.c +++ b/source/passdb/login_cache.c @@ -140,7 +140,7 @@ BOOL login_cache_write(const struct samu *sampass, LOGIN_CACHE entry) entry.acct_ctrl, entry.bad_password_count, entry.bad_password_time); - databuf.dptr = SMB_MALLOC(databuf.dsize); + databuf.dptr = SMB_MALLOC_ARRAY(char, databuf.dsize); if (!databuf.dptr) { SAFE_FREE(keybuf.dptr); return False; diff --git a/source/passdb/lookup_sid.c b/source/passdb/lookup_sid.c index dba43ed6c4f..a7a3fdc94d5 100644 --- a/source/passdb/lookup_sid.c +++ b/source/passdb/lookup_sid.c @@ -63,6 +63,7 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, if ((domain == NULL) || (name == NULL)) { DEBUG(0, ("talloc failed\n")); + TALLOC_FREE(tmp_ctx); return False; } @@ -74,7 +75,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, sid_append_rid(&sid, rid); goto ok; } - goto failed; + TALLOC_FREE(tmp_ctx); + return False; } if (strequal(domain, builtin_domain_name())) { @@ -86,7 +88,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, type = SID_NAME_ALIAS; goto ok; } - goto failed; + TALLOC_FREE(tmp_ctx); + return False; } /* Try the explicit winbind lookup first, don't let it guess the @@ -102,7 +105,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, type = SID_NAME_USER; goto ok; } - goto failed; + TALLOC_FREE(tmp_ctx); + return False; } if (strequal(domain, unix_groups_domain_name())) { @@ -110,11 +114,13 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, type = SID_NAME_DOM_GRP; goto ok; } - goto failed; + TALLOC_FREE(tmp_ctx); + return False; } if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) { - goto failed; + TALLOC_FREE(tmp_ctx); + return False; } /* @@ -201,7 +207,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, if (strequal(name, get_global_sam_name())) { if (!secrets_fetch_domain_sid(name, &sid)) { DEBUG(3, ("Could not fetch my SID\n")); - goto failed; + TALLOC_FREE(tmp_ctx); + return False; } /* Swap domain and name */ tmp = name; name = domain; domain = tmp; @@ -214,7 +221,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, if (!IS_DC && strequal(name, lp_workgroup())) { if (!secrets_fetch_domain_sid(name, &sid)) { DEBUG(3, ("Could not fetch the domain SID\n")); - goto failed; + TALLOC_FREE(tmp_ctx); + return False; } /* Swap domain and name */ tmp = name; name = domain; domain = tmp; @@ -258,7 +266,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, /* Now our local possibilities are exhausted. */ if (!(flags & LOOKUP_NAME_REMOTE)) { - goto failed; + TALLOC_FREE(tmp_ctx); + return False; } /* If we are not a DC, we have to ask in our primary domain. Let @@ -298,7 +307,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, (domain_type != SID_NAME_DOMAIN)) { DEBUG(2, ("winbind could not find the domain's name " "it just looked up for us\n")); - goto failed; + TALLOC_FREE(tmp_ctx); + return False; } goto ok; } @@ -320,7 +330,10 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, goto ok; } - failed: + /* + * Ok, all possibilities tried. Fail. + */ + TALLOC_FREE(tmp_ctx); return False; @@ -331,14 +344,26 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, return False; } - if (ret_name != NULL) { - *ret_name = talloc_steal(mem_ctx, name); + /* + * Hand over the results to the talloc context we've been given. + */ + + if ((ret_name != NULL) && + !(*ret_name = talloc_strdup(mem_ctx, name))) { + DEBUG(0, ("talloc failed\n")); + TALLOC_FREE(tmp_ctx); + return False; } if (ret_domain != NULL) { - char *tmp_dom = talloc_strdup(tmp_ctx, domain); + char *tmp_dom; + if (!(tmp_dom = talloc_strdup(tmp_ctx, domain))) { + DEBUG(0, ("talloc failed\n")); + TALLOC_FREE(tmp_ctx); + return False; + } strupper_m(tmp_dom); - *ret_domain = talloc_steal(mem_ctx, tmp_dom); + *ret_domain = tmp_dom; } if (ret_sid != NULL) { @@ -353,34 +378,46 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, return True; } -static BOOL winbind_lookup_rids(TALLOC_CTX *mem_ctx, - const DOM_SID *domain_sid, - int num_rids, uint32 *rids, - const char **domain_name, - const char **names, enum SID_NAME_USE *types) +static BOOL wb_lookup_rids(TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + int num_rids, uint32 *rids, + const char **domain_name, + const char **names, enum SID_NAME_USE *types) { - /* Unless the winbind interface is upgraded, fall back to ask for - * individual sids. I imagine introducing a lookuprids operation that - * directly proxies to lsa_lookupsids to the correct DC. -- vl */ - int i; - for (i=0; i<num_rids; i++) { - DOM_SID sid; + const char **my_names; + enum SID_NAME_USE *my_types; + TALLOC_CTX *tmp_ctx; - sid_copy(&sid, domain_sid); - sid_append_rid(&sid, rids[i]); + if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) { + return False; + } - if (winbind_lookup_sid(mem_ctx, &sid, - *domain_name == NULL ? - domain_name : NULL, - &names[i], &types[i])) { - if ((names[i] == NULL) || ((*domain_name) == NULL)) { - return False; - } - } else { + if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids, + domain_name, &my_names, &my_types)) { + for (i=0; i<num_rids; i++) { types[i] = SID_NAME_UNKNOWN; } + return True; } + + /* + * winbind_lookup_rids allocates its own array. We've been given the + * array, so copy it over + */ + + for (i=0; i<num_rids; i++) { + if (my_names[i] == NULL) { + TALLOC_FREE(tmp_ctx); + return False; + } + if (!(names[i] = talloc_strdup(names, my_names[i]))) { + TALLOC_FREE(tmp_ctx); + return False; + } + types[i] = my_types[i]; + } + TALLOC_FREE(tmp_ctx); return True; } @@ -489,8 +526,8 @@ static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, return True; } - return winbind_lookup_rids(mem_ctx, domain_sid, num_rids, rids, - domain_name, *names, *types); + return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids, + domain_name, *names, *types); } /* @@ -627,18 +664,17 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids, int i, j; - tmp_ctx = talloc_new(mem_ctx); - if (tmp_ctx == NULL) { + if (!(tmp_ctx = talloc_new(mem_ctx))) { DEBUG(0, ("talloc_new failed\n")); return NT_STATUS_NO_MEMORY; } - name_infos = TALLOC_ARRAY(tmp_ctx, struct lsa_name_info, num_sids); - dom_infos = TALLOC_ZERO_ARRAY(tmp_ctx, struct lsa_dom_info, + name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids); + dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info, MAX_REF_DOMAINS); if ((name_infos == NULL) || (dom_infos == NULL)) { result = NT_STATUS_NO_MEMORY; - goto done; + goto fail; } /* First build up the data structures: @@ -673,7 +709,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids, */ if (domain_name == NULL) { result = NT_STATUS_NO_MEMORY; - goto done; + goto fail; } name_infos[i].rid = 0; @@ -687,14 +723,14 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids, name_infos, builtin_domain_name()); if (name_infos[i].name == NULL) { result = NT_STATUS_NO_MEMORY; - goto done; + goto fail; } } } else { /* This is a normal SID with rid component */ if (!sid_split_rid(&sid, &rid)) { result = NT_STATUS_INVALID_PARAMETER; - goto done; + goto fail; } } @@ -717,7 +753,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids, if (j == MAX_REF_DOMAINS) { /* TODO: What's the right error message here? */ result = NT_STATUS_NONE_MAPPED; - goto done; + goto fail; } if (!dom_infos[j].valid) { @@ -730,7 +766,11 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids, /* This name was being found above in the case * when we found a domain SID */ dom_infos[j].name = - talloc_steal(dom_infos, domain_name); + talloc_strdup(dom_infos, domain_name); + if (dom_infos[j].name == NULL) { + result = NT_STATUS_NO_MEMORY; + goto fail; + } } else { /* lookup_rids will take care of this */ dom_infos[j].name = NULL; @@ -747,7 +787,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids, if (dom_infos[j].idxs == NULL) { result = NT_STATUS_NO_MEMORY; - goto done; + goto fail; } } } @@ -756,6 +796,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids, for (i=0; i<MAX_REF_DOMAINS; i++) { uint32_t *rids; + const char *domain_name = NULL; const char **names; enum SID_NAME_USE *types; struct lsa_dom_info *dom = &dom_infos[i]; @@ -765,11 +806,9 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids, break; } - rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs); - - if (rids == NULL) { + if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) { result = NT_STATUS_NO_MEMORY; - goto done; + goto fail; } for (j=0; j<dom->num_idxs; j++) { @@ -777,31 +816,40 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids, } if (!lookup_rids(tmp_ctx, &dom->sid, - dom->num_idxs, rids, &dom->name, + dom->num_idxs, rids, &domain_name, &names, &types)) { result = NT_STATUS_NO_MEMORY; - goto done; + goto fail; } - talloc_steal(dom_infos, dom->name); - + if (!(dom->name = talloc_strdup(dom_infos, domain_name))) { + result = NT_STATUS_NO_MEMORY; + goto fail; + } + for (j=0; j<dom->num_idxs; j++) { int idx = dom->idxs[j]; name_infos[idx].type = types[j]; if (types[j] != SID_NAME_UNKNOWN) { name_infos[idx].name = - talloc_steal(name_infos, names[j]); + talloc_strdup(name_infos, names[j]); + if (name_infos[idx].name == NULL) { + result = NT_STATUS_NO_MEMORY; + goto fail; + } } else { name_infos[idx].name = NULL; } } } - *ret_domains = talloc_steal(mem_ctx, dom_infos); - *ret_names = talloc_steal(mem_ctx, name_infos); - result = NT_STATUS_OK; + *ret_domains = dom_infos; + *ret_names = name_infos; + return NT_STATUS_OK; - done: + fail: + TALLOC_FREE(dom_infos); + TALLOC_FREE(name_infos); TALLOC_FREE(tmp_ctx); return result; } @@ -819,9 +867,7 @@ BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, TALLOC_CTX *tmp_ctx; BOOL ret = False; - tmp_ctx = talloc_new(mem_ctx); - - if (tmp_ctx == NULL) { + if (!(tmp_ctx = talloc_new(mem_ctx))) { DEBUG(0, ("talloc_new failed\n")); return False; } @@ -835,12 +881,14 @@ BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, goto done; } - if (ret_domain != NULL) { - *ret_domain = talloc_steal(mem_ctx, domain->name); + if ((ret_domain != NULL) && + !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) { + goto done; } - if (ret_name != NULL) { - *ret_name = talloc_steal(mem_ctx, name->name); + if ((ret_name != NULL) && + !(*ret_name = talloc_strdup(mem_ctx, name->name))) { + goto done; } if (ret_type != NULL) { diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c index cbb30ead023..f74b1fbe3ba 100644 --- a/source/passdb/passdb.c +++ b/source/passdb/passdb.c @@ -52,7 +52,7 @@ const char *my_sam_name(void) static int samu_destroy(void *p) { - struct samu *user = p; + struct samu *user = (struct samu *)p; data_blob_clear_free( &user->lm_pw ); data_blob_clear_free( &user->nt_pw ); @@ -111,7 +111,7 @@ struct samu *samu_new( TALLOC_CTX *ctx ) user->profile_path = ""; user->acct_desc = ""; user->workstations = ""; - user->unknown_str = ""; + user->comment = ""; user->munged_dial = ""; user->plaintext_pw = NULL; @@ -926,14 +926,15 @@ BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen) if (homedir) { fstrcpy( tmpstring, homedir ); if (expand_explicit) { - standard_sub_basic( username, tmpstring, + standard_sub_basic( username, domain, tmpstring, sizeof(tmpstring) ); } pdb_set_homedir(sampass, tmpstring, PDB_SET); } else { pdb_set_homedir(sampass, - talloc_sub_basic(sampass, username, lp_logon_home()), + talloc_sub_basic(sampass, username, domain, + lp_logon_home()), PDB_DEFAULT); } @@ -945,28 +946,29 @@ BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen) if (logon_script) { fstrcpy( tmpstring, logon_script ); if (expand_explicit) { - standard_sub_basic( username, tmpstring, + standard_sub_basic( username, domain, tmpstring, sizeof(tmpstring) ); } pdb_set_logon_script(sampass, tmpstring, PDB_SET); } else { pdb_set_logon_script(sampass, - talloc_sub_basic(sampass, username, lp_logon_script()), + talloc_sub_basic(sampass, username, domain, + lp_logon_script()), PDB_DEFAULT); } if (profile_path) { fstrcpy( tmpstring, profile_path ); if (expand_explicit) { - standard_sub_basic( username, tmpstring, + standard_sub_basic( username, domain, tmpstring, sizeof(tmpstring) ); } pdb_set_profile_path(sampass, tmpstring, PDB_SET); } else { pdb_set_profile_path(sampass, - talloc_sub_basic(sampass, username, lp_logon_path()), + talloc_sub_basic(sampass, username, domain, lp_logon_path()), PDB_DEFAULT); } @@ -990,7 +992,7 @@ BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen) pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); if (pwHistLen) { - uint8 *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN); + uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN); if (!pw_hist) { ret = False; goto done; diff --git a/source/passdb/pdb_get_set.c b/source/passdb/pdb_get_set.c index 2e69240b1af..3b774b510b0 100644 --- a/source/passdb/pdb_get_set.c +++ b/source/passdb/pdb_get_set.c @@ -288,9 +288,9 @@ const char *pdb_get_workstations(const struct samu *sampass) return sampass->workstations; } -const char *pdb_get_unknown_str(const struct samu *sampass) +const char *pdb_get_comment(const struct samu *sampass) { - return sampass->unknown_str; + return sampass->comment; } const char *pdb_get_munged_dial(const struct samu *sampass) @@ -752,23 +752,22 @@ BOOL pdb_set_workstations(struct samu *sampass, const char *workstations, enum p } /********************************************************************* - Set the user's 'unknown_str', whatever the heck this actually is... ********************************************************************/ -BOOL pdb_set_unknown_str(struct samu *sampass, const char *unknown_str, enum pdb_value_state flag) +BOOL pdb_set_comment(struct samu *sampass, const char *comment, enum pdb_value_state flag) { - if (unknown_str) { - sampass->unknown_str = talloc_strdup(sampass, unknown_str); + if (comment) { + sampass->comment = talloc_strdup(sampass, comment); - if (!sampass->unknown_str) { - DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n")); + if (!sampass->comment) { + DEBUG(0, ("pdb_set_comment: talloc_strdup() failed!\n")); return False; } } else { - sampass->unknown_str = PDB_NOT_QUITE_NULL; + sampass->comment = PDB_NOT_QUITE_NULL; } - return pdb_set_init_flags(sampass, PDB_UNKNOWNSTR, flag); + return pdb_set_init_flags(sampass, PDB_COMMENT, flag); } /********************************************************************* @@ -1021,7 +1020,7 @@ BOOL pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext) if (current_history_len < pwHistLen) { /* Ensure we have space for the needed history. */ - uchar *new_history = TALLOC(sampass, + uchar *new_history = (uchar *)TALLOC(sampass, pwHistLen*PW_HISTORY_ENTRY_LEN); if (!new_history) { return False; diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c index a0310d0c71f..20aa72d24ee 100644 --- a/source/passdb/pdb_interface.c +++ b/source/passdb/pdb_interface.c @@ -361,6 +361,15 @@ static NTSTATUS pdb_default_create_user(struct pdb_methods *methods, add_ret = smbrun(add_script,NULL); DEBUG(add_ret ? 0 : 3, ("_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret)); + +#ifdef ENABLE_BUILD_FARM_HACKS + if (add_ret != 0) { + DEBUG(1, ("Creating a faked user %s for build farm " + "purposes", name)); + faked_create_user(name); + } +#endif + flush_pwnam_cache(); pwd = Get_Pwnam_alloc(tmp_ctx, name); @@ -1711,7 +1720,7 @@ struct user_search { static BOOL next_entry_users(struct pdb_search *s, struct samr_displayentry *entry) { - struct user_search *state = s->private_data; + struct user_search *state = (struct user_search *)s->private_data; struct samu *user = NULL; next: @@ -1786,7 +1795,7 @@ struct group_search { static BOOL next_entry_groups(struct pdb_search *s, struct samr_displayentry *entry) { - struct group_search *state = s->private_data; + struct group_search *state = (struct group_search *)s->private_data; uint32 rid; GROUP_MAP *map = &state->groups[state->current_group]; @@ -1804,7 +1813,8 @@ static BOOL next_entry_groups(struct pdb_search *s, static void search_end_groups(struct pdb_search *search) { - struct group_search *state = search->private_data; + struct group_search *state = + (struct group_search *)search->private_data; SAFE_FREE(state->groups); } diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c index 4d0c84b5433..83f8d7183cc 100644 --- a/source/passdb/pdb_ldap.c +++ b/source/passdb/pdb_ldap.c @@ -650,12 +650,13 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir)) { pdb_set_homedir( sampass, - talloc_sub_basic(sampass, username, lp_logon_home()), + talloc_sub_basic(sampass, username, domain, + lp_logon_home()), PDB_DEFAULT ); } else { pstrcpy( tmpstring, homedir ); if (expand_explicit) { - standard_sub_basic( username, tmpstring, + standard_sub_basic( username, domain, tmpstring, sizeof(tmpstring) ); } pdb_set_homedir(sampass, tmpstring, PDB_SET); @@ -665,12 +666,13 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script)) { pdb_set_logon_script( sampass, - talloc_sub_basic(sampass, username, lp_logon_script()), + talloc_sub_basic(sampass, username, domain, + lp_logon_script()), PDB_DEFAULT ); } else { pstrcpy( tmpstring, logon_script ); if (expand_explicit) { - standard_sub_basic( username, tmpstring, + standard_sub_basic( username, domain, tmpstring, sizeof(tmpstring) ); } pdb_set_logon_script(sampass, tmpstring, PDB_SET); @@ -680,12 +682,13 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path)) { pdb_set_profile_path( sampass, - talloc_sub_basic( sampass, username, lp_logon_path()), + talloc_sub_basic( sampass, username, domain, + lp_logon_path()), PDB_DEFAULT ); } else { pstrcpy( tmpstring, profile_path ); if (expand_explicit) { - standard_sub_basic( username, tmpstring, + standard_sub_basic( username, domain, tmpstring, sizeof(tmpstring) ); } pdb_set_profile_path(sampass, tmpstring, PDB_SET); @@ -787,7 +790,7 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state, pwHistLen = MIN(pwHistLen, MAX_PW_HISTORY_LEN); - if ((pwhist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN)) == NULL){ + if ((pwhist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN)) == NULL){ DEBUG(0, ("init_sam_from_ldap: malloc failed!\n")); return False; } @@ -967,15 +970,14 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, /* only update the RID if we actually need to */ if (need_update(sampass, PDB_USERSID)) { fstring sid_string; - fstring dom_sid_string; const DOM_SID *user_sid = pdb_get_user_sid(sampass); switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) { DEBUG(1, ("init_ldap_from_sam: User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n", - sid_to_string(sid_string, user_sid), - sid_to_string(dom_sid_string, &ldap_state->domain_sid))); + sid_string_static(user_sid), + sid_string_static(&ldap_state->domain_sid))); return False; } slprintf(temp, sizeof(temp) - 1, "%i", rid); @@ -1001,15 +1003,14 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, if (need_update(sampass, PDB_GROUPSID)) { fstring sid_string; - fstring dom_sid_string; const DOM_SID *group_sid = pdb_get_group_sid(sampass); switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) { DEBUG(1, ("init_ldap_from_sam: User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n", - sid_to_string(sid_string, group_sid), - sid_to_string(dom_sid_string, &ldap_state->domain_sid))); + sid_string_static(group_sid), + sid_string_static(&ldap_state->domain_sid))); return False; } @@ -1747,7 +1748,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc LDAPMod **mods = NULL; const char **attr_list; - result = pdb_get_backend_private_data(newpwd, my_methods); + result = (LDAPMessage *)pdb_get_backend_private_data(newpwd, my_methods); if (!result) { attr_list = get_userattr_list(NULL, ldap_state->schema_ver); if (pdb_get_username(newpwd) == NULL) { @@ -3923,7 +3924,8 @@ struct ldap_search_state { static BOOL ldapsam_search_firstpage(struct pdb_search *search) { - struct ldap_search_state *state = search->private_data; + struct ldap_search_state *state = + (struct ldap_search_state *)search->private_data; LDAP *ld; int rc = LDAP_OPERATIONS_ERROR; @@ -3975,7 +3977,8 @@ static BOOL ldapsam_search_firstpage(struct pdb_search *search) static BOOL ldapsam_search_nextpage(struct pdb_search *search) { - struct ldap_search_state *state = search->private_data; + struct ldap_search_state *state = + (struct ldap_search_state *)search->private_data; int rc; if (!state->connection->paged_results) { @@ -4005,7 +4008,8 @@ static BOOL ldapsam_search_nextpage(struct pdb_search *search) static BOOL ldapsam_search_next_entry(struct pdb_search *search, struct samr_displayentry *entry) { - struct ldap_search_state *state = search->private_data; + struct ldap_search_state *state = + (struct ldap_search_state *)search->private_data; BOOL result; retry: @@ -4040,7 +4044,8 @@ static BOOL ldapsam_search_next_entry(struct pdb_search *search, static void ldapsam_search_end(struct pdb_search *search) { - struct ldap_search_state *state = search->private_data; + struct ldap_search_state *state = + (struct ldap_search_state *)search->private_data; int rc; if (state->pagedresults_cookie == NULL) @@ -4156,7 +4161,8 @@ static BOOL ldapsam_search_users(struct pdb_methods *methods, struct pdb_search *search, uint32 acct_flags) { - struct ldapsam_privates *ldap_state = methods->private_data; + struct ldapsam_privates *ldap_state = + (struct ldapsam_privates *)methods->private_data; struct ldap_search_state *state; state = TALLOC_P(search->mem_ctx, struct ldap_search_state); @@ -4314,7 +4320,8 @@ static BOOL ldapsam_search_grouptype(struct pdb_methods *methods, const DOM_SID *sid, enum SID_NAME_USE type) { - struct ldapsam_privates *ldap_state = methods->private_data; + struct ldapsam_privates *ldap_state = + (struct ldapsam_privates *)methods->private_data; struct ldap_search_state *state; state = TALLOC_P(search->mem_ctx, struct ldap_search_state); @@ -4473,8 +4480,8 @@ static NTSTATUS ldapsam_new_rid_internal(struct pdb_methods *methods, uint32 *ri int i; for (i=0; i<10; i++) { - NTSTATUS result = ldapsam_get_new_rid(methods->private_data, - rid); + NTSTATUS result = ldapsam_get_new_rid( + (struct ldapsam_privates *)methods->private_data, rid); if (NT_STATUS_IS_OK(result)) { return result; } @@ -4500,7 +4507,8 @@ static BOOL ldapsam_sid_to_id(struct pdb_methods *methods, const DOM_SID *sid, union unid_t *id, enum SID_NAME_USE *type) { - struct ldapsam_privates *priv = methods->private_data; + struct ldapsam_privates *priv = + (struct ldapsam_privates *)methods->private_data; char *filter; const char *attrs[] = { "sambaGroupType", "gidNumber", "uidNumber", NULL }; @@ -5487,7 +5495,7 @@ NTSTATUS pdb_init_ldapsam_compat(struct pdb_methods **pdb_method, const char *lo (*pdb_method)->name = "ldapsam_compat"; - ldap_state = (*pdb_method)->private_data; + ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data); ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT; sid_copy(&ldap_state->domain_sid, get_global_sam_sid()); @@ -5545,7 +5553,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location) } } - ldap_state = (*pdb_method)->private_data; + ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data); ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT; /* Try to setup the Domain Name, Domain SID, algorithmic rid base */ diff --git a/source/passdb/pdb_nds.c b/source/passdb/pdb_nds.c index 08ad96efa4b..ab4a1a7f208 100644 --- a/source/passdb/pdb_nds.c +++ b/source/passdb/pdb_nds.c @@ -241,7 +241,7 @@ static int berDecodeLoginData( if(retData) { retOctStrLen = *retDataLen + 1; - retOctStr = SMB_MALLOC(retOctStrLen); + retOctStr = SMB_MALLOC_ARRAY(char, retOctStrLen); if(!retOctStr) { err = LDAP_OPERATIONS_ERROR; @@ -404,7 +404,7 @@ static int nmasldap_get_simple_pwd( size_t pwdBufLen, bufferLen; bufferLen = pwdBufLen = pwdLen+2; - pwdBuf = SMB_MALLOC(pwdBufLen); /* digest and null */ + pwdBuf = SMB_MALLOC_ARRAY(char, pwdBufLen); /* digest and null */ if(pwdBuf == NULL) { return LDAP_NO_MEMORY; @@ -568,7 +568,7 @@ static int nmasldap_get_password( } bufferLen = pwdBufLen = *pwdSize; - pwdBuf = SMB_MALLOC(pwdBufLen+2); + pwdBuf = SMB_MALLOC_ARRAY(char, pwdBufLen+2); if(pwdBuf == NULL) { return LDAP_NO_MEMORY; @@ -769,7 +769,7 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods, DEBUG(5,("pdb_nds_update_login_attempts: %s login for %s\n", success ? "Successful" : "Failed", username)); - result = pdb_get_backend_private_data(sam_acct, methods); + result = (LDAPMessage *)pdb_get_backend_private_data(sam_acct, methods); if (!result) { attr_list = get_userattr_list(NULL, ldap_state->schema_ver); @@ -854,7 +854,8 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods, static NTSTATUS pdb_init_NDS_ldapsam_common(struct pdb_methods **pdb_method, const char *location) { - struct ldapsam_privates *ldap_state = (*pdb_method)->private_data; + struct ldapsam_privates *ldap_state = + (struct ldapsam_privates *)((*pdb_method)->private_data); /* Mark this as eDirectory ldap */ ldap_state->is_nds_ldap = True; diff --git a/source/passdb/pdb_smbpasswd.c b/source/passdb/pdb_smbpasswd.c index a8a42196d48..aec1db48b5d 100644 --- a/source/passdb/pdb_smbpasswd.c +++ b/source/passdb/pdb_smbpasswd.c @@ -584,7 +584,8 @@ static char *format_new_smbpasswd_entry(const struct smb_passwd *newpwd) Routine to add an entry to the smbpasswd file. *************************************************************************/ -static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, struct smb_passwd *newpwd) +static NTSTATUS add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, + struct smb_passwd *newpwd) { const char *pfile = smbpasswd_state->smbpasswd_file; struct smb_passwd *pwd = NULL; @@ -605,7 +606,7 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str if (fp == NULL) { DEBUG(0, ("add_smbfilepwd_entry: unable to open file.\n")); - return False; + return map_nt_error_from_unix(errno); } /* @@ -616,7 +617,7 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str if (strequal(newpwd->smb_name, pwd->smb_name)) { DEBUG(0, ("add_smbfilepwd_entry: entry with name %s already exists\n", pwd->smb_name)); endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth); - return False; + return NT_STATUS_USER_EXISTS; } } @@ -630,17 +631,18 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str fd = fileno(fp); if((offpos = sys_lseek(fd, 0, SEEK_END)) == -1) { + NTSTATUS result = map_nt_error_from_unix(errno); DEBUG(0, ("add_smbfilepwd_entry(sys_lseek): Failed to add entry for user %s to file %s. \ Error was %s\n", newpwd->smb_name, pfile, strerror(errno))); endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth); - return False; + return result; } if((new_entry = format_new_smbpasswd_entry(newpwd)) == NULL) { DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \ Error was %s\n", newpwd->smb_name, pfile, strerror(errno))); endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth); - return False; + return NT_STATUS_NO_MEMORY; } new_entry_length = strlen(new_entry); @@ -651,6 +653,7 @@ Error was %s\n", newpwd->smb_name, pfile, strerror(errno))); #endif if ((wr_len = write(fd, new_entry, new_entry_length)) != new_entry_length) { + NTSTATUS result = map_nt_error_from_unix(errno); DEBUG(0, ("add_smbfilepwd_entry(write): %d Failed to add entry for user %s to file %s. \ Error was %s\n", wr_len, newpwd->smb_name, pfile, strerror(errno))); @@ -663,12 +666,12 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n", endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth); free(new_entry); - return False; + return result; } free(new_entry); endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth); - return True; + return NT_STATUS_OK; } /************************************************************************ @@ -1308,7 +1311,7 @@ static NTSTATUS smbpasswd_getsampwnam(struct pdb_methods *my_methods, NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; struct smb_passwd *smb_pw; - void *fp = NULL; + FILE *fp = NULL; DEBUG(10, ("getsampwnam (smbpasswd): search by name: %s\n", username)); @@ -1352,7 +1355,7 @@ static NTSTATUS smbpasswd_getsampwsid(struct pdb_methods *my_methods, struct sam NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; struct smb_passwd *smb_pw; - void *fp = NULL; + FILE *fp = NULL; fstring sid_str; uint32 rid; @@ -1423,11 +1426,7 @@ static NTSTATUS smbpasswd_add_sam_account(struct pdb_methods *my_methods, struct } /* add the entry */ - if(!add_smbfilepwd_entry(smbpasswd_state, &smb_pw)) { - return NT_STATUS_UNSUCCESSFUL; - } - - return NT_STATUS_OK; + return add_smbfilepwd_entry(smbpasswd_state, &smb_pw); } static NTSTATUS smbpasswd_update_sam_account(struct pdb_methods *my_methods, struct samu *sampass) diff --git a/source/passdb/pdb_tdb.c b/source/passdb/pdb_tdb.c index f3ae4b7b02e..ac8cbbe91a3 100644 --- a/source/passdb/pdb_tdb.c +++ b/source/passdb/pdb_tdb.c @@ -169,7 +169,8 @@ static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buf } else { pdb_set_homedir(sampass, - talloc_sub_basic(sampass, username, lp_logon_home()), + talloc_sub_basic(sampass, username, domain, + lp_logon_home()), PDB_DEFAULT); } @@ -177,7 +178,8 @@ static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buf pdb_set_dir_drive(sampass, dir_drive, PDB_SET); else { pdb_set_dir_drive(sampass, - talloc_sub_basic(sampass, username, lp_logon_drive()), + talloc_sub_basic(sampass, username, domain, + lp_logon_drive()), PDB_DEFAULT); } @@ -185,7 +187,8 @@ static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buf pdb_set_logon_script(sampass, logon_script, PDB_SET); else { pdb_set_logon_script(sampass, - talloc_sub_basic(sampass, username, lp_logon_script()), + talloc_sub_basic(sampass, username, domain, + lp_logon_script()), PDB_DEFAULT); } @@ -193,7 +196,8 @@ static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buf pdb_set_profile_path(sampass, profile_path, PDB_SET); } else { pdb_set_profile_path(sampass, - talloc_sub_basic(sampass, username, lp_logon_path()), + talloc_sub_basic(sampass, username, domain, + lp_logon_path()), PDB_DEFAULT); } @@ -356,7 +360,8 @@ static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buf } else { pdb_set_homedir(sampass, - talloc_sub_basic(sampass, username, lp_logon_home()), + talloc_sub_basic(sampass, username, domain, + lp_logon_home()), PDB_DEFAULT); } @@ -364,7 +369,8 @@ static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buf pdb_set_dir_drive(sampass, dir_drive, PDB_SET); else { pdb_set_dir_drive(sampass, - talloc_sub_basic(sampass, username, lp_logon_drive()), + talloc_sub_basic(sampass, username, domain, + lp_logon_drive()), PDB_DEFAULT); } @@ -372,7 +378,8 @@ static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buf pdb_set_logon_script(sampass, logon_script, PDB_SET); else { pdb_set_logon_script(sampass, - talloc_sub_basic(sampass, username, lp_logon_script()), + talloc_sub_basic(sampass, username, domain, + lp_logon_script()), PDB_DEFAULT); } @@ -380,7 +387,8 @@ static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buf pdb_set_profile_path(sampass, profile_path, PDB_SET); } else { pdb_set_profile_path(sampass, - talloc_sub_basic(sampass, username, lp_logon_path()), + talloc_sub_basic(sampass, username, domain, + lp_logon_path()), PDB_DEFAULT); } @@ -541,14 +549,15 @@ BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen) if (homedir) { fstrcpy( tmpstring, homedir ); if (expand_explicit) { - standard_sub_basic( username, tmpstring, + standard_sub_basic( username, domain, tmpstring, sizeof(tmpstring) ); } pdb_set_homedir(sampass, tmpstring, PDB_SET); } else { pdb_set_homedir(sampass, - talloc_sub_basic(sampass, username, lp_logon_home()), + talloc_sub_basic(sampass, username, domain, + lp_logon_home()), PDB_DEFAULT); } @@ -560,28 +569,30 @@ BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen) if (logon_script) { fstrcpy( tmpstring, logon_script ); if (expand_explicit) { - standard_sub_basic( username, tmpstring, + standard_sub_basic( username, domain, tmpstring, sizeof(tmpstring) ); } pdb_set_logon_script(sampass, tmpstring, PDB_SET); } else { pdb_set_logon_script(sampass, - talloc_sub_basic(sampass, username, lp_logon_script()), + talloc_sub_basic(sampass, username, domain, + lp_logon_script()), PDB_DEFAULT); } if (profile_path) { fstrcpy( tmpstring, profile_path ); if (expand_explicit) { - standard_sub_basic( username, tmpstring, + standard_sub_basic( username, domain, tmpstring, sizeof(tmpstring) ); } pdb_set_profile_path(sampass, tmpstring, PDB_SET); } else { pdb_set_profile_path(sampass, - talloc_sub_basic(sampass, username, lp_logon_path()), + talloc_sub_basic(sampass, username, domain, + lp_logon_path()), PDB_DEFAULT); } @@ -606,7 +617,7 @@ BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen) /* Change from V1 is addition of password history field. */ pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); if (pwHistLen) { - uint8 *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN); + uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN); if (!pw_hist) { ret = False; goto done; @@ -901,7 +912,7 @@ static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, /* save a copy of the key */ - ptr->key.dptr = memdup( key.dptr, key.dsize ); + ptr->key.dptr = (char *)memdup( key.dptr, key.dsize ); if (!ptr->key.dptr) { DEBUG(0,("tdbsam_traverse_setpwent: memdup failed\n")); /* just return 0 and let the traversal continue */ diff --git a/source/passdb/secrets.c b/source/passdb/secrets.c index 04d6da2814a..f72a7cb8d54 100644 --- a/source/passdb/secrets.c +++ b/source/passdb/secrets.c @@ -104,8 +104,9 @@ BOOL secrets_store(const char *key, const void *data, size_t size) secrets_init(); if (!tdb) return False; - return tdb_store(tdb, string_tdb_data(key), make_tdb_data(data, size), - TDB_REPLACE) == 0; + return tdb_trans_store(tdb, string_tdb_data(key), + make_tdb_data((const char *)data, size), + TDB_REPLACE) == 0; } @@ -288,7 +289,8 @@ BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16], return True; } - if (!(pass = secrets_fetch(trust_keystr(domain), &size))) { + if (!(pass = (struct machine_acct_pass *)secrets_fetch( + trust_keystr(domain), &size))) { DEBUG(5, ("secrets_fetch failed!\n")); return False; } @@ -319,6 +321,136 @@ BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16], return True; } +/** + * Pack SID passed by pointer + * + * @param pack_buf pointer to buffer which is to be filled with packed data + * @param bufsize size of packing buffer + * @param sid pointer to sid to be packed + * + * @return length of the packed representation of the whole structure + **/ +static size_t tdb_sid_pack(char* pack_buf, int bufsize, DOM_SID* sid) +{ + int idx; + size_t len = 0; + + if (!sid || !pack_buf) return -1; + + len += tdb_pack(pack_buf + len, bufsize - len, "bb", sid->sid_rev_num, + sid->num_auths); + + for (idx = 0; idx < 6; idx++) { + len += tdb_pack(pack_buf + len, bufsize - len, "b", + sid->id_auth[idx]); + } + + for (idx = 0; idx < MAXSUBAUTHS; idx++) { + len += tdb_pack(pack_buf + len, bufsize - len, "d", + sid->sub_auths[idx]); + } + + return len; +} + +/** + * Unpack SID into a pointer + * + * @param pack_buf pointer to buffer with packed representation + * @param bufsize size of the buffer + * @param sid pointer to sid structure to be filled with unpacked data + * + * @return size of structure unpacked from buffer + **/ +static size_t tdb_sid_unpack(char* pack_buf, int bufsize, DOM_SID* sid) +{ + int idx, len = 0; + + if (!sid || !pack_buf) return -1; + + len += tdb_unpack(pack_buf + len, bufsize - len, "bb", + &sid->sid_rev_num, &sid->num_auths); + + for (idx = 0; idx < 6; idx++) { + len += tdb_unpack(pack_buf + len, bufsize - len, "b", + &sid->id_auth[idx]); + } + + for (idx = 0; idx < MAXSUBAUTHS; idx++) { + len += tdb_unpack(pack_buf + len, bufsize - len, "d", + &sid->sub_auths[idx]); + } + + return len; +} + +/** + * Pack TRUSTED_DOM_PASS passed by pointer + * + * @param pack_buf pointer to buffer which is to be filled with packed data + * @param bufsize size of the buffer + * @param pass pointer to trusted domain password to be packed + * + * @return length of the packed representation of the whole structure + **/ +static size_t tdb_trusted_dom_pass_pack(char* pack_buf, int bufsize, + TRUSTED_DOM_PASS* pass) +{ + int idx, len = 0; + + if (!pack_buf || !pass) return -1; + + /* packing unicode domain name and password */ + len += tdb_pack(pack_buf + len, bufsize - len, "d", + pass->uni_name_len); + + for (idx = 0; idx < 32; idx++) + len += tdb_pack(pack_buf + len, bufsize - len, "w", + pass->uni_name[idx]); + + len += tdb_pack(pack_buf + len, bufsize - len, "dPd", pass->pass_len, + pass->pass, pass->mod_time); + + /* packing SID structure */ + len += tdb_sid_pack(pack_buf + len, bufsize - len, &pass->domain_sid); + + return len; +} + + +/** + * Unpack TRUSTED_DOM_PASS passed by pointer + * + * @param pack_buf pointer to buffer with packed representation + * @param bufsize size of the buffer + * @param pass pointer to trusted domain password to be filled with unpacked data + * + * @return size of structure unpacked from buffer + **/ +size_t tdb_trusted_dom_pass_unpack(char* pack_buf, int bufsize, + TRUSTED_DOM_PASS* pass) +{ + int idx, len = 0; + + if (!pack_buf || !pass) return -1; + + /* unpack unicode domain name and plaintext password */ + len += tdb_unpack(pack_buf, bufsize - len, "d", &pass->uni_name_len); + + for (idx = 0; idx < 32; idx++) + len += tdb_unpack(pack_buf + len, bufsize - len, "w", + &pass->uni_name[idx]); + + len += tdb_unpack(pack_buf + len, bufsize - len, "dPd", + &pass->pass_len, &pass->pass, &pass->mod_time); + + /* unpack domain sid */ + len += tdb_sid_unpack(pack_buf + len, bufsize - len, + &pass->domain_sid); + + return len; +} + /************************************************************************ Routine to get account password to trusted domain ************************************************************************/ @@ -336,7 +468,8 @@ BOOL secrets_fetch_trusted_domain_password(const char *domain, char** pwd, ZERO_STRUCT(pass); /* fetching trusted domain password structure */ - if (!(pass_buf = secrets_fetch(trustdom_keystr(domain), &size))) { + if (!(pass_buf = (char *)secrets_fetch(trustdom_keystr(domain), + &size))) { DEBUG(5, ("secrets_fetch failed!\n")); return False; } @@ -494,7 +627,7 @@ char *secrets_fetch_machine_password(const char *domain, uint32 *last_set_time; asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain); strupper_m(key); - last_set_time = secrets_fetch(key, &size); + last_set_time = (unsigned int *)secrets_fetch(key, &size); if (last_set_time) { *pass_last_set_time = IVAL(last_set_time,0); SAFE_FREE(last_set_time); @@ -509,7 +642,7 @@ char *secrets_fetch_machine_password(const char *domain, uint32 *channel_type; asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain); strupper_m(key); - channel_type = secrets_fetch(key, &size); + channel_type = (unsigned int *)secrets_fetch(key, &size); if (channel_type) { *channel = IVAL(channel_type,0); SAFE_FREE(channel_type); @@ -613,7 +746,7 @@ BOOL fetch_ldap_pw(char **dn, char** pw) DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n")); } - *pw=secrets_fetch(key, &size); + *pw=(char *)secrets_fetch(key, &size); SAFE_FREE(key); if (!size) { @@ -631,7 +764,7 @@ BOOL fetch_ldap_pw(char **dn, char** pw) for (p=old_style_key; *p; p++) if (*p == ',') *p = '/'; - data=secrets_fetch(old_style_key, &size); + data=(char *)secrets_fetch(old_style_key, &size); if (!size && size < sizeof(old_style_pw)) { DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n")); SAFE_FREE(old_style_key); @@ -672,20 +805,35 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains, { TDB_LIST_NODE *keys, *k; char *pattern; + TALLOC_CTX *tmp_ctx; + + if (!(tmp_ctx = talloc_new(mem_ctx))) { + return NT_STATUS_NO_MEMORY; + } if (!secrets_init()) return NT_STATUS_ACCESS_DENIED; /* generate searching pattern */ - pattern = talloc_asprintf(mem_ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS); + pattern = talloc_asprintf(tmp_ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS); if (pattern == NULL) { DEBUG(0, ("secrets_trusted_domains: talloc_asprintf() " "failed!\n")); + TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } - *domains = NULL; *num_domains = 0; + /* + * Make sure that a talloc context for the trustdom_info structs + * exists + */ + + if (!(*domains = TALLOC_ARRAY(mem_ctx, struct trustdom_info *, 1))) { + TALLOC_FREE(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + /* fetching trusted domains' data and collecting them in a list */ keys = tdb_search_keys(tdb, pattern); @@ -698,16 +846,17 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains, struct trustdom_info *dom_info; /* important: ensure null-termination of the key string */ - secrets_key = talloc_strndup(mem_ctx, + secrets_key = talloc_strndup(tmp_ctx, k->node_key.dptr, k->node_key.dsize); if (!secrets_key) { DEBUG(0, ("strndup failed!\n")); tdb_search_list_free(keys); + TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } - packed_pass = secrets_fetch(secrets_key, &size); + packed_pass = (char *)secrets_fetch(secrets_key, &size); packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size, &pass); /* packed representation isn't needed anymore */ @@ -727,30 +876,31 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains, continue; } - dom_info = TALLOC_P(mem_ctx, struct trustdom_info); - if (dom_info == NULL) { + if (!(dom_info = TALLOC_P(*domains, struct trustdom_info))) { DEBUG(0, ("talloc failed\n")); tdb_search_list_free(keys); + TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } - if (pull_ucs2_talloc(mem_ctx, &dom_info->name, + if (pull_ucs2_talloc(dom_info, &dom_info->name, pass.uni_name) == (size_t)-1) { DEBUG(2, ("pull_ucs2_talloc failed\n")); tdb_search_list_free(keys); + TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } sid_copy(&dom_info->sid, &pass.domain_sid); - ADD_TO_ARRAY(mem_ctx, struct trustdom_info *, dom_info, + ADD_TO_ARRAY(*domains, struct trustdom_info *, dom_info, domains, num_domains); if (*domains == NULL) { tdb_search_list_free(keys); + TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } - talloc_steal(*domains, dom_info); } DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n", @@ -758,6 +908,7 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains, /* free the results of searching the keys */ tdb_search_list_free(keys); + TALLOC_FREE(tmp_ctx); return NT_STATUS_OK; } @@ -858,9 +1009,9 @@ BOOL secrets_fetch_afs_key(const char *cell, struct afs_key *result) *******************************************************************************/ void secrets_fetch_ipc_userpass(char **username, char **domain, char **password) { - *username = secrets_fetch(SECRETS_AUTH_USER, NULL); - *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL); - *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL); + *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL); + *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL); + *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL); if (*username && **username) { @@ -965,7 +1116,7 @@ BOOL secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx, pdc->remote_machine, pdc->domain); - value.dptr = TALLOC(mem_ctx, value.dsize); + value.dptr = (char *)TALLOC(mem_ctx, value.dsize); if (!value.dptr) { TALLOC_FREE(keystr); return False; diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c index bcdf0e04625..4b71f6e0b66 100644 --- a/source/printing/nt_printing.c +++ b/source/printing/nt_printing.c @@ -1281,6 +1281,8 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr SMB_STRUCT_STAT stat_buf; BOOL bad_path; + NTSTATUS status; + SET_STAT_INVALID(st); SET_STAT_INVALID(stat_buf); new_create_time = (time_t)0; @@ -1291,16 +1293,16 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf); - fsp = open_file_ntcreate(conn, filepath, &stat_buf, + status = open_file_ntcreate(conn, filepath, &stat_buf, FILE_GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, - NULL); + NULL, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { /* Old file not found, so by definition new file is in fact newer */ DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n", filepath, errno)); @@ -1327,16 +1329,16 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr pstrcpy(filepath, new_file); driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf); - fsp = open_file_ntcreate(conn, filepath, &stat_buf, + status = open_file_ntcreate(conn, filepath, &stat_buf, FILE_GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, - NULL); + NULL, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { /* New file not found, this shouldn't occur if the caller did its job */ DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n", filepath, errno)); @@ -1405,6 +1407,7 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_ BOOL bad_path; SMB_STRUCT_STAT st; connection_struct *conn; + NTSTATUS status; SET_STAT_INVALID(st); @@ -1460,16 +1463,16 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_ goto error_exit; } - fsp = open_file_ntcreate(conn, driverpath, &st, + status = open_file_ntcreate(conn, driverpath, &st, FILE_GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, - NULL); + NULL, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n", driverpath, errno)); *perr = WERR_ACCESS_DENIED; @@ -4368,7 +4371,8 @@ WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_print fstrcpy( servername, print_hnd->servername ); else { fstrcpy( servername, "%L" ); - standard_sub_basic( "", servername, sizeof(servername)-1 ); + standard_sub_basic( "", "", servername, + sizeof(servername)-1 ); } result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename ); @@ -5441,7 +5445,7 @@ BOOL print_access_check(struct current_user *user, int snum, int access_type) Check the time parameters allow a print operation. *****************************************************************************/ -BOOL print_time_access_check(int snum) +BOOL print_time_access_check(const char *servicename) { NT_PRINTER_INFO_LEVEL *printer = NULL; BOOL ok = False; @@ -5449,7 +5453,7 @@ BOOL print_time_access_check(int snum) struct tm *t; uint32 mins; - if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum)))) + if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename))) return False; if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0) diff --git a/source/printing/print_generic.c b/source/printing/print_generic.c index 1ea762695b1..aef4e50bfaa 100644 --- a/source/printing/print_generic.c +++ b/source/printing/print_generic.c @@ -30,7 +30,9 @@ for local substitution strings static int print_run_command(int snum, const char* printername, BOOL do_sub, const char *command, int *outfd, ...) { - + extern struct current_user current_user; + extern userdom_struct current_user_info; + pstring syscmd; char *arg; int ret; @@ -56,7 +58,12 @@ static int print_run_command(int snum, const char* printername, BOOL do_sub, pstring_sub( syscmd, "%p", printername ); if ( do_sub && snum != -1 ) - standard_sub_snum(snum,syscmd,sizeof(syscmd)); + standard_sub_advanced(lp_servicename(snum), + current_user_info.unix_name, "", + current_user.ut.gid, + get_current_username(), + current_user_info.domain, + syscmd, sizeof(syscmd)); ret = smbrun(syscmd,outfd); diff --git a/source/printing/printfsp.c b/source/printing/printfsp.c index c248851822b..5278c60f992 100644 --- a/source/printing/printfsp.c +++ b/source/printing/printfsp.c @@ -28,15 +28,19 @@ open a print file and setup a fsp for it. This is a wrapper around print_job_start(). ***************************************************************************/ -files_struct *print_fsp_open(connection_struct *conn, const char *fname) +NTSTATUS print_fsp_open(connection_struct *conn, const char *fname, + files_struct **result) { int jobid; SMB_STRUCT_STAT sbuf; - files_struct *fsp = file_new(conn); + files_struct *fsp; fstring name; + NTSTATUS status; - if(!fsp) - return NULL; + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; + } fstrcpy( name, "Remote Downlevel Document"); if (fname) { @@ -50,8 +54,9 @@ files_struct *print_fsp_open(connection_struct *conn, const char *fname) jobid = print_job_start(¤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/source/printing/printing.c b/source/printing/printing.c index 9dd6bec0be4..bb756c88707 100644 --- a/source/printing/printing.c +++ b/source/printing/printing.c @@ -839,10 +839,9 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void Check if the print queue has been updated recently enough. ****************************************************************************/ -static void print_cache_flush(int snum) +static void print_cache_flush(const char *sharename) { fstring key; - const char *sharename = lp_const_servicename(snum); struct tdb_print_db *pdb = get_print_db_byname(sharename); if (!pdb) @@ -1439,6 +1438,8 @@ update the internal database from the system print queue for a queue static void print_queue_update(int snum, BOOL force) { + extern struct current_user current_user; + extern userdom_struct current_user_info; fstring key; fstring sharename; pstring lpqcommand, lprmcommand; @@ -1456,12 +1457,22 @@ static void print_queue_update(int snum, BOOL force) pstrcpy( lpqcommand, lp_lpqcommand(snum)); string_sub2( lpqcommand, "%p", PRINTERNAME(snum), sizeof(lpqcommand), False, False, False ); - standard_sub_snum( snum, lpqcommand, sizeof(lpqcommand) ); + standard_sub_advanced(lp_servicename(snum), + current_user_info.unix_name, "", + current_user.ut.gid, + get_current_username(), + current_user_info.domain, + lpqcommand, sizeof(lpqcommand) ); pstrcpy( lprmcommand, lp_lprmcommand(snum)); string_sub2( lprmcommand, "%p", PRINTERNAME(snum), sizeof(lprmcommand), False, False, False ); - standard_sub_snum( snum, lprmcommand, sizeof(lprmcommand) ); + standard_sub_advanced(lp_servicename(snum), + current_user_info.unix_name, "", + current_user.ut.gid, + get_current_username(), + current_user_info.domain, + lprmcommand, sizeof(lprmcommand) ); /* * Make sure that the background queue process exists. @@ -1781,7 +1792,7 @@ NT_DEVICEMODE *print_job_devmode(const char* sharename, uint32 jobid) Set the place in the queue for a job. ****************************************************************************/ -BOOL print_job_set_place(int snum, uint32 jobid, int place) +BOOL print_job_set_place(const char *sharename, uint32 jobid, int place) { DEBUG(2,("print_job_set_place not implemented yet\n")); return False; @@ -1791,9 +1802,8 @@ BOOL print_job_set_place(int snum, uint32 jobid, int place) Set the name of a job. Only possible for owner. ****************************************************************************/ -BOOL print_job_set_name(int snum, uint32 jobid, char *name) +BOOL print_job_set_name(const char *sharename, uint32 jobid, char *name) { - const char* sharename = lp_const_servicename(snum); struct printjob *pjob; pjob = print_job_find(sharename, jobid); @@ -1930,9 +1940,10 @@ static BOOL print_job_delete1(int snum, uint32 jobid) Return true if the current user owns the print job. ****************************************************************************/ -static BOOL is_owner(struct current_user *user, int snum, uint32 jobid) +static BOOL is_owner(struct current_user *user, const char *servicename, + uint32 jobid) { - struct printjob *pjob = print_job_find(lp_const_servicename(snum), jobid); + struct printjob *pjob = print_job_find(servicename, jobid); user_struct *vuser; if (!pjob || !user) @@ -1958,7 +1969,7 @@ BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR *errcode = WERR_OK; - owner = is_owner(user, snum, jobid); + owner = is_owner(user, lp_const_servicename(snum), jobid); /* Check access against security descriptor or whether the user owns their job. */ @@ -2037,7 +2048,7 @@ BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR * return False; } - if (!is_owner(user, snum, jobid) && + if (!is_owner(user, lp_const_servicename(snum), jobid) && !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) { DEBUG(3, ("pause denied by security descriptor\n")); @@ -2061,7 +2072,7 @@ pause, or resume print job. User name: %s. Printer name: %s.", } /* force update the database */ - print_cache_flush(snum); + print_cache_flush(lp_const_servicename(snum)); /* Send a printer notify message */ @@ -2097,7 +2108,7 @@ BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR return False; } - if (!is_owner(user, snum, jobid) && + if (!is_owner(user, lp_const_servicename(snum), jobid) && !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) { DEBUG(3, ("resume denied by security descriptor\n")); *errcode = WERR_ACCESS_DENIED; @@ -2119,7 +2130,7 @@ pause, or resume print job. User name: %s. Printer name: %s.", } /* force update the database */ - print_cache_flush(snum); + print_cache_flush(lp_const_servicename(snum)); /* Send a printer notify message */ @@ -2325,7 +2336,7 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE return (uint32)-1; } - if (!print_time_access_check(snum)) { + if (!print_time_access_check(lp_servicename(snum))) { DEBUG(3, ("print_job_start: job start denied by time check\n")); release_print_db(pdb); return (uint32)-1; @@ -2739,7 +2750,7 @@ BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode) } /* force update the database */ - print_cache_flush(snum); + print_cache_flush(lp_const_servicename(snum)); /* Send a printer notify message */ @@ -2805,7 +2816,7 @@ BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode) become_root(); for (i=0;i<njobs;i++) { - BOOL owner = is_owner(user, snum, queue[i].job); + BOOL owner = is_owner(user, lp_const_servicename(snum), queue[i].job); if (owner || can_job_admin) { print_job_delete1(snum, queue[i].job); diff --git a/source/profile/profile.c b/source/profile/profile.c index c3512ec01d8..926cc508dd2 100644 --- a/source/profile/profile.c +++ b/source/profile/profile.c @@ -2,7 +2,8 @@ Unix SMB/CIFS implementation. store smbd profiling information in shared memory Copyright (C) Andrew Tridgell 1999 - + Copyright (C) James Peach 2006 + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -249,4 +250,182 @@ BOOL profile_setup(BOOL rdonly) message_register(MSG_REQ_PROFILELEVEL, reqprofile_message); return True; } + + const char * profile_value_name(enum profile_stats_values val) +{ + static const char * valnames[PR_VALUE_MAX + 1] = + { + "smbd_idle", /* PR_VALUE_SMBD_IDLE */ + "syscall_opendir", /* PR_VALUE_SYSCALL_OPENDIR */ + "syscall_readdir", /* PR_VALUE_SYSCALL_READDIR */ + "syscall_seekdir", /* PR_VALUE_SYSCALL_SEEKDIR */ + "syscall_telldir", /* PR_VALUE_SYSCALL_TELLDIR */ + "syscall_rewinddir", /* PR_VALUE_SYSCALL_REWINDDIR */ + "syscall_mkdir", /* PR_VALUE_SYSCALL_MKDIR */ + "syscall_rmdir", /* PR_VALUE_SYSCALL_RMDIR */ + "syscall_closedir", /* PR_VALUE_SYSCALL_CLOSEDIR */ + "syscall_open", /* PR_VALUE_SYSCALL_OPEN */ + "syscall_close", /* PR_VALUE_SYSCALL_CLOSE */ + "syscall_read", /* PR_VALUE_SYSCALL_READ */ + "syscall_pread", /* PR_VALUE_SYSCALL_PREAD */ + "syscall_write", /* PR_VALUE_SYSCALL_WRITE */ + "syscall_pwrite", /* PR_VALUE_SYSCALL_PWRITE */ + "syscall_lseek", /* PR_VALUE_SYSCALL_LSEEK */ + "syscall_sendfile", /* PR_VALUE_SYSCALL_SENDFILE */ + "syscall_rename", /* PR_VALUE_SYSCALL_RENAME */ + "syscall_fsync", /* PR_VALUE_SYSCALL_FSYNC */ + "syscall_stat", /* PR_VALUE_SYSCALL_STAT */ + "syscall_fstat", /* PR_VALUE_SYSCALL_FSTAT */ + "syscall_lstat", /* PR_VALUE_SYSCALL_LSTAT */ + "syscall_unlink", /* PR_VALUE_SYSCALL_UNLINK */ + "syscall_chmod", /* PR_VALUE_SYSCALL_CHMOD */ + "syscall_fchmod", /* PR_VALUE_SYSCALL_FCHMOD */ + "syscall_chown", /* PR_VALUE_SYSCALL_CHOWN */ + "syscall_fchown", /* PR_VALUE_SYSCALL_FCHOWN */ + "syscall_chdir", /* PR_VALUE_SYSCALL_CHDIR */ + "syscall_getwd", /* PR_VALUE_SYSCALL_GETWD */ + "syscall_utime", /* PR_VALUE_SYSCALL_UTIME */ + "syscall_ftruncate", /* PR_VALUE_SYSCALL_FTRUNCATE */ + "syscall_fcntl_lock", /* PR_VALUE_SYSCALL_FCNTL_LOCK */ + "syscall_fcntl_getlock", /* PR_VALUE_SYSCALL_FCNTL_GETLOCK */ + "syscall_readlink", /* PR_VALUE_SYSCALL_READLINK */ + "syscall_symlink", /* PR_VALUE_SYSCALL_SYMLINK */ + "syscall_link", /* PR_VALUE_SYSCALL_LINK */ + "syscall_mknod", /* PR_VALUE_SYSCALL_MKNOD */ + "syscall_realpath", /* PR_VALUE_SYSCALL_REALPATH */ + "syscall_get_quota", /* PR_VALUE_SYSCALL_GET_QUOTA */ + "syscall_set_quota", /* PR_VALUE_SYSCALL_SET_QUOTA */ + "SMBmkdir", /* PR_VALUE_SMBMKDIR */ + "SMBrmdir", /* PR_VALUE_SMBRMDIR */ + "SMBopen", /* PR_VALUE_SMBOPEN */ + "SMBcreate", /* PR_VALUE_SMBCREATE */ + "SMBclose", /* PR_VALUE_SMBCLOSE */ + "SMBflush", /* PR_VALUE_SMBFLUSH */ + "SMBunlink", /* PR_VALUE_SMBUNLINK */ + "SMBmv", /* PR_VALUE_SMBMV */ + "SMBgetatr", /* PR_VALUE_SMBGETATR */ + "SMBsetatr", /* PR_VALUE_SMBSETATR */ + "SMBread", /* PR_VALUE_SMBREAD */ + "SMBwrite", /* PR_VALUE_SMBWRITE */ + "SMBlock", /* PR_VALUE_SMBLOCK */ + "SMBunlock", /* PR_VALUE_SMBUNLOCK */ + "SMBctemp", /* PR_VALUE_SMBCTEMP */ + "SMBmknew", /* PR_VALUE_SMBMKNEW */ + "SMBchkpth", /* PR_VALUE_SMBCHKPTH */ + "SMBexit", /* PR_VALUE_SMBEXIT */ + "SMBlseek", /* PR_VALUE_SMBLSEEK */ + "SMBlockread", /* PR_VALUE_SMBLOCKREAD */ + "SMBwriteunlock", /* PR_VALUE_SMBWRITEUNLOCK */ + "SMBreadbraw", /* PR_VALUE_SMBREADBRAW */ + "SMBreadBmpx", /* PR_VALUE_SMBREADBMPX */ + "SMBreadBs", /* PR_VALUE_SMBREADBS */ + "SMBwritebraw", /* PR_VALUE_SMBWRITEBRAW */ + "SMBwriteBmpx", /* PR_VALUE_SMBWRITEBMPX */ + "SMBwriteBs", /* PR_VALUE_SMBWRITEBS */ + "SMBwritec", /* PR_VALUE_SMBWRITEC */ + "SMBsetattrE", /* PR_VALUE_SMBSETATTRE */ + "SMBgetattrE", /* PR_VALUE_SMBGETATTRE */ + "SMBlockingX", /* PR_VALUE_SMBLOCKINGX */ + "SMBtrans", /* PR_VALUE_SMBTRANS */ + "SMBtranss", /* PR_VALUE_SMBTRANSS */ + "SMBioctl", /* PR_VALUE_SMBIOCTL */ + "SMBioctls", /* PR_VALUE_SMBIOCTLS */ + "SMBcopy", /* PR_VALUE_SMBCOPY */ + "SMBmove", /* PR_VALUE_SMBMOVE */ + "SMBecho", /* PR_VALUE_SMBECHO */ + "SMBwriteclose", /* PR_VALUE_SMBWRITECLOSE */ + "SMBopenX", /* PR_VALUE_SMBOPENX */ + "SMBreadX", /* PR_VALUE_SMBREADX */ + "SMBwriteX", /* PR_VALUE_SMBWRITEX */ + "SMBtrans2", /* PR_VALUE_SMBTRANS2 */ + "SMBtranss2", /* PR_VALUE_SMBTRANSS2 */ + "SMBfindclose", /* PR_VALUE_SMBFINDCLOSE */ + "SMBfindnclose", /* PR_VALUE_SMBFINDNCLOSE */ + "SMBtcon", /* PR_VALUE_SMBTCON */ + "SMBtdis", /* PR_VALUE_SMBTDIS */ + "SMBnegprot", /* PR_VALUE_SMBNEGPROT */ + "SMBsesssetupX", /* PR_VALUE_SMBSESSSETUPX */ + "SMBulogoffX", /* PR_VALUE_SMBULOGOFFX */ + "SMBtconX", /* PR_VALUE_SMBTCONX */ + "SMBdskattr", /* PR_VALUE_SMBDSKATTR */ + "SMBsearch", /* PR_VALUE_SMBSEARCH */ + "SMBffirst", /* PR_VALUE_SMBFFIRST */ + "SMBfunique", /* PR_VALUE_SMBFUNIQUE */ + "SMBfclose", /* PR_VALUE_SMBFCLOSE */ + "SMBnttrans", /* PR_VALUE_SMBNTTRANS */ + "SMBnttranss", /* PR_VALUE_SMBNTTRANSS */ + "SMBntcreateX", /* PR_VALUE_SMBNTCREATEX */ + "SMBntcancel", /* PR_VALUE_SMBNTCANCEL */ + "SMBntrename", /* PR_VALUE_SMBNTRENAME */ + "SMBsplopen", /* PR_VALUE_SMBSPLOPEN */ + "SMBsplwr", /* PR_VALUE_SMBSPLWR */ + "SMBsplclose", /* PR_VALUE_SMBSPLCLOSE */ + "SMBsplretq", /* PR_VALUE_SMBSPLRETQ */ + "SMBsends", /* PR_VALUE_SMBSENDS */ + "SMBsendb", /* PR_VALUE_SMBSENDB */ + "SMBfwdname", /* PR_VALUE_SMBFWDNAME */ + "SMBcancelf", /* PR_VALUE_SMBCANCELF */ + "SMBgetmac", /* PR_VALUE_SMBGETMAC */ + "SMBsendstrt", /* PR_VALUE_SMBSENDSTRT */ + "SMBsendend", /* PR_VALUE_SMBSENDEND */ + "SMBsendtxt", /* PR_VALUE_SMBSENDTXT */ + "SMBinvalid", /* PR_VALUE_SMBINVALID */ + "pathworks_setdir", /* PR_VALUE_PATHWORKS_SETDIR */ + "Trans2_open", /* PR_VALUE_TRANS2_OPEN */ + "Trans2_findfirst", /* PR_VALUE_TRANS2_FINDFIRST */ + "Trans2_findnext", /* PR_VALUE_TRANS2_FINDNEXT */ + "Trans2_qfsinfo", /* PR_VALUE_TRANS2_QFSINFO */ + "Trans2_setfsinfo", /* PR_VALUE_TRANS2_SETFSINFO */ + "Trans2_qpathinfo", /* PR_VALUE_TRANS2_QPATHINFO */ + "Trans2_setpathinfo", /* PR_VALUE_TRANS2_SETPATHINFO */ + "Trans2_qfileinfo", /* PR_VALUE_TRANS2_QFILEINFO */ + "Trans2_setfileinfo", /* PR_VALUE_TRANS2_SETFILEINFO */ + "Trans2_fsctl", /* PR_VALUE_TRANS2_FSCTL */ + "Trans2_ioctl", /* PR_VALUE_TRANS2_IOCTL */ + "Trans2_findnotifyfirst", /* PR_VALUE_TRANS2_FINDNOTIFYFIRST */ + "Trans2_findnotifynext", /* PR_VALUE_TRANS2_FINDNOTIFYNEXT */ + "Trans2_mkdir", /* PR_VALUE_TRANS2_MKDIR */ + "Trans2_session_setup", /* PR_VALUE_TRANS2_SESSION_SETUP */ + "Trans2_get_dfs_referral", /* PR_VALUE_TRANS2_GET_DFS_REFERRAL */ + "Trans2_report_dfs_inconsistancy", /* PR_VALUE_TRANS2_REPORT_DFS_INCONSISTANCY */ + "NT_transact_create", /* PR_VALUE_NT_TRANSACT_CREATE */ + "NT_transact_ioctl", /* PR_VALUE_NT_TRANSACT_IOCTL */ + "NT_transact_set_security_desc", /* PR_VALUE_NT_TRANSACT_SET_SECURITY_DESC */ + "NT_transact_notify_change",/* PR_VALUE_NT_TRANSACT_NOTIFY_CHANGE */ + "NT_transact_rename", /* PR_VALUE_NT_TRANSACT_RENAME */ + "NT_transact_query_security_desc", /* PR_VALUE_NT_TRANSACT_QUERY_SECURITY_DESC */ + "NT_transact_get_user_quota",/* PR_VALUE_NT_TRANSACT_GET_USER_QUOTA */ + "NT_transact_set_user_quota",/* PR_VALUE_NT_TRANSACT_SET_USER_QUOTA */ + "get_nt_acl", /* PR_VALUE_GET_NT_ACL */ + "fget_nt_acl", /* PR_VALUE_FGET_NT_ACL */ + "set_nt_acl", /* PR_VALUE_SET_NT_ACL */ + "fset_nt_acl", /* PR_VALUE_FSET_NT_ACL */ + "chmod_acl", /* PR_VALUE_CHMOD_ACL */ + "fchmod_acl", /* PR_VALUE_FCHMOD_ACL */ + "name_release", /* PR_VALUE_NAME_RELEASE */ + "name_refresh", /* PR_VALUE_NAME_REFRESH */ + "name_registration", /* PR_VALUE_NAME_REGISTRATION */ + "node_status", /* PR_VALUE_NODE_STATUS */ + "name_query", /* PR_VALUE_NAME_QUERY */ + "host_announce", /* PR_VALUE_HOST_ANNOUNCE */ + "workgroup_announce", /* PR_VALUE_WORKGROUP_ANNOUNCE */ + "local_master_announce", /* PR_VALUE_LOCAL_MASTER_ANNOUNCE */ + "master_browser_announce", /* PR_VALUE_MASTER_BROWSER_ANNOUNCE */ + "lm_host_announce", /* PR_VALUE_LM_HOST_ANNOUNCE */ + "get_backup_list", /* PR_VALUE_GET_BACKUP_LIST */ + "reset_browser", /* PR_VALUE_RESET_BROWSER */ + "announce_request", /* PR_VALUE_ANNOUNCE_REQUEST */ + "lm_announce_request", /* PR_VALUE_LM_ANNOUNCE_REQUEST */ + "domain_logon", /* PR_VALUE_DOMAIN_LOGON */ + "sync_browse_lists", /* PR_VALUE_SYNC_BROWSE_LISTS */ + "run_elections", /* PR_VALUE_RUN_ELECTIONS */ + "election", /* PR_VALUE_ELECTION */ + "" /* PR_VALUE_MAX */ + }; + + SMB_ASSERT(val >= 0); + SMB_ASSERT(val < PR_VALUE_MAX); + return valnames[val]; +} + #endif /* WITH_PROFILE */ diff --git a/source/python/py_smb.c b/source/python/py_smb.c index 679c113f397..f92a9e258dc 100644 --- a/source/python/py_smb.c +++ b/source/python/py_smb.c @@ -43,7 +43,7 @@ static PyObject *py_smb_connect(PyObject *self, PyObject *args, PyObject *kw) if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &server)) return NULL; - if (!(cli = cli_initialise(NULL))) + if (!(cli = cli_initialise())) return NULL; ZERO_STRUCT(ip); diff --git a/source/registry/reg_printing.c b/source/registry/reg_printing.c index 3ecff3d6964..338bc7af6a7 100644 --- a/source/registry/reg_printing.c +++ b/source/registry/reg_printing.c @@ -382,7 +382,6 @@ static void fill_in_printer_values( NT_PRINTER_INFO_LEVEL_2 *info2, REGVAL_CTR * UNISTR2 data; char *p; uint32 printer_status = PRINTER_STATUS_OK; - int snum; regval_ctr_addvalue( values, "Attributes", REG_DWORD, (char*)&info2->attributes, sizeof(info2->attributes) ); regval_ctr_addvalue( values, "Priority", REG_DWORD, (char*)&info2->priority, sizeof(info2->attributes) ); @@ -438,8 +437,7 @@ static void fill_in_printer_values( NT_PRINTER_INFO_LEVEL_2 *info2, REGVAL_CTR * /* stream the device mode */ - snum = lp_servicenumber(info2->sharename); - if ( (devmode = construct_dev_mode( snum )) != NULL ) { + if ( (devmode = construct_dev_mode( info2->sharename )) != NULL ) { if ( spoolss_io_devmode( "devmode", &prs, 0, devmode ) ) { offset = prs_offset( &prs ); regval_ctr_addvalue( values, "Default Devmode", REG_BINARY, prs_data_p(&prs), offset ); diff --git a/source/rpc_client/cli_lsarpc.c b/source/rpc_client/cli_lsarpc.c index 97d8eb621be..7e29332ef97 100644 --- a/source/rpc_client/cli_lsarpc.c +++ b/source/rpc_client/cli_lsarpc.c @@ -1284,43 +1284,43 @@ done: BOOL fetch_domain_sid( char *domain, char *remote_machine, DOM_SID *psid) { extern pstring global_myname; - struct cli_state cli; + struct cli_state *cli; NTSTATUS result; POLICY_HND lsa_pol; BOOL ret = False; ZERO_STRUCT(cli); - if(cli_initialise(&cli) == False) { + if((cli = cli_initialise()) == NULL) { DEBUG(0,("fetch_domain_sid: unable to initialize client connection.\n")); return False; } - if(!resolve_name( remote_machine, &cli.dest_ip, 0x20)) { + if(!resolve_name( remote_machine, &cli->dest_ip, 0x20)) { DEBUG(0,("fetch_domain_sid: Can't resolve address for %s\n", remote_machine)); goto done; } - if (!cli_connect(&cli, remote_machine, &cli.dest_ip)) { + if (!cli_connect(cli, remote_machine, &cli->dest_ip)) { DEBUG(0,("fetch_domain_sid: unable to connect to SMB server on \ -machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli) )); +machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli) )); goto done; } - if (!attempt_netbios_session_request(&cli, global_myname, remote_machine, &cli.dest_ip)) { + if (!attempt_netbios_session_request(cli, global_myname, remote_machine, &cli->dest_ip)) { DEBUG(0,("fetch_domain_sid: machine %s rejected the NetBIOS session request.\n", remote_machine)); goto done; } - cli.protocol = PROTOCOL_NT1; + cli->protocol = PROTOCOL_NT1; - if (!cli_negprot(&cli)) { + if (!cli_negprot(cli)) { DEBUG(0,("fetch_domain_sid: machine %s rejected the negotiate protocol. \ -Error was : %s.\n", remote_machine, cli_errstr(&cli) )); +Error was : %s.\n", remote_machine, cli_errstr(cli) )); goto done; } - if (cli.protocol != PROTOCOL_NT1) { + if (cli->protocol != PROTOCOL_NT1) { DEBUG(0,("fetch_domain_sid: machine %s didn't negotiate NT protocol.\n", remote_machine)); goto done; @@ -1330,39 +1330,39 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) )); * Do an anonymous session setup. */ - if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) { + if (!cli_session_setup(cli, "", "", 0, "", 0, "")) { DEBUG(0,("fetch_domain_sid: machine %s rejected the session setup. \ -Error was : %s.\n", remote_machine, cli_errstr(&cli) )); +Error was : %s.\n", remote_machine, cli_errstr(cli) )); goto done; } - if (!(cli.sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) { + if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) { DEBUG(0,("fetch_domain_sid: machine %s isn't in user level security mode\n", remote_machine)); goto done; } - if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { + if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) { DEBUG(0,("fetch_domain_sid: machine %s rejected the tconX on the IPC$ share. \ -Error was : %s.\n", remote_machine, cli_errstr(&cli) )); +Error was : %s.\n", remote_machine, cli_errstr(cli) )); goto done; } /* Fetch domain sid */ - if (!cli_nt_session_open(&cli, PI_LSARPC)) { + if (!cli_nt_session_open(cli, PI_LSARPC)) { DEBUG(0, ("fetch_domain_sid: Error connecting to SAM pipe\n")); goto done; } - result = cli_lsa_open_policy(&cli, cli.mem_ctx, True, SEC_RIGHTS_QUERY_VALUE, &lsa_pol); + result = cli_lsa_open_policy(cli, cli->mem_ctx, True, SEC_RIGHTS_QUERY_VALUE, &lsa_pol); if (!NT_STATUS_IS_OK(result)) { DEBUG(0, ("fetch_domain_sid: Error opening lsa policy handle. %s\n", nt_errstr(result) )); goto done; } - result = cli_lsa_query_info_policy(&cli, cli.mem_ctx, &lsa_pol, 5, domain, psid); + result = cli_lsa_query_info_policy(cli, cli->mem_ctx, &lsa_pol, 5, domain, psid); if (!NT_STATUS_IS_OK(result)) { DEBUG(0, ("fetch_domain_sid: Error querying lsa policy handle. %s\n", nt_errstr(result) )); @@ -1373,7 +1373,7 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) )); done: - cli_shutdown(&cli); + cli_shutdown(cli); return ret; } diff --git a/source/rpc_client/cli_srvsvc.c b/source/rpc_client/cli_srvsvc.c index 0d50e94d577..7b4818b4b06 100644 --- a/source/rpc_client/cli_srvsvc.c +++ b/source/rpc_client/cli_srvsvc.c @@ -5,6 +5,8 @@ Copyright (C) Tim Potter 2001 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002 Copyright (C) Jeremy Allison 2005. + Copyright (C) Gerald (Jerry) Carter 2006. + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -537,38 +539,37 @@ WERROR rpccli_srvsvc_net_file_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ ZERO_STRUCTP(ctr); - ctr->switch_value = file_level; + ctr->level = file_level; ctr->num_entries = ctr->num_entries2 = r.ctr.num_entries; switch(file_level) { case 3: - ctr->file.info3 = TALLOC_ARRAY(mem_ctx, SRV_FILE_INFO_3, ctr->num_entries); - if (ctr->file.info3 == NULL) { + if ( (ctr->file.info3 = TALLOC_ARRAY(mem_ctx, FILE_INFO_3, ctr->num_entries)) == NULL ) { return WERR_NOMEM; } - memset(ctr->file.info3, 0, - sizeof(SRV_FILE_INFO_3) * ctr->num_entries); + memset(ctr->file.info3, 0, sizeof(FILE_INFO_3) * ctr->num_entries); for (i = 0; i < r.ctr.num_entries; i++) { - SRV_FILE_INFO_3 *info3 = &ctr->file.info3[i]; + FILE_INFO_3 *info3 = &ctr->file.info3[i]; char *s; /* Copy pointer crap */ - memcpy(&info3->info_3, &r.ctr.file.info3[i].info_3, - sizeof(FILE_INFO_3)); + memcpy(info3, &r.ctr.file.info3[i], sizeof(FILE_INFO_3)); /* Duplicate strings */ - s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_path_name); - if (s) - init_unistr2(&info3->info_3_str.uni_path_name, s, UNI_STR_TERMINATE); + if ( (s = unistr2_tdup(mem_ctx, r.ctr.file.info3[i].path)) != NULL ) { + info3->path = TALLOC_P( mem_ctx, UNISTR2 ); + init_unistr2(info3->path, s, UNI_STR_TERMINATE); + } - s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_user_name); - if (s) - init_unistr2(&info3->info_3_str.uni_user_name, s, UNI_STR_TERMINATE); + if ( (s = unistr2_tdup(mem_ctx, r.ctr.file.info3[i].user)) != NULL ) { + info3->user = TALLOC_P( mem_ctx, UNISTR2 ); + init_unistr2(info3->user, s, UNI_STR_TERMINATE); + } } diff --git a/source/rpc_client/cli_unixinfo.c b/source/rpc_client/cli_unixinfo.c new file mode 100644 index 00000000000..b9a960dfd1a --- /dev/null +++ b/source/rpc_client/cli_unixinfo.c @@ -0,0 +1,226 @@ +/* + Unix SMB/CIFS implementation. + + RPC pipe client + + Copyright (C) Volker Lendecke 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +NTSTATUS rpccli_unixinfo_uid2sid(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, uid_t uid, DOM_SID *sid) +{ + prs_struct qbuf, rbuf; + UNIXINFO_Q_UID_TO_SID q; + UNIXINFO_R_UID_TO_SID r; + NTSTATUS result = NT_STATUS_NET_WRITE_FAULT; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Marshall data and send request */ + { + UINT64_S uid64; + uid64.high = 0; + uid64.low = uid; + init_q_unixinfo_uid_to_sid(&q, uid64); + } + + CLI_DO_RPC(cli, mem_ctx, PI_UNIXINFO, UNIXINFO_UID_TO_SID, + q, r, + qbuf, rbuf, + unixinfo_io_q_unixinfo_uid_to_sid, + unixinfo_io_r_unixinfo_uid_to_sid, + NT_STATUS_NET_WRITE_FAULT); + + if (NT_STATUS_IS_OK(r.status) && (sid != NULL)) { + sid_copy(sid, &r.sid); + } + + result = r.status; + return result; +} + +NTSTATUS rpccli_unixinfo_sid2uid(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, uid_t *uid) +{ + prs_struct qbuf, rbuf; + UNIXINFO_Q_SID_TO_UID q; + UNIXINFO_R_SID_TO_UID r; + NTSTATUS result = NT_STATUS_NET_WRITE_FAULT; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Marshall data and send request */ + init_q_unixinfo_sid_to_uid(&q, sid); + + CLI_DO_RPC(cli, mem_ctx, PI_UNIXINFO, UNIXINFO_SID_TO_UID, + q, r, + qbuf, rbuf, + unixinfo_io_q_unixinfo_sid_to_uid, + unixinfo_io_r_unixinfo_sid_to_uid, + NT_STATUS_NET_WRITE_FAULT); + + if (NT_STATUS_IS_OK(r.status)) { + if (r.uid.high != 0) { + /* 64-Bit uid's not yet handled */ + return NT_STATUS_INVALID_PARAMETER; + } + if (uid != NULL) { + *uid = r.uid.low; + } + } + + result = r.status; + return result; +} + +NTSTATUS rpccli_unixinfo_gid2sid(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, gid_t gid, DOM_SID *sid) +{ + prs_struct qbuf, rbuf; + UNIXINFO_Q_GID_TO_SID q; + UNIXINFO_R_GID_TO_SID r; + NTSTATUS result = NT_STATUS_NET_WRITE_FAULT; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Marshall data and send request */ + { + UINT64_S gid64; + gid64.high = 0; + gid64.low = gid; + init_q_unixinfo_gid_to_sid(&q, gid64); + } + + CLI_DO_RPC(cli, mem_ctx, PI_UNIXINFO, UNIXINFO_GID_TO_SID, + q, r, + qbuf, rbuf, + unixinfo_io_q_unixinfo_gid_to_sid, + unixinfo_io_r_unixinfo_gid_to_sid, + NT_STATUS_NET_WRITE_FAULT); + + if (NT_STATUS_IS_OK(r.status) && (sid != NULL)) { + sid_copy(sid, &r.sid); + } + + result = r.status; + return result; +} + +NTSTATUS rpccli_unixinfo_sid2gid(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const DOM_SID *sid, gid_t *gid) +{ + prs_struct qbuf, rbuf; + UNIXINFO_Q_SID_TO_GID q; + UNIXINFO_R_SID_TO_GID r; + NTSTATUS result = NT_STATUS_NET_WRITE_FAULT; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Marshall data and send request */ + init_q_unixinfo_sid_to_gid(&q, sid); + + CLI_DO_RPC(cli, mem_ctx, PI_UNIXINFO, UNIXINFO_SID_TO_GID, + q, r, + qbuf, rbuf, + unixinfo_io_q_unixinfo_sid_to_gid, + unixinfo_io_r_unixinfo_sid_to_gid, + NT_STATUS_NET_WRITE_FAULT); + + if (NT_STATUS_IS_OK(r.status)) { + if (r.gid.high != 0) { + /* 64-Bit gid's not yet handled */ + return NT_STATUS_INVALID_PARAMETER; + } + if (gid != NULL) { + *gid = r.gid.low; + } + } + + result = r.status; + return result; +} + +NTSTATUS rpccli_unixinfo_getpwuid(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + int count, uid_t *uids, + struct unixinfo_getpwuid **info) +{ + prs_struct qbuf, rbuf; + UNIXINFO_Q_GETPWUID q; + UNIXINFO_R_GETPWUID r; + NTSTATUS result = NT_STATUS_NET_WRITE_FAULT; + int i; + UINT64_S *uids64; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Marshall data and send request */ + + uids64 = TALLOC_ARRAY(mem_ctx, UINT64_S, count); + if (uids64 == NULL) { + return NT_STATUS_NO_MEMORY; + } + + for (i=0; i<count; i++) { + uids64[i].high = 0; + uids64[i].low = uids[i]; + } + + init_q_unixinfo_getpwuid(&q, count, uids64); + + CLI_DO_RPC(cli, mem_ctx, PI_UNIXINFO, UNIXINFO_GETPWUID, + q, r, + qbuf, rbuf, + unixinfo_io_q_unixinfo_getpwuid, + unixinfo_io_r_unixinfo_getpwuid, + NT_STATUS_NET_WRITE_FAULT); + + if (!NT_STATUS_IS_OK(r.status)) { + result = r.status; + *info = NULL; + return result; + } + + if (r.count != count) { + DEBUG(0, ("Expected array size %d, got %d\n", + count, r.count)); + return NT_STATUS_INVALID_PARAMETER; + } + + *info = TALLOC_ARRAY(mem_ctx, struct unixinfo_getpwuid, count); + if (*info == NULL) { + return NT_STATUS_NO_MEMORY; + } + + for (i=0; i<count; i++) { + (*info)[i].status = r.info[i].status; + (*info)[i].homedir = talloc_strdup(mem_ctx, r.info[i].homedir); + (*info)[i].shell = talloc_strdup(mem_ctx, r.info[i].shell); + } + + result = r.status; + return result; +} diff --git a/source/rpc_client/ndr.c b/source/rpc_client/ndr.c new file mode 100644 index 00000000000..985490f71cb --- /dev/null +++ b/source/rpc_client/ndr.c @@ -0,0 +1,90 @@ +/* + Unix SMB/CIFS implementation. + + libndr interface + + Copyright (C) Jelmer Vernooij 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + + +NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, + int p_idx, int opnum, void *data, + ndr_pull_flags_fn_t pull_fn, ndr_push_flags_fn_t push_fn) +{ + prs_struct q_ps, r_ps; + struct ndr_pull *pull; + DATA_BLOB blob; + struct ndr_push *push; + NTSTATUS status; + + SMB_ASSERT(cli->pipe_idx == p_idx); + + push = ndr_push_init_ctx(mem_ctx); + if (!push) { + return NT_STATUS_NO_MEMORY; + } + + status = push_fn(push, NDR_IN, data); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + blob = ndr_push_blob(push); + + if (!prs_init_data_blob(&q_ps, &blob, mem_ctx)) { + return NT_STATUS_NO_MEMORY; + } + + talloc_free(push); + + if (!prs_init( &r_ps, 0, mem_ctx, UNMARSHALL )) { + prs_mem_free( &q_ps ); + return NT_STATUS_NO_MEMORY; + } + + status = rpc_api_pipe_req(cli, opnum, &q_ps, &r_ps); + + prs_mem_free( &q_ps ); + + if (!NT_STATUS_IS_OK(status)) { + prs_mem_free( &r_ps ); + return status; + } + + if (!prs_data_blob(&r_ps, &blob, mem_ctx)) { + prs_mem_free( &r_ps ); + return NT_STATUS_NO_MEMORY; + } + + prs_mem_free( &r_ps ); + + pull = ndr_pull_init_blob(&blob, mem_ctx); + if (pull == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = pull_fn(pull, NDR_OUT, data); + talloc_free(pull); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; +} diff --git a/source/rpc_parse/parse_eventlog.c b/source/rpc_parse/parse_eventlog.c index 4aff9734eed..addf433feb8 100644 --- a/source/rpc_parse/parse_eventlog.c +++ b/source/rpc_parse/parse_eventlog.c @@ -54,7 +54,7 @@ BOOL eventlog_io_q_open_eventlog(const char *desc, EVENTLOG_Q_OPEN_EVENTLOG *q_u if(!prs_align(ps)) return False; - if ( !prs_pointer("", ps, depth, (void**)&q_u->unknown0, sizeof(EVENTLOG_OPEN_UNKNOWN0), (PRS_POINTER_CAST)prs_ev_open_unknown0)) + if ( !prs_pointer("", ps, depth, (void*)&q_u->unknown0, sizeof(EVENTLOG_OPEN_UNKNOWN0), (PRS_POINTER_CAST)prs_ev_open_unknown0)) return False; if ( !prs_unistr4("logname", ps, depth, &q_u->logname) ) diff --git a/source/rpc_parse/parse_lsa.c b/source/rpc_parse/parse_lsa.c index ae4cff53e4b..919b7c39552 100644 --- a/source/rpc_parse/parse_lsa.c +++ b/source/rpc_parse/parse_lsa.c @@ -664,7 +664,7 @@ BOOL lsa_io_r_enum_trust_dom(const char *desc, LSA_R_ENUM_TRUST_DOM *out, if(!prs_uint32("count", ps, depth, &out->count)) return False; - if ( !prs_pointer("trusted_domains", ps, depth, (void**)&out->domlist, sizeof(DOMAIN_LIST), (PRS_POINTER_CAST)lsa_io_domain_list)) + if ( !prs_pointer("trusted_domains", ps, depth, (void*)&out->domlist, sizeof(DOMAIN_LIST), (PRS_POINTER_CAST)lsa_io_domain_list)) return False; if(!prs_ntstatus("status", ps, depth, &out->status)) @@ -3250,7 +3250,7 @@ BOOL lsa_io_r_enum_acct_rights(const char *desc, LSA_R_ENUM_ACCT_RIGHTS *out, pr if(!prs_uint32("count ", ps, depth, &out->count)) return False; - if ( !prs_pointer("rights", ps, depth, (void**)&out->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) ) + if ( !prs_pointer("rights", ps, depth, (void*)&out->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) ) return False; if(!prs_align(ps)) @@ -3302,7 +3302,7 @@ BOOL lsa_io_q_add_acct_rights(const char *desc, LSA_Q_ADD_ACCT_RIGHTS *in, prs_s if(!prs_uint32("count", ps, depth, &in->count)) return False; - if ( !prs_pointer("rights", ps, depth, (void**)&in->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) ) + if ( !prs_pointer("rights", ps, depth, (void*)&in->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) ) return False; return True; @@ -3371,7 +3371,7 @@ BOOL lsa_io_q_remove_acct_rights(const char *desc, LSA_Q_REMOVE_ACCT_RIGHTS *in, if(!prs_uint32("count", ps, depth, &in->count)) return False; - if ( !prs_pointer("rights", ps, depth, (void**)&in->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) ) + if ( !prs_pointer("rights", ps, depth, (void*)&in->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) ) return False; return True; @@ -4056,7 +4056,7 @@ BOOL lsa_io_r_query_trusted_domain_info(const char *desc, prs_debug(ps, depth, desc, "lsa_io_r_query_trusted_domain_info"); depth++; - if (!prs_pointer("trustdom", ps, depth, (void**)&r_q->info, + if (!prs_pointer("trustdom", ps, depth, (void*)&r_q->info, sizeof(LSA_TRUSTED_DOMAIN_INFO), (PRS_POINTER_CAST)lsa_io_trustdom_query) ) return False; @@ -4185,7 +4185,7 @@ BOOL lsa_io_r_query_dom_info(const char *desc, LSA_R_QUERY_DOM_INFO_POLICY *out, prs_debug(ps, depth, desc, "lsa_io_r_query_dom_info"); depth++; - if (!prs_pointer("dominfo", ps, depth, (void**)&out->info, + if (!prs_pointer("dominfo", ps, depth, (void*)&out->info, sizeof(LSA_DOM_INFO_UNION), (PRS_POINTER_CAST)lsa_io_dom_info_query) ) return False; diff --git a/source/rpc_parse/parse_ntsvcs.c b/source/rpc_parse/parse_ntsvcs.c index 599257e8020..ab5f3f75e87 100644 --- a/source/rpc_parse/parse_ntsvcs.c +++ b/source/rpc_parse/parse_ntsvcs.c @@ -77,7 +77,7 @@ BOOL ntsvcs_io_q_get_device_list_size(const char *desc, NTSVCS_Q_GET_DEVICE_LIST if(!prs_align(ps)) return False; - if ( !prs_pointer("devicename", ps, depth, (void**)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) ) + if ( !prs_pointer("devicename", ps, depth, (void*)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) ) return False; if ( !prs_align(ps) ) return False; @@ -127,7 +127,7 @@ BOOL ntsvcs_io_q_get_device_list(const char *desc, NTSVCS_Q_GET_DEVICE_LIST *q_u if(!prs_align(ps)) return False; - if ( !prs_pointer("devicename", ps, depth, (void**)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) ) + if ( !prs_pointer("devicename", ps, depth, (void*)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) ) return False; if( !prs_align(ps) ) return False; diff --git a/source/rpc_parse/parse_prs.c b/source/rpc_parse/parse_prs.c index 14e190892d7..29a3e60aa90 100644 --- a/source/rpc_parse/parse_prs.c +++ b/source/rpc_parse/parse_prs.c @@ -624,9 +624,10 @@ BOOL prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8) ********************************************************************/ BOOL prs_pointer( const char *name, prs_struct *ps, int depth, - void **data, size_t data_size, + void *dta, size_t data_size, BOOL(*prs_fn)(const char*, prs_struct*, int, void*) ) { + void ** data = (void **)dta; uint32 data_p; /* output f000baaa to stream if the pointer is non-zero. */ @@ -1793,3 +1794,32 @@ BOOL schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l return (memcmp(digest_final, verf->packet_digest, sizeof(verf->packet_digest)) == 0); } + +/******************************************************************* +creates a new prs_struct containing a DATA_BLOB +********************************************************************/ +BOOL prs_init_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx) +{ + if (!prs_init( prs, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL )) + return False; + + + if (!prs_copy_data_in(prs, (char *)blob->data, blob->length)) + return False; + + return True; +} + +/******************************************************************* +return the contents of a prs_struct in a DATA_BLOB +********************************************************************/ +BOOL prs_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx) +{ + blob->length = prs_offset(prs); + blob->data = talloc_zero_size(mem_ctx, blob->length); + + if (!prs_copy_all_data_out((char *)blob->data, prs)) + return False; + + return True; +} diff --git a/source/rpc_parse/parse_reg.c b/source/rpc_parse/parse_reg.c index fef1332e5c7..1820a595eda 100644 --- a/source/rpc_parse/parse_reg.c +++ b/source/rpc_parse/parse_reg.c @@ -76,7 +76,7 @@ BOOL reg_io_q_open_hive(const char *desc, REG_Q_OPEN_HIVE *q_u, if(!prs_align(ps)) return False; - if(!prs_pointer("server", ps, depth, (void**)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) + if(!prs_pointer("server", ps, depth, (void*)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) return False; if(!prs_align(ps)) @@ -276,7 +276,7 @@ BOOL reg_io_q_create_key_ex(const char *desc, REG_Q_CREATE_KEY_EX *q_u, if(!prs_uint32("access", ps, depth, &q_u->access)) return False; - if(!prs_pointer("sec_info", ps, depth, (void**)&q_u->sec_info, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + if(!prs_pointer("sec_info", ps, depth, (void*)&q_u->sec_info, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; if ( q_u->sec_info ) { @@ -286,7 +286,7 @@ BOOL reg_io_q_create_key_ex(const char *desc, REG_Q_CREATE_KEY_EX *q_u, return False; } - if(!prs_pointer("disposition", ps, depth, (void**)&q_u->disposition, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + if(!prs_pointer("disposition", ps, depth, (void*)&q_u->disposition, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; return True; @@ -1060,17 +1060,17 @@ BOOL reg_io_r_query_value(const char *desc, REG_R_QUERY_VALUE *r_u, prs_struct * if(!prs_align(ps)) return False; - if ( !prs_pointer("type", ps, depth, (void**)&r_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + if ( !prs_pointer("type", ps, depth, (void*)&r_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - if ( !prs_pointer("value", ps, depth, (void**)&r_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer)) + if ( !prs_pointer("value", ps, depth, (void*)&r_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer)) return False; if(!prs_align(ps)) return False; - if ( !prs_pointer("buf_max_len", ps, depth, (void**)&r_u->buf_max_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + if ( !prs_pointer("buf_max_len", ps, depth, (void*)&r_u->buf_max_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - if ( !prs_pointer("buf_len", ps, depth, (void**)&r_u->buf_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + if ( !prs_pointer("buf_len", ps, depth, (void*)&r_u->buf_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; if(!prs_werror("status", ps, depth, &r_u->status)) @@ -1207,17 +1207,17 @@ BOOL reg_io_q_enum_val(const char *desc, REG_Q_ENUM_VALUE *q_u, prs_struct *ps, if(!prs_align(ps)) return False; - if(!prs_pointer("type", ps, depth, (void**)&q_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + if(!prs_pointer("type", ps, depth, (void*)&q_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - if ( !prs_pointer("value", ps, depth, (void**)&q_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer)) + if ( !prs_pointer("value", ps, depth, (void*)&q_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer)) return False; if(!prs_align(ps)) return False; - if(!prs_pointer("buffer_len", ps, depth, (void**)&q_u->buffer_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + if(!prs_pointer("buffer_len", ps, depth, (void*)&q_u->buffer_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - if(!prs_pointer("name_len", ps, depth, (void**)&q_u->name_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + if(!prs_pointer("name_len", ps, depth, (void*)&q_u->name_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; return True; @@ -1243,17 +1243,17 @@ BOOL reg_io_r_enum_val(const char *desc, REG_R_ENUM_VALUE *r_u, prs_struct *ps, if(!prs_align(ps)) return False; - if(!prs_pointer("type", ps, depth, (void**)&r_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + if(!prs_pointer("type", ps, depth, (void*)&r_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - if ( !prs_pointer("value", ps, depth, (void**)&r_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer)) + if ( !prs_pointer("value", ps, depth, (void*)&r_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer)) return False; if(!prs_align(ps)) return False; - if(!prs_pointer("buffer_len1", ps, depth, (void**)&r_u->buffer_len1, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + if(!prs_pointer("buffer_len1", ps, depth, (void*)&r_u->buffer_len1, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - if(!prs_pointer("buffer_len2", ps, depth, (void**)&r_u->buffer_len2, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + if(!prs_pointer("buffer_len2", ps, depth, (void*)&r_u->buffer_len2, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; if(!prs_werror("status", ps, depth, &r_u->status)) @@ -1457,12 +1457,12 @@ BOOL reg_io_r_enum_key(const char *desc, REG_R_ENUM_KEY *q_u, prs_struct *ps, i if(!prs_align(ps)) return False; - if (!prs_pointer("class", ps, depth, (void**)&q_u->classname, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4)) + if (!prs_pointer("class", ps, depth, (void*)&q_u->classname, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4)) return False; if(!prs_align(ps)) return False; - if (!prs_pointer("time", ps, depth, (void**)&q_u->time, sizeof(NTTIME), (PRS_POINTER_CAST)smb_io_nttime)) + if (!prs_pointer("time", ps, depth, (void*)&q_u->time, sizeof(NTTIME), (PRS_POINTER_CAST)smb_io_nttime)) return False; if(!prs_align(ps)) @@ -1620,12 +1620,12 @@ BOOL reg_io_q_shutdown(const char *desc, REG_Q_SHUTDOWN *q_u, prs_struct *ps, if (!prs_align(ps)) return False; - if (!prs_pointer("server", ps, depth, (void**)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) + if (!prs_pointer("server", ps, depth, (void*)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) return False; if (!prs_align(ps)) return False; - if (!prs_pointer("message", ps, depth, (void**)&q_u->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4)) + if (!prs_pointer("message", ps, depth, (void*)&q_u->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4)) return False; if (!prs_align(ps)) @@ -1680,12 +1680,12 @@ BOOL reg_io_q_shutdown_ex(const char *desc, REG_Q_SHUTDOWN_EX *q_u, prs_struct * if (!prs_align(ps)) return False; - if (!prs_pointer("server", ps, depth, (void**)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) + if (!prs_pointer("server", ps, depth, (void*)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) return False; if (!prs_align(ps)) return False; - if (!prs_pointer("message", ps, depth, (void**)&q_u->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4)) + if (!prs_pointer("message", ps, depth, (void*)&q_u->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4)) return False; if (!prs_align(ps)) @@ -1759,7 +1759,7 @@ BOOL reg_io_q_abort_shutdown(const char *desc, REG_Q_ABORT_SHUTDOWN *q_u, if (!prs_align(ps)) return False; - if (!prs_pointer("server", ps, depth, (void**)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) + if (!prs_pointer("server", ps, depth, (void*)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) return False; if (!prs_align(ps)) return False; diff --git a/source/rpc_parse/parse_rpc.c b/source/rpc_parse/parse_rpc.c index 2d166c773b4..240cac886cf 100644 --- a/source/rpc_parse/parse_rpc.c +++ b/source/rpc_parse/parse_rpc.c @@ -191,6 +191,16 @@ interface/version dce/rpc pipe identification }, 0x00 \ } +#define SYNT_UNIXINFO_V0 \ +{ \ + { \ + 0x9c54e310, 0xa955, 0x4885, \ + { 0xbd, 0x31 }, \ + { 0x78, 0x78, \ + 0x71, 0x47, 0xdf, 0xa6 } \ + }, 0x00 \ +} + #define SYNT_NTSVCS_V1 \ { \ { \ @@ -222,6 +232,7 @@ const struct pipe_id_info pipe_names [] = { PIPE_SHUTDOWN, SYNT_SHUTDOWN_V1 , PIPE_SHUTDOWN , TRANS_SYNT_V2 }, { PIPE_SVCCTL , SYNT_SVCCTL_V2 , PIPE_NTSVCS , TRANS_SYNT_V2 }, { PIPE_EVENTLOG, SYNT_EVENTLOG_V0 , PIPE_EVENTLOG , TRANS_SYNT_V2 }, + { PIPE_UNIXINFO, SYNT_UNIXINFO_V0 , PIPE_UNIXINFO , TRANS_SYNT_V2 }, { PIPE_NTSVCS , SYNT_NTSVCS_V1 , PIPE_NTSVCS , TRANS_SYNT_V2 }, { NULL , SYNT_NONE_V0 , NULL , SYNT_NONE_V0 } }; diff --git a/source/rpc_parse/parse_samr.c b/source/rpc_parse/parse_samr.c index 9026d503c30..26da7b426d7 100644 --- a/source/rpc_parse/parse_samr.c +++ b/source/rpc_parse/parse_samr.c @@ -3854,7 +3854,7 @@ BOOL samr_io_r_query_aliasinfo(const char *desc, SAMR_R_QUERY_ALIASINFO *out, if(!prs_align(ps)) return False; - if ( !prs_pointer("alias", ps, depth, (void**)&out->ctr, sizeof(ALIAS_INFO_CTR), (PRS_POINTER_CAST)samr_alias_info_ctr)) + if ( !prs_pointer("alias", ps, depth, (void*)&out->ctr, sizeof(ALIAS_INFO_CTR), (PRS_POINTER_CAST)samr_alias_info_ctr)) return False; if(!prs_align(ps)) return False; @@ -4896,7 +4896,7 @@ inits a SAMR_R_LOOKUP_NAMES structure. NTSTATUS init_samr_r_lookup_names(TALLOC_CTX *ctx, SAMR_R_LOOKUP_NAMES * r_u, uint32 num_rids, - uint32 *rid, uint32 *type, + uint32 *rid, enum SID_NAME_USE *type, NTSTATUS status) { DEBUG(5, ("init_samr_r_lookup_names\n")); @@ -5741,8 +5741,8 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z copy_unistr2(&usr->uni_workstations, wkstas); init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations); - copy_unistr2(&usr->uni_unknown_str, unk_str); - init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str); + copy_unistr2(&usr->uni_comment, unk_str); + init_uni_hdr(&usr->hdr_comment, &usr->uni_comment); copy_unistr2(&usr->uni_munged_dial, mung_dial); init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial); @@ -5835,8 +5835,8 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z init_unistr2(&usr->uni_workstations, wkstas, UNI_FLAGS_NONE); init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations); - init_unistr2(&usr->uni_unknown_str, unk_str, UNI_FLAGS_NONE); - init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str); + init_unistr2(&usr->uni_comment, unk_str, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_comment, &usr->uni_comment); init_unistr2_from_datablob(&usr->uni_munged_dial, &blob); init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial); @@ -5895,7 +5895,7 @@ static BOOL sam_io_user_info23(const char *desc, SAM_USER_INFO_23 * usr, return False; if(!smb_io_unihdr("hdr_workstations", &usr->hdr_workstations, ps, depth)) /* wkstas user can log on from */ return False; - if(!smb_io_unihdr("hdr_unknown_str ", &usr->hdr_unknown_str, ps, depth)) /* unknown string */ + if(!smb_io_unihdr("hdr_comment ", &usr->hdr_comment, ps, depth)) /* unknown string */ return False; if(!smb_io_unihdr("hdr_munged_dial ", &usr->hdr_munged_dial, ps, depth)) /* wkstas user can log on from */ return False; @@ -5963,7 +5963,7 @@ static BOOL sam_io_user_info23(const char *desc, SAM_USER_INFO_23 * usr, if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth)) /* worksations user can log on from */ return False; - if(!smb_io_unistr2("uni_unknown_str ", &usr->uni_unknown_str, usr->hdr_unknown_str.buffer, ps, depth)) /* unknown string */ + if(!smb_io_unistr2("uni_comment ", &usr->uni_comment, usr->hdr_comment.buffer, ps, depth)) /* unknown string */ return False; if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial, usr->hdr_munged_dial.buffer, ps, depth)) @@ -6025,7 +6025,7 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str return False; if(!smb_io_unihdr("hdr_workstations", &usr->hdr_workstations, ps, depth)) /* wkstas user can log on from */ return False; - if(!smb_io_unihdr("hdr_unknown_str ", &usr->hdr_unknown_str, ps, depth)) /* unknown string */ + if(!smb_io_unihdr("hdr_comment ", &usr->hdr_comment, ps, depth)) /* unknown string */ return False; if(!smb_io_unihdr("hdr_munged_dial ", &usr->hdr_munged_dial, ps, depth)) /* wkstas user can log on from */ return False; @@ -6076,7 +6076,7 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth)) /* worksations user can log on from */ return False; - if(!smb_io_unistr2("uni_unknown_str ", &usr->uni_unknown_str, usr->hdr_unknown_str.buffer, ps, depth)) /* unknown string */ + if(!smb_io_unistr2("uni_comment ", &usr->uni_comment, usr->hdr_comment.buffer, ps, depth)) /* unknown string */ return False; if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial, usr->hdr_munged_dial.buffer, ps, depth)) @@ -6182,8 +6182,8 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr, copy_unistr2(&usr->uni_workstations, wkstas); init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations); - copy_unistr2(&usr->uni_unknown_str, unk_str); - init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str); + copy_unistr2(&usr->uni_comment, unk_str); + init_uni_hdr(&usr->hdr_comment, &usr->uni_comment); copy_unistr2(&usr->uni_munged_dial, mung_dial); init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial); @@ -6331,8 +6331,8 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, struct samu *pw, DOM_SID * init_unistr2(&usr->uni_workstations, workstations, UNI_STR_TERMINATE); init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations); - init_unistr2(&usr->uni_unknown_str, NULL, UNI_STR_TERMINATE); - init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str); + init_unistr2(&usr->uni_comment, NULL, UNI_STR_TERMINATE); + init_uni_hdr(&usr->hdr_comment, &usr->uni_comment); init_unistr2_from_datablob(&usr->uni_munged_dial, &munged_dial_blob); init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial); @@ -6398,7 +6398,7 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr, return False; if(!smb_io_unihdr("hdr_workstations", &usr->hdr_workstations, ps, depth)) /* wkstas user can log on from */ return False; - if(!smb_io_unihdr("hdr_unknown_str ", &usr->hdr_unknown_str, ps, depth)) /* unknown string */ + if(!smb_io_unihdr("hdr_comment ", &usr->hdr_comment, ps, depth)) /* unknown string */ return False; if(!smb_io_unihdr("hdr_munged_dial ", &usr->hdr_munged_dial, ps, depth)) /* wkstas user can log on from */ return False; @@ -6438,25 +6438,25 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr, /* here begins pointed-to data */ - if(!smb_io_unistr2("uni_user_name ", &usr->uni_user_name,usr->hdr_user_name.buffer, ps, depth)) /* username unicode string */ + if(!smb_io_unistr2("uni_user_name ", &usr->uni_user_name,usr->hdr_user_name.buffer, ps, depth)) return False; - if(!smb_io_unistr2("uni_full_name ", &usr->uni_full_name, usr->hdr_full_name.buffer, ps, depth)) /* user's full name unicode string */ + if(!smb_io_unistr2("uni_full_name ", &usr->uni_full_name, usr->hdr_full_name.buffer, ps, depth)) return False; - if(!smb_io_unistr2("uni_home_dir ", &usr->uni_home_dir, usr->hdr_home_dir.buffer, ps, depth)) /* home directory unicode string */ + if(!smb_io_unistr2("uni_home_dir ", &usr->uni_home_dir, usr->hdr_home_dir.buffer, ps, depth)) return False; - if(!smb_io_unistr2("uni_dir_drive ", &usr->uni_dir_drive, usr->hdr_dir_drive.buffer, ps, depth)) /* home directory drive unicode string */ + if(!smb_io_unistr2("uni_dir_drive ", &usr->uni_dir_drive, usr->hdr_dir_drive.buffer, ps, depth)) return False; - if(!smb_io_unistr2("uni_logon_script", &usr->uni_logon_script, usr->hdr_logon_script.buffer, ps, depth)) /* logon script unicode string */ + if(!smb_io_unistr2("uni_logon_script", &usr->uni_logon_script, usr->hdr_logon_script.buffer, ps, depth)) return False; - if(!smb_io_unistr2("uni_profile_path", &usr->uni_profile_path, usr->hdr_profile_path.buffer, ps, depth)) /* profile path unicode string */ + if(!smb_io_unistr2("uni_profile_path", &usr->uni_profile_path, usr->hdr_profile_path.buffer, ps, depth)) return False; - if(!smb_io_unistr2("uni_acct_desc ", &usr->uni_acct_desc, usr->hdr_acct_desc.buffer, ps, depth)) /* user desc unicode string */ + if(!smb_io_unistr2("uni_acct_desc ", &usr->uni_acct_desc, usr->hdr_acct_desc.buffer, ps, depth)) return False; - if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth)) /* worksations user can log on from */ + if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth)) return False; - if(!smb_io_unistr2("uni_unknown_str ", &usr->uni_unknown_str, usr->hdr_unknown_str.buffer, ps, depth)) /* unknown string */ + if(!smb_io_unistr2("uni_comment", &usr->uni_comment, usr->hdr_comment.buffer, ps, depth)) return False; - if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial,usr->hdr_munged_dial.buffer, ps, depth)) /* worksations user can log on from */ + if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial,usr->hdr_munged_dial.buffer, ps, depth)) return False; /* ok, this is only guess-work (as usual) */ diff --git a/source/rpc_parse/parse_shutdown.c b/source/rpc_parse/parse_shutdown.c index da338077333..8c417c05dce 100644 --- a/source/rpc_parse/parse_shutdown.c +++ b/source/rpc_parse/parse_shutdown.c @@ -100,12 +100,12 @@ BOOL shutdown_io_q_init(const char *desc, SHUTDOWN_Q_INIT *q_s, prs_struct *ps, if (!prs_align(ps)) return False; - if (!prs_pointer("server", ps, depth, (void**)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) + if (!prs_pointer("server", ps, depth, (void*)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) return False; if (!prs_align(ps)) return False; - if (!prs_pointer("message", ps, depth, (void**)&q_s->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4)) + if (!prs_pointer("message", ps, depth, (void*)&q_s->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4)) return False; if (!prs_align(ps)) @@ -159,12 +159,12 @@ BOOL shutdown_io_q_init_ex(const char *desc, SHUTDOWN_Q_INIT_EX * q_s, prs_struc if (!prs_align(ps)) return False; - if (!prs_pointer("server", ps, depth, (void**)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) + if (!prs_pointer("server", ps, depth, (void*)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) return False; if (!prs_align(ps)) return False; - if (!prs_pointer("message", ps, depth, (void**)&q_s->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4)) + if (!prs_pointer("message", ps, depth, (void*)&q_s->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4)) return False; if (!prs_align(ps)) @@ -238,7 +238,7 @@ BOOL shutdown_io_q_abort(const char *desc, SHUTDOWN_Q_ABORT *q_s, if (!prs_align(ps)) return False; - if (!prs_pointer("server", ps, depth, (void**)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) + if (!prs_pointer("server", ps, depth, (void*)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) return False; if (!prs_align(ps)) return False; diff --git a/source/rpc_parse/parse_spoolss.c b/source/rpc_parse/parse_spoolss.c index 2884883e893..8d4a757a74a 100644 --- a/source/rpc_parse/parse_spoolss.c +++ b/source/rpc_parse/parse_spoolss.c @@ -606,7 +606,7 @@ static BOOL spool_io_user_level(const char *desc, SPOOL_USER_CTR *q_u, prs_struc switch ( q_u->level ) { case 1: - if ( !prs_pointer( "" , ps, depth, (void**)&q_u->user.user1, + if ( !prs_pointer( "" , ps, depth, (void*)&q_u->user.user1, sizeof(SPOOL_USER_1), (PRS_POINTER_CAST)spool_io_user_level_1 )) { return False; diff --git a/source/rpc_parse/parse_srv.c b/source/rpc_parse/parse_srv.c index 7d15eda630f..5123d1c2cca 100644 --- a/source/rpc_parse/parse_srv.c +++ b/source/rpc_parse/parse_srv.c @@ -7,6 +7,7 @@ * Copyright (C) Jeremy Allison 1999, * Copyright (C) Nigel Williams 2001, * Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2002. + * Copyright (C) Gerald (Jerry) Carter 2006. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1588,64 +1589,17 @@ BOOL srv_io_r_net_share_del(const char *desc, SRV_R_NET_SHARE_DEL *q_n, prs_stru Inits a SESS_INFO_0_STR structure ********************************************************************/ -void init_srv_sess_info0_str(SESS_INFO_0_STR *ss0, const char *name) +void init_srv_sess_info0( SESS_INFO_0 *ss0, const char *name ) { - DEBUG(5,("init_srv_sess_info0_str\n")); + ZERO_STRUCTP( ss0 ); - init_unistr2(&ss0->uni_name, name, UNI_STR_TERMINATE); -} - -/******************************************************************* - Reads or writes a structure. -********************************************************************/ - -static BOOL srv_io_sess_info0_str(const char *desc, SESS_INFO_0_STR *ss0, prs_struct *ps, int depth) -{ - if (ss0 == NULL) - return False; - - prs_debug(ps, depth, desc, "srv_io_sess_info0_str"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!smb_io_unistr2("", &ss0->uni_name, True, ps, depth)) - return False; - - return True; -} - -/******************************************************************* - Inits a SESS_INFO_0 structure -********************************************************************/ - -void init_srv_sess_info0(SESS_INFO_0 *ss0, const char *name) -{ - DEBUG(5,("init_srv_sess_info0: %s\n", name)); - - ss0->ptr_name = (name != NULL) ? 1 : 0; -} - -/******************************************************************* - Reads or writes a structure. -********************************************************************/ - -static BOOL srv_io_sess_info0(const char *desc, SESS_INFO_0 *ss0, prs_struct *ps, int depth) -{ - if (ss0 == NULL) - return False; - - prs_debug(ps, depth, desc, "srv_io_sess_info0"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("ptr_name", ps, depth, &ss0->ptr_name)) - return False; - - return True; + if ( name ) { + if ( (ss0->sharename = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) { + DEBUG(0,("init_srv_sess_info0: talloc failed!\n")); + return; + } + init_unistr2( ss0->sharename, name, UNI_STR_TERMINATE ); + } } /******************************************************************* @@ -1681,13 +1635,15 @@ static BOOL srv_io_srv_sess_info_0(const char *desc, SRV_SESS_INFO_0 *ss0, prs_s SMB_ASSERT_ARRAY(ss0->info_0, num_entries); + /* first the pointers */ for (i = 0; i < num_entries; i++) { - if(!srv_io_sess_info0("", &ss0->info_0[i], ps, depth)) + if ( !prs_io_unistr2_p("", ps, depth, &ss0->info_0[i].sharename ) ) return False; } + /* now the strings */ for (i = 0; i < num_entries; i++) { - if(!srv_io_sess_info0_str("", &ss0->info_0_str[i], ps, depth)) + if ( !prs_io_unistr2("sharename", ps, depth, ss0->info_0[i].sharename )) return False; } @@ -1699,53 +1655,32 @@ static BOOL srv_io_srv_sess_info_0(const char *desc, SRV_SESS_INFO_0 *ss0, prs_s } /******************************************************************* - Inits a SESS_INFO_1_STR structure -********************************************************************/ - -void init_srv_sess_info1_str(SESS_INFO_1_STR *ss1, const char *name, const char *user) -{ - DEBUG(5,("init_srv_sess_info1_str\n")); - - init_unistr2(&ss1->uni_name, name, UNI_STR_TERMINATE); - init_unistr2(&ss1->uni_user, user, UNI_STR_TERMINATE); -} - -/******************************************************************* - Reads or writes a structure. -********************************************************************/ - -static BOOL srv_io_sess_info1_str(const char *desc, SESS_INFO_1_STR *ss1, prs_struct *ps, int depth) -{ - if (ss1 == NULL) - return False; - - prs_debug(ps, depth, desc, "srv_io_sess_info1_str"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!smb_io_unistr2("", &ss1->uni_name, True, ps, depth)) - return False; - if(!smb_io_unistr2("", &(ss1->uni_user), True, ps, depth)) - return False; - - return True; -} - -/******************************************************************* Inits a SESS_INFO_1 structure ********************************************************************/ -void init_srv_sess_info1(SESS_INFO_1 *ss1, - const char *name, const char *user, - uint32 num_opens, uint32 open_time, uint32 idle_time, - uint32 user_flags) +void init_srv_sess_info1( SESS_INFO_1 *ss1, const char *name, const char *user, + uint32 num_opens, uint32 open_time, uint32 idle_time, + uint32 user_flags) { DEBUG(5,("init_srv_sess_info1: %s\n", name)); - ss1->ptr_name = (name != NULL) ? 1 : 0; - ss1->ptr_user = (user != NULL) ? 1 : 0; + ZERO_STRUCTP( ss1 ); + + if ( name ) { + if ( (ss1->sharename = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) { + DEBUG(0,("init_srv_sess_info0: talloc failed!\n")); + return; + } + init_unistr2( ss1->sharename, name, UNI_STR_TERMINATE ); + } + + if ( user ) { + if ( (ss1->username = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) { + DEBUG(0,("init_srv_sess_info0: talloc failed!\n")); + return; + } + init_unistr2( ss1->username, user, UNI_STR_TERMINATE ); + } ss1->num_opens = num_opens; ss1->open_time = open_time; @@ -1753,37 +1688,6 @@ void init_srv_sess_info1(SESS_INFO_1 *ss1, ss1->user_flags = user_flags; } -/******************************************************************* -reads or writes a structure. -********************************************************************/ - -static BOOL srv_io_sess_info1(const char *desc, SESS_INFO_1 *ss1, prs_struct *ps, int depth) -{ - if (ss1 == NULL) - return False; - - prs_debug(ps, depth, desc, "srv_io_sess_info1"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("ptr_name ", ps, depth, &ss1->ptr_name)) - return False; - if(!prs_uint32("ptr_user ", ps, depth, &ss1->ptr_user)) - return False; - - if(!prs_uint32("num_opens ", ps, depth, &ss1->num_opens)) - return False; - if(!prs_uint32("open_time ", ps, depth, &ss1->open_time)) - return False; - if(!prs_uint32("idle_time ", ps, depth, &ss1->idle_time)) - return False; - if(!prs_uint32("user_flags", ps, depth, &ss1->user_flags)) - return False; - - return True; -} /******************************************************************* Reads or writes a structure. @@ -1818,13 +1722,31 @@ static BOOL srv_io_srv_sess_info_1(const char *desc, SRV_SESS_INFO_1 *ss1, prs_s SMB_ASSERT_ARRAY(ss1->info_1, num_entries); + /* first the pointers and flags */ + for (i = 0; i < num_entries; i++) { - if(!srv_io_sess_info1("", &ss1->info_1[i], ps, depth)) + + if ( !prs_io_unistr2_p("", ps, depth, &ss1->info_1[i].sharename )) + return False; + if ( !prs_io_unistr2_p("", ps, depth, &ss1->info_1[i].username )) + return False; + + if(!prs_uint32("num_opens ", ps, depth, &ss1->info_1[i].num_opens)) + return False; + if(!prs_uint32("open_time ", ps, depth, &ss1->info_1[i].open_time)) + return False; + if(!prs_uint32("idle_time ", ps, depth, &ss1->info_1[i].idle_time)) + return False; + if(!prs_uint32("user_flags", ps, depth, &ss1->info_1[i].user_flags)) return False; } + /* now the strings */ + for (i = 0; i < num_entries; i++) { - if(!srv_io_sess_info1_str("", &ss1->info_1_str[i], ps, depth)) + if ( !prs_io_unistr2("", ps, depth, ss1->info_1[i].sharename )) + return False; + if ( !prs_io_unistr2("", ps, depth, ss1->info_1[i].username )) return False; } @@ -1884,36 +1806,12 @@ static BOOL srv_io_srv_sess_ctr(const char *desc, SRV_SESS_INFO_CTR **pp_ctr, pr } /******************************************************************* - Inits a SRV_Q_NET_SESS_ENUM structure. -********************************************************************/ - -void init_srv_q_net_sess_enum(SRV_Q_NET_SESS_ENUM *q_n, - const char *srv_name, const char *qual_name, - const char *user_name, uint32 sess_level, - SRV_SESS_INFO_CTR *ctr, uint32 preferred_len, - ENUM_HND *hnd) -{ - q_n->ctr = ctr; - - DEBUG(5,("init_q_net_sess_enum\n")); - - init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name); - init_buf_unistr2(&q_n->uni_qual_name, &q_n->ptr_qual_name, qual_name); - init_buf_unistr2(&q_n->uni_user_name, &q_n->ptr_user_name, user_name); - - q_n->sess_level = sess_level; - q_n->preferred_len = preferred_len; - - memcpy(&q_n->enum_hnd, hnd, sizeof(*hnd)); -} - -/******************************************************************* Reads or writes a structure. ********************************************************************/ -BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_n, prs_struct *ps, int depth) +BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_u, prs_struct *ps, int depth) { - if (q_n == NULL) + if (q_u == NULL) return False; prs_debug(ps, depth, desc, "srv_io_q_net_sess_enum"); @@ -1922,41 +1820,36 @@ BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_n, prs_stru if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name)) - return False; - if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth)) + if(!prs_pointer("servername", ps, depth, (void*)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_qual_name", ps, depth, &q_n->ptr_qual_name)) - return False; - if(!smb_io_unistr2("", &q_n->uni_qual_name, q_n->ptr_qual_name, ps, depth)) + if(!prs_pointer("qualifier", ps, depth, (void*)&q_u->qualifier, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_user_name", ps, depth, &q_n->ptr_user_name)) - return False; - if(!smb_io_unistr2("", &q_n->uni_user_name, q_n->ptr_user_name, ps, depth)) + + if(!prs_pointer("username", ps, depth, (void*)&q_u->username, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("sess_level", ps, depth, &q_n->sess_level)) + if(!prs_uint32("sess_level", ps, depth, &q_u->sess_level)) return False; - if (q_n->sess_level != (uint32)-1) { - if(!srv_io_srv_sess_ctr("sess_ctr", &q_n->ctr, ps, depth)) + if (q_u->sess_level != (uint32)-1) { + if(!srv_io_srv_sess_ctr("sess_ctr", &q_u->ctr, ps, depth)) return False; } - if(!prs_uint32("preferred_len", ps, depth, &q_n->preferred_len)) + if(!prs_uint32("preferred_len", ps, depth, &q_u->preferred_len)) return False; - if(!smb_io_enum_hnd("enum_hnd", &q_n->enum_hnd, ps, depth)) + if(!smb_io_enum_hnd("enum_hnd", &q_u->enum_hnd, ps, depth)) return False; return True; @@ -2434,22 +2327,10 @@ BOOL srv_io_r_net_conn_enum(const char *desc, SRV_R_NET_CONN_ENUM *r_n, prs_str } /******************************************************************* - Inits a FILE_INFO_3_STR structure -********************************************************************/ - -void init_srv_file_info3_str(FILE_INFO_3_STR *fi3, const char *user_name, const char *path_name) -{ - DEBUG(5,("init_srv_file_info3_str\n")); - - init_unistr2(&fi3->uni_path_name, path_name, UNI_STR_TERMINATE); - init_unistr2(&fi3->uni_user_name, user_name, UNI_STR_TERMINATE); -} - -/******************************************************************* Reads or writes a structure. ********************************************************************/ -static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_struct *ps, int depth) +static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3 *sh1, prs_struct *ps, int depth) { if (sh1 == NULL) return False; @@ -2460,10 +2341,15 @@ static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_st if(!prs_align(ps)) return False; - if(!smb_io_unistr2("", &sh1->uni_path_name, True, ps, depth)) - return False; - if(!smb_io_unistr2("", &sh1->uni_user_name, True, ps, depth)) - return False; + if ( sh1->path ) { + if(!smb_io_unistr2("", sh1->path, True, ps, depth)) + return False; + } + + if ( sh1->user ) { + if(!smb_io_unistr2("", sh1->user, True, ps, depth)) + return False; + } return True; } @@ -2472,18 +2358,26 @@ static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_st Inits a FILE_INFO_3 structure ********************************************************************/ -void init_srv_file_info3(FILE_INFO_3 *fl3, - uint32 id, uint32 perms, uint32 num_locks, - const char *path_name, const char *user_name) +void init_srv_file_info3( FILE_INFO_3 *fl3, uint32 id, uint32 perms, uint32 num_locks, + const char *user_name, const char *path_name ) { - DEBUG(5,("init_srv_file_info3: %s %s\n", path_name, user_name)); - fl3->id = id; fl3->perms = perms; fl3->num_locks = num_locks; - fl3->ptr_path_name = (path_name != NULL) ? 1 : 0; - fl3->ptr_user_name = (user_name != NULL) ? 1 : 0; + if ( path_name ) { + if ( (fl3->path = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) + return; + init_unistr2(fl3->path, path_name, UNI_STR_TERMINATE); + } + + if ( user_name ) { + if ( (fl3->user = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) + return; + init_unistr2(fl3->user, user_name, UNI_STR_TERMINATE); + } + + return; } /******************************************************************* @@ -2492,6 +2386,8 @@ void init_srv_file_info3(FILE_INFO_3 *fl3, static BOOL srv_io_file_info3(const char *desc, FILE_INFO_3 *fl3, prs_struct *ps, int depth) { + uint32 uni_p; + if (fl3 == NULL) return False; @@ -2507,10 +2403,24 @@ static BOOL srv_io_file_info3(const char *desc, FILE_INFO_3 *fl3, prs_struct *ps return False; if(!prs_uint32("num_locks ", ps, depth, &fl3->num_locks)) return False; - if(!prs_uint32("ptr_path_name", ps, depth, &fl3->ptr_path_name)) + + uni_p = fl3->path ? 1 : 0; + if(!prs_uint32("ptr", ps, depth, &uni_p)) return False; - if(!prs_uint32("ptr_user_name", ps, depth, &fl3->ptr_user_name)) + if (UNMARSHALLING(ps)) { + if ( (fl3->path = PRS_ALLOC_MEM( ps, UNISTR2, 1)) == NULL ) { + return False; + } + } + + uni_p = fl3->user ? 1 : 0; + if(!prs_uint32("ptr", ps, depth, &uni_p)) return False; + if (UNMARSHALLING(ps)) { + if ( (fl3->user = PRS_ALLOC_MEM( ps, UNISTR2, 1)) == NULL ) { + return False; + } + } return True; } @@ -2528,55 +2438,53 @@ static BOOL srv_io_srv_file_ctr(const char *desc, SRV_FILE_INFO_CTR *ctr, prs_st depth++; if (UNMARSHALLING(ps)) { - memset(ctr, '\0', sizeof(SRV_FILE_INFO_CTR)); + ZERO_STRUCTP(ctr); } if(!prs_align(ps)) return False; - if(!prs_uint32("switch_value", ps, depth, &ctr->switch_value)) + if(!prs_uint32("level", ps, depth, &ctr->level)) return False; - if (ctr->switch_value != 3) { - DEBUG(5,("%s File info %d level not supported\n", - tab_depth(depth), ctr->switch_value)); - } + if(!prs_uint32("ptr_file_info", ps, depth, &ctr->ptr_file_info)) return False; if(!prs_uint32("num_entries", ps, depth, &ctr->num_entries)) return False; if(!prs_uint32("ptr_entries", ps, depth, &ctr->ptr_entries)) return False; + if (ctr->ptr_entries == 0) return True; - if(!prs_uint32("num_entries2", ps, depth, - &ctr->num_entries2)) + + if(!prs_uint32("num_entries2", ps, depth, &ctr->num_entries2)) return False; - switch (ctr->switch_value) { + switch (ctr->level) { case 3: { - SRV_FILE_INFO_3 *info3 = ctr->file.info3; + FILE_INFO_3 *info3 = ctr->file.info3; int num_entries = ctr->num_entries; int i; if (UNMARSHALLING(ps)) { - if (!(info3 = PRS_ALLOC_MEM(ps, SRV_FILE_INFO_3, num_entries))) + if (!(info3 = PRS_ALLOC_MEM(ps, FILE_INFO_3, num_entries))) return False; ctr->file.info3 = info3; } for (i = 0; i < num_entries; i++) { - if(!srv_io_file_info3("", &ctr->file.info3[i].info_3, ps, depth)) + if(!srv_io_file_info3("", &ctr->file.info3[i], ps, depth)) return False; } + for (i = 0; i < num_entries; i++) { - if(!srv_io_file_info3_str("", &ctr->file.info3[i].info_3_str, ps, depth)) + if(!srv_io_file_info3_str("", &ctr->file.info3[i], ps, depth)) return False; } break; } default: - DEBUG(5,("%s no file info at switch_value %d\n", - tab_depth(depth), ctr->switch_value)); + DEBUG(5,("%s no file info at switch_value %d\n", tab_depth(depth), ctr->level)); break; } @@ -2594,13 +2502,28 @@ void init_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n, uint32 preferred_len, ENUM_HND *hnd) { - DEBUG(5,("init_q_net_file_enum\n")); + uint32 ptr; - init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name); - init_buf_unistr2(&q_n->uni_qual_name, &q_n->ptr_qual_name, qual_name); - init_buf_unistr2(&q_n->uni_user_name, &q_n->ptr_user_name, user_name); + if ( srv_name ) { + if ( (q_n->servername = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) + return; + init_buf_unistr2(q_n->servername, &ptr, srv_name); + } + + if ( qual_name ) { + if ( (q_n->qualifier = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) + return; + init_buf_unistr2(q_n->qualifier, &ptr, qual_name); + } + + if ( user_name ) { + if ( (q_n->username = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) + return; + init_buf_unistr2(q_n->username, &ptr, user_name); + } + + q_n->level = q_n->ctr.level = file_level; - q_n->file_level = q_n->ctr.switch_value = file_level; q_n->preferred_len = preferred_len; q_n->ctr.ptr_file_info = 1; q_n->ctr.num_entries = 0; @@ -2613,9 +2536,9 @@ void init_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n, Reads or writes a structure. ********************************************************************/ -BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_n, prs_struct *ps, int depth) +BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_u, prs_struct *ps, int depth) { - if (q_n == NULL) + if (q_u == NULL) return False; prs_debug(ps, depth, desc, "srv_io_q_net_file_enum"); @@ -2624,41 +2547,33 @@ BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_n, prs_stru if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name)) + if(!prs_pointer("servername", ps, depth, (void*)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; - if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth)) - return False; - if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_qual_name", ps, depth, &q_n->ptr_qual_name)) - return False; - if(!smb_io_unistr2("", &q_n->uni_qual_name, q_n->ptr_qual_name, ps, depth)) + if(!prs_pointer("qualifier", ps, depth, (void*)&q_u->qualifier, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; - if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_user_name", ps, depth, &q_n->ptr_user_name)) - return False; - if(!smb_io_unistr2("", &q_n->uni_user_name, q_n->ptr_user_name, ps, depth)) + if(!prs_pointer("username", ps, depth, (void*)&q_u->username, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; - if(!prs_align(ps)) return False; - if(!prs_uint32("file_level", ps, depth, &q_n->file_level)) + + if(!prs_uint32("level", ps, depth, &q_u->level)) return False; - if (q_n->file_level != (uint32)-1) { - if(!srv_io_srv_file_ctr("file_ctr", &q_n->ctr, ps, depth)) + if (q_u->level != (uint32)-1) { + if(!srv_io_srv_file_ctr("file_ctr", &q_u->ctr, ps, depth)) return False; } - if(!prs_uint32("preferred_len", ps, depth, &q_n->preferred_len)) + if(!prs_uint32("preferred_len", ps, depth, &q_u->preferred_len)) return False; - if(!smb_io_enum_hnd("enum_hnd", &q_n->enum_hnd, ps, depth)) + if(!smb_io_enum_hnd("enum_hnd", &q_u->enum_hnd, ps, depth)) return False; return True; @@ -2679,10 +2594,10 @@ BOOL srv_io_r_net_file_enum(const char *desc, SRV_R_NET_FILE_ENUM *r_n, prs_stru if(!prs_align(ps)) return False; - if(!prs_uint32("file_level", ps, depth, &r_n->file_level)) + if(!prs_uint32("level", ps, depth, &r_n->level)) return False; - if (r_n->file_level != 0) { + if (r_n->level != 0) { if(!srv_io_srv_file_ctr("file_ctr", &r_n->ctr, ps, depth)) return False; } @@ -2703,63 +2618,17 @@ BOOL srv_io_r_net_file_enum(const char *desc, SRV_R_NET_FILE_ENUM *r_n, prs_stru void init_srv_q_net_file_close(SRV_Q_NET_FILE_CLOSE *q_n, const char *server, uint32 file_id) { - q_n->ptr_srv_name = 1; - init_unistr2(&q_n->uni_srv_name, server, UNI_STR_TERMINATE); - q_n->file_id = file_id; -} - -/******************************************************************* - Reads or writes a structure. -********************************************************************/ -BOOL srv_io_q_net_file_close(const char *desc, SRV_Q_NET_FILE_CLOSE *q_n, - prs_struct *ps, int depth) -{ - if (q_n == NULL) - return False; - - prs_debug(ps, depth, desc, "srv_io_q_net_file_close"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name)) - return False; - if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth)) - return False; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("file_id", ps, depth, &q_n->file_id)) - return False; + if ( server ) { + if ( (q_n->servername = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) { + return; + } + init_unistr2(q_n->servername, server, UNI_STR_TERMINATE); + } - return True; + q_n->file_id = file_id; } /******************************************************************* - Reads or writes a structure. -********************************************************************/ - -BOOL srv_io_r_net_file_close(const char *desc, SRV_R_NET_FILE_CLOSE *q_n, - prs_struct *ps, int depth) -{ - if (q_n == NULL) - return False; - - prs_debug(ps, depth, desc, "srv_io_r_net_file_close"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_werror("status", ps, depth, &q_n->status)) - return False; - - return True; -} - -/******************************************************************* Inits a SRV_INFO_100 structure. ********************************************************************/ @@ -3411,25 +3280,6 @@ BOOL srv_io_r_net_disk_enum(const char *desc, SRV_R_NET_DISK_ENUM *r_n, prs_stru } /******************************************************************* - initialises a structure. - ********************************************************************/ - -BOOL init_srv_q_net_name_validate(SRV_Q_NET_NAME_VALIDATE *q_n, const char *srv_name, const char *share_name, int type) -{ - uint32 ptr_share_name; - - DEBUG(5,("init_srv_q_net_name_validate\n")); - - init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name); - init_buf_unistr2(&q_n->uni_name, &ptr_share_name, share_name); - - q_n->type = type; - q_n->flags = 0; - - return True; -} - -/******************************************************************* Reads or writes a structure. ********************************************************************/ @@ -3444,16 +3294,13 @@ BOOL srv_io_q_net_name_validate(const char *desc, SRV_Q_NET_NAME_VALIDATE *q_n, if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name)) - return False; - - if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth)) + if(!prs_pointer("servername", ps, depth, (void*)&q_n->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; if(!prs_align(ps)) return False; - if(!smb_io_unistr2("", &q_n->uni_name, True, ps, depth)) + if(!smb_io_unistr2("", &q_n->sharename, True, ps, depth)) return False; if(!prs_align(ps)) @@ -3663,3 +3510,48 @@ void init_srv_q_net_remote_tod(SRV_Q_NET_REMOTE_TOD *q_u, const char *server) q_u->ptr_srv_name = 1; init_unistr2(&q_u->uni_srv_name, server, UNI_STR_TERMINATE); } + + +/******************************************************************* + Reads or writes a structure. +********************************************************************/ + +BOOL srv_io_q_net_file_close(const char *desc, SRV_Q_NET_FILE_CLOSE *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "srv_io_q_net_file_close"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_pointer("servername", ps, depth, (void*)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) + return False; + if(!prs_align(ps)) + return False; + + if(!prs_uint32("file_id", ps, depth, &q_u->file_id)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +BOOL srv_io_r_net_file_close(const char *desc, SRV_R_NET_FILE_CLOSE *r_n, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "srv_io_r_net_file_close"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_werror("status", ps, depth, &r_n->status)) + return False; + + return True; +} diff --git a/source/rpc_parse/parse_svcctl.c b/source/rpc_parse/parse_svcctl.c index 2cb44c63195..dc4ee3e6e99 100644 --- a/source/rpc_parse/parse_svcctl.c +++ b/source/rpc_parse/parse_svcctl.c @@ -257,12 +257,12 @@ BOOL svcctl_io_q_open_scmanager(const char *desc, SVCCTL_Q_OPEN_SCMANAGER *q_u, if(!prs_align(ps)) return False; - if(!prs_pointer("servername", ps, depth, (void**)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) + if(!prs_pointer("servername", ps, depth, (void*)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; if(!prs_align(ps)) return False; - if(!prs_pointer("database", ps, depth, (void**)&q_u->database, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) + if(!prs_pointer("database", ps, depth, (void*)&q_u->database, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) return False; if(!prs_align(ps)) return False; @@ -486,7 +486,7 @@ BOOL svcctl_io_q_enum_services_status(const char *desc, SVCCTL_Q_ENUM_SERVICES_S if(!prs_uint32("buffer_size", ps, depth, &q_u->buffer_size)) return False; - if(!prs_pointer("resume", ps, depth, (void**)&q_u->resume, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + if(!prs_pointer("resume", ps, depth, (void*)&q_u->resume, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; return True; @@ -517,7 +517,7 @@ BOOL svcctl_io_r_enum_services_status(const char *desc, SVCCTL_R_ENUM_SERVICES_S if(!prs_uint32("returned", ps, depth, &r_u->returned)) return False; - if(!prs_pointer("resume", ps, depth, (void**)&r_u->resume, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + if(!prs_pointer("resume", ps, depth, (void*)&r_u->resume, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; if(!prs_werror("status", ps, depth, &r_u->status)) @@ -546,7 +546,7 @@ BOOL svcctl_io_q_start_service(const char *desc, SVCCTL_Q_START_SERVICE *q_u, pr if(!prs_uint32("parmcount", ps, depth, &q_u->parmcount)) return False; - if ( !prs_pointer("rights", ps, depth, (void**)&q_u->parameters, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) ) + if ( !prs_pointer("rights", ps, depth, (void*)&q_u->parameters, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) ) return False; return True; @@ -821,9 +821,9 @@ BOOL svcctl_io_service_fa( const char *desc, SERVICE_FAILURE_ACTIONS *fa, RPC_BU if ( !prs_uint32("reset_period", ps, depth, &fa->reset_period) ) return False; - if ( !prs_pointer( desc, ps, depth, (void**)&fa->rebootmsg, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) ) + if ( !prs_pointer( desc, ps, depth, (void*)&fa->rebootmsg, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) ) return False; - if ( !prs_pointer( desc, ps, depth, (void**)&fa->command, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) ) + if ( !prs_pointer( desc, ps, depth, (void*)&fa->command, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) ) return False; if ( !prs_uint32("num_actions", ps, depth, &fa->num_actions) ) diff --git a/source/rpc_parse/parse_unixinfo.c b/source/rpc_parse/parse_unixinfo.c new file mode 100644 index 00000000000..391713ce901 --- /dev/null +++ b/source/rpc_parse/parse_unixinfo.c @@ -0,0 +1,266 @@ +/* + * Unix SMB/CIFS implementation. + * + * RPC Pipe client / server routines + * + * Copyright (C) Volker Lendecke 2005 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_PARSE + +void init_q_unixinfo_sid_to_uid(UNIXINFO_Q_SID_TO_UID *q_d, const DOM_SID *sid) +{ + sid_copy(&q_d->sid, sid); +} + +BOOL unixinfo_io_q_unixinfo_sid_to_uid(const char *desc, UNIXINFO_Q_SID_TO_UID *q_d, + prs_struct *ps, int depth) +{ + return smb_io_dom_sid(desc, &q_d->sid, ps, depth); +} + +BOOL unixinfo_io_r_unixinfo_sid_to_uid(const char *desc, UNIXINFO_R_SID_TO_UID *r_d, + prs_struct *ps, int depth) +{ + if (!prs_uint64(desc, ps, depth, &r_d->uid)) + return False; + + if (!prs_ntstatus(desc, ps, depth, &r_d->status)) + return False; + + return True; +} + +void init_q_unixinfo_uid_to_sid(UNIXINFO_Q_UID_TO_SID *q_d, UINT64_S uid) +{ + q_d->uid = uid; +} + +BOOL unixinfo_io_q_unixinfo_uid_to_sid(const char *desc, UNIXINFO_Q_UID_TO_SID *q_d, + prs_struct *ps, int depth) +{ + return prs_uint64(desc, ps, depth, &q_d->uid); +} + +void init_r_unixinfo_uid_to_sid(UNIXINFO_R_UID_TO_SID *r_d, DOM_SID *sid) +{ + if (sid == NULL) { + r_d->sidptr = 0; + return; + } + r_d->sidptr = 1; + sid_copy(&r_d->sid, sid); +} + +BOOL unixinfo_io_r_unixinfo_uid_to_sid(const char *desc, UNIXINFO_R_UID_TO_SID *r_d, + prs_struct *ps, int depth) +{ + if (!prs_uint32("sidptr", ps, depth, &r_d->sidptr)) + return False; + + if (r_d->sidptr != 0) { + if (!smb_io_dom_sid(desc, &r_d->sid, ps, depth)) + return False; + } + + if (!prs_ntstatus(desc, ps, depth, &r_d->status)) + return False; + + return True; +} + +void init_q_unixinfo_sid_to_gid(UNIXINFO_Q_SID_TO_GID *q_d, const DOM_SID *sid) +{ + sid_copy(&q_d->sid, sid); +} + +BOOL unixinfo_io_q_unixinfo_sid_to_gid(const char *desc, UNIXINFO_Q_SID_TO_GID *q_d, + prs_struct *ps, int depth) +{ + return smb_io_dom_sid(desc, &q_d->sid, ps, depth); +} + +void init_r_unixinfo_sid_to_gid(UNIXINFO_R_SID_TO_GID *r_d, UINT64_S gid) +{ + r_d->gid = gid; + r_d->status = NT_STATUS_OK; +} + +BOOL unixinfo_io_r_unixinfo_sid_to_gid(const char *desc, UNIXINFO_R_SID_TO_GID *r_d, + prs_struct *ps, int depth) +{ + if (!prs_uint64(desc, ps, depth, &r_d->gid)) + return False; + + if (!prs_ntstatus(desc, ps, depth, &r_d->status)) + return False; + + return True; +} + +void init_q_unixinfo_gid_to_sid(UNIXINFO_Q_GID_TO_SID *q_d, UINT64_S gid) +{ + q_d->gid = gid; +} + +BOOL unixinfo_io_q_unixinfo_gid_to_sid(const char *desc, UNIXINFO_Q_GID_TO_SID *q_d, + prs_struct *ps, int depth) +{ + return prs_uint64(desc, ps, depth, &q_d->gid); +} + +void init_r_unixinfo_gid_to_sid(UNIXINFO_R_GID_TO_SID *r_d, DOM_SID *sid) +{ + if (sid == NULL) { + r_d->sidptr = 0; + return; + } + r_d->sidptr = 1; + sid_copy(&r_d->sid, sid); +} + +BOOL unixinfo_io_r_unixinfo_gid_to_sid(const char *desc, UNIXINFO_R_GID_TO_SID *r_d, + prs_struct *ps, int depth) +{ + if (!prs_uint32("sidptr", ps, depth, &r_d->sidptr)) + return False; + + if (r_d->sidptr != 0) { + if (!smb_io_dom_sid(desc, &r_d->sid, ps, depth)) + return False; + } + + if (!prs_ntstatus(desc, ps, depth, &r_d->status)) + return False; + + return True; +} + +void init_q_unixinfo_getpwuid(UNIXINFO_Q_GETPWUID *r_d, int count, + UINT64_S *uids) +{ + r_d->count = count; + r_d->uid = uids; +} + +BOOL unixinfo_io_q_unixinfo_getpwuid(const char *desc, + UNIXINFO_Q_GETPWUID *q_d, + prs_struct *ps, int depth) +{ + uint32 arraysize; + int i; + + if (!prs_uint32("count", ps, depth, &q_d->count)) + return False; + + arraysize = q_d->count; + + if (!prs_uint32("arraysize", ps, depth, &arraysize)) + return False; + + if (arraysize != q_d->count) { + DEBUG(10, ("count!=arraysize\n")); + return False; + } + + if (q_d->count > 1023) { + DEBUG(10, ("Range exceeded\n")); + return False; + } + + if (UNMARSHALLING(ps)) { + q_d->uid = PRS_ALLOC_MEM(ps, UINT64_S, q_d->count); + if (q_d->uid == NULL) { + return False; + } + } + + for (i=0; i<q_d->count; i++) { + if (!prs_uint64(desc, ps, depth+1, &q_d->uid[i])) + return False; + } + + return True; +} + +void init_r_unixinfo_getpwuid(UNIXINFO_R_GETPWUID *r_d, uint32 count, + struct unixinfo_getpwuid *info) +{ + r_d->count = count; + r_d->info = info; +} + +BOOL unixinfo_io_r_unixinfo_getpwuid(const char *desc, + UNIXINFO_R_GETPWUID *r_d, + prs_struct *ps, int depth) +{ + uint32 arraysize; + int i; + + if (!prs_uint32("count", ps, depth, &r_d->count)) + return False; + + arraysize = r_d->count; + + if (!prs_uint32("arraysize", ps, depth, &arraysize)) + return False; + + if (arraysize != r_d->count) { + DEBUG(10, ("count!=arraysize\n")); + return False; + } + + if (r_d->count > 1023) { + DEBUG(10, ("Range exceeded\n")); + return False; + } + + if (UNMARSHALLING(ps)) { + r_d->info = PRS_ALLOC_MEM(ps, struct unixinfo_getpwuid, + r_d->count); + if (r_d->info == NULL) { + return False; + } + } + + for (i=0; i<r_d->count; i++) { + if (!prs_align(ps)) + return False; + + if (!prs_ntstatus("status", ps, depth+1, &r_d->info[i].status)) + return False; + + if (!prs_string_alloc("homedir", ps, depth+1, + &r_d->info[i].homedir)) + return False; + + if (!prs_string_alloc("shell", ps, depth+1, + &r_d->info[i].shell)) + return False; + } + + if (!prs_align(ps)) + return False; + + if (!prs_ntstatus(desc, ps, depth, &r_d->status)) + return False; + + return True; +} diff --git a/source/rpc_server/srv_dfs_nt.c b/source/rpc_server/srv_dfs_nt.c index 8239584522a..c7f8e05d91c 100644 --- a/source/rpc_server/srv_dfs_nt.c +++ b/source/rpc_server/srv_dfs_nt.c @@ -40,7 +40,6 @@ uint32 _dfs_GetManagerVersion(pipes_struct *p, NETDFS_Q_DFS_GETMANAGERVERSION *q WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u) { - struct current_user user; struct junction_map jn; struct referral* old_referral_list = NULL; BOOL exists = False; @@ -48,9 +47,7 @@ WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u) pstring dfspath, servername, sharename; pstring altpath; - get_current_user(&user,p); - - if (user.ut.uid != 0) { + if (p->pipe_user.ut.uid != 0) { DEBUG(10,("_dfs_add: uid != 0. Access denied.\n")); return WERR_ACCESS_DENIED; } @@ -104,16 +101,13 @@ WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u) WERROR _dfs_Remove(pipes_struct *p, NETDFS_Q_DFS_REMOVE *q_u, NETDFS_R_DFS_REMOVE *r_u) { - struct current_user user; struct junction_map jn; BOOL found = False; pstring dfspath, servername, sharename; pstring altpath; - get_current_user(&user,p); - - if (user.ut.uid != 0) { + if (p->pipe_user.ut.uid != 0) { DEBUG(10,("_dfs_remove: uid != 0. Access denied.\n")); return WERR_ACCESS_DENIED; } diff --git a/source/rpc_server/srv_lsa_nt.c b/source/rpc_server/srv_lsa_nt.c index efa7156eea6..2cc5ef61104 100644 --- a/source/rpc_server/srv_lsa_nt.c +++ b/source/rpc_server/srv_lsa_nt.c @@ -1557,17 +1557,23 @@ NTSTATUS _lsa_create_account(pipes_struct *p, LSA_Q_CREATEACCOUNT *q_u, LSA_R_CR * I don't know if it's the right one. not documented. * but guessed with rpcclient. */ - if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION)) + if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION)) { + DEBUG(10, ("_lsa_create_account: No POLICY_GET_PRIVATE_INFORMATION access right!\n")); return NT_STATUS_ACCESS_DENIED; + } /* check to see if the pipe_user is a Domain Admin since account_pol.tdb was already opened as root, this is all we have */ - if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) + if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) { + DEBUG(10, ("_lsa_create_account: The use is not a Domain Admin, deny access!\n")); return NT_STATUS_ACCESS_DENIED; + } - if ( is_privileged_sid( &q_u->sid.sid ) ) + if ( is_privileged_sid( &q_u->sid.sid ) ) { + DEBUG(10, ("_lsa_create_account: Policy account already exists!\n")); return NT_STATUS_OBJECT_NAME_COLLISION; + } /* associate the user/group SID with the (unique) handle. */ @@ -1582,6 +1588,7 @@ NTSTATUS _lsa_create_account(pipes_struct *p, LSA_Q_CREATEACCOUNT *q_u, LSA_R_CR if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info)) return NT_STATUS_OBJECT_NAME_NOT_FOUND; + DEBUG(10, ("_lsa_create_account: call privileges code to create an account\n")); return privilege_create_account( &info->sid ); } @@ -1676,7 +1683,7 @@ NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA return NT_STATUS_INVALID_HANDLE; if (!lookup_sid(p->mem_ctx, &info->sid, NULL, NULL, NULL)) - return NT_STATUS_ACCESS_DENIED; + return NT_STATUS_OK; /* 0x01 -> Log on locally @@ -1727,7 +1734,6 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u struct lsa_info *info = NULL; SE_PRIV mask; PRIVILEGE_SET *set = NULL; - struct current_user user; /* find the connection policy handle. */ if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) @@ -1736,8 +1742,7 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u /* check to see if the pipe_user is root or a Domain Admin since account_pol.tdb was already opened as root, this is all we have */ - get_current_user( &user, p ); - if ( user.ut.uid != sec_initial_uid() + if ( p->pipe_user.ut.uid != sec_initial_uid() && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) { return NT_STATUS_ACCESS_DENIED; @@ -1768,7 +1773,6 @@ NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEP struct lsa_info *info = NULL; SE_PRIV mask; PRIVILEGE_SET *set = NULL; - struct current_user user; /* find the connection policy handle. */ if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) @@ -1777,8 +1781,7 @@ NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEP /* check to see if the pipe_user is root or a Domain Admin since account_pol.tdb was already opened as root, this is all we have */ - get_current_user( &user, p ); - if ( user.ut.uid != sec_initial_uid() + if ( p->pipe_user.ut.uid != sec_initial_uid() && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) { return NT_STATUS_ACCESS_DENIED; @@ -1929,7 +1932,6 @@ NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R DOM_SID sid; fstring privname; UNISTR4_ARRAY *uni_privnames = q_u->rights; - struct current_user user; /* find the connection policy handle. */ @@ -1939,8 +1941,7 @@ NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R /* check to see if the pipe_user is a Domain Admin since account_pol.tdb was already opened as root, this is all we have */ - get_current_user( &user, p ); - if ( user.ut.uid != sec_initial_uid() + if ( p->pipe_user.ut.uid != sec_initial_uid() && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) { return NT_STATUS_ACCESS_DENIED; @@ -1987,7 +1988,6 @@ NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u, DOM_SID sid; fstring privname; UNISTR4_ARRAY *uni_privnames = q_u->rights; - struct current_user user; /* find the connection policy handle. */ @@ -1997,8 +1997,7 @@ NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u, /* check to see if the pipe_user is a Domain Admin since account_pol.tdb was already opened as root, this is all we have */ - get_current_user( &user, p ); - if ( user.ut.uid != sec_initial_uid() + if ( p->pipe_user.ut.uid != sec_initial_uid() && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) { return NT_STATUS_ACCESS_DENIED; diff --git a/source/rpc_server/srv_pipe.c b/source/rpc_server/srv_pipe.c index 812a720d905..e2c5e865ed1 100644 --- a/source/rpc_server/srv_pipe.c +++ b/source/rpc_server/srv_pipe.c @@ -46,6 +46,11 @@ static void free_pipe_ntlmssp_auth_data(struct pipe_auth_data *auth) auth->a_u.auth_ntlmssp_state = NULL; } +static DATA_BLOB generic_session_key(void) +{ + return data_blob("SystemLibraryDTC", 16); +} + /******************************************************************* Generate the next PDU to be returned from the data in p->rdata. Handle NTLMSSP. @@ -610,16 +615,6 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) ZERO_STRUCT(reply); - memset(p->user_name, '\0', sizeof(p->user_name)); - memset(p->pipe_user_name, '\0', sizeof(p->pipe_user_name)); - memset(p->domain, '\0', sizeof(p->domain)); - memset(p->wks, '\0', sizeof(p->wks)); - - /* Set up for non-authenticated user. */ - TALLOC_FREE(p->pipe_user.nt_user_token); - p->pipe_user.ut.ngroups = 0; - SAFE_FREE( p->pipe_user.ut.groups); - /* this has to be done as root in order to verify the password */ become_root(); status = auth_ntlmssp_update(a, *p_resp_blob, &reply); @@ -632,6 +627,12 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) return False; } + if (a->server_info->ptok == NULL) { + DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n")); + p->pipe_user.nt_user_token = NULL; + return False; + } + /* Finally - if the pipe negotiated integrity (sign) or privacy (seal) ensure the underlying NTLMSSP flags are also set. If not we should refuse the bind. */ @@ -653,13 +654,9 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) } } - fstrcpy(p->user_name, a->ntlmssp_state->user); - fstrcpy(p->pipe_user_name, a->server_info->unix_name); - fstrcpy(p->domain, a->ntlmssp_state->domain); - fstrcpy(p->wks, a->ntlmssp_state->workstation); - DEBUG(5,("pipe_ntlmssp_verify_final: OK: user: %s domain: %s workstation: %s\n", - p->user_name, p->domain, p->wks)); + a->ntlmssp_state->user, a->ntlmssp_state->domain, + a->ntlmssp_state->workstation)); /* * Store the UNIX credential data (uid/gid pair) in the pipe structure. @@ -669,11 +666,13 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) p->pipe_user.ut.gid = a->server_info->gid; /* - * Copy the session key from the ntlmssp state. + * We're an authenticated bind over smb, so the session key needs to + * be set to "SystemLibraryDTC". Weird, but this is what Windows + * does. See the RPC-SAMBA3SESSIONKEY. */ data_blob_free(&p->session_key); - p->session_key = data_blob(a->ntlmssp_state->session_key.data, a->ntlmssp_state->session_key.length); + p->session_key = generic_session_key(); if (!p->session_key.data) { return False; } @@ -688,23 +687,21 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) } } - if (a->server_info->ptok) { - p->pipe_user.nt_user_token = - dup_nt_token(NULL, a->server_info->ptok); - if (!p->pipe_user.nt_user_token) { - DEBUG(1,("pipe_ntlmssp_verify_final: dup_nt_token failed.\n")); - data_blob_free(&p->session_key); - SAFE_FREE(p->pipe_user.ut.groups); - return False; - } - - } else { + if (!a->server_info->ptok) { DEBUG(1,("pipe_ntlmssp_verify_final: Error: Authmodule failed to provide nt_user_token\n")); data_blob_free(&p->session_key); SAFE_FREE(p->pipe_user.ut.groups); return False; } + p->pipe_user.nt_user_token = dup_nt_token(NULL, a->server_info->ptok); + if (!p->pipe_user.nt_user_token) { + DEBUG(1,("pipe_ntlmssp_verify_final: dup_nt_token failed.\n")); + data_blob_free(&p->session_key); + SAFE_FREE(p->pipe_user.ut.groups); + return False; + } + return True; } @@ -1361,8 +1358,21 @@ static BOOL pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, * JRA. Should we also copy the schannel session key into the pipe session key p->session_key * here ? We do that for NTLMSSP, but the session key is already set up from the vuser * struct of the person who opened the pipe. I need to test this further. JRA. + * + * VL. As we are mapping this to guest set the generic key + * "SystemLibraryDTC" key here. It's a bit difficult to test against + * W2k3, as it does not allow schannel binds against SAMR and LSA + * anymore. */ + data_blob_free(&p->session_key); + p->session_key = generic_session_key(); + if (p->session_key.data == NULL) { + DEBUG(0, ("pipe_schannel_auth_bind: Could not alloc session" + " key\n")); + return False; + } + init_rpc_hdr_auth(&auth_info, RPC_SCHANNEL_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1); if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) { DEBUG(0,("pipe_schannel_auth_bind: marshalling of RPC_HDR_AUTH failed.\n")); @@ -1391,6 +1401,12 @@ static BOOL pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, p->auth.auth_data_free_func = NULL; p->auth.auth_type = PIPE_AUTH_TYPE_SCHANNEL; + if (!set_current_user_guest(&p->pipe_user)) { + DEBUG(1, ("pipe_schannel_auth_bind: Could not set guest " + "token\n")); + return False; + } + p->pipe_bound = True; return True; @@ -1641,11 +1657,18 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) case RPC_ANONYMOUS_AUTH_TYPE: /* Unauthenticated bind request. */ + /* Get the authenticated pipe user from current_user */ + if (!copy_current_user(&p->pipe_user, ¤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: @@ -2149,23 +2172,6 @@ BOOL api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss } /**************************************************************************** - Return a user struct for a pipe user. -****************************************************************************/ - -struct current_user *get_current_user(struct current_user *user, pipes_struct *p) -{ - if (p->pipe_bound && - (p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP || - (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) { - memcpy(user, &p->pipe_user, sizeof(struct current_user)); - } else { - memcpy(user, ¤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/source/rpc_server/srv_pipe_hnd.c b/source/rpc_server/srv_pipe_hnd.c index 9cc8b72546f..8aa5bb3e6d1 100644 --- a/source/rpc_server/srv_pipe_hnd.c +++ b/source/rpc_server/srv_pipe_hnd.c @@ -351,8 +351,6 @@ static void *make_internal_rpc_pipe_p(char *pipe_name, /* Store the session key and NT_TOKEN */ if (vuser) { p->session_key = data_blob(vuser->session_key.data, vuser->session_key.length); - p->pipe_user.nt_user_token = dup_nt_token( - NULL, vuser->nt_user_token); } /* @@ -1169,6 +1167,13 @@ BOOL close_rpc_pipe_hnd(smb_np_struct *p) p->name, p->pnum, pipes_open)); DLIST_REMOVE(Pipes, p); + + /* TODO: Remove from pipe open db */ + + if ( !delete_pipe_opendb( p ) ) { + DEBUG(3,("close_rpc_pipe_hnd: failed to delete %s " + "pipe from open db.\n", p->name)); + } ZERO_STRUCTP(p); diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c index e045de56396..2e0b355db5f 100644 --- a/source/rpc_server/srv_samr_nt.c +++ b/source/rpc_server/srv_samr_nt.c @@ -1435,7 +1435,7 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO } } - init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, (uint32 *)type, r_u->status); + init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, type, r_u->status); DEBUG(5,("_samr_lookup_names: %d\n", __LINE__)); @@ -2508,7 +2508,8 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, } DEBUG(5, ("_samr_create_user: %s can add this account : %s\n", - p->pipe_user_name, can_add_account ? "True":"False" )); + uidtoname(p->pipe_user.ut.uid), + can_add_account ? "True":"False" )); /********** BEGIN Admin BLOCK **********/ @@ -3110,9 +3111,11 @@ static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21, } /* we need to separately check for an account rename first */ + if (rpcstr_pull(new_name, id21->uni_user_name.buffer, - sizeof(new_name), id21->uni_user_name.uni_str_len*2, 0) && - (!strequal(new_name, pdb_get_username(pwd)))) { + sizeof(new_name), id21->uni_user_name.uni_str_len*2, 0) + && (!strequal(new_name, pdb_get_username(pwd)))) + { /* check to see if the new username already exists. Note: we can't reliably lock all backends, so there is potentially the @@ -3435,7 +3438,8 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE } DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n", - p->pipe_user_name, has_enough_rights ? "" : " not")); + uidtoname(p->pipe_user.ut.uid), + has_enough_rights ? "" : " not")); /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */ @@ -3593,7 +3597,8 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_ } DEBUG(5, ("_samr_set_userinfo2: %s does%s possess sufficient rights\n", - p->pipe_user_name, has_enough_rights ? "" : " not")); + uidtoname(p->pipe_user.ut.uid), + has_enough_rights ? "" : " not")); /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */ diff --git a/source/rpc_server/srv_samr_util.c b/source/rpc_server/srv_samr_util.c index 2b65eb210fd..c4bec79c9cb 100644 --- a/source/rpc_server/srv_samr_util.c +++ b/source/rpc_server/srv_samr_util.c @@ -195,14 +195,13 @@ void copy_id21_to_sam_passwd(struct samu *to, SAM_USER_INFO_21 *from) pdb_set_workstations(to , new_string, PDB_CHANGED); } - /* is this right? */ - if ((from->fields_present & ACCT_ADMIN_DESC) && - (from->hdr_unknown_str.buffer)) { - old_string = pdb_get_unknown_str(to); - new_string = unistr2_static(&from->uni_unknown_str); - DEBUG(10,("INFO_21 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string)); + if ((from->fields_present & ACCT_COMMENT) && + (from->hdr_comment.buffer)) { + old_string = pdb_get_comment(to); + new_string = unistr2_static(&from->uni_comment); + DEBUG(10,("INFO_21 UNI_COMMENT: %s -> %s\n",old_string, new_string)); if (STRING_CHANGED) - pdb_set_unknown_str(to , new_string, PDB_CHANGED); + pdb_set_comment(to, new_string, PDB_CHANGED); } if ((from->fields_present & ACCT_CALLBACK) && @@ -445,14 +444,13 @@ void copy_id23_to_sam_passwd(struct samu *to, SAM_USER_INFO_23 *from) pdb_set_workstations(to , new_string, PDB_CHANGED); } - /* is this right? */ - if ((from->fields_present & ACCT_ADMIN_DESC) && - (from->hdr_unknown_str.buffer)) { - old_string = pdb_get_unknown_str(to); - new_string = unistr2_static(&from->uni_unknown_str); + if ((from->fields_present & ACCT_COMMENT) && + (from->hdr_comment.buffer)) { + old_string = pdb_get_comment(to); + new_string = unistr2_static(&from->uni_comment); DEBUG(10,("INFO_23 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string)); if (STRING_CHANGED) - pdb_set_unknown_str(to , new_string, PDB_CHANGED); + pdb_set_comment(to , new_string, PDB_CHANGED); } if ((from->fields_present & ACCT_CALLBACK) && @@ -683,14 +681,13 @@ void copy_id25_to_sam_passwd(struct samu *to, SAM_USER_INFO_25 *from) pdb_set_workstations(to , new_string, PDB_CHANGED); } - /* is this right? */ - if ((from->fields_present & ACCT_ADMIN_DESC) && - (from->hdr_unknown_str.buffer)) { - old_string = pdb_get_unknown_str(to); - new_string = unistr2_static(&from->uni_unknown_str); + if ((from->fields_present & ACCT_COMMENT) && + (from->hdr_comment.buffer)) { + old_string = pdb_get_comment(to); + new_string = unistr2_static(&from->uni_comment); DEBUG(10,("INFO_25 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string)); if (STRING_CHANGED) - pdb_set_unknown_str(to , new_string, PDB_CHANGED); + pdb_set_comment(to , new_string, PDB_CHANGED); } if ((from->fields_present & ACCT_CALLBACK) && diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c index 0281e3da0ca..3dbad208cc8 100644 --- a/source/rpc_server/srv_spoolss_nt.c +++ b/source/rpc_server/srv_spoolss_nt.c @@ -331,7 +331,7 @@ WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename ) /* go ahead and re-read the services immediately */ reload_services( False ); - if ( lp_servicenumber( sharename ) < 0 ) + if ( !share_defined( sharename ) ) return WERR_ACCESS_DENIED; return WERR_OK; @@ -1509,7 +1509,6 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, fstring name; int snum; - struct current_user user; Printer_entry *Printer=NULL; if ( !q_u->printername ) @@ -1533,8 +1532,6 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, return WERR_INVALID_PRINTER_NAME; } - get_current_user(&user, p); - /* * First case: the user is opening the print server: * @@ -1599,12 +1596,12 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege, and not a printer admin, then fail */ - if ((user.ut.uid != 0) && - !user_has_privileges(user.nt_user_token, + if ((p->pipe_user.ut.uid != 0) && + !user_has_privileges(p->pipe_user.nt_user_token, &se_printop ) && !token_contains_name_in_list( - uidtoname(user.ut.uid), NULL, - user.nt_user_token, + uidtoname(p->pipe_user.ut.uid), NULL, + p->pipe_user.nt_user_token, lp_printer_admin(snum))) { close_printer_handle(p, handle); return WERR_ACCESS_DENIED; @@ -1657,9 +1654,9 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, return WERR_ACCESS_DENIED; } - if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token, - snum) || - !print_access_check(&user, snum, + if (!user_ok_token(uidtoname(p->pipe_user.ut.uid), + p->pipe_user.nt_user_token, snum) || + !print_access_check(&p->pipe_user, snum, printer_default->access_required)) { DEBUG(3, ("access DENIED for printer open\n")); close_printer_handle(p, handle); @@ -1953,20 +1950,17 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER NT_PRINTER_DRIVER_INFO_LEVEL info; NT_PRINTER_DRIVER_INFO_LEVEL info_win2k; int version; - struct current_user user; WERROR status; WERROR status_win2k = WERR_ACCESS_DENIED; SE_PRIV se_printop = SE_PRINT_OPERATOR; - get_current_user(&user, p); - /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege, and not a printer admin, then fail */ - if ( (user.ut.uid != 0) - && !user_has_privileges(user.nt_user_token, &se_printop ) - && !token_contains_name_in_list( uidtoname(user.ut.uid), - NULL, user.nt_user_token, lp_printer_admin(-1)) ) + if ( (p->pipe_user.ut.uid != 0) + && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop ) + && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid), + NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) ) { return WERR_ACCESS_DENIED; } @@ -2013,7 +2007,7 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER /* if we get to here, we now have 2 driver info structures to remove */ /* remove the Win2k driver first*/ - status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False ); + status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False ); free_a_printer_driver( info_win2k, 3 ); /* this should not have failed---if it did, report to client */ @@ -2025,7 +2019,7 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER } } - status = delete_printer_driver(info.info_3, &user, version, False); + status = delete_printer_driver(info.info_3, &p->pipe_user, version, False); /* if at least one of the deletes succeeded return OK */ @@ -2051,20 +2045,17 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV int version; uint32 flags = q_u->delete_flags; BOOL delete_files; - struct current_user user; WERROR status; WERROR status_win2k = WERR_ACCESS_DENIED; SE_PRIV se_printop = SE_PRINT_OPERATOR; - get_current_user(&user, p); - /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege, and not a printer admin, then fail */ - if ( (user.ut.uid != 0) - && !user_has_privileges(user.nt_user_token, &se_printop ) - && !token_contains_name_in_list( uidtoname(user.ut.uid), - NULL, user.nt_user_token, lp_printer_admin(-1)) ) + if ( (p->pipe_user.ut.uid != 0) + && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop ) + && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid), + NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) ) { return WERR_ACCESS_DENIED; } @@ -2150,7 +2141,7 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV /* if we get to here, we now have 2 driver info structures to remove */ /* remove the Win2k driver first*/ - status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files); + status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files); free_a_printer_driver( info_win2k, 3 ); /* this should not have failed---if it did, report to client */ @@ -2160,7 +2151,7 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV } } - status = delete_printer_driver(info.info_3, &user, version, delete_files); + status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files); if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) ) status = WERR_OK; @@ -4073,7 +4064,7 @@ static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode Create a DEVMODE struct. Returns malloced memory. ****************************************************************************/ -DEVICEMODE *construct_dev_mode(int snum) +DEVICEMODE *construct_dev_mode(const char *servicename) { NT_PRINTER_INFO_LEVEL *printer = NULL; DEVICEMODE *devmode = NULL; @@ -4082,7 +4073,7 @@ DEVICEMODE *construct_dev_mode(int snum) DEBUGADD(8,("getting printer characteristics\n")); - if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum)))) + if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename))) return NULL; if ( !printer->info_2->devmode ) { @@ -4154,7 +4145,7 @@ static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *p printer->cjobs = count; /* jobs */ printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */ - if ( !(printer->devmode = construct_dev_mode(snum)) ) + if ( !(printer->devmode = construct_dev_mode(lp_const_servicename(snum))) ) DEBUG(8, ("Returning NULL Devicemode!\n")); printer->secdesc = NULL; @@ -5640,15 +5631,12 @@ WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, S pstring jobname; fstring datatype; Printer_entry *Printer = find_printer_index_by_hnd(p, handle); - struct current_user user; if (!Printer) { DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle))); return WERR_BADFID; } - get_current_user(&user, p); - /* * a nice thing with NT is it doesn't listen to what you tell it. * when asked to send _only_ RAW datas, it tries to send datas @@ -5672,7 +5660,7 @@ WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, S unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname)); - Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode); + Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode); /* An error occured in print_job_start() so return an appropriate NT error code. */ @@ -5745,13 +5733,10 @@ WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R static WERROR control_printer(POLICY_HND *handle, uint32 command, pipes_struct *p) { - struct current_user user; int snum; WERROR errcode = WERR_BADFUNC; Printer_entry *Printer = find_printer_index_by_hnd(p, handle); - get_current_user(&user, p); - if (!Printer) { DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle))); return WERR_BADFID; @@ -5762,18 +5747,18 @@ static WERROR control_printer(POLICY_HND *handle, uint32 command, switch (command) { case PRINTER_CONTROL_PAUSE: - if (print_queue_pause(&user, snum, &errcode)) { + if (print_queue_pause(&p->pipe_user, snum, &errcode)) { errcode = WERR_OK; } break; case PRINTER_CONTROL_RESUME: case PRINTER_CONTROL_UNPAUSE: - if (print_queue_resume(&user, snum, &errcode)) { + if (print_queue_resume(&p->pipe_user, snum, &errcode)) { errcode = WERR_OK; } break; case PRINTER_CONTROL_PURGE: - if (print_queue_purge(&user, snum, &errcode)) { + if (print_queue_purge(&p->pipe_user, snum, &errcode)) { errcode = WERR_OK; } break; @@ -5795,7 +5780,6 @@ WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R POLICY_HND *handle = &q_u->handle; Printer_entry *Printer = find_printer_index_by_hnd(p, handle); int snum; - struct current_user user; WERROR errcode = WERR_OK; if (!Printer) { @@ -5806,9 +5790,7 @@ WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R if (!get_printer_snum(p, handle, &snum)) return WERR_BADFID; - get_current_user( &user, p ); - - print_job_delete( &user, snum, Printer->jobid, &errcode ); + print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode ); return errcode; } @@ -6018,7 +6000,9 @@ BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer) SE_PRIV se_printop = SE_PRINT_OPERATOR; BOOL is_print_op = False; - standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine)); + standard_sub_basic(current_user_info.smb_name, + current_user_info.domain, + remote_machine,sizeof(remote_machine)); slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"", cmd, printer->info_2->printername, printer->info_2->sharename, @@ -6544,7 +6528,7 @@ static WERROR enumjobs_level2(print_queue_struct *queue, int snum, /* this should not be a failure condition if the devmode is NULL */ - devmode = construct_dev_mode(snum); + devmode = construct_dev_mode(lp_const_servicename(snum)); for (i=0; i<*returned; i++) fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode); @@ -6664,7 +6648,6 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u uint32 jobid = q_u->jobid; uint32 command = q_u->command; - struct current_user user; int snum; WERROR errcode = WERR_BADFUNC; @@ -6676,23 +6659,21 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u return WERR_INVALID_PRINTER_NAME; } - get_current_user(&user, p); - switch (command) { case JOB_CONTROL_CANCEL: case JOB_CONTROL_DELETE: - if (print_job_delete(&user, snum, jobid, &errcode)) { + if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) { errcode = WERR_OK; } break; case JOB_CONTROL_PAUSE: - if (print_job_pause(&user, snum, jobid, &errcode)) { + if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) { errcode = WERR_OK; } break; case JOB_CONTROL_RESTART: case JOB_CONTROL_RESUME: - if (print_job_resume(&user, snum, jobid, &errcode)) { + if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) { errcode = WERR_OK; } break; @@ -7618,26 +7599,23 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info; WERROR err = WERR_OK; NT_PRINTER_DRIVER_INFO_LEVEL driver; - struct current_user user; fstring driver_name; uint32 version; ZERO_STRUCT(driver); - get_current_user(&user, p); - if (!convert_printer_driver_info(info, &driver, level)) { err = WERR_NOMEM; goto done; } DEBUG(5,("Cleaning driver's information\n")); - err = clean_up_driver_struct(driver, level, &user); + err = clean_up_driver_struct(driver, level, &p->pipe_user); if (!W_ERROR_IS_OK(err)) goto done; DEBUG(5,("Moving driver to final destination\n")); - if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) { + if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) { goto done; } @@ -8777,7 +8755,7 @@ static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, */ if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) ) - devmode = construct_dev_mode(snum); + devmode = construct_dev_mode(lp_const_servicename(snum)); else { if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) { ZERO_STRUCTP( devmode ); diff --git a/source/rpc_server/srv_srvsvc.c b/source/rpc_server/srv_srvsvc.c index 0b4eac5cc73..e4f85d0bdb4 100644 --- a/source/rpc_server/srv_srvsvc.c +++ b/source/rpc_server/srv_srvsvc.c @@ -6,6 +6,7 @@ * Copyright (C) Paul Ashton 1997, * Copyright (C) Jeremy Allison 2001, * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003. + * Copyright (C) Gera;d (Jerry) Carter 2006. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -551,6 +552,35 @@ static BOOL api_srv_net_file_set_secdesc(pipes_struct *p) } /******************************************************************* +*******************************************************************/ + +static BOOL api_srv_net_file_close(pipes_struct *p) +{ + SRV_Q_NET_FILE_CLOSE q_u; + SRV_R_NET_FILE_CLOSE r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + /* Unmarshall the net file set info from Win9x */ + if(!srv_io_q_net_file_close("", &q_u, data, 0)) { + DEBUG(0,("api_srv_net_file_close: Failed to unmarshall SRV_Q_NET_FILE_SET_SECDESC.\n")); + return False; + } + + r_u.status = _srv_net_file_close(p, &q_u, &r_u); + + if(!srv_io_r_net_file_close("", &r_u, rdata, 0)) { + DEBUG(0,("api_srv_net_file_close: Failed to marshall SRV_R_NET_FILE_SET_SECDESC.\n")); + return False; + } + + return True; +} + +/******************************************************************* \PIPE\srvsvc commands ********************************************************************/ @@ -573,7 +603,8 @@ static struct api_struct api_srv_cmds[] = { "SRV_NET_DISK_ENUM" , SRV_NET_DISK_ENUM , api_srv_net_disk_enum }, { "SRV_NET_NAME_VALIDATE" , SRV_NET_NAME_VALIDATE , api_srv_net_name_validate }, { "SRV_NET_FILE_QUERY_SECDESC", SRV_NET_FILE_QUERY_SECDESC, api_srv_net_file_query_secdesc }, - { "SRV_NET_FILE_SET_SECDESC" , SRV_NET_FILE_SET_SECDESC , api_srv_net_file_set_secdesc } + { "SRV_NET_FILE_SET_SECDESC" , SRV_NET_FILE_SET_SECDESC , api_srv_net_file_set_secdesc }, + { "SRV_NET_FILE_CLOSE" , SRV_NET_FILE_CLOSE , api_srv_net_file_close } }; void srvsvc_get_pipe_fns( struct api_struct **fns, int *n_fns ) diff --git a/source/rpc_server/srv_srvsvc_nt.c b/source/rpc_server/srv_srvsvc_nt.c index a936ef58709..12a86ce9f33 100644 --- a/source/rpc_server/srv_srvsvc_nt.c +++ b/source/rpc_server/srv_srvsvc_nt.c @@ -4,6 +4,7 @@ * Copyright (C) Andrew Tridgell 1992-1997, * Copyright (C) Jeremy Allison 2001. * Copyright (C) Nigel Williams 2001. + * Copyright (C) Gerald (Jerry) Carter 2006. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,10 +26,179 @@ #include "includes.h" extern struct generic_mapping file_generic_mapping; +extern userdom_struct current_user_info; #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV +/* Use for enumerating connections, pipes, & files */ + +struct file_enum_count { + TALLOC_CTX *ctx; + int count; + FILE_INFO_3 *info; +}; + +struct sess_file_count { + pid_t pid; + uid_t uid; + int count; +}; + +/**************************************************************************** + Count the entries belonging to a service in the connection db. +****************************************************************************/ + +static int pipe_enum_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *p) +{ + struct pipe_open_rec prec; + struct file_enum_count *fenum = (struct file_enum_count *)p; + + if (dbuf.dsize != sizeof(struct pipe_open_rec)) + return 0; + + memcpy(&prec, dbuf.dptr, sizeof(struct pipe_open_rec)); + + if ( process_exists(prec.pid) ) { + FILE_INFO_3 *f; + int i = fenum->count; + pstring fullpath; + + snprintf( fullpath, sizeof(fullpath), "\\PIPE\\%s", prec.name ); + + f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, FILE_INFO_3, i+1 ); + if ( !f ) { + DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1)); + return 1; + } + fenum->info = f; + + + init_srv_file_info3( &fenum->info[i], + (uint32)((procid_to_pid(&prec.pid)<<16) & prec.pnum), + (FILE_READ_DATA|FILE_WRITE_DATA), + 0, + uidtoname( prec.uid ), + fullpath ); + + fenum->count++; + } + + return 0; +} + +/******************************************************************* +********************************************************************/ + +static WERROR net_enum_pipes( TALLOC_CTX *ctx, FILE_INFO_3 **info, + uint32 *count, uint32 resume ) +{ + struct file_enum_count fenum; + TDB_CONTEXT *conn_tdb = conn_tdb_ctx(); + + if ( !conn_tdb ) { + DEBUG(0,("net_enum_pipes: Failed to retrieve the connections tdb handle!\n")); + return WERR_ACCESS_DENIED; + } + + fenum.ctx = ctx; + fenum.count = *count; + fenum.info = *info; + + if (tdb_traverse(conn_tdb, pipe_enum_fn, &fenum) == -1) { + DEBUG(0,("net_enum_pipes: traverse of connections.tdb failed with error %s.\n", + tdb_errorstr(conn_tdb) )); + return WERR_NOMEM; + } + + *info = fenum.info; + *count = fenum.count; + + return WERR_OK;} + +/******************************************************************* +********************************************************************/ + +/* global needed to make use of the share_mode_forall() callback */ +static struct file_enum_count f_enum_cnt; + +static void enum_file_fn( const struct share_mode_entry *e, + const char *sharepath, const char *fname ) +{ + struct file_enum_count *fenum = &f_enum_cnt; + + /* If the pid was not found delete the entry from connections.tdb */ + + if ( process_exists(e->pid) ) { + FILE_INFO_3 *f; + int i = fenum->count; + files_struct fsp; + struct byte_range_lock *brl; + int num_locks = 0; + pstring fullpath; + uint32 permissions; + + f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, FILE_INFO_3, i+1 ); + if ( !f ) { + DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1)); + return; + } + fenum->info = f; + + /* need to count the number of locks on a file */ + + ZERO_STRUCT( fsp ); + fsp.dev = e->dev; + fsp.inode = e->inode; + + if ( (brl = brl_get_locks(NULL,&fsp)) != NULL ) { + num_locks = brl->num_locks; + TALLOC_FREE( brl ); + } + + if ( strcmp( fname, "." ) == 0 ) { + pstr_sprintf( fullpath, "C:%s", sharepath ); + } else { + pstr_sprintf( fullpath, "C:%s/%s", sharepath, fname ); + } + string_replace( fullpath, '/', '\\' ); + + /* mask out create (what ever that is) */ + permissions = e->share_access & (FILE_READ_DATA|FILE_WRITE_DATA); + + /* now fill in the FILE_INFO_3 struct */ + init_srv_file_info3( &fenum->info[i], + e->share_file_id, + permissions, + num_locks, + uidtoname(e->uid), + fullpath ); + + fenum->count++; + } + + return; + +} + +/******************************************************************* +********************************************************************/ + +static WERROR net_enum_files( TALLOC_CTX *ctx, FILE_INFO_3 **info, + uint32 *count, uint32 resume ) +{ + f_enum_cnt.ctx = ctx; + f_enum_cnt.count = *count; + f_enum_cnt.info = *info; + + share_mode_forall( enum_file_fn ); + + *info = f_enum_cnt.info; + *count = f_enum_cnt.count; + + return WERR_OK; +} + /******************************************************************* Utility function to get the 'type' of a share from an snum. ********************************************************************/ @@ -70,11 +240,16 @@ static void init_srv_share_info_0(pipes_struct *p, SRV_SHARE_INFO_0 *sh0, int sn static void init_srv_share_info_1(pipes_struct *p, SRV_SHARE_INFO_1 *sh1, int snum) { + connection_struct *conn = p->conn; pstring remark; char *net_name = lp_servicename(snum); pstrcpy(remark, lp_comment(snum)); - standard_sub_conn(p->conn, remark,sizeof(remark)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + remark, sizeof(remark)); init_srv_share_info1(&sh1->info_1, net_name, get_share_type(snum), remark); init_srv_share_info1_str(&sh1->info_1_str, net_name, remark); @@ -86,15 +261,21 @@ static void init_srv_share_info_1(pipes_struct *p, SRV_SHARE_INFO_1 *sh1, int sn static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int snum) { + connection_struct *conn = p->conn; pstring remark; pstring path; pstring passwd; int max_connections = lp_max_connections(snum); uint32 max_uses = max_connections!=0 ? max_connections : 0xffffffff; - + int count = 0; char *net_name = lp_servicename(snum); + pstrcpy(remark, lp_comment(snum)); - standard_sub_conn(p->conn, remark,sizeof(remark)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + remark, sizeof(remark)); pstrcpy(path, "C:"); pstrcat(path, lp_pathname(snum)); @@ -107,7 +288,10 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn pstrcpy(passwd, ""); - init_srv_share_info2(&sh2->info_2, net_name, get_share_type(snum), remark, 0, max_uses, 1, path, passwd); + count = count_current_connections( net_name, False ); + init_srv_share_info2(&sh2->info_2, net_name, get_share_type(snum), + remark, 0, max_uses, count, path, passwd); + init_srv_share_info2_str(&sh2->info_2_str, net_name, remark, path, passwd); } @@ -179,11 +363,16 @@ out: static void init_srv_share_info_501(pipes_struct *p, SRV_SHARE_INFO_501 *sh501, int snum) { + connection_struct *conn = p->conn; pstring remark; const char *net_name = lp_servicename(snum); pstrcpy(remark, lp_comment(snum)); - standard_sub_conn(p->conn, remark, sizeof(remark)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + remark, sizeof(remark)); init_srv_share_info501(&sh501->info_501, net_name, get_share_type(snum), remark, (lp_csc_policy(snum) << 4)); init_srv_share_info501_str(&sh501->info_501_str, net_name, remark); @@ -195,6 +384,7 @@ static void init_srv_share_info_501(pipes_struct *p, SRV_SHARE_INFO_501 *sh501, static void init_srv_share_info_502(pipes_struct *p, SRV_SHARE_INFO_502 *sh502, int snum) { + connection_struct *conn = p->conn; pstring net_name; pstring remark; pstring path; @@ -208,7 +398,11 @@ static void init_srv_share_info_502(pipes_struct *p, SRV_SHARE_INFO_502 *sh502, pstrcpy(net_name, lp_servicename(snum)); pstrcpy(remark, lp_comment(snum)); - standard_sub_conn(p->conn, remark,sizeof(remark)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + remark, sizeof(remark)); pstrcpy(path, "C:"); pstrcat(path, lp_pathname(snum)); @@ -233,10 +427,15 @@ static void init_srv_share_info_502(pipes_struct *p, SRV_SHARE_INFO_502 *sh502, static void init_srv_share_info_1004(pipes_struct *p, SRV_SHARE_INFO_1004* sh1004, int snum) { + connection_struct *conn = p->conn; pstring remark; pstrcpy(remark, lp_comment(snum)); - standard_sub_conn(p->conn, remark, sizeof(remark)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + remark, sizeof(remark)); ZERO_STRUCTP(sh1004); @@ -633,16 +832,6 @@ static void init_srv_r_net_share_get_info(pipes_struct *p, SRV_R_NET_SHARE_GET_I } /******************************************************************* - fill in a sess info level 1 structure. - ********************************************************************/ - -static void init_srv_sess_0_info(SESS_INFO_0 *se0, SESS_INFO_0_STR *str0, char *name) -{ - init_srv_sess_info0(se0, name); - init_srv_sess_info0_str(str0, name); -} - -/******************************************************************* fill in a sess info level 0 structure. ********************************************************************/ @@ -662,11 +851,7 @@ static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto if (snum) { for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) { - init_srv_sess_0_info(&ss0->info_0[num_entries], - &ss0->info_0_str[num_entries], session_list[(*snum)].remote_machine); - - /* move on to creating next session */ - /* move on to creating next sess */ + init_srv_sess_info0( &ss0->info_0[num_entries], session_list[(*snum)].remote_machine); num_entries++; } @@ -687,17 +872,35 @@ static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto } /******************************************************************* - fill in a sess info level 1 structure. - ********************************************************************/ +********************************************************************/ -static void init_srv_sess_1_info(SESS_INFO_1 *se1, SESS_INFO_1_STR *str1, - char *name, char *user, - uint32 num_opens, - uint32 open_time, uint32 idle_time, - uint32 usr_flgs) +/* global needed to make use of the share_mode_forall() callback */ +static struct sess_file_count s_file_cnt; + +static void sess_file_fn( const struct share_mode_entry *e, + const char *sharepath, const char *fname ) { - init_srv_sess_info1(se1 , name, user, num_opens, open_time, idle_time, usr_flgs); - init_srv_sess_info1_str(str1, name, user); + struct sess_file_count *sess = &s_file_cnt; + + if ( (procid_to_pid(&e->pid) == sess->pid) && (sess->uid == e->uid) ) { + sess->count++; + } + + return; +} + +/******************************************************************* +********************************************************************/ + +static int net_count_files( uid_t uid, pid_t pid ) +{ + s_file_cnt.count = 0; + s_file_cnt.uid = uid; + s_file_cnt.pid = pid; + + share_mode_forall( sess_file_fn ); + + return s_file_cnt.count; } /******************************************************************* @@ -708,43 +911,58 @@ static void init_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *sto { struct sessionid *session_list; uint32 num_entries = 0; - (*stot) = list_sessions(&session_list); + time_t now = time(NULL); + if ( !snum ) { + ss1->num_entries_read = 0; + ss1->ptr_sess_info = 0; + ss1->num_entries_read2 = 0; + + (*stot) = 0; + + return; + } + if (ss1 == NULL) { (*snum) = 0; - SAFE_FREE(session_list); return; } - DEBUG(5,("init_srv_sess_1_ss1\n")); - - if (snum) { - for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) { - init_srv_sess_1_info(&ss1->info_1[num_entries], - &ss1->info_1_str[num_entries], - session_list[*snum].remote_machine, - session_list[*snum].username, - 1, 10, 5, 0); - - /* move on to creating next session */ - /* move on to creating next sess */ - num_entries++; - } + (*stot) = list_sessions(&session_list); + - ss1->num_entries_read = num_entries; - ss1->ptr_sess_info = num_entries > 0 ? 1 : 0; - ss1->num_entries_read2 = num_entries; - - if ((*snum) >= (*stot)) { - (*snum) = 0; + for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) { + uint32 num_files; + uint32 connect_time; + struct passwd *pw = sys_getpwnam(session_list[*snum].username); + BOOL guest; + + if ( !pw ) { + DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n", + session_list[*snum].username)); + continue; } - - } else { - ss1->num_entries_read = 0; - ss1->ptr_sess_info = 0; - ss1->num_entries_read2 = 0; - - (*stot) = 0; + + connect_time = (uint32)(now - session_list[*snum].connect_start); + num_files = net_count_files(pw->pw_uid, session_list[*snum].pid); + guest = strequal( session_list[*snum].username, lp_guestaccount() ); + + init_srv_sess_info1( &ss1->info_1[num_entries], + session_list[*snum].remote_machine, + session_list[*snum].username, + num_files, + connect_time, + 0, + guest); + num_entries++; + } + + ss1->num_entries_read = num_entries; + ss1->ptr_sess_info = num_entries > 0 ? 1 : 0; + ss1->num_entries_read2 = num_entries; + + if ((*snum) >= (*stot)) { + (*snum) = 0; } SAFE_FREE(session_list); @@ -964,66 +1182,53 @@ static void init_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n, makes a SRV_R_NET_FILE_ENUM structure. ********************************************************************/ -static WERROR init_srv_file_info_ctr(pipes_struct *p, SRV_FILE_INFO_CTR *ctr, - int switch_value, uint32 *resume_hnd, - uint32 *total_entries) +static WERROR net_file_enum_3( SRV_R_NET_FILE_ENUM *r, uint32 resume_hnd ) { - WERROR status = WERR_OK; - TALLOC_CTX *ctx = p->mem_ctx; - DEBUG(5,("init_srv_file_info_ctr: %d\n", __LINE__)); - *total_entries = 1; /* dummy entries only, for */ + TALLOC_CTX *ctx = get_talloc_ctx(); + SRV_FILE_INFO_CTR *ctr = &r->ctr; - ctr->switch_value = switch_value; - ctr->num_entries = *total_entries - *resume_hnd; + /* TODO -- Windows enumerates + (b) active pipes + (c) open directories and files */ + + r->status = net_enum_files( ctx, &ctr->file.info3, &ctr->num_entries, resume_hnd ); + if ( !W_ERROR_IS_OK(r->status)) + goto done; + + r->status = net_enum_pipes( ctx, &ctr->file.info3, &ctr->num_entries, resume_hnd ); + if ( !W_ERROR_IS_OK(r->status)) + goto done; + + r->level = ctr->level = 3; + r->total_entries = ctr->num_entries; + /* ctr->num_entries = r->total_entries - resume_hnd; */ ctr->num_entries2 = ctr->num_entries; + ctr->ptr_file_info = 1; - switch (switch_value) { - case 3: { - int i; - if (*total_entries > 0) { - ctr->ptr_entries = 1; - ctr->file.info3 = TALLOC_ARRAY(ctx, SRV_FILE_INFO_3, ctr->num_entries); - } - for (i=0 ;i<ctr->num_entries;i++) { - init_srv_file_info3(&ctr->file.info3[i].info_3, i+*resume_hnd, 0x35, 0, "\\PIPE\\samr", "dummy user"); - init_srv_file_info3_str(&ctr->file.info3[i].info_3_str, "\\PIPE\\samr", "dummy user"); - - } - ctr->ptr_file_info = 1; - *resume_hnd = 0; - break; - } - default: - DEBUG(5,("init_srv_file_info_ctr: unsupported switch value %d\n", switch_value)); - (*resume_hnd = 0); - (*total_entries) = 0; - ctr->ptr_entries = 0; - status = WERR_UNKNOWN_LEVEL; - break; - } + r->status = WERR_OK; - return status; +done: + if ( ctr->num_entries > 0 ) + ctr->ptr_entries = 1; + + init_enum_hnd(&r->enum_hnd, 0); + + return r->status; } /******************************************************************* - makes a SRV_R_NET_FILE_ENUM structure. -********************************************************************/ +*******************************************************************/ -static void init_srv_r_net_file_enum(pipes_struct *p, SRV_R_NET_FILE_ENUM *r_n, - uint32 resume_hnd, int file_level, int switch_value) +WERROR _srv_net_file_enum(pipes_struct *p, SRV_Q_NET_FILE_ENUM *q_u, SRV_R_NET_FILE_ENUM *r_u) { - DEBUG(5,("init_srv_r_net_file_enum: %d\n", __LINE__)); - - r_n->file_level = file_level; - if (file_level == 0) - r_n->status = WERR_UNKNOWN_LEVEL; - else - r_n->status = init_srv_file_info_ctr(p, &r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries)); - - if (!W_ERROR_IS_OK(r_n->status)) - resume_hnd = 0; - - init_enum_hnd(&r_n->enum_hnd, resume_hnd); + switch ( q_u->level ) { + case 3: + return net_file_enum_3( r_u, get_enum_hnd(&q_u->enum_hnd) ); + default: + return WERR_UNKNOWN_LEVEL; + } + + return WERR_OK; } /******************************************************************* @@ -1110,25 +1315,6 @@ WERROR _srv_net_srv_set_info(pipes_struct *p, SRV_Q_NET_SRV_SET_INFO *q_u, SRV_R } /******************************************************************* -net file enum -********************************************************************/ - -WERROR _srv_net_file_enum(pipes_struct *p, SRV_Q_NET_FILE_ENUM *q_u, SRV_R_NET_FILE_ENUM *r_u) -{ - DEBUG(5,("srv_net_file_enum: %d\n", __LINE__)); - - /* set up the */ - init_srv_r_net_file_enum(p, r_u, - get_enum_hnd(&q_u->enum_hnd), - q_u->file_level, - q_u->ctr.switch_value); - - DEBUG(5,("srv_net_file_enum: %d\n", __LINE__)); - - return r_u->status; -} - -/******************************************************************* net conn enum ********************************************************************/ @@ -1185,7 +1371,6 @@ net sess del WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SESS_DEL *r_u) { struct sessionid *session_list; - struct current_user user; int num_sessions, snum; fstring username; fstring machine; @@ -1205,11 +1390,9 @@ WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SES r_u->status = WERR_ACCESS_DENIED; - get_current_user(&user, p); - /* fail out now if you are not root or not a domain admin */ - if ((user.ut.uid != sec_initial_uid()) && + if ((p->pipe_user.ut.uid != sec_initial_uid()) && ( ! nt_token_check_domain_rid(p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS))) { goto done; @@ -1220,7 +1403,7 @@ WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SES if ((strequal(session_list[snum].username, username) || username[0] == '\0' ) && strequal(session_list[snum].remote_machine, machine)) { - if (user.ut.uid != sec_initial_uid()) { + if (p->pipe_user.ut.uid != sec_initial_uid()) { not_root = True; become_root(); } @@ -1337,7 +1520,6 @@ char *valid_share_pathname(char *dos_pathname) WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, SRV_R_NET_SHARE_SET_INFO *r_u) { - struct current_user user; pstring command; fstring share_name; fstring comment; @@ -1374,13 +1556,11 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S if (lp_print_ok(snum)) return WERR_ACCESS_DENIED; - get_current_user(&user,p); - is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop ); /* fail out now if you are not root and not a disk op */ - if ( user.ut.uid != sec_initial_uid() && !is_disk_op ) + if ( p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op ) return WERR_ACCESS_DENIED; switch (q_u->info_level) { @@ -1525,7 +1705,6 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_SHARE_ADD *r_u) { - struct current_user user; pstring command; fstring share_name; fstring comment; @@ -1543,11 +1722,9 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S r_u->parm_error = 0; - get_current_user(&user,p); - is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop ); - if (user.ut.uid != sec_initial_uid() && !is_disk_op ) + if (p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op ) return WERR_ACCESS_DENIED; if (!lp_add_share_cmd() || !*lp_add_share_cmd()) { @@ -1682,7 +1859,6 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_SHARE_DEL *r_u) { - struct current_user user; pstring command; fstring share_name; int ret; @@ -1710,11 +1886,9 @@ WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_S if (lp_print_ok(snum)) return WERR_ACCESS_DENIED; - get_current_user(&user,p); - is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop ); - if (user.ut.uid != sec_initial_uid() && !is_disk_op ) + if (p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op ) return WERR_ACCESS_DENIED; if (!lp_delete_share_cmd() || !*lp_delete_share_cmd()) { @@ -1826,7 +2000,6 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC SMB_STRUCT_STAT st; BOOL bad_path; NTSTATUS nt_status; - struct current_user user; connection_struct *conn = NULL; BOOL became_user = False; @@ -1839,10 +2012,8 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC /* Null password is ok - we are already an authenticated user... */ null_pw = data_blob(NULL, 0); - get_current_user(&user, p); - become_root(); - conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status); + conn = make_connection(qualname, null_pw, "A:", p->pipe_user.vuid, &nt_status); unbecome_root(); if (conn == NULL) { @@ -1872,18 +2043,18 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC goto error_exit; } - fsp = open_file_stat(conn, filename, &st); - if (!fsp) { + nt_status = open_file_stat(conn, filename, &st, &fsp); + if (!NT_STATUS_IS_OK(nt_status)) { /* Perhaps it is a directory */ - if (errno == EISDIR) - fsp = open_directory(conn, filename, &st, + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY)) + nt_status = open_directory(conn, filename, &st, READ_CONTROL_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, - NULL); + NULL, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", filename)); r_u->status = WERR_ACCESS_DENIED; goto error_exit; @@ -1908,7 +2079,7 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC close_file(fsp, NORMAL_CLOSE); unbecome_user(); - close_cnum(conn, user.vuid); + close_cnum(conn, p->pipe_user.vuid); return r_u->status; error_exit: @@ -1921,7 +2092,7 @@ error_exit: unbecome_user(); if (conn) - close_cnum(conn, user.vuid); + close_cnum(conn, p->pipe_user.vuid); return r_u->status; } @@ -1941,7 +2112,6 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ SMB_STRUCT_STAT st; BOOL bad_path; NTSTATUS nt_status; - struct current_user user; connection_struct *conn = NULL; BOOL became_user = False; @@ -1954,10 +2124,8 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ /* Null password is ok - we are already an authenticated user... */ null_pw = data_blob(NULL, 0); - get_current_user(&user, p); - become_root(); - conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status); + conn = make_connection(qualname, null_pw, "A:", p->pipe_user.vuid, &nt_status); unbecome_root(); if (conn == NULL) { @@ -1988,19 +2156,19 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ } - fsp = open_file_stat(conn, filename, &st); + nt_status = open_file_stat(conn, filename, &st, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(nt_status)) { /* Perhaps it is a directory */ - if (errno == EISDIR) - fsp = open_directory(conn, filename, &st, + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY)) + nt_status = open_directory(conn, filename, &st, FILE_READ_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, - NULL); + NULL, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", filename)); r_u->status = WERR_ACCESS_DENIED; goto error_exit; @@ -2017,7 +2185,7 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ close_file(fsp, NORMAL_CLOSE); unbecome_user(); - close_cnum(conn, user.vuid); + close_cnum(conn, p->pipe_user.vuid); return r_u->status; error_exit: @@ -2031,7 +2199,7 @@ error_exit: } if (conn) { - close_cnum(conn, user.vuid); + close_cnum(conn, p->pipe_user.vuid); } return r_u->status; @@ -2133,7 +2301,7 @@ WERROR _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV switch ( q_u->type ) { case 0x9: - rpcstr_pull(sharename, q_u->uni_name.buffer, sizeof(sharename), q_u->uni_name.uni_str_len*2, 0); + rpcstr_pull(sharename, q_u->sharename.buffer, sizeof(sharename), q_u->sharename.uni_str_len*2, 0); if ( !validate_net_name( sharename, INVALID_SHARENAME_CHARS, sizeof(sharename) ) ) { DEBUG(5,("_srv_net_name_validate: Bad sharename \"%s\"\n", sharename)); return WERR_INVALID_NAME; @@ -2146,3 +2314,13 @@ WERROR _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV return WERR_OK; } + + +/******************************************************************** +********************************************************************/ + +WERROR _srv_net_file_close(pipes_struct *p, SRV_Q_NET_FILE_CLOSE *q_u, SRV_R_NET_FILE_CLOSE *r_u) +{ + return WERR_ACCESS_DENIED; +} + diff --git a/source/rpc_server/srv_svcctl_nt.c b/source/rpc_server/srv_svcctl_nt.c index 6062dcee5ce..dd790691d36 100644 --- a/source/rpc_server/srv_svcctl_nt.c +++ b/source/rpc_server/srv_svcctl_nt.c @@ -624,7 +624,7 @@ static WERROR fill_svc_config( TALLOC_CTX *ctx, const char *name, SERVICE_CONFIG the client from showing the "Start" button (if of course the services are not running */ - if ( strequal( name, "NETLOGON" ) && ( lp_servicenumber(name) == -1 ) ) + if ( strequal( name, "NETLOGON" ) && ( !share_defined(name) ) ) config->start_type = SVCCTL_DISABLED; else if ( strequal( name, "WINS" ) && ( !lp_wins_support() )) config->start_type = SVCCTL_DISABLED; diff --git a/source/rpc_server/srv_unixinfo.c b/source/rpc_server/srv_unixinfo.c new file mode 100644 index 00000000000..f21416dfabe --- /dev/null +++ b/source/rpc_server/srv_unixinfo.c @@ -0,0 +1,163 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines for unixinfo-pipe + * Copyright (C) Volker Lendecke 2005 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This is the interface to the rpcunixinfo pipe. */ + +#include "includes.h" +#include "nterr.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +static BOOL api_sid_to_uid(pipes_struct *p) +{ + UNIXINFO_Q_SID_TO_UID q_u; + UNIXINFO_R_SID_TO_UID r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if (!unixinfo_io_q_unixinfo_sid_to_uid("", &q_u, data, 0)) + return False; + + r_u.status = _unixinfo_sid_to_uid(p, &q_u, &r_u); + + if (!unixinfo_io_r_unixinfo_sid_to_uid("", &r_u, rdata, 0)) + return False; + + return True; +} + +static BOOL api_uid_to_sid(pipes_struct *p) +{ + UNIXINFO_Q_UID_TO_SID q_u; + UNIXINFO_R_UID_TO_SID r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if (!unixinfo_io_q_unixinfo_uid_to_sid("", &q_u, data, 0)) + return False; + + r_u.status = _unixinfo_uid_to_sid(p, &q_u, &r_u); + + if (!unixinfo_io_r_unixinfo_uid_to_sid("", &r_u, rdata, 0)) + return False; + + return True; +} + +static BOOL api_sid_to_gid(pipes_struct *p) +{ + UNIXINFO_Q_SID_TO_GID q_u; + UNIXINFO_R_SID_TO_GID r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if (!unixinfo_io_q_unixinfo_sid_to_gid("", &q_u, data, 0)) + return False; + + r_u.status = _unixinfo_sid_to_gid(p, &q_u, &r_u); + + if (!unixinfo_io_r_unixinfo_sid_to_gid("", &r_u, rdata, 0)) + return False; + + return True; +} + +static BOOL api_gid_to_sid(pipes_struct *p) +{ + UNIXINFO_Q_GID_TO_SID q_u; + UNIXINFO_R_GID_TO_SID r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if (!unixinfo_io_q_unixinfo_gid_to_sid("", &q_u, data, 0)) + return False; + + r_u.status = _unixinfo_gid_to_sid(p, &q_u, &r_u); + + if (!unixinfo_io_r_unixinfo_gid_to_sid("", &r_u, rdata, 0)) + return False; + + return True; +} + +static BOOL api_getpwuid(pipes_struct *p) +{ + UNIXINFO_Q_GETPWUID q_u; + UNIXINFO_R_GETPWUID r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if (!unixinfo_io_q_unixinfo_getpwuid("", &q_u, data, 0)) + return False; + + r_u.status = _unixinfo_getpwuid(p, &q_u, &r_u); + + if (!unixinfo_io_r_unixinfo_getpwuid("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* +\pipe\unixinfo commands +********************************************************************/ + +struct api_struct api_unixinfo_cmds[] = { + {"SID_TO_UID", UNIXINFO_SID_TO_UID, api_sid_to_uid }, + {"UID_TO_SID", UNIXINFO_UID_TO_SID, api_uid_to_sid }, + {"SID_TO_GID", UNIXINFO_SID_TO_GID, api_sid_to_gid }, + {"GID_TO_SID", UNIXINFO_GID_TO_SID, api_gid_to_sid }, + {"GETPWUID", UNIXINFO_GETPWUID, api_getpwuid }, +}; + + +void unixinfo_get_pipe_fns( struct api_struct **fns, int *n_fns ) +{ + *fns = api_unixinfo_cmds; + *n_fns = sizeof(api_unixinfo_cmds) / sizeof(struct api_struct); +} + +NTSTATUS rpc_unixinfo_init(void) +{ + return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, + "unixinfo", "unixinfo", api_unixinfo_cmds, + sizeof(api_unixinfo_cmds) / sizeof(struct api_struct)); +} diff --git a/source/rpc_server/srv_unixinfo_nt.c b/source/rpc_server/srv_unixinfo_nt.c new file mode 100644 index 00000000000..79756f20a74 --- /dev/null +++ b/source/rpc_server/srv_unixinfo_nt.c @@ -0,0 +1,166 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines for unixinfo-pipe + * Copyright (C) Volker Lendecke 2005 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This is the interface to the rpcunixinfo pipe. */ + +#include "includes.h" +#include "nterr.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +/* Map a sid to a uid */ + +NTSTATUS _unixinfo_sid_to_uid(pipes_struct *p, + UNIXINFO_Q_SID_TO_UID *q_u, + UNIXINFO_R_SID_TO_UID *r_u) +{ + uid_t uid; + + r_u->uid.low = 0; + r_u->uid.high = 0; + + r_u->status = sid_to_uid(&q_u->sid, &uid) ? NT_STATUS_OK : NT_STATUS_NONE_MAPPED; + if (NT_STATUS_IS_OK(r_u->status)) + r_u->uid.low = uid; + + return r_u->status; +} + +/* Map a uid to a sid */ + +NTSTATUS _unixinfo_uid_to_sid(pipes_struct *p, + UNIXINFO_Q_UID_TO_SID *q_u, + UNIXINFO_R_UID_TO_SID *r_u) +{ + DOM_SID sid; + + r_u->status = NT_STATUS_NO_SUCH_USER; + + if (q_u->uid.high == 0) { + uid_to_sid(&sid, q_u->uid.low); + r_u->status = NT_STATUS_OK; + } + + init_r_unixinfo_uid_to_sid(r_u, + NT_STATUS_IS_OK(r_u->status) ? &sid : NULL); + + return r_u->status; +} + +/* Map a sid to a gid */ + +NTSTATUS _unixinfo_sid_to_gid(pipes_struct *p, + UNIXINFO_Q_SID_TO_GID *q_u, + UNIXINFO_R_SID_TO_GID *r_u) +{ + gid_t gid; + + r_u->gid.low = 0; + r_u->gid.high = 0; + + r_u->status = sid_to_gid(&q_u->sid, &gid) ? NT_STATUS_OK : NT_STATUS_NONE_MAPPED; + if (NT_STATUS_IS_OK(r_u->status)) + r_u->gid.low = gid; + + return r_u->status; +} + +/* Map a gid to a sid */ + +NTSTATUS _unixinfo_gid_to_sid(pipes_struct *p, + UNIXINFO_Q_GID_TO_SID *q_u, + UNIXINFO_R_GID_TO_SID *r_u) +{ + DOM_SID sid; + + r_u->status = NT_STATUS_NO_SUCH_USER; + + if (q_u->gid.high == 0) { + gid_to_sid(&sid, q_u->gid.low); + r_u->status = NT_STATUS_OK; + } + + init_r_unixinfo_gid_to_sid(r_u, + NT_STATUS_IS_OK(r_u->status) ? &sid : NULL); + + return r_u->status; +} + +/* Get unix struct passwd information */ + +NTSTATUS _unixinfo_getpwuid(pipes_struct *p, + UNIXINFO_Q_GETPWUID *q_u, + UNIXINFO_R_GETPWUID *r_u) +{ + int i; + + if (r_u->count > 1023) { + return NT_STATUS_INVALID_PARAMETER; + } + + r_u->info = TALLOC_ARRAY(p->mem_ctx, struct unixinfo_getpwuid, + q_u->count); + + if ((r_u->count > 0) && (r_u->info == NULL)) { + return NT_STATUS_NO_MEMORY; + } + + r_u->status = NT_STATUS_OK; + r_u->count = q_u->count; + + for (i=0; i<r_u->count; i++) { + struct passwd *pw; + char *homedir, *shell; + ssize_t len1, len2; + + r_u->info[i].status = NT_STATUS_NO_SUCH_USER; + r_u->info[i].homedir = ""; + r_u->info[i].shell = ""; + + if (q_u->uid[i].high != 0) { + DEBUG(10, ("64-bit uids not yet supported...\n")); + continue; + } + + pw = getpwuid(q_u->uid[i].low); + + if (pw == NULL) { + DEBUG(10, ("Did not find uid %d\n", q_u->uid[i].low)); + continue; + } + + len1 = push_utf8_talloc(p->mem_ctx, &homedir, pw->pw_dir); + len2 = push_utf8_talloc(p->mem_ctx, &shell, pw->pw_shell); + + if ((len1 < 0) || (len2 < 0) || (homedir == NULL) || + (shell == NULL)) { + DEBUG(3, ("push_utf8_talloc failed\n")); + r_u->info[i].status = NT_STATUS_NO_MEMORY; + continue; + } + + r_u->info[i].status = NT_STATUS_OK; + r_u->info[i].homedir = homedir; + r_u->info[i].shell = shell; + } + + return r_u->status; +} diff --git a/source/rpcclient/cmd_samr.c b/source/rpcclient/cmd_samr.c index 1a204e70bc7..2aab35ea3c4 100644 --- a/source/rpcclient/cmd_samr.c +++ b/source/rpcclient/cmd_samr.c @@ -77,7 +77,7 @@ static void display_sam_user_info_21(SAM_USER_INFO_21 *usr) unistr2_to_ascii(temp, &usr->uni_workstations, sizeof(temp)-1); printf("\tWorkstations:\t%s\n", temp); - unistr2_to_ascii(temp, &usr->uni_unknown_str, sizeof(temp)-1); + unistr2_to_ascii(temp, &usr->uni_comment, sizeof(temp)-1); printf("\tUnknown Str :\t%s\n", temp); unistr2_to_ascii(temp, &usr->uni_munged_dial, sizeof(temp)-1); diff --git a/source/rpcclient/cmd_spoolss.c b/source/rpcclient/cmd_spoolss.c index ed5653eb704..d77c58ad959 100644 --- a/source/rpcclient/cmd_spoolss.c +++ b/source/rpcclient/cmd_spoolss.c @@ -709,17 +709,23 @@ static void display_reg_value(REGISTRY_VALUE value) break; } case REG_MULTI_SZ: { - uint16 *curstr = (uint16 *) value.data_p; - uint8 *start = value.data_p; - printf("%s: REG_MULTI_SZ:\n", value.valuename); - while (((uint8 *) curstr < start + value.size)) { - rpcstr_pull(text, curstr, sizeof(text), -1, - STR_TERMINATE); - printf(" %s\n", *text != 0 ? text : "NULL"); - curstr += strlen(text) + 1; + int i, num_values; + char **values; + + if (!NT_STATUS_IS_OK(reg_pull_multi_sz(NULL, value.data_p, + value.size, + &num_values, + &values))) { + d_printf("reg_pull_multi_sz failed\n"); + break; + } + + for (i=0; i<num_values; i++) { + d_printf("%s\n", values[i]); } + TALLOC_FREE(values); + break; } - break; default: printf("%s: unknown type %d\n", value.valuename, value.type); } @@ -2012,7 +2018,7 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli, if (!W_ERROR_IS_OK(result)) goto done; - printf("%s\n", timestring(True)); + printf("%s\n", current_timestring(True)); printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id); /* Set the printer data */ @@ -2088,7 +2094,7 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli, if (!W_ERROR_IS_OK(result)) goto done; - printf("%s\n", timestring(True)); + printf("%s\n", current_timestring(True)); printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id); done: diff --git a/source/rpcclient/cmd_unixinfo.c b/source/rpcclient/cmd_unixinfo.c new file mode 100644 index 00000000000..2e9ab106522 --- /dev/null +++ b/source/rpcclient/cmd_unixinfo.c @@ -0,0 +1,195 @@ +/* + Unix SMB/CIFS implementation. + RPC pipe client + + Copyright (C) Volker Lendecke 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "rpcclient.h" + +static NTSTATUS cmd_unixinfo_uid2sid(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + uid_t uid; + DOM_SID sid; + NTSTATUS result; + + if (argc != 2) { + printf("Usage: %s uid\n", argv[0]); + return NT_STATUS_INVALID_PARAMETER; + } + + uid = atoi(argv[1]); + + result = rpccli_unixinfo_uid2sid(cli, mem_ctx, uid, &sid); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + printf("%s\n", sid_string_static(&sid)); + +done: + return result; +} + +static NTSTATUS cmd_unixinfo_sid2uid(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + uid_t uid; + DOM_SID sid; + NTSTATUS result; + + if (argc != 2) { + printf("Usage: %s sid\n", argv[0]); + return NT_STATUS_INVALID_PARAMETER; + } + + if (!string_to_sid(&sid, argv[1])) { + result = NT_STATUS_INVALID_SID; + goto done; + } + + result = rpccli_unixinfo_sid2uid(cli, mem_ctx, &sid, &uid); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + printf("%u\n", uid); + +done: + return result; +} + +static NTSTATUS cmd_unixinfo_gid2sid(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + gid_t gid; + DOM_SID sid; + NTSTATUS result; + + if (argc != 2) { + printf("Usage: %s gid\n", argv[0]); + return NT_STATUS_INVALID_PARAMETER; + } + + gid = atoi(argv[1]); + + result = rpccli_unixinfo_gid2sid(cli, mem_ctx, gid, &sid); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + printf("%s\n", sid_string_static(&sid)); + +done: + return result; +} + +static NTSTATUS cmd_unixinfo_sid2gid(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + gid_t gid; + DOM_SID sid; + NTSTATUS result; + + if (argc != 2) { + printf("Usage: %s sid\n", argv[0]); + return NT_STATUS_INVALID_PARAMETER; + } + + if (!string_to_sid(&sid, argv[1])) { + result = NT_STATUS_INVALID_SID; + goto done; + } + + result = rpccli_unixinfo_sid2gid(cli, mem_ctx, &sid, &gid); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + printf("%u\n", gid); + +done: + return result; +} + +static NTSTATUS cmd_unixinfo_getpwuid(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + uid_t *uids; + int i, num_uids; + struct unixinfo_getpwuid *info; + NTSTATUS result; + + if (argc < 2) { + printf("Usage: %s uid [uid2 uid3 ...]\n", argv[0]); + return NT_STATUS_INVALID_PARAMETER; + } + + num_uids = argc-1; + uids = TALLOC_ARRAY(mem_ctx, uid_t, num_uids); + + if (uids == NULL) { + return NT_STATUS_NO_MEMORY; + } + + for (i=0; i<num_uids; i++) { + uids[i] = atoi(argv[i+1]); + } + + result = rpccli_unixinfo_getpwuid(cli, mem_ctx, num_uids, uids, &info); + + if (!NT_STATUS_IS_OK(result)) { + return result; + } + + for (i=0; i<num_uids; i++) { + if (NT_STATUS_IS_OK(info[i].status)) { + printf("%d:%s:%s\n", uids[i], info[i].homedir, + info[i].shell); + } else { + printf("%d:%s\n", uids[i], nt_errstr(info[i].status)); + } + } + + return NT_STATUS_OK; +} + +/* List of commands exported by this module */ + +struct cmd_set unixinfo_commands[] = { + + { "UNIXINFO" }, + + { "uid2sid", RPC_RTYPE_NTSTATUS, cmd_unixinfo_uid2sid, NULL, + PI_UNIXINFO, NULL, "Convert a uid to a sid", "" }, + { "sid2uid", RPC_RTYPE_NTSTATUS, cmd_unixinfo_sid2uid, NULL, + PI_UNIXINFO, NULL, "Convert a sid to a uid", "" }, + { "gid2sid", RPC_RTYPE_NTSTATUS, cmd_unixinfo_gid2sid, NULL, + PI_UNIXINFO, NULL, "Convert a gid to a sid", "" }, + { "sid2gid", RPC_RTYPE_NTSTATUS, cmd_unixinfo_sid2gid, NULL, + PI_UNIXINFO, NULL, "Convert a sid to a gid", "" }, + { "getpwuid", RPC_RTYPE_NTSTATUS, cmd_unixinfo_getpwuid, NULL, + PI_UNIXINFO, NULL, "Get passwd info", "" }, + { NULL } +}; diff --git a/source/rpcclient/rpcclient.c b/source/rpcclient/rpcclient.c index d5425aa43d1..4ca674c2b10 100644 --- a/source/rpcclient/rpcclient.c +++ b/source/rpcclient/rpcclient.c @@ -457,6 +457,7 @@ static struct cmd_set separator_command[] = { /* Various pipe commands */ +extern struct cmd_set unixinfo_commands[]; extern struct cmd_set lsarpc_commands[]; extern struct cmd_set samr_commands[]; extern struct cmd_set spoolss_commands[]; @@ -471,6 +472,7 @@ extern struct cmd_set test_commands[]; static struct cmd_set *rpcclient_command_list[] = { rpcclient_commands, + unixinfo_commands, lsarpc_commands, ds_commands, samr_commands, diff --git a/source/sam/idmap.c b/source/sam/idmap.c index aa5b923d3dd..e8ebd9272c3 100644 --- a/source/sam/idmap.c +++ b/source/sam/idmap.c @@ -4,7 +4,7 @@ Copyright (C) Tim Potter 2000 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003 Copyright (C) Simo Sorce 2003 - Copyright (C) Jeremy Allison 2003. + Copyright (C) Jeremy Allison 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -182,13 +182,14 @@ BOOL idmap_proxyonly(void) set up for a sid to a POSIX id. **************************************************************************/ -NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) +NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, enum idmap_type id_type) { struct idmap_methods *map = remote_map; DOM_SID tmp_sid; - if (proxyonly) + if (proxyonly) { return NT_STATUS_UNSUCCESSFUL; + } if (sid_check_is_in_our_domain(sid)) { DEBUG(3, ("Refusing to add SID %s to idmap, it's our own " @@ -204,14 +205,12 @@ NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) DEBUG(10, ("idmap_set_mapping: Set %s to %s %lu\n", sid_string_static(sid), - ((id_type & ID_TYPEMASK) == ID_USERID) ? "UID" : "GID", - ((id_type & ID_TYPEMASK) == ID_USERID) ? (unsigned long)id.uid : + (id_type == ID_USERID) ? "UID" : "GID", + (id_type == ID_USERID) ? (unsigned long)id.uid : (unsigned long)id.gid)); - if ( (NT_STATUS_IS_OK(cache_map-> - get_sid_from_id(&tmp_sid, id, - id_type | ID_QUERY_ONLY))) && - sid_equal(sid, &tmp_sid) ) { + if ( (NT_STATUS_IS_OK(cache_map->get_sid_from_id(&tmp_sid, id, id_type, IDMAP_FLAG_QUERY_ONLY))) && + sid_equal(sid, &tmp_sid) ) { /* Nothing to do, we already have that mapping */ DEBUG(10, ("idmap_set_mapping: Mapping already there\n")); return NT_STATUS_OK; @@ -230,14 +229,14 @@ NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) Get ID from SID. This can create a mapping for a SID to a POSIX id. **************************************************************************/ -NTSTATUS idmap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) +NTSTATUS idmap_get_id_from_sid(unid_t *id, enum idmap_type *id_type, const DOM_SID *sid, int flags) { NTSTATUS ret; - int loc_type; - unid_t loc_id; + int cache_flags = flags; - if (proxyonly) + if (proxyonly) { return NT_STATUS_UNSUCCESSFUL; + } if (sid_check_is_in_our_domain(sid)) { DEBUG(9, ("sid %s is in our domain -- go look in passdb\n", @@ -251,55 +250,24 @@ NTSTATUS idmap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) return NT_STATUS_NONE_MAPPED; } - loc_type = *id_type; - if (remote_map) { /* We have a central remote idmap so only look in - cache, don't allocate */ - loc_type |= ID_QUERY_ONLY; + cache, ensure we don't allocate */ + cache_flags |= IDMAP_FLAG_QUERY_ONLY; } - ret = cache_map->get_id_from_sid(id, &loc_type, sid); - + ret = cache_map->get_id_from_sid(id, id_type, sid, cache_flags); if (NT_STATUS_IS_OK(ret)) { - *id_type = loc_type & ID_TYPEMASK; return NT_STATUS_OK; } - if ((remote_map == NULL) || (loc_type & ID_CACHE_ONLY)) { + if ((remote_map == NULL) || (flags & IDMAP_FLAG_CACHE_ONLY)) { return ret; } - /* Before forking out to the possibly slow remote map, lets see if we - * already have the sid as uid when asking for a gid or vice versa. */ - - loc_type = *id_type & ID_TYPEMASK; - - switch (loc_type) { - case ID_USERID: - loc_type = ID_GROUPID; - break; - case ID_GROUPID: - loc_type = ID_USERID; - break; - default: - loc_type = ID_EMPTY; - } - - loc_type |= ID_QUERY_ONLY; - - ret = cache_map->get_id_from_sid(&loc_id, &loc_type, sid); - - if (NT_STATUS_IS_OK(ret)) { - /* Ok, we have the uid as gid or vice versa. The remote map - * would not know anything different, so return here. */ - return NT_STATUS_UNSUCCESSFUL; - } - - /* Ok, the mapping was not in the cache, give the remote map a - second try. */ + /* Ok, the mapping was not in the cache, give the remote map a try. */ - ret = remote_map->get_id_from_sid(id, id_type, sid); + ret = remote_map->get_id_from_sid(id, id_type, sid, flags); if (NT_STATUS_IS_OK(ret)) { /* The remote backend gave us a valid mapping, cache it. */ @@ -313,30 +281,34 @@ NTSTATUS idmap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) Get SID from ID. This must have been created before. **************************************************************************/ -NTSTATUS idmap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) +NTSTATUS idmap_get_sid_from_id(DOM_SID *sid, unid_t id, enum idmap_type id_type, int flags) { NTSTATUS ret; - int loc_type; + int cache_flags = flags; - if (proxyonly) + if (proxyonly) { return NT_STATUS_UNSUCCESSFUL; + } - loc_type = id_type; if (remote_map) { - loc_type = id_type | ID_QUERY_ONLY; + /* We have a central remote idmap so only look in + cache, ensure we don't allocate */ + cache_flags |= IDMAP_FLAG_QUERY_ONLY; } - ret = cache_map->get_sid_from_id(sid, id, loc_type); + ret = cache_map->get_sid_from_id(sid, id, id_type, cache_flags); - if (NT_STATUS_IS_OK(ret)) + if (NT_STATUS_IS_OK(ret)) { return ret; + } - if ((remote_map == NULL) || (loc_type & ID_CACHE_ONLY)) + if ((remote_map == NULL) || (flags & IDMAP_FLAG_CACHE_ONLY)) { return ret; + } - /* We have a second chance, ask our authoritative backend */ + /* Not in cache, ask our authoritative backend */ - ret = remote_map->get_sid_from_id(sid, id, id_type); + ret = remote_map->get_sid_from_id(sid, id, id_type, flags); if (NT_STATUS_IS_OK(ret)) { /* The remote backend gave us a valid mapping, cache it. */ @@ -350,15 +322,17 @@ NTSTATUS idmap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) Alloocate a new UNIX uid/gid **************************************************************************/ -NTSTATUS idmap_allocate_id(unid_t *id, int id_type) +NTSTATUS idmap_allocate_id(unid_t *id, enum idmap_type id_type) { /* we have to allocate from the authoritative backend */ - if (proxyonly) + if (proxyonly) { return NT_STATUS_UNSUCCESSFUL; + } - if ( remote_map ) + if ( remote_map ) { return remote_map->allocate_id( id, id_type ); + } return cache_map->allocate_id( id, id_type ); } @@ -371,8 +345,9 @@ NTSTATUS idmap_close(void) { NTSTATUS ret; - if (proxyonly) + if (proxyonly) { return NT_STATUS_OK; + } ret = cache_map->close_fn(); if (!NT_STATUS_IS_OK(ret)) { @@ -398,6 +373,7 @@ NTSTATUS idmap_close(void) void idmap_status(void) { cache_map->status(); - if (remote_map) + if (remote_map) { remote_map->status(); + } } diff --git a/source/sam/idmap_ad.c b/source/sam/idmap_ad.c index 5edfad487d7..f0adfa4028a 100644 --- a/source/sam/idmap_ad.c +++ b/source/sam/idmap_ad.c @@ -139,7 +139,7 @@ static ADS_STRUCT *ad_idmap_cached_connection(void) return ads; } -static NTSTATUS ad_idmap_init(char *uri) +static NTSTATUS ad_idmap_init(const char *uri) { ad_idmap_uri = SMB_STRDUP(uri); if (ad_idmap_uri == NULL) { @@ -149,7 +149,7 @@ static NTSTATUS ad_idmap_init(char *uri) return NT_STATUS_OK; } -static NTSTATUS ad_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type) +static NTSTATUS ad_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, enum idmap_type id_type, int flags) { ADS_STATUS rc; NTSTATUS status = NT_STATUS_NONE_MAPPED; @@ -171,7 +171,7 @@ static NTSTATUS ad_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type) return NT_STATUS_NOT_SUPPORTED; } - switch (id_type & ID_TYPEMASK) { + switch (id_type) { case ID_USERID: if (asprintf(&expr, "(&(|(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d))(%s=%d))", ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST, @@ -231,7 +231,7 @@ done: return status; } -static NTSTATUS ad_idmap_get_id_from_sid(unid_t *unid, int *id_type, const DOM_SID *sid) +static NTSTATUS ad_idmap_get_id_from_sid(unid_t *unid, enum idmap_type *id_type, const DOM_SID *sid, int flags) { ADS_STATUS rc; NTSTATUS status = NT_STATUS_NONE_MAPPED; @@ -331,7 +331,7 @@ done: } -static NTSTATUS ad_idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) +static NTSTATUS ad_idmap_set_mapping(const DOM_SID *sid, unid_t id, enum idmap_type id_type) { /* Not supported, and probably won't be... */ /* (It's not particularly feasible with a single-master model.) */ @@ -356,7 +356,7 @@ static NTSTATUS ad_idmap_close(void) return NT_STATUS_OK; } -static NTSTATUS ad_idmap_allocate_id(unid_t *id, int id_type) +static NTSTATUS ad_idmap_allocate_id(unid_t *id, enum idmap_type id_type) { return NT_STATUS_NOT_IMPLEMENTED; } @@ -378,7 +378,7 @@ static struct idmap_methods ad_methods = { /* support for new authentication subsystem */ -NTSTATUS init_module(void) +NTSTATUS idmap_ad_init(void) { return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ad", &ad_methods); } diff --git a/source/sam/idmap_ldap.c b/source/sam/idmap_ldap.c index 6169c89b3b9..3fec3a142be 100644 --- a/source/sam/idmap_ldap.c +++ b/source/sam/idmap_ldap.c @@ -49,7 +49,7 @@ static struct ldap_idmap_state ldap_state; This function cannot be called to modify a mapping, only set a new one ***********************************************************************/ -static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) +static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, enum idmap_type id_type) { pstring dn; pstring id_str; @@ -66,12 +66,13 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) pstr_sprintf(dn, "%s=%s,%s", get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID), sid_string, lp_ldap_idmap_suffix()); - if ( id_type & ID_USERID ) + if ( id_type == ID_USERID ) { fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ) ); - else + } else { fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ) ); + } - pstr_sprintf(id_str, "%lu", ((id_type & ID_USERID) ? (unsigned long)id.uid : + pstr_sprintf(id_str, "%lu", ((id_type == ID_USERID) ? (unsigned long)id.uid : (unsigned long)id.gid)); smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDMAP_ENTRY ); @@ -117,7 +118,7 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) Allocate a new uid or gid *****************************************************************************/ -static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) +static NTSTATUS ldap_allocate_id(unid_t *id, enum idmap_type id_type) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; int rc = LDAP_SERVER_DOWN; @@ -133,8 +134,11 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) uid_t luid, huid; gid_t lgid, hgid; + if (id_type != ID_USERID && id_type != ID_GROUPID) { + return NT_STATUS_INVALID_PARAMETER; + } - type = (id_type & ID_USERID) ? + type = (id_type == ID_USERID) ? get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ) : get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); @@ -177,15 +181,14 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) /* make sure we still have room to grow */ - if (id_type & ID_USERID) { + if (id_type == ID_USERID) { id->uid = strtoul(id_str, NULL, 10); if (id->uid > huid ) { DEBUG(0,("ldap_allocate_id: Cannot allocate uid above %lu!\n", (unsigned long)huid)); goto out; } - } - else { + } else { id->gid = strtoul(id_str, NULL, 10); if (id->gid > hgid ) { DEBUG(0,("ldap_allocate_id: Cannot allocate gid above %lu!\n", @@ -195,7 +198,7 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) } pstr_sprintf(new_id_str, "%lu", - ((id_type & ID_USERID) ? (unsigned long)id->uid : + ((id_type == ID_USERID) ? (unsigned long)id->uid : (unsigned long)id->gid) + 1); smbldap_set_mod( &mods, LDAP_MOD_DELETE, type, id_str ); @@ -228,7 +231,7 @@ out: get a sid from an id *****************************************************************************/ -static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) +static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, enum idmap_type id_type, int flags) { LDAPMessage *result = NULL; LDAPMessage *entry = NULL; @@ -241,7 +244,7 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; const char **attr_list; - if ( id_type & ID_USERID ) + if ( id_type == ID_USERID ) type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ); else type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); @@ -289,10 +292,12 @@ out: } /*********************************************************************** - Get an id from a sid + Get an id from a sid - urg. This is assuming the *output* parameter id_type + has been initialized with the correct needed type - ID_USERID or ID_GROUPID. + This *sucks* and is bad design and needs fixing. JRA. ***********************************************************************/ -static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) +static NTSTATUS ldap_get_id_from_sid(unid_t *id, enum idmap_type *id_type, const DOM_SID *sid, int flags) { LDAPMessage *result = NULL; LDAPMessage *entry = NULL; @@ -316,7 +321,7 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, sid_str); - if ( *id_type & ID_GROUPID ) + if ( *id_type == ID_GROUPID ) type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ); else type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ); @@ -348,7 +353,7 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si if ( !count ) { int i; - if (*id_type & ID_QUERY_ONLY) { + if (flags & IDMAP_FLAG_QUERY_ONLY) { DEBUG(5,("ldap_get_id_from_sid: No matching entry found and QUERY_ONLY flag set\n")); goto out; } @@ -387,7 +392,7 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si DEBUG(10, ("Found mapping entry at dn=%s, looking for %s\n", dn, type)); if ( smbldap_get_single_pstring(ldap_state.smbldap_state->ldap_struct, entry, type, id_str) ) { - if ( (*id_type & ID_USERID) ) + if ( (*id_type == ID_USERID) ) id->uid = strtoul(id_str, NULL, 10); else id->gid = strtoul(id_str, NULL, 10); @@ -470,7 +475,7 @@ static NTSTATUS verify_idpool( void ) Initialise idmap database. *****************************************************************************/ -static NTSTATUS ldap_idmap_init( char *params ) +static NTSTATUS ldap_idmap_init( const char *params ) { NTSTATUS nt_status; diff --git a/source/sam/idmap_rid.c b/source/sam/idmap_rid.c index 58838512a68..23496d69692 100644 --- a/source/sam/idmap_rid.c +++ b/source/sam/idmap_rid.c @@ -334,7 +334,7 @@ out: return status; } -static NTSTATUS rid_idmap_init(char *init_param) +static NTSTATUS rid_idmap_init(const char *init_param) { int i, j; uid_t u_low, u_high; @@ -432,7 +432,8 @@ out: return nt_status; } -static NTSTATUS rid_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type) +static NTSTATUS rid_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, enum idmap_type id_type, int flags) + { fstring sid_string; int i; @@ -469,7 +470,7 @@ static NTSTATUS rid_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type return NT_STATUS_OK; } -static NTSTATUS rid_idmap_get_id_from_sid(unid_t *unid, int *id_type, const DOM_SID *sid) +static NTSTATUS rid_idmap_get_id_from_sid(unid_t *unid, enum idmap_type *id_type, const DOM_SID *sid, int flags) { fstring sid_string; int i; @@ -521,7 +522,7 @@ static NTSTATUS rid_idmap_get_id_from_sid(unid_t *unid, int *id_type, const DOM_ } -static NTSTATUS rid_idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) +static NTSTATUS rid_idmap_set_mapping(const DOM_SID *sid, unid_t id, enum idmap_type id_type) { return NT_STATUS_NOT_IMPLEMENTED; } @@ -533,7 +534,7 @@ static NTSTATUS rid_idmap_close(void) return NT_STATUS_OK; } -static NTSTATUS rid_idmap_allocate_id(unid_t *id, int id_type) +static NTSTATUS rid_idmap_allocate_id(unid_t *id, enum idmap_type id_type) { return NT_STATUS_NOT_IMPLEMENTED; } @@ -553,7 +554,7 @@ static struct idmap_methods rid_methods = { rid_idmap_status }; -NTSTATUS init_module(void) +NTSTATUS idmap_rid_init(void) { return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "rid", &rid_methods); } diff --git a/source/sam/idmap_smbldap.c b/source/sam/idmap_smbldap.c index 4d80364437c..9850921fa39 100644 --- a/source/sam/idmap_smbldap.c +++ b/source/sam/idmap_smbldap.c @@ -90,7 +90,7 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) Allocate a new uid or gid *****************************************************************************/ -static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) +static NTSTATUS ldap_allocate_id(unid_t *id, enum idmap_type id_type) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; uid_t luid, huid; @@ -104,7 +104,11 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) const char *id_attrib; char *mod; - id_attrib = (id_type & ID_USERID) ? "uidNumber" : "gidNumber"; + if (id_type != ID_USERID && id_type != ID_GROUPID) { + return NT_STATUS_INVALID_PARAMETER; + } + + id_attrib = (id_type == ID_USERID) ? "uidNumber" : "gidNumber"; idpool_s = new_ldap_search_message(lp_ldap_suffix(), LDAP_SEARCH_SCOPE_SUB, @@ -129,7 +133,7 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) /* make sure we still have room to grow */ - if (id_type & ID_USERID) { + if (id_type == ID_USERID) { id->uid = value; if (id->uid > huid ) { DEBUG(0,("ldap_allocate_id: Cannot allocate uid " diff --git a/source/sam/idmap_tdb.c b/source/sam/idmap_tdb.c index 665c56d2f67..02a3178d61a 100644 --- a/source/sam/idmap_tdb.c +++ b/source/sam/idmap_tdb.c @@ -6,6 +6,7 @@ Copyright (C) Tim Potter 2000 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003 Copyright (C) Simo Sorce 2003 + Copyright (C) Jeremy Allison 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -46,16 +47,13 @@ static struct idmap_state { Allocate either a user or group id from the pool **********************************************************************/ -static NTSTATUS db_allocate_id(unid_t *id, int id_type) +static NTSTATUS db_allocate_id(unid_t *id, enum idmap_type id_type) { BOOL ret; int hwm; - if (!id) - return NT_STATUS_INVALID_PARAMETER; - /* Get current high water mark */ - switch (id_type & ID_TYPEMASK) { + switch (id_type) { case ID_USERID: if ((hwm = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) { @@ -125,274 +123,327 @@ static NTSTATUS db_allocate_id(unid_t *id, int id_type) return NT_STATUS_OK; } -/* Get a sid from an id */ -static NTSTATUS internal_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) +/* Get a sid from an id - internal non-reverse map checking function. */ + +static NTSTATUS db_internal_get_sid_from_id(DOM_SID *sid, unid_t id, enum idmap_type id_type) { TDB_DATA key, data; - fstring keystr; + TALLOC_CTX *memctx; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - if (!sid) - return NT_STATUS_INVALID_PARAMETER; + if ((memctx = talloc_new(NULL)) == NULL) { + DEBUG(0, ("ERROR: Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } - switch (id_type & ID_TYPEMASK) { + switch (id_type) { case ID_USERID: - slprintf(keystr, sizeof(keystr), "UID %lu", (unsigned long)id.uid); + key.dptr = talloc_asprintf(memctx, "UID %lu", (unsigned long)id.uid); break; case ID_GROUPID: - slprintf(keystr, sizeof(keystr), "GID %lu", (unsigned long)id.gid); + key.dptr = talloc_asprintf(memctx, "GID %lu", (unsigned long)id.gid); break; default: - return NT_STATUS_UNSUCCESSFUL; + ret = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + if (key.dptr == NULL) { + DEBUG(0, ("ERROR: Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; } - key.dptr = keystr; - key.dsize = strlen(keystr) + 1; + key.dsize = strlen(key.dptr) + 1; - DEBUG(10,("internal_get_sid_from_id: fetching record %s\n", keystr )); + DEBUG(10,("db_internal_get_sid_from_id: fetching record %s\n", key.dptr)); data = tdb_fetch(idmap_tdb, key); if (data.dptr) { if (string_to_sid(sid, data.dptr)) { - DEBUG(10,("internal_get_sid_from_id: fetching record %s -> %s\n", keystr, data.dptr )); + DEBUG(10,("db_internal_get_sid_from_id: fetching record %s -> %s\n", key.dptr, data.dptr )); ret = NT_STATUS_OK; } SAFE_FREE(data.dptr); } +done: + talloc_free(memctx); return ret; } -/* Error codes for get_id_from_sid */ -enum getidfromsiderr { GET_ID_FROM_SID_OK = 0, GET_ID_FROM_SID_NOTFOUND, GET_ID_FROM_SID_WRONG_TYPE, GET_ID_FROM_SID_ERR }; +/* Get an id from a sid - internal non-reverse map checking function. */ -static enum getidfromsiderr internal_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) +static NTSTATUS db_internal_get_id_from_sid(unid_t *id, enum idmap_type *id_type, const DOM_SID *sid) { - enum getidfromsiderr ret = GET_ID_FROM_SID_ERR; - fstring keystr; + NTSTATUS ret; TDB_DATA key, data; - int type = *id_type & ID_TYPEMASK; + TALLOC_CTX *memctx; + unsigned long rec_id; + + if ((memctx = talloc_new(NULL)) == NULL) { + DEBUG(0, ("ERROR: Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } /* Check if sid is present in database */ - sid_to_string(keystr, sid); + if ((key.dptr = talloc_asprintf(memctx, "%s", sid_string_static(sid))) == NULL) { + DEBUG(0, ("ERROR: Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } - key.dptr = keystr; - key.dsize = strlen(keystr) + 1; + key.dsize = strlen(key.dptr) + 1; - DEBUG(10,("internal_get_id_from_sid: fetching record %s of type 0x%x\n", keystr, type )); + DEBUG(10,("db_internal_get_id_from_sid: fetching record %s\n", key.dptr)); data = tdb_fetch(idmap_tdb, key); if (!data.dptr) { - DEBUG(10,("internal_get_id_from_sid: record %s not found\n", keystr )); - return GET_ID_FROM_SID_NOTFOUND; + DEBUG(10,("db_internal_get_id_from_sid: record %s not found\n", key.dptr)); + ret = NT_STATUS_NO_SUCH_USER; + goto done; } else { - DEBUG(10,("internal_get_id_from_sid: record %s -> %s\n", keystr, data.dptr )); + DEBUG(10,("db_internal_get_id_from_sid: record %s -> %s\n", key.dptr, data.dptr)); } - if (type == ID_EMPTY || type == ID_USERID) { - fstring scanstr; - /* Parse and return existing uid */ - fstrcpy(scanstr, "UID %d"); - - if (sscanf(data.dptr, scanstr, &((*id).uid)) == 1) { - /* uid ok? */ - if (type == ID_EMPTY) { - *id_type = ID_USERID; - } - DEBUG(10,("internal_get_id_from_sid: %s fetching record %s -> %s \n", - (type == ID_EMPTY) ? "ID_EMPTY" : "ID_USERID", - keystr, data.dptr )); - ret = GET_ID_FROM_SID_OK; - } else { - ret = GET_ID_FROM_SID_WRONG_TYPE; - } - } - - if ((ret != GET_ID_FROM_SID_OK) && (type == ID_EMPTY || type == ID_GROUPID)) { - fstring scanstr; - /* Parse and return existing gid */ - fstrcpy(scanstr, "GID %d"); - - if (sscanf(data.dptr, scanstr, &((*id).gid)) == 1) { - /* gid ok? */ - if (type == ID_EMPTY) { - *id_type = ID_GROUPID; - } - DEBUG(10,("internal_get_id_from_sid: %s fetching record %s -> %s \n", - (type == ID_EMPTY) ? "ID_EMPTY" : "ID_GROUPID", - keystr, data.dptr )); - ret = GET_ID_FROM_SID_OK; - } else { - ret = GET_ID_FROM_SID_WRONG_TYPE; - } + /* What type of record is this ? */ + + /* Try and parse and return a uid */ + if (sscanf(data.dptr, "UID %lu", &rec_id) == 1) { + id->uid = (uid_t)rec_id; + *id_type = ID_USERID; + DEBUG(10,("db_internal_get_id_from_sid: fetching uid record %s -> %s \n", + key.dptr, data.dptr )); + ret = NT_STATUS_OK; + } else if (sscanf(data.dptr, "GID %lu", &rec_id) == 1) { /* Try a GID record. */ + id->gid = (uid_t)rec_id; + *id_type = ID_GROUPID; + DEBUG(10,("db_internal_get_id_from_sid: fetching gid record %s -> %s \n", + key.dptr, data.dptr )); + ret = NT_STATUS_OK; + } else { + /* Unknown record type ! */ + ret = NT_STATUS_INTERNAL_DB_ERROR; } SAFE_FREE(data.dptr); +done: + talloc_free(memctx); return ret; } -/* Get a sid from an id */ -static NTSTATUS db_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type_in) +/* Get a sid from an id - internal non-reverse map checking function. */ + +static NTSTATUS db_get_sid_from_id(DOM_SID *sid, unid_t id, enum idmap_type id_type, int flags) { - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - enum getidfromsiderr iderr; - int id_type = id_type_in & ID_TYPEMASK; - unid_t id_tmp = id; - int id_type_tmp = id_type; + NTSTATUS ret; + unid_t tmp_id; + enum idmap_type tmp_id_type; - DEBUG(10,("db_get_sid_from_id: id_type_in = 0x%x\n", id_type_in)); + ret = db_internal_get_sid_from_id(sid, id, id_type); - ret = internal_get_sid_from_id(sid, id, id_type); if (!NT_STATUS_IS_OK(ret)) { return ret; } - - iderr = internal_get_id_from_sid(&id_tmp, &id_type_tmp, sid); - if (iderr != GET_ID_FROM_SID_OK) { - return NT_STATUS_UNSUCCESSFUL; - } - if (id_type_tmp != id_type) { - return NT_STATUS_UNSUCCESSFUL; - } else if (id_type == ID_USERID) { - if (id_tmp.uid != id.uid) { - return NT_STATUS_UNSUCCESSFUL; - } - } else if (id_type == ID_GROUPID) { - if (id_tmp.gid != id.gid) { - return NT_STATUS_UNSUCCESSFUL; + + /* Ensure the reverse mapping exists. */ + + ret = db_internal_get_id_from_sid(&tmp_id, &tmp_id_type, sid); + if (NT_STATUS_IS_OK(ret)) { + /* Check the reverse mapping is the same. */ + if (tmp_id.uid != id.uid || tmp_id_type != id_type) { + DEBUG(10,("db_get_sid_from_id: reverse mapping mismatch " + "tmp_id = %u, id = %u, tmp_id_type = %u, id_type = %u\n", + (unsigned int)tmp_id.uid, (unsigned int)id.uid, + (unsigned int)tmp_id_type, (unsigned int)id_type )); + return NT_STATUS_NO_SUCH_USER; } - } else { - return NT_STATUS_UNSUCCESSFUL; } + return ret; } -/* Get an id from a sid */ -static NTSTATUS db_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) + +/*********************************************************************** + Why is this function internal and not part of the interface ????? + This *sucks* and is bad design and needs fixing. JRA. +***********************************************************************/ + +static NTSTATUS db_internal_allocate_new_id_for_sid(unid_t *id, enum idmap_type *id_type, const DOM_SID *sid) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - enum getidfromsiderr iderr; + TDB_DATA sid_data; + TDB_DATA ugid_data; + TALLOC_CTX *memctx; + + if ((memctx = talloc_new(NULL)) == NULL) { + DEBUG(0, ("ERROR: Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } - DEBUG(10,("db_get_id_from_sid\n")); + if ((sid_data.dptr = talloc_asprintf(memctx, "%s", sid_string_static(sid))) == NULL) { + DEBUG(0, ("ERROR: Out of memory!\n")); + talloc_free(memctx); + return NT_STATUS_NO_MEMORY; + } - if (!sid || !id || !id_type) - return NT_STATUS_INVALID_PARAMETER; + sid_data.dsize = strlen(sid_data.dptr) + 1; - iderr = internal_get_id_from_sid(id, id_type, sid); - if (iderr == GET_ID_FROM_SID_OK) { - DOM_SID sid_tmp; - ret = internal_get_sid_from_id(&sid_tmp, *id, *id_type); - if (NT_STATUS_IS_OK(ret)) { - if (!sid_equal(&sid_tmp, sid)) { - return NT_STATUS_UNSUCCESSFUL; - } - } - } else if (iderr == GET_ID_FROM_SID_WRONG_TYPE) { - /* We found a record but not the type we wanted. - * This is an error, not an opportunity to overwrite... - * JRA. - */ + /* Lock the record for this SID. */ + if (tdb_chainlock(idmap_tdb, sid_data) != 0) { + DEBUG(10,("db_internal_allocate_new_id_for_sid: failed to lock record %s. Error %s\n", + sid_data.dptr, tdb_errorstr(idmap_tdb) )); + talloc_free(memctx); return NT_STATUS_UNSUCCESSFUL; } - if (!(*id_type & ID_QUERY_ONLY) && (iderr != GET_ID_FROM_SID_OK) && - (((*id_type & ID_TYPEMASK) == ID_USERID) - || (*id_type & ID_TYPEMASK) == ID_GROUPID)) { - TDB_DATA sid_data; - TDB_DATA ugid_data; - fstring sid_string; - - sid_to_string(sid_string, sid); - - sid_data.dptr = sid_string; - sid_data.dsize = strlen(sid_string)+1; - - /* Lock the record for this SID. */ - if (tdb_chainlock(idmap_tdb, sid_data) != 0) { - DEBUG(10,("db_get_id_from_sid: failed to lock record %s. Error %s\n", - sid_string, tdb_errorstr(idmap_tdb) )); - return NT_STATUS_UNSUCCESSFUL; + do { + /* Allocate a new id for this sid */ + ret = db_allocate_id(id, *id_type); + if (!NT_STATUS_IS_OK(ret)) { + goto done; + } + + /* Store the UID side */ + /* Store new id */ + if (*id_type == ID_USERID) { + ugid_data.dptr = talloc_asprintf(memctx, "UID %lu", + (unsigned long)((*id).uid)); + } else { + ugid_data.dptr = talloc_asprintf(memctx, "GID %lu", + (unsigned long)((*id).gid)); } - do { - fstring ugid_str; + if (ugid_data.dptr == NULL) { + DEBUG(0, ("ERROR: Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } - /* Allocate a new id for this sid */ - ret = db_allocate_id(id, *id_type); - if (!NT_STATUS_IS_OK(ret)) - break; + ugid_data.dsize = strlen(ugid_data.dptr) + 1; - /* Store the UID side */ - /* Store new id */ - if (*id_type & ID_USERID) { - slprintf(ugid_str, sizeof(ugid_str), "UID %lu", - (unsigned long)((*id).uid)); - } else { - slprintf(ugid_str, sizeof(ugid_str), "GID %lu", - (unsigned long)((*id).gid)); - } - - ugid_data.dptr = ugid_str; - ugid_data.dsize = strlen(ugid_str) + 1; + DEBUG(10,("db_internal_allocate_new_id_for_sid: storing %s -> %s\n", + ugid_data.dptr, sid_data.dptr )); - DEBUG(10,("db_get_id_from_sid: storing %s -> %s\n", - ugid_data.dptr, sid_data.dptr )); + if (tdb_store(idmap_tdb, ugid_data, sid_data, TDB_INSERT) != -1) { + ret = NT_STATUS_OK; + break; + } + if (tdb_error(idmap_tdb) != TDB_ERR_EXISTS) { + DEBUG(10,("db_internal_allocate_new_id_for_sid: error %s\n", tdb_errorstr(idmap_tdb))); + } + + ret = NT_STATUS_INTERNAL_DB_ERROR; - if (tdb_store(idmap_tdb, ugid_data, sid_data, TDB_INSERT) != -1) { - ret = NT_STATUS_OK; - break; - } - if (tdb_error(idmap_tdb) != TDB_ERR_EXISTS) - DEBUG(10,("db_get_id_from_sid: error %s\n", tdb_errorstr(idmap_tdb) )); - ret = NT_STATUS_UNSUCCESSFUL; - } while (tdb_error(idmap_tdb) == TDB_ERR_EXISTS); + } while (tdb_error(idmap_tdb) == TDB_ERR_EXISTS); - if (NT_STATUS_IS_OK(ret)) { + if (NT_STATUS_IS_OK(ret)) { + DEBUG(10,("db_internal_allocate_new_id_for_sid: storing %s -> %s\n", + sid_data.dptr, ugid_data.dptr )); - DEBUG(10,("db_get_id_from_sid: storing %s -> %s\n", - sid_data.dptr, ugid_data.dptr )); + if (tdb_store(idmap_tdb, sid_data, ugid_data, TDB_REPLACE) == -1) { + DEBUG(10,("db_internal_allocate_new_id_for_sid: error %s\n", tdb_errorstr(idmap_tdb) )); + ret = NT_STATUS_INTERNAL_DB_ERROR; + } + } - if (tdb_store(idmap_tdb, sid_data, ugid_data, TDB_REPLACE) == -1) { - DEBUG(10,("db_get_id_from_sid: error %s\n", tdb_errorstr(idmap_tdb) )); - /* TODO: print tdb error !! */ - tdb_chainunlock(idmap_tdb, sid_data); - return NT_STATUS_UNSUCCESSFUL; + done: + + tdb_chainunlock(idmap_tdb, sid_data); + talloc_free(memctx); + + return ret; +} + +/*********************************************************************** + Get an id from a sid - urg. This is assuming the *output* parameter id_type + has been initialized with the correct needed type - ID_USERID or ID_GROUPID. + This function also allocates new mappings ! WTF ?????? + This *sucks* and is bad design and needs fixing. JRA. +***********************************************************************/ + +static NTSTATUS db_get_id_from_sid(unid_t *id, enum idmap_type *id_type, const DOM_SID *sid, int flags) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + enum idmap_type tmp_id_type = *id_type; + + DEBUG(10,("db_get_id_from_sid %s\n", sid_string_static(sid))); + + ret = db_internal_get_id_from_sid(id, &tmp_id_type, sid); + + if (NT_STATUS_IS_OK(ret)) { + DOM_SID sid_tmp; + + /* Check the reverse mapping is the same. Remember *id_type was set as a parameter + to this call... */ + if (tmp_id_type != *id_type) { + DEBUG(10,("db_get_sid_from_id: sid %s reverse mapping mismatch " + "tmp_id_type = %u, id_type = %u\n", + sid_string_static(sid), + (unsigned int)tmp_id_type, (unsigned int)(*id_type) )); + return NT_STATUS_NO_SUCH_USER; + } + + ret = db_internal_get_sid_from_id(&sid_tmp, *id, *id_type); + if (NT_STATUS_IS_OK(ret)) { + if (!sid_equal(&sid_tmp, sid)) { + DEBUG(10,("db_get_sid_from_id: sid %s reverse mapping SID mismatch" + "id = %u, id_type = %u\n", + sid_string_static(sid), + (unsigned int)id->uid, (unsigned int)(*id_type) )); + return NT_STATUS_NO_SUCH_USER; } } + return ret; + } - tdb_chainunlock(idmap_tdb, sid_data); + if (flags & IDMAP_FLAG_QUERY_ONLY) { + return ret; } - - return ret; + + /* We're in to bad design territory.... This call is now + *allocating* and storing a new mapping for sid -> id. This SHOULD + NOT BE DONE HERE ! There needs to be a separate upper + level call for this... I think the reason this was badly + designed this way was the desire to reuse cache code with + a tdb idmap implementation. They MUST be separated ! JRA */ + + return db_internal_allocate_new_id_for_sid(id, id_type, sid); } -static NTSTATUS db_set_mapping(const DOM_SID *sid, unid_t id, int id_type) +static NTSTATUS db_set_mapping(const DOM_SID *sid, unid_t id, enum idmap_type id_type) { + NTSTATUS ret; TDB_DATA ksid, kid, data; - fstring ksidstr; - fstring kidstr; + TALLOC_CTX *memctx; - DEBUG(10,("db_set_mapping: id_type = 0x%x\n", id_type)); + DEBUG(10,("db_set_mapping: id_type = 0x%x\n", (unsigned int)id_type)); - if (!sid) - return NT_STATUS_INVALID_PARAMETER; - - sid_to_string(ksidstr, sid); + if ((memctx = talloc_new(NULL)) == NULL) { + DEBUG(0, ("ERROR: Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } - ksid.dptr = ksidstr; - ksid.dsize = strlen(ksidstr) + 1; + if ((ksid.dptr = talloc_asprintf(memctx, "%s", sid_string_static(sid))) == NULL) { + DEBUG(0, ("ERROR: Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + ksid.dsize = strlen(ksid.dptr) + 1; - if (id_type & ID_USERID) { - slprintf(kidstr, sizeof(kidstr), "UID %lu", (unsigned long)id.uid); - } else if (id_type & ID_GROUPID) { - slprintf(kidstr, sizeof(kidstr), "GID %lu", (unsigned long)id.gid); + if (id_type == ID_USERID) { + kid.dptr = talloc_asprintf(memctx, "UID %lu", (unsigned long)id.uid); } else { - return NT_STATUS_INVALID_PARAMETER; + kid.dptr = talloc_asprintf(memctx, "GID %lu", (unsigned long)id.gid); } - kid.dptr = kidstr; - kid.dsize = strlen(kidstr) + 1; + if (kid.dptr == NULL) { + DEBUG(0, ("ERROR: Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + kid.dsize = strlen(kid.dptr) + 1; /* *DELETE* prevoius mappings if any. * This is done both SID and [U|G]ID passed in */ @@ -400,7 +451,7 @@ static NTSTATUS db_set_mapping(const DOM_SID *sid, unid_t id, int id_type) /* Lock the record for this SID. */ if (tdb_chainlock(idmap_tdb, ksid) != 0) { DEBUG(10,("db_set_mapping: failed to lock record %s. Error %s\n", - ksidstr, tdb_errorstr(idmap_tdb) )); + ksid.dptr, tdb_errorstr(idmap_tdb) )); return NT_STATUS_UNSUCCESSFUL; } @@ -424,24 +475,29 @@ static NTSTATUS db_set_mapping(const DOM_SID *sid, unid_t id, int id_type) if (tdb_store(idmap_tdb, ksid, kid, TDB_INSERT) == -1) { DEBUG(0, ("idb_set_mapping: tdb_store 1 error: %s\n", tdb_errorstr(idmap_tdb))); tdb_chainunlock(idmap_tdb, ksid); - return NT_STATUS_UNSUCCESSFUL; + ret = NT_STATUS_UNSUCCESSFUL; + goto done; } if (tdb_store(idmap_tdb, kid, ksid, TDB_INSERT) == -1) { DEBUG(0, ("idb_set_mapping: tdb_store 2 error: %s\n", tdb_errorstr(idmap_tdb))); tdb_chainunlock(idmap_tdb, ksid); - return NT_STATUS_UNSUCCESSFUL; + ret = NT_STATUS_UNSUCCESSFUL; + goto done; } tdb_chainunlock(idmap_tdb, ksid); DEBUG(10,("db_set_mapping: stored %s -> %s and %s -> %s\n", ksid.dptr, kid.dptr, kid.dptr, ksid.dptr )); - return NT_STATUS_OK; + ret = NT_STATUS_OK; +done: + talloc_free(memctx); + return ret; } /***************************************************************************** Initialise idmap database. *****************************************************************************/ -static NTSTATUS db_idmap_init( char *params ) +static NTSTATUS db_idmap_init( const char *params ) { SMB_STRUCT_STAT stbuf; char *tdbfile = NULL; diff --git a/source/sam/idmap_util.c b/source/sam/idmap_util.c index f78d3bdc233..8320b294f8f 100644 --- a/source/sam/idmap_util.c +++ b/source/sam/idmap_util.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. ID Mapping Copyright (C) Simo Sorce 2003 + Copyright (C) Jeremy Allison 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,10 +33,9 @@ NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid, int flags) DEBUG(10,("idmap_uid_to_sid: uid = [%lu]\n", (unsigned long)uid)); - flags |= ID_USERID; id.uid = uid; - return idmap_get_sid_from_id(sid, id, flags); + return idmap_get_sid_from_id(sid, id, ID_USERID, flags); } /***************************************************************** @@ -49,10 +49,9 @@ NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid, int flags) DEBUG(10,("idmap_gid_to_sid: gid = [%lu]\n", (unsigned long)gid)); - flags |= ID_GROUPID; id.gid = gid; - return idmap_get_sid_from_id(sid, id, flags); + return idmap_get_sid_from_id(sid, id, ID_GROUPID, flags); } /***************************************************************** @@ -62,24 +61,32 @@ NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid, int flags) was done correctly, False if not. *****************************************************************/ -NTSTATUS idmap_sid_to_uid(const DOM_SID *sid, uid_t *uid, uint32 flags) +NTSTATUS idmap_sid_to_uid(const DOM_SID *sid, uid_t *uid, int flags) { - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + NTSTATUS ret; + enum idmap_type id_type; unid_t id; DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_static(sid))); - flags |= ID_USERID; + /* For the LDAP and tdb backends we must *KNOW* what we're looking for. + This interface design *SUCKS* ! JRA. */ - ret = idmap_get_id_from_sid(&id, (int *)&flags, sid); - - if ( NT_STATUS_IS_OK(ret) ) { - DEBUG(10,("idmap_sid_to_uid: uid = [%lu]\n", (unsigned long)id.uid)); - *uid = id.uid; - } + id_type = ID_USERID; + ret = idmap_get_id_from_sid(&id, &id_type, sid, flags); + + if (!NT_STATUS_IS_OK(ret)) { + return ret; + } + + if (id_type != ID_USERID) { + return NT_STATUS_NONE_MAPPED; + } - return ret; + DEBUG(10,("idmap_sid_to_uid: uid = [%lu]\n", (unsigned long)id.uid)); + *uid = id.uid; + return NT_STATUS_OK; } /***************************************************************** @@ -91,22 +98,30 @@ NTSTATUS idmap_sid_to_uid(const DOM_SID *sid, uid_t *uid, uint32 flags) was done correctly, False if not. *****************************************************************/ -NTSTATUS idmap_sid_to_gid(const DOM_SID *sid, gid_t *gid, uint32 flags) +NTSTATUS idmap_sid_to_gid(const DOM_SID *sid, gid_t *gid, int flags) { - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + NTSTATUS ret; + enum idmap_type id_type; unid_t id; DEBUG(10,("sid_to_gid: sid = [%s]\n", sid_string_static(sid))); - flags |= ID_GROUPID; + /* For the LDAP and tdb backends we must *KNOW* what we're looking for. + This interface design *SUCKS* ! JRA. */ - ret = idmap_get_id_from_sid(&id, (int *)&flags, sid); + id_type = ID_GROUPID; + ret = idmap_get_id_from_sid(&id, &id_type, sid, flags); - if ( NT_STATUS_IS_OK(ret) ) - { - DEBUG(10,("idmap_sid_to_gid: gid = [%lu]\n", (unsigned long)id.gid)); - *gid = id.gid; + if (!NT_STATUS_IS_OK(ret)) { + return ret; + } + + if (id_type != ID_GROUPID) { + return NT_STATUS_NONE_MAPPED; } - return ret; + DEBUG(10,("idmap_sid_to_gid: gid = [%lu]\n", (unsigned long)id.gid)); + *gid = id.gid; + + return NT_STATUS_OK; } diff --git a/source/script/mkproto.awk b/source/script/mkproto.awk index a0f3096c842..30b5628b336 100644 --- a/source/script/mkproto.awk +++ b/source/script/mkproto.awk @@ -48,6 +48,11 @@ END { printf "BOOL %s(int );\n", a[2] } +/^FN_LOCAL_PARM_BOOL/ { + split($0,a,"[,()]") + printf "BOOL %s(const struct share_params *p );\n", a[2] +} + /^FN_LOCAL_LIST/ { split($0,a,"[,()]") printf "const char **%s(int );\n", a[2] @@ -58,6 +63,11 @@ END { printf "char *%s(int );\n", a[2] } +/^FN_LOCAL_PARM_STRING/ { + split($0,a,"[,()]") + printf "char *%s(const struct share_params *p );\n", a[2] +} + /^FN_LOCAL_CONST_STRING/ { split($0,a,"[,()]") printf "const char *%s(int );\n", a[2] @@ -70,7 +80,7 @@ END { /^FN_LOCAL_CHAR/ { split($0,a,"[,()]") - printf "char %s(int );\n", a[2] + printf "char %s(const struct share_params *p );\n", a[2] } /^FN_GLOBAL_BOOL/ { diff --git a/source/script/mkproto.sh b/source/script/mkproto.sh index 62041c7e331..e46e73e3e90 100755 --- a/source/script/mkproto.sh +++ b/source/script/mkproto.sh @@ -25,7 +25,7 @@ header="$1" shift headertmp="$header.$$.tmp~" -proto_src="`echo $@ | tr ' ' '\n' | sed -e 's/\.o/\.c/g' | sort | uniq | egrep -v 'ubiqx/|wrapped|modules/getdate'`" +proto_src="`echo $@ | tr ' ' '\n' | sed -e 's/\.o/\.c/g' | sort | uniq | egrep -v 'tdb/|wrapped|modules/getdate'`" echo creating $header diff --git a/source/script/tests/selftest.sh b/source/script/tests/selftest.sh index fe943b87b5e..d7a2db5eb64 100755 --- a/source/script/tests/selftest.sh +++ b/source/script/tests/selftest.sh @@ -111,12 +111,22 @@ cat >$SERVERCONFFILE<<EOF bind interfaces only = yes include = $COMMONCONFFILE + ; Necessary to add the build farm hacks + add user script = /bin/false + add machine script = /bin/false + kernel oplocks = no [tmp] path = $PREFIX_ABS/tmp read only = no smbd:sharedelay = 100000 +[hideunread] + copy = tmp + hide unreadable = yes +[hideunwrite] + copy = tmp + hide unwriteable files = yes EOF @@ -181,8 +191,8 @@ START=`date` bin/nmblookup $CONFIGURATION $SERVER # make sure smbd is also up set echo "wait for smbd" - bin/smbclient $CONFIGURATION -L $SERVER_IP -N -p 139 | head -2 - bin/smbclient $CONFIGURATION -L $SERVER_IP -N -p 139 | head -2 + bin/smbclient $CONFIGURATION -L $SERVER_IP -U% -p 139 | head -2 + bin/smbclient $CONFIGURATION -L $SERVER_IP -U% -p 139 | head -2 failed=0 diff --git a/source/script/tests/test_posix_s3.sh b/source/script/tests/test_posix_s3.sh index 2274a1f7fe5..d4a03f85817 100755 --- a/source/script/tests/test_posix_s3.sh +++ b/source/script/tests/test_posix_s3.sh @@ -31,12 +31,13 @@ raw="RAW-ACLS RAW-CHKPATH RAW-CLOSE RAW-COMPOSITE RAW-CONTEXT RAW-EAS" raw="$raw RAW-IOCTL RAW-LOCK RAW-MKDIR RAW-MUX RAW-NOTIFY RAW-OPEN RAW-OPLOCK" raw="$raw RAW-QFILEINFO RAW-QFSINFO RAW-READ RAW-RENAME RAW-SEARCH RAW-SEEK" raw="$raw RAW-SFILEINFO RAW-SFILEINFO-BUG RAW-STREAMS RAW-UNLINK RAW-WRITE" +raw="$raw RAW-SAMBA3HIDE RAW-SAMBA3BADPATH" -rpc="RPC-AUTHCONTEXT" +rpc="RPC-AUTHCONTEXT RPC-BINDSAMBA3 RPC-NETLOGSAMBA3 RPC-SAMBA3SESSIONKEY" tests="$base $raw $rpc" -skipped="BASE-CHARSET BASE-DEFER_OPEN BASE-DELAYWRITE BASE-DELETE BASE-OPENATTR BASE-TCONDEV" +skipped="BASE-CHARSET BASE-DEFER_OPEN BASE-DELAYWRITE BASE-OPENATTR BASE-TCONDEV" skipped="$skipped RAW-ACLS RAW-CLOSE RAW-COMPOSITE RAW-CONTEXT RAW-EAS" skipped="$skipped RAW-IOCTL RAW-MKDIR RAW-MUX RAW-NOTIFY RAW-OPEN" skipped="$skipped RAW-QFILEINFO RAW-QFSINFO RAW-RENAME RAW-SEARCH" diff --git a/source/script/tests/test_smbtorture_s3.sh b/source/script/tests/test_smbtorture_s3.sh index d0e15345df8..842d914ecff 100755 --- a/source/script/tests/test_smbtorture_s3.sh +++ b/source/script/tests/test_smbtorture_s3.sh @@ -24,7 +24,7 @@ tests="$tests UNLINK BROWSE ATTR TRANS2 MAXFID TORTURE " tests="$tests OPLOCK1 OPLOCK2 OPLOCK3" tests="$tests DIR DIR1 TCON TCONDEV RW1 RW2 RW3" tests="$tests OPEN XCOPY RENAME DELETE PROPERTIES W2K" -tests="$tests PIPE_NUMBER TCON2 IOCTL CHKPATH FDSESS" +tests="$tests PIPE_NUMBER TCON2 IOCTL CHKPATH FDSESS LOCAL-SUBSTITUTE" skipped1="RANDOMIPC NEGNOWAIT NBENCH ERRMAPEXTRACT TRANS2SCAN NTTRANSSCAN" skipped2="DENY1 DENY2 OPENATTR CASETABLE EATEST" diff --git a/source/services/svc_netlogon.c b/source/services/svc_netlogon.c index 1bbef325ac3..c561870552c 100644 --- a/source/services/svc_netlogon.c +++ b/source/services/svc_netlogon.c @@ -32,7 +32,7 @@ static WERROR netlogon_status( const char *service, SERVICE_STATUS *service_stat service_status->type = 0x20; service_status->controls_accepted = SVCCTL_ACCEPT_NONE; - if ( lp_servicenumber("NETLOGON") != -1 ) { + if ( share_defined("NETLOGON") ) { service_status->state = SVCCTL_RUNNING; service_status->win32_exit_code = WERR_SERVICE_NEVER_STARTED; } @@ -57,7 +57,7 @@ static WERROR netlogon_stop( const char *service, SERVICE_STATUS *service_status static WERROR netlogon_start( const char *service ) { - if ( lp_servicenumber("NETLOGON") == -1 ) + if ( share_defined("NETLOGON") ) return WERR_SERVICE_DISABLED; return WERR_ACCESS_DENIED; diff --git a/source/smbd/blocking.c b/source/smbd/blocking.c index a8db498ef5a..04ab01eb664 100644 --- a/source/smbd/blocking.c +++ b/source/smbd/blocking.c @@ -34,7 +34,7 @@ typedef struct _blocking_lock_record { int lock_num; SMB_BIG_UINT offset; SMB_BIG_UINT count; - uint16 lock_pid; + uint32 lock_pid; enum brl_flavour lock_flav; enum brl_type lock_type; char *inbuf; @@ -74,7 +74,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, files_struct *fsp, int lock_timeout, int lock_num, - uint16 lock_pid, + uint32 lock_pid, enum brl_type lock_type, enum brl_flavour lock_flav, SMB_BIG_UINT offset, SMB_BIG_UINT count) @@ -121,7 +121,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, memcpy(blr->inbuf, inbuf, length); blr->length = length; - br_lck = brl_get_locks(blr->fsp); + br_lck = brl_get_locks(NULL, blr->fsp); if (!br_lck) { free_blocking_lock_record(blr); return False; @@ -136,7 +136,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, PENDING_LOCK, blr->lock_flav, &my_lock_ctx); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); @@ -236,7 +236,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) files_struct *fsp = blr->fsp; uint16 num_ulocks = SVAL(inbuf,smb_vwv6); SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT) 0; - uint16 lock_pid; + uint32 lock_pid; unsigned char locktype = CVAL(inbuf,smb_vwv3); BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; @@ -344,7 +344,7 @@ static BOOL process_lockread(blocking_lock_record *blr) data = smb_buf(outbuf) + 3; status = do_lock_spin(fsp, - SVAL(inbuf,smb_pid), + (uint32)SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, startpos, READ_LOCK, @@ -417,7 +417,7 @@ static BOOL process_lock(blocking_lock_record *blr) errno = 0; status = do_lock_spin(fsp, - SVAL(inbuf,smb_pid), + (uint32)SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, @@ -471,7 +471,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; - uint16 lock_pid; + uint32 lock_pid; BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); char *data; BOOL my_lock_ctx = False; @@ -625,7 +625,7 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp) for(blr = blocking_lock_queue; blr; blr = next) { next = blr->next; if(blr->fsp->fnum == fsp->fnum) { - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); if (br_lck) { DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ @@ -637,7 +637,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); blr->offset, blr->count, blr->lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } @@ -658,7 +658,7 @@ void remove_pending_lock_requests_by_mid(int mid) next = blr->next; if(SVAL(blr->inbuf,smb_mid) == mid) { files_struct *fsp = blr->fsp; - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); if (br_lck) { DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ @@ -670,7 +670,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); blr->offset, blr->count, blr->lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); @@ -754,7 +754,7 @@ void process_blocking_lock_queue(time_t t) fsp->fnum, fsp->fsp_name )); if((blr->expire_time != -1) && (blr->expire_time <= t)) { - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); /* * Lock expired - throw away all previously @@ -771,7 +771,7 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, blr->lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); @@ -780,7 +780,7 @@ void process_blocking_lock_queue(time_t t) } if(!change_to_user(conn,vuid)) { - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); /* * Remove the entry and return an error to the client. @@ -793,7 +793,7 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, blr->lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", @@ -804,7 +804,7 @@ void process_blocking_lock_queue(time_t t) } if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) { - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); /* * Remove the entry and return an error to the client. @@ -817,7 +817,7 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, blr->lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); @@ -834,7 +834,7 @@ void process_blocking_lock_queue(time_t t) */ if(blocking_lock_record_process(blr)) { - struct byte_range_lock *br_lck = brl_get_locks(fsp); + struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); if (br_lck) { brl_remove_pending_lock(br_lck, @@ -843,7 +843,7 @@ void process_blocking_lock_queue(time_t t) blr->offset, blr->count, blr->lock_flav); - byte_range_lock_destructor(br_lck); + TALLOC_FREE(br_lck); } free_blocking_lock_record(blr); diff --git a/source/smbd/change_trust_pw.c b/source/smbd/change_trust_pw.c index 738d12151db..31f03cc7fad 100644 --- a/source/smbd/change_trust_pw.c +++ b/source/smbd/change_trust_pw.c @@ -79,17 +79,19 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", dc_name, nt_errstr(nt_status))); cli_shutdown(cli); + cli = NULL; goto failed; } nt_status = trust_pw_find_change_and_store_it(netlogon_pipe, cli->mem_ctx, domain); cli_shutdown(cli); + cli = NULL; failed: if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n", - timestring(False), domain)); + current_timestring(False), domain)); } else DEBUG(5,("change_trust_account_password: sucess!\n")); diff --git a/source/smbd/conn.c b/source/smbd/conn.c index d857611c355..52182f31294 100644 --- a/source/smbd/conn.c +++ b/source/smbd/conn.c @@ -57,7 +57,7 @@ BOOL conn_snum_used(int snum) { connection_struct *conn; for (conn=Connections;conn;conn=conn->next) { - if (conn->service == snum) { + if (conn->params->service == snum) { return(True); } } @@ -136,8 +136,10 @@ find_again: return NULL; } - if ((conn=TALLOC_ZERO_P(mem_ctx, connection_struct))==NULL) { + if (!(conn=TALLOC_ZERO_P(mem_ctx, connection_struct)) || + !(conn->params = TALLOC_P(mem_ctx, struct share_params))) { DEBUG(0,("talloc_zero() failed!\n")); + TALLOC_FREE(mem_ctx); return NULL; } conn->mem_ctx = mem_ctx; @@ -314,7 +316,7 @@ void msg_force_tdis(int msg_type, struct process_id pid, void *buf, size_t len) for (conn=Connections;conn;conn=next) { next=conn->next; - if (strequal(lp_servicename(conn->service), sharename)) { + if (strequal(lp_servicename(SNUM(conn)), sharename)) { DEBUG(1,("Forcing close of share %s cnum=%d\n", sharename, conn->cnum)); close_cnum(conn, (uint16)-1); diff --git a/source/smbd/connection.c b/source/smbd/connection.c index 07d3181144f..0442a9441ad 100644 --- a/source/smbd/connection.c +++ b/source/smbd/connection.c @@ -83,7 +83,7 @@ BOOL yield_connection(connection_struct *conn, const char *name) struct count_stat { pid_t mypid; int curr_connections; - char *name; + const char *name; BOOL Clear; }; @@ -124,43 +124,55 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u Claim an entry in the connections database. ****************************************************************************/ -BOOL claim_connection(connection_struct *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags) +int count_current_connections( const char *sharename, BOOL clear ) { - struct connections_key key; - struct connections_data crec; - TDB_DATA kbuf, dbuf; - - if (!tdb) - tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR | O_CREAT, 0644); + struct count_stat cs; - if (!tdb) - return False; + cs.mypid = sys_getpid(); + cs.curr_connections = 0; + cs.name = sharename; + cs.Clear = clear; /* - * Enforce the max connections parameter. + * This has a race condition, but locking the chain before hand is worse + * as it leads to deadlock. */ - if (max_connections > 0) { - struct count_stat cs; + if (tdb_traverse(tdb, count_fn, &cs) == -1) { + DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n", + tdb_errorstr(tdb) )); + return False; + } + + return cs.curr_connections; +} - cs.mypid = sys_getpid(); - cs.curr_connections = 0; - cs.name = lp_servicename(SNUM(conn)); - cs.Clear = Clear; +/**************************************************************************** + Claim an entry in the connections database. +****************************************************************************/ - /* - * This has a race condition, but locking the chain before hand is worse - * as it leads to deadlock. - */ +BOOL claim_connection(connection_struct *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags) +{ + struct connections_key key; + struct connections_data crec; + TDB_DATA kbuf, dbuf; - if (tdb_traverse(tdb, count_fn, &cs) == -1) { - DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n", - tdb_errorstr(tdb) )); + if (!tdb) { + if ( (tdb =conn_tdb_ctx()) == NULL ) { return False; } + } + + /* + * Enforce the max connections parameter. + */ - if (cs.curr_connections >= max_connections) { + if (max_connections > 0) { + int curr_connections; + + curr_connections = count_current_connections( lp_servicename(SNUM(conn)), True ); + + if (curr_connections >= max_connections) { DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n", max_connections, name )); return False; @@ -241,3 +253,108 @@ BOOL register_message_flags(BOOL doreg, uint32 msg_flags) SAFE_FREE(dbuf.dptr); return True; } + +/********************************************************************* +*********************************************************************/ + +static TDB_DATA* make_pipe_rec_key( struct pipe_open_rec *prec ) +{ + TDB_DATA *kbuf = NULL; + fstring key_string; + + if ( !prec ) + return NULL; + + if ( (kbuf = TALLOC_P(prec, TDB_DATA)) == NULL ) { + return NULL; + } + + snprintf( key_string, sizeof(key_string), "%s/%d/%d", + prec->name, procid_to_pid(&prec->pid), prec->pnum ); + + if ( (kbuf->dptr = talloc_strdup(prec, key_string)) == NULL ) + return NULL; + + kbuf->dsize = strlen(key_string)+1; + + return kbuf; +} + +/********************************************************************* +*********************************************************************/ + +static void fill_pipe_open_rec( struct pipe_open_rec *prec, smb_np_struct *p ) +{ + prec->pid = pid_to_procid(sys_getpid()); + prec->pnum = p->pnum; + prec->uid = geteuid(); + fstrcpy( prec->name, p->name ); + + return; +} + +/********************************************************************* +*********************************************************************/ + +BOOL store_pipe_opendb( smb_np_struct *p ) +{ + struct pipe_open_rec *prec; + TDB_DATA *key; + TDB_DATA data; + TDB_CONTEXT *pipe_tdb; + BOOL ret = False; + + if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) { + DEBUG(0,("store_pipe_opendb: talloc failed!\n")); + return False; + } + + fill_pipe_open_rec( prec, p ); + if ( (key = make_pipe_rec_key( prec )) == NULL ) { + goto done; + } + + data.dptr = (char*)prec; + data.dsize = sizeof(struct pipe_open_rec); + + if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) { + goto done; + } + + ret = (tdb_store( pipe_tdb, *key, data, TDB_REPLACE ) != -1); + +done: + TALLOC_FREE( prec ); + return ret; +} + +/********************************************************************* +*********************************************************************/ + +BOOL delete_pipe_opendb( smb_np_struct *p ) +{ + struct pipe_open_rec *prec; + TDB_DATA *key; + TDB_CONTEXT *pipe_tdb; + BOOL ret = False; + + if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) { + DEBUG(0,("store_pipe_opendb: talloc failed!\n")); + return False; + } + + fill_pipe_open_rec( prec, p ); + if ( (key = make_pipe_rec_key( prec )) == NULL ) { + goto done; + } + + if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) { + goto done; + } + + ret = (tdb_delete( pipe_tdb, *key ) != -1 ); + +done: + TALLOC_FREE( prec ); + return ret; +} diff --git a/source/smbd/dir.c b/source/smbd/dir.c index 5ba9e1ed575..96e0923dbd0 100644 --- a/source/smbd/dir.c +++ b/source/smbd/dir.c @@ -741,7 +741,7 @@ BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype) static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask) { - mangle_map(filename,True,False,SNUM(conn)); + mangle_map(filename,True,False,conn->params); return mask_match_search(filename,mask,False); } @@ -787,8 +787,9 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fn mask_match_search(filename,mask,False) || mangle_mask_match(conn,filename,mask)) { - if (!mangle_is_8_3(filename, False, SNUM(conn))) - mangle_map(filename,True,False,SNUM(conn)); + if (!mangle_is_8_3(filename, False, conn->params)) + mangle_map(filename,True,False, + conn->params); pstrcpy(fname,filename); *path = 0; @@ -857,17 +858,17 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S /* Pseudo-open the file (note - no fd's created). */ if(S_ISDIR(pst->st_mode)) { - fsp = open_directory(conn, name, pst, + status = open_directory(conn, name, pst, READ_CONTROL_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, /* no create options. */ - NULL); + NULL, &fsp); } else { - fsp = open_file_stat(conn, name, pst); + status = open_file_stat(conn, name, pst, &fsp); } - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { return False; } @@ -920,17 +921,17 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ if(S_ISDIR(pst->st_mode)) { return True; } else { - fsp = open_file_ntcreate(conn, name, pst, + status = open_file_ntcreate(conn, name, pst, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, - &info); + &info, &fsp); } - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { return False; } diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c index 61145fde2f0..260a8dadbd6 100644 --- a/source/smbd/dosmode.c +++ b/source/smbd/dosmode.c @@ -300,8 +300,7 @@ static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_ * are not violating security in doing the setxattr. */ - fsp = open_file_fchmod(conn,path,sbuf); - if (!fsp) + if (!NT_STATUS_IS_OK(open_file_fchmod(conn,path,sbuf,&fsp))) return ret; become_root(); if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) { @@ -518,8 +517,8 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, * holding. We need to review this.... may need to * break batch oplocks open by others. JRA. */ - files_struct *fsp = open_file_fchmod(conn,fname,st); - if (!fsp) + files_struct *fsp; + if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,st,&fsp))) return -1; become_root(); ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode); diff --git a/source/smbd/error.c b/source/smbd/error.c index fa236f0de05..409781eaa94 100644 --- a/source/smbd/error.c +++ b/source/smbd/error.c @@ -24,40 +24,6 @@ extern struct unix_error_map unix_dos_nt_errmap[]; extern uint32 global_client_caps; -/* these can be set by some functions to override the error codes */ -static int override_ERR_class; -static uint32 override_ERR_code; -static NTSTATUS override_ERR_ntstatus; - -/**************************************************************************** - Setting eclass and ecode only and status to NT_STATUS_INVALID forces DOS errors. - Setting status only and eclass and ecode to -1 forces NT errors. -****************************************************************************/ - -void set_saved_error_triple(int eclass, int ecode, NTSTATUS status) -{ - override_ERR_class = eclass; - override_ERR_code = ecode; - override_ERR_ntstatus = status; -} - -void set_saved_ntstatus(NTSTATUS status) -{ - uint8 tmp_eclass; /* Hmmm. override_ERR_class is not uint8... */ - override_ERR_ntstatus = status; - ntstatus_to_dos(status, &tmp_eclass, &override_ERR_code); - override_ERR_class = tmp_eclass; - -} - -/**************************************************************************** - Return the current settings of the error triple. Return True if any are set. -****************************************************************************/ - -NTSTATUS get_saved_ntstatus(void) -{ - return override_ERR_ntstatus; -} /**************************************************************************** Create an error packet from a cached error. @@ -103,6 +69,10 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_s return error_packet(outbuf,eclass,ecode,ntstatus,line,file); } +BOOL use_nt_status(void) +{ + return lp_nt_status_support() && (global_client_caps & CAP_STATUS32); +} /**************************************************************************** Create an error packet. Normally called using the ERROR() macro. @@ -117,18 +87,9 @@ int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, in BOOL force_nt_status = False; BOOL force_dos_status = False; - if (override_ERR_class != SMB_SUCCESS || !NT_STATUS_IS_OK(override_ERR_ntstatus)) { - eclass = override_ERR_class; - ecode = override_ERR_code; - ntstatus = override_ERR_ntstatus; - override_ERR_class = SMB_SUCCESS; - override_ERR_code = 0; - override_ERR_ntstatus = NT_STATUS_OK; - } - if (eclass == (uint8)-1) { force_nt_status = True; - } else if (NT_STATUS_IS_INVALID(ntstatus)) { + } else if (NT_STATUS_IS_DOS(ntstatus)) { force_dos_status = True; } @@ -146,7 +107,10 @@ int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, in nt_errstr(ntstatus))); } else { /* We're returning a DOS error only. */ - if (eclass == 0 && NT_STATUS_V(ntstatus)) { + if (NT_STATUS_IS_DOS(ntstatus)) { + eclass = NT_STATUS_DOS_CLASS(ntstatus); + ecode = NT_STATUS_DOS_CODE(ntstatus); + } else if (eclass == 0 && NT_STATUS_V(ntstatus)) { ntstatus_to_dos(ntstatus, &eclass, &ecode); } diff --git a/source/smbd/fake_file.c b/source/smbd/fake_file.c index b4f1f02b724..7c5eeae5c7d 100644 --- a/source/smbd/fake_file.c +++ b/source/smbd/fake_file.c @@ -101,24 +101,26 @@ enum FAKE_FILE_TYPE is_fake_file(const char *fname) Open a fake quota file with a share mode. ****************************************************************************/ -files_struct *open_fake_file(connection_struct *conn, +NTSTATUS open_fake_file(connection_struct *conn, enum FAKE_FILE_TYPE fake_file_type, const char *fname, - uint32 access_mask) + uint32 access_mask, + files_struct **result) { files_struct *fsp = NULL; + NTSTATUS status; /* access check */ if (current_user.ut.uid != 0) { DEBUG(1,("open_fake_file_shared: access_denied to service[%s] file[%s] user[%s]\n", lp_servicename(SNUM(conn)),fname,conn->user)); - errno = EACCES; - return NULL; + return NT_STATUS_ACCESS_DENIED; + } - fsp = file_new(conn); - if(!fsp) { - return NULL; + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; } DEBUG(5,("open_fake_file_shared: fname = %s, FID = %d, access_mask = 0x%x\n", @@ -128,7 +130,7 @@ files_struct *open_fake_file(connection_struct *conn, fsp->fh->fd = -1; fsp->vuid = current_user.vuid; fsp->fh->pos = -1; - fsp->can_lock = True; /* Should this be true ? */ + fsp->can_lock = False; /* Should this be true ? - No, JRA */ fsp->access_mask = access_mask; string_set(&fsp->fsp_name,fname); @@ -136,11 +138,12 @@ files_struct *open_fake_file(connection_struct *conn, if (fsp->fake_file_handle==NULL) { file_free(fsp); - return NULL; + return NT_STATUS_NO_MEMORY; } conn->num_files_open++; - return fsp; + *result = fsp; + return NT_STATUS_OK; } void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh) diff --git a/source/smbd/filename.c b/source/smbd/filename.c index 6c0f8b77585..1ea5228e919 100644 --- a/source/smbd/filename.c +++ b/source/smbd/filename.c @@ -46,12 +46,13 @@ static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitiv Mangle the 2nd name and check if it is then equal to the first name. ****************************************************************************/ -static BOOL mangled_equal(const char *name1, const char *name2, int snum) +static BOOL mangled_equal(const char *name1, const char *name2, + const struct share_params *p) { pstring tmpname; pstrcpy(tmpname, name2); - mangle_map(tmpname, True, False, snum); + mangle_map(tmpname, True, False, p); return strequal(name1, tmpname); } @@ -189,7 +190,8 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * sensitive then searching won't help. */ - if (conn->case_sensitive && !mangle_is_mangled(name, SNUM(conn)) && !*lp_mangled_map(SNUM(conn))) + if (conn->case_sensitive && !mangle_is_mangled(name, conn->params) && + !*lp_mangled_map(conn->params)) return(False); name_has_wildcard = ms_has_wild(start); @@ -199,7 +201,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * just a component. JRA. */ - if (mangle_is_mangled(start, SNUM(conn))) + if (mangle_is_mangled(start, conn->params)) component_was_mangled = True; /* @@ -318,7 +320,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * purposes. Fix inspired by Thomas Neumann <t.neumann@iku-ag.de>. */ if (!conn->case_preserve || - (mangle_is_8_3(start, False, SNUM(conn)) && + (mangle_is_8_3(start, False, conn->params) && !conn->short_case_preserve)) { strnorm(start, lp_defaultcase(SNUM(conn))); } @@ -328,8 +330,8 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * base of the filename. */ - if (mangle_is_mangled(start, SNUM(conn))) { - mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), SNUM(conn)); + if (mangle_is_mangled(start, conn->params)) { + mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), conn->params); } DEBUG(5,("New file %s\n",start)); @@ -444,7 +446,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name BOOL mangled; long curpos; - mangled = mangle_is_mangled(name, SNUM(conn)); + mangled = mangle_is_mangled(name, conn->params); /* handle null paths */ if (*path == 0) @@ -466,7 +468,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name */ if (mangled && !conn->case_sensitive) { - mangled = !mangle_check_cache( name, maxlength, SNUM(conn)); + mangled = !mangle_check_cache( name, maxlength, conn->params); } /* open the directory */ @@ -495,7 +497,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name * against unmangled name. */ - if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname, conn->case_sensitive)) { + if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ safe_strcpy(name, dname, maxlength); CloseDir(cur_dir); diff --git a/source/smbd/files.c b/source/smbd/files.c index e020d8e13a6..7069818dee4 100644 --- a/source/smbd/files.c +++ b/source/smbd/files.c @@ -59,7 +59,7 @@ static unsigned long get_gen_count(void) Find first available file slot. ****************************************************************************/ -files_struct *file_new(connection_struct *conn) +NTSTATUS file_new(connection_struct *conn, files_struct **result) { int i; static int first_file; @@ -82,14 +82,12 @@ files_struct *file_new(connection_struct *conn) /* TODO: We have to unconditionally return a DOS error here, * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with * NTSTATUS negotiated */ - set_saved_ntstatus(NT_STATUS_TOO_MANY_OPENED_FILES); - return NULL; + return NT_STATUS_TOO_MANY_OPENED_FILES; } fsp = SMB_MALLOC_P(files_struct); if (!fsp) { - set_saved_ntstatus(NT_STATUS_NO_MEMORY); - return NULL; + return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(fsp); @@ -97,8 +95,7 @@ files_struct *file_new(connection_struct *conn) fsp->fh = SMB_MALLOC_P(struct fd_handle); if (!fsp->fh) { SAFE_FREE(fsp); - set_saved_ntstatus(NT_STATUS_NO_MEMORY); - return NULL; + return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(fsp->fh); @@ -131,8 +128,9 @@ files_struct *file_new(connection_struct *conn) if (fsp_fi_cache.fsp == NULL) { ZERO_STRUCT(fsp_fi_cache); } - - return fsp; + + *result = fsp; + return NT_STATUS_OK; } /**************************************************************************** @@ -464,24 +462,16 @@ void file_free(files_struct *fsp) } /**************************************************************************** - Get a fsp from a packet given the offset of a 16 bit fnum. + Get an fsp from a 16 bit fnum. ****************************************************************************/ -files_struct *file_fsp(char *buf, int where) +files_struct *file_fnum(uint16 fnum) { - int fnum, count=0; files_struct *fsp; - - if (chain_fsp) - return chain_fsp; - - if (!buf) - return NULL; - fnum = SVAL(buf, where); + int count=0; for (fsp=Files;fsp;fsp=fsp->next, count++) { if (fsp->fnum == fnum) { - chain_fsp = fsp; if (count > 10) { DLIST_PROMOTE(Files, fsp); } @@ -492,6 +482,29 @@ files_struct *file_fsp(char *buf, int where) } /**************************************************************************** + Get an fsp from a packet given the offset of a 16 bit fnum. +****************************************************************************/ + +files_struct *file_fsp(char *buf, int where) +{ + files_struct *fsp; + + if (chain_fsp) { + return chain_fsp; + } + + if (!buf) { + return NULL; + } + + fsp = file_fnum(SVAL(buf, where)); + if (fsp) { + chain_fsp = fsp; + } + return fsp; +} + +/**************************************************************************** Reset the chained fsp - done at the start of a packet reply. ****************************************************************************/ @@ -504,15 +517,19 @@ void file_chain_reset(void) Duplicate the file handle part for a DOS or FCB open. ****************************************************************************/ -files_struct *dup_file_fsp(files_struct *fsp, +NTSTATUS dup_file_fsp(files_struct *fsp, uint32 access_mask, uint32 share_access, - uint32 create_options) + uint32 create_options, + files_struct **result) { - files_struct *dup_fsp = file_new(fsp->conn); + NTSTATUS status; + files_struct *dup_fsp; - if (!dup_fsp) { - return NULL; + status = file_new(fsp->conn, &dup_fsp); + + if (!NT_STATUS_IS_OK(status)) { + return status; } SAFE_FREE(dup_fsp->fh); @@ -547,5 +564,6 @@ files_struct *dup_file_fsp(files_struct *fsp, dup_fsp->aio_write_behind = fsp->aio_write_behind; string_set(&dup_fsp->fsp_name,fsp->fsp_name); - return dup_fsp; + *result = dup_fsp; + return NT_STATUS_OK; } diff --git a/source/smbd/lanman.c b/source/smbd/lanman.c index e4531d8ae98..2d6db8f2a30 100644 --- a/source/smbd/lanman.c +++ b/source/smbd/lanman.c @@ -72,7 +72,11 @@ static int CopyExpanded(connection_struct *conn, StrnCpy(buf,src,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf,sizeof(buf)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + buf, sizeof(buf)); l = push_ascii(*dst,buf,*n, STR_TERMINATE); (*dst) += l; (*n) -= l; @@ -99,7 +103,11 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s) } StrnCpy(buf,s,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf,sizeof(buf)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + buf, sizeof(buf)); return strlen(buf) + 1; } @@ -111,7 +119,11 @@ static char *Expand(connection_struct *conn, int snum, char *s) } StrnCpy(buf,s,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf,sizeof(buf)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + buf, sizeof(buf)); return &buf[0]; } @@ -593,7 +605,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */ fstrcpy(location, "\\\\%L\\print$\\WIN40\\0"); - standard_sub_basic( "", location, sizeof(location)-1 ); + standard_sub_basic( "", "", location, sizeof(location)-1 ); PACKS(desc,"z", location); /* share to retrieve files */ PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */ @@ -2534,7 +2546,6 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); uint32 jobid; - int snum; fstring sharename; int uLevel = SVAL(p,2); int function = SVAL(p,4); @@ -2548,9 +2559,9 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha return False; } - if ( (snum = lp_servicenumber(sharename)) == -1 ) { - DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n", - sharename)); + if (!share_defined(sharename)) { + DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n", + sharename)); return False; } @@ -2573,14 +2584,14 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha /* change job place in the queue, data gives the new place */ place = SVAL(data,0); - if (print_job_set_place(snum, jobid, place)) { + if (print_job_set_place(sharename, jobid, place)) { errcode=NERR_Success; } break; case 0xb: /* change print job name, data gives the name */ - if (print_job_set_name(snum, jobid, data)) { + if (print_job_set_name(sharename, jobid, data)) { errcode=NERR_Success; } break; @@ -2701,7 +2712,11 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par SIVAL(p,6,0); } else { SIVAL(p,6,PTR_DIFF(p2,*rdata)); - standard_sub_conn(conn,comment,sizeof(comment)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + comment, sizeof(comment)); StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0)); p2 = skip_string(p2,1); } @@ -3126,8 +3141,12 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SSVALS(p,102,-1); /* bad_pw_count */ SSVALS(p,104,-1); /* num_logons */ SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */ - pstrcpy(p2,"\\\\%L"); - standard_sub_conn(conn, p2,0); + { + pstring tmp; + pstrcpy(tmp, "\\\\%L"); + standard_sub_basic("", "", tmp, sizeof(tmp)); + pstrcpy(p2, tmp); + } p2 = skip_string(p2,1); SSVAL(p,110,49); /* country_code */ SSVAL(p,112,860); /* code page */ diff --git a/source/smbd/mangle.c b/source/smbd/mangle.c index ed69a6210e8..16f99636eb5 100644 --- a/source/smbd/mangle.c +++ b/source/smbd/mangle.c @@ -81,22 +81,24 @@ void mangle_change_to_posix(void) /* see if a filename has come out of our mangling code */ -BOOL mangle_is_mangled(const char *s, int snum) +BOOL mangle_is_mangled(const char *s, const struct share_params *p) { - return mangle_fns->is_mangled(s, snum); + return mangle_fns->is_mangled(s, p); } /* see if a filename matches the rules of a 8.3 filename */ -BOOL mangle_is_8_3(const char *fname, BOOL check_case, int snum) +BOOL mangle_is_8_3(const char *fname, BOOL check_case, + const struct share_params *p) { - return mangle_fns->is_8_3(fname, check_case, False, snum); + return mangle_fns->is_8_3(fname, check_case, False, p); } -BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case, int snum) +BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case, + const struct share_params *p) { - return mangle_fns->is_8_3(fname, check_case, True, snum); + return mangle_fns->is_8_3(fname, check_case, True, p); } /* @@ -105,20 +107,22 @@ BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case, int snum) looking for a matching name if it doesn't. It should succeed most of the time or there will be a huge performance penalty */ -BOOL mangle_check_cache(char *s, size_t maxlen, int snum) +BOOL mangle_check_cache(char *s, size_t maxlen, + const struct share_params *p) { - return mangle_fns->check_cache(s, maxlen, snum); + return mangle_fns->check_cache(s, maxlen, p); } /* map a long filename to a 8.3 name. */ -void mangle_map(pstring OutName, BOOL need83, BOOL cache83, int snum) +void mangle_map(pstring OutName, BOOL need83, BOOL cache83, + const struct share_params *p) { /* name mangling can be disabled for speed, in which case we just truncate the string */ - if (!lp_manglednames(snum)) { + if (!lp_manglednames(p)) { if (need83) { string_truncate(OutName, 12); } @@ -126,6 +130,6 @@ void mangle_map(pstring OutName, BOOL need83, BOOL cache83, int snum) } /* invoke the inane "mangled map" code */ - mangle_map_filename(OutName, snum); - mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(snum), snum); + mangle_map_filename(OutName, p); + mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(p->service), p); } diff --git a/source/smbd/mangle_hash.c b/source/smbd/mangle_hash.c index 2092f430c07..320e31ab679 100644 --- a/source/smbd/mangle_hash.c +++ b/source/smbd/mangle_hash.c @@ -275,14 +275,15 @@ done: return ret; } -static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum) +static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, + const struct share_params *p) { const char *f; smb_ucs2_t *ucs2name; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; size_t size; - magic_char = lp_magicchar(snum); + magic_char = lp_magicchar(p); if (!fname || !*fname) return False; @@ -360,11 +361,11 @@ static void init_chartest( void ) * * ************************************************************************** ** */ -static BOOL is_mangled(const char *s, int snum) +static BOOL is_mangled(const char *s, const struct share_params *p) { char *magic; - magic_char = lp_magicchar(snum); + magic_char = lp_magicchar(p); if( !ct_initialized ) init_chartest(); @@ -460,13 +461,13 @@ static void cache_mangled_name( const char mangled_name[13], char *raw_name ) * ************************************************************************** ** */ -static BOOL check_cache( char *s, size_t maxlen, int snum ) +static BOOL check_cache( char *s, size_t maxlen, const struct share_params *p ) { TDB_DATA data_val; char *ext_start = NULL; char *saved_ext = NULL; - magic_char = lp_magicchar(snum); + magic_char = lp_magicchar(p); /* If the cache isn't initialized, give up. */ if( !tdb_mangled_cache ) @@ -606,10 +607,11 @@ static void to_8_3(char *s, int default_case) * **************************************************************************** */ -static void name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum) +static void name_map(char *OutName, BOOL need83, BOOL cache83, + int default_case, const struct share_params *p) { smb_ucs2_t *OutName_ucs2; - magic_char = lp_magicchar(snum); + magic_char = lp_magicchar(p); DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName, need83 ? "True" : "False", cache83 ? "True" : "False")); diff --git a/source/smbd/mangle_hash2.c b/source/smbd/mangle_hash2.c index 0a161c9e769..d1ce1af9eac 100644 --- a/source/smbd/mangle_hash2.c +++ b/source/smbd/mangle_hash2.c @@ -101,7 +101,7 @@ static unsigned mangle_prefix; hashing the resulting cache entry to match the known hash */ static char **prefix_cache; -static u32 *prefix_cache_hashes; +static unsigned int *prefix_cache_hashes; /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -119,10 +119,10 @@ static const char *reserved_names[] = this hash needs to be fast with a low collision rate (what hash doesn't?) */ -static u32 mangle_hash(const char *key, unsigned int length) +static unsigned int mangle_hash(const char *key, unsigned int length) { - u32 value; - u32 i; + unsigned int value; + unsigned int i; fstring str; /* we have to uppercase here to ensure that the mangled name @@ -139,8 +139,8 @@ static u32 mangle_hash(const char *key, unsigned int length) /* Set the initial value from the key size. */ for (value = FNV1_INIT, i=0; i < length; i++) { - value *= (u32)FNV1_PRIME; - value ^= (u32)(str[i]); + value *= (unsigned int)FNV1_PRIME; + value ^= (unsigned int)(str[i]); } /* note that we force it to a 31 bit hash, to keep within the limits @@ -162,7 +162,7 @@ static BOOL cache_init(void) return False; } - prefix_cache_hashes = SMB_CALLOC_ARRAY(u32, MANGLE_CACHE_SIZE); + prefix_cache_hashes = SMB_CALLOC_ARRAY(unsigned int, MANGLE_CACHE_SIZE); if (!prefix_cache_hashes) { return False; } @@ -173,7 +173,7 @@ static BOOL cache_init(void) /* insert an entry into the prefix cache. The string might not be null terminated */ -static void cache_insert(const char *prefix, int length, u32 hash) +static void cache_insert(const char *prefix, int length, unsigned int hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -188,7 +188,7 @@ static void cache_insert(const char *prefix, int length, u32 hash) /* lookup an entry in the prefix cache. Return NULL if not found. */ -static const char *cache_lookup(u32 hash) +static const char *cache_lookup(unsigned int hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -268,7 +268,7 @@ static BOOL is_mangled_component(const char *name, size_t len) directory separators. It should return true if any component is mangled */ -static BOOL is_mangled(const char *name, int snum) +static BOOL is_mangled(const char *name, const struct share_params *parm) { const char *p; const char *s; @@ -293,7 +293,7 @@ static BOOL is_mangled(const char *name, int snum) simplifies things greatly (it means that we know the string won't get larger when converted from UNIX to DOS formats) */ -static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, int snum) +static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, const struct share_params *p) { int len, i; char *dot_p; @@ -370,15 +370,15 @@ static void mangle_reset(void) try to find a 8.3 name in the cache, and if found then replace the string with the original long name. */ -static BOOL check_cache(char *name, size_t maxlen, int snum) +static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p) { - u32 hash, multiplier; + unsigned int hash, multiplier; unsigned int i; const char *prefix; char extension[4]; /* make sure that this is a mangled name from this cache */ - if (!is_mangled(name, snum)) { + if (!is_mangled(name, p)) { M_DEBUG(10,("check_cache: %s -> not mangled\n", name)); return False; } @@ -386,7 +386,7 @@ static BOOL check_cache(char *name, size_t maxlen, int snum) /* we need to extract the hash from the 8.3 name */ hash = base_reverse[(unsigned char)name[7]]; for (multiplier=36, i=5;i>=mangle_prefix;i--) { - u32 v = base_reverse[(unsigned char)name[i]]; + unsigned int v = base_reverse[(unsigned char)name[i]]; hash += multiplier * v; multiplier *= 36; } @@ -510,21 +510,21 @@ static BOOL is_legal_name(const char *name) the name parameter must be able to hold 13 bytes */ -static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, int snum) +static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, const struct share_params *p) { char *dot_p; char lead_chars[7]; char extension[4]; unsigned int extension_length, i; unsigned int prefix_len; - u32 hash, v; + unsigned int hash, v; char new_name[13]; /* reserved names are handled specially */ if (!is_reserved_name(name)) { /* if the name is already a valid 8.3 name then we don't need to do anything */ - if (is_8_3(name, False, False, snum)) { + if (is_8_3(name, False, False, p)) { return; } @@ -724,22 +724,22 @@ struct mangle_fns *mangle_hash2_init(void) static void posix_mangle_reset(void) {;} -static BOOL posix_is_mangled(const char *s, int snum) +static BOOL posix_is_mangled(const char *s, const struct share_params *p) { return False; } -static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum) +static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, const struct share_params *p) { return False; } -static BOOL posix_check_cache( char *s, size_t maxlen, int snum ) +static BOOL posix_check_cache( char *s, size_t maxlen, const struct share_params *p ) { return False; } -static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum) +static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, const struct share_params *p) { if (need83) { memset(OutName, '\0', 13); diff --git a/source/smbd/mangle_map.c b/source/smbd/mangle_map.c index 9e798fd41b4..c5803786ec0 100644 --- a/source/smbd/mangle_map.c +++ b/source/smbd/mangle_map.c @@ -201,11 +201,11 @@ static void mangled_map(char *s, const char *MangledMap) front end routine to the mangled map code personally I think that the whole idea of "mangled map" is completely bogus */ -void mangle_map_filename(fstring fname, int snum) +void mangle_map_filename(fstring fname, const struct share_params *p) { char *map; - map = lp_mangled_map(snum); + map = lp_mangled_map(p); if (!map || !*map) return; mangled_map(fname, map); diff --git a/source/smbd/message.c b/source/smbd/message.c index 31dab458443..fd53e60c141 100644 --- a/source/smbd/message.c +++ b/source/smbd/message.c @@ -101,7 +101,8 @@ static void msg_deliver(void) pstrcpy(s,lp_msg_command()); pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,NULL,sizeof(alpha_msgfrom))); pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,NULL,sizeof(alpha_msgto))); - standard_sub_basic(current_user_info.smb_name, s, sizeof(s)); + standard_sub_basic(current_user_info.smb_name, + current_user_info.domain, s, sizeof(s)); pstring_sub(s,"%s",name); smbrun(s,NULL); } diff --git a/source/smbd/msdfs.c b/source/smbd/msdfs.c index b22b5674d6f..69da4194fda 100644 --- a/source/smbd/msdfs.c +++ b/source/smbd/msdfs.c @@ -135,7 +135,6 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) ZERO_STRUCTP(conn); - conn->service = snum; pstrcpy(connpath, path); pstring_sub(connpath , "%S", lp_servicename(snum)); @@ -145,6 +144,13 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) DEBUG(0,("talloc_init(connection_struct) failed!\n")); return False; } + + if (!(conn->params = TALLOC_P(conn->mem_ctx, struct share_params))) { + DEBUG(0, ("TALLOC failed\n")); + return False; + } + + conn->params->service = snum; set_conn_connectpath(conn, connpath); diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c index aa6f79e1657..0b1bdcadbb1 100644 --- a/source/smbd/nttrans.c +++ b/source/smbd/nttrans.c @@ -321,7 +321,7 @@ static int nt_open_pipe(char *fname, connection_struct *conn, smb_np_struct *p = NULL; uint16 vuid = SVAL(inbuf, smb_uid); int i; - + DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname)); /* See if it is one we want to handle. */ @@ -350,6 +350,12 @@ static int nt_open_pipe(char *fname, connection_struct *conn, return(ERROR_DOS(ERRSRV,ERRnofids)); } + /* TODO: Add pipe to db */ + + if ( !store_pipe_opendb( p ) ) { + DEBUG(3,("nt_open_pipe: failed to store %s pipe open.\n", fname)); + } + *ppnum = p->pnum; return 0; } @@ -412,10 +418,14 @@ int reply_ntcreate_and_X_quota(connection_struct *conn, int result; char *p; uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); - files_struct *fsp = open_fake_file(conn, fake_file_type, fname, desired_access); + files_struct *fsp; + NTSTATUS status; - if (!fsp) { - return ERROR_NT(NT_STATUS_ACCESS_DENIED); + status = open_fake_file(conn, fake_file_type, fname, desired_access, + &fsp); + + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); } set_message(outbuf,34,0,True); @@ -688,18 +698,18 @@ create_options = 0x%x root_dir_fid = 0x%x\n", return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - fsp = open_directory(conn, fname, &sbuf, + status = open_directory(conn, fname, &sbuf, access_mask, share_access, create_disposition, create_options, - &info); + &info, &fsp); restore_case_semantics(conn, file_attributes); - if(!fsp) { + if(!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return ERROR_NT(status); } } else { /* @@ -719,15 +729,15 @@ create_options = 0x%x root_dir_fid = 0x%x\n", * before issuing an oplock break request to * our client. JRA. */ - fsp = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,fname,&sbuf, access_mask, share_access, create_disposition, create_options, file_attributes, oplock_request, - &info); - if (!fsp) { + &info, &fsp); + if (!NT_STATUS_IS_OK(status)) { /* We cheat here. There are two cases we * care about. One is a directory rename, * where the NT client will attempt to @@ -747,7 +757,8 @@ create_options = 0x%x root_dir_fid = 0x%x\n", * we handle in the open_file_stat case. JRA. */ - if(errno == EISDIR) { + if (NT_STATUS_EQUAL(status, + NT_STATUS_FILE_IS_A_DIRECTORY)) { /* * Fail the open if it was explicitly a non-directory file. @@ -760,17 +771,17 @@ create_options = 0x%x root_dir_fid = 0x%x\n", } oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, + status = open_directory(conn, fname, &sbuf, access_mask, share_access, create_disposition, create_options, - &info); + &info, &fsp); - if(!fsp) { + if(!NT_STATUS_IS_OK(status)) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return ERROR_NT(status); } } else { @@ -780,7 +791,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", /* We have re-scheduled this call. */ return -1; } - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return ERROR_NT(status); } } } @@ -1331,16 +1342,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * CreateDirectory() call. */ - fsp = open_directory(conn, fname, &sbuf, + status = open_directory(conn, fname, &sbuf, access_mask, share_access, create_disposition, create_options, - &info); - if(!fsp) { + &info, &fsp); + if(!NT_STATUS_IS_OK(status)) { talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return ERROR_NT(status); } } else { @@ -1349,17 +1360,18 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * Ordinary file case. */ - fsp = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,fname,&sbuf, access_mask, share_access, create_disposition, create_options, file_attributes, oplock_request, - &info); + &info, &fsp); - if (!fsp) { - if(errno == EISDIR) { + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, + NT_STATUS_FILE_IS_A_DIRECTORY)) { /* * Fail the open if it was explicitly a non-directory file. @@ -1371,16 +1383,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } oplock_request = 0; - fsp = open_directory(conn, fname, &sbuf, + status = open_directory(conn, fname, &sbuf, access_mask, share_access, create_disposition, create_options, - &info); - if(!fsp) { + &info, &fsp); + if(!NT_STATUS_IS_OK(status)) { talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return ERROR_NT(status); } } else { talloc_destroy(ctx); @@ -1389,7 +1401,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /* We have re-scheduled this call. */ return -1; } - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); + return ERROR_NT(status); } } } @@ -1655,39 +1667,29 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname)); - fsp1 = open_file_ntcreate(conn,oldname,&sbuf1, + status = open_file_ntcreate(conn,oldname,&sbuf1, FILE_READ_DATA, /* Read-only. */ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, /* No create options. */ FILE_ATTRIBUTE_NORMAL, NO_OPLOCK, - &info); + &info, &fsp1); - if (!fsp1) { - status = get_saved_ntstatus(); - if (NT_STATUS_IS_OK(status)) { - status = NT_STATUS_ACCESS_DENIED; - } - set_saved_ntstatus(NT_STATUS_OK); + if (!NT_STATUS_IS_OK(status)) { return status; } - fsp2 = open_file_ntcreate(conn,newname,&sbuf2, - FILE_WRITE_DATA, /* Write-only. */ + status = open_file_ntcreate(conn,newname,&sbuf2, + FILE_WRITE_DATA, /* Read-only. */ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_CREATE, 0, /* No create options. */ fattr, NO_OPLOCK, - &info); + &info, &fsp2); - if (!fsp2) { - status = get_saved_ntstatus(); - if (NT_STATUS_IS_OK(status)) { - status = NT_STATUS_ACCESS_DENIED; - } - set_saved_ntstatus(NT_STATUS_OK); + if (!NT_STATUS_IS_OK(status)) { close_file(fsp1,ERROR_CLOSE); return status; } @@ -2389,7 +2391,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, return ERROR_NT(NT_STATUS_INVALID_HANDLE); } - /* the NULL pointer cheking for fsp->fake_file_handle->pd + /* the NULL pointer checking for fsp->fake_file_handle->pd * is done by CHECK_NTQUOTA_HANDLE_OK() */ qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->pd; diff --git a/source/smbd/open.c b/source/smbd/open.c index 832a8df7559..7c04cdbe7cc 100644 --- a/source/smbd/open.c +++ b/source/smbd/open.c @@ -38,24 +38,29 @@ struct deferred_open_record { fd support routines - attempt to do a dos_open. ****************************************************************************/ -static int fd_open(struct connection_struct *conn, +static BOOL fd_open(struct connection_struct *conn, const char *fname, + files_struct *fsp, int flags, mode_t mode) { - int fd; + int sav; + #ifdef O_NOFOLLOW if (!lp_symlinks(SNUM(conn))) { flags |= O_NOFOLLOW; } #endif - fd = SMB_VFS_OPEN(conn,fname,flags,mode); + fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode); + sav = errno; - DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, - flags, (int)mode, fd, (fd == -1) ? strerror(errno) : "" )); + DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", + fname, flags, (int)mode, fsp->fh->fd, + (fsp->fh->fd == -1) ? strerror(errno) : "" )); - return fd; + errno = sav; + return fsp->fh->fd != -1; } /**************************************************************************** @@ -179,7 +184,7 @@ void change_owner_to_parent(connection_struct *conn, Open a file. ****************************************************************************/ -static BOOL open_file(files_struct *fsp, +static NTSTATUS open_file(files_struct *fsp, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, @@ -210,7 +215,7 @@ static BOOL open_file(files_struct *fsp, /* It's a read-only share - fail if we wanted to write. */ if(accmode != O_RDONLY) { DEBUG(3,("Permission denied opening %s\n",fname)); - return False; + return NT_STATUS_ACCESS_DENIED; } else if(flags & O_CREAT) { /* We don't want to write - but we must make sure that O_CREAT doesn't create the file if we have write @@ -265,17 +270,15 @@ static BOOL open_file(files_struct *fsp, /* Don't create files with Microsoft wildcard characters. */ if ((local_flags & O_CREAT) && !file_existed && ms_has_wild(fname)) { - set_saved_ntstatus(NT_STATUS_OBJECT_NAME_INVALID); - return False; + return NT_STATUS_OBJECT_NAME_INVALID; } /* Actually do the open */ - fsp->fh->fd = fd_open(conn, fname, local_flags, unx_mode); - if (fsp->fh->fd == -1) { + if (!fd_open(conn, fname, fsp, local_flags, unx_mode)) { DEBUG(3,("Error opening file %s (%s) (local_flags=%d) " "(flags=%d)\n", fname,strerror(errno),local_flags,flags)); - return False; + return map_nt_error_from_unix(errno); } /* Inherit the ACL if the file was created. */ @@ -303,8 +306,9 @@ static BOOL open_file(files_struct *fsp, /* For a non-io open, this stat failing means file not found. JRA */ if (ret == -1) { + NTSTATUS status = map_nt_error_from_unix(errno); fd_close(conn, fsp); - return False; + return status; } } @@ -317,7 +321,7 @@ static BOOL open_file(files_struct *fsp, if(S_ISDIR(psbuf->st_mode)) { fd_close(conn, fsp); errno = EISDIR; - return False; + return NT_STATUS_FILE_IS_A_DIRECTORY; } fsp->mode = psbuf->st_mode; @@ -351,7 +355,7 @@ static BOOL open_file(files_struct *fsp, conn->num_files_open + 1)); errno = 0; - return True; + return NT_STATUS_OK; } /******************************************************************* @@ -894,8 +898,8 @@ static files_struct *fcb_or_dos_open(connection_struct *conn, } /* We need to duplicate this fsp. */ - dup_fsp = dup_file_fsp(fsp, access_mask, share_access, create_options); - if (!dup_fsp) { + if (!NT_STATUS_IS_OK(dup_file_fsp(fsp, access_mask, share_access, + create_options, &dup_fsp))) { return NULL; } @@ -1081,7 +1085,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, struct timeval requ Open a file with a share mode. ****************************************************************************/ -files_struct *open_file_ntcreate(connection_struct *conn, +NTSTATUS open_file_ntcreate(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */ @@ -1091,7 +1095,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, uint32 new_dos_attributes, /* attributes used for new file. */ int oplock_request, /* internal Samba oplock codes. */ /* Information (FILE_EXISTS etc.) */ - int *pinfo) + int *pinfo, + files_struct **result) { int flags=0; int flags2=0; @@ -1099,7 +1104,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, BOOL def_acl = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; - BOOL fsp_open = False; + NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; files_struct *fsp = NULL; mode_t new_unx_mode = (mode_t)0; mode_t unx_mode = (mode_t)0; @@ -1123,7 +1128,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname)); - return print_fsp_open(conn, fname); + return print_fsp_open(conn, fname, &fsp); } /* We add aARCH to this as this mode is only used if the file is @@ -1162,7 +1167,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, } if (!check_name(fname,conn)) { - return NULL; + return map_nt_error_from_unix(errno); } new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; @@ -1181,11 +1186,12 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) { /* OS/2 Workplace shell fix may be main code stream in a later * release. */ - set_saved_error_triple(ERRDOS, ERRcannotopen, - NT_STATUS_OBJECT_NAME_NOT_FOUND); DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not " "supported.\n")); - return NULL; + if (use_nt_status()) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + return NT_STATUS_DOS(ERRDOS, ERRcannotopen); } switch( create_disposition ) { @@ -1213,9 +1219,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: FILE_OPEN " "requested for file %s and file " "doesn't exist.\n", fname )); - set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); errno = ENOENT; - return NULL; + return NT_STATUS_OBJECT_NAME_NOT_FOUND; } break; @@ -1226,9 +1231,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE " "requested for file %s and file " "doesn't exist.\n", fname )); - set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); errno = ENOENT; - return NULL; + return NT_STATUS_OBJECT_NAME_NOT_FOUND; } flags2 |= O_TRUNC; break; @@ -1245,7 +1249,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, } else { errno = EEXIST; } - return NULL; + return map_nt_error_from_unix(errno); } flags2 |= (O_CREAT|O_EXCL); break; @@ -1257,8 +1261,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, break; default: - set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); - return NULL; + return NT_STATUS_INVALID_PARAMETER; } /* We only care about matching attributes on file exists and @@ -1277,7 +1280,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, (unsigned int)psbuf->st_mode, (unsigned int)unx_mode )); errno = EACCES; - return NULL; + return NT_STATUS_ACCESS_DENIED; } } @@ -1334,14 +1337,13 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: write access requested for " "file %s on read only %s\n", fname, !CAN_WRITE(conn) ? "share" : "file" )); - set_saved_ntstatus(NT_STATUS_ACCESS_DENIED); errno = EACCES; - return NULL; + return NT_STATUS_ACCESS_DENIED; } - fsp = file_new(conn); - if(!fsp) { - return NULL; + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; } fsp->dev = psbuf->st_dev; @@ -1367,8 +1369,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (lck == NULL) { file_free(fsp); DEBUG(0, ("Could not get share mode lock\n")); - set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } /* First pass - send break only on batch oplocks. */ @@ -1376,7 +1377,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, schedule_defer_open(lck, request_time); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } status = open_mode_check(conn, fname, lck, @@ -1390,16 +1391,15 @@ files_struct *open_file_ntcreate(connection_struct *conn, schedule_defer_open(lck, request_time); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } } if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { /* DELETE_PENDING is not deferred for a second */ - set_saved_ntstatus(status); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return status; } if (!NT_STATUS_IS_OK(status)) { @@ -1424,7 +1424,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, *pinfo = FILE_WAS_OPENED; } conn->num_files_open++; - return fsp_dup; + *result = fsp_dup; + return NT_STATUS_OK; } } @@ -1449,13 +1450,13 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(4,("open_file_ntcreate : share_mode deny - " "calling open_file with flags=0x%X " - "flags2=0x%X mode=0%o returned %d\n", + "flags2=0x%X mode=0%o returned %s\n", flags, (flags2&~(O_TRUNC|O_CREAT)), - (unsigned int)unx_mode, (int)fsp_open )); + (unsigned int)unx_mode, nt_errstr(fsp_open))); - if (!fsp_open && errno) { + if (!NT_STATUS_IS_OK(fsp_open) && errno) { /* Default error. */ - set_saved_ntstatus(NT_STATUS_ACCESS_DENIED); + status = NT_STATUS_ACCESS_DENIED; } /* @@ -1471,7 +1472,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, /* this is a hack to speed up torture tests in 'make test' */ - timeout_usecs = lp_parm_int(conn->service, + timeout_usecs = lp_parm_int(SNUM(conn), "smbd","sharedelay", SHARING_VIOLATION_USEC_WAIT); @@ -1502,16 +1503,16 @@ files_struct *open_file_ntcreate(connection_struct *conn, } TALLOC_FREE(lck); - if (fsp_open) { + if (NT_STATUS_IS_OK(fsp_open)) { fd_close(conn, fsp); /* * We have detected a sharing violation here * so return the correct error code */ - set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); + status = NT_STATUS_SHARING_VIOLATION; } file_free(fsp); - return NULL; + return status; } /* @@ -1542,12 +1543,12 @@ files_struct *open_file_ntcreate(connection_struct *conn, fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, access_mask); - if (!fsp_open) { + if (!NT_STATUS_IS_OK(fsp_open)) { if (lck != NULL) { TALLOC_FREE(lck); } file_free(fsp); - return NULL; + return fsp_open; } if (!file_existed) { @@ -1578,8 +1579,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); fd_close(conn, fsp); file_free(fsp); - set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } status = open_mode_check(conn, fname, lck, @@ -1606,7 +1606,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, defer_open(lck, request_time, timeval_zero(), &state); TALLOC_FREE(lck); - return NULL; + return status; } /* @@ -1642,10 +1642,11 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { + status = map_nt_error_from_unix(errno); TALLOC_FREE(lck); fd_close(conn,fsp); file_free(fsp); - return NULL; + return status; } } @@ -1692,16 +1693,15 @@ files_struct *open_file_ntcreate(connection_struct *conn, /* Handle strange delete on close create semantics. */ if (create_options & FILE_DELETE_ON_CLOSE) { - NTSTATUS result = can_set_delete_on_close(fsp, True, new_dos_attributes); + status = can_set_delete_on_close(fsp, True, new_dos_attributes); - if (!NT_STATUS_IS_OK(result)) { + if (!NT_STATUS_IS_OK(status)) { /* Remember to delete the mode we just added. */ del_share_mode(lck, fsp); TALLOC_FREE(lck); fd_close(conn,fsp); file_free(fsp); - set_saved_ntstatus(result); - return NULL; + return status; } /* Note that here we set the *inital* delete on close flag, not the regular one. */ @@ -1770,31 +1770,32 @@ files_struct *open_file_ntcreate(connection_struct *conn, conn->num_files_open++; - return fsp; + *result = fsp; + return NT_STATUS_OK; } /**************************************************************************** Open a file for for write to ensure that we can fchmod it. ****************************************************************************/ -files_struct *open_file_fchmod(connection_struct *conn, const char *fname, - SMB_STRUCT_STAT *psbuf) +NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, + SMB_STRUCT_STAT *psbuf, files_struct **result) { files_struct *fsp = NULL; - BOOL fsp_open; + NTSTATUS status; if (!VALID_STAT(*psbuf)) { - return NULL; + return NT_STATUS_INVALID_PARAMETER; } - fsp = file_new(conn); - if(!fsp) { - return NULL; + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; } /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ - fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA); + status = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA); /* * This is not a user visible file open. @@ -1802,12 +1803,13 @@ files_struct *open_file_fchmod(connection_struct *conn, const char *fname, * the conn->num_files_open. */ - if (!fsp_open) { + if (!NT_STATUS_IS_OK(status)) { file_free(fsp); - return NULL; + return status; } - return fsp; + *result = fsp; + return NT_STATUS_OK; } /**************************************************************************** @@ -1825,14 +1827,15 @@ int close_file_fchmod(files_struct *fsp) Open a directory from an NT SMB call. ****************************************************************************/ -files_struct *open_directory(connection_struct *conn, +NTSTATUS open_directory(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask, uint32 share_access, uint32 create_disposition, uint32 create_options, - int *pinfo) + int *pinfo, + files_struct **result) { files_struct *fsp = NULL; BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; @@ -1852,8 +1855,7 @@ files_struct *open_directory(connection_struct *conn, if (is_ntfs_stream_name(fname)) { DEBUG(0,("open_directory: %s is a stream name!\n", fname )); - set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY); - return NULL; + return NT_STATUS_NOT_A_DIRECTORY; } switch( create_disposition ) { @@ -1864,8 +1866,7 @@ files_struct *open_directory(connection_struct *conn, DEBUG(5,("open_directory: FILE_OPEN requested " "for directory %s and it doesn't " "exist.\n", fname )); - set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); - return NULL; + return NT_STATUS_OBJECT_NAME_NOT_FOUND; } info = FILE_WAS_OPENED; break; @@ -1877,9 +1878,12 @@ files_struct *open_directory(connection_struct *conn, DEBUG(5,("open_directory: FILE_CREATE " "requested for directory %s and it " "already exists.\n", fname )); - set_saved_error_triple(ERRDOS, ERRfilexists, - NT_STATUS_OBJECT_NAME_COLLISION); - return NULL; + if (use_nt_status()) { + return NT_STATUS_OBJECT_NAME_COLLISION; + } else { + return NT_STATUS_DOS(ERRDOS, + ERRfilexists); + } } create_dir = True; info = FILE_WAS_CREATED; @@ -1903,8 +1907,7 @@ files_struct *open_directory(connection_struct *conn, DEBUG(5,("open_directory: invalid create_disposition " "0x%x for directory %s\n", (unsigned int)create_disposition, fname)); - set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); - return NULL; + return NT_STATUS_INVALID_PARAMETER; } if (create_dir) { @@ -1921,27 +1924,26 @@ files_struct *open_directory(connection_struct *conn, "Error was %s\n", fname, strerror(errno) )); /* Ensure we return the correct NT status to the * client. */ - set_saved_error_triple(0, 0, status); - return NULL; + return status; } /* Ensure we're checking for a symlink here.... */ /* We don't want to get caught by a symlink racer. */ if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { - return NULL; + return map_nt_error_from_unix(errno); } if(!S_ISDIR(psbuf->st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - return NULL; + return NT_STATUS_NOT_A_DIRECTORY; } } - fsp = file_new(conn); - if(!fsp) { - return NULL; + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; } /* @@ -1953,7 +1955,7 @@ files_struct *open_directory(connection_struct *conn, fsp->dev = psbuf->st_dev; fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; - fsp->can_lock = True; + fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; @@ -1976,8 +1978,7 @@ files_struct *open_directory(connection_struct *conn, if (lck == NULL) { DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname)); file_free(fsp); - set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } status = open_mode_check(conn, fname, lck, @@ -1985,10 +1986,9 @@ files_struct *open_directory(connection_struct *conn, create_options, &dir_existed); if (!NT_STATUS_IS_OK(status)) { - set_saved_ntstatus(status); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return status; } set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK); @@ -1998,10 +1998,9 @@ files_struct *open_directory(connection_struct *conn, if (create_options & FILE_DELETE_ON_CLOSE) { status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { - set_saved_ntstatus(status); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return status; } set_delete_on_close_token(lck, ¤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/source/smbd/password.c b/source/smbd/password.c index 73b0ebb4b32..389086e9bf7 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -29,9 +29,6 @@ static user_struct *validated_users; static int next_vuid = VUID_OFFSET; static int num_validated_vuids; -extern userdom_struct current_user_info; - - /**************************************************************************** Check if a uid has been validated, and return an pointer to the user_struct if it has. NULL if not. vuid is biased by an offset. This allows us to @@ -550,9 +547,11 @@ static BOOL user_ok(const char *user, int snum) str_list_copy(&invalid, lp_invalid_users(snum)); if (invalid && str_list_substitute(invalid, "%S", lp_servicename(snum))) { - if ( invalid && - str_list_sub_basic(invalid, - current_user_info.smb_name) ) { + + /* This is used in sec=share only, so no current user + * around to pass to str_list_sub_basic() */ + + if ( invalid && str_list_sub_basic(invalid, "", "") ) { ret = !user_in_list(user, (const char **)invalid); } @@ -565,9 +564,11 @@ static BOOL user_ok(const char *user, int snum) str_list_copy(&valid, lp_valid_users(snum)); if ( valid && str_list_substitute(valid, "%S", lp_servicename(snum)) ) { - if ( valid && - str_list_sub_basic(valid, - current_user_info.smb_name) ) { + + /* This is used in sec=share only, so no current user + * around to pass to str_list_sub_basic() */ + + if ( valid && str_list_sub_basic(valid, "", "") ) { ret = user_in_list(user, (const char **)valid); } } diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 2d90383706b..52660da2ffe 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -31,6 +31,21 @@ #define PIPE "\\PIPE\\" #define PIPELEN strlen(PIPE) +#define MAX_PIPE_NAME_LEN 24 + +/* PIPE/<name>/<pid>/<pnum> */ +#define PIPEDB_KEY_FORMAT "PIPE/%s/%u/%d" + +struct pipe_dbrec { + struct process_id pid; + int pnum; + uid_t uid; + + char name[MAX_PIPE_NAME_LEN]; + fstring user; +}; + + extern struct pipe_id_info pipe_names[]; /**************************************************************************** @@ -284,6 +299,8 @@ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf) if (!close_rpc_pipe_hnd(p)) { return ERROR_DOS(ERRDOS,ERRbadfid); } + + /* TODO: REMOVE PIPE FROM DB */ return(outsize); } diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c index 6e403dba92a..73744cf26e7 100644 --- a/source/smbd/posix_acls.c +++ b/source/smbd/posix_acls.c @@ -3043,8 +3043,7 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ return -1; } - fsp = open_file_fchmod(conn,fname,&st); - if (!fsp) { + if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,&st,&fsp))) { return -1; } @@ -4236,12 +4235,19 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) pstring filename; ZERO_STRUCT( conn ); - conn.service = -1; if ( !(conn.mem_ctx = talloc_init( "novfs_get_nt_acl" )) ) { DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n")); return NULL; } + + if (!(conn.params = TALLOC_P(conn.mem_ctx, struct share_params))) { + DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n")); + TALLOC_FREE(conn.mem_ctx); + return NULL; + } + + conn.params->service = -1; pstrcpy( path, "/" ); set_conn_connectpath(&conn, path); diff --git a/source/smbd/process.c b/source/smbd/process.c index b3ce49360d8..ce352adfd7d 100644 --- a/source/smbd/process.c +++ b/source/smbd/process.c @@ -21,7 +21,7 @@ #include "includes.h" -extern uint16 global_smbpid; +uint16 global_smbpid; extern int keepalive; extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; @@ -172,7 +172,6 @@ BOOL open_was_deferred(uint16 mid) for (pml = deferred_open_queue; pml; pml = pml->next) { if (SVAL(pml->buf.data,smb_mid) == mid) { - set_saved_ntstatus(NT_STATUS_OK); return True; } } @@ -459,11 +458,20 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) } } - maxfd = select_on_fd(smbd_server_fd(), maxfd, &fds); - maxfd = select_on_fd(change_notify_fd(), maxfd, &fds); - maxfd = select_on_fd(oplock_notify_fd(), maxfd, &fds); + { + int sav; + START_PROFILE(smbd_idle); + + maxfd = select_on_fd(smbd_server_fd(), maxfd, &fds); + maxfd = select_on_fd(change_notify_fd(), maxfd, &fds); + maxfd = select_on_fd(oplock_notify_fd(), maxfd, &fds); - selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to); + selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to); + sav = errno; + + END_PROFILE(smbd_idle); + errno = sav; + } /* if we get EINTR then maybe we have received an oplock signal - treat this as select returning 1. This is ugly, but @@ -885,7 +893,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize pid = sys_getpid(); errno = 0; - set_saved_ntstatus(NT_STATUS_OK); last_message = type; @@ -954,7 +961,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize } if (!change_to_user(conn,session_tag)) { - return(ERROR_FORCE_DOS(ERRSRV,ERRbaduid)); + return(ERROR_NT(NT_STATUS_DOS(ERRSRV,ERRbaduid))); } /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */ diff --git a/source/smbd/reply.c b/source/smbd/reply.c index e68e8662d74..ff3c6832e4f 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -427,6 +427,7 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de } else { *err = check_path_syntax_wcard(dest, tmppath, contains_wcard); } + return ret; } @@ -453,6 +454,7 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len } else { *err = check_path_syntax(dest, tmppath); } + return ret; } @@ -809,6 +811,14 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBchkpth); + + /* Strange DOS error code semantics only for chkpth... */ + if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) { + if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) { + /* We need to map to ERRbadpath */ + status = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + } return ERROR_NT(status); } @@ -1370,25 +1380,25 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask, &share_mode, &create_disposition, &create_options)) { END_PROFILE(SMBopen); - return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess); + return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess)); } - fsp = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,fname,&sbuf, access_mask, share_mode, create_disposition, create_options, dos_attr, oplock_request, - &info); + &info, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopen); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; } - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); + return ERROR_NT(status); } size = sbuf.st_size; @@ -1493,25 +1503,25 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt &create_disposition, &create_options)) { END_PROFILE(SMBopenX); - return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess); + return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess)); } - fsp = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,fname,&sbuf, access_mask, share_mode, create_disposition, create_options, smb_attr, oplock_request, - &smb_action); + &smb_action, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBopenX); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; } - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); + return ERROR_NT(status); } size = sbuf.st_size; @@ -1672,22 +1682,22 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } /* Open file using ntcreate. */ - fsp = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,fname,&sbuf, access_mask, share_mode, create_disposition, create_options, fattr, oplock_request, - NULL); + NULL, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; } - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); + return ERROR_NT(status); } outsize = set_message(outbuf,1,0,True); @@ -1756,25 +1766,25 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, SMB_VFS_STAT(conn,fname,&sbuf); /* We should fail if file does not exist. */ - fsp = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,fname,&sbuf, FILE_GENERIC_READ | FILE_GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, fattr, oplock_request, - NULL); + NULL, &fsp); /* close fd from smb_mkstemp() */ close(tmpfd); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBctemp); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; } - return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); + return ERROR_NT(status); } outsize = set_message(outbuf,1,0,True); @@ -1822,6 +1832,7 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, { files_struct *fsp; uint32 fmode; + NTSTATUS status; if (!CAN_WRITE(conn)) { return NT_STATUS_MEDIA_WRITE_PROTECTED; @@ -1836,25 +1847,16 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, return NT_STATUS_OK; } - /* We need a better way to return NT status codes from open... */ - set_saved_ntstatus(NT_STATUS_OK); - - fsp = open_file_ntcreate(conn, fname, pst, + status = open_file_ntcreate(conn, fname, pst, DELETE_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, 0, - NULL); + NULL, &fsp); - if (!fsp) { - NTSTATUS ret = get_saved_ntstatus(); - if (!NT_STATUS_IS_OK(ret)) { - set_saved_ntstatus(NT_STATUS_OK); - return ret; - } - set_saved_ntstatus(NT_STATUS_OK); + if (!NT_STATUS_IS_OK(status)) { return NT_STATUS_ACCESS_DENIED; } close_file(fsp,NORMAL_CLOSE); @@ -1870,6 +1872,7 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b SMB_STRUCT_STAT sbuf; uint32 fattr; files_struct *fsp; + NTSTATUS status; DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype )); @@ -1929,26 +1932,17 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b /* On open checks the open itself will check the share mode, so don't do it here as we'll get it wrong. */ - /* We need a better way to return NT status codes from open... */ - set_saved_ntstatus(NT_STATUS_OK); - - fsp = open_file_ntcreate(conn, fname, &sbuf, + status = open_file_ntcreate(conn, fname, &sbuf, DELETE_ACCESS, FILE_SHARE_NONE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, 0, - NULL); + NULL, &fsp); - if (!fsp) { - NTSTATUS ret = get_saved_ntstatus(); - if (!NT_STATUS_IS_OK(ret)) { - set_saved_ntstatus(NT_STATUS_OK); - return ret; - } - set_saved_ntstatus(NT_STATUS_OK); - return NT_STATUS_ACCESS_DENIED; + if (!NT_STATUS_IS_OK(status)) { + return status; } close_file(fsp,NORMAL_CLOSE); } @@ -1994,8 +1988,8 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B * Tine Smukavec <valentin.smukavec@hermes.si>. */ - if (!rc && mangle_is_mangled(mask,SNUM(conn))) - mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn)); + if (!rc && mangle_is_mangled(mask,conn->params)) + mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); if (!has_wild) { pstrcat(directory,"/"); @@ -2331,7 +2325,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s /* ensure we don't overrun the packet size */ maxcount = MIN(65535,maxcount); - if (!is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { SMB_STRUCT_STAT st; SMB_OFF_T size = 0; @@ -2403,7 +2397,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length */ status = do_lock_spin(fsp, - SVAL(inbuf,smb_pid), + (uint32)SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, @@ -2510,7 +2504,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", data = smb_buf(outbuf) + 3; - if (is_locked(fsp,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) { END_PROFILE(SMBread); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2717,7 +2711,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } - if (is_locked(fsp,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) { END_PROFILE(SMBreadX); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2780,7 +2774,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, SCVAL(inbuf,smb_com,SMBwritec); SCVAL(outbuf,smb_com,SMBwritec); - if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwritebraw); return(ERROR_DOS(ERRDOS,ERRlock)); } @@ -2901,7 +2895,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwriteunlock); return ERROR_DOS(ERRDOS,ERRlock); } @@ -2924,7 +2918,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, if (numtowrite) { status = do_unlock(fsp, - SVAL(inbuf,smb_pid), + (uint32)SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, WINDOWS_LOCK); @@ -2978,7 +2972,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; - if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwrite); return ERROR_DOS(ERRDOS,ERRlock); } @@ -3093,7 +3087,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng #endif /* LARGE_SMB_OFF_T */ } - if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwriteX); return ERROR_DOS(ERRDOS,ERRlock); } @@ -3368,7 +3362,7 @@ int reply_writeclose(connection_struct *conn, mtime = srv_make_unix_date3(inbuf+smb_vwv4); data = smb_buf(inbuf) + 1; - if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { + if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { END_PROFILE(SMBwriteclose); return ERROR_DOS(ERRDOS,ERRlock); } @@ -3439,7 +3433,7 @@ int reply_lock(connection_struct *conn, fsp->fh->fd, fsp->fnum, (double)offset, (double)count)); status = do_lock_spin(fsp, - SVAL(inbuf,smb_pid), + (uint32)SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, @@ -3494,7 +3488,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3); status = do_unlock(fsp, - SVAL(inbuf,smb_pid), + (uint32)SVAL(inbuf,smb_pid), count, offset, WINDOWS_LOCK); @@ -3598,6 +3592,8 @@ int reply_printopen(connection_struct *conn, { int outsize = 0; files_struct *fsp; + NTSTATUS status; + START_PROFILE(SMBsplopen); if (!CAN_PRINT(conn)) { @@ -3606,11 +3602,11 @@ int reply_printopen(connection_struct *conn, } /* Open for exclusive use, write only. */ - fsp = print_fsp_open(conn, NULL); + status = print_fsp_open(conn, NULL, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBsplopen); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return(ERROR_NT(status)); } outsize = set_message(outbuf,1,0,True); @@ -3838,6 +3834,17 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, status = mkdir_internal(conn, directory,bad_path); if (!NT_STATUS_IS_OK(status)) { + + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION) && + !use_nt_status()) { + /* + * Yes, in the DOS error code case we get a + * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR + * samba4 torture test. + */ + status = NT_STATUS_DOS(ERRDOS, ERRnoaccess); + } + END_PROFILE(SMBmkdir); return ERROR_NT(status); } @@ -4408,14 +4415,14 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui * Tine Smukavec <valentin.smukavec@hermes.si>. */ - if (!rc && mangle_is_mangled(mask,SNUM(conn))) - mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn)); + if (!rc && mangle_is_mangled(mask, conn->params)) + mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); if (!has_wild) { /* * No wildcards - just process the one file. */ - BOOL is_short_name = mangle_is_8_3(name, True, SNUM(conn)); + BOOL is_short_name = mangle_is_8_3(name, True, conn->params); /* Add a terminating '/' to the directory name. */ pstrcat(directory,"/"); @@ -4739,6 +4746,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, pstring dest; uint32 dosattrs; uint32 new_create_disposition; + NTSTATUS status; *err_ret = 0; @@ -4767,16 +4775,16 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } } - fsp1 = open_file_ntcreate(conn,src,&src_sbuf, + status = open_file_ntcreate(conn,src,&src_sbuf, FILE_GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, - NULL); + NULL, &fsp1); - if (!fsp1) { + if (!NT_STATUS_IS_OK(status)) { return(False); } @@ -4785,16 +4793,16 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, ZERO_STRUCTP(&sbuf2); } - fsp2 = open_file_ntcreate(conn,dest,&sbuf2, + status = open_file_ntcreate(conn,dest,&sbuf2, FILE_GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, new_create_disposition, 0, dosattrs, INTERNAL_OPEN_ONLY, - NULL); + NULL, &fsp2); - if (!fsp2) { + if (!NT_STATUS_IS_OK(status)) { close_file(fsp1,ERROR_CLOSE); return(False); } @@ -4926,8 +4934,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, * Tine Smukavec <valentin.smukavec@hermes.si>. */ - if (!rc && mangle_is_mangled(mask, SNUM(conn))) - mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn)); + if (!rc && mangle_is_mangled(mask, conn->params)) + mangle_check_cache( mask, sizeof(pstring)-1, conn->params ); has_wild = path_contains_wcard1; @@ -4995,8 +5003,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBcopy); return ERROR_DOS(ERRDOS,error); } else { - if((errno == ENOENT) && (bad_path1 || bad_path2)) { - set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK); + if((errno == ENOENT) && (bad_path1 || bad_path2) && + !use_nt_status()) { + /* Samba 3.0.22 has ERRDOS/ERRbadpath in the + * DOS error code case + */ + return ERROR_DOS(ERRDOS, ERRbadpath); } END_PROFILE(SMBcopy); return(UNIXERROR(ERRDOS,error)); @@ -5067,12 +5079,12 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size Get a lock pid, dealing with large count requests. ****************************************************************************/ -uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format) +uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format) { if(!large_file_format) - return SVAL(data,SMB_LPID_OFFSET(data_offset)); + return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset)); else - return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset)); + return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset)); } /**************************************************************************** @@ -5209,7 +5221,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); SMB_BIG_UINT count = 0, offset = 0; - uint16 lock_pid; + uint32 lock_pid; int32 lock_timeout = IVAL(inbuf,smb_vwv4); int i; char *data; @@ -5229,7 +5241,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, /* we don't support these - and CANCEL_LOCK makes w2k and XP reboot so I don't really want to be compatible! (tridge) */ - return ERROR_FORCE_DOS(ERRDOS, ERRnoatomiclocks); + return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks)); } if (locktype & LOCKING_ANDX_CANCEL_LOCK) { @@ -5505,7 +5517,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, tcount = maxcount; total_read = 0; - if (is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) { END_PROFILE(SMBreadBmpx); return ERROR_DOS(ERRDOS,ERRlock); } @@ -5637,7 +5649,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, not an SMBwritebmpx - set this up now so we don't forget */ SCVAL(outbuf,smb_com,SMBwritec); - if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) { + if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) { END_PROFILE(SMBwriteBmpx); return(ERROR_DOS(ERRDOS,ERRlock)); } diff --git a/source/smbd/server.c b/source/smbd/server.c index 2bfeae9f541..0fba6af6970 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -912,18 +912,12 @@ void build_options(BOOL screen); if (!message_init()) exit(1); - /* Initialize our global sam sid first -- quite a lot of the other - * initialization routines further down depend on it. - */ - /* Initialise the password backed before the global_sam_sid to ensure that we fetch from ldap before we make a domain sid up */ if(!initialize_password_db(False)) exit(1); - /* Fail gracefully if we can't open secrets.tdb */ - if (!secrets_init()) { DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n")); exit(1); diff --git a/source/smbd/service.c b/source/smbd/service.c index cb9bfcc27ae..9dcb8a354f4 100644 --- a/source/smbd/service.c +++ b/source/smbd/service.c @@ -371,35 +371,38 @@ static NTSTATUS find_forced_user(int snum, BOOL vuser_is_guest, { TALLOC_CTX *mem_ctx; char *fuser, *found_username; + struct nt_user_token *tmp_token; NTSTATUS result; - mem_ctx = talloc_new(NULL); - if (mem_ctx == NULL) { + if (!(mem_ctx = talloc_new(NULL))) { DEBUG(0, ("talloc_new failed\n")); return NT_STATUS_NO_MEMORY; } - fuser = talloc_string_sub(mem_ctx, lp_force_user(snum), "%S", - lp_servicename(snum)); - if (fuser == NULL) { - result = NT_STATUS_NO_MEMORY; - goto done; + if (!(fuser = talloc_string_sub(mem_ctx, lp_force_user(snum), "%S", + lp_servicename(snum)))) { + TALLOC_FREE(mem_ctx); + return NT_STATUS_NO_MEMORY; + } result = create_token_from_username(mem_ctx, fuser, vuser_is_guest, uid, gid, &found_username, - token); + &tmp_token); if (!NT_STATUS_IS_OK(result)) { - goto done; + TALLOC_FREE(mem_ctx); + return result; + } + + if (!(*token = dup_nt_token(NULL, tmp_token))) { + TALLOC_FREE(mem_ctx); + return NT_STATUS_NO_MEMORY; } - talloc_steal(NULL, *token); fstrcpy(username, found_username); - result = NT_STATUS_OK; - done: TALLOC_FREE(mem_ctx); - return result; + return NT_STATUS_OK; } /* @@ -620,7 +623,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, sizeof(conn->client_address)-1); conn->num_files_open = 0; conn->lastused = conn->lastused_count = time(NULL); - conn->service = snum; + conn->params->service = snum; conn->used = True; conn->printer = (strncmp(dev,"LPT",3) == 0); conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || @@ -646,7 +649,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, string_set(&conn->dirpath,""); string_set(&conn->user,user); - conn->read_only = lp_readonly(conn->service); + conn->read_only = lp_readonly(SNUM(conn)); conn->admin_user = False; /* @@ -746,7 +749,11 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, { pstring s; pstrcpy(s,lp_pathname(snum)); - standard_sub_conn(conn,s,sizeof(s)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + s, sizeof(s)); set_conn_connectpath(conn,s); DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum))); @@ -821,7 +828,11 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (*lp_rootpreexec(snum)) { pstring cmd; pstrcpy(cmd,lp_rootpreexec(snum)); - standard_sub_conn(conn,cmd,sizeof(cmd)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + cmd, sizeof(cmd)); DEBUG(5,("cmd=%s\n",cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_rootpreexec_close(snum)) { @@ -854,7 +865,11 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (*lp_preexec(snum)) { pstring cmd; pstrcpy(cmd,lp_preexec(snum)); - standard_sub_conn(conn,cmd,sizeof(cmd)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + cmd, sizeof(cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_preexec_close(snum)) { DEBUG(1,("preexec gave %d - failing connection\n", @@ -1148,7 +1163,11 @@ void close_cnum(connection_struct *conn, uint16 vuid) change_to_user(conn, vuid)) { pstring cmd; pstrcpy(cmd,lp_postexec(SNUM(conn))); - standard_sub_conn(conn,cmd,sizeof(cmd)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + cmd, sizeof(cmd)); smbrun(cmd,NULL); change_to_root_user(); } @@ -1158,7 +1177,11 @@ void close_cnum(connection_struct *conn, uint16 vuid) if (*lp_rootpostexec(SNUM(conn))) { pstring cmd; pstrcpy(cmd,lp_rootpostexec(SNUM(conn))); - standard_sub_conn(conn,cmd,sizeof(cmd)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + cmd, sizeof(cmd)); smbrun(cmd,NULL); } diff --git a/source/smbd/session.c b/source/smbd/session.c index 41f8fd0ed43..bcb840a3fe4 100644 --- a/source/smbd/session.c +++ b/source/smbd/session.c @@ -1,8 +1,10 @@ /* Unix SMB/CIFS implementation. session handling for utmp and PAM - Copyright (C) tridge@samba.org 2001 - Copyright (C) abartlet@pcug.org.au 2001 + + Copyright (C) tridge@samba.org 2001 + Copyright (C) abartlet@samba.org 2001 + Copyright (C) Gerald (Jerry) Carter 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +31,9 @@ static TDB_CONTEXT *tdb; +/******************************************************************** +********************************************************************/ + BOOL session_init(void) { if (tdb) @@ -44,7 +49,10 @@ BOOL session_init(void) return True; } -/* called when a session is created */ +/******************************************************************** + called when a session is created +********************************************************************/ + BOOL session_claim(user_struct *vuser) { int i = 0; @@ -126,6 +134,7 @@ BOOL session_claim(user_struct *vuser) sessionid.gid = vuser->gid; fstrcpy(sessionid.remote_machine, get_remote_machine_name()); fstrcpy(sessionid.ip_addr, client_addr()); + sessionid.connect_start = time(NULL); client_ip = client_inaddr(&sa); @@ -159,7 +168,10 @@ BOOL session_claim(user_struct *vuser) return True; } -/* called when a session is destroyed */ +/******************************************************************** + called when a session is destroyed +********************************************************************/ + void session_yield(user_struct *vuser) { TDB_DATA dbuf; @@ -198,6 +210,9 @@ void session_yield(user_struct *vuser) tdb_delete(tdb, key); } +/******************************************************************** +********************************************************************/ + BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), void *state) { @@ -210,32 +225,40 @@ BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), return True; } +/******************************************************************** +********************************************************************/ + struct session_list { int count; struct sessionid *sessions; }; -static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf, - void *state) +static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) { + uint32 i; struct session_list *sesslist = (struct session_list *) state; const struct sessionid *current = (const struct sessionid *) dbuf.dptr; - sesslist->count += 1; - sesslist->sessions = SMB_REALLOC_ARRAY(sesslist->sessions, struct sessionid, - sesslist->count); + i = sesslist->count; + + sesslist->sessions = SMB_REALLOC_ARRAY(sesslist->sessions, struct sessionid, i+1); if (!sesslist->sessions) { sesslist->count = 0; return -1; } - memcpy(&sesslist->sessions[sesslist->count - 1], current, - sizeof(struct sessionid)); + memcpy(&sesslist->sessions[i], current, sizeof(struct sessionid)); + sesslist->count++; + DEBUG(7,("gather_sessioninfo session from %s@%s\n", current->username, current->remote_machine)); + return 0; } +/******************************************************************** +********************************************************************/ + int list_sessions(struct sessionid **session_list) { struct session_list sesslist; diff --git a/source/smbd/share_access.c b/source/smbd/share_access.c index 468f61560b9..5334976d8dc 100644 --- a/source/smbd/share_access.c +++ b/source/smbd/share_access.c @@ -28,6 +28,8 @@ * + and & may be combined */ +extern userdom_struct current_user_info; + static BOOL do_group_checks(const char **name, const char **pattern) { if ((*name)[0] == '@') { @@ -74,7 +76,8 @@ static BOOL token_contains_name(TALLOC_CTX *mem_ctx, enum SID_NAME_USE type; if (username != NULL) { - name = talloc_sub_basic(mem_ctx, username, name); + name = talloc_sub_basic(mem_ctx, username, + current_user_info.domain, name); } if (sharename != NULL) { name = talloc_string_sub(mem_ctx, name, "%S", sharename); diff --git a/source/smbd/statcache.c b/source/smbd/statcache.c index 548d7c4a487..b453fdd5447 100644 --- a/source/smbd/statcache.c +++ b/source/smbd/statcache.c @@ -52,7 +52,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat if (!lp_stat_cache()) return; - if (sc_size && (tdb_stat_cache->map_size > sc_size*1024)) { + if (sc_size && (tdb_map_size(tdb_stat_cache) > sc_size*1024)) { reset_stat_cache(); } @@ -291,12 +291,12 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, JRA. Use a djb-algorithm hash for speed. ***************************************************************/ -u32 fast_string_hash(TDB_DATA *key) +unsigned int fast_string_hash(TDB_DATA *key) { - u32 n = 0; + unsigned int n = 0; const char *p; for (p = key->dptr; *p != '\0'; p++) { - n = ((n << 5) + n) ^ (u32)(*p); + n = ((n << 5) + n) ^ (unsigned int)(*p); } return n; } diff --git a/source/smbd/statvfs.c b/source/smbd/statvfs.c index 8f981a63288..300b14a7c08 100644 --- a/source/smbd/statvfs.c +++ b/source/smbd/statvfs.c @@ -21,7 +21,7 @@ #include "includes.h" -#if defined(LINUX) +#if defined(LINUX) && defined(HAVE_FSID_INT) static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf) { struct statvfs statvfs_buf; @@ -51,7 +51,7 @@ static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf) */ int sys_statvfs(const char *path, vfs_statvfs_struct *statbuf) { -#if defined(LINUX) +#if defined(LINUX) && defined(HAVE_FSID_INT) return linux_statvfs(path, statbuf); #else /* BB change this to return invalid level */ diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index 9030737b1b4..aca1fcd70e9 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -837,16 +837,16 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - fsp = open_file_ntcreate(conn,fname,&sbuf, + status = open_file_ntcreate(conn,fname,&sbuf, access_mask, share_mode, create_disposition, create_options, open_attr, oplock_request, - &smb_action); + &smb_action, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(status)) { talloc_destroy(ctx); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ @@ -1070,7 +1070,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, BOOL was_8_3; uint32 nt_extmode; /* Used for NT connections instead of mode */ BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); - BOOL check_mangled_names = lp_manglednames(SNUM(conn)); + BOOL check_mangled_names = lp_manglednames(conn->params); *fname = 0; *out_of_space = False; @@ -1117,7 +1117,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive))) got_match = mask_match(fname, mask, conn->case_sensitive); - if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) { + if(!got_match && check_mangled_names && + !mangle_is_8_3(fname, False, conn->params)) { /* * It turns out that NT matches wildcards against @@ -1128,7 +1129,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstring newname; pstrcpy( newname, fname); - mangle_map( newname, True, False, SNUM(conn)); + mangle_map( newname, True, False, conn->params); if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive))) got_match = mask_match(newname, mask, conn->case_sensitive); } @@ -1202,7 +1203,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } } - mangle_map(fname,False,True,SNUM(conn)); + mangle_map(fname,False,True,conn->params); p = pdata; last_entry_ptr = p; @@ -1338,7 +1339,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); - was_8_3 = mangle_is_8_3(fname, True, SNUM(conn)); + was_8_3 = mangle_is_8_3(fname, True, conn->params); p += 4; SIVAL(p,0,reskey); p += 4; put_long_date(p,cdate); p += 8; @@ -1361,7 +1362,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if (!was_8_3 && check_mangled_names) { pstring mangled_name; pstrcpy(mangled_name, fname); - mangle_map(mangled_name,True,True,SNUM(conn)); + mangle_map(mangled_name,True,True, + conn->params); mangled_name[12] = 0; len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); if (len < 24) { @@ -1480,7 +1482,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, case SMB_FIND_ID_BOTH_DIRECTORY_INFO: DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n")); - was_8_3 = mangle_is_8_3(fname, True, SNUM(conn)); + was_8_3 = mangle_is_8_3(fname, True, conn->params); p += 4; SIVAL(p,0,reskey); p += 4; put_long_date(p,cdate); p += 8; @@ -1503,7 +1505,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if (!was_8_3 && check_mangled_names) { pstring mangled_name; pstrcpy(mangled_name, fname); - mangle_map(mangled_name,True,True,SNUM(conn)); + mangle_map(mangled_name,True,True, + conn->params); mangled_name[12] = 0; len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); SSVAL(p, 0, len); @@ -1871,8 +1874,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd * (see PR#13758). JRA. */ - if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn))) - mangle_map(mask, True, True, SNUM(conn)); + if(!mangle_is_8_3_wildcards( mask, False, conn->params)) + mangle_map(mask, True, True, conn->params); return(-1); } @@ -2068,8 +2071,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd * could be mangled. Ensure we check the unmangled name. */ - if (mangle_is_mangled(resume_name, SNUM(conn))) { - mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn)); + if (mangle_is_mangled(resume_name, conn->params)) { + mangle_check_cache(resume_name, sizeof(resume_name)-1, + conn->params); } /* @@ -2441,17 +2445,10 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION); SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION); /* We have POSIX ACLs, pathname and locking capability. */ -#if defined(DEVELOPER) /* Not quite finished yet... */ SBIG_UINT(pdata,4,((SMB_BIG_UINT)( CIFS_UNIX_POSIX_ACLS_CAP| CIFS_UNIX_POSIX_PATHNAMES_CAP| CIFS_UNIX_FCNTL_LOCKS_CAP))); -#else - SBIG_UINT(pdata,4,((SMB_BIG_UINT)( - CIFS_UNIX_POSIX_ACLS_CAP| - CIFS_UNIX_POSIX_PATHNAMES_CAP| - 0))); -#endif break; case SMB_QUERY_POSIX_FS_INFO: @@ -2567,11 +2564,10 @@ cap_low = 0x%x, cap_high = 0x%x\n", lp_set_posix_pathnames(); mangle_change_to_posix(); } -#if defined(DEVELOPER) + if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) { lp_set_posix_cifsx_locktype(POSIX_LOCK); } -#endif break; } case SMB_FS_QUOTA_INFORMATION: @@ -2832,9 +2828,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * TALLOC_CTX *data_ctx = NULL; struct ea_list *ea_list = NULL; uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ -#if defined(DEVELOPER) char *lock_data = NULL; -#endif if (!params) return ERROR_NT(NT_STATUS_INVALID_PARAMETER); @@ -3006,7 +3000,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } break; } -#if defined(DEVELOPER) + case SMB_QUERY_POSIX_LOCK: { if (fsp == NULL || fsp->fh->fd == -1) { @@ -3028,7 +3022,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return ERROR_NT(NT_STATUS_NO_MEMORY); } } -#endif default: break; } @@ -3229,8 +3222,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n")); pstrcpy(short_name,base_name); /* Mangle if not already 8.3 */ - if(!mangle_is_8_3(short_name, True, SNUM(conn))) { - mangle_map(short_name,True,True,SNUM(conn)); + if(!mangle_is_8_3(short_name, True, conn->params)) { + mangle_map(short_name,True,True,conn->params); } len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE); data_size = 4 + len; @@ -3448,7 +3441,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd { int i; - DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC")); + DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC ")); for (i=0; i<100; i++) DEBUG(4,("%d=%x, ",i, (*ppdata)[i])); @@ -3559,13 +3552,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd #endif -#if defined(DEVELOPER) case SMB_QUERY_POSIX_LOCK: { NTSTATUS status = NT_STATUS_INVALID_LEVEL; SMB_BIG_UINT count; SMB_BIG_UINT offset; - uint16 lock_pid; + uint32 lock_pid; enum brl_type lock_type; if (total_data != POSIX_LOCK_DATA_SIZE) { @@ -3586,7 +3578,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET); + lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET); #if defined(HAVE_LONGLONG) offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) | ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET)); @@ -3632,7 +3624,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } break; } -#endif default: return ERROR_NT(NT_STATUS_INVALID_LEVEL); @@ -4030,16 +4021,16 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if (fd == -1) { files_struct *new_fsp = NULL; - new_fsp = open_file_ntcreate(conn, fname, &sbuf, + status = open_file_ntcreate(conn, fname, &sbuf, FILE_WRITE_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, FORCE_OPLOCK_BREAK_TO_NONE, - NULL); + NULL, &new_fsp); - if (new_fsp == NULL) { + if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; @@ -4404,7 +4395,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", case SMB_FILE_RENAME_INFORMATION: { BOOL overwrite; - uint32 root_fid; + /* uint32 root_fid; */ /* Not used */ uint32 len; pstring newname; pstring base_name; @@ -4415,7 +4406,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } overwrite = (CVAL(pdata,0) ? True : False); - root_fid = IVAL(pdata,4); + /* root_fid = IVAL(pdata,4); */ len = IVAL(pdata,8); srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status); if (!NT_STATUS_IS_OK(status)) { @@ -4507,12 +4498,11 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } #endif -#if defined(DEVELOPER) case SMB_SET_POSIX_LOCK: { SMB_BIG_UINT count; SMB_BIG_UINT offset; - uint16 lock_pid; + uint32 lock_pid; BOOL lock_blocking; enum brl_type lock_type; BOOL my_lock_ctx; @@ -4551,7 +4541,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } - lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET); + lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET); #if defined(HAVE_LONGLONG) offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) | ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET)); @@ -4605,7 +4595,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); return(-1); } -#endif default: return ERROR_NT(NT_STATUS_INVALID_LEVEL); @@ -4673,16 +4662,16 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (fd == -1) { files_struct *new_fsp = NULL; - new_fsp = open_file_ntcreate(conn, fname, &sbuf, + status = open_file_ntcreate(conn, fname, &sbuf, FILE_WRITE_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, FORCE_OPLOCK_BREAK_TO_NONE, - NULL); + NULL, &new_fsp); - if (new_fsp == NULL) { + if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ return -1; diff --git a/source/smbd/uid.c b/source/smbd/uid.c index c62c9d928ab..48d7f590c39 100644 --- a/source/smbd/uid.c +++ b/source/smbd/uid.c @@ -102,7 +102,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) readonly_share = is_share_read_only_for_token(vuser->user.unix_name, vuser->nt_user_token, - conn->service); + SNUM(conn)); if (!readonly_share && !share_access_check(conn, snum, vuser, FILE_WRITE_DATA)) { @@ -129,7 +129,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) ent->admin_user = token_contains_name_in_list( vuser->user.unix_name, NULL, vuser->nt_user_token, - lp_admin_users(conn->service)); + lp_admin_users(SNUM(conn))); conn->read_only = ent->read_only; conn->admin_user = ent->admin_user; diff --git a/source/smbd/vfs-wrap.c b/source/smbd/vfs-wrap.c deleted file mode 100644 index ee251c17d8d..00000000000 --- a/source/smbd/vfs-wrap.c +++ /dev/null @@ -1,1104 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Wrap disk only vfs functions to sidestep dodgy compilers. - Copyright (C) Tim Potter 1998 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_VFS - - -/* Check for NULL pointer parameters in vfswrap_* functions */ - -/* We don't want to have NULL function pointers lying around. Someone - is sure to try and execute them. These stubs are used to prevent - this possibility. */ - -int vfswrap_dummy_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user) -{ - return 0; /* Return >= 0 for success */ -} - -void vfswrap_dummy_disconnect(vfs_handle_struct *handle, connection_struct *conn) -{ -} - -/* Disk operations */ - -SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, - SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) -{ - SMB_BIG_UINT result; - - result = sys_disk_free(conn, path, small_query, bsize, dfree, dsize); - return result; -} - -int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) -{ -#ifdef HAVE_SYS_QUOTAS - int result; - - START_PROFILE(syscall_get_quota); - result = sys_get_quota(conn->connectpath, qtype, id, qt); - END_PROFILE(syscall_get_quota); - return result; -#else - errno = ENOSYS; - return -1; -#endif -} - -int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) -{ -#ifdef HAVE_SYS_QUOTAS - int result; - - START_PROFILE(syscall_set_quota); - result = sys_set_quota(conn->connectpath, qtype, id, qt); - END_PROFILE(syscall_set_quota); - return result; -#else - errno = ENOSYS; - return -1; -#endif -} - -int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels) -{ - errno = ENOSYS; - return -1; /* Not implemented. */ -} - -int vfswrap_statvfs(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, vfs_statvfs_struct *statbuf) -{ - return sys_statvfs(path, statbuf); -} - -/* Directory operations */ - -SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr) -{ - SMB_STRUCT_DIR *result; - - START_PROFILE(syscall_opendir); - result = sys_opendir(fname); - END_PROFILE(syscall_opendir); - return result; -} - -SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp) -{ - SMB_STRUCT_DIRENT *result; - - START_PROFILE(syscall_readdir); - result = sys_readdir(dirp); - END_PROFILE(syscall_readdir); - return result; -} - -void vfswrap_seekdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp, long offset) -{ - START_PROFILE(syscall_seekdir); - sys_seekdir(dirp, offset); - END_PROFILE(syscall_seekdir); -} - -long vfswrap_telldir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp) -{ - long result; - START_PROFILE(syscall_telldir); - result = sys_telldir(dirp); - END_PROFILE(syscall_telldir); - return result; -} - -void vfswrap_rewinddir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp) -{ - START_PROFILE(syscall_rewinddir); - sys_rewinddir(dirp); - END_PROFILE(syscall_rewinddir); -} - -int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) -{ - int result; - BOOL has_dacl = False; - - START_PROFILE(syscall_mkdir); - - if (lp_inherit_acls(SNUM(conn)) && (has_dacl = directory_has_default_acl(conn, parent_dirname(path)))) - mode = 0777; - - result = mkdir(path, mode); - - if (result == 0 && !has_dacl) { - /* - * We need to do this as the default behavior of POSIX ACLs - * is to set the mask to be the requested group permission - * bits, not the group permission bits to be the requested - * group permission bits. This is not what we want, as it will - * mess up any inherited ACL bits that were set. JRA. - */ - int saved_errno = errno; /* We may get ENOSYS */ - if ((SMB_VFS_CHMOD_ACL(conn, path, mode) == -1) && (errno == ENOSYS)) - errno = saved_errno; - } - - END_PROFILE(syscall_mkdir); - return result; -} - -int vfswrap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) -{ - int result; - - START_PROFILE(syscall_rmdir); - result = rmdir(path); - END_PROFILE(syscall_rmdir); - return result; -} - -int vfswrap_closedir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp) -{ - int result; - - START_PROFILE(syscall_closedir); - result = sys_closedir(dirp); - END_PROFILE(syscall_closedir); - return result; -} - -/* File operations */ - -int vfswrap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode) -{ - int result; - - START_PROFILE(syscall_open); - result = sys_open(fname, flags, mode); - END_PROFILE(syscall_open); - return result; -} - -int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp, int fd) -{ - int result; - - START_PROFILE(syscall_close); - - result = close(fd); - END_PROFILE(syscall_close); - return result; -} - -ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n) -{ - ssize_t result; - - START_PROFILE_BYTES(syscall_read, n); - result = sys_read(fd, data, n); - END_PROFILE(syscall_read); - return result; -} - -ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, - size_t n, SMB_OFF_T offset) -{ - ssize_t result; - -#if defined(HAVE_PREAD) || defined(HAVE_PREAD64) - START_PROFILE_BYTES(syscall_pread, n); - result = sys_pread(fd, data, n, offset); - END_PROFILE(syscall_pread); - - if (result == -1 && errno == ESPIPE) { - /* Maintain the fiction that pipes can be seeked (sought?) on. */ - result = SMB_VFS_READ(fsp, fd, data, n); - fsp->fh->pos = 0; - } - -#else /* HAVE_PREAD */ - SMB_OFF_T curr; - int lerrno; - - curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); - if (curr == -1 && errno == ESPIPE) { - /* Maintain the fiction that pipes can be seeked (sought?) on. */ - result = SMB_VFS_READ(fsp, fd, data, n); - fsp->fh->pos = 0; - return result; - } - - if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) { - return -1; - } - - errno = 0; - result = SMB_VFS_READ(fsp, fd, data, n); - lerrno = errno; - - SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET); - errno = lerrno; - -#endif /* HAVE_PREAD */ - - return result; -} - -ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n) -{ - ssize_t result; - - START_PROFILE_BYTES(syscall_write, n); - result = sys_write(fd, data, n); - END_PROFILE(syscall_write); - return result; -} - -ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, - size_t n, SMB_OFF_T offset) -{ - ssize_t result; - -#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64) - START_PROFILE_BYTES(syscall_pwrite, n); - result = sys_pwrite(fd, data, n, offset); - END_PROFILE(syscall_pwrite); - - if (result == -1 && errno == ESPIPE) { - /* Maintain the fiction that pipes can be sought on. */ - result = SMB_VFS_WRITE(fsp, fd, data, n); - } - -#else /* HAVE_PWRITE */ - SMB_OFF_T curr; - int lerrno; - - curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); - if (curr == -1) { - return -1; - } - - if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) { - return -1; - } - - result = SMB_VFS_WRITE(fsp, fd, data, n); - lerrno = errno; - - SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET); - errno = lerrno; - -#endif /* HAVE_PWRITE */ - - return result; -} - -SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) -{ - SMB_OFF_T result = 0; - - START_PROFILE(syscall_lseek); - - /* Cope with 'stat' file opens. */ - if (filedes != -1) - result = sys_lseek(filedes, offset, whence); - - /* - * We want to maintain the fiction that we can seek - * on a fifo for file system purposes. This allows - * people to set up UNIX fifo's that feed data to Windows - * applications. JRA. - */ - - if((result == -1) && (errno == ESPIPE)) { - result = 0; - errno = 0; - } - - END_PROFILE(syscall_lseek); - return result; -} - -ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *hdr, - SMB_OFF_T offset, size_t n) -{ - ssize_t result; - - START_PROFILE_BYTES(syscall_sendfile, n); - result = sys_sendfile(tofd, fromfd, hdr, offset, n); - END_PROFILE(syscall_sendfile); - return result; -} - -/********************************************************* - For rename across filesystems Patch from Warren Birnbaum - <warrenb@hpcvscdp.cv.hp.com> -**********************************************************/ - -static int copy_reg(const char *source, const char *dest) -{ - SMB_STRUCT_STAT source_stats; - int saved_errno; - int ifd = -1; - int ofd = -1; - - if (sys_lstat (source, &source_stats) == -1) - return -1; - - if (!S_ISREG (source_stats.st_mode)) - return -1; - - if((ifd = sys_open (source, O_RDONLY, 0)) < 0) - return -1; - - if (unlink (dest) && errno != ENOENT) - return -1; - -#ifdef O_NOFOLLOW - if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 ) -#else - if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 ) -#endif - goto err; - - if (transfer_file(ifd, ofd, (size_t)-1) == -1) - goto err; - - /* - * Try to preserve ownership. For non-root it might fail, but that's ok. - * But root probably wants to know, e.g. if NFS disallows it. - */ - -#ifdef HAVE_FCHOWN - if ((fchown(ofd, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM)) -#else - if ((chown(dest, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM)) -#endif - goto err; - - /* - * fchown turns off set[ug]id bits for non-root, - * so do the chmod last. - */ - -#if defined(HAVE_FCHMOD) - if (fchmod (ofd, source_stats.st_mode & 07777)) -#else - if (chmod (dest, source_stats.st_mode & 07777)) -#endif - goto err; - - if (close (ifd) == -1) - goto err; - - if (close (ofd) == -1) - return -1; - - /* Try to copy the old file's modtime and access time. */ - { - struct utimbuf tv; - - tv.actime = source_stats.st_atime; - tv.modtime = source_stats.st_mtime; - utime(dest, &tv); - } - - if (unlink (source) == -1) - return -1; - - return 0; - - err: - - saved_errno = errno; - if (ifd != -1) - close(ifd); - if (ofd != -1) - close(ofd); - errno = saved_errno; - return -1; -} - -int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname) -{ - int result; - - START_PROFILE(syscall_rename); - result = rename(oldname, newname); - if (errno == EXDEV) { - /* Rename across filesystems needed. */ - result = copy_reg(oldname, newname); - } - - END_PROFILE(syscall_rename); - return result; -} - -int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd) -{ -#ifdef HAVE_FSYNC - int result; - - START_PROFILE(syscall_fsync); - result = fsync(fd); - END_PROFILE(syscall_fsync); - return result; -#else - return 0; -#endif -} - -int vfswrap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf) -{ - int result; - - START_PROFILE(syscall_stat); - result = sys_stat(fname, sbuf); - END_PROFILE(syscall_stat); - return result; -} - -int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) -{ - int result; - - START_PROFILE(syscall_fstat); - result = sys_fstat(fd, sbuf); - END_PROFILE(syscall_fstat); - return result; -} - -int vfswrap_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) -{ - int result; - - START_PROFILE(syscall_lstat); - result = sys_lstat(path, sbuf); - END_PROFILE(syscall_lstat); - return result; -} - -int vfswrap_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path) -{ - int result; - - START_PROFILE(syscall_unlink); - result = unlink(path); - END_PROFILE(syscall_unlink); - return result; -} - -int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) -{ - int result; - - START_PROFILE(syscall_chmod); - - /* - * We need to do this due to the fact that the default POSIX ACL - * chmod modifies the ACL *mask* for the group owner, not the - * group owner bits directly. JRA. - */ - - - { - int saved_errno = errno; /* We might get ENOSYS */ - if ((result = SMB_VFS_CHMOD_ACL(conn, path, mode)) == 0) { - END_PROFILE(syscall_chmod); - return result; - } - /* Error - return the old errno. */ - errno = saved_errno; - } - - result = chmod(path, mode); - END_PROFILE(syscall_chmod); - return result; -} - -int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) -{ - int result; - - START_PROFILE(syscall_fchmod); - - /* - * We need to do this due to the fact that the default POSIX ACL - * chmod modifies the ACL *mask* for the group owner, not the - * group owner bits directly. JRA. - */ - - { - int saved_errno = errno; /* We might get ENOSYS */ - if ((result = SMB_VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) { - END_PROFILE(syscall_fchmod); - return result; - } - /* Error - return the old errno. */ - errno = saved_errno; - } - -#if defined(HAVE_FCHMOD) - result = fchmod(fd, mode); -#else - result = -1; - errno = ENOSYS; -#endif - - END_PROFILE(syscall_fchmod); - return result; -} - -int vfswrap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid) -{ - int result; - - START_PROFILE(syscall_chown); - result = sys_chown(path, uid, gid); - END_PROFILE(syscall_chown); - return result; -} - -int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid) -{ -#ifdef HAVE_FCHOWN - int result; - - START_PROFILE(syscall_fchown); - result = fchown(fd, uid, gid); - END_PROFILE(syscall_fchown); - return result; -#else - errno = ENOSYS; - return -1; -#endif -} - -int vfswrap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) -{ - int result; - - START_PROFILE(syscall_chdir); - result = chdir(path); - END_PROFILE(syscall_chdir); - return result; -} - -char *vfswrap_getwd(vfs_handle_struct *handle, connection_struct *conn, char *path) -{ - char *result; - - START_PROFILE(syscall_getwd); - result = sys_getwd(path); - END_PROFILE(syscall_getwd); - return result; -} - -int vfswrap_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times) -{ - int result; - - START_PROFILE(syscall_utime); - result = utime(path, times); - END_PROFILE(syscall_utime); - return result; -} - -/********************************************************************* - A version of ftruncate that will write the space on disk if strict - allocate is set. -**********************************************************************/ - -static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len) -{ - SMB_STRUCT_STAT st; - SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); - unsigned char zero_space[4096]; - SMB_OFF_T space_to_write; - - if (currpos == -1) - return -1; - - if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) - return -1; - - space_to_write = len - st.st_size; - -#ifdef S_ISFIFO - if (S_ISFIFO(st.st_mode)) - return 0; -#endif - - if (st.st_size == len) - return 0; - - /* Shrink - just ftruncate. */ - if (st.st_size > len) - return sys_ftruncate(fd, len); - - /* Write out the real space on disk. */ - if (SMB_VFS_LSEEK(fsp, fd, st.st_size, SEEK_SET) != st.st_size) - return -1; - - space_to_write = len - st.st_size; - - memset(zero_space, '\0', sizeof(zero_space)); - while ( space_to_write > 0) { - SMB_OFF_T retlen; - SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write); - - retlen = SMB_VFS_WRITE(fsp,fsp->fh->fd,(char *)zero_space,current_len_to_write); - if (retlen <= 0) - return -1; - - space_to_write -= retlen; - } - - /* Seek to where we were */ - if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) - return -1; - - return 0; -} - -int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len) -{ - int result = -1; - SMB_STRUCT_STAT st; - char c = 0; - SMB_OFF_T currpos; - - START_PROFILE(syscall_ftruncate); - - if (lp_strict_allocate(SNUM(fsp->conn))) { - result = strict_allocate_ftruncate(handle, fsp, fd, len); - END_PROFILE(syscall_ftruncate); - return result; - } - - /* we used to just check HAVE_FTRUNCATE_EXTEND and only use - sys_ftruncate if the system supports it. Then I discovered that - you can have some filesystems that support ftruncate - expansion and some that don't! On Linux fat can't do - ftruncate extend but ext2 can. */ - - result = sys_ftruncate(fd, len); - if (result == 0) - goto done; - - /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot - extend a file with ftruncate. Provide alternate implementation - for this */ - currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); - if (currpos == -1) { - goto done; - } - - /* Do an fstat to see if the file is longer than the requested - size in which case the ftruncate above should have - succeeded or shorter, in which case seek to len - 1 and - write 1 byte of zero */ - if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) { - goto done; - } - -#ifdef S_ISFIFO - if (S_ISFIFO(st.st_mode)) { - result = 0; - goto done; - } -#endif - - if (st.st_size == len) { - result = 0; - goto done; - } - - if (st.st_size > len) { - /* the sys_ftruncate should have worked */ - goto done; - } - - if (SMB_VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1) - goto done; - - if (SMB_VFS_WRITE(fsp, fd, &c, 1)!=1) - goto done; - - /* Seek to where we were */ - if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) - goto done; - result = 0; - - done: - - END_PROFILE(syscall_ftruncate); - return result; -} - -BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) -{ - BOOL result; - - START_PROFILE(syscall_fcntl_lock); - result = fcntl_lock(fd, op, offset, count, type); - END_PROFILE(syscall_fcntl_lock); - return result; -} - -BOOL vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid) -{ - BOOL result; - - START_PROFILE(syscall_fcntl_getlock); - result = fcntl_getlock(fd, poffset, pcount, ptype, ppid); - END_PROFILE(syscall_fcntl_getlock); - return result; -} - -int vfswrap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) -{ - int result; - - START_PROFILE(syscall_symlink); - result = sys_symlink(oldpath, newpath); - END_PROFILE(syscall_symlink); - return result; -} - -int vfswrap_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz) -{ - int result; - - START_PROFILE(syscall_readlink); - result = sys_readlink(path, buf, bufsiz); - END_PROFILE(syscall_readlink); - return result; -} - -int vfswrap_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) -{ - int result; - - START_PROFILE(syscall_link); - result = sys_link(oldpath, newpath); - END_PROFILE(syscall_link); - return result; -} - -int vfswrap_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev) -{ - int result; - - START_PROFILE(syscall_mknod); - result = sys_mknod(pathname, mode, dev); - END_PROFILE(syscall_mknod); - return result; -} - -char *vfswrap_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path) -{ - char *result; - - START_PROFILE(syscall_realpath); - result = sys_realpath(path, resolved_path); - END_PROFILE(syscall_realpath); - return result; -} - -size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, SEC_DESC **ppdesc) -{ - size_t result; - - START_PROFILE(fget_nt_acl); - result = get_nt_acl(fsp, security_info, ppdesc); - END_PROFILE(fget_nt_acl); - return result; -} - -size_t vfswrap_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, SEC_DESC **ppdesc) -{ - size_t result; - - START_PROFILE(get_nt_acl); - result = get_nt_acl(fsp, security_info, ppdesc); - END_PROFILE(get_nt_acl); - return result; -} - -BOOL vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd) -{ - BOOL result; - - START_PROFILE(fset_nt_acl); - result = set_nt_acl(fsp, security_info_sent, psd); - END_PROFILE(fset_nt_acl); - return result; -} - -BOOL vfswrap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd) -{ - BOOL result; - - START_PROFILE(set_nt_acl); - result = set_nt_acl(fsp, security_info_sent, psd); - END_PROFILE(set_nt_acl); - return result; -} - -int vfswrap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode) -{ -#ifdef HAVE_NO_ACL - errno = ENOSYS; - return -1; -#else - int result; - - START_PROFILE(chmod_acl); - result = chmod_acl(conn, name, mode); - END_PROFILE(chmod_acl); - return result; -#endif -} - -int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) -{ -#ifdef HAVE_NO_ACL - errno = ENOSYS; - return -1; -#else - int result; - - START_PROFILE(fchmod_acl); - result = fchmod_acl(fsp, fd, mode); - END_PROFILE(fchmod_acl); - return result; -#endif -} - -int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - return sys_acl_get_entry(theacl, entry_id, entry_p); -} - -int vfswrap_sys_acl_get_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) -{ - return sys_acl_get_tag_type(entry_d, tag_type_p); -} - -int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - return sys_acl_get_permset(entry_d, permset_p); -} - -void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d) -{ - return sys_acl_get_qualifier(entry_d); -} - -SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type) -{ - return sys_acl_get_file(path_p, type); -} - -SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) -{ - return sys_acl_get_fd(fd); -} - -int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset) -{ - return sys_acl_clear_perms(permset); -} - -int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return sys_acl_add_perm(permset, perm); -} - -char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen) -{ - return sys_acl_to_text(theacl, plen); -} - -SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle, connection_struct *conn, int count) -{ - return sys_acl_init(count); -} - -int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) -{ - return sys_acl_create_entry(pacl, pentry); -} - -int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - return sys_acl_set_tag_type(entry, tagtype); -} - -int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual) -{ - return sys_acl_set_qualifier(entry, qual); -} - -int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) -{ - return sys_acl_set_permset(entry, permset); -} - -int vfswrap_sys_acl_valid(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl ) -{ - return sys_acl_valid(theacl ); -} - -int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) -{ - return sys_acl_set_file(name, acltype, theacl); -} - -int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl) -{ - return sys_acl_set_fd(fd, theacl); -} - -int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path) -{ - return sys_acl_delete_def_file(path); -} - -int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return sys_acl_get_perm(permset, perm); -} - -int vfswrap_sys_acl_free_text(vfs_handle_struct *handle, connection_struct *conn, char *text) -{ - return sys_acl_free_text(text); -} - -int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T posix_acl) -{ - return sys_acl_free_acl(posix_acl); -} - -int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype) -{ - return sys_acl_free_qualifier(qualifier, tagtype); -} - -/**************************************************************** - Extended attribute operations. -*****************************************************************/ - -ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size) -{ - return sys_getxattr(path, name, value, size); -} - -ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size) -{ - return sys_lgetxattr(path, name, value, size); -} - -ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size) -{ - return sys_fgetxattr(fd, name, value, size); -} - -ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size) -{ - return sys_listxattr(path, list, size); -} - -ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size) -{ - return sys_llistxattr(path, list, size); -} - -ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size) -{ - return sys_flistxattr(fd, list, size); -} - -int vfswrap_removexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name) -{ - return sys_removexattr(path, name); -} - -int vfswrap_lremovexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name) -{ - return sys_lremovexattr(path, name); -} - -int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name) -{ - return sys_fremovexattr(fd, name); -} - -int vfswrap_setxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags) -{ - return sys_setxattr(path, name, value, size, flags); -} - -int vfswrap_lsetxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags) -{ - return sys_lsetxattr(path, name, value, size, flags); -} - -int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags) -{ - return sys_fsetxattr(fd, name, value, size, flags); -} - -int vfswrap_aio_read(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) -{ - return sys_aio_read(aiocb); -} - -int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) -{ - return sys_aio_write(aiocb); -} - -ssize_t vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) -{ - return sys_aio_return(aiocb); -} - -int vfswrap_aio_cancel(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_STRUCT_AIOCB *aiocb) -{ - return sys_aio_cancel(fd, aiocb); -} - -int vfswrap_aio_error(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb) -{ - return sys_aio_error(aiocb); -} - -int vfswrap_aio_fsync(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb) -{ - return sys_aio_fsync(op, aiocb); -} - -int vfswrap_aio_suspend(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_AIOCB * const aiocb[], int n, const struct timespec *timeout) -{ - return sys_aio_suspend(aiocb, n, timeout); -} diff --git a/source/smbd/vfs.c b/source/smbd/vfs.c index 2c9403a0790..7bb5f798f97 100644 --- a/source/smbd/vfs.c +++ b/source/smbd/vfs.c @@ -4,6 +4,7 @@ VFS initialisation and support functions Copyright (C) Tim Potter 1999 Copyright (C) Alexander Bokovoy 2002 + Copyright (C) James Peach 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -37,131 +38,6 @@ struct vfs_init_function_entry { static struct vfs_init_function_entry *backends = NULL; -/* Some structures to help us initialise the vfs operations table */ - -struct vfs_syminfo { - char *name; - void *fptr; -}; - -/* Default vfs hooks. WARNING: The order of these initialisers is - very important. They must be in the same order as defined in - vfs.h. Change at your own peril. */ - -static struct vfs_ops default_vfs = { - - { - /* Disk operations */ - - vfswrap_dummy_connect, - vfswrap_dummy_disconnect, - vfswrap_disk_free, - vfswrap_get_quota, - vfswrap_set_quota, - vfswrap_get_shadow_copy_data, - vfswrap_statvfs, - - /* Directory operations */ - - vfswrap_opendir, - vfswrap_readdir, - vfswrap_seekdir, - vfswrap_telldir, - vfswrap_rewinddir, - vfswrap_mkdir, - vfswrap_rmdir, - vfswrap_closedir, - - /* File operations */ - - vfswrap_open, - vfswrap_close, - vfswrap_read, - vfswrap_pread, - vfswrap_write, - vfswrap_pwrite, - vfswrap_lseek, - vfswrap_sendfile, - vfswrap_rename, - vfswrap_fsync, - vfswrap_stat, - vfswrap_fstat, - vfswrap_lstat, - vfswrap_unlink, - vfswrap_chmod, - vfswrap_fchmod, - vfswrap_chown, - vfswrap_fchown, - vfswrap_chdir, - vfswrap_getwd, - vfswrap_utime, - vfswrap_ftruncate, - vfswrap_lock, - vfswrap_getlock, - vfswrap_symlink, - vfswrap_readlink, - vfswrap_link, - vfswrap_mknod, - vfswrap_realpath, - - /* Windows ACL operations. */ - vfswrap_fget_nt_acl, - vfswrap_get_nt_acl, - vfswrap_fset_nt_acl, - vfswrap_set_nt_acl, - - /* POSIX ACL operations. */ - vfswrap_chmod_acl, - vfswrap_fchmod_acl, - - vfswrap_sys_acl_get_entry, - vfswrap_sys_acl_get_tag_type, - vfswrap_sys_acl_get_permset, - vfswrap_sys_acl_get_qualifier, - vfswrap_sys_acl_get_file, - vfswrap_sys_acl_get_fd, - vfswrap_sys_acl_clear_perms, - vfswrap_sys_acl_add_perm, - vfswrap_sys_acl_to_text, - vfswrap_sys_acl_init, - vfswrap_sys_acl_create_entry, - vfswrap_sys_acl_set_tag_type, - vfswrap_sys_acl_set_qualifier, - vfswrap_sys_acl_set_permset, - vfswrap_sys_acl_valid, - vfswrap_sys_acl_set_file, - vfswrap_sys_acl_set_fd, - vfswrap_sys_acl_delete_def_file, - vfswrap_sys_acl_get_perm, - vfswrap_sys_acl_free_text, - vfswrap_sys_acl_free_acl, - vfswrap_sys_acl_free_qualifier, - - /* EA operations. */ - vfswrap_getxattr, - vfswrap_lgetxattr, - vfswrap_fgetxattr, - vfswrap_listxattr, - vfswrap_llistxattr, - vfswrap_flistxattr, - vfswrap_removexattr, - vfswrap_lremovexattr, - vfswrap_fremovexattr, - vfswrap_setxattr, - vfswrap_lsetxattr, - vfswrap_fsetxattr, - - /* AIO operations. */ - vfswrap_aio_read, - vfswrap_aio_write, - vfswrap_aio_return, - vfswrap_aio_cancel, - vfswrap_aio_error, - vfswrap_aio_fsync, - vfswrap_aio_suspend - } -}; - /**************************************************************************** maintain the list of available backends ****************************************************************************/ @@ -217,15 +93,20 @@ NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tu static void vfs_init_default(connection_struct *conn) { DEBUG(3, ("Initialising default vfs hooks\n")); - - memcpy(&conn->vfs.ops, &default_vfs.ops, sizeof(default_vfs.ops)); - memcpy(&conn->vfs_opaque.ops, &default_vfs.ops, sizeof(default_vfs.ops)); + vfs_init_custom(conn, DEFAULT_VFS_MODULE_NAME); } /**************************************************************************** initialise custom vfs hooks ****************************************************************************/ +static inline void vfs_set_operation(struct vfs_ops * vfs, vfs_op_type which, + struct vfs_handle_struct * handle, void * op) +{ + ((struct vfs_handle_struct **)&vfs->handles)[which] = handle; + ((void**)&vfs->ops)[which] = op; +} + BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) { vfs_op_tuple *ops; @@ -292,18 +173,15 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) for(i=0; ops[i].op != NULL; i++) { DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer)); if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) { - /* Check whether this operation was already made opaque by different module */ - if(((void**)&conn->vfs_opaque.ops)[ops[i].type] == ((void**)&default_vfs.ops)[ops[i].type]) { - /* No, it isn't overloaded yet. Overload. */ - DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); - ((void**)&conn->vfs_opaque.ops)[ops[i].type] = ops[i].op; - ((vfs_handle_struct **)&conn->vfs_opaque.handles)[ops[i].type] = handle; - } + /* If this operation was already made opaque by different module, it + * will be overridded here. + */ + DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); + vfs_set_operation(&conn->vfs_opaque, ops[i].type, handle, ops[i].op); } /* Change current VFS disposition*/ DEBUGADD(5, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object)); - ((void**)&conn->vfs.ops)[ops[i].type] = ops[i].op; - ((vfs_handle_struct **)&conn->vfs.handles)[ops[i].type] = handle; + vfs_set_operation(&conn->vfs, ops[i].type, handle, ops[i].op); } SAFE_FREE(module_name); @@ -311,6 +189,71 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) } /***************************************************************** + Allow VFS modules to extend files_struct with VFS-specific state. + This will be ok for small numbers of extensions, but might need to + be refactored if it becomes more widely used. +******************************************************************/ + +#define EXT_DATA_AREA(e) ((uint8 *)(e) + sizeof(struct vfs_fsp_data)) + +void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle, files_struct *fsp, size_t ext_size) +{ + struct vfs_fsp_data *ext; + void * ext_data; + + /* Prevent VFS modules adding multiple extensions. */ + if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) { + return ext_data; + } + + ext = TALLOC_ZERO(handle->conn->mem_ctx, + sizeof(struct vfs_fsp_data) + ext_size); + if (ext == NULL) { + return NULL; + } + + ext->owner = handle; + ext->next = fsp->vfs_extension; + fsp->vfs_extension = ext; + return EXT_DATA_AREA(ext); +} + +void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp) +{ + struct vfs_fsp_data *curr; + struct vfs_fsp_data *prev; + + for (curr = fsp->vfs_extension, prev = NULL; + curr; + prev = curr, curr = curr->next) { + if (curr->owner == handle) { + if (prev) { + prev->next = curr->next; + } else { + fsp->vfs_extension = curr->next; + } + TALLOC_FREE(curr); + return; + } + } +} + +void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp) +{ + struct vfs_fsp_data *head; + + for (head = fsp->vfs_extension; head; head = head->next) { + if (head->owner == handle) { + return EXT_DATA_AREA(head); + } + } + + return NULL; +} + +#undef EXT_DATA_AREA + +/***************************************************************** Generic VFS init. ******************************************************************/ diff --git a/source/smbwrapper/smbw.c b/source/smbwrapper/smbw.c index d4a5b51af4e..89ae9396aaf 100644 --- a/source/smbwrapper/smbw.c +++ b/source/smbwrapper/smbw.c @@ -432,7 +432,7 @@ return a connection to a server (existing or new) struct smbw_server *smbw_server(char *server, char *share) { struct smbw_server *srv=NULL; - struct cli_state c; + struct cli_state *c; char *username; char *password; char *workgroup; @@ -499,13 +499,13 @@ struct smbw_server *smbw_server(char *server, char *share) } /* have to open a new connection */ - if (!cli_initialise(&c) || !cli_connect(&c, server_n, &ip)) { + if (((c = cli_initialise()) == NULL) || !cli_connect(c, server_n, &ip)) { errno = ENOENT; return NULL; } - if (!cli_session_request(&c, &calling, &called)) { - cli_shutdown(&c); + if (!cli_session_request(c, &calling, &called)) { + cli_shutdown(c); if (strcmp(called.name, "*SMBSERVER")) { make_nmb_name(&called , "*SMBSERVER", 0x20); goto again; @@ -516,29 +516,29 @@ struct smbw_server *smbw_server(char *server, char *share) DEBUG(4,(" session request ok\n")); - if (!cli_negprot(&c)) { - cli_shutdown(&c); + if (!cli_negprot(c)) { + cli_shutdown(c); errno = ENOENT; return NULL; } - if (!cli_session_setup(&c, username, + if (!cli_session_setup(c, username, password, strlen(password), password, strlen(password), workgroup) && /* try an anonymous login if it failed */ - !cli_session_setup(&c, "", "", 1,"", 0, workgroup)) { - cli_shutdown(&c); + !cli_session_setup(c, "", "", 1,"", 0, workgroup)) { + cli_shutdown(c); errno = EPERM; return NULL; } DEBUG(4,(" session setup ok\n")); - if (!cli_send_tconX(&c, share, "?????", + if (!cli_send_tconX(c, share, "?????", password, strlen(password)+1)) { - errno = smbw_errno(&c); - cli_shutdown(&c); + errno = smbw_errno(c); + cli_shutdown(c); return NULL; } @@ -584,11 +584,11 @@ struct smbw_server *smbw_server(char *server, char *share) /* some programs play with file descriptors fairly intimately. We try to get out of the way by duping to a high fd number */ - if (fcntl(SMBW_CLI_FD + srv->cli.fd, F_GETFD) && errno == EBADF) { - if (dup2(srv->cli.fd,SMBW_CLI_FD+srv->cli.fd) == - srv->cli.fd+SMBW_CLI_FD) { - close(srv->cli.fd); - srv->cli.fd += SMBW_CLI_FD; + if (fcntl(SMBW_CLI_FD + srv->cli->fd, F_GETFD) && errno == EBADF) { + if (dup2(srv->cli->fd,SMBW_CLI_FD+srv->cli->fd) == + srv->cli->fd+SMBW_CLI_FD) { + close(srv->cli->fd); + srv->cli->fd += SMBW_CLI_FD; } } @@ -597,7 +597,7 @@ struct smbw_server *smbw_server(char *server, char *share) return srv; failed: - cli_shutdown(&c); + cli_shutdown(c); if (!srv) return NULL; SAFE_FREE(srv->server_name); diff --git a/source/smbwrapper/smbw.h b/source/smbwrapper/smbw.h index 3f0b1cbb443..f64cb209649 100644 --- a/source/smbwrapper/smbw.h +++ b/source/smbwrapper/smbw.h @@ -32,7 +32,7 @@ struct smbw_server { struct smbw_server *next, *prev; - struct cli_state cli; + struct cli_state *cli; char *server_name; char *share_name; char *workgroup; diff --git a/source/tdb/dump.c b/source/tdb/dump.c new file mode 100644 index 00000000000..577f23aac68 --- /dev/null +++ b/source/tdb/dump.c @@ -0,0 +1,135 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tdb_private.h" + +static tdb_off_t tdb_dump_record(struct tdb_context *tdb, tdb_off_t offset) +{ + struct list_struct rec; + tdb_off_t tailer_ofs, tailer; + + if (tdb->methods->tdb_read(tdb, offset, (char *)&rec, + sizeof(rec), DOCONV()) == -1) { + printf("ERROR: failed to read record at %u\n", offset); + return 0; + } + + printf(" rec: offset=0x%08x next=0x%08x rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n", + offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, rec.full_hash, rec.magic); + + tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off_t); + + if (tdb_ofs_read(tdb, tailer_ofs, &tailer) == -1) { + printf("ERROR: failed to read tailer at %u\n", tailer_ofs); + return rec.next; + } + + if (tailer != rec.rec_len + sizeof(rec)) { + printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", + (unsigned int)tailer, (unsigned int)(rec.rec_len + sizeof(rec))); + } + return rec.next; +} + +static int tdb_dump_chain(struct tdb_context *tdb, int i) +{ + tdb_off_t rec_ptr, top; + + top = TDB_HASH_TOP(i); + + if (tdb_lock(tdb, i, F_WRLCK) != 0) + return -1; + + if (tdb_ofs_read(tdb, top, &rec_ptr) == -1) + return tdb_unlock(tdb, i, F_WRLCK); + + if (rec_ptr) + printf("hash=%d\n", i); + + while (rec_ptr) { + rec_ptr = tdb_dump_record(tdb, rec_ptr); + } + + return tdb_unlock(tdb, i, F_WRLCK); +} + +void tdb_dump_all(struct tdb_context *tdb) +{ + int i; + for (i=0;i<tdb->header.hash_size;i++) { + tdb_dump_chain(tdb, i); + } + printf("freelist:\n"); + tdb_dump_chain(tdb, -1); +} + +int tdb_printfreelist(struct tdb_context *tdb) +{ + int ret; + long total_free = 0; + tdb_off_t offset, rec_ptr; + struct list_struct rec; + + if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0) + return ret; + + offset = FREELIST_TOP; + + /* read in the freelist top */ + if (tdb_ofs_read(tdb, offset, &rec_ptr) == -1) { + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + } + + printf("freelist top=[0x%08x]\n", rec_ptr ); + while (rec_ptr) { + if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec, + sizeof(rec), DOCONV()) == -1) { + tdb_unlock(tdb, -1, F_WRLCK); + return -1; + } + + if (rec.magic != TDB_FREE_MAGIC) { + printf("bad magic 0x%08x in free list\n", rec.magic); + tdb_unlock(tdb, -1, F_WRLCK); + return -1; + } + + printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n", + rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len); + total_free += rec.rec_len; + + /* move to the next record */ + rec_ptr = rec.next; + } + printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, + (int)total_free); + + return tdb_unlock(tdb, -1, F_WRLCK); +} + diff --git a/source/tdb/error.c b/source/tdb/error.c new file mode 100644 index 00000000000..4cf33a29ab2 --- /dev/null +++ b/source/tdb/error.c @@ -0,0 +1,58 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tdb_private.h" + +enum TDB_ERROR tdb_error(struct tdb_context *tdb) +{ + return tdb->ecode; +} + +static struct tdb_errname { + enum TDB_ERROR ecode; const char *estring; +} emap[] = { {TDB_SUCCESS, "Success"}, + {TDB_ERR_CORRUPT, "Corrupt database"}, + {TDB_ERR_IO, "IO Error"}, + {TDB_ERR_LOCK, "Locking error"}, + {TDB_ERR_OOM, "Out of memory"}, + {TDB_ERR_EXISTS, "Record exists"}, + {TDB_ERR_NOLOCK, "Lock exists on other keys"}, + {TDB_ERR_EINVAL, "Invalid parameter"}, + {TDB_ERR_NOEXIST, "Record does not exist"}, + {TDB_ERR_RDONLY, "write not permitted"} }; + +/* Error string for the last tdb error */ +const char *tdb_errorstr(struct tdb_context *tdb) +{ + u32 i; + for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++) + if (tdb->ecode == emap[i].ecode) + return emap[i].estring; + return "Invalid error code"; +} + diff --git a/source/tdb/freelist.c b/source/tdb/freelist.c new file mode 100644 index 00000000000..34837511647 --- /dev/null +++ b/source/tdb/freelist.c @@ -0,0 +1,331 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tdb_private.h" + +/* read a freelist record and check for simple errors */ +static int rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec) +{ + if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) + return -1; + + if (rec->magic == TDB_MAGIC) { + /* this happens when a app is showdown while deleting a record - we should + not completely fail when this happens */ + TDB_LOG((tdb, 0,"rec_free_read non-free magic 0x%x at offset=%d - fixing\n", + rec->magic, off)); + rec->magic = TDB_FREE_MAGIC; + if (tdb->methods->tdb_write(tdb, off, rec, sizeof(*rec)) == -1) + return -1; + } + + if (rec->magic != TDB_FREE_MAGIC) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, 0,"rec_free_read bad magic 0x%x at offset=%d\n", + rec->magic, off)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); + } + if (tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0) + return -1; + return 0; +} + + + +/* Remove an element from the freelist. Must have alloc lock. */ +static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_t next) +{ + tdb_off_t last_ptr, i; + + /* read in the freelist top */ + last_ptr = FREELIST_TOP; + while (tdb_ofs_read(tdb, last_ptr, &i) != -1 && i != 0) { + if (i == off) { + /* We've found it! */ + return tdb_ofs_write(tdb, last_ptr, &next); + } + /* Follow chain (next offset is at start of record) */ + last_ptr = i; + } + TDB_LOG((tdb, 0,"remove_from_freelist: not on list at off=%d\n", off)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); +} + + +/* update a record tailer (must hold allocation lock) */ +static int update_tailer(struct tdb_context *tdb, tdb_off_t offset, + const struct list_struct *rec) +{ + tdb_off_t totalsize; + + /* Offset of tailer from record header */ + totalsize = sizeof(*rec) + rec->rec_len; + return tdb_ofs_write(tdb, offset + totalsize - sizeof(tdb_off_t), + &totalsize); +} + +/* Add an element into the freelist. Merge adjacent records if + neccessary. */ +int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) +{ + tdb_off_t right, left; + + /* Allocation and tailer lock */ + if (tdb_lock(tdb, -1, F_WRLCK) != 0) + return -1; + + /* set an initial tailer, so if we fail we don't leave a bogus record */ + if (update_tailer(tdb, offset, rec) != 0) { + TDB_LOG((tdb, 0, "tdb_free: upfate_tailer failed!\n")); + goto fail; + } + + /* Look right first (I'm an Australian, dammit) */ + right = offset + sizeof(*rec) + rec->rec_len; + if (right + sizeof(*rec) <= tdb->map_size) { + struct list_struct r; + + if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { + TDB_LOG((tdb, 0, "tdb_free: right read failed at %u\n", right)); + goto left; + } + + /* If it's free, expand to include it. */ + if (r.magic == TDB_FREE_MAGIC) { + if (remove_from_freelist(tdb, right, r.next) == -1) { + TDB_LOG((tdb, 0, "tdb_free: right free failed at %u\n", right)); + goto left; + } + rec->rec_len += sizeof(r) + r.rec_len; + } + } + +left: + /* Look left */ + left = offset - sizeof(tdb_off_t); + if (left > TDB_DATA_START(tdb->header.hash_size)) { + struct list_struct l; + tdb_off_t leftsize; + + /* Read in tailer and jump back to header */ + if (tdb_ofs_read(tdb, left, &leftsize) == -1) { + TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left)); + goto update; + } + + /* it could be uninitialised data */ + if (leftsize == 0 || leftsize == TDB_PAD_U32) { + goto update; + } + + left = offset - leftsize; + + /* Now read in record */ + if (tdb->methods->tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { + TDB_LOG((tdb, 0, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); + goto update; + } + + /* If it's free, expand to include it. */ + if (l.magic == TDB_FREE_MAGIC) { + if (remove_from_freelist(tdb, left, l.next) == -1) { + TDB_LOG((tdb, 0, "tdb_free: left free failed at %u\n", left)); + goto update; + } else { + offset = left; + rec->rec_len += leftsize; + } + } + } + +update: + if (update_tailer(tdb, offset, rec) == -1) { + TDB_LOG((tdb, 0, "tdb_free: update_tailer failed at %u\n", offset)); + goto fail; + } + + /* Now, prepend to free list */ + rec->magic = TDB_FREE_MAGIC; + + if (tdb_ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || + tdb_rec_write(tdb, offset, rec) == -1 || + tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) { + TDB_LOG((tdb, 0, "tdb_free record write failed at offset=%d\n", offset)); + goto fail; + } + + /* And we're done. */ + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return -1; +} + + +/* + the core of tdb_allocate - called when we have decided which + free list entry to use + */ +static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, tdb_len_t length, tdb_off_t rec_ptr, + struct list_struct *rec, tdb_off_t last_ptr) +{ + struct list_struct newrec; + tdb_off_t newrec_ptr; + + memset(&newrec, '\0', sizeof(newrec)); + + /* found it - now possibly split it up */ + if (rec->rec_len > length + MIN_REC_SIZE) { + /* Length of left piece */ + length = TDB_ALIGN(length, TDB_ALIGNMENT); + + /* Right piece to go on free list */ + newrec.rec_len = rec->rec_len - (sizeof(*rec) + length); + newrec_ptr = rec_ptr + sizeof(*rec) + length; + + /* And left record is shortened */ + rec->rec_len = length; + } else { + newrec_ptr = 0; + } + + /* Remove allocated record from the free list */ + if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) { + return 0; + } + + /* Update header: do this before we drop alloc + lock, otherwise tdb_free() might try to + merge with us, thinking we're free. + (Thanks Jeremy Allison). */ + rec->magic = TDB_MAGIC; + if (tdb_rec_write(tdb, rec_ptr, rec) == -1) { + return 0; + } + + /* Did we create new block? */ + if (newrec_ptr) { + /* Update allocated record tailer (we + shortened it). */ + if (update_tailer(tdb, rec_ptr, rec) == -1) { + return 0; + } + + /* Free new record */ + if (tdb_free(tdb, newrec_ptr, &newrec) == -1) { + return 0; + } + } + + /* all done - return the new record offset */ + return rec_ptr; +} + +/* allocate some space from the free list. The offset returned points + to a unconnected list_struct within the database with room for at + least length bytes of total data + + 0 is returned if the space could not be allocated + */ +tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec) +{ + tdb_off_t rec_ptr, last_ptr, newrec_ptr; + struct { + tdb_off_t rec_ptr, last_ptr; + tdb_len_t rec_len; + } bestfit; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) + return 0; + + /* Extra bytes required for tailer */ + length += sizeof(tdb_off_t); + + again: + last_ptr = FREELIST_TOP; + + /* read in the freelist top */ + if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) + goto fail; + + bestfit.rec_ptr = 0; + bestfit.last_ptr = 0; + bestfit.rec_len = 0; + + /* + this is a best fit allocation strategy. Originally we used + a first fit strategy, but it suffered from massive fragmentation + issues when faced with a slowly increasing record size. + */ + while (rec_ptr) { + if (rec_free_read(tdb, rec_ptr, rec) == -1) { + goto fail; + } + + if (rec->rec_len >= length) { + if (bestfit.rec_ptr == 0 || + rec->rec_len < bestfit.rec_len) { + bestfit.rec_len = rec->rec_len; + bestfit.rec_ptr = rec_ptr; + bestfit.last_ptr = last_ptr; + /* consider a fit to be good enough if + we aren't wasting more than half + the space */ + if (bestfit.rec_len < 2*length) { + break; + } + } + } + + /* move to the next record */ + last_ptr = rec_ptr; + rec_ptr = rec->next; + } + + if (bestfit.rec_ptr != 0) { + if (rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) { + goto fail; + } + + newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr); + tdb_unlock(tdb, -1, F_WRLCK); + return newrec_ptr; + } + + /* we didn't find enough space. See if we can expand the + database and if we can then try again */ + if (tdb_expand(tdb, length + sizeof(*rec)) == 0) + goto again; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return 0; +} + diff --git a/source/tdb/io.c b/source/tdb/io.c new file mode 100644 index 00000000000..ac6f4cdf573 --- /dev/null +++ b/source/tdb/io.c @@ -0,0 +1,412 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "tdb_private.h" + +#ifndef HAVE_PREAD + static ssize_t pread(int fd, void *buf, size_t count, off_t offset) +{ + if (lseek(fd, offset, SEEK_SET) != offset) { + errno = EIO; + return -1; + } + return read(fd, buf, count); +} +#endif + +#ifndef HAVE_PWRITE + static ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + if (lseek(fd, offset, SEEK_SET) != offset) { + errno = EIO; + return -1; + } + return write(fd, buf, count); +} +#endif + +/* check for an out of bounds access - if it is out of bounds then + see if the database has been expanded by someone else and expand + if necessary + note that "len" is the minimum length needed for the db +*/ +static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) +{ + struct stat st; + if (len <= tdb->map_size) + return 0; + if (tdb->flags & TDB_INTERNAL) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_oob len %d beyond internal malloc size %d\n", + (int)len, (int)tdb->map_size)); + } + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + + if (fstat(tdb->fd, &st) == -1) { + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + + if (st.st_size < (size_t)len) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_oob len %d beyond eof at %d\n", + (int)len, (int)st.st_size)); + } + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + + /* Unmap, update size, remap */ + if (tdb_munmap(tdb) == -1) + return TDB_ERRCODE(TDB_ERR_IO, -1); + tdb->map_size = st.st_size; + tdb_mmap(tdb); + return 0; +} + +/* write a lump of data at a specified offset */ +static int tdb_write(struct tdb_context *tdb, tdb_off_t off, + const void *buf, tdb_len_t len) +{ + if (len == 0) { + return 0; + } + + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) + return -1; + + if (tdb->map_ptr) { + memcpy(off + (char *)tdb->map_ptr, buf, len); + } else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_write failed at %d len=%d (%s)\n", + off, len, strerror(errno))); + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + return 0; +} + +/* Endian conversion: we only ever deal with 4 byte quantities */ +void *tdb_convert(void *buf, u32 size) +{ + u32 i, *p = buf; + for (i = 0; i < size / 4; i++) + p[i] = TDB_BYTEREV(p[i]); + return buf; +} + + +/* read a lump of data at a specified offset, maybe convert */ +static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, + tdb_len_t len, int cv) +{ + if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) { + return -1; + } + + if (tdb->map_ptr) { + memcpy(buf, off + (char *)tdb->map_ptr, len); + } else { + ssize_t ret = pread(tdb->fd, buf, len, off); + if (ret != (ssize_t)len) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_read failed at %d len=%d ret=%d (%s) map_size=%d\n", + off, len, (int)ret, strerror(errno), (int)tdb->map_size)); + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + } + if (cv) { + tdb_convert(buf, len); + } + return 0; +} + + + +/* + do an unlocked scan of the hash table heads to find the next non-zero head. The value + will then be confirmed with the lock held +*/ +static void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain) +{ + u32 h = *chain; + if (tdb->map_ptr) { + for (;h < tdb->header.hash_size;h++) { + if (0 != *(u32 *)(TDB_HASH_TOP(h) + (unsigned char *)tdb->map_ptr)) { + break; + } + } + } else { + u32 off=0; + for (;h < tdb->header.hash_size;h++) { + if (tdb_ofs_read(tdb, TDB_HASH_TOP(h), &off) != 0 || off != 0) { + break; + } + } + } + (*chain) = h; +} + + +int tdb_munmap(struct tdb_context *tdb) +{ + if (tdb->flags & TDB_INTERNAL) + return 0; + +#ifdef HAVE_MMAP + if (tdb->map_ptr) { + int ret = munmap(tdb->map_ptr, tdb->map_size); + if (ret != 0) + return ret; + } +#endif + tdb->map_ptr = NULL; + return 0; +} + +void tdb_mmap(struct tdb_context *tdb) +{ + if (tdb->flags & TDB_INTERNAL) + return; + +#ifdef HAVE_MMAP + if (!(tdb->flags & TDB_NOMMAP)) { + tdb->map_ptr = mmap(NULL, tdb->map_size, + PROT_READ|(tdb->read_only? 0:PROT_WRITE), + MAP_SHARED|MAP_FILE, tdb->fd, 0); + + /* + * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!! + */ + + if (tdb->map_ptr == MAP_FAILED) { + tdb->map_ptr = NULL; + TDB_LOG((tdb, 2, "tdb_mmap failed for size %d (%s)\n", + tdb->map_size, strerror(errno))); + } + } else { + tdb->map_ptr = NULL; + } +#else + tdb->map_ptr = NULL; +#endif +} + +/* expand a file. we prefer to use ftruncate, as that is what posix + says to use for mmap expansion */ +static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t addition) +{ + char buf[1024]; + + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + if (ftruncate(tdb->fd, size+addition) == -1) { + char b = 0; + if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) { + TDB_LOG((tdb, 0, "expand_file to %d failed (%s)\n", + size+addition, strerror(errno))); + return -1; + } + } + + /* now fill the file with something. This ensures that the + file isn't sparse, which would be very bad if we ran out of + disk. This must be done with write, not via mmap */ + memset(buf, TDB_PAD_BYTE, sizeof(buf)); + while (addition) { + int n = addition>sizeof(buf)?sizeof(buf):addition; + int ret = pwrite(tdb->fd, buf, n, size); + if (ret != n) { + TDB_LOG((tdb, 0, "expand_file write of %d failed (%s)\n", + n, strerror(errno))); + return -1; + } + addition -= n; + size += n; + } + return 0; +} + + +/* expand the database at least size bytes by expanding the underlying + file and doing the mmap again if necessary */ +int tdb_expand(struct tdb_context *tdb, tdb_off_t size) +{ + struct list_struct rec; + tdb_off_t offset; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + TDB_LOG((tdb, 0, "lock failed in tdb_expand\n")); + return -1; + } + + /* must know about any previous expansions by another process */ + tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1); + + /* always make room for at least 10 more records, and round + the database up to a multiple of the page size */ + size = TDB_ALIGN(tdb->map_size + size*10, tdb->page_size) - tdb->map_size; + + if (!(tdb->flags & TDB_INTERNAL)) + tdb_munmap(tdb); + + /* + * We must ensure the file is unmapped before doing this + * to ensure consistency with systems like OpenBSD where + * writes and mmaps are not consistent. + */ + + /* expand the file itself */ + if (!(tdb->flags & TDB_INTERNAL)) { + if (tdb->methods->tdb_expand_file(tdb, tdb->map_size, size) != 0) + goto fail; + } + + tdb->map_size += size; + + if (tdb->flags & TDB_INTERNAL) { + char *new_map_ptr = realloc(tdb->map_ptr, tdb->map_size); + if (!new_map_ptr) { + tdb->map_size -= size; + goto fail; + } + tdb->map_ptr = new_map_ptr; + } else { + /* + * We must ensure the file is remapped before adding the space + * to ensure consistency with systems like OpenBSD where + * writes and mmaps are not consistent. + */ + + /* We're ok if the mmap fails as we'll fallback to read/write */ + tdb_mmap(tdb); + } + + /* form a new freelist record */ + memset(&rec,'\0',sizeof(rec)); + rec.rec_len = size - sizeof(rec); + + /* link it into the free list */ + offset = tdb->map_size - size; + if (tdb_free(tdb, offset, &rec) == -1) + goto fail; + + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return -1; +} + +/* read/write a tdb_off_t */ +int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) +{ + return tdb->methods->tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); +} + +int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) +{ + tdb_off_t off = *d; + return tdb->methods->tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); +} + + +/* read a lump of data, allocating the space for it */ +char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len) +{ + char *buf; + + /* some systems don't like zero length malloc */ + if (len == 0) { + len = 1; + } + + if (!(buf = malloc(len))) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_OOM; + TDB_LOG((tdb, 0,"tdb_alloc_read malloc failed len=%d (%s)\n", + len, strerror(errno))); + return TDB_ERRCODE(TDB_ERR_OOM, buf); + } + if (tdb->methods->tdb_read(tdb, offset, buf, len, 0) == -1) { + SAFE_FREE(buf); + return NULL; + } + return buf; +} + +/* read/write a record */ +int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) +{ + if (tdb->methods->tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) + return -1; + if (TDB_BAD_MAGIC(rec)) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, 0,"tdb_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); + } + return tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0); +} + +int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) +{ + struct list_struct r = *rec; + return tdb->methods->tdb_write(tdb, offset, CONVERT(r), sizeof(r)); +} + +static const struct tdb_methods io_methods = { + tdb_read, + tdb_write, + tdb_next_hash_chain, + tdb_oob, + tdb_expand_file, + tdb_brlock +}; + +/* + initialise the default methods table +*/ +void tdb_io_init(struct tdb_context *tdb) +{ + tdb->methods = &io_methods; +} diff --git a/source/tdb/lock.c b/source/tdb/lock.c new file mode 100644 index 00000000000..a96d77a229a --- /dev/null +++ b/source/tdb/lock.c @@ -0,0 +1,276 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tdb_private.h" + +/* a byte range locking function - return 0 on success + this functions locks/unlocks 1 byte at the specified offset. + + On error, errno is also set so that errors are passed back properly + through tdb_open(). + + note that a len of zero means lock to end of file +*/ +int tdb_brlock_len(struct tdb_context *tdb, tdb_off_t offset, + int rw_type, int lck_type, int probe, size_t len) +{ + struct flock fl; + int ret; + + if (tdb->flags & TDB_NOLOCK) { + return 0; + } + + if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + fl.l_type = rw_type; + fl.l_whence = SEEK_SET; + fl.l_start = offset; + fl.l_len = len; + fl.l_pid = 0; + + do { + ret = fcntl(tdb->fd,lck_type,&fl); + } while (ret == -1 && errno == EINTR); + + if (ret == -1) { + /* Generic lock error. errno set by fcntl. + * EAGAIN is an expected return from non-blocking + * locks. */ + if (!probe && lck_type != F_SETLK) { + /* Ensure error code is set for log fun to examine. */ + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n", + tdb->fd, offset, rw_type, lck_type, (int)len)); + } + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + return 0; +} + + +/* + upgrade a read lock to a write lock. This needs to be handled in a + special way as some OSes (such as solaris) have too conservative + deadlock detection and claim a deadlock when progress can be + made. For those OSes we may loop for a while. +*/ +int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len) +{ + int count = 1000; + while (count--) { + struct timeval tv; + if (tdb_brlock_len(tdb, offset, F_WRLCK, F_SETLKW, 1, len) == 0) { + return 0; + } + if (errno != EDEADLK) { + break; + } + /* sleep for as short a time as we can - more portable than usleep() */ + tv.tv_sec = 0; + tv.tv_usec = 1; + select(0, NULL, NULL, NULL, &tv); + } + TDB_LOG((tdb, 5,"tdb_brlock_upgrade failed at offset %d\n", offset)); + return -1; +} + + +/* a byte range locking function - return 0 on success + this functions locks/unlocks 1 byte at the specified offset. + + On error, errno is also set so that errors are passed back properly + through tdb_open(). */ +int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, + int rw_type, int lck_type, int probe) +{ + return tdb_brlock_len(tdb, offset, rw_type, lck_type, probe, 1); +} + +/* lock a list in the database. list -1 is the alloc list */ +int tdb_lock(struct tdb_context *tdb, int list, int ltype) +{ + if (list < -1 || list >= (int)tdb->header.hash_size) { + TDB_LOG((tdb, 0,"tdb_lock: invalid list %d for ltype=%d\n", + list, ltype)); + return -1; + } + if (tdb->flags & TDB_NOLOCK) + return 0; + + /* Since fcntl locks don't nest, we do a lock for the first one, + and simply bump the count for future ones */ + if (tdb->locked[list+1].count == 0) { + if (tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) { + TDB_LOG((tdb, 0,"tdb_lock failed on list %d ltype=%d (%s)\n", + list, ltype, strerror(errno))); + return -1; + } + tdb->locked[list+1].ltype = ltype; + tdb->num_locks++; + } + tdb->locked[list+1].count++; + return 0; +} + +/* unlock the database: returns void because it's too late for errors. */ + /* changed to return int it may be interesting to know there + has been an error --simo */ +int tdb_unlock(struct tdb_context *tdb, int list, int ltype) +{ + int ret = -1; + + if (tdb->flags & TDB_NOLOCK) + return 0; + + /* Sanity checks */ + if (list < -1 || list >= (int)tdb->header.hash_size) { + TDB_LOG((tdb, 0, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size)); + return ret; + } + + if (tdb->locked[list+1].count==0) { + TDB_LOG((tdb, 0, "tdb_unlock: count is 0\n")); + return ret; + } + + if (tdb->locked[list+1].count == 1) { + /* Down to last nested lock: unlock underneath */ + ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, F_SETLKW, 0); + tdb->num_locks--; + } else { + ret = 0; + } + tdb->locked[list+1].count--; + + if (ret) + TDB_LOG((tdb, 0,"tdb_unlock: An error occurred unlocking!\n")); + return ret; +} + + + +/* lock/unlock entire database */ +int tdb_lockall(struct tdb_context *tdb) +{ + u32 i; + + /* There are no locks on read-only dbs */ + if (tdb->read_only || tdb->traverse_read) + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + for (i = 0; i < tdb->header.hash_size; i++) + if (tdb_lock(tdb, i, F_WRLCK)) + break; + + /* If error, release locks we have... */ + if (i < tdb->header.hash_size) { + u32 j; + + for ( j = 0; j < i; j++) + tdb_unlock(tdb, j, F_WRLCK); + return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); + } + + return 0; +} +void tdb_unlockall(struct tdb_context *tdb) +{ + u32 i; + for (i=0; i < tdb->header.hash_size; i++) + tdb_unlock(tdb, i, F_WRLCK); +} + +/* lock/unlock one hash chain. This is meant to be used to reduce + contention - it cannot guarantee how many records will be locked */ +int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); +} + +int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); +} + +int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); +} + +int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); +} + + + +/* record lock stops delete underneath */ +int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off) +{ + return off ? tdb->methods->tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0) : 0; +} + +/* + Write locks override our own fcntl readlocks, so check it here. + Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not + an error to fail to get the lock here. +*/ +int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off) +{ + struct tdb_traverse_lock *i; + for (i = &tdb->travlocks; i; i = i->next) + if (i->off == off) + return -1; + return tdb->methods->tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1); +} + +/* + Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not + an error to fail to get the lock here. +*/ +int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off) +{ + return tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0); +} + +/* fcntl locks don't stack: avoid unlocking someone else's */ +int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off) +{ + struct tdb_traverse_lock *i; + u32 count = 0; + + if (off == 0) + return 0; + for (i = &tdb->travlocks; i; i = i->next) + if (i->off == off) + count++; + return (count == 1 ? tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0) : 0); +} diff --git a/source/tdb/open.c b/source/tdb/open.c new file mode 100644 index 00000000000..cb4a9cd9945 --- /dev/null +++ b/source/tdb/open.c @@ -0,0 +1,453 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tdb_private.h" + +/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */ +static struct tdb_context *tdbs = NULL; + + +/* This is based on the hash algorithm from gdbm */ +static unsigned int default_tdb_hash(TDB_DATA *key) +{ + u32 value; /* Used to compute the hash value. */ + u32 i; /* Used to cycle through random values. */ + + /* Set the initial value from the key size. */ + for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++) + value = (value + (key->dptr[i] << (i*5 % 24))); + + return (1103515243 * value + 12345); +} + + +/* initialise a new database with a specified hash size */ +static int tdb_new_database(struct tdb_context *tdb, int hash_size) +{ + struct tdb_header *newdb; + int size, ret = -1; + + /* We make it up in memory, then write it out if not internal */ + size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t); + if (!(newdb = calloc(size, 1))) + return TDB_ERRCODE(TDB_ERR_OOM, -1); + + /* Fill in the header */ + newdb->version = TDB_VERSION; + newdb->hash_size = hash_size; + if (tdb->flags & TDB_INTERNAL) { + tdb->map_size = size; + tdb->map_ptr = (char *)newdb; + memcpy(&tdb->header, newdb, sizeof(tdb->header)); + /* Convert the `ondisk' version if asked. */ + CONVERT(*newdb); + return 0; + } + if (lseek(tdb->fd, 0, SEEK_SET) == -1) + goto fail; + + if (ftruncate(tdb->fd, 0) == -1) + goto fail; + + /* This creates an endian-converted header, as if read from disk */ + CONVERT(*newdb); + memcpy(&tdb->header, newdb, sizeof(tdb->header)); + /* Don't endian-convert the magic food! */ + memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1); + if (write(tdb->fd, newdb, size) != size) { + ret = -1; + } else { + ret = 0; + } + + fail: + SAFE_FREE(newdb); + return ret; +} + + + +static int tdb_already_open(dev_t device, + ino_t ino) +{ + struct tdb_context *i; + + for (i = tdbs; i; i = i->next) { + if (i->device == device && i->inode == ino) { + return 1; + } + } + + return 0; +} + +/* open the database, creating it if necessary + + The open_flags and mode are passed straight to the open call on the + database file. A flags value of O_WRONLY is invalid. The hash size + is advisory, use zero for a default value. + + Return is NULL on error, in which case errno is also set. Don't + try to call tdb_error or tdb_errname, just do strerror(errno). + + @param name may be NULL for internal databases. */ +struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL); +} + +/* a default logging function */ +static void null_log_fn(struct tdb_context *tdb, int level, const char *fmt, ...) +{ +} + + +struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + tdb_log_func log_fn, + tdb_hash_func hash_fn) +{ + struct tdb_context *tdb; + struct stat st; + int rev = 0, locked = 0; + unsigned char *vp; + u32 vertest; + + if (!(tdb = calloc(1, sizeof *tdb))) { + /* Can't log this */ + errno = ENOMEM; + goto fail; + } + tdb_io_init(tdb); + tdb->fd = -1; + tdb->name = NULL; + tdb->map_ptr = NULL; + tdb->flags = tdb_flags; + tdb->open_flags = open_flags; + tdb->log_fn = log_fn?log_fn:null_log_fn; + tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; + + /* cache the page size */ + tdb->page_size = getpagesize(); + if (tdb->page_size <= 0) { + tdb->page_size = 0x2000; + } + + if ((open_flags & O_ACCMODE) == O_WRONLY) { + TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n", + name)); + errno = EINVAL; + goto fail; + } + + if (hash_size == 0) + hash_size = DEFAULT_HASH_SIZE; + if ((open_flags & O_ACCMODE) == O_RDONLY) { + tdb->read_only = 1; + /* read only databases don't do locking or clear if first */ + tdb->flags |= TDB_NOLOCK; + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + } + + /* internal databases don't mmap or lock, and start off cleared */ + if (tdb->flags & TDB_INTERNAL) { + tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + if (tdb_new_database(tdb, hash_size) != 0) { + TDB_LOG((tdb, 0, "tdb_open_ex: tdb_new_database failed!")); + goto fail; + } + goto internal; + } + + if ((tdb->fd = open(name, open_flags, mode)) == -1) { + TDB_LOG((tdb, 5, "tdb_open_ex: could not open file %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by open(2) */ + } + + /* ensure there is only one process initialising at once */ + if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_open_ex: failed to get global lock on %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by tdb_brlock */ + } + + /* we need to zero database if we are the only one with it open */ + if ((tdb_flags & TDB_CLEAR_IF_FIRST) && + (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) { + open_flags |= O_CREAT; + if (ftruncate(tdb->fd, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_open_ex: " + "failed to truncate %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by ftruncate */ + } + } + + if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) + || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0 + || (tdb->header.version != TDB_VERSION + && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) { + /* its not a valid database - possibly initialise it */ + if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) { + errno = EIO; /* ie bad format or something */ + goto fail; + } + rev = (tdb->flags & TDB_CONVERT); + } + vp = (unsigned char *)&tdb->header.version; + vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) | + (((u32)vp[2]) << 8) | (u32)vp[3]; + tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; + if (!rev) + tdb->flags &= ~TDB_CONVERT; + else { + tdb->flags |= TDB_CONVERT; + tdb_convert(&tdb->header, sizeof(tdb->header)); + } + if (fstat(tdb->fd, &st) == -1) + goto fail; + + if (tdb->header.rwlocks != 0) { + TDB_LOG((tdb, 5, "tdb_open_ex: spinlocks no longer supported\n")); + goto fail; + } + + /* Is it already in the open list? If so, fail. */ + if (tdb_already_open(st.st_dev, st.st_ino)) { + TDB_LOG((tdb, 2, "tdb_open_ex: " + "%s (%d,%d) is already open in this process\n", + name, (int)st.st_dev, (int)st.st_ino)); + errno = EBUSY; + goto fail; + } + + if (!(tdb->name = (char *)strdup(name))) { + errno = ENOMEM; + goto fail; + } + + tdb->map_size = st.st_size; + tdb->device = st.st_dev; + tdb->inode = st.st_ino; + tdb->locked = calloc(tdb->header.hash_size+1, sizeof(tdb->locked[0])); + if (!tdb->locked) { + TDB_LOG((tdb, 2, "tdb_open_ex: " + "failed to allocate lock structure for %s\n", + name)); + errno = ENOMEM; + goto fail; + } + tdb_mmap(tdb); + if (locked) { + if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_open_ex: " + "failed to take ACTIVE_LOCK on %s: %s\n", + name, strerror(errno))); + goto fail; + } + + } + + /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if + we didn't get the initial exclusive lock as we need to let all other + users know we're using it. */ + + if (tdb_flags & TDB_CLEAR_IF_FIRST) { + /* leave this lock in place to indicate it's in use */ + if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) + goto fail; + } + + /* if needed, run recovery */ + if (tdb_transaction_recover(tdb) == -1) { + goto fail; + } + + internal: + /* Internal (memory-only) databases skip all the code above to + * do with disk files, and resume here by releasing their + * global lock and hooking into the active list. */ + if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1) + goto fail; + tdb->next = tdbs; + tdbs = tdb; + return tdb; + + fail: + { int save_errno = errno; + + if (!tdb) + return NULL; + + if (tdb->map_ptr) { + if (tdb->flags & TDB_INTERNAL) + SAFE_FREE(tdb->map_ptr); + else + tdb_munmap(tdb); + } + SAFE_FREE(tdb->name); + if (tdb->fd != -1) + if (close(tdb->fd) != 0) + TDB_LOG((tdb, 5, "tdb_open_ex: failed to close tdb->fd on error!\n")); + SAFE_FREE(tdb->locked); + SAFE_FREE(tdb); + errno = save_errno; + return NULL; + } +} + +/** + * Close a database. + * + * @returns -1 for error; 0 for success. + **/ +int tdb_close(struct tdb_context *tdb) +{ + struct tdb_context **i; + int ret = 0; + + if (tdb->transaction) { + tdb_transaction_cancel(tdb); + } + + if (tdb->map_ptr) { + if (tdb->flags & TDB_INTERNAL) + SAFE_FREE(tdb->map_ptr); + else + tdb_munmap(tdb); + } + SAFE_FREE(tdb->name); + if (tdb->fd != -1) + ret = close(tdb->fd); + SAFE_FREE(tdb->locked); + + /* Remove from contexts list */ + for (i = &tdbs; *i; i = &(*i)->next) { + if (*i == tdb) { + *i = tdb->next; + break; + } + } + + memset(tdb, 0, sizeof(*tdb)); + SAFE_FREE(tdb); + + return ret; +} + +/* register a loging function */ +void tdb_logging_function(struct tdb_context *tdb, void (*fn)(struct tdb_context *, int , const char *, ...)) +{ + tdb->log_fn = fn?fn:null_log_fn; +} + + +/* reopen a tdb - this can be used after a fork to ensure that we have an independent + seek pointer from our parent and to re-establish locks */ +int tdb_reopen(struct tdb_context *tdb) +{ + struct stat st; + + if (tdb->flags & TDB_INTERNAL) { + return 0; /* Nothing to do. */ + } + + if (tdb->num_locks != 0) { + TDB_LOG((tdb, 0, "tdb_reopen: reopen not allowed with locks held\n")); + goto fail; + } + + if (tdb->transaction != 0) { + TDB_LOG((tdb, 0, "tdb_reopen: reopen not allowed inside a transaction\n")); + goto fail; + } + + if (tdb_munmap(tdb) != 0) { + TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); + goto fail; + } + if (close(tdb->fd) != 0) + TDB_LOG((tdb, 0, "tdb_reopen: WARNING closing tdb->fd failed!\n")); + tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); + if (tdb->fd == -1) { + TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno))); + goto fail; + } + if ((tdb->flags & TDB_CLEAR_IF_FIRST) && + (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) { + TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n")); + goto fail; + } + if (fstat(tdb->fd, &st) != 0) { + TDB_LOG((tdb, 0, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); + goto fail; + } + if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { + TDB_LOG((tdb, 0, "tdb_reopen: file dev/inode has changed!\n")); + goto fail; + } + tdb_mmap(tdb); + + return 0; + +fail: + tdb_close(tdb); + return -1; +} + +/* reopen all tdb's */ +int tdb_reopen_all(int parent_longlived) +{ + struct tdb_context *tdb; + + for (tdb=tdbs; tdb; tdb = tdb->next) { + /* + * If the parent is longlived (ie. a + * parent daemon architecture), we know + * it will keep it's active lock on a + * tdb opened with CLEAR_IF_FIRST. Thus + * for child processes we don't have to + * add an active lock. This is essential + * to improve performance on systems that + * keep POSIX locks as a non-scalable data + * structure in the kernel. + */ + if (parent_longlived) { + /* Ensure no clear-if-first. */ + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + } + + if (tdb_reopen(tdb) != 0) + return -1; + } + + return 0; +} diff --git a/source/tdb/spinlock.c b/source/tdb/spinlock.c deleted file mode 100644 index e42a6901c71..00000000000 --- a/source/tdb/spinlock.c +++ /dev/null @@ -1,472 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - trivial database library - - Copyright (C) Anton Blanchard 2001 - - ** NOTE! The following LGPL license applies to the tdb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#if HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef STANDALONE -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/stat.h> -#include <time.h> -#include <signal.h> -#include "tdb.h" -#include "spinlock.h" - -#define DEBUG -#else -#include "includes.h" -#endif - -#ifdef USE_SPINLOCKS - -/* - * ARCH SPECIFIC - */ - -#if defined(SPARC_SPINLOCKS) - -static inline int __spin_trylock(spinlock_t *lock) -{ - unsigned int result; - - asm volatile("ldstub [%1], %0" - : "=r" (result) - : "r" (lock) - : "memory"); - - return (result == 0) ? 0 : EBUSY; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - asm volatile("":::"memory"); - *lock = 0; -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - *lock = 0; -} - -static inline int __spin_is_locked(spinlock_t *lock) -{ - return (*lock != 0); -} - -#elif defined(POWERPC_SPINLOCKS) - -static inline int __spin_trylock(spinlock_t *lock) -{ - unsigned int result; - - __asm__ __volatile__( -"1: lwarx %0,0,%1\n\ - cmpwi 0,%0,0\n\ - li %0,0\n\ - bne- 2f\n\ - li %0,1\n\ - stwcx. %0,0,%1\n\ - bne- 1b\n\ - isync\n\ -2:" : "=&r"(result) - : "r"(lock) - : "cr0", "memory"); - - return (result == 1) ? 0 : EBUSY; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - asm volatile("eieio":::"memory"); - *lock = 0; -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - *lock = 0; -} - -static inline int __spin_is_locked(spinlock_t *lock) -{ - return (*lock != 0); -} - -#elif defined(INTEL_SPINLOCKS) - -static inline int __spin_trylock(spinlock_t *lock) -{ - int oldval; - - asm volatile("xchgl %0,%1" - : "=r" (oldval), "=m" (*lock) - : "0" (0) - : "memory"); - - return oldval > 0 ? 0 : EBUSY; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - asm volatile("":::"memory"); - *lock = 1; -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - *lock = 1; -} - -static inline int __spin_is_locked(spinlock_t *lock) -{ - return (*lock != 1); -} - -#elif defined(MIPS_SPINLOCKS) && defined(sgi) && (_COMPILER_VERSION >= 730) - -/* Implement spinlocks on IRIX using the MIPSPro atomic fetch operations. See - * sync(3) for the details of the intrinsic operations. - * - * "sgi" and "_COMPILER_VERSION" are always defined by MIPSPro. - */ - -#ifdef STANDALONE - -/* MIPSPro 7.3 has "__inline" as an extension, but not "inline. */ -#define inline __inline - -#endif /* STANDALONE */ - -/* Returns 0 if the lock is acquired, EBUSY otherwise. */ -static inline int __spin_trylock(spinlock_t *lock) -{ - unsigned int val; - val = __lock_test_and_set(lock, 1); - return val == 0 ? 0 : EBUSY; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - __lock_release(lock); -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - __lock_release(lock); -} - -/* Returns 1 if the lock is held, 0 otherwise. */ -static inline int __spin_is_locked(spinlock_t *lock) -{ - unsigned int val; - val = __add_and_fetch(lock, 0); - return val; -} - -#elif defined(MIPS_SPINLOCKS) - -static inline unsigned int load_linked(unsigned long addr) -{ - unsigned int res; - - __asm__ __volatile__("ll\t%0,(%1)" - : "=r" (res) - : "r" (addr)); - - return res; -} - -static inline unsigned int store_conditional(unsigned long addr, unsigned int value) -{ - unsigned int res; - - __asm__ __volatile__("sc\t%0,(%2)" - : "=r" (res) - : "0" (value), "r" (addr)); - return res; -} - -static inline int __spin_trylock(spinlock_t *lock) -{ - unsigned int mw; - - do { - mw = load_linked(lock); - if (mw) - return EBUSY; - } while (!store_conditional(lock, 1)); - - asm volatile("":::"memory"); - - return 0; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - asm volatile("":::"memory"); - *lock = 0; -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - *lock = 0; -} - -static inline int __spin_is_locked(spinlock_t *lock) -{ - return (*lock != 0); -} - -#else -#error Need to implement spinlock code in spinlock.c -#endif - -/* - * OS SPECIFIC - */ - -static void yield_cpu(void) -{ - struct timespec tm; - -#ifdef USE_SCHED_YIELD - sched_yield(); -#else - /* Linux will busy loop for delays < 2ms on real time tasks */ - tm.tv_sec = 0; - tm.tv_nsec = 2000000L + 1; - nanosleep(&tm, NULL); -#endif -} - -/* - * GENERIC - */ - -static int smp_machine = 0; - -static inline void __spin_lock(spinlock_t *lock) -{ - int ntries = 0; - - while(__spin_trylock(lock)) { - while(__spin_is_locked(lock)) { - if (smp_machine && ntries++ < MAX_BUSY_LOOPS) - continue; - yield_cpu(); - } - } -} - -static void __read_lock(tdb_rwlock_t *rwlock) -{ - int ntries = 0; - - while(1) { - __spin_lock(&rwlock->lock); - - if (!(rwlock->count & RWLOCK_BIAS)) { - rwlock->count++; - __spin_unlock(&rwlock->lock); - return; - } - - __spin_unlock(&rwlock->lock); - - while(rwlock->count & RWLOCK_BIAS) { - if (smp_machine && ntries++ < MAX_BUSY_LOOPS) - continue; - yield_cpu(); - } - } -} - -static void __write_lock(tdb_rwlock_t *rwlock) -{ - int ntries = 0; - - while(1) { - __spin_lock(&rwlock->lock); - - if (rwlock->count == 0) { - rwlock->count |= RWLOCK_BIAS; - __spin_unlock(&rwlock->lock); - return; - } - - __spin_unlock(&rwlock->lock); - - while(rwlock->count != 0) { - if (smp_machine && ntries++ < MAX_BUSY_LOOPS) - continue; - yield_cpu(); - } - } -} - -static void __write_unlock(tdb_rwlock_t *rwlock) -{ - __spin_lock(&rwlock->lock); - -#ifdef DEBUG - if (!(rwlock->count & RWLOCK_BIAS)) - fprintf(stderr, "bug: write_unlock\n"); -#endif - - rwlock->count &= ~RWLOCK_BIAS; - __spin_unlock(&rwlock->lock); -} - -static void __read_unlock(tdb_rwlock_t *rwlock) -{ - __spin_lock(&rwlock->lock); - -#ifdef DEBUG - if (!rwlock->count) - fprintf(stderr, "bug: read_unlock\n"); - - if (rwlock->count & RWLOCK_BIAS) - fprintf(stderr, "bug: read_unlock\n"); -#endif - - rwlock->count--; - __spin_unlock(&rwlock->lock); -} - -/* TDB SPECIFIC */ - -/* lock a list in the database. list -1 is the alloc list */ -int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) -{ - tdb_rwlock_t *rwlocks; - - if (!tdb->map_ptr) return -1; - rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); - - switch(rw_type) { - case F_RDLCK: - __read_lock(&rwlocks[list+1]); - break; - - case F_WRLCK: - __write_lock(&rwlocks[list+1]); - break; - - default: - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - return 0; -} - -/* unlock the database. */ -int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) -{ - tdb_rwlock_t *rwlocks; - - if (!tdb->map_ptr) return -1; - rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); - - switch(rw_type) { - case F_RDLCK: - __read_unlock(&rwlocks[list+1]); - break; - - case F_WRLCK: - __write_unlock(&rwlocks[list+1]); - break; - - default: - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - - return 0; -} - -int tdb_create_rwlocks(int fd, unsigned int hash_size) -{ - unsigned size, i; - tdb_rwlock_t *rwlocks; - - size = TDB_SPINLOCK_SIZE(hash_size); - rwlocks = malloc(size); - if (!rwlocks) - return -1; - - for(i = 0; i < hash_size+1; i++) { - __spin_lock_init(&rwlocks[i].lock); - rwlocks[i].count = 0; - } - - /* Write it out (appending to end) */ - if (write(fd, rwlocks, size) != size) { - free(rwlocks); - return -1; - } - smp_machine = this_is_smp(); - free(rwlocks); - return 0; -} - -int tdb_clear_spinlocks(TDB_CONTEXT *tdb) -{ - tdb_rwlock_t *rwlocks; - unsigned i; - - if (tdb->header.rwlocks == 0) return 0; - if (!tdb->map_ptr) return -1; - - /* We're mmapped here */ - rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); - for(i = 0; i < tdb->header.hash_size+1; i++) { - __spin_lock_init(&rwlocks[i].lock); - rwlocks[i].count = 0; - } - return 0; -} -#else -int tdb_create_rwlocks(int fd, unsigned int hash_size) { return 0; } -int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; } -int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; } - -/* Non-spinlock version: remove spinlock pointer */ -int tdb_clear_spinlocks(TDB_CONTEXT *tdb) -{ - tdb_off off = (tdb_off)((char *)&tdb->header.rwlocks - - (char *)&tdb->header); - - tdb->header.rwlocks = 0; - if (lseek(tdb->fd, off, SEEK_SET) != off - || write(tdb->fd, (void *)&tdb->header.rwlocks, - sizeof(tdb->header.rwlocks)) - != sizeof(tdb->header.rwlocks)) - return -1; - return 0; -} -#endif diff --git a/source/tdb/spinlock.h b/source/tdb/spinlock.h deleted file mode 100644 index 967fe37457f..00000000000 --- a/source/tdb/spinlock.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef __SPINLOCK_H__ -#define __SPINLOCK_H__ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "tdb.h" - -#ifdef USE_SPINLOCKS - -#define RWLOCK_BIAS 0x1000UL - -/* OS SPECIFIC */ -#define MAX_BUSY_LOOPS 1000 -#undef USE_SCHED_YIELD - -/* ARCH SPECIFIC */ -/* We should make sure these are padded to a cache line */ -#if defined(SPARC_SPINLOCKS) -typedef volatile char spinlock_t; -#elif defined(POWERPC_SPINLOCKS) -typedef volatile unsigned long spinlock_t; -#elif defined(INTEL_SPINLOCKS) -typedef volatile int spinlock_t; -#elif defined(MIPS_SPINLOCKS) -typedef volatile unsigned long spinlock_t; -#else -#error Need to implement spinlock code in spinlock.h -#endif - -typedef struct { - spinlock_t lock; - volatile int count; -} tdb_rwlock_t; - -int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_create_rwlocks(int fd, unsigned int hash_size); -int tdb_clear_spinlocks(TDB_CONTEXT *tdb); - -#define TDB_SPINLOCK_SIZE(hash_size) (((hash_size) + 1) * sizeof(tdb_rwlock_t)) - -#else /* !USE_SPINLOCKS */ -#if 0 -#define tdb_create_rwlocks(fd, hash_size) 0 -#define tdb_spinlock(tdb, list, rw_type) (-1) -#define tdb_spinunlock(tdb, list, rw_type) (-1) -#else -int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_create_rwlocks(int fd, unsigned int hash_size); -#endif -int tdb_clear_spinlocks(TDB_CONTEXT *tdb); -#define TDB_SPINLOCK_SIZE(hash_size) 0 - -#endif - -#endif diff --git a/source/tdb/tdb.c b/source/tdb/tdb.c index ad73a1d9aa0..1fae6b6de1d 100644 --- a/source/tdb/tdb.c +++ b/source/tdb/tdb.c @@ -3,7 +3,7 @@ trivial database library - Copyright (C) Andrew Tridgell 1999-2004 + Copyright (C) Andrew Tridgell 1999-2005 Copyright (C) Paul `Rusty' Russell 2000 Copyright (C) Jeremy Allison 2000-2003 @@ -20,1004 +20,57 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "tdb_private.h" -/* NOTE: If you use tdbs under valgrind, and in particular if you run - * tdbtorture, you may get spurious "uninitialized value" warnings. I - * think this is because valgrind doesn't understand that the mmap'd - * area may be written to by other processes. Memory can, from the - * point of view of the grinded process, spontaneously become - * initialized. - * - * I can think of a few solutions. [mbp 20030311] - * - * 1 - Write suppressions for Valgrind so that it doesn't complain - * about this. Probably the most reasonable but people need to - * remember to use them. - * - * 2 - Use IO not mmap when running under valgrind. Not so nice. - * - * 3 - Use the special valgrind macros to mark memory as valid at the - * right time. Probably too hard -- the process just doesn't know. - */ - -#ifdef STANDALONE -#if HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <signal.h> -#include "tdb.h" -#include "spinlock.h" -#else -#include "includes.h" - -#if defined(PARANOID_MALLOC_CHECKER) -#ifdef malloc -#undef malloc -#endif - -#ifdef realloc -#undef realloc -#endif - -#ifdef calloc -#undef calloc -#endif - -#ifdef strdup -#undef strdup -#endif - -#ifdef strndup -#undef strndup -#endif - -#endif - -#endif - -#define TDB_MAGIC_FOOD "TDB file\n" -#define TDB_VERSION (0x26011967 + 6) -#define TDB_MAGIC (0x26011999U) -#define TDB_FREE_MAGIC (~TDB_MAGIC) -#define TDB_DEAD_MAGIC (0xFEE1DEAD) -#define TDB_ALIGNMENT 4 -#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT) -#define DEFAULT_HASH_SIZE 131 -#define TDB_PAGE_SIZE 0x2000 -#define FREELIST_TOP (sizeof(struct tdb_header)) -#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) -#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24)) -#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) -#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) -#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off)) -#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + TDB_SPINLOCK_SIZE(hash_size)) - - -/* NB assumes there is a local variable called "tdb" that is the - * current context, also takes doubly-parenthesized print-style - * argument. */ -#define TDB_LOG(x) (tdb->log_fn?((tdb->log_fn x),0) : 0) - -/* lock offsets */ -#define GLOBAL_LOCK 0 -#define ACTIVE_LOCK 4 - -#ifndef MAP_FILE -#define MAP_FILE 0 -#endif - -#ifndef MAP_FAILED -#define MAP_FAILED ((void *)-1) -#endif - -/* free memory if the pointer is valid and zero the pointer */ -#ifndef SAFE_FREE -#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0) -#endif - -#define BUCKET(hash) ((hash) % tdb->header.hash_size) TDB_DATA tdb_null; -/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */ -static TDB_CONTEXT *tdbs = NULL; - -static int tdb_munmap(TDB_CONTEXT *tdb) +/* + increment the tdb sequence number if the tdb has been opened using + the TDB_SEQNUM flag +*/ +static void tdb_increment_seqnum(struct tdb_context *tdb) { - if (tdb->flags & TDB_INTERNAL) - return 0; - -#ifdef HAVE_MMAP - if (tdb->map_ptr) { - int ret = munmap(tdb->map_ptr, tdb->map_size); - if (ret != 0) - return ret; + tdb_off_t seqnum=0; + + if (!(tdb->flags & TDB_SEQNUM)) { + return; } -#endif - tdb->map_ptr = NULL; - return 0; -} -static void tdb_mmap(TDB_CONTEXT *tdb) -{ - if (tdb->flags & TDB_INTERNAL) + if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1) != 0) { return; - -#ifdef HAVE_MMAP - if (!(tdb->flags & TDB_NOMMAP)) { - tdb->map_ptr = mmap(NULL, tdb->map_size, - PROT_READ|(tdb->read_only? 0:PROT_WRITE), - MAP_SHARED|MAP_FILE, tdb->fd, 0); - - /* - * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!! - */ - - if (tdb->map_ptr == MAP_FAILED) { - tdb->map_ptr = NULL; - TDB_LOG((tdb, 2, "tdb_mmap failed for size %d (%s)\n", - tdb->map_size, strerror(errno))); - } - } else { - tdb->map_ptr = NULL; } -#else - tdb->map_ptr = NULL; -#endif -} -/* Endian conversion: we only ever deal with 4 byte quantities */ -static void *convert(void *buf, u32 size) -{ - u32 i, *p = buf; - for (i = 0; i < size / 4; i++) - p[i] = TDB_BYTEREV(p[i]); - return buf; -} -#define DOCONV() (tdb->flags & TDB_CONVERT) -#define CONVERT(x) (DOCONV() ? convert(&x, sizeof(x)) : &x) - -/* the body of the database is made of one list_struct for the free space - plus a separate data list for each hash value */ -struct list_struct { - tdb_off next; /* offset of the next record in the list */ - tdb_len rec_len; /* total byte length of record */ - tdb_len key_len; /* byte length of key */ - tdb_len data_len; /* byte length of data */ - u32 full_hash; /* the full 32 bit hash of the key */ - u32 magic; /* try to catch errors */ - /* the following union is implied: - union { - char record[rec_len]; - struct { - char key[key_len]; - char data[data_len]; - } - u32 totalsize; (tailer) - } + /* we ignore errors from this, as we have no sane way of + dealing with them. */ -}; - -/*************************************************************** - Allow a caller to set a "alarm" flag that tdb can check to abort - a blocking lock on SIGALRM. -***************************************************************/ - -static sig_atomic_t *palarm_fired; - -void tdb_set_lock_alarm(sig_atomic_t *palarm) -{ - palarm_fired = palarm; -} - -/* a byte range locking function - return 0 on success - this functions locks/unlocks 1 byte at the specified offset. - - On error, errno is also set so that errors are passed back properly - through tdb_open(). */ -static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, - int rw_type, int lck_type, int probe) -{ - struct flock fl; - int ret; - - if (tdb->flags & TDB_NOLOCK) - return 0; - if ((rw_type == F_WRLCK) && (tdb->read_only)) { - errno = EACCES; - return -1; - } - - fl.l_type = rw_type; - fl.l_whence = SEEK_SET; - fl.l_start = offset; - fl.l_len = 1; - fl.l_pid = 0; - - do { - ret = fcntl(tdb->fd,lck_type,&fl); - if (ret == -1 && errno == EINTR && palarm_fired && *palarm_fired) - break; - } while (ret == -1 && errno == EINTR); - - if (ret == -1) { - if (!probe && lck_type != F_SETLK) { - /* Ensure error code is set for log fun to examine. */ - if (errno == EINTR && palarm_fired && *palarm_fired) - tdb->ecode = TDB_ERR_LOCK_TIMEOUT; - else - tdb->ecode = TDB_ERR_LOCK; - TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", - tdb->fd, offset, rw_type, lck_type)); - } - /* Was it an alarm timeout ? */ - if (errno == EINTR && palarm_fired && *palarm_fired) { - TDB_LOG((tdb, 5, "tdb_brlock timed out (fd=%d) at offset %d rw_type=%d lck_type=%d\n", - tdb->fd, offset, rw_type, lck_type)); - return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1); - } - /* Otherwise - generic lock error. errno set by fcntl. - * EAGAIN is an expected return from non-blocking - * locks. */ - if (errno != EAGAIN) { - TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n", - tdb->fd, offset, rw_type, lck_type, - strerror(errno))); - } - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - return 0; -} - -/* lock a list in the database. list -1 is the alloc list */ -static int tdb_lock(TDB_CONTEXT *tdb, int list, int ltype) -{ - if (list < -1 || list >= (int)tdb->header.hash_size) { - TDB_LOG((tdb, 0,"tdb_lock: invalid list %d for ltype=%d\n", - list, ltype)); - return -1; - } - if (tdb->flags & TDB_NOLOCK) - return 0; - - /* Since fcntl locks don't nest, we do a lock for the first one, - and simply bump the count for future ones */ - if (tdb->locked[list+1].count == 0) { - if (!tdb->read_only && tdb->header.rwlocks) { - if (tdb_spinlock(tdb, list, ltype)) { - TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list %d ltype=%d\n", - list, ltype)); - return -1; - } - } else if (tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) { - TDB_LOG((tdb, 0,"tdb_lock failed on list %d ltype=%d (%s)\n", - list, ltype, strerror(errno))); - return -1; - } - tdb->locked[list+1].ltype = ltype; - } - tdb->locked[list+1].count++; - return 0; -} - -/* unlock the database: returns void because it's too late for errors. */ - /* changed to return int it may be interesting to know there - has been an error --simo */ -static int tdb_unlock(TDB_CONTEXT *tdb, int list, int ltype) -{ - int ret = -1; - - if (tdb->flags & TDB_NOLOCK) - return 0; - - /* Sanity checks */ - if (list < -1 || list >= (int)tdb->header.hash_size) { - TDB_LOG((tdb, 0, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size)); - return ret; - } - - if (tdb->locked[list+1].count==0) { - TDB_LOG((tdb, 0, "tdb_unlock: count is 0\n")); - return ret; - } - - if (tdb->locked[list+1].count == 1) { - /* Down to last nested lock: unlock underneath */ - if (!tdb->read_only && tdb->header.rwlocks) { - ret = tdb_spinunlock(tdb, list, ltype); - } else { - ret = tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, F_SETLKW, 0); - } - } else { - ret = 0; - } - tdb->locked[list+1].count--; - - if (ret) - TDB_LOG((tdb, 0,"tdb_unlock: An error occurred unlocking!\n")); - return ret; -} - -/* check for an out of bounds access - if it is out of bounds then - see if the database has been expanded by someone else and expand - if necessary - note that "len" is the minimum length needed for the db -*/ -static int tdb_oob(TDB_CONTEXT *tdb, tdb_off len, int probe) -{ - struct stat st; - if (len <= tdb->map_size) - return 0; - if (tdb->flags & TDB_INTERNAL) { - if (!probe) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_oob len %d beyond internal malloc size %d\n", - (int)len, (int)tdb->map_size)); - } - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - - if (fstat(tdb->fd, &st) == -1) - return TDB_ERRCODE(TDB_ERR_IO, -1); - - if (st.st_size < (size_t)len) { - if (!probe) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_oob len %d beyond eof at %d\n", - (int)len, (int)st.st_size)); - } - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - - /* Unmap, update size, remap */ - if (tdb_munmap(tdb) == -1) - return TDB_ERRCODE(TDB_ERR_IO, -1); - tdb->map_size = st.st_size; - tdb_mmap(tdb); - return 0; -} - -/* write a lump of data at a specified offset */ -static int tdb_write(TDB_CONTEXT *tdb, tdb_off off, void *buf, tdb_len len) -{ - if (tdb_oob(tdb, off + len, 0) != 0) - return -1; - - if (tdb->map_ptr) - memcpy(off + (char *)tdb->map_ptr, buf, len); -#ifdef HAVE_PWRITE - else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) { -#else - else if (lseek(tdb->fd, off, SEEK_SET) != off - || write(tdb->fd, buf, len) != (ssize_t)len) { -#endif - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_write failed at %d len=%d (%s)\n", - off, len, strerror(errno))); - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - return 0; -} - -/* read a lump of data at a specified offset, maybe convert */ -static int tdb_read(TDB_CONTEXT *tdb,tdb_off off,void *buf,tdb_len len,int cv) -{ - if (tdb_oob(tdb, off + len, 0) != 0) - return -1; - - if (tdb->map_ptr) - memcpy(buf, off + (char *)tdb->map_ptr, len); -#ifdef HAVE_PREAD - else if (pread(tdb->fd, buf, len, off) != (ssize_t)len) { -#else - else if (lseek(tdb->fd, off, SEEK_SET) != off - || read(tdb->fd, buf, len) != (ssize_t)len) { -#endif - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_read failed at %d len=%d (%s)\n", - off, len, strerror(errno))); - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - if (cv) - convert(buf, len); - return 0; -} - -/* read a lump of data, allocating the space for it */ -static char *tdb_alloc_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_len len) -{ - char *buf; + tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); + seqnum++; + tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum); - if (!(buf = malloc(len))) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_OOM; - TDB_LOG((tdb, 0,"tdb_alloc_read malloc failed len=%d (%s)\n", - len, strerror(errno))); - return TDB_ERRCODE(TDB_ERR_OOM, buf); - } - if (tdb_read(tdb, offset, buf, len, 0) == -1) { - SAFE_FREE(buf); - return NULL; - } - return buf; -} - -/* read/write a tdb_off */ -static int ofs_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d) -{ - return tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); -} -static int ofs_write(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d) -{ - tdb_off off = *d; - return tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); + tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1); } -/* read/write a record */ -static int rec_read(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) -{ - if (tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) - return -1; - if (TDB_BAD_MAGIC(rec)) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_CORRUPT; - TDB_LOG((tdb, 0,"rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); - } - return tdb_oob(tdb, rec->next+sizeof(*rec), 0); -} -static int rec_write(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) -{ - struct list_struct r = *rec; - return tdb_write(tdb, offset, CONVERT(r), sizeof(r)); -} - -/* read a freelist record and check for simple errors */ -static int rec_free_read(TDB_CONTEXT *tdb, tdb_off off, struct list_struct *rec) -{ - if (tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) - return -1; - - if (rec->magic == TDB_MAGIC) { - /* this happens when a app is showdown while deleting a record - we should - not completely fail when this happens */ - TDB_LOG((tdb, 0,"rec_free_read non-free magic 0x%x at offset=%d - fixing\n", - rec->magic, off)); - rec->magic = TDB_FREE_MAGIC; - if (tdb_write(tdb, off, rec, sizeof(*rec)) == -1) - return -1; - } - - if (rec->magic != TDB_FREE_MAGIC) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_CORRUPT; - TDB_LOG((tdb, 0,"rec_free_read bad magic 0x%x at offset=%d\n", - rec->magic, off)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); - } - if (tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0) - return -1; - return 0; -} - -/* update a record tailer (must hold allocation lock) */ -static int update_tailer(TDB_CONTEXT *tdb, tdb_off offset, - const struct list_struct *rec) -{ - tdb_off totalsize; - - /* Offset of tailer from record header */ - totalsize = sizeof(*rec) + rec->rec_len; - return ofs_write(tdb, offset + totalsize - sizeof(tdb_off), - &totalsize); -} - -static tdb_off tdb_dump_record(TDB_CONTEXT *tdb, tdb_off offset) -{ - struct list_struct rec; - tdb_off tailer_ofs, tailer; - - if (tdb_read(tdb, offset, (char *)&rec, sizeof(rec), DOCONV()) == -1) { - printf("ERROR: failed to read record at %u\n", offset); - return 0; - } - - printf(" rec: offset=%u next=%d rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n", - offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, rec.full_hash, rec.magic); - - tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off); - if (ofs_read(tdb, tailer_ofs, &tailer) == -1) { - printf("ERROR: failed to read tailer at %u\n", tailer_ofs); - return rec.next; - } - - if (tailer != rec.rec_len + sizeof(rec)) { - printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", - (unsigned)tailer, (unsigned)(rec.rec_len + sizeof(rec))); - } - return rec.next; -} - -static int tdb_dump_chain(TDB_CONTEXT *tdb, int i) -{ - tdb_off rec_ptr, top; - int hash_length = 0; - - top = TDB_HASH_TOP(i); - - if (tdb_lock(tdb, i, F_WRLCK) != 0) - return -1; - - if (ofs_read(tdb, top, &rec_ptr) == -1) - return tdb_unlock(tdb, i, F_WRLCK); - - if (rec_ptr) - printf("hash=%d\n", i); - - while (rec_ptr) { - rec_ptr = tdb_dump_record(tdb, rec_ptr); - hash_length += 1; - } - - printf("chain %d length %d\n", i, hash_length); - - return tdb_unlock(tdb, i, F_WRLCK); -} - -void tdb_dump_all(TDB_CONTEXT *tdb) -{ - int i; - for (i=0;i<tdb->header.hash_size;i++) { - tdb_dump_chain(tdb, i); - } - tdb_printfreelist(tdb); -} - -int tdb_printfreelist(TDB_CONTEXT *tdb) -{ - int ret; - long total_free = 0; - tdb_off offset, rec_ptr; - struct list_struct rec; - - if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0) - return ret; - - offset = FREELIST_TOP; - - /* read in the freelist top */ - if (ofs_read(tdb, offset, &rec_ptr) == -1) { - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - } - - printf("freelist top=[0x%08x]\n", rec_ptr ); - while (rec_ptr) { - if (tdb_read(tdb, rec_ptr, (char *)&rec, sizeof(rec), DOCONV()) == -1) { - tdb_unlock(tdb, -1, F_WRLCK); - return -1; - } - - if (rec.magic != TDB_FREE_MAGIC) { - printf("bad magic 0x%08x in free list\n", rec.magic); - tdb_unlock(tdb, -1, F_WRLCK); - return -1; - } - - printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)]\n", rec.next, rec.rec_len, rec.rec_len ); - total_free += rec.rec_len; - - /* move to the next record */ - rec_ptr = rec.next; - } - printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, - (int)total_free); - - return tdb_unlock(tdb, -1, F_WRLCK); -} - -/* Remove an element from the freelist. Must have alloc lock. */ -static int remove_from_freelist(TDB_CONTEXT *tdb, tdb_off off, tdb_off next) -{ - tdb_off last_ptr, i; - - /* read in the freelist top */ - last_ptr = FREELIST_TOP; - while (ofs_read(tdb, last_ptr, &i) != -1 && i != 0) { - if (i == off) { - /* We've found it! */ - return ofs_write(tdb, last_ptr, &next); - } - /* Follow chain (next offset is at start of record) */ - last_ptr = i; - } - TDB_LOG((tdb, 0,"remove_from_freelist: not on list at off=%d\n", off)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); -} - -/* Add an element into the freelist. Merge adjacent records if - neccessary. */ -static int tdb_free(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) -{ - tdb_off right, left; - - /* Allocation and tailer lock */ - if (tdb_lock(tdb, -1, F_WRLCK) != 0) - return -1; - - /* set an initial tailer, so if we fail we don't leave a bogus record */ - if (update_tailer(tdb, offset, rec) != 0) { - TDB_LOG((tdb, 0, "tdb_free: upfate_tailer failed!\n")); - goto fail; - } - - /* Look right first (I'm an Australian, dammit) */ - right = offset + sizeof(*rec) + rec->rec_len; - if (right + sizeof(*rec) <= tdb->map_size) { - struct list_struct r; - - if (tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { - TDB_LOG((tdb, 0, "tdb_free: right read failed at %u\n", right)); - goto left; - } - - /* If it's free, expand to include it. */ - if (r.magic == TDB_FREE_MAGIC) { - if (remove_from_freelist(tdb, right, r.next) == -1) { - TDB_LOG((tdb, 0, "tdb_free: right free failed at %u\n", right)); - goto left; - } - rec->rec_len += sizeof(r) + r.rec_len; - } - } - -left: - /* Look left */ - left = offset - sizeof(tdb_off); - if (left > TDB_DATA_START(tdb->header.hash_size)) { - struct list_struct l; - tdb_off leftsize; - - /* Read in tailer and jump back to header */ - if (ofs_read(tdb, left, &leftsize) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left)); - goto update; - } - left = offset - leftsize; - - /* Now read in record */ - if (tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); - goto update; - } - - /* If it's free, expand to include it. */ - if (l.magic == TDB_FREE_MAGIC) { - if (remove_from_freelist(tdb, left, l.next) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left free failed at %u\n", left)); - goto update; - } else { - offset = left; - rec->rec_len += leftsize; - } - } - } - -update: - if (update_tailer(tdb, offset, rec) == -1) { - TDB_LOG((tdb, 0, "tdb_free: update_tailer failed at %u\n", offset)); - goto fail; - } - - /* Now, prepend to free list */ - rec->magic = TDB_FREE_MAGIC; - - if (ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || - rec_write(tdb, offset, rec) == -1 || - ofs_write(tdb, FREELIST_TOP, &offset) == -1) { - TDB_LOG((tdb, 0, "tdb_free record write failed at offset=%d\n", offset)); - goto fail; - } - - /* And we're done. */ - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return -1; -} - - -/* expand a file. we prefer to use ftruncate, as that is what posix - says to use for mmap expansion */ -static int expand_file(TDB_CONTEXT *tdb, tdb_off size, tdb_off addition) -{ - char buf[1024]; -#if HAVE_FTRUNCATE_EXTEND - if (ftruncate(tdb->fd, size+addition) != 0) { - TDB_LOG((tdb, 0, "expand_file ftruncate to %d failed (%s)\n", - size+addition, strerror(errno))); - return -1; - } -#else - char b = 0; - -#ifdef HAVE_PWRITE - if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) { -#else - if (lseek(tdb->fd, (size+addition) - 1, SEEK_SET) != (size+addition) - 1 || - write(tdb->fd, &b, 1) != 1) { -#endif - TDB_LOG((tdb, 0, "expand_file to %d failed (%s)\n", - size+addition, strerror(errno))); - return -1; - } -#endif - - /* now fill the file with something. This ensures that the file isn't sparse, which would be - very bad if we ran out of disk. This must be done with write, not via mmap */ - memset(buf, 0x42, sizeof(buf)); - while (addition) { - int n = addition>sizeof(buf)?sizeof(buf):addition; -#ifdef HAVE_PWRITE - int ret = pwrite(tdb->fd, buf, n, size); -#else - int ret; - if (lseek(tdb->fd, size, SEEK_SET) != size) - return -1; - ret = write(tdb->fd, buf, n); -#endif - if (ret != n) { - TDB_LOG((tdb, 0, "expand_file write of %d failed (%s)\n", - n, strerror(errno))); - return -1; - } - addition -= n; - size += n; - } - return 0; -} - - -/* expand the database at least size bytes by expanding the underlying - file and doing the mmap again if necessary */ -static int tdb_expand(TDB_CONTEXT *tdb, tdb_off size) -{ - struct list_struct rec; - tdb_off offset; - - if (tdb_lock(tdb, -1, F_WRLCK) == -1) { - TDB_LOG((tdb, 0, "lock failed in tdb_expand\n")); - return -1; - } - - /* must know about any previous expansions by another process */ - tdb_oob(tdb, tdb->map_size + 1, 1); - - /* always make room for at least 10 more records, and round - the database up to a multiple of TDB_PAGE_SIZE */ - size = TDB_ALIGN(tdb->map_size + size*10, TDB_PAGE_SIZE) - tdb->map_size; - - if (!(tdb->flags & TDB_INTERNAL)) - tdb_munmap(tdb); - - /* - * We must ensure the file is unmapped before doing this - * to ensure consistency with systems like OpenBSD where - * writes and mmaps are not consistent. - */ - - /* expand the file itself */ - if (!(tdb->flags & TDB_INTERNAL)) { - if (expand_file(tdb, tdb->map_size, size) != 0) - goto fail; - } - - tdb->map_size += size; - - if (tdb->flags & TDB_INTERNAL) { - char *new_map_ptr = realloc(tdb->map_ptr, tdb->map_size); - if (!new_map_ptr) { - tdb->map_size -= size; - goto fail; - } - tdb->map_ptr = new_map_ptr; - } else { - /* - * We must ensure the file is remapped before adding the space - * to ensure consistency with systems like OpenBSD where - * writes and mmaps are not consistent. - */ - - /* We're ok if the mmap fails as we'll fallback to read/write */ - tdb_mmap(tdb); - } - - /* form a new freelist record */ - memset(&rec,'\0',sizeof(rec)); - rec.rec_len = size - sizeof(rec); - - /* link it into the free list */ - offset = tdb->map_size - size; - if (tdb_free(tdb, offset, &rec) == -1) - goto fail; - - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return -1; -} - -/* allocate some space from the free list. The offset returned points - to a unconnected list_struct within the database with room for at - least length bytes of total data - - 0 is returned if the space could not be allocated - */ -static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length, - struct list_struct *rec) -{ - tdb_off rec_ptr, last_ptr, newrec_ptr; - struct list_struct newrec; - - memset(&newrec, '\0', sizeof(newrec)); - - if (tdb_lock(tdb, -1, F_WRLCK) == -1) - return 0; - - /* Extra bytes required for tailer */ - length += sizeof(tdb_off); - - again: - last_ptr = FREELIST_TOP; - - /* read in the freelist top */ - if (ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) - goto fail; - - /* keep looking until we find a freelist record big enough */ - while (rec_ptr) { - if (rec_free_read(tdb, rec_ptr, rec) == -1) - goto fail; - - if (rec->rec_len >= length) { - /* found it - now possibly split it up */ - if (rec->rec_len > length + MIN_REC_SIZE) { - /* Length of left piece */ - length = TDB_ALIGN(length, TDB_ALIGNMENT); - - /* Right piece to go on free list */ - newrec.rec_len = rec->rec_len - - (sizeof(*rec) + length); - newrec_ptr = rec_ptr + sizeof(*rec) + length; - - /* And left record is shortened */ - rec->rec_len = length; - } else - newrec_ptr = 0; - - /* Remove allocated record from the free list */ - if (ofs_write(tdb, last_ptr, &rec->next) == -1) - goto fail; - - /* Update header: do this before we drop alloc - lock, otherwise tdb_free() might try to - merge with us, thinking we're free. - (Thanks Jeremy Allison). */ - rec->magic = TDB_MAGIC; - if (rec_write(tdb, rec_ptr, rec) == -1) - goto fail; - - /* Did we create new block? */ - if (newrec_ptr) { - /* Update allocated record tailer (we - shortened it). */ - if (update_tailer(tdb, rec_ptr, rec) == -1) - goto fail; - - /* Free new record */ - if (tdb_free(tdb, newrec_ptr, &newrec) == -1) - goto fail; - } - - /* all done - return the new record offset */ - tdb_unlock(tdb, -1, F_WRLCK); - return rec_ptr; - } - /* move to the next record */ - last_ptr = rec_ptr; - rec_ptr = rec->next; - } - /* we didn't find enough space. See if we can expand the - database and if we can then try again */ - if (tdb_expand(tdb, length + sizeof(*rec)) == 0) - goto again; - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return 0; -} - -/* initialise a new database with a specified hash size */ -static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size) -{ - struct tdb_header *newdb; - int size, ret = -1; - - /* We make it up in memory, then write it out if not internal */ - size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off); - if (!(newdb = calloc(size, 1))) - return TDB_ERRCODE(TDB_ERR_OOM, -1); - - /* Fill in the header */ - newdb->version = TDB_VERSION; - newdb->hash_size = hash_size; -#ifdef USE_SPINLOCKS - newdb->rwlocks = size; -#endif - if (tdb->flags & TDB_INTERNAL) { - tdb->map_size = size; - tdb->map_ptr = (char *)newdb; - memcpy(&tdb->header, newdb, sizeof(tdb->header)); - /* Convert the `ondisk' version if asked. */ - CONVERT(*newdb); - return 0; - } - if (lseek(tdb->fd, 0, SEEK_SET) == -1) - goto fail; - - if (ftruncate(tdb->fd, 0) == -1) - goto fail; - - /* This creates an endian-converted header, as if read from disk */ - CONVERT(*newdb); - memcpy(&tdb->header, newdb, sizeof(tdb->header)); - /* Don't endian-convert the magic food! */ - memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1); - if (write(tdb->fd, newdb, size) != size) - ret = -1; - else - ret = tdb_create_rwlocks(tdb->fd, hash_size); - - fail: - SAFE_FREE(newdb); - return ret; -} /* Returns 0 on fail. On success, return offset of record, and fills in rec */ -static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, +static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, u32 hash, struct list_struct *r) { - tdb_off rec_ptr; + tdb_off_t rec_ptr; /* read in the hash top */ - if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) return 0; /* keep looking until we find the right record */ while (rec_ptr) { - if (rec_read(tdb, rec_ptr, r) == -1) + if (tdb_rec_read(tdb, rec_ptr, r) == -1) return 0; if (!TDB_DEAD(r) && hash==r->full_hash && key.dsize==r->key_len) { @@ -1040,8 +93,8 @@ static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, } /* As tdb_find, but if you succeed, keep the lock */ -static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype, - struct list_struct *rec) +tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype, + struct list_struct *rec) { u32 rec_ptr; @@ -1052,60 +105,34 @@ static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int return rec_ptr; } -enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb) -{ - return tdb->ecode; -} - -static struct tdb_errname { - enum TDB_ERROR ecode; const char *estring; -} emap[] = { {TDB_SUCCESS, "Success"}, - {TDB_ERR_CORRUPT, "Corrupt database"}, - {TDB_ERR_IO, "IO Error"}, - {TDB_ERR_LOCK, "Locking error"}, - {TDB_ERR_OOM, "Out of memory"}, - {TDB_ERR_EXISTS, "Record exists"}, - {TDB_ERR_NOLOCK, "Lock exists on other keys"}, - {TDB_ERR_NOEXIST, "Record does not exist"} }; - -/* Error string for the last tdb error */ -const char *tdb_errorstr(TDB_CONTEXT *tdb) -{ - u32 i; - for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++) - if (tdb->ecode == emap[i].ecode) - return emap[i].estring; - return "Invalid error code"; -} /* update an entry in place - this only works if the new data size is <= the old data size and the key exists. on failure return -1. */ - -static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf) +static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf) { struct list_struct rec; - tdb_off rec_ptr; + tdb_off_t rec_ptr; /* find entry */ if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) return -1; /* must be long enough key, data and tailer */ - if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off)) { + if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off_t)) { tdb->ecode = TDB_SUCCESS; /* Not really an error */ return -1; } - if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len, + if (tdb->methods->tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len, dbuf.dptr, dbuf.dsize) == -1) return -1; if (dbuf.dsize != rec.data_len) { /* update size */ rec.data_len = dbuf.dsize; - return rec_write(tdb, rec_ptr, &rec); + return tdb_rec_write(tdb, rec_ptr, &rec); } return 0; @@ -1114,13 +141,12 @@ static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA db /* find an entry in the database given a key */ /* If an entry doesn't exist tdb_err will be set to * TDB_ERR_NOEXIST. If a key has no data attached - * tdb_err will not be set. Both will return a - * zero pptr and zero dsize. + * then the TDB_DATA will have zero length but + * a non-zero pointer */ - -TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) +TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key) { - tdb_off rec_ptr; + tdb_off_t rec_ptr; struct list_struct rec; TDB_DATA ret; u32 hash; @@ -1130,11 +156,8 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) return tdb_null; - if (rec.data_len) - ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, - rec.data_len); - else - ret.dptr = NULL; + ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, + rec.data_len); ret.dsize = rec.data_len; tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); return ret; @@ -1146,7 +169,7 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) this doesn't match the conventions in the rest of this module, but is compatible with gdbm */ -static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) +static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash) { struct list_struct rec; @@ -1156,82 +179,39 @@ static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) return 1; } -int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key) +int tdb_exists(struct tdb_context *tdb, TDB_DATA key) { u32 hash = tdb->hash_fn(&key); return tdb_exists_hash(tdb, key, hash); } -/* record lock stops delete underneath */ -static int lock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - return off ? tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0) : 0; -} -/* - Write locks override our own fcntl readlocks, so check it here. - Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not - an error to fail to get the lock here. -*/ - -static int write_lock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - struct tdb_traverse_lock *i; - for (i = &tdb->travlocks; i; i = i->next) - if (i->off == off) - return -1; - return tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1); -} - -/* - Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not - an error to fail to get the lock here. -*/ - -static int write_unlock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - return tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0); -} -/* fcntl locks don't stack: avoid unlocking someone else's */ -static int unlock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - struct tdb_traverse_lock *i; - u32 count = 0; - - if (off == 0) - return 0; - for (i = &tdb->travlocks; i; i = i->next) - if (i->off == off) - count++; - return (count == 1 ? tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0) : 0); -} - /* actually delete an entry in the database given the offset */ -static int do_delete(TDB_CONTEXT *tdb, tdb_off rec_ptr, struct list_struct*rec) +int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct*rec) { - tdb_off last_ptr, i; + tdb_off_t last_ptr, i; struct list_struct lastrec; - if (tdb->read_only) return -1; + if (tdb->read_only || tdb->traverse_read) return -1; - if (write_lock_record(tdb, rec_ptr) == -1) { + if (tdb_write_lock_record(tdb, rec_ptr) == -1) { /* Someone traversing here: mark it as dead */ rec->magic = TDB_DEAD_MAGIC; - return rec_write(tdb, rec_ptr, rec); + return tdb_rec_write(tdb, rec_ptr, rec); } - if (write_unlock_record(tdb, rec_ptr) != 0) + if (tdb_write_unlock_record(tdb, rec_ptr) != 0) return -1; /* find previous record in hash chain */ - if (ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1) + if (tdb_ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1) return -1; for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next) - if (rec_read(tdb, i, &lastrec) == -1) + if (tdb_rec_read(tdb, i, &lastrec) == -1) return -1; /* unlink it: next ptr is at start of record. */ if (last_ptr == 0) last_ptr = TDB_HASH_TOP(rec->full_hash); - if (ofs_write(tdb, last_ptr, &rec->next) == -1) + if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) return -1; /* recover the space */ @@ -1240,283 +220,27 @@ static int do_delete(TDB_CONTEXT *tdb, tdb_off rec_ptr, struct list_struct*rec) return 0; } -/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */ -static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, - struct list_struct *rec) -{ - int want_next = (tlock->off != 0); - - /* Lock each chain from the start one. */ - for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { - - /* this is an optimisation for the common case where - the hash chain is empty, which is particularly - common for the use of tdb with ldb, where large - hashes are used. In that case we spend most of our - time in tdb_brlock(), locking empty hash chains. - - To avoid this, we do an unlocked pre-check to see - if the hash chain is empty before starting to look - inside it. If it is empty then we can avoid that - hash chain. If it isn't empty then we can't believe - the value we get back, as we read it without a - lock, so instead we get the lock and re-fetch the - value below. - - Notice that not doing this optimisation on the - first hash chain is critical. We must guarantee - that we have done at least one fcntl lock at the - start of a search to guarantee that memory is - coherent on SMP systems. If records are added by - others during the search then thats OK, and we - could possibly miss those with this trick, but we - could miss them anyway without this trick, so the - semantics don't change. - - With a non-indexed ldb search this trick gains us a - factor of around 80 in speed on a linux 2.6.x - system (testing using ldbtest). - */ - if (!tlock->off && tlock->hash != 0) { - u32 off; - if (tdb->map_ptr) { - for (;tlock->hash < tdb->header.hash_size;tlock->hash++) { - if (0 != *(u32 *)(TDB_HASH_TOP(tlock->hash) + (unsigned char *)tdb->map_ptr)) { - break; - } - } - if (tlock->hash == tdb->header.hash_size) { - continue; - } - } else { - if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), &off) == 0 && - off == 0) { - continue; - } - } - } - - if (tdb_lock(tdb, tlock->hash, F_WRLCK) == -1) - return -1; - - /* No previous record? Start at top of chain. */ - if (!tlock->off) { - if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), - &tlock->off) == -1) - goto fail; - } else { - /* Otherwise unlock the previous record. */ - if (unlock_record(tdb, tlock->off) != 0) - goto fail; - } - - if (want_next) { - /* We have offset of old record: grab next */ - if (rec_read(tdb, tlock->off, rec) == -1) - goto fail; - tlock->off = rec->next; - } - - /* Iterate through chain */ - while( tlock->off) { - tdb_off current; - if (rec_read(tdb, tlock->off, rec) == -1) - goto fail; - - /* Detect infinite loops. From "Shlomi Yaakobovich" <Shlomi@exanet.com>. */ - if (tlock->off == rec->next) { - TDB_LOG((tdb, 0, "tdb_next_lock: loop detected.\n")); - goto fail; - } - - if (!TDB_DEAD(rec)) { - /* Woohoo: we found one! */ - if (lock_record(tdb, tlock->off) != 0) - goto fail; - return tlock->off; - } - - /* Try to clean dead ones from old traverses */ - current = tlock->off; - tlock->off = rec->next; - if (!tdb->read_only && - do_delete(tdb, current, rec) != 0) - goto fail; - } - tdb_unlock(tdb, tlock->hash, F_WRLCK); - want_next = 0; - } - /* We finished iteration without finding anything */ - return TDB_ERRCODE(TDB_SUCCESS, 0); - - fail: - tlock->off = 0; - if (tdb_unlock(tdb, tlock->hash, F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_next_lock: On error unlock failed!\n")); - return -1; -} - -/* traverse the entire database - calling fn(tdb, key, data) on each element. - return -1 on error or the record count traversed - if fn is NULL then it is not called - a non-zero return value from fn() indicates that the traversal should stop - */ -int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *private_val) -{ - TDB_DATA key, dbuf; - struct list_struct rec; - struct tdb_traverse_lock tl = { NULL, 0, 0 }; - int ret, count = 0; - - /* This was in the initializaton, above, but the IRIX compiler - * did not like it. crh - */ - tl.next = tdb->travlocks.next; - - /* fcntl locks don't stack: beware traverse inside traverse */ - tdb->travlocks.next = &tl; - - /* tdb_next_lock places locks on the record returned, and its chain */ - while ((ret = tdb_next_lock(tdb, &tl, &rec)) > 0) { - count++; - /* now read the full record */ - key.dptr = tdb_alloc_read(tdb, tl.off + sizeof(rec), - rec.key_len + rec.data_len); - if (!key.dptr) { - ret = -1; - if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) - goto out; - if (unlock_record(tdb, tl.off) != 0) - TDB_LOG((tdb, 0, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); - goto out; - } - key.dsize = rec.key_len; - dbuf.dptr = key.dptr + rec.key_len; - dbuf.dsize = rec.data_len; - - /* Drop chain lock, call out */ - if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) { - ret = -1; - SAFE_FREE(key.dptr); - goto out; - } - if (fn && fn(tdb, key, dbuf, private_val)) { - /* They want us to terminate traversal */ - ret = count; - if (unlock_record(tdb, tl.off) != 0) { - TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));; - ret = -1; - } - SAFE_FREE(key.dptr); - goto out; - } - SAFE_FREE(key.dptr); - } -out: - tdb->travlocks.next = tl.next; - if (ret < 0) - return -1; - else - return count; -} - -/* find the first entry in the database and return its key */ -TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb) -{ - TDB_DATA key; - struct list_struct rec; - - /* release any old lock */ - if (unlock_record(tdb, tdb->travlocks.off) != 0) - return tdb_null; - tdb->travlocks.off = tdb->travlocks.hash = 0; - - if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0) - return tdb_null; - /* now read the key */ - key.dsize = rec.key_len; - key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); - if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_firstkey: error occurred while tdb_unlocking!\n")); - return key; -} - -/* find the next entry in the database, returning its key */ -TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey) -{ - u32 oldhash; - TDB_DATA key = tdb_null; - struct list_struct rec; - char *k = NULL; - - /* Is locked key the old key? If so, traverse will be reliable. */ - if (tdb->travlocks.off) { - if (tdb_lock(tdb,tdb->travlocks.hash,F_WRLCK)) - return tdb_null; - if (rec_read(tdb, tdb->travlocks.off, &rec) == -1 - || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec), - rec.key_len)) - || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) { - /* No, it wasn't: unlock it and start from scratch */ - if (unlock_record(tdb, tdb->travlocks.off) != 0) { - SAFE_FREE(k); - return tdb_null; - } - if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) { - SAFE_FREE(k); - return tdb_null; - } - tdb->travlocks.off = 0; - } - - SAFE_FREE(k); - } - - if (!tdb->travlocks.off) { - /* No previous element: do normal find, and lock record */ - tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), F_WRLCK, &rec); - if (!tdb->travlocks.off) - return tdb_null; - tdb->travlocks.hash = BUCKET(rec.full_hash); - if (lock_record(tdb, tdb->travlocks.off) != 0) { - TDB_LOG((tdb, 0, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); - return tdb_null; - } - } - oldhash = tdb->travlocks.hash; - - /* Grab next record: locks chain and returned record, - unlocks old record */ - if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) { - key.dsize = rec.key_len; - key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec), - key.dsize); - /* Unlock the chain of this new record */ - if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); - } - /* Unlock the chain of old record */ - if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); - return key; -} - /* delete an entry in the database given a key */ -static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) +static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash) { - tdb_off rec_ptr; + tdb_off_t rec_ptr; struct list_struct rec; int ret; if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec))) return -1; - ret = do_delete(tdb, rec_ptr, &rec); + ret = tdb_do_delete(tdb, rec_ptr, &rec); + + if (ret == 0) { + tdb_increment_seqnum(tdb); + } + if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0) TDB_LOG((tdb, 0, "tdb_delete: WARNING tdb_unlock failed!\n")); return ret; } -int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) +int tdb_delete(struct tdb_context *tdb, TDB_DATA key) { u32 hash = tdb->hash_fn(&key); return tdb_delete_hash(tdb, key, hash); @@ -1527,14 +251,19 @@ int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) return 0 on success, -1 on failure */ -int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) +int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) { struct list_struct rec; u32 hash; - tdb_off rec_ptr; + tdb_off_t rec_ptr; char *p = NULL; int ret = 0; + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + /* find which hash bucket it is in */ hash = tdb->hash_fn(&key); if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) @@ -1555,7 +284,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) /* if the record doesn't exist and we are in TDB_MODIFY mode then we should fail the store */ goto fail; - } + } } /* reset the error code potentially set by the tdb_update() */ tdb->ecode = TDB_SUCCESS; @@ -1583,7 +312,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) goto fail; /* Read hash top into next ptr */ - if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) goto fail; rec.key_len = key.dsize; @@ -1592,12 +321,15 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) rec.magic = TDB_MAGIC; /* write out and point the top of the hash chain at it */ - if (rec_write(tdb, rec_ptr, &rec) == -1 - || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 - || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { + if (tdb_rec_write(tdb, rec_ptr, &rec) == -1 + || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 + || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { /* Need to tdb_unallocate() here */ goto fail; } + + tdb_increment_seqnum(tdb); + out: SAFE_FREE(p); tdb_unlock(tdb, BUCKET(hash), F_WRLCK); @@ -1607,521 +339,92 @@ fail: goto out; } -/* Attempt to append data to an entry in place - this only works if the new data size - is <= the old data size and the key exists. - on failure return -1. Record must be locked before calling. -*/ -static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA new_dbuf) -{ - struct list_struct rec; - tdb_off rec_ptr; - - /* find entry */ - if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) - return -1; - - /* Append of 0 is always ok. */ - if (new_dbuf.dsize == 0) - return 0; - - /* must be long enough for key, old data + new data and tailer */ - if (rec.rec_len < key.dsize + rec.data_len + new_dbuf.dsize + sizeof(tdb_off)) { - /* No room. */ - tdb->ecode = TDB_SUCCESS; /* Not really an error */ - return -1; - } - - if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len + rec.data_len, - new_dbuf.dptr, new_dbuf.dsize) == -1) - return -1; - - /* update size */ - rec.data_len += new_dbuf.dsize; - return rec_write(tdb, rec_ptr, &rec); -} /* Append to an entry. Create if not exist. */ - -int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) +int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf) { - struct list_struct rec; u32 hash; - tdb_off rec_ptr; - char *p = NULL; - int ret = 0; - size_t new_data_size = 0; + TDB_DATA dbuf; + int ret = -1; /* find which hash bucket it is in */ hash = tdb->hash_fn(&key); if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) return -1; - /* first try in-place. */ - if (tdb_append_inplace(tdb, key, hash, new_dbuf) == 0) - goto out; + dbuf = tdb_fetch(tdb, key); - /* reset the error code potentially set by the tdb_append_inplace() */ - tdb->ecode = TDB_SUCCESS; - - /* find entry */ - if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) { - if (tdb->ecode != TDB_ERR_NOEXIST) - goto fail; - - /* Not found - create. */ - - ret = tdb_store(tdb, key, new_dbuf, TDB_INSERT); - goto out; + if (dbuf.dptr == NULL) { + dbuf.dptr = malloc(new_dbuf.dsize); + } else { + dbuf.dptr = realloc(dbuf.dptr, dbuf.dsize + new_dbuf.dsize); } - new_data_size = rec.data_len + new_dbuf.dsize; - - /* Copy key+old_value+value *before* allocating free space in case malloc - fails and we are left with a dead spot in the tdb. */ - - if (!(p = (char *)malloc(key.dsize + new_data_size))) { + if (dbuf.dptr == NULL) { tdb->ecode = TDB_ERR_OOM; - goto fail; - } - - /* Copy the key in place. */ - memcpy(p, key.dptr, key.dsize); - - /* Now read the old data into place. */ - if (rec.data_len && - tdb_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, p + key.dsize, rec.data_len, 0) == -1) - goto fail; - - /* Finally append the new data. */ - if (new_dbuf.dsize) - memcpy(p+key.dsize+rec.data_len, new_dbuf.dptr, new_dbuf.dsize); - - /* delete any existing record - if it doesn't exist we don't - care. Doing this first reduces fragmentation, and avoids - coalescing with `allocated' block before it's updated. */ - - tdb_delete_hash(tdb, key, hash); - - if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec))) - goto fail; - - /* Read hash top into next ptr */ - if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) - goto fail; - - rec.key_len = key.dsize; - rec.data_len = new_data_size; - rec.full_hash = hash; - rec.magic = TDB_MAGIC; - - /* write out and point the top of the hash chain at it */ - if (rec_write(tdb, rec_ptr, &rec) == -1 - || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+new_data_size)==-1 - || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { - /* Need to tdb_unallocate() here */ - goto fail; + goto failed; } - out: - SAFE_FREE(p); - tdb_unlock(tdb, BUCKET(hash), F_WRLCK); - return ret; - -fail: - ret = -1; - goto out; -} + memcpy(dbuf.dptr + dbuf.dsize, new_dbuf.dptr, new_dbuf.dsize); + dbuf.dsize += new_dbuf.dsize; -static int tdb_already_open(dev_t device, - ino_t ino) -{ - TDB_CONTEXT *i; + ret = tdb_store(tdb, key, dbuf, 0); - for (i = tdbs; i; i = i->next) { - if (i->device == device && i->inode == ino) { - return 1; - } - } - - return 0; -} - -/* This is based on the hash algorithm from gdbm */ -static u32 default_tdb_hash(TDB_DATA *key) -{ - u32 value; /* Used to compute the hash value. */ - u32 i; /* Used to cycle through random values. */ - - /* Set the initial value from the key size. */ - for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++) - value = (value + (key->dptr[i] << (i*5 % 24))); - - return (1103515243 * value + 12345); -} - -/* open the database, creating it if necessary - - The open_flags and mode are passed straight to the open call on the - database file. A flags value of O_WRONLY is invalid. The hash size - is advisory, use zero for a default value. - - Return is NULL on error, in which case errno is also set. Don't - try to call tdb_error or tdb_errname, just do strerror(errno). - - @param name may be NULL for internal databases. */ -TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode) -{ - return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL); -} - - -TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode, - tdb_log_func log_fn, - tdb_hash_func hash_fn) -{ - TDB_CONTEXT *tdb; - struct stat st; - int rev = 0, locked = 0; - unsigned char *vp; - u32 vertest; - - if (!(tdb = calloc(1, sizeof *tdb))) { - /* Can't log this */ - errno = ENOMEM; - goto fail; - } - tdb->fd = -1; - tdb->name = NULL; - tdb->map_ptr = NULL; - tdb->flags = tdb_flags; - tdb->open_flags = open_flags; - tdb->log_fn = log_fn; - tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; - - if ((open_flags & O_ACCMODE) == O_WRONLY) { - TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n", - name)); - errno = EINVAL; - goto fail; - } - - if (hash_size == 0) - hash_size = DEFAULT_HASH_SIZE; - if ((open_flags & O_ACCMODE) == O_RDONLY) { - tdb->read_only = 1; - /* read only databases don't do locking or clear if first */ - tdb->flags |= TDB_NOLOCK; - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - } - - /* internal databases don't mmap or lock, and start off cleared */ - if (tdb->flags & TDB_INTERNAL) { - tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - if (tdb_new_database(tdb, hash_size) != 0) { - TDB_LOG((tdb, 0, "tdb_open_ex: tdb_new_database failed!")); - goto fail; - } - goto internal; - } - - if ((tdb->fd = open(name, open_flags, mode)) == -1) { - TDB_LOG((tdb, 5, "tdb_open_ex: could not open file %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by open(2) */ - } - - /* ensure there is only one process initialising at once */ - if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: failed to get global lock on %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by tdb_brlock */ - } - - /* we need to zero database if we are the only one with it open */ - if ((tdb_flags & TDB_CLEAR_IF_FIRST) && - (locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) { - open_flags |= O_CREAT; - if (ftruncate(tdb->fd, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: " - "failed to truncate %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by ftruncate */ - } - } - - if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) - || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0 - || (tdb->header.version != TDB_VERSION - && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) { - /* its not a valid database - possibly initialise it */ - if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) { - errno = EIO; /* ie bad format or something */ - goto fail; - } - rev = (tdb->flags & TDB_CONVERT); - } - vp = (unsigned char *)&tdb->header.version; - vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) | - (((u32)vp[2]) << 8) | (u32)vp[3]; - tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; - if (!rev) - tdb->flags &= ~TDB_CONVERT; - else { - tdb->flags |= TDB_CONVERT; - convert(&tdb->header, sizeof(tdb->header)); - } - if (fstat(tdb->fd, &st) == -1) - goto fail; - - /* Is it already in the open list? If so, fail. */ - if (tdb_already_open(st.st_dev, st.st_ino)) { - TDB_LOG((tdb, 2, "tdb_open_ex: " - "%s (%d,%d) is already open in this process\n", - name, (int)st.st_dev, (int)st.st_ino)); - errno = EBUSY; - goto fail; - } - - if (!(tdb->name = (char *)strdup(name))) { - errno = ENOMEM; - goto fail; - } - - tdb->map_size = st.st_size; - tdb->device = st.st_dev; - tdb->inode = st.st_ino; - tdb->locked = calloc(tdb->header.hash_size+1, sizeof(tdb->locked[0])); - if (!tdb->locked) { - TDB_LOG((tdb, 2, "tdb_open_ex: " - "failed to allocate lock structure for %s\n", - name)); - errno = ENOMEM; - goto fail; - } - tdb_mmap(tdb); - if (locked) { - if (!tdb->read_only) - if (tdb_clear_spinlocks(tdb) != 0) { - TDB_LOG((tdb, 0, "tdb_open_ex: " - "failed to clear spinlock\n")); - goto fail; - } - if (tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: " - "failed to take ACTIVE_LOCK on %s: %s\n", - name, strerror(errno))); - goto fail; - } - - } - - /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if - we didn't get the initial exclusive lock as we need to let all other - users know we're using it. */ - - if (tdb_flags & TDB_CLEAR_IF_FIRST) { - /* leave this lock in place to indicate it's in use */ - if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) - goto fail; - } - - - internal: - /* Internal (memory-only) databases skip all the code above to - * do with disk files, and resume here by releasing their - * global lock and hooking into the active list. */ - if (tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1) - goto fail; - tdb->next = tdbs; - tdbs = tdb; - return tdb; - - fail: - { int save_errno = errno; - - if (!tdb) - return NULL; - - if (tdb->map_ptr) { - if (tdb->flags & TDB_INTERNAL) - SAFE_FREE(tdb->map_ptr); - else - tdb_munmap(tdb); - } - SAFE_FREE(tdb->name); - if (tdb->fd != -1) - if (close(tdb->fd) != 0) - TDB_LOG((tdb, 5, "tdb_open_ex: failed to close tdb->fd on error!\n")); - SAFE_FREE(tdb->locked); - SAFE_FREE(tdb); - errno = save_errno; - return NULL; - } -} - -/** - * Close a database. - * - * @returns -1 for error; 0 for success. - **/ -int tdb_close(TDB_CONTEXT *tdb) -{ - TDB_CONTEXT **i; - int ret = 0; - - if (tdb->map_ptr) { - if (tdb->flags & TDB_INTERNAL) - SAFE_FREE(tdb->map_ptr); - else - tdb_munmap(tdb); - } - SAFE_FREE(tdb->name); - if (tdb->fd != -1) - ret = close(tdb->fd); - SAFE_FREE(tdb->locked); - - /* Remove from contexts list */ - for (i = &tdbs; *i; i = &(*i)->next) { - if (*i == tdb) { - *i = tdb->next; - break; - } - } - - memset(tdb, 0, sizeof(*tdb)); - SAFE_FREE(tdb); - +failed: + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + SAFE_FREE(dbuf.dptr); return ret; } -/* lock/unlock entire database */ -int tdb_lockall(TDB_CONTEXT *tdb) -{ - u32 i; - - /* There are no locks on read-only dbs */ - if (tdb->read_only) - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - for (i = 0; i < tdb->header.hash_size; i++) - if (tdb_lock(tdb, i, F_WRLCK)) - break; - - /* If error, release locks we have... */ - if (i < tdb->header.hash_size) { - u32 j; - - for ( j = 0; j < i; j++) - tdb_unlock(tdb, j, F_WRLCK); - return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); - } - - return 0; -} -void tdb_unlockall(TDB_CONTEXT *tdb) -{ - u32 i; - for (i=0; i < tdb->header.hash_size; i++) - tdb_unlock(tdb, i, F_WRLCK); -} - -/* lock/unlock one hash chain. This is meant to be used to reduce - contention - it cannot guarantee how many records will be locked */ -int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key) -{ - return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); -} -int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key) +/* + return the name of the current tdb file + useful for external logging functions +*/ +const char *tdb_name(struct tdb_context *tdb) { - return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); + return tdb->name; } -int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key) +/* + return the underlying file descriptor being used by tdb, or -1 + useful for external routines that want to check the device/inode + of the fd +*/ +int tdb_fd(struct tdb_context *tdb) { - return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); + return tdb->fd; } -int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key) +/* + return the current logging function + useful for external tdb routines that wish to log tdb errors +*/ +tdb_log_func tdb_log_fn(struct tdb_context *tdb) { - return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); + return tdb->log_fn; } -/* register a loging function */ -void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , const char *, ...)) -{ - tdb->log_fn = fn; -} - -/* reopen a tdb - this can be used after a fork to ensure that we have an independent - seek pointer from our parent and to re-establish locks */ -int tdb_reopen(TDB_CONTEXT *tdb) +/* + get the tdb sequence number. Only makes sense if the writers opened + with TDB_SEQNUM set. Note that this sequence number will wrap quite + quickly, so it should only be used for a 'has something changed' + test, not for code that relies on the count of the number of changes + made. If you want a counter then use a tdb record. + + The aim of this sequence number is to allow for a very lightweight + test of a possible tdb change. +*/ +int tdb_get_seqnum(struct tdb_context *tdb) { - struct stat st; + tdb_off_t seqnum=0; - if (tdb->flags & TDB_INTERNAL) - return 0; /* Nothing to do. */ - if (tdb_munmap(tdb) != 0) { - TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); - goto fail; - } - if (close(tdb->fd) != 0) - TDB_LOG((tdb, 0, "tdb_reopen: WARNING closing tdb->fd failed!\n")); - tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); - if (tdb->fd == -1) { - TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno))); - goto fail; - } - if ((tdb->flags & TDB_CLEAR_IF_FIRST) && - (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) { - TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n")); - goto fail; - } - if (fstat(tdb->fd, &st) != 0) { - TDB_LOG((tdb, 0, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); - goto fail; - } - if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { - TDB_LOG((tdb, 0, "tdb_reopen: file dev/inode has changed!\n")); - goto fail; - } - tdb_mmap(tdb); - - return 0; - -fail: - tdb_close(tdb); - return -1; + tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); + return seqnum; } -/* reopen all tdb's */ -int tdb_reopen_all(int parent_longlived) +int tdb_hash_size(struct tdb_context *tdb) { - TDB_CONTEXT *tdb; - - for (tdb=tdbs; tdb; tdb = tdb->next) { - /* - * If the parent is longlived (ie. a - * parent daemon architecture), we know - * it will keep it's active lock on a - * tdb opened with CLEAR_IF_FIRST. Thus - * for child processes we don't have to - * add an active lock. This is essential - * to improve performance on systems that - * keep POSIX locks as a non-scalable data - * structure in the kernel. - */ - if (parent_longlived) { - /* Ensure no clear-if-first. */ - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - } - - if (tdb_reopen(tdb) != 0) - return -1; - } - - return 0; + return tdb->header.hash_size; } diff --git a/source/tdb/tdb.h b/source/tdb/tdb.h index b5b87ee5a54..82f8828c89d 100644 --- a/source/tdb/tdb.h +++ b/source/tdb/tdb.h @@ -3,9 +3,9 @@ /* Unix SMB/CIFS implementation. - + trivial database library - + Copyright (C) Andrew Tridgell 1999-2004 ** NOTE! The following LGPL license applies to the tdb @@ -21,7 +21,7 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -31,17 +31,6 @@ extern "C" { #endif -#ifndef PRINTF_ATTRIBUTE -/** Use gcc attribute to check printf fns. a1 is the 1-based index of - * the parameter containing the format, and a2 the index of the first - * argument. Note that some gcc 2.x versions don't handle this - * properly **/ -#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) -#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) -#else -#define PRINTF_ATTRIBUTE(a1, a2) -#endif -#endif /* flags to tdb_store() */ #define TDB_REPLACE 1 @@ -56,102 +45,83 @@ extern "C" { #define TDB_NOMMAP 8 /* don't use mmap */ #define TDB_CONVERT 16 /* convert endian (internal use) */ #define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */ +#define TDB_NOSYNC 64 /* don't use synchronous transactions */ +#define TDB_SEQNUM 128 /* maintain a sequence number */ #define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret) /* error codes */ enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT, - TDB_ERR_NOEXIST}; - -#ifndef u32 -#define u32 unsigned -#endif + TDB_ERR_NOEXIST, TDB_ERR_EINVAL, TDB_ERR_RDONLY}; -typedef struct { +typedef struct TDB_DATA { char *dptr; size_t dsize; } TDB_DATA; -typedef u32 tdb_len; -typedef u32 tdb_off; - -/* this is stored at the front of every database */ -struct tdb_header { - char magic_food[32]; /* for /etc/magic */ - u32 version; /* version of the code */ - u32 hash_size; /* number of hash entries */ - tdb_off rwlocks; - tdb_off reserved[31]; -}; - -struct tdb_lock_type { - u32 count; - u32 ltype; -}; - -struct tdb_traverse_lock { - struct tdb_traverse_lock *next; - u32 off; - u32 hash; -}; +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif /* this is the context structure that is returned from a db open */ -typedef struct tdb_context { - char *name; /* the name of the database */ - void *map_ptr; /* where it is currently mapped */ - int fd; /* open file descriptor for the database */ - tdb_len map_size; /* how much space has been mapped */ - int read_only; /* opened read-only */ - struct tdb_lock_type *locked; /* array of chain locks */ - enum TDB_ERROR ecode; /* error code for last tdb error */ - struct tdb_header header; /* a cached copy of the header */ - u32 flags; /* the flags passed to tdb_open */ - struct tdb_traverse_lock travlocks; /* current traversal locks */ - struct tdb_context *next; /* all tdbs to avoid multiple opens */ - dev_t device; /* uniquely identifies this tdb */ - ino_t inode; /* uniquely identifies this tdb */ - void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */ - u32 (*hash_fn)(TDB_DATA *key); - int open_flags; /* flags used in the open - needed by reopen */ -} TDB_CONTEXT; - -typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *); -typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...); -typedef u32 (*tdb_hash_func)(TDB_DATA *key); - -TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, +typedef struct tdb_context TDB_CONTEXT; + +typedef int (*tdb_traverse_func)(struct tdb_context *, TDB_DATA, TDB_DATA, void *); +typedef void (*tdb_log_func)(struct tdb_context *, int , const char *, ...); +typedef unsigned int (*tdb_hash_func)(TDB_DATA *key); + +struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode); -TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, +struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, tdb_log_func log_fn, tdb_hash_func hash_fn); -int tdb_reopen(TDB_CONTEXT *tdb); -int tdb_reopen_all(int); -void tdb_logging_function(TDB_CONTEXT *tdb, tdb_log_func); -enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb); -const char *tdb_errorstr(TDB_CONTEXT *tdb); -TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); -int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf); -int tdb_close(TDB_CONTEXT *tdb); -TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb); -TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *); -int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_lockall(TDB_CONTEXT *tdb); -void tdb_unlockall(TDB_CONTEXT *tdb); +int tdb_reopen(struct tdb_context *tdb); +int tdb_reopen_all(int parent_longlived); +void tdb_logging_function(struct tdb_context *tdb, tdb_log_func); +enum TDB_ERROR tdb_error(struct tdb_context *tdb); +const char *tdb_errorstr(struct tdb_context *tdb); +TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key); +int tdb_delete(struct tdb_context *tdb, TDB_DATA key); +int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); +int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf); +int tdb_close(struct tdb_context *tdb); +TDB_DATA tdb_firstkey(struct tdb_context *tdb); +TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA key); +int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *); +int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *); +int tdb_exists(struct tdb_context *tdb, TDB_DATA key); +int tdb_lockall(struct tdb_context *tdb); +void tdb_unlockall(struct tdb_context *tdb); +const char *tdb_name(struct tdb_context *tdb); +int tdb_fd(struct tdb_context *tdb); +tdb_log_func tdb_log_fn(struct tdb_context *tdb); +int tdb_transaction_start(struct tdb_context *tdb); +int tdb_transaction_commit(struct tdb_context *tdb); +int tdb_transaction_cancel(struct tdb_context *tdb); +int tdb_transaction_recover(struct tdb_context *tdb); +int tdb_get_seqnum(struct tdb_context *tdb); +int tdb_hash_size(struct tdb_context *tdb); /* Low level locking functions: use with care */ -void tdb_set_lock_alarm(sig_atomic_t *palarm); -int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key); +int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key); /* Debug functions. Not used in production. */ -void tdb_dump_all(TDB_CONTEXT *tdb); -int tdb_printfreelist(TDB_CONTEXT *tdb); +void tdb_dump_all(struct tdb_context *tdb); +int tdb_printfreelist(struct tdb_context *tdb); extern TDB_DATA tdb_null; diff --git a/source/tdb/tdb_private.h b/source/tdb/tdb_private.h new file mode 100644 index 00000000000..d10c1c46bf6 --- /dev/null +++ b/source/tdb/tdb_private.h @@ -0,0 +1,241 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library - private includes + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _SAMBA_BUILD_ +#include "config.h" +#include <stdlib.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/mman.h> +#include <sys/stat.h> +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#include "tdb.h" + +#ifndef HAVE_PREAD_DECL +ssize_t pread(int fd, void *buf, size_t count, off_t offset); +#endif +#ifndef HAVE_PWRITE_DECL +ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset); +#endif + +#else +#include "includes.h" +#undef malloc +#undef realloc +#undef calloc +#undef strdup +#endif + +#ifndef u32 +#define u32 unsigned +#endif + +#ifndef HAVE_GETPAGESIZE +#define getpagesize() 0x2000 +#endif + +typedef u32 tdb_len_t; +typedef u32 tdb_off_t; + +#ifndef offsetof +#define offsetof(t,f) ((unsigned int)&((t *)0)->f) +#endif + +#define TDB_MAGIC_FOOD "TDB file\n" +#define TDB_VERSION (0x26011967 + 6) +#define TDB_MAGIC (0x26011999U) +#define TDB_FREE_MAGIC (~TDB_MAGIC) +#define TDB_DEAD_MAGIC (0xFEE1DEAD) +#define TDB_RECOVERY_MAGIC (0xf53bc0e7U) +#define TDB_ALIGNMENT 4 +#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT) +#define DEFAULT_HASH_SIZE 131 +#define FREELIST_TOP (sizeof(struct tdb_header)) +#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) +#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24)) +#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) +#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) +#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off_t)) +#define TDB_HASHTABLE_SIZE(tdb) ((tdb->header.hash_size+1)*sizeof(tdb_off_t)) +#define TDB_DATA_START(hash_size) TDB_HASH_TOP(hash_size-1) +#define TDB_RECOVERY_HEAD offsetof(struct tdb_header, recovery_start) +#define TDB_SEQNUM_OFS offsetof(struct tdb_header, sequence_number) +#define TDB_PAD_BYTE 0x42 +#define TDB_PAD_U32 0x42424242 + +/* NB assumes there is a local variable called "tdb" that is the + * current context, also takes doubly-parenthesized print-style + * argument. */ +#define TDB_LOG(x) tdb->log_fn x + +/* lock offsets */ +#define GLOBAL_LOCK 0 +#define ACTIVE_LOCK 4 +#define TRANSACTION_LOCK 8 + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +/* free memory if the pointer is valid and zero the pointer */ +#ifndef SAFE_FREE +#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0) +#endif + +#define BUCKET(hash) ((hash) % tdb->header.hash_size) + +#define DOCONV() (tdb->flags & TDB_CONVERT) +#define CONVERT(x) (DOCONV() ? tdb_convert(&x, sizeof(x)) : &x) + + +/* the body of the database is made of one list_struct for the free space + plus a separate data list for each hash value */ +struct list_struct { + tdb_off_t next; /* offset of the next record in the list */ + tdb_len_t rec_len; /* total byte length of record */ + tdb_len_t key_len; /* byte length of key */ + tdb_len_t data_len; /* byte length of data */ + u32 full_hash; /* the full 32 bit hash of the key */ + u32 magic; /* try to catch errors */ + /* the following union is implied: + union { + char record[rec_len]; + struct { + char key[key_len]; + char data[data_len]; + } + u32 totalsize; (tailer) + } + */ +}; + + +/* this is stored at the front of every database */ +struct tdb_header { + char magic_food[32]; /* for /etc/magic */ + u32 version; /* version of the code */ + u32 hash_size; /* number of hash entries */ + tdb_off_t rwlocks; /* obsolete - kept to detect old formats */ + tdb_off_t recovery_start; /* offset of transaction recovery region */ + tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */ + tdb_off_t reserved[29]; +}; + +struct tdb_lock_type { + u32 count; + u32 ltype; +}; + +struct tdb_traverse_lock { + struct tdb_traverse_lock *next; + u32 off; + u32 hash; + int lock_rw; +}; + + +struct tdb_methods { + int (*tdb_read)(struct tdb_context *, tdb_off_t , void *, tdb_len_t , int ); + int (*tdb_write)(struct tdb_context *, tdb_off_t, const void *, tdb_len_t); + void (*next_hash_chain)(struct tdb_context *, u32 *); + int (*tdb_oob)(struct tdb_context *, tdb_off_t , int ); + int (*tdb_expand_file)(struct tdb_context *, tdb_off_t , tdb_off_t ); + int (*tdb_brlock)(struct tdb_context *, tdb_off_t , int, int, int); +}; + +struct tdb_context { + char *name; /* the name of the database */ + void *map_ptr; /* where it is currently mapped */ + int fd; /* open file descriptor for the database */ + tdb_len_t map_size; /* how much space has been mapped */ + int read_only; /* opened read-only */ + int traverse_read; /* read-only traversal */ + struct tdb_lock_type *locked; /* array of chain locks */ + enum TDB_ERROR ecode; /* error code for last tdb error */ + struct tdb_header header; /* a cached copy of the header */ + u32 flags; /* the flags passed to tdb_open */ + struct tdb_traverse_lock travlocks; /* current traversal locks */ + struct tdb_context *next; /* all tdbs to avoid multiple opens */ + dev_t device; /* uniquely identifies this tdb */ + ino_t inode; /* uniquely identifies this tdb */ + void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */ + unsigned int (*hash_fn)(TDB_DATA *key); + int open_flags; /* flags used in the open - needed by reopen */ + unsigned int num_locks; /* number of chain locks held */ + const struct tdb_methods *methods; + struct tdb_transaction *transaction; + int page_size; +}; + + +/* + internal prototypes +*/ +int tdb_munmap(struct tdb_context *tdb); +void tdb_mmap(struct tdb_context *tdb); +int tdb_lock(struct tdb_context *tdb, int list, int ltype); +int tdb_unlock(struct tdb_context *tdb, int list, int ltype); +int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe); +int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len); +int tdb_brlock_len(struct tdb_context *tdb, tdb_off_t offset, + int rw_type, int lck_type, int probe, size_t len); +int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off); +int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off); +int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +void *tdb_convert(void *buf, u32 size); +int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec); +tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec); +int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off); +int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off); +int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec); +int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec); +int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct *rec); +char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len); +tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype, + struct list_struct *rec); +void tdb_io_init(struct tdb_context *tdb); +int tdb_expand(struct tdb_context *tdb, tdb_off_t size); + + diff --git a/source/tdb/tdbback.c b/source/tdb/tdbback.c index 7967a6bbf54..c337924d6cf 100644 --- a/source/tdb/tdbback.c +++ b/source/tdb/tdbback.c @@ -77,7 +77,7 @@ static int copy_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) TDB_CONTEXT *tdb_new = (TDB_CONTEXT *)state; if (tdb_store(tdb_new, key, dbuf, TDB_INSERT) != 0) { - fprintf(stderr,"Failed to insert into %s\n", tdb_new->name); + fprintf(stderr,"Failed to insert into %s\n", tdb_name(tdb)); failed = 1; return 1; } @@ -122,7 +122,7 @@ int backup_tdb(const char *old_name, const char *new_name) /* create the new tdb */ unlink(tmp_name); - tdb_new = tdb_open(tmp_name, tdb->header.hash_size, + tdb_new = tdb_open(tmp_name, tdb_hash_size(tdb), TDB_DEFAULT, O_RDWR|O_CREAT|O_EXCL, st.st_mode & 0777); if (!tdb_new) { @@ -179,7 +179,7 @@ int backup_tdb(const char *old_name, const char *new_name) } /* make sure the new tdb has reached stable storage */ - fsync(tdb_new->fd); + fsync(tdb_fd(tdb_new)); /* close the new tdb and rename it to .bak */ tdb_close(tdb_new); diff --git a/source/tdb/tdbutil.c b/source/tdb/tdbutil.c index fc45fa93606..e13f7e3e678 100644 --- a/source/tdb/tdbutil.c +++ b/source/tdb/tdbutil.c @@ -19,9 +19,21 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "includes.h" +#include "tdb_private.h" #include <fnmatch.h> +/*************************************************************** + Allow a caller to set a "alarm" flag that tdb can check to abort + a blocking lock on SIGALRM. +***************************************************************/ + +static sig_atomic_t *palarm_fired; + +static void tdb_set_lock_alarm(sig_atomic_t *palarm) +{ + palarm_fired = palarm; +} + /* these are little tdb utility functions that are meant to make dealing with a tdb database a little less cumbersome in Samba */ @@ -641,129 +653,6 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) } -/** - * Pack SID passed by pointer - * - * @param pack_buf pointer to buffer which is to be filled with packed data - * @param bufsize size of packing buffer - * @param sid pointer to sid to be packed - * - * @return length of the packed representation of the whole structure - **/ -size_t tdb_sid_pack(char* pack_buf, int bufsize, DOM_SID* sid) -{ - int idx; - size_t len = 0; - - if (!sid || !pack_buf) return -1; - - len += tdb_pack(pack_buf + len, bufsize - len, "bb", sid->sid_rev_num, - sid->num_auths); - - for (idx = 0; idx < 6; idx++) { - len += tdb_pack(pack_buf + len, bufsize - len, "b", sid->id_auth[idx]); - } - - for (idx = 0; idx < MAXSUBAUTHS; idx++) { - len += tdb_pack(pack_buf + len, bufsize - len, "d", sid->sub_auths[idx]); - } - - return len; -} - - -/** - * Unpack SID into a pointer - * - * @param pack_buf pointer to buffer with packed representation - * @param bufsize size of the buffer - * @param sid pointer to sid structure to be filled with unpacked data - * - * @return size of structure unpacked from buffer - **/ -size_t tdb_sid_unpack(char* pack_buf, int bufsize, DOM_SID* sid) -{ - int idx, len = 0; - - if (!sid || !pack_buf) return -1; - - len += tdb_unpack(pack_buf + len, bufsize - len, "bb", - &sid->sid_rev_num, &sid->num_auths); - - for (idx = 0; idx < 6; idx++) { - len += tdb_unpack(pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]); - } - - for (idx = 0; idx < MAXSUBAUTHS; idx++) { - len += tdb_unpack(pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]); - } - - return len; -} - - -/** - * Pack TRUSTED_DOM_PASS passed by pointer - * - * @param pack_buf pointer to buffer which is to be filled with packed data - * @param bufsize size of the buffer - * @param pass pointer to trusted domain password to be packed - * - * @return length of the packed representation of the whole structure - **/ -size_t tdb_trusted_dom_pass_pack(char* pack_buf, int bufsize, TRUSTED_DOM_PASS* pass) -{ - int idx, len = 0; - - if (!pack_buf || !pass) return -1; - - /* packing unicode domain name and password */ - len += tdb_pack(pack_buf + len, bufsize - len, "d", pass->uni_name_len); - - for (idx = 0; idx < 32; idx++) - len += tdb_pack(pack_buf + len, bufsize - len, "w", pass->uni_name[idx]); - - len += tdb_pack(pack_buf + len, bufsize - len, "dPd", pass->pass_len, - pass->pass, pass->mod_time); - - /* packing SID structure */ - len += tdb_sid_pack(pack_buf + len, bufsize - len, &pass->domain_sid); - - return len; -} - - -/** - * Unpack TRUSTED_DOM_PASS passed by pointer - * - * @param pack_buf pointer to buffer with packed representation - * @param bufsize size of the buffer - * @param pass pointer to trusted domain password to be filled with unpacked data - * - * @return size of structure unpacked from buffer - **/ -size_t tdb_trusted_dom_pass_unpack(char* pack_buf, int bufsize, TRUSTED_DOM_PASS* pass) -{ - int idx, len = 0; - - if (!pack_buf || !pass) return -1; - - /* unpack unicode domain name and plaintext password */ - len += tdb_unpack(pack_buf, bufsize - len, "d", &pass->uni_name_len); - - for (idx = 0; idx < 32; idx++) - len += tdb_unpack(pack_buf + len, bufsize - len, "w", &pass->uni_name[idx]); - - len += tdb_unpack(pack_buf + len, bufsize - len, "dPd", &pass->pass_len, &pass->pass, - &pass->mod_time); - - /* unpack domain sid */ - len += tdb_sid_unpack(pack_buf + len, bufsize - len, &pass->domain_sid); - - return len; -} - - /**************************************************************************** Log tdb messages via DEBUG(). ****************************************************************************/ @@ -806,15 +695,6 @@ TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, } /**************************************************************************** - return the name of the current tdb file useful for external logging - functions -****************************************************************************/ -const char *tdb_name(struct tdb_context *tdb) -{ - return tdb->name; -} - -/**************************************************************************** Allow tdb_delete to be used as a tdb_traversal_fn. ****************************************************************************/ @@ -893,3 +773,43 @@ void tdb_search_list_free(TDB_LIST_NODE* node) node = next_node; }; } + +size_t tdb_map_size(struct tdb_context *tdb) +{ + return tdb->map_size; +} + +int tdb_get_flags(struct tdb_context *tdb) +{ + return tdb->flags; +} + +/**************************************************************************** + tdb_store, wrapped in a transaction. This way we make sure that a process + that dies within writing does not leave a corrupt tdb behind. +****************************************************************************/ + +int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, + int flag) +{ + int res; + + if ((res = tdb_transaction_start(tdb)) != 0) { + DEBUG(5, ("tdb_transaction_start failed\n")); + return res; + } + + if ((res = tdb_store(tdb, key, dbuf, flag)) != 0) { + DEBUG(10, ("tdb_store failed\n")); + if (tdb_transaction_cancel(tdb) != 0) { + smb_panic("Cancelling transaction failed\n"); + } + return res; + } + + if ((res = tdb_transaction_commit(tdb)) != 0) { + DEBUG(5, ("tdb_transaction_commit failed\n")); + } + + return res; +} diff --git a/source/tdb/tdbutil.h b/source/tdb/tdbutil.h index 1a181a962f2..44351619f45 100644 --- a/source/tdb/tdbutil.h +++ b/source/tdb/tdbutil.h @@ -1,8 +1,7 @@ /* Unix SMB/CIFS implementation. tdb utility functions - Copyright (C) Andrew Tridgell 1999 - Copyright (C) Rafal Szczesniak 2002 + Copyright (C) Andrew Tridgell 1999 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,6 +21,7 @@ #ifndef __TDBUTIL_H__ #define __TDBUTIL_H__ +#include "tdb.h" /* single node of a list returned by tdb_search_keys */ typedef struct keys_node @@ -31,8 +31,38 @@ typedef struct keys_node } TDB_LIST_NODE; -TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT*, const char*); +TDB_LIST_NODE *tdb_search_keys(struct tdb_context*, const char*); void tdb_search_list_free(TDB_LIST_NODE*); - +int32_t tdb_change_int32_atomic(struct tdb_context *tdb, const char *keystr, int32_t *oldval, int32_t change_val); +int tdb_lock_bystring(struct tdb_context *tdb, const char *keyval); +int tdb_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, + int timeout); +void tdb_unlock_bystring(struct tdb_context *tdb, const char *keyval); +int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, + unsigned int timeout); +void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval); +int32_t tdb_fetch_int32(struct tdb_context *tdb, const char *keystr); +BOOL tdb_store_uint32(struct tdb_context *tdb, const char *keystr, uint32_t value); +int tdb_store_int32(struct tdb_context *tdb, const char *keystr, int32_t v); +BOOL tdb_fetch_uint32(struct tdb_context *tdb, const char *keystr, uint32_t *value); +int tdb_traverse_delete_fn(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA dbuf, + void *state); +int tdb_store_bystring(struct tdb_context *tdb, const char *keystr, TDB_DATA data, int flags); +TDB_DATA tdb_fetch_bystring(struct tdb_context *tdb, const char *keystr); +int tdb_delete_bystring(struct tdb_context *tdb, const char *keystr); +struct tdb_context *tdb_open_log(const char *name, int hash_size, + int tdb_flags, int open_flags, mode_t mode); +int tdb_unpack(char *buf, int bufsize, const char *fmt, ...); +size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...); +TDB_DATA make_tdb_data(const char *dptr, size_t dsize); +TDB_DATA string_tdb_data(const char *string); +int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, + int flag); +BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, + uint32 *oldval, uint32 change_val); +int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, + unsigned int timeout); +int tdb_get_flags(struct tdb_context *tdb); +size_t tdb_map_size(struct tdb_context *tdb); #endif /* __TDBUTIL_H__ */ diff --git a/source/tdb/transaction.c b/source/tdb/transaction.c new file mode 100644 index 00000000000..aa54c4ae3c8 --- /dev/null +++ b/source/tdb/transaction.c @@ -0,0 +1,1043 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tdb_private.h" + +/* + transaction design: + + - only allow a single transaction at a time per database. This makes + using the transaction API simpler, as otherwise the caller would + have to cope with temporary failures in transactions that conflict + with other current transactions + + - keep the transaction recovery information in the same file as the + database, using a special 'transaction recovery' record pointed at + by the header. This removes the need for extra journal files as + used by some other databases + + - dymacially allocated the transaction recover record, re-using it + for subsequent transactions. If a larger record is needed then + tdb_free() the old record to place it on the normal tdb freelist + before allocating the new record + + - during transactions, keep a linked list of writes all that have + been performed by intercepting all tdb_write() calls. The hooked + transaction versions of tdb_read() and tdb_write() check this + linked list and try to use the elements of the list in preference + to the real database. + + - don't allow any locks to be held when a transaction starts, + otherwise we can end up with deadlock (plus lack of lock nesting + in posix locks would mean the lock is lost) + + - if the caller gains a lock during the transaction but doesn't + release it then fail the commit + + - allow for nested calls to tdb_transaction_start(), re-using the + existing transaction record. If the inner transaction is cancelled + then a subsequent commit will fail + + - keep a mirrored copy of the tdb hash chain heads to allow for the + fast hash heads scan on traverse, updating the mirrored copy in + the transaction version of tdb_write + + - allow callers to mix transaction and non-transaction use of tdb, + although once a transaction is started then an exclusive lock is + gained until the transaction is committed or cancelled + + - the commit stategy involves first saving away all modified data + into a linearised buffer in the transaction recovery area, then + marking the transaction recovery area with a magic value to + indicate a valid recovery record. In total 4 fsync/msync calls are + needed per commit to prevent race conditions. It might be possible + to reduce this to 3 or even 2 with some more work. + + - check for a valid recovery record on open of the tdb, while the + global lock is held. Automatically recover from the transaction + recovery area if needed, then continue with the open as + usual. This allows for smooth crash recovery with no administrator + intervention. + + - if TDB_NOSYNC is passed to flags in tdb_open then transactions are + still available, but no transaction recovery area is used and no + fsync/msync calls are made. + +*/ + + +/* + hold the context of any current transaction +*/ +struct tdb_transaction { + /* we keep a mirrored copy of the tdb hash heads here so + tdb_next_hash_chain() can operate efficiently */ + u32 *hash_heads; + + /* the original io methods - used to do IOs to the real db */ + const struct tdb_methods *io_methods; + + /* the list of transaction elements. We use a doubly linked + list with a last pointer to allow us to keep the list + ordered, with first element at the front of the list. It + needs to be doubly linked as the read/write traversals need + to be backwards, while the commit needs to be forwards */ + struct tdb_transaction_el { + struct tdb_transaction_el *next, *prev; + tdb_off_t offset; + tdb_len_t length; + unsigned char *data; + } *elements, *elements_last; + + /* non-zero when an internal transaction error has + occurred. All write operations will then fail until the + transaction is ended */ + int transaction_error; + + /* when inside a transaction we need to keep track of any + nested tdb_transaction_start() calls, as these are allowed, + but don't create a new transaction */ + int nesting; + + /* old file size before transaction */ + tdb_len_t old_map_size; +}; + + +/* + read while in a transaction. We need to check first if the data is in our list + of transaction elements, then if not do a real read +*/ +static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf, + tdb_len_t len, int cv) +{ + struct tdb_transaction_el *el; + + /* we need to walk the list backwards to get the most recent data */ + for (el=tdb->transaction->elements_last;el;el=el->prev) { + tdb_len_t partial; + + if (off+len <= el->offset) { + continue; + } + if (off >= el->offset + el->length) { + continue; + } + + /* an overlapping read - needs to be split into up to + 2 reads and a memcpy */ + if (off < el->offset) { + partial = el->offset - off; + if (transaction_read(tdb, off, buf, partial, cv) != 0) { + goto fail; + } + len -= partial; + off += partial; + buf = (void *)(partial + (char *)buf); + } + if (off + len <= el->offset + el->length) { + partial = len; + } else { + partial = el->offset + el->length - off; + } + memcpy(buf, el->data + (off - el->offset), partial); + if (cv) { + tdb_convert(buf, len); + } + len -= partial; + off += partial; + buf = (void *)(partial + (char *)buf); + + if (len != 0 && transaction_read(tdb, off, buf, len, cv) != 0) { + goto fail; + } + + return 0; + } + + /* its not in the transaction elements - do a real read */ + return tdb->transaction->io_methods->tdb_read(tdb, off, buf, len, cv); + +fail: + TDB_LOG((tdb, 0, "transaction_read: failed at off=%d len=%d\n", off, len)); + tdb->ecode = TDB_ERR_IO; + tdb->transaction->transaction_error = 1; + return -1; +} + + +/* + write while in a transaction +*/ +static int transaction_write(struct tdb_context *tdb, tdb_off_t off, + const void *buf, tdb_len_t len) +{ + struct tdb_transaction_el *el, *best_el=NULL; + + if (len == 0) { + return 0; + } + + /* if the write is to a hash head, then update the transaction + hash heads */ + if (len == sizeof(tdb_off_t) && off >= FREELIST_TOP && + off < FREELIST_TOP+TDB_HASHTABLE_SIZE(tdb)) { + u32 chain = (off-FREELIST_TOP) / sizeof(tdb_off_t); + memcpy(&tdb->transaction->hash_heads[chain], buf, len); + } + + /* first see if we can replace an existing entry */ + for (el=tdb->transaction->elements_last;el;el=el->prev) { + tdb_len_t partial; + + if (best_el == NULL && off == el->offset+el->length) { + best_el = el; + } + + if (off+len <= el->offset) { + continue; + } + if (off >= el->offset + el->length) { + continue; + } + + /* an overlapping write - needs to be split into up to + 2 writes and a memcpy */ + if (off < el->offset) { + partial = el->offset - off; + if (transaction_write(tdb, off, buf, partial) != 0) { + goto fail; + } + len -= partial; + off += partial; + buf = (const void *)(partial + (const char *)buf); + } + if (off + len <= el->offset + el->length) { + partial = len; + } else { + partial = el->offset + el->length - off; + } + memcpy(el->data + (off - el->offset), buf, partial); + len -= partial; + off += partial; + buf = (const void *)(partial + (const char *)buf); + + if (len != 0 && transaction_write(tdb, off, buf, len) != 0) { + goto fail; + } + + return 0; + } + + /* see if we can append the new entry to an existing entry */ + if (best_el && best_el->offset + best_el->length == off && + (off+len < tdb->transaction->old_map_size || + off > tdb->transaction->old_map_size)) { + unsigned char *data = best_el->data; + el = best_el; + el->data = realloc(el->data, el->length + len); + if (el->data == NULL) { + tdb->ecode = TDB_ERR_OOM; + tdb->transaction->transaction_error = 1; + el->data = data; + return -1; + } + if (buf) { + memcpy(el->data + el->length, buf, len); + } else { + memset(el->data + el->length, TDB_PAD_BYTE, len); + } + el->length += len; + return 0; + } + + /* add a new entry at the end of the list */ + el = malloc(sizeof(*el)); + if (el == NULL) { + tdb->ecode = TDB_ERR_OOM; + tdb->transaction->transaction_error = 1; + return -1; + } + el->next = NULL; + el->prev = tdb->transaction->elements_last; + el->offset = off; + el->length = len; + el->data = malloc(len); + if (el->data == NULL) { + free(el); + tdb->ecode = TDB_ERR_OOM; + tdb->transaction->transaction_error = 1; + return -1; + } + if (buf) { + memcpy(el->data, buf, len); + } else { + memset(el->data, TDB_PAD_BYTE, len); + } + if (el->prev) { + el->prev->next = el; + } else { + tdb->transaction->elements = el; + } + tdb->transaction->elements_last = el; + return 0; + +fail: + TDB_LOG((tdb, 0, "transaction_write: failed at off=%d len=%d\n", off, len)); + tdb->ecode = TDB_ERR_IO; + tdb->transaction->transaction_error = 1; + return -1; +} + +/* + accelerated hash chain head search, using the cached hash heads +*/ +static void transaction_next_hash_chain(struct tdb_context *tdb, u32 *chain) +{ + u32 h = *chain; + for (;h < tdb->header.hash_size;h++) { + /* the +1 takes account of the freelist */ + if (0 != tdb->transaction->hash_heads[h+1]) { + break; + } + } + (*chain) = h; +} + +/* + out of bounds check during a transaction +*/ +static int transaction_oob(struct tdb_context *tdb, tdb_off_t len, int probe) +{ + if (len <= tdb->map_size) { + return 0; + } + return TDB_ERRCODE(TDB_ERR_IO, -1); +} + +/* + transaction version of tdb_expand(). +*/ +static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size, + tdb_off_t addition) +{ + /* add a write to the transaction elements, so subsequent + reads see the zero data */ + if (transaction_write(tdb, size, NULL, addition) != 0) { + return -1; + } + + return 0; +} + +/* + brlock during a transaction - ignore them +*/ +int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset, + int rw_type, int lck_type, int probe) +{ + return 0; +} + +static const struct tdb_methods transaction_methods = { + transaction_read, + transaction_write, + transaction_next_hash_chain, + transaction_oob, + transaction_expand_file, + transaction_brlock +}; + + +/* + start a tdb transaction. No token is returned, as only a single + transaction is allowed to be pending per tdb_context +*/ +int tdb_transaction_start(struct tdb_context *tdb) +{ + /* some sanity checks */ + if (tdb->read_only || (tdb->flags & TDB_INTERNAL) || tdb->traverse_read) { + TDB_LOG((tdb, 0, "tdb_transaction_start: cannot start a transaction on a read-only or internal db\n")); + tdb->ecode = TDB_ERR_EINVAL; + return -1; + } + + /* cope with nested tdb_transaction_start() calls */ + if (tdb->transaction != NULL) { + tdb->transaction->nesting++; + TDB_LOG((tdb, 0, "tdb_transaction_start: nesting %d\n", + tdb->transaction->nesting)); + return 0; + } + + if (tdb->num_locks != 0) { + /* the caller must not have any locks when starting a + transaction as otherwise we'll be screwed by lack + of nested locks in posix */ + TDB_LOG((tdb, 0, "tdb_transaction_start: cannot start a transaction with locks held\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb->travlocks.next != NULL) { + /* you cannot use transactions inside a traverse (although you can use + traverse inside a transaction) as otherwise you can end up with + deadlock */ + TDB_LOG((tdb, 0, "tdb_transaction_start: cannot start a transaction within a traverse\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + tdb->transaction = calloc(sizeof(struct tdb_transaction), 1); + if (tdb->transaction == NULL) { + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + /* get the transaction write lock. This is a blocking lock. As + discussed with Volker, there are a number of ways we could + make this async, which we will probably do in the future */ + if (tdb_brlock_len(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_start: failed to get transaction lock\n")); + tdb->ecode = TDB_ERR_LOCK; + SAFE_FREE(tdb->transaction); + return -1; + } + + /* get a read lock from the freelist to the end of file. This + is upgraded to a write lock during the commit */ + if (tdb_brlock_len(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_start: failed to get hash locks\n")); + tdb->ecode = TDB_ERR_LOCK; + goto fail; + } + + /* setup a copy of the hash table heads so the hash scan in + traverse can be fast */ + tdb->transaction->hash_heads = calloc(tdb->header.hash_size+1, sizeof(tdb_off_t)); + if (tdb->transaction->hash_heads == NULL) { + tdb->ecode = TDB_ERR_OOM; + goto fail; + } + if (tdb->methods->tdb_read(tdb, FREELIST_TOP, tdb->transaction->hash_heads, + TDB_HASHTABLE_SIZE(tdb), 0) != 0) { + TDB_LOG((tdb, 0, "tdb_transaction_start: failed to read hash heads\n")); + tdb->ecode = TDB_ERR_IO; + goto fail; + } + + /* make sure we know about any file expansions already done by + anyone else */ + tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1); + tdb->transaction->old_map_size = tdb->map_size; + + /* finally hook the io methods, replacing them with + transaction specific methods */ + tdb->transaction->io_methods = tdb->methods; + tdb->methods = &transaction_methods; + + /* by calling this transaction write here, we ensure that we don't grow the + transaction linked list due to hash table updates */ + if (transaction_write(tdb, FREELIST_TOP, tdb->transaction->hash_heads, + TDB_HASHTABLE_SIZE(tdb)) != 0) { + TDB_LOG((tdb, 0, "tdb_transaction_start: failed to prime hash table\n")); + tdb->ecode = TDB_ERR_IO; + goto fail; + } + + return 0; + +fail: + tdb_brlock_len(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); + tdb_brlock_len(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1); + SAFE_FREE(tdb->transaction->hash_heads); + SAFE_FREE(tdb->transaction); + return -1; +} + + +/* + cancel the current transaction +*/ +int tdb_transaction_cancel(struct tdb_context *tdb) +{ + if (tdb->transaction == NULL) { + TDB_LOG((tdb, 0, "tdb_transaction_cancel: no transaction\n")); + return -1; + } + + if (tdb->transaction->nesting != 0) { + tdb->transaction->transaction_error = 1; + tdb->transaction->nesting--; + return 0; + } + + tdb->map_size = tdb->transaction->old_map_size; + + /* free all the transaction elements */ + while (tdb->transaction->elements) { + struct tdb_transaction_el *el = tdb->transaction->elements; + tdb->transaction->elements = el->next; + free(el->data); + free(el); + } + + /* remove any locks created during the transaction */ + if (tdb->num_locks != 0) { + int h; + for (h=0;h<tdb->header.hash_size+1;h++) { + if (tdb->locked[h].count != 0) { + tdb_brlock_len(tdb,FREELIST_TOP+4*h,F_UNLCK,F_SETLKW, 0, 1); + tdb->locked[h].count = 0; + } + } + tdb->num_locks = 0; + } + + /* restore the normal io methods */ + tdb->methods = tdb->transaction->io_methods; + + tdb_brlock_len(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); + tdb_brlock_len(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1); + SAFE_FREE(tdb->transaction->hash_heads); + SAFE_FREE(tdb->transaction); + + return 0; +} + +/* + sync to disk +*/ +static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t length) +{ + if (fsync(tdb->fd) != 0) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0, "tdb_transaction: fsync failed\n")); + return -1; + } +#ifdef MS_SYNC + if (tdb->map_ptr) { + tdb_off_t moffset = offset & ~(tdb->page_size-1); + if (msync(moffset + (char *)tdb->map_ptr, + length + (offset - moffset), MS_SYNC) != 0) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0, "tdb_transaction: msync failed - %s\n", + strerror(errno))); + return -1; + } + } +#endif + return 0; +} + + +/* + work out how much space the linearised recovery data will consume +*/ +static tdb_len_t tdb_recovery_size(struct tdb_context *tdb) +{ + struct tdb_transaction_el *el; + tdb_len_t recovery_size = 0; + + recovery_size = sizeof(u32); + for (el=tdb->transaction->elements;el;el=el->next) { + if (el->offset >= tdb->transaction->old_map_size) { + continue; + } + recovery_size += 2*sizeof(tdb_off_t) + el->length; + } + + return recovery_size; +} + +/* + allocate the recovery area, or use an existing recovery area if it is + large enough +*/ +static int tdb_recovery_allocate(struct tdb_context *tdb, + tdb_len_t *recovery_size, + tdb_off_t *recovery_offset, + tdb_len_t *recovery_max_size) +{ + struct list_struct rec; + const struct tdb_methods *methods = tdb->transaction->io_methods; + tdb_off_t recovery_head; + + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { + TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to read recovery head\n")); + return -1; + } + + rec.rec_len = 0; + + if (recovery_head != 0 && + methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) { + TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to read recovery record\n")); + return -1; + } + + *recovery_size = tdb_recovery_size(tdb); + + if (recovery_head != 0 && *recovery_size <= rec.rec_len) { + /* it fits in the existing area */ + *recovery_max_size = rec.rec_len; + *recovery_offset = recovery_head; + return 0; + } + + /* we need to free up the old recovery area, then allocate a + new one at the end of the file. Note that we cannot use + tdb_allocate() to allocate the new one as that might return + us an area that is being currently used (as of the start of + the transaction) */ + if (recovery_head != 0) { + if (tdb_free(tdb, recovery_head, &rec) == -1) { + TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to free previous recovery area\n")); + return -1; + } + } + + /* the tdb_free() call might have increased the recovery size */ + *recovery_size = tdb_recovery_size(tdb); + + /* round up to a multiple of page size */ + *recovery_max_size = TDB_ALIGN(sizeof(rec) + *recovery_size, tdb->page_size) - sizeof(rec); + *recovery_offset = tdb->map_size; + recovery_head = *recovery_offset; + + if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, + (tdb->map_size - tdb->transaction->old_map_size) + + sizeof(rec) + *recovery_max_size) == -1) { + TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to create recovery area\n")); + return -1; + } + + /* remap the file (if using mmap) */ + methods->tdb_oob(tdb, tdb->map_size + 1, 1); + + /* we have to reset the old map size so that we don't try to expand the file + again in the transaction commit, which would destroy the recovery area */ + tdb->transaction->old_map_size = tdb->map_size; + + /* write the recovery header offset and sync - we can sync without a race here + as the magic ptr in the recovery record has not been set */ + CONVERT(recovery_head); + if (methods->tdb_write(tdb, TDB_RECOVERY_HEAD, + &recovery_head, sizeof(tdb_off_t)) == -1) { + TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to write recovery head\n")); + return -1; + } + + return 0; +} + + +/* + setup the recovery data that will be used on a crash during commit +*/ +static int transaction_setup_recovery(struct tdb_context *tdb, + tdb_off_t *magic_offset) +{ + struct tdb_transaction_el *el; + tdb_len_t recovery_size; + unsigned char *data, *p; + const struct tdb_methods *methods = tdb->transaction->io_methods; + struct list_struct *rec; + tdb_off_t recovery_offset, recovery_max_size; + tdb_off_t old_map_size = tdb->transaction->old_map_size; + u32 magic, tailer; + + /* + check that the recovery area has enough space + */ + if (tdb_recovery_allocate(tdb, &recovery_size, + &recovery_offset, &recovery_max_size) == -1) { + return -1; + } + + data = malloc(recovery_size + sizeof(*rec)); + if (data == NULL) { + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + rec = (struct list_struct *)data; + memset(rec, 0, sizeof(*rec)); + + rec->magic = 0; + rec->data_len = recovery_size; + rec->rec_len = recovery_max_size; + rec->key_len = old_map_size; + CONVERT(rec); + + /* build the recovery data into a single blob to allow us to do a single + large write, which should be more efficient */ + p = data + sizeof(*rec); + for (el=tdb->transaction->elements;el;el=el->next) { + if (el->offset >= old_map_size) { + continue; + } + if (el->offset + el->length > tdb->transaction->old_map_size) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: transaction data over new region boundary\n")); + free(data); + tdb->ecode = TDB_ERR_CORRUPT; + return -1; + } + memcpy(p, &el->offset, 4); + memcpy(p+4, &el->length, 4); + if (DOCONV()) { + tdb_convert(p, 8); + } + /* the recovery area contains the old data, not the + new data, so we have to call the original tdb_read + method to get it */ + if (methods->tdb_read(tdb, el->offset, p + 8, el->length, 0) != 0) { + free(data); + tdb->ecode = TDB_ERR_IO; + return -1; + } + p += 8 + el->length; + } + + /* and the tailer */ + tailer = sizeof(*rec) + recovery_max_size; + memcpy(p, &tailer, 4); + CONVERT(p); + + /* write the recovery data to the recovery area */ + if (methods->tdb_write(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to write recovery data\n")); + free(data); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* as we don't have ordered writes, we have to sync the recovery + data before we update the magic to indicate that the recovery + data is present */ + if (transaction_sync(tdb, recovery_offset, sizeof(*rec) + recovery_size) == -1) { + free(data); + return -1; + } + + free(data); + + magic = TDB_RECOVERY_MAGIC; + CONVERT(magic); + + *magic_offset = recovery_offset + offsetof(struct list_struct, magic); + + if (methods->tdb_write(tdb, *magic_offset, &magic, sizeof(magic)) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to write recovery magic\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* ensure the recovery magic marker is on disk */ + if (transaction_sync(tdb, *magic_offset, sizeof(magic)) == -1) { + return -1; + } + + return 0; +} + +/* + commit the current transaction +*/ +int tdb_transaction_commit(struct tdb_context *tdb) +{ + const struct tdb_methods *methods; + tdb_off_t magic_offset = 0; + u32 zero = 0; + + if (tdb->transaction == NULL) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: no transaction\n")); + return -1; + } + + if (tdb->transaction->transaction_error) { + tdb->ecode = TDB_ERR_IO; + tdb_transaction_cancel(tdb); + TDB_LOG((tdb, 0, "tdb_transaction_commit: transaction error pending\n")); + return -1; + } + + if (tdb->transaction->nesting != 0) { + tdb->transaction->nesting--; + return 0; + } + + /* check for a null transaction */ + if (tdb->transaction->elements == NULL) { + tdb_transaction_cancel(tdb); + return 0; + } + + methods = tdb->transaction->io_methods; + + /* if there are any locks pending then the caller has not + nested their locks properly, so fail the transaction */ + if (tdb->num_locks) { + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, 0, "tdb_transaction_commit: locks pending on commit\n")); + tdb_transaction_cancel(tdb); + return -1; + } + + /* upgrade the main transaction lock region to a write lock */ + if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_start: failed to upgrade hash locks\n")); + tdb->ecode = TDB_ERR_LOCK; + tdb_transaction_cancel(tdb); + return -1; + } + + /* get the global lock - this prevents new users attaching to the database + during the commit */ + if (tdb_brlock_len(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to get global lock\n")); + tdb->ecode = TDB_ERR_LOCK; + tdb_transaction_cancel(tdb); + return -1; + } + + if (!(tdb->flags & TDB_NOSYNC)) { + /* write the recovery data to the end of the file */ + if (transaction_setup_recovery(tdb, &magic_offset) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to setup recovery data\n")); + tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); + tdb_transaction_cancel(tdb); + return -1; + } + } + + /* expand the file to the new size if needed */ + if (tdb->map_size != tdb->transaction->old_map_size) { + if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, + tdb->map_size - + tdb->transaction->old_map_size) == -1) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0, "tdb_transaction_commit: expansion failed\n")); + tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); + tdb_transaction_cancel(tdb); + return -1; + } + tdb->map_size = tdb->transaction->old_map_size; + methods->tdb_oob(tdb, tdb->map_size + 1, 1); + } + + /* perform all the writes */ + while (tdb->transaction->elements) { + struct tdb_transaction_el *el = tdb->transaction->elements; + + if (methods->tdb_write(tdb, el->offset, el->data, el->length) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: write failed during commit\n")); + + /* we've overwritten part of the data and + possibly expanded the file, so we need to + run the crash recovery code */ + tdb->methods = methods; + tdb_transaction_recover(tdb); + + tdb_transaction_cancel(tdb); + tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); + + TDB_LOG((tdb, 0, "tdb_transaction_commit: write failed\n")); + return -1; + } + tdb->transaction->elements = el->next; + free(el->data); + free(el); + } + + if (!(tdb->flags & TDB_NOSYNC)) { + /* ensure the new data is on disk */ + if (transaction_sync(tdb, 0, tdb->map_size) == -1) { + return -1; + } + + /* remove the recovery marker */ + if (methods->tdb_write(tdb, magic_offset, &zero, 4) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to remove recovery magic\n")); + return -1; + } + + /* ensure the recovery marker has been removed on disk */ + if (transaction_sync(tdb, magic_offset, 4) == -1) { + return -1; + } + } + + tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); + + /* + TODO: maybe write to some dummy hdr field, or write to magic + offset without mmap, before the last sync, instead of the + utime() call + */ + + /* on some systems (like Linux 2.6.x) changes via mmap/msync + don't change the mtime of the file, this means the file may + not be backed up (as tdb rounding to block sizes means that + file size changes are quite rare too). The following forces + mtime changes when a transaction completes */ +#ifdef HAVE_UTIME + utime(tdb->name, NULL); +#endif + + /* use a transaction cancel to free memory and remove the + transaction locks */ + tdb_transaction_cancel(tdb); + return 0; +} + + +/* + recover from an aborted transaction. Must be called with exclusive + database write access already established (including the global + lock to prevent new processes attaching) +*/ +int tdb_transaction_recover(struct tdb_context *tdb) +{ + tdb_off_t recovery_head, recovery_eof; + unsigned char *data, *p; + u32 zero = 0; + struct list_struct rec; + + /* find the recovery area */ + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to read recovery head\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + if (recovery_head == 0) { + /* we have never allocated a recovery record */ + return 0; + } + + /* read the recovery record */ + if (tdb->methods->tdb_read(tdb, recovery_head, &rec, + sizeof(rec), DOCONV()) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to read recovery record\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + if (rec.magic != TDB_RECOVERY_MAGIC) { + /* there is no valid recovery data */ + return 0; + } + + if (tdb->read_only) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: attempt to recover read only database\n")); + tdb->ecode = TDB_ERR_CORRUPT; + return -1; + } + + recovery_eof = rec.key_len; + + data = malloc(rec.data_len); + if (data == NULL) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to allocate recovery data\n")); + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + /* read the full recovery data */ + if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data, + rec.data_len, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to read recovery data\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* recover the file data */ + p = data; + while (p+8 < data + rec.data_len) { + u32 ofs, len; + if (DOCONV()) { + tdb_convert(p, 8); + } + memcpy(&ofs, p, 4); + memcpy(&len, p+4, 4); + + if (tdb->methods->tdb_write(tdb, ofs, p+8, len) == -1) { + free(data); + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to recover %d bytes at offset %d\n", len, ofs)); + tdb->ecode = TDB_ERR_IO; + return -1; + } + p += 8 + len; + } + + free(data); + + if (transaction_sync(tdb, 0, tdb->map_size) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to sync recovery\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* if the recovery area is after the recovered eof then remove it */ + if (recovery_eof <= recovery_head) { + if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to remove recovery head\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + } + + /* remove the recovery magic */ + if (tdb_ofs_write(tdb, recovery_head + offsetof(struct list_struct, magic), + &zero) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to remove recovery magic\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* reduce the file size to the old size */ + tdb_munmap(tdb); + if (ftruncate(tdb->fd, recovery_eof) != 0) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to reduce to recovery size\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + tdb->map_size = recovery_eof; + tdb_mmap(tdb); + + if (transaction_sync(tdb, 0, recovery_eof) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to sync2 recovery\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + TDB_LOG((tdb, 0, "tdb_transaction_recover: recovered %d byte database\n", + recovery_eof)); + + /* all done */ + return 0; +} diff --git a/source/tdb/traverse.c b/source/tdb/traverse.c new file mode 100644 index 00000000000..d070e0a7662 --- /dev/null +++ b/source/tdb/traverse.c @@ -0,0 +1,334 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tdb_private.h" + +/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */ +static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tlock, + struct list_struct *rec) +{ + int want_next = (tlock->off != 0); + + /* Lock each chain from the start one. */ + for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { + if (!tlock->off && tlock->hash != 0) { + /* this is an optimisation for the common case where + the hash chain is empty, which is particularly + common for the use of tdb with ldb, where large + hashes are used. In that case we spend most of our + time in tdb_brlock(), locking empty hash chains. + + To avoid this, we do an unlocked pre-check to see + if the hash chain is empty before starting to look + inside it. If it is empty then we can avoid that + hash chain. If it isn't empty then we can't believe + the value we get back, as we read it without a + lock, so instead we get the lock and re-fetch the + value below. + + Notice that not doing this optimisation on the + first hash chain is critical. We must guarantee + that we have done at least one fcntl lock at the + start of a search to guarantee that memory is + coherent on SMP systems. If records are added by + others during the search then thats OK, and we + could possibly miss those with this trick, but we + could miss them anyway without this trick, so the + semantics don't change. + + With a non-indexed ldb search this trick gains us a + factor of around 80 in speed on a linux 2.6.x + system (testing using ldbtest). + */ + tdb->methods->next_hash_chain(tdb, &tlock->hash); + if (tlock->hash == tdb->header.hash_size) { + continue; + } + } + + if (tdb_lock(tdb, tlock->hash, tlock->lock_rw) == -1) + return -1; + + /* No previous record? Start at top of chain. */ + if (!tlock->off) { + if (tdb_ofs_read(tdb, TDB_HASH_TOP(tlock->hash), + &tlock->off) == -1) + goto fail; + } else { + /* Otherwise unlock the previous record. */ + if (tdb_unlock_record(tdb, tlock->off) != 0) + goto fail; + } + + if (want_next) { + /* We have offset of old record: grab next */ + if (tdb_rec_read(tdb, tlock->off, rec) == -1) + goto fail; + tlock->off = rec->next; + } + + /* Iterate through chain */ + while( tlock->off) { + tdb_off_t current; + if (tdb_rec_read(tdb, tlock->off, rec) == -1) + goto fail; + + /* Detect infinite loops. From "Shlomi Yaakobovich" <Shlomi@exanet.com>. */ + if (tlock->off == rec->next) { + TDB_LOG((tdb, 0, "tdb_next_lock: loop detected.\n")); + goto fail; + } + + if (!TDB_DEAD(rec)) { + /* Woohoo: we found one! */ + if (tdb_lock_record(tdb, tlock->off) != 0) + goto fail; + return tlock->off; + } + + /* Try to clean dead ones from old traverses */ + current = tlock->off; + tlock->off = rec->next; + if (!(tdb->read_only || tdb->traverse_read) && + tdb_do_delete(tdb, current, rec) != 0) + goto fail; + } + tdb_unlock(tdb, tlock->hash, tlock->lock_rw); + want_next = 0; + } + /* We finished iteration without finding anything */ + return TDB_ERRCODE(TDB_SUCCESS, 0); + + fail: + tlock->off = 0; + if (tdb_unlock(tdb, tlock->hash, tlock->lock_rw) != 0) + TDB_LOG((tdb, 0, "tdb_next_lock: On error unlock failed!\n")); + return -1; +} + +/* traverse the entire database - calling fn(tdb, key, data) on each element. + return -1 on error or the record count traversed + if fn is NULL then it is not called + a non-zero return value from fn() indicates that the traversal should stop + */ +static int tdb_traverse_internal(struct tdb_context *tdb, + tdb_traverse_func fn, void *private_data, + struct tdb_traverse_lock *tl) +{ + TDB_DATA key, dbuf; + struct list_struct rec; + int ret, count = 0; + + /* This was in the initializaton, above, but the IRIX compiler + * did not like it. crh + */ + tl->next = tdb->travlocks.next; + + /* fcntl locks don't stack: beware traverse inside traverse */ + tdb->travlocks.next = tl; + + /* tdb_next_lock places locks on the record returned, and its chain */ + while ((ret = tdb_next_lock(tdb, tl, &rec)) > 0) { + count++; + /* now read the full record */ + key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec), + rec.key_len + rec.data_len); + if (!key.dptr) { + ret = -1; + if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) + goto out; + if (tdb_unlock_record(tdb, tl->off) != 0) + TDB_LOG((tdb, 0, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); + goto out; + } + key.dsize = rec.key_len; + dbuf.dptr = key.dptr + rec.key_len; + dbuf.dsize = rec.data_len; + + /* Drop chain lock, call out */ + if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) { + ret = -1; + SAFE_FREE(key.dptr); + goto out; + } + if (fn && fn(tdb, key, dbuf, private_data)) { + /* They want us to terminate traversal */ + ret = count; + if (tdb_unlock_record(tdb, tl->off) != 0) { + TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));; + ret = -1; + } + SAFE_FREE(key.dptr); + goto out; + } + SAFE_FREE(key.dptr); + } +out: + tdb->travlocks.next = tl->next; + if (ret < 0) + return -1; + else + return count; +} + + +/* + a write style traverse - temporarily marks the db read only +*/ +int tdb_traverse_read(struct tdb_context *tdb, + tdb_traverse_func fn, void *private_data) +{ + struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK }; + int ret; + + /* we need to get a read lock on the transaction lock here to + cope with the lock ordering semantics of solaris10 */ + if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_RDLCK, F_SETLKW, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_traverse_read: failed to get transaction lock\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + tdb->traverse_read++; + ret = tdb_traverse_internal(tdb, fn, private_data, &tl); + tdb->traverse_read--; + + tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0); + + return ret; +} + +/* + a write style traverse - needs to get the transaction lock to + prevent deadlocks +*/ +int tdb_traverse(struct tdb_context *tdb, + tdb_traverse_func fn, void *private_data) +{ + struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK }; + int ret; + + if (tdb->read_only || tdb->traverse_read) { + return tdb_traverse_read(tdb, fn, private_data); + } + + if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_traverse: failed to get transaction lock\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + ret = tdb_traverse_internal(tdb, fn, private_data, &tl); + + tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0); + + return ret; +} + + +/* find the first entry in the database and return its key */ +TDB_DATA tdb_firstkey(struct tdb_context *tdb) +{ + TDB_DATA key; + struct list_struct rec; + + /* release any old lock */ + if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) + return tdb_null; + tdb->travlocks.off = tdb->travlocks.hash = 0; + + if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0) + return tdb_null; + /* now read the key */ + key.dsize = rec.key_len; + key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); + if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_firstkey: error occurred while tdb_unlocking!\n")); + return key; +} + +/* find the next entry in the database, returning its key */ +TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey) +{ + u32 oldhash; + TDB_DATA key = tdb_null; + struct list_struct rec; + char *k = NULL; + + /* Is locked key the old key? If so, traverse will be reliable. */ + if (tdb->travlocks.off) { + if (tdb_lock(tdb,tdb->travlocks.hash,F_WRLCK)) + return tdb_null; + if (tdb_rec_read(tdb, tdb->travlocks.off, &rec) == -1 + || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec), + rec.key_len)) + || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) { + /* No, it wasn't: unlock it and start from scratch */ + if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) { + SAFE_FREE(k); + return tdb_null; + } + if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) { + SAFE_FREE(k); + return tdb_null; + } + tdb->travlocks.off = 0; + } + + SAFE_FREE(k); + } + + if (!tdb->travlocks.off) { + /* No previous element: do normal find, and lock record */ + tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), F_WRLCK, &rec); + if (!tdb->travlocks.off) + return tdb_null; + tdb->travlocks.hash = BUCKET(rec.full_hash); + if (tdb_lock_record(tdb, tdb->travlocks.off) != 0) { + TDB_LOG((tdb, 0, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); + return tdb_null; + } + } + oldhash = tdb->travlocks.hash; + + /* Grab next record: locks chain and returned record, + unlocks old record */ + if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) { + key.dsize = rec.key_len; + key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec), + key.dsize); + /* Unlock the chain of this new record */ + if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + } + /* Unlock the chain of old record */ + if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + return key; +} + diff --git a/source/torture/cmd_vfs.c b/source/torture/cmd_vfs.c index cc683977e8c..6cecd693f83 100644 --- a/source/torture/cmd_vfs.c +++ b/source/torture/cmd_vfs.c @@ -94,7 +94,7 @@ static NTSTATUS cmd_show_data(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int ar static NTSTATUS cmd_connect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { - SMB_VFS_CONNECT(vfs->conn, lp_servicename(vfs->conn->service), "vfstest"); + SMB_VFS_CONNECT(vfs->conn, lp_servicename(SNUM(vfs->conn)), "vfstest"); return NT_STATUS_OK; } @@ -200,9 +200,10 @@ static NTSTATUS cmd_closedir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int arg static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { - int flags, fd; + int flags; mode_t mode; const char *flagstr; + files_struct *fsp; mode = 00400; @@ -278,18 +279,21 @@ static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c } } - fd = SMB_VFS_OPEN(vfs->conn, argv[1], flags, mode); - if (fd == -1) { + fsp = SMB_MALLOC_P(struct files_struct); + fsp->fsp_name = SMB_STRDUP(argv[1]); + fsp->fh = SMB_MALLOC_P(struct fd_handle); + fsp->conn = vfs->conn; + + fsp->fh->fd = SMB_VFS_OPEN(vfs->conn, argv[1], fsp, flags, mode); + if (fsp->fh->fd == -1) { printf("open: error=%d (%s)\n", errno, strerror(errno)); + SAFE_FREE(fsp->fh); + SAFE_FREE(fsp); return NT_STATUS_UNSUCCESSFUL; } - vfs->files[fd] = SMB_MALLOC_P(struct files_struct); - vfs->files[fd]->fsp_name = SMB_STRDUP(argv[1]); - vfs->files[fd]->fh = SMB_MALLOC_P(struct fd_handle); - vfs->files[fd]->fh->fd = fd; - vfs->files[fd]->conn = vfs->conn; - printf("open: fd=%d\n", fd); + vfs->files[fsp->fh->fd] = fsp; + printf("open: fd=%d\n", fsp->fh->fd); return NT_STATUS_OK; } diff --git a/source/torture/locktest.c b/source/torture/locktest.c index b946e48666e..3559a55a467 100644 --- a/source/torture/locktest.c +++ b/source/torture/locktest.c @@ -113,9 +113,13 @@ static struct record preset[] = { static struct record *recorded; -static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, - enum brl_type lock_type, - br_off start, br_off size) +static void print_brl(SMB_DEV_T dev, + SMB_INO_T ino, + struct process_id pid, + enum brl_type lock_type, + enum brl_flavour lock_flav, + br_off start, + br_off size) { #if NASTY_POSIX_LOCK_HACK { @@ -178,7 +182,7 @@ static struct cli_state *connect_one(char *share, int snum) zero_ip(&ip); /* have to open a new connection */ - if (!(c=cli_initialise(NULL)) || !cli_connect(c, server_n, &ip)) { + if (!(c=cli_initialise()) || !cli_connect(c, server_n, &ip)) { DEBUG(0,("Connection to %s failed\n", server_n)); return NULL; } diff --git a/source/torture/locktest2.c b/source/torture/locktest2.c index 519acebe8e8..5f2f2499acd 100644 --- a/source/torture/locktest2.c +++ b/source/torture/locktest2.c @@ -135,6 +135,7 @@ static BOOL try_unlock(struct cli_state *c, int fstype, static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, enum brl_type lock_type, + enum brl_flavour lock_flav, br_off start, br_off size) { printf("%6d %05x:%05x %s %.0f:%.0f(%.0f)\n", diff --git a/source/torture/masktest.c b/source/torture/masktest.c index ffc9a20e71c..44d26cdc5ad 100644 --- a/source/torture/masktest.c +++ b/source/torture/masktest.c @@ -184,7 +184,7 @@ struct cli_state *connect_one(char *share) zero_ip(&ip); /* have to open a new connection */ - if (!(c=cli_initialise(NULL)) || !cli_connect(c, server_n, &ip)) { + if (!(c=cli_initialise()) || !cli_connect(c, server_n, &ip)) { DEBUG(0,("Connection to %s failed\n", server_n)); return NULL; } diff --git a/source/torture/nsstest.c b/source/torture/nsstest.c index d2b17f0f635..7673f922090 100644 --- a/source/torture/nsstest.c +++ b/source/torture/nsstest.c @@ -62,7 +62,9 @@ static void report_nss_error(const char *who, NSS_STATUS status) static struct passwd *nss_getpwent(void) { NSS_STATUS (*_nss_getpwent_r)(struct passwd *, char *, - size_t , int *) = find_fn("getpwent_r"); + size_t , int *) = + (NSS_STATUS (*)(struct passwd *, char *, + size_t, int *))find_fn("getpwent_r"); static struct passwd pwd; static char buf[1000]; NSS_STATUS status; @@ -84,7 +86,9 @@ static struct passwd *nss_getpwent(void) static struct passwd *nss_getpwnam(const char *name) { NSS_STATUS (*_nss_getpwnam_r)(const char *, struct passwd *, char *, - size_t , int *) = find_fn("getpwnam_r"); + size_t , int *) = + (NSS_STATUS (*)(const char *, struct passwd *, char *, + size_t, int *))find_fn("getpwnam_r"); static struct passwd pwd; static char buf[1000]; NSS_STATUS status; @@ -106,7 +110,9 @@ static struct passwd *nss_getpwnam(const char *name) static struct passwd *nss_getpwuid(uid_t uid) { NSS_STATUS (*_nss_getpwuid_r)(uid_t , struct passwd *, char *, - size_t , int *) = find_fn("getpwuid_r"); + size_t , int *) = + (NSS_STATUS (*)(uid_t, struct passwd *, char *, + size_t, int *))find_fn("getpwuid_r"); static struct passwd pwd; static char buf[1000]; NSS_STATUS status; @@ -127,7 +133,8 @@ static struct passwd *nss_getpwuid(uid_t uid) static void nss_setpwent(void) { - NSS_STATUS (*_nss_setpwent)(void) = find_fn("setpwent"); + NSS_STATUS (*_nss_setpwent)(void) = + (NSS_STATUS(*)(void))find_fn("setpwent"); NSS_STATUS status; if (!_nss_setpwent) @@ -141,7 +148,8 @@ static void nss_setpwent(void) static void nss_endpwent(void) { - NSS_STATUS (*_nss_endpwent)(void) = find_fn("endpwent"); + NSS_STATUS (*_nss_endpwent)(void) = + (NSS_STATUS (*)(void))find_fn("endpwent"); NSS_STATUS status; if (!_nss_endpwent) @@ -157,7 +165,9 @@ static void nss_endpwent(void) static struct group *nss_getgrent(void) { NSS_STATUS (*_nss_getgrent_r)(struct group *, char *, - size_t , int *) = find_fn("getgrent_r"); + size_t , int *) = + (NSS_STATUS (*)(struct group *, char *, + size_t, int *))find_fn("getgrent_r"); static struct group grp; static char *buf; static int buflen = 1024; @@ -167,13 +177,13 @@ static struct group *nss_getgrent(void) return NULL; if (!buf) - buf = SMB_MALLOC(buflen); + buf = SMB_MALLOC_ARRAY(char, buflen); again: status = _nss_getgrent_r(&grp, buf, buflen, &nss_errno); if (status == NSS_STATUS_TRYAGAIN) { buflen *= 2; - buf = SMB_REALLOC(buf, buflen); + buf = SMB_REALLOC_ARRAY(buf, char, buflen); if (!buf) { return NULL; } @@ -192,7 +202,9 @@ again: static struct group *nss_getgrnam(const char *name) { NSS_STATUS (*_nss_getgrnam_r)(const char *, struct group *, char *, - size_t , int *) = find_fn("getgrnam_r"); + size_t , int *) = + (NSS_STATUS (*)(const char *, struct group *, char *, + size_t, int *))find_fn("getgrnam_r"); static struct group grp; static char *buf; static int buflen = 1000; @@ -202,12 +214,12 @@ static struct group *nss_getgrnam(const char *name) return NULL; if (!buf) - buf = SMB_MALLOC(buflen); + buf = SMB_MALLOC_ARRAY(char, buflen); again: status = _nss_getgrnam_r(name, &grp, buf, buflen, &nss_errno); if (status == NSS_STATUS_TRYAGAIN) { buflen *= 2; - buf = SMB_REALLOC(buf, buflen); + buf = SMB_REALLOC_ARRAY(buf, char, buflen); if (!buf) { return NULL; } @@ -226,7 +238,9 @@ again: static struct group *nss_getgrgid(gid_t gid) { NSS_STATUS (*_nss_getgrgid_r)(gid_t , struct group *, char *, - size_t , int *) = find_fn("getgrgid_r"); + size_t , int *) = + (NSS_STATUS (*)(gid_t, struct group *, char *, + size_t, int *))find_fn("getgrgid_r"); static struct group grp; static char *buf; static int buflen = 1000; @@ -236,13 +250,13 @@ static struct group *nss_getgrgid(gid_t gid) return NULL; if (!buf) - buf = SMB_MALLOC(buflen); + buf = SMB_MALLOC_ARRAY(char, buflen); again: status = _nss_getgrgid_r(gid, &grp, buf, buflen, &nss_errno); if (status == NSS_STATUS_TRYAGAIN) { buflen *= 2; - buf = SMB_REALLOC(buf, buflen); + buf = SMB_REALLOC_ARRAY(buf, char, buflen); if (!buf) { return NULL; } @@ -260,7 +274,8 @@ again: static void nss_setgrent(void) { - NSS_STATUS (*_nss_setgrent)(void) = find_fn("setgrent"); + NSS_STATUS (*_nss_setgrent)(void) = + (NSS_STATUS (*)(void))find_fn("setgrent"); NSS_STATUS status; if (!_nss_setgrent) @@ -274,7 +289,8 @@ static void nss_setgrent(void) static void nss_endgrent(void) { - NSS_STATUS (*_nss_endgrent)(void) = find_fn("endgrent"); + NSS_STATUS (*_nss_endgrent)(void) = + (NSS_STATUS (*)(void))find_fn("endgrent"); NSS_STATUS status; if (!_nss_endgrent) @@ -290,7 +306,9 @@ static int nss_initgroups(char *user, gid_t group, gid_t **groups, long int *sta { NSS_STATUS (*_nss_initgroups)(char *, gid_t , long int *, long int *, gid_t **, long int , int *) = - find_fn("initgroups_dyn"); + (NSS_STATUS (*)(char *, gid_t, long int *, + long int *, gid_t **, + long int, int *))find_fn("initgroups_dyn"); NSS_STATUS status; if (!_nss_initgroups) diff --git a/source/torture/pdbtest.c b/source/torture/pdbtest.c new file mode 100644 index 00000000000..e1a35b79127 --- /dev/null +++ b/source/torture/pdbtest.c @@ -0,0 +1,392 @@ +/* + Unix SMB/CIFS implementation. + passdb testing utility + + Copyright (C) Wilco Baan Hofman 2006 + Copyright (C) Jelmer Vernooij 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include "includes.h" + +static BOOL samu_correct(struct samu *s1, struct samu *s2) +{ + BOOL ret = True; + uint32 s1_len, s2_len; + const char *s1_buf, *s2_buf; + const uint8 *d1_buf, *d2_buf; + + /* Check Unix username */ + s1_buf = pdb_get_username(s1); + s2_buf = pdb_get_username(s2); + if (s2_buf == NULL && s1_buf != NULL) { + DEBUG(0, ("Username is not set\n")); + ret = False; + } else if (s1_buf == NULL) { + /* Do nothing */ + } else if (strcmp(s1_buf,s2_buf)) { + DEBUG(0, ("Username not written correctly, want %s, got \"%s\"\n", + pdb_get_username(s1), + pdb_get_username(s2))); + ret = False; + } + + /* Check NT username */ + s1_buf = pdb_get_nt_username(s1); + s2_buf = pdb_get_nt_username(s2); + if (s2_buf == NULL && s1_buf != NULL) { + DEBUG(0, ("NT Username is not set\n")); + ret = False; + } else if (s1_buf == NULL) { + /* Do nothing */ + } else if (strcmp(s1_buf, s2_buf)) { + DEBUG(0, ("NT Username not written correctly, want \"%s\", got \"%s\"\n", + pdb_get_nt_username(s1), + pdb_get_nt_username(s2))); + ret = False; + } + + /* Check acct ctrl */ + if (pdb_get_acct_ctrl(s1) != pdb_get_acct_ctrl(s2)) { + DEBUG(0, ("Acct ctrl field not written correctly, want %d (0x%X), got %d (0x%X)\n", + pdb_get_acct_ctrl(s1), + pdb_get_acct_ctrl(s1), + pdb_get_acct_ctrl(s2), + pdb_get_acct_ctrl(s2))); + ret = False; + } + + /* Check NT password */ + d1_buf = pdb_get_nt_passwd(s1); + d2_buf = pdb_get_nt_passwd(s2); + if (d2_buf == NULL && d1_buf != NULL) { + DEBUG(0, ("NT password is not set\n")); + ret = False; + } else if (d1_buf == NULL) { + /* Do nothing */ + } else if (memcmp(d1_buf, d2_buf, NT_HASH_LEN)) { + DEBUG(0, ("NT password not written correctly\n")); + ret = False; + } + + /* Check lanman password */ + d1_buf = pdb_get_lanman_passwd(s1); + d2_buf = pdb_get_lanman_passwd(s2); + if (d2_buf == NULL && d1_buf != NULL) { + DEBUG(0, ("Lanman password is not set\n")); + } else if (d1_buf == NULL) { + /* Do nothing */ + } else if (memcmp(d1_buf, d2_buf, NT_HASH_LEN)) { + DEBUG(0, ("Lanman password not written correctly\n")); + ret = False; + } + + /* Check password history */ + d1_buf = pdb_get_pw_history(s1, &s1_len); + d2_buf = pdb_get_pw_history(s2, &s2_len); + if (d2_buf == NULL && d1_buf != NULL) { + DEBUG(0, ("Password history is not set\n")); + } else if (d1_buf == NULL) { + /* Do nothing */ + } else if (s1_len != s1_len) { + DEBUG(0, ("Password history not written correctly, lengths differ, want %d, got %d\n", + s1_len, s2_len)); + ret = False; + } else if (strncmp(s1_buf, s2_buf, s1_len)) { + DEBUG(0, ("Password history not written correctly\n")); + ret = False; + } + + /* Check logon time */ + if (pdb_get_logon_time(s1) != pdb_get_logon_time(s2)) { + DEBUG(0, ("Logon time is not written correctly\n")); + ret = False; + } + + /* Check logoff time */ + if (pdb_get_logoff_time(s1) != pdb_get_logoff_time(s2)) { + DEBUG(0, ("Logoff time is not written correctly\n")); + ret = False; + } + + /* Check kickoff time */ + if (pdb_get_kickoff_time(s1) != pdb_get_logoff_time(s2)) { + DEBUG(0, ("Kickoff time is not written correctly\n")); + ret = False; + } + + /* Check bad password time */ + if (pdb_get_bad_password_time(s1) != pdb_get_bad_password_time(s2)) { + DEBUG(0, ("Bad password time is not written correctly\n")); + ret = False; + } + + /* Check password last set time */ + if (pdb_get_pass_last_set_time(s1) != pdb_get_pass_last_set_time(s2)) { + DEBUG(0, ("Password last set time is not written correctly\n")); + ret = False; + } + + /* Check password can change time */ + if (pdb_get_pass_can_change_time(s1) != pdb_get_pass_can_change_time(s2)) { + DEBUG(0, ("Password can change time is not written correctly\n")); + ret = False; + } + + /* Check password must change time */ + if (pdb_get_pass_must_change_time(s1) != pdb_get_pass_must_change_time(s2)) { + DEBUG(0, ("Password must change time is not written correctly\n")); + ret = False; + } + + /* Check logon divs */ + if (pdb_get_logon_divs(s1) != pdb_get_logon_divs(s2)) { + DEBUG(0, ("Logon divs not written correctly\n")); + ret = False; + } + + /* Check logon hours */ + if (pdb_get_hours_len(s1) != pdb_get_hours_len(s2)) { + DEBUG(0, ("Logon hours length not written correctly\n")); + ret = False; + } else if (pdb_get_hours_len(s1) != 0) { + d1_buf = pdb_get_hours(s1); + d2_buf = pdb_get_hours(s2); + if (d2_buf == NULL && d2_buf != NULL) { + DEBUG(0, ("Logon hours is not set\n")); + ret = False; + } else if (d1_buf == NULL) { + /* Do nothing */ + } else if (memcmp(d1_buf, d2_buf, MAX_HOURS_LEN)) { + DEBUG(0, ("Logon hours is not written correctly\n")); + ret = False; + } + } + + /* Check profile path */ + s1_buf = pdb_get_profile_path(s1); + s2_buf = pdb_get_profile_path(s2); + if (s2_buf == NULL && s1_buf != NULL) { + DEBUG(0, ("Profile path is not set\n")); + ret = False; + } else if (s1_buf == NULL) { + /* Do nothing */ + } else if (strcmp(s1_buf, s2_buf)) { + DEBUG(0, ("Profile path is not written correctly\n")); + ret = False; + } + + /* Check home dir */ + s1_buf = pdb_get_homedir(s1); + s2_buf = pdb_get_homedir(s2); + if (s2_buf == NULL && s1_buf != NULL) { + DEBUG(0, ("Home dir is not set\n")); + ret = False; + } else if (s1_buf == NULL) { + /* Do nothing */ + } else if (strcmp(s1_buf, s2_buf)) { + DEBUG(0, ("Home dir is not written correctly\n")); + ret = False; + } + + /* Check logon script */ + s1_buf = pdb_get_logon_script(s1); + s2_buf = pdb_get_logon_script(s2); + if (s2_buf == NULL && s1_buf != NULL) { + DEBUG(0, ("Logon script not set\n")); + ret = False; + } else if (s1_buf == NULL) { + /* Do nothing */ + } else if (strcmp(s1_buf, s2_buf)) { + DEBUG(0, ("Logon script is not written correctly\n")); + ret = False; + } + + /* TODO Check user and group sids */ + + return ret; +} + + +int main(int argc, char **argv) +{ + TALLOC_CTX *ctx; + struct samu *out = NULL; + struct samu *in = NULL; + NTSTATUS rv; + int i; + struct timeval tv; + BOOL error = False; + struct passwd *pwd; + uint8 *buf; + uint32 expire, min_age, history; + struct pdb_methods *pdb; + poptContext pc; + static char *backend = NULL; + static const char *unix_user = "nobody"; + struct poptOption long_options[] = { + {"username", 'u', POPT_ARG_STRING, &unix_user, 0, "Unix user to use for testing", "USERNAME" }, + {"backend", 'b', POPT_ARG_STRING, &backend, 0, "Backend to use if not default", "BACKEND[:SETTINGS]" }, + POPT_AUTOHELP + POPT_COMMON_SAMBA + POPT_TABLEEND + }; + + load_case_tables(); + + pc = poptGetContext("vfstest", argc, (const char **) argv, + long_options, 0); + + poptSetOtherOptionHelp(pc, "backend[:settings] username"); + + while(poptGetNextOpt(pc) != -1); + + poptFreeContext(pc); + + /* Load configuration */ + lp_load(dyn_CONFIGFILE, False, False, True, True); + setup_logging("pdbtest", True); + + if (backend == NULL) { + backend = lp_passdb_backend(); + } + + rv = make_pdb_method_name(&pdb, backend); + if (NT_STATUS_IS_ERR(rv)) { + fprintf(stderr, "Error initializing '%s': %s\n", backend, get_friendly_nt_error_msg(rv)); + exit(1); + } + + ctx = talloc_init("PDBTEST"); + + if (!(out = samu_new(ctx))) { + fprintf(stderr, "Can't create samu structure.\n"); + exit(1); + } + + if ((pwd = getpwnam_alloc(ctx, unix_user)) == NULL) { + fprintf(stderr, "Error getting user information for %s\n", unix_user); + exit(1); + } + + samu_set_unix(out, pwd); + + pdb_set_profile_path(out, "\\\\torture\\profile", PDB_SET); + pdb_set_homedir(out, "\\\\torture\\home", PDB_SET); + pdb_set_logon_script(out, "torture_script.cmd", PDB_SET); + + pdb_get_account_policy(AP_PASSWORD_HISTORY, &history); + if (history * PW_HISTORY_ENTRY_LEN < NT_HASH_LEN) { + buf = TALLOC(ctx, NT_HASH_LEN); + } else { + buf = TALLOC(ctx, history * PW_HISTORY_ENTRY_LEN); + } + + /* Generate some random hashes */ + GetTimeOfDay(&tv); + srand(tv.tv_usec); + for (i = 0; i < NT_HASH_LEN; i++) { + buf[i] = (uint8) rand(); + } + pdb_set_nt_passwd(out, buf, PDB_SET); + for (i = 0; i < LM_HASH_LEN; i++) { + buf[i] = (uint8) rand(); + } + pdb_set_lanman_passwd(out, buf, PDB_SET); + for (i = 0; i < history * PW_HISTORY_ENTRY_LEN; i++) { + buf[i] = (uint8) rand(); + } + pdb_set_pw_history(out, buf, history, PDB_SET); + + pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire); + pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age); + pdb_set_pass_last_set_time(out, time(NULL), PDB_SET); + + if (expire == 0 || expire == (uint32)-1) { + pdb_set_pass_must_change_time(out, get_time_t_max(), PDB_SET); + } else { + pdb_set_pass_must_change_time(out, time(NULL)+expire, PDB_SET); + } + + if (min_age == (uint32)-1) { + pdb_set_pass_can_change_time(out, 0, PDB_SET); + } else { + pdb_set_pass_can_change_time(out, time(NULL)+min_age, PDB_SET); + } + + /* Create account */ + if (!NT_STATUS_IS_OK(rv = pdb->add_sam_account(pdb, out))) { + fprintf(stderr, "Error in add_sam_account: %s\n", + get_friendly_nt_error_msg(rv)); + exit(1); + } + + if (!(in = samu_new(ctx))) { + fprintf(stderr, "Can't create samu structure.\n"); + exit(1); + } + + /* Get account information through getsampwnam() */ + if (NT_STATUS_IS_ERR(pdb->getsampwnam(pdb, in, out->username))) { + fprintf(stderr, "Error getting sampw of added user %s.\n", + out->username); + if (!NT_STATUS_IS_OK(rv = pdb->delete_sam_account(pdb, out))) { + fprintf(stderr, "Error in delete_sam_account %s\n", + get_friendly_nt_error_msg(rv)); + } + TALLOC_FREE(ctx); + } + + /* Verify integrity */ + if (samu_correct(out, in)) { + printf("User info written correctly\n"); + } else { + printf("User info NOT written correctly\n"); + error = True; + } + + /* Delete account */ + if (!NT_STATUS_IS_OK(rv = pdb->delete_sam_account(pdb, out))) { + fprintf(stderr, "Error in delete_sam_account %s\n", + get_friendly_nt_error_msg(rv)); + } + + pdb->setsampwent(pdb, False, 0); + while (NT_STATUS_IS_OK(pdb->getsampwent(pdb, out))) { + if (pdb_get_username(out) == NULL) { + fprintf(stderr, "Got bad username through getsampwent()\n"); + error = True; + break; + } + if (NT_STATUS_IS_ERR(pdb->getsampwnam(pdb, in, pdb_get_username(out)))) { + fprintf(stderr, "Error getting samu through getsampwnam() of an account we got through getsampwent!\n"); + error = True; + continue; + } + if (!samu_correct(out, in)) { + printf("Record gotten through getsampwnam() differs from same record through getsampwent()\n"); + } + } + pdb->endsampwent(pdb); + + TALLOC_FREE(ctx); + + if (error) { + return 1; + } + return 0; +} diff --git a/source/torture/rpctorture.c b/source/torture/rpctorture.c index d69cc8eb8df..98f2dc105fa 100644 --- a/source/torture/rpctorture.c +++ b/source/torture/rpctorture.c @@ -493,7 +493,7 @@ enum client_action strupper_m(global_myname); fstrcpy(cli_info.myhostname, global_myname); - DEBUG(3,("%s client started (version %s)\n",timestring(False),SAMBA_VERSION_STRING)); + DEBUG(3,("%s client started (version %s)\n",current_timestring(False),SAMBA_VERSION_STRING)); if (*smb_cli->domain == 0) { diff --git a/source/torture/scanner.c b/source/torture/scanner.c index 1893be83699..1510cd70f4c 100644 --- a/source/torture/scanner.c +++ b/source/torture/scanner.c @@ -49,7 +49,7 @@ static NTSTATUS try_trans2(struct cli_state *cli, int op, char *param, char *data, int param_len, int data_len, - int *rparam_len, int *rdata_len) + unsigned int *rparam_len, unsigned int *rdata_len) { uint16 setup = op; char *rparam=NULL, *rdata=NULL; @@ -80,7 +80,7 @@ static NTSTATUS try_trans2_len(struct cli_state *cli, int op, int level, char *param, char *data, int param_len, int *data_len, - int *rparam_len, int *rdata_len) + unsigned int *rparam_len, unsigned int *rdata_len) { NTSTATUS ret=NT_STATUS_OK; @@ -115,7 +115,7 @@ static BOOL scan_trans2(struct cli_state *cli, int op, int level, { int data_len = 0; int param_len = 0; - int rparam_len, rdata_len; + unsigned int rparam_len, rdata_len; pstring param, data; NTSTATUS status; @@ -253,7 +253,7 @@ static NTSTATUS try_nttrans(struct cli_state *cli, int op, char *param, char *data, int param_len, int data_len, - int *rparam_len, int *rdata_len) + unsigned int *rparam_len, unsigned int *rdata_len) { char *rparam=NULL, *rdata=NULL; @@ -282,7 +282,7 @@ static NTSTATUS try_nttrans_len(struct cli_state *cli, int op, int level, char *param, char *data, int param_len, int *data_len, - int *rparam_len, int *rdata_len) + unsigned int *rparam_len, unsigned int *rdata_len) { NTSTATUS ret=NT_STATUS_OK; @@ -317,7 +317,7 @@ static BOOL scan_nttrans(struct cli_state *cli, int op, int level, { int data_len = 0; int param_len = 0; - int rparam_len, rdata_len; + unsigned int rparam_len, rdata_len; pstring param, data; NTSTATUS status; diff --git a/source/torture/torture.c b/source/torture/torture.c index 0b3bfc18f4a..25e249ed2e1 100644 --- a/source/torture/torture.c +++ b/source/torture/torture.c @@ -94,28 +94,27 @@ void *shm_setup(int size) } -static BOOL open_nbt_connection(struct cli_state *c) +static struct cli_state *open_nbt_connection(void) { struct nmb_name called, calling; struct in_addr ip; - - ZERO_STRUCTP(c); + struct cli_state *c; make_nmb_name(&calling, myname, 0x0); make_nmb_name(&called , host, 0x20); zero_ip(&ip); - if (!cli_initialise(c)) { + if (!(c = cli_initialise())) { printf("Failed initialize cli_struct to connect with %s\n", host); - return False; + return NULL; } c->port = port_to_use; if (!cli_connect(c, host, &ip)) { printf("Failed to connect with %s\n", host); - return False; + return NULL; } c->use_kerberos = use_kerberos; @@ -131,7 +130,7 @@ static BOOL open_nbt_connection(struct cli_state *c) */ if (!cli_connect(c, host, &ip)) { printf("Failed to connect with %s\n", host); - return False; + return NULL; } make_nmb_name(&called, "*SMBSERVER", 0x20); @@ -140,11 +139,11 @@ static BOOL open_nbt_connection(struct cli_state *c) printf("We tried with a called name of %s & %s\n", host, "*SMBSERVER"); cli_shutdown(c); - return False; + return NULL; } } - return True; + return c; } BOOL torture_open_connection(struct cli_state **c) @@ -462,8 +461,8 @@ static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2) int fnum1; int fnum2; int i; - uchar buf[131072]; - uchar buf_rd[131072]; + char buf[131072]; + char buf_rd[131072]; BOOL correct = True; ssize_t bytes_read; @@ -494,7 +493,7 @@ static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2) printf("%d\r", i); fflush(stdout); } - generate_random_buffer(buf, buf_size); + generate_random_buffer((unsigned char *)buf, buf_size); if (cli_write(c1, fnum1, 0, buf, 0, buf_size) != buf_size) { printf("write failed (%s)\n", cli_errstr(c1)); @@ -2174,20 +2173,20 @@ static void rand_buf(char *buf, int len) static BOOL run_negprot_nowait(int dummy) { int i; - static struct cli_state cli; + static struct cli_state *cli; BOOL correct = True; printf("starting negprot nowait test\n"); - if (!open_nbt_connection(&cli)) { + if (!(cli = open_nbt_connection())) { return False; } for (i=0;i<50000;i++) { - cli_negprot_send(&cli); + cli_negprot_send(cli); } - if (!torture_close_connection(&cli)) { + if (!torture_close_connection(cli)) { correct = False; } @@ -2202,7 +2201,7 @@ static BOOL run_randomipc(int dummy) { char *rparam = NULL; char *rdata = NULL; - int rdrcnt,rprcnt; + unsigned int rdrcnt,rprcnt; pstring param; int api, param_len, i; struct cli_state *cli; @@ -4418,7 +4417,8 @@ static BOOL run_eatest(int dummy) for (i = 0; i < num_eas; i++) { printf("%d: ea_name = %s. Val = ", i, ea_list[i].name); - dump_data(0, ea_list[i].value.data, ea_list[i].value.length); + dump_data(0, (char *)ea_list[i].value.data, + ea_list[i].value.length); } /* Setting EA's to zero length deletes them. Test this */ @@ -4445,7 +4445,8 @@ static BOOL run_eatest(int dummy) printf("num_eas = %d\n", num_eas); for (i = 0; i < num_eas; i++) { printf("%d: ea_name = %s. Val = ", i, ea_list[i].name); - dump_data(0, ea_list[i].value.data, ea_list[i].value.length); + dump_data(0, (char *)ea_list[i].value.data, + ea_list[i].value.length); } if (num_eas != 0) { @@ -4550,8 +4551,8 @@ static BOOL run_dirtest1(int dummy) static BOOL run_error_map_extract(int dummy) { - static struct cli_state c_dos; - static struct cli_state c_nt; + static struct cli_state *c_dos; + static struct cli_state *c_nt; uint32 error; @@ -4564,81 +4565,81 @@ static BOOL run_error_map_extract(int dummy) { /* NT-Error connection */ - if (!open_nbt_connection(&c_nt)) { + if (!(c_nt = open_nbt_connection())) { return False; } - c_nt.use_spnego = False; + c_nt->use_spnego = False; - if (!cli_negprot(&c_nt)) { - printf("%s rejected the NT-error negprot (%s)\n",host, cli_errstr(&c_nt)); - cli_shutdown(&c_nt); + if (!cli_negprot(c_nt)) { + printf("%s rejected the NT-error negprot (%s)\n",host, cli_errstr(c_nt)); + cli_shutdown(c_nt); return False; } - if (!cli_session_setup(&c_nt, "", "", 0, "", 0, + if (!cli_session_setup(c_nt, "", "", 0, "", 0, workgroup)) { - printf("%s rejected the NT-error initial session setup (%s)\n",host, cli_errstr(&c_nt)); + printf("%s rejected the NT-error initial session setup (%s)\n",host, cli_errstr(c_nt)); return False; } /* DOS-Error connection */ - if (!open_nbt_connection(&c_dos)) { + if (!(c_dos = open_nbt_connection())) { return False; } - c_dos.use_spnego = False; - c_dos.force_dos_errors = True; + c_dos->use_spnego = False; + c_dos->force_dos_errors = True; - if (!cli_negprot(&c_dos)) { - printf("%s rejected the DOS-error negprot (%s)\n",host, cli_errstr(&c_dos)); - cli_shutdown(&c_dos); + if (!cli_negprot(c_dos)) { + printf("%s rejected the DOS-error negprot (%s)\n",host, cli_errstr(c_dos)); + cli_shutdown(c_dos); return False; } - if (!cli_session_setup(&c_dos, "", "", 0, "", 0, + if (!cli_session_setup(c_dos, "", "", 0, "", 0, workgroup)) { - printf("%s rejected the DOS-error initial session setup (%s)\n",host, cli_errstr(&c_dos)); + printf("%s rejected the DOS-error initial session setup (%s)\n",host, cli_errstr(c_dos)); return False; } for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) { fstr_sprintf(user, "%X", error); - if (cli_session_setup(&c_nt, user, + if (cli_session_setup(c_nt, user, password, strlen(password), password, strlen(password), workgroup)) { printf("/** Session setup succeeded. This shouldn't happen...*/\n"); } - flgs2 = SVAL(c_nt.inbuf,smb_flg2); + flgs2 = SVAL(c_nt->inbuf,smb_flg2); /* Case #1: 32-bit NT errors */ if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) { - nt_status = NT_STATUS(IVAL(c_nt.inbuf,smb_rcls)); + nt_status = NT_STATUS(IVAL(c_nt->inbuf,smb_rcls)); } else { printf("/** Dos error on NT connection! (%s) */\n", - cli_errstr(&c_nt)); + cli_errstr(c_nt)); nt_status = NT_STATUS(0xc0000000); } - if (cli_session_setup(&c_dos, user, + if (cli_session_setup(c_dos, user, password, strlen(password), password, strlen(password), workgroup)) { printf("/** Session setup succeeded. This shouldn't happen...*/\n"); } - flgs2 = SVAL(c_dos.inbuf,smb_flg2), errnum; + flgs2 = SVAL(c_dos->inbuf,smb_flg2), errnum; /* Case #1: 32-bit NT errors */ if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) { printf("/** NT error on DOS connection! (%s) */\n", - cli_errstr(&c_nt)); + cli_errstr(c_nt)); errnum = errclass = 0; } else { - cli_dos_error(&c_dos, &errclass, &errnum); + cli_dos_error(c_dos, &errclass, &errnum); } if (NT_STATUS_V(nt_status) != error) { @@ -4655,6 +4656,42 @@ static BOOL run_error_map_extract(int dummy) { return True; } +static BOOL run_local_substitute(int dummy) +{ + TALLOC_CTX *mem_ctx; + int diff = 0; + + if ((mem_ctx = talloc_init("run_local_subst")) == NULL) { + printf("talloc_init failed\n"); + return False; + } + + diff |= strcmp(talloc_sub_specified(mem_ctx, "%U", "bla", "", -1, -1), + "bla"); + diff |= strcmp(talloc_sub_specified(mem_ctx, "%u%U", "bla", "", -1, -1), + "blabla"); + diff |= strcmp(talloc_sub_specified(mem_ctx, "%g", "", "", -1, -1), + "NO_GROUP"); + diff |= strcmp(talloc_sub_specified(mem_ctx, "%G", "", "", -1, -1), + "NO_GROUP"); + diff |= strcmp(talloc_sub_specified(mem_ctx, "%g", "", "", -1, 0), + gidtoname(0)); + diff |= strcmp(talloc_sub_specified(mem_ctx, "%G", "", "", -1, 0), + gidtoname(0)); + diff |= strcmp(talloc_sub_specified(mem_ctx, "%D%u", "u", "dom", -1, 0), + "domu"); + diff |= strcmp(talloc_sub_specified(mem_ctx, "%i %I", "", "", -1, -1), + "0.0.0.0 0.0.0.0"); + + /* Different captialization rules in sub_basic... */ + + diff |= strcmp(talloc_sub_basic(mem_ctx, "BLA", "dom", "%U%D"), + "blaDOM"); + + TALLOC_FREE(mem_ctx); + return (diff == 0); +} + static double create_procs(BOOL (*fn)(int), BOOL *result) { int i, status; @@ -4805,6 +4842,7 @@ static struct { {"CHKPATH", torture_chkpath_test, 0}, {"FDSESS", run_fdsesstest, 0}, { "EATEST", run_eatest, 0}, + { "LOCAL-SUBSTITUTE", run_local_substitute, 0}, {NULL, NULL, 0}}; diff --git a/source/torture/vfstest.c b/source/torture/vfstest.c index 61bb4b0bf65..fa0545988e9 100644 --- a/source/torture/vfstest.c +++ b/source/torture/vfstest.c @@ -575,6 +575,6 @@ int main(int argc, char *argv[]) process_cmd(&vfs, line); } - free(vfs.conn); + conn_free(vfs.conn); return 0; } diff --git a/source/utils/debug2html.c b/source/utils/debug2html.c index bec4d81ae2b..6d1b2b25352 100644 --- a/source/utils/debug2html.c +++ b/source/utils/debug2html.c @@ -145,6 +145,8 @@ static void newblock( dbg_Token old, dbg_Token newtok ) case dbg_lineno: (void)printf( ")" ); break; + default: + break; } switch( newtok ) @@ -158,6 +160,8 @@ static void newblock( dbg_Token old, dbg_Token newtok ) case dbg_lineno: (void)printf( "(" ); break; + default: + break; } } /* newblock */ diff --git a/source/utils/net.c b/source/utils/net.c index bef2a0a83c2..8b4fb042fcf 100644 --- a/source/utils/net.c +++ b/source/utils/net.c @@ -77,6 +77,7 @@ const char *opt_target_workgroup = NULL; int opt_machine_pass = 0; BOOL opt_localgroup = False; BOOL opt_domaingroup = False; +static BOOL do_talloc_report=False; const char *opt_newntname = ""; int opt_rid = 0; int opt_acls = 0; @@ -513,7 +514,7 @@ static int net_changesecretpw(int argc, const char **argv) set_line_buffering(stdout); set_line_buffering(stderr); } - + trust_pw = get_pass("Enter machine password: ", opt_stdin); if (!secrets_store_machine_password(trust_pw, lp_workgroup(), sec_channel_type)) { @@ -884,6 +885,7 @@ static struct functable net_func[] = { {"timestamps", 0, POPT_ARG_NONE, &opt_timestamps}, {"exclude", 'e', POPT_ARG_STRING, &opt_exclude}, {"destination", 0, POPT_ARG_STRING, &opt_destination}, + {"tallocreport", 0, POPT_ARG_NONE, &do_talloc_report}, POPT_COMMON_SAMBA { 0, 0, 0, 0} @@ -947,6 +949,10 @@ static struct functable net_func[] = { } } + if (do_talloc_report) { + talloc_enable_leak_report(); + } + if (opt_requester_name) { set_global_myname(opt_requester_name); } diff --git a/source/utils/net_ads.c b/source/utils/net_ads.c index 9d122a466bb..bfbc80759aa 100644 --- a/source/utils/net_ads.c +++ b/source/utils/net_ads.c @@ -506,7 +506,8 @@ static int ads_user_info(int argc, const char **argv) return -1; } - grouplist = ldap_get_values(ads->ld, res, "memberOf"); + grouplist = ldap_get_values((LDAP *)ads->ld, + (LDAPMessage *)res, "memberOf"); if (grouplist) { int i; @@ -591,7 +592,7 @@ int net_ads_user(int argc, const char **argv) shortattrs, usergrp_display, disp_fields); ads_destroy(&ads); - return 0; + return ADS_ERR_OK(rc) ? 0 : -1; } return net_run_function(argc, argv, func, net_ads_user_usage); @@ -716,7 +717,7 @@ int net_ads_group(int argc, const char **argv) disp_fields); ads_destroy(&ads); - return 0; + return ADS_ERR_OK(rc) ? 0 : -1; } return net_run_function(argc, argv, func, net_ads_group_usage); } @@ -1011,7 +1012,7 @@ static ADS_STATUS net_precreate_machine_acct( ADS_STRUCT *ads, const char *ou ) asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path); free(ou_str); - rc = ads_search_dn(ads, (void**)&res, dn, NULL); + rc = ads_search_dn(ads, &res, dn, NULL); ads_msgfree(ads, res); if (ADS_ERR_OK(rc)) { @@ -1340,7 +1341,7 @@ static int net_ads_printer_publish(int argc, const char **argv) return -1; } - srv_dn = ldap_get_dn(ads->ld, res); + srv_dn = ldap_get_dn((LDAP *)ads->ld, (LDAPMessage *)res); srv_cn = ldap_explode_dn(srv_dn, 1); asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn); diff --git a/source/utils/net_idmap.c b/source/utils/net_idmap.c index 47e1f93b69f..87da952247a 100644 --- a/source/utils/net_idmap.c +++ b/source/utils/net_idmap.c @@ -185,6 +185,7 @@ static NTSTATUS net_idmap_fixup_hwm(void) /*********************************************************** Write entries from stdin to current local idmap **********************************************************/ + static int net_idmap_restore(int argc, const char **argv) { if (!idmap_init(lp_idmap_backend())) { @@ -193,10 +194,11 @@ static int net_idmap_restore(int argc, const char **argv) } while (!feof(stdin)) { - fstring line, sid_string, fmt_string; + fstring line, sid_string, fmt_string1, fmt_string2; int len; unid_t id; - int type = ID_EMPTY; + enum idmap_type type; + unsigned long idval; DOM_SID sid; if (fgets(line, sizeof(line)-1, stdin) == NULL) @@ -207,20 +209,16 @@ static int net_idmap_restore(int argc, const char **argv) if ( (len > 0) && (line[len-1] == '\n') ) line[len-1] = '\0'; - /* Yuck - this is broken for sizeof(gid_t) != sizeof(int) */ - snprintf(fmt_string, sizeof(fmt_string), "GID %%d %%%us", FSTRING_LEN); - if (sscanf(line, fmt_string, &id.gid, sid_string) == 2) { - type = ID_GROUPID; - } - - /* Yuck - this is broken for sizeof(uid_t) != sizeof(int) */ + snprintf(fmt_string1, sizeof(fmt_string1), "GID %%ul %%%us", FSTRING_LEN); + snprintf(fmt_string2, sizeof(fmt_string2), "UID %%ul %%%us", FSTRING_LEN); - snprintf(fmt_string, sizeof(fmt_string), "UID %%d %%%us", FSTRING_LEN); - if (sscanf(line, fmt_string, &id.uid, sid_string) == 2) { + if (sscanf(line, fmt_string1, &idval, sid_string) == 2) { + type = ID_GROUPID; + id.gid = (gid_t)idval; + } else if (sscanf(line, fmt_string2, &idval, sid_string) == 2) { type = ID_USERID; - } - - if (type == ID_EMPTY) { + id.uid = (uid_t)idval; + } else { d_printf("ignoring invalid line [%s]\n", line); continue; } diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c index f32348935fc..f2cd4adb176 100644 --- a/source/utils/net_rpc.c +++ b/source/utils/net_rpc.c @@ -4934,12 +4934,12 @@ static int rpc_file_close(int argc, const char **argv) * @param str3 strings for FILE_INFO_3 **/ -static void display_file_info_3(FILE_INFO_3 *info3, FILE_INFO_3_STR *str3) +static void display_file_info_3( FILE_INFO_3 *info3 ) { fstring user = "", path = ""; - rpcstr_pull_unistr2_fstring(user, &str3->uni_user_name); - rpcstr_pull_unistr2_fstring(path, &str3->uni_path_name); + rpcstr_pull_unistr2_fstring(user, info3->user); + rpcstr_pull_unistr2_fstring(path, info3->path); d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n", info3->id, user, info3->perms, info3->num_locks, path); @@ -4994,8 +4994,7 @@ static NTSTATUS rpc_file_list_internals(const DOM_SID *domain_sid, "\nFileId Opened by Perms Locks Path"\ "\n------ --------- ----- ----- ---- \n"); for (i = 0; i < ctr.num_entries; i++) - display_file_info_3(&ctr.file.info3[i].info_3, - &ctr.file.info3[i].info_3_str); + display_file_info_3(&ctr.file.info3[i]); done: return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } @@ -6269,7 +6268,7 @@ static int rpc_trustdom(int argc, const char **argv) */ BOOL net_rpc_check(unsigned flags) { - struct cli_state cli; + struct cli_state *cli; BOOL ret = False; struct in_addr server_ip; char *server_name = NULL; @@ -6278,23 +6277,23 @@ BOOL net_rpc_check(unsigned flags) if (!net_find_server(NULL, flags, &server_ip, &server_name)) return False; - ZERO_STRUCT(cli); - if (cli_initialise(&cli) == False) + if ((cli = cli_initialise()) == NULL) { return False; + } - if (!cli_connect(&cli, server_name, &server_ip)) + if (!cli_connect(cli, server_name, &server_ip)) goto done; if (!attempt_netbios_session_request(&cli, global_myname(), server_name, &server_ip)) goto done; - if (!cli_negprot(&cli)) + if (!cli_negprot(cli)) goto done; - if (cli.protocol < PROTOCOL_NT1) + if (cli->protocol < PROTOCOL_NT1) goto done; ret = True; done: - cli_shutdown(&cli); + cli_shutdown(cli); return ret; } diff --git a/source/utils/net_rpc_printer.c b/source/utils/net_rpc_printer.c index 8808d549ac5..50ab50bace3 100644 --- a/source/utils/net_rpc_printer.c +++ b/source/utils/net_rpc_printer.c @@ -129,18 +129,23 @@ static void display_reg_value(const char *subkey, REGISTRY_VALUE value) break; case REG_MULTI_SZ: { - uint16 *curstr = (uint16 *) value.data_p; - uint8 *start = value.data_p; - d_printf("\t[%s:%s]: REG_MULTI_SZ:\n", subkey, value.valuename); - while ((*curstr != 0) && - ((uint8 *) curstr < start + value.size)) { - rpcstr_pull(text, curstr, sizeof(text), -1, - STR_TERMINATE); - d_printf("%s\n", text); - curstr += strlen(text) + 1; + int i, num_values; + char **values; + + if (!NT_STATUS_IS_OK(reg_pull_multi_sz(NULL, value.data_p, + value.size, + &num_values, + &values))) { + d_printf("reg_pull_multi_sz failed\n"); + break; + } + + for (i=0; i<num_values; i++) { + d_printf("%s\n", values[i]); } + TALLOC_FREE(values); + break; } - break; default: d_printf("\t%s: unknown type %d\n", value.valuename, value.type); diff --git a/source/utils/net_rpc_registry.c b/source/utils/net_rpc_registry.c index 873cb7b4597..3eaff901554 100644 --- a/source/utils/net_rpc_registry.c +++ b/source/utils/net_rpc_registry.c @@ -25,35 +25,6 @@ /******************************************************************** ********************************************************************/ -char* dump_regval_type( uint32 type ) -{ - static fstring string; - - switch (type) { - case REG_SZ: - fstrcpy( string, "REG_SZ" ); - break; - case REG_MULTI_SZ: - fstrcpy( string, "REG_MULTI_SZ" ); - break; - case REG_EXPAND_SZ: - fstrcpy( string, "REG_EXPAND_SZ" ); - break; - case REG_DWORD: - fstrcpy( string, "REG_DWORD" ); - break; - case REG_BINARY: - fstrcpy( string, "REG_BINARY" ); - break; - default: - fstr_sprintf( string, "UNKNOWN [%d]", type ); - } - - return string; -} -/******************************************************************** -********************************************************************/ - void dump_regval_buffer( uint32 type, REGVAL_BUFFER *buffer ) { pstring string; @@ -64,9 +35,26 @@ void dump_regval_buffer( uint32 type, REGVAL_BUFFER *buffer ) rpcstr_pull( string, buffer->buffer, sizeof(string), -1, STR_TERMINATE ); d_printf("%s\n", string); break; - case REG_MULTI_SZ: + case REG_MULTI_SZ: { + int i, num_values; + char **values; + d_printf("\n"); + + if (!NT_STATUS_IS_OK(reg_pull_multi_sz(NULL, buffer->buffer, + buffer->buf_len, + &num_values, + &values))) { + d_printf("reg_pull_multi_sz failed\n"); + break; + } + + for (i=0; i<num_values; i++) { + d_printf("%s\n", values[i]); + } + TALLOC_FREE(values); break; + } case REG_DWORD: value = IVAL( buffer->buffer, 0 ); d_printf( "0x%x\n", value ); @@ -113,16 +101,17 @@ static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid, result = rpccli_reg_connect(pipe_hnd, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive ); if ( !W_ERROR_IS_OK(result) ) { - d_fprintf(stderr, "Unable to connect to remote registry\n"); + d_fprintf(stderr, "Unable to connect to remote registry: " + "%s\n", dos_errstr(result)); return werror_to_ntstatus(result); } - if ( strlen( subpath ) != 0 ) { - result = rpccli_reg_open_entry(pipe_hnd, mem_ctx, &pol_hive, subpath, MAXIMUM_ALLOWED_ACCESS, &pol_key ); - if ( !W_ERROR_IS_OK(result) ) { - d_fprintf(stderr, "Unable to open [%s]\n", argv[0]); - return werror_to_ntstatus(result); - } + result = rpccli_reg_open_entry(pipe_hnd, mem_ctx, &pol_hive, subpath, + MAXIMUM_ALLOWED_ACCESS, &pol_key ); + if ( !W_ERROR_IS_OK(result) ) { + d_fprintf(stderr, "Unable to open [%s]: %s\n", argv[0], + dos_errstr(result)); + return werror_to_ntstatus(result); } /* get the subkeys */ @@ -173,7 +162,7 @@ static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid, } d_printf("Valuename = %s\n", name ); - d_printf("Type = %s\n", dump_regval_type(type) ); + d_printf("Type = %s\n", reg_type_lookup(type)); d_printf("Data = " ); dump_regval_buffer( type, &value ); d_printf("\n" ); @@ -279,7 +268,7 @@ static void dump_values( REGF_NK_REC *nk ) for ( i=0; i<nk->num_values; i++ ) { d_printf( "\"%s\" = ", nk->values[i].valuename ? nk->values[i].valuename : "(default)" ); - d_printf( "(%s) ", dump_regval_type( nk->values[i].type ) ); + d_printf( "(%s) ", reg_type_lookup( nk->values[i].type ) ); data_size = nk->values[i].data_size & ~VK_DATA_IN_OFFSET; switch ( nk->values[i].type ) { diff --git a/source/utils/net_rpc_samsync.c b/source/utils/net_rpc_samsync.c index 4f99c3035c8..861040533c6 100644 --- a/source/utils/net_rpc_samsync.c +++ b/source/utils/net_rpc_samsync.c @@ -42,7 +42,7 @@ static void display_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *g) d_printf("\n"); } -static const char *display_time(NTTIME *nttime) +static const char *display_time(const UINT64_S *nttime) { static fstring string; @@ -123,11 +123,19 @@ static void display_account_info(uint32 rid, SAM_ACCOUNT_INFO *a) pdb_encode_acct_ctrl(a->acb_info, NEW_PW_FORMAT_SPACE_PADDED_LEN)); } +static time_t uint64s_nt_time_to_unix_abs(const UINT64_S *src) +{ + NTTIME nttime; + nttime.high = src->high; + nttime.low = src->low; + return nt_time_to_unix_abs(&nttime); +} + static void display_domain_info(SAM_DOMAIN_INFO *a) { time_t u_logout; - u_logout = nt_time_to_unix_abs((NTTIME *)&a->force_logoff); + u_logout = uint64s_nt_time_to_unix_abs(&a->force_logoff); d_printf("Domain name: %s\n", unistr2_static(&a->uni_dom_name)); @@ -136,11 +144,11 @@ static void display_domain_info(SAM_DOMAIN_INFO *a) d_printf("Force Logoff: %d\n", (int)u_logout); - d_printf("Max Password Age: %s\n", display_time((NTTIME *)&a->max_pwd_age)); - d_printf("Min Password Age: %s\n", display_time((NTTIME *)&a->min_pwd_age)); + d_printf("Max Password Age: %s\n", display_time(&a->max_pwd_age)); + d_printf("Min Password Age: %s\n", display_time(&a->min_pwd_age)); - d_printf("Lockout Time: %s\n", display_time((NTTIME *)&a->account_lockout.lockout_duration)); - d_printf("Lockout Reset Time: %s\n", display_time((NTTIME *)&a->account_lockout.reset_count)); + d_printf("Lockout Time: %s\n", display_time(&a->account_lockout.lockout_duration)); + d_printf("Lockout Reset Time: %s\n", display_time(&a->account_lockout.reset_count)); d_printf("Bad Attempt Lockout: %d\n", a->account_lockout.bad_attempt_lockout); d_printf("User must logon to change password: %d\n", a->logon_chgpass); @@ -858,11 +866,11 @@ static NTSTATUS fetch_domain_info(uint32 rid, SAM_DOMAIN_INFO *delta) NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; pstring domname; - u_max_age = nt_time_to_unix_abs((NTTIME *)&delta->max_pwd_age); - u_min_age = nt_time_to_unix_abs((NTTIME *)&delta->min_pwd_age); - u_logout = nt_time_to_unix_abs((NTTIME *)&delta->force_logoff); - u_lockoutreset = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.reset_count); - u_lockouttime = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.lockout_duration); + u_max_age = uint64s_nt_time_to_unix_abs(&delta->max_pwd_age); + u_min_age = uint64s_nt_time_to_unix_abs(&delta->min_pwd_age); + u_logout = uint64s_nt_time_to_unix_abs(&delta->force_logoff); + u_lockoutreset = uint64s_nt_time_to_unix_abs(&delta->account_lockout.reset_count); + u_lockouttime = uint64s_nt_time_to_unix_abs(&delta->account_lockout.lockout_duration); unistr2_to_ascii(domname, &delta->uni_dom_name, sizeof(domname) - 1); diff --git a/source/utils/net_time.c b/source/utils/net_time.c index f6486286a65..f6269627dab 100644 --- a/source/utils/net_time.c +++ b/source/utils/net_time.c @@ -30,8 +30,10 @@ static time_t cli_servertime(const char *host, struct in_addr *ip, int *zone) time_t ret = 0; struct cli_state *cli = NULL; - cli = cli_initialise(NULL); - if (!cli) goto done; + cli = cli_initialise(); + if (!cli) { + goto done; + } if (!cli_connect(cli, host, ip)) { fprintf(stderr,"Can't contact server\n"); @@ -58,7 +60,9 @@ static time_t cli_servertime(const char *host, struct in_addr *ip, int *zone) if (zone) *zone = cli->serverzone; done: - if (cli) cli_shutdown(cli); + if (cli) { + cli_shutdown(cli); + } return ret; } diff --git a/source/utils/ntlm_auth.c b/source/utils/ntlm_auth.c index ef24f9f1611..fc9e3e9546a 100644 --- a/source/utils/ntlm_auth.c +++ b/source/utils/ntlm_auth.c @@ -515,7 +515,7 @@ static NTSTATUS ntlm_auth_start_ntlmssp_server(NTLMSSP_STATE **ntlmssp_state) NTSTATUS status = ntlmssp_server_start(ntlmssp_state); if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Could not start NTLMSSP client: %s\n", + DEBUG(1, ("Could not start NTLMSSP server: %s\n", nt_errstr(status))); return status; } diff --git a/source/utils/ntlm_auth_diagnostics.c b/source/utils/ntlm_auth_diagnostics.c index c8ea966a558..e69715affd0 100644 --- a/source/utils/ntlm_auth_diagnostics.c +++ b/source/utils/ntlm_auth_diagnostics.c @@ -445,6 +445,7 @@ static BOOL test_plaintext(enum ntlm_break break_which) DATA_BLOB nt_response = data_blob(NULL, 0); DATA_BLOB lm_response = data_blob(NULL, 0); char *password; + smb_ucs2_t *nt_response_ucs2; uchar user_session_key[16]; uchar lm_key[16]; @@ -457,12 +458,13 @@ static BOOL test_plaintext(enum ntlm_break break_which) flags |= WBFLAG_PAM_LMKEY; flags |= WBFLAG_PAM_USER_SESSION_KEY; - if ((push_ucs2_allocate((smb_ucs2_t **)&nt_response.data, opt_password)) == -1) { + if ((push_ucs2_allocate(&nt_response_ucs2, opt_password)) == -1) { DEBUG(0, ("push_ucs2_allocate failed!\n")); exit(1); } - nt_response.length = strlen_w(((void *)nt_response.data))*sizeof(smb_ucs2_t); + nt_response.data = (unsigned char *)nt_response_ucs2; + nt_response.length = strlen_w(nt_response_ucs2)*sizeof(smb_ucs2_t); if ((password = strdup_upper(opt_password)) == NULL) { DEBUG(0, ("strdup_upper failed!\n")); @@ -472,7 +474,7 @@ static BOOL test_plaintext(enum ntlm_break break_which) if ((convert_string_allocate(NULL, CH_UNIX, CH_DOS, password, strlen(password)+1, - (void**)&lm_response.data,True)) == -1) { + &lm_response.data,True)) == -1) { DEBUG(0, ("convert_string_allocate failed!\n")); exit(1); } diff --git a/source/utils/sharesec.c b/source/utils/sharesec.c new file mode 100644 index 00000000000..aa4210b51dc --- /dev/null +++ b/source/utils/sharesec.c @@ -0,0 +1,414 @@ +/* + * Unix SMB/Netbios implementation. + * Utility for managing share permissions + * + * Copyright (C) Tim Potter 2000 + * Copyright (C) Jeremy Allison 2000 + * Copyright (C) Jelmer Vernooij 2003 + * Copyright (C) Gerald (Jerry) Carter 2005. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "includes.h" + +#define CREATE_ACCESS_READ READ_CONTROL_ACCESS + +/* numeric is set when the user wants numeric SIDs and ACEs rather + than going via LSA calls to resolve them */ +static BOOL numeric = False; + +enum acl_mode {SMB_ACL_REMOVE, SMB_ACL_MODIFY, SMB_ACL_ADD, SMB_ACL_REPLACE, SMB_ACL_VIEW }; +enum exit_values {EXIT_OK, EXIT_FAILED, EXIT_PARSE_ERROR}; + +struct perm_value { + const char *perm; + uint32 mask; +}; + +/* These values discovered by inspection */ + +static const struct perm_value special_values[] = { + { "R", 0x00120089 }, + { "W", 0x00120116 }, + { "X", 0x001200a0 }, + { "D", 0x00010000 }, + { "P", 0x00040000 }, + { "O", 0x00080000 }, + { NULL, 0 }, +}; + +static const struct perm_value standard_values[] = { + { "READ", 0x001200a9 }, + { "CHANGE", 0x001301bf }, + { "FULL", 0x001f01ff }, + { NULL, 0 }, +}; + +/******************************************************************** + print an ACE on a FILE, using either numeric or ascii representation +********************************************************************/ + +static void print_ace(FILE *f, SEC_ACE *ace) +{ + const struct perm_value *v; + fstring sidstr; + int do_print = 0; + uint32 got_mask; + + sid_to_string(sidstr, &ace->trustee); + + fprintf(f, "%s:", sidstr); + + if (numeric) { + fprintf(f, "%d/%d/0x%08x", + ace->type, ace->flags, ace->info.mask); + return; + } + + /* Ace type */ + + if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) { + fprintf(f, "ALLOWED"); + } else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) { + fprintf(f, "DENIED"); + } else { + fprintf(f, "%d", ace->type); + } + + /* Not sure what flags can be set in a file ACL */ + + fprintf(f, "/%d/", ace->flags); + + /* Standard permissions */ + + for (v = standard_values; v->perm; v++) { + if (ace->info.mask == v->mask) { + fprintf(f, "%s", v->perm); + return; + } + } + + /* Special permissions. Print out a hex value if we have + leftover bits in the mask. */ + + got_mask = ace->info.mask; + + again: + for (v = special_values; v->perm; v++) { + if ((ace->info.mask & v->mask) == v->mask) { + if (do_print) { + fprintf(f, "%s", v->perm); + } + got_mask &= ~v->mask; + } + } + + if (!do_print) { + if (got_mask != 0) { + fprintf(f, "0x%08x", ace->info.mask); + } else { + do_print = 1; + goto again; + } + } +} + +/******************************************************************** + print a ascii version of a security descriptor on a FILE handle +********************************************************************/ + +static void sec_desc_print(FILE *f, SEC_DESC *sd) +{ + fstring sidstr; + uint32 i; + + fprintf(f, "REVISION:%d\n", sd->revision); + + /* Print owner and group sid */ + + if (sd->owner_sid) { + sid_to_string(sidstr, sd->owner_sid); + } else { + fstrcpy(sidstr, ""); + } + + fprintf(f, "OWNER:%s\n", sidstr); + + if (sd->grp_sid) { + sid_to_string(sidstr, sd->grp_sid); + } else { + fstrcpy(sidstr, ""); + } + + fprintf(f, "GROUP:%s\n", sidstr); + + /* Print aces */ + for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) { + SEC_ACE *ace = &sd->dacl->ace[i]; + fprintf(f, "ACL:"); + print_ace(f, ace); + fprintf(f, "\n"); + } + +} + +/******************************************************************** +********************************************************************/ + +static BOOL parse_ace( TALLOC_CTX *ctx, SEC_ACE *ace, char *entry ) +{ + SEC_ACCESS sa; + char *p = strchr_m( entry, ':' ); + DOM_SID sid; + uint32 mask; + + if ( !p ) + return False; + + *p = '\0'; + p++; + + string_to_sid( &sid, entry ); + + switch ( *p ) { + case 'F': + case 'f': + mask = GENERIC_RIGHTS_FILE_ALL_ACCESS|STD_RIGHT_ALL_ACCESS; + break; + + case 'R': + case 'r': + mask = GENERIC_RIGHTS_FILE_READ|GENERIC_RIGHTS_FILE_EXECUTE|\ + STANDARD_RIGHTS_READ_ACCESS|STANDARD_RIGHTS_EXECUTE_ACCESS; + break; + + default: + return False; + } + + init_sec_access( &sa, mask ); + + /* no flags on share permissions */ + init_sec_ace( ace, &sid, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0 ); + + return True; +} + + +/******************************************************************** +********************************************************************/ + +static SEC_DESC* parse_acl_string( TALLOC_CTX *ctx, const char *szACL, size_t *sd_size ) +{ + SEC_DESC *sd = NULL; + SEC_ACE *ace; + SEC_ACL *acl; + int num_ace; + const char *pacl; + int i; + + if ( !szACL ) + return NULL; + + pacl = szACL; + num_ace = count_chars( pacl, ',' ) + 1; + + if ( !(ace = TALLOC_ZERO_ARRAY( ctx, SEC_ACE, num_ace )) ) + return NULL; + + for ( i=0; i<num_ace; i++ ) { + char *end_acl = strchr_m( pacl, ',' ); + fstring acl_string; + + strncpy( acl_string, pacl, MIN( PTR_DIFF( end_acl, pacl ), sizeof(fstring)-1) ); + acl_string[MIN( PTR_DIFF( end_acl, pacl ), sizeof(fstring)-1)] = '\0'; + + if ( !parse_ace( ctx, &ace[i], acl_string ) ) + return NULL; + + pacl = end_acl; + pacl++; + } + + if ( !(acl = make_sec_acl( ctx, NT4_ACL_REVISION, num_ace, ace )) ) + return NULL; + + sd = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, + &global_sid_Builtin_Administrators, + &global_sid_Builtin_Administrators, + NULL, acl, sd_size); + + return sd; +} + +/******************************************************************** + main program +********************************************************************/ + +int main(int argc, const char *argv[]) +{ + int opt; + enum acl_mode mode = SMB_ACL_REPLACE; + static char *the_acl = NULL; + fstring sharename; + BOOL force_acl = False; + size_t sd_size = 0; + SEC_DESC *secdesc; + int snum; + poptContext pc; + TALLOC_CTX *ctx; + BOOL initialize_sid = False; + struct poptOption long_options[] = { + POPT_AUTOHELP +#if 0 + { "remove", 'r', POPT_ARG_STRING, NULL, 'r', "Delete an ACE", "ACL" }, + { "modify", 'm', POPT_ARG_STRING, NULL, 'm', "Modify an acl", "ACL" }, + { "add", 'a', POPT_ARG_STRING, NULL, 'a', "Add an ACE", "ACL" }, +#endif + { "replace", 'R', POPT_ARG_STRING, NULL, 'R', "Set share mission ACL", "ACLS" }, + { "view", 'v', POPT_ARG_NONE, NULL, 'v', "View current share permissions" }, + { "machine-sid", 'M', POPT_ARG_NONE, NULL, 'M', "Initialize the machine SID" }, + { "force", 'F', POPT_ARG_NONE, NULL, 'F', "Force storing the ACL", "ACLS" }, + POPT_COMMON_SAMBA + { NULL } + }; + + if ( !(ctx = talloc_init("main")) ) { + fprintf( stderr, "Failed to initialize talloc context!\n"); + return -1; + } + + /* set default debug level to 1 regardless of what smb.conf sets */ + setup_logging( "sharesec", True ); + DEBUGLEVEL_CLASS[DBGC_ALL] = 1; + dbf = x_stderr; + x_setbuf( x_stderr, NULL ); + + setlinebuf(stdout); + + load_case_tables(); + + lp_load( dyn_CONFIGFILE, False, False, False, True ); + + pc = poptGetContext("smbcacls", argc, argv, long_options, 0); + + poptSetOtherOptionHelp(pc, "sharename\n"); + + while ((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { +#if 0 + case 'r': + the_acl = smb_xstrdup(poptGetOptArg(pc)); + mode = SMB_ACL_REMOVE; + break; + + case 'm': + the_acl = smb_xstrdup(poptGetOptArg(pc)); + mode = SMB_ACL_MODIFY; + break; + + case 'a': + the_acl = smb_xstrdup(poptGetOptArg(pc)); + mode = SMB_ACL_ADD; + break; +#endif + case 'R': + the_acl = smb_xstrdup(poptGetOptArg(pc)); + mode = SMB_ACL_REPLACE; + break; + + case 'v': + mode = SMB_ACL_VIEW; + break; + + case 'F': + force_acl = True; + break; + + case 'M': + initialize_sid = True; + break; + } + } + + /* check for initializing secrets.tdb first */ + + if ( initialize_sid ) { + DOM_SID *sid = get_global_sam_sid(); + + if ( !sid ) { + fprintf( stderr, "Failed to retrieve Machine SID!\n"); + return 3; + } + + printf ("%s\n", sid_string_static( sid ) ); + return 0; + } + + if ( mode == SMB_ACL_VIEW && force_acl ) { + fprintf( stderr, "Invalid combination of -F and -v\n"); + return -1; + } + + /* get the sharename */ + + if(!poptPeekArg(pc)) { + poptPrintUsage(pc, stderr, 0); + return -1; + } + + fstrcpy(sharename, poptGetArg(pc)); + + snum = lp_servicenumber( sharename ); + + if ( snum == -1 && !force_acl ) { + fprintf( stderr, "Invalid sharename: %s\n", sharename); + return -1; + } + + switch ( mode ) { + case SMB_ACL_VIEW: + if (!(secdesc = get_share_security( ctx, snum, &sd_size )) ) { + fprintf(stderr, "Unable to retrieve permissions for share [%s]\n", sharename); + return -1; + } + sec_desc_print( stdout, secdesc ); + break; + + case SMB_ACL_REMOVE: + case SMB_ACL_ADD: + case SMB_ACL_MODIFY: + printf( "Not implemented\n"); + break; + + case SMB_ACL_REPLACE: + if ( !(secdesc = parse_acl_string( ctx, the_acl, &sd_size )) ) { + fprintf( stderr, "Failed to parse acl\n"); + return -1; + } + + if ( !set_share_security( ctx, lp_servicename(snum), secdesc ) ) { + fprintf( stderr, "Failed to store acl for share [%s]\n", sharename ); + return 2; + } + break; + } + + talloc_destroy(ctx); + + return 0; +} diff --git a/source/utils/smbcontrol.c b/source/utils/smbcontrol.c index 0c6a1341c03..a23492f9dcc 100644 --- a/source/utils/smbcontrol.c +++ b/source/utils/smbcontrol.c @@ -890,7 +890,7 @@ static BOOL do_winbind_offline(const struct process_id pid, ret = send_message(pid, MSG_WINBIND_OFFLINE, NULL, 0, False); /* Check that the entry "WINBINDD_OFFLINE" still exists. */ - tdb->ecode = TDB_SUCCESS; + /* tdb->ecode = TDB_SUCCESS; */ d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" ); /* As this is a key with no data we don't need to free, we diff --git a/source/utils/status.c b/source/utils/status.c index 163d99a2f69..58349f1f9a5 100644 --- a/source/utils/status.c +++ b/source/utils/status.c @@ -48,6 +48,9 @@ static BOOL numeric_only = False; const char *username = NULL; +extern BOOL status_profile_dump(BOOL be_verbose); +extern BOOL status_profile_rates(BOOL be_verbose); + /* added by OH */ static void Ucrit_addUid(uid_t uid) { @@ -182,368 +185,6 @@ static void print_brl(SMB_DEV_T dev, (double)start, (double)size); } - -/******************************************************************* - dump the elements of the profile structure - ******************************************************************/ -static int profile_dump(void) -{ -#ifdef WITH_PROFILE - if (!profile_setup(True)) { - fprintf(stderr,"Failed to initialise profile memory\n"); - return -1; - } - - d_printf("smb_count: %u\n", profile_p->smb_count); - d_printf("uid_changes: %u\n", profile_p->uid_changes); - d_printf("************************ System Calls ****************************\n"); - d_printf("opendir_count: %u\n", profile_p->syscall_opendir_count); - d_printf("opendir_time: %u\n", profile_p->syscall_opendir_time); - d_printf("readdir_count: %u\n", profile_p->syscall_readdir_count); - d_printf("readdir_time: %u\n", profile_p->syscall_readdir_time); - d_printf("mkdir_count: %u\n", profile_p->syscall_mkdir_count); - d_printf("mkdir_time: %u\n", profile_p->syscall_mkdir_time); - d_printf("rmdir_count: %u\n", profile_p->syscall_rmdir_count); - d_printf("rmdir_time: %u\n", profile_p->syscall_rmdir_time); - d_printf("closedir_count: %u\n", profile_p->syscall_closedir_count); - d_printf("closedir_time: %u\n", profile_p->syscall_closedir_time); - d_printf("open_count: %u\n", profile_p->syscall_open_count); - d_printf("open_time: %u\n", profile_p->syscall_open_time); - d_printf("close_count: %u\n", profile_p->syscall_close_count); - d_printf("close_time: %u\n", profile_p->syscall_close_time); - d_printf("read_count: %u\n", profile_p->syscall_read_count); - d_printf("read_time: %u\n", profile_p->syscall_read_time); - d_printf("read_bytes: %u\n", profile_p->syscall_read_bytes); - d_printf("write_count: %u\n", profile_p->syscall_write_count); - d_printf("write_time: %u\n", profile_p->syscall_write_time); - d_printf("write_bytes: %u\n", profile_p->syscall_write_bytes); - d_printf("pread_count: %u\n", profile_p->syscall_pread_count); - d_printf("pread_time: %u\n", profile_p->syscall_pread_time); - d_printf("pread_bytes: %u\n", profile_p->syscall_pread_bytes); - d_printf("pwrite_count: %u\n", profile_p->syscall_pwrite_count); - d_printf("pwrite_time: %u\n", profile_p->syscall_pwrite_time); - d_printf("pwrite_bytes: %u\n", profile_p->syscall_pwrite_bytes); -#ifdef WITH_SENDFILE - d_printf("sendfile_count: %u\n", profile_p->syscall_sendfile_count); - d_printf("sendfile_time: %u\n", profile_p->syscall_sendfile_time); - d_printf("sendfile_bytes: %u\n", profile_p->syscall_sendfile_bytes); -#endif - d_printf("lseek_count: %u\n", profile_p->syscall_lseek_count); - d_printf("lseek_time: %u\n", profile_p->syscall_lseek_time); - d_printf("rename_count: %u\n", profile_p->syscall_rename_count); - d_printf("rename_time: %u\n", profile_p->syscall_rename_time); - d_printf("fsync_count: %u\n", profile_p->syscall_fsync_count); - d_printf("fsync_time: %u\n", profile_p->syscall_fsync_time); - d_printf("stat_count: %u\n", profile_p->syscall_stat_count); - d_printf("stat_time: %u\n", profile_p->syscall_stat_time); - d_printf("fstat_count: %u\n", profile_p->syscall_fstat_count); - d_printf("fstat_time: %u\n", profile_p->syscall_fstat_time); - d_printf("lstat_count: %u\n", profile_p->syscall_lstat_count); - d_printf("lstat_time: %u\n", profile_p->syscall_lstat_time); - d_printf("unlink_count: %u\n", profile_p->syscall_unlink_count); - d_printf("unlink_time: %u\n", profile_p->syscall_unlink_time); - d_printf("chmod_count: %u\n", profile_p->syscall_chmod_count); - d_printf("chmod_time: %u\n", profile_p->syscall_chmod_time); - d_printf("fchmod_count: %u\n", profile_p->syscall_fchmod_count); - d_printf("fchmod_time: %u\n", profile_p->syscall_fchmod_time); - d_printf("chown_count: %u\n", profile_p->syscall_chown_count); - d_printf("chown_time: %u\n", profile_p->syscall_chown_time); - d_printf("fchown_count: %u\n", profile_p->syscall_fchown_count); - d_printf("fchown_time: %u\n", profile_p->syscall_fchown_time); - d_printf("chdir_count: %u\n", profile_p->syscall_chdir_count); - d_printf("chdir_time: %u\n", profile_p->syscall_chdir_time); - d_printf("getwd_count: %u\n", profile_p->syscall_getwd_count); - d_printf("getwd_time: %u\n", profile_p->syscall_getwd_time); - d_printf("utime_count: %u\n", profile_p->syscall_utime_count); - d_printf("utime_time: %u\n", profile_p->syscall_utime_time); - d_printf("ftruncate_count: %u\n", profile_p->syscall_ftruncate_count); - d_printf("ftruncate_time: %u\n", profile_p->syscall_ftruncate_time); - d_printf("fcntl_lock_count: %u\n", profile_p->syscall_fcntl_lock_count); - d_printf("fcntl_lock_time: %u\n", profile_p->syscall_fcntl_lock_time); - d_printf("readlink_count: %u\n", profile_p->syscall_readlink_count); - d_printf("readlink_time: %u\n", profile_p->syscall_readlink_time); - d_printf("symlink_count: %u\n", profile_p->syscall_symlink_count); - d_printf("symlink_time: %u\n", profile_p->syscall_symlink_time); - d_printf("************************ Statcache *******************************\n"); - d_printf("lookups: %u\n", profile_p->statcache_lookups); - d_printf("misses: %u\n", profile_p->statcache_misses); - d_printf("hits: %u\n", profile_p->statcache_hits); - d_printf("************************ Writecache ******************************\n"); - d_printf("read_hits: %u\n", profile_p->writecache_read_hits); - d_printf("abutted_writes: %u\n", profile_p->writecache_abutted_writes); - d_printf("total_writes: %u\n", profile_p->writecache_total_writes); - d_printf("non_oplock_writes: %u\n", profile_p->writecache_non_oplock_writes); - d_printf("direct_writes: %u\n", profile_p->writecache_direct_writes); - d_printf("init_writes: %u\n", profile_p->writecache_init_writes); - d_printf("flushed_writes[SEEK]: %u\n", profile_p->writecache_flushed_writes[SEEK_FLUSH]); - d_printf("flushed_writes[READ]: %u\n", profile_p->writecache_flushed_writes[READ_FLUSH]); - d_printf("flushed_writes[WRITE]: %u\n", profile_p->writecache_flushed_writes[WRITE_FLUSH]); - d_printf("flushed_writes[READRAW]: %u\n", profile_p->writecache_flushed_writes[READRAW_FLUSH]); - d_printf("flushed_writes[OPLOCK_RELEASE]: %u\n", profile_p->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH]); - d_printf("flushed_writes[CLOSE]: %u\n", profile_p->writecache_flushed_writes[CLOSE_FLUSH]); - d_printf("flushed_writes[SYNC]: %u\n", profile_p->writecache_flushed_writes[SYNC_FLUSH]); - d_printf("flushed_writes[SIZECHANGE]: %u\n", profile_p->writecache_flushed_writes[SIZECHANGE_FLUSH]); - d_printf("num_perfect_writes: %u\n", profile_p->writecache_num_perfect_writes); - d_printf("num_write_caches: %u\n", profile_p->writecache_num_write_caches); - d_printf("allocated_write_caches: %u\n", profile_p->writecache_allocated_write_caches); - d_printf("************************ SMB Calls *******************************\n"); - d_printf("mkdir_count: %u\n", profile_p->SMBmkdir_count); - d_printf("mkdir_time: %u\n", profile_p->SMBmkdir_time); - d_printf("rmdir_count: %u\n", profile_p->SMBrmdir_count); - d_printf("rmdir_time: %u\n", profile_p->SMBrmdir_time); - d_printf("open_count: %u\n", profile_p->SMBopen_count); - d_printf("open_time: %u\n", profile_p->SMBopen_time); - d_printf("create_count: %u\n", profile_p->SMBcreate_count); - d_printf("create_time: %u\n", profile_p->SMBcreate_time); - d_printf("close_count: %u\n", profile_p->SMBclose_count); - d_printf("close_time: %u\n", profile_p->SMBclose_time); - d_printf("flush_count: %u\n", profile_p->SMBflush_count); - d_printf("flush_time: %u\n", profile_p->SMBflush_time); - d_printf("unlink_count: %u\n", profile_p->SMBunlink_count); - d_printf("unlink_time: %u\n", profile_p->SMBunlink_time); - d_printf("mv_count: %u\n", profile_p->SMBmv_count); - d_printf("mv_time: %u\n", profile_p->SMBmv_time); - d_printf("getatr_count: %u\n", profile_p->SMBgetatr_count); - d_printf("getatr_time: %u\n", profile_p->SMBgetatr_time); - d_printf("setatr_count: %u\n", profile_p->SMBsetatr_count); - d_printf("setatr_time: %u\n", profile_p->SMBsetatr_time); - d_printf("read_count: %u\n", profile_p->SMBread_count); - d_printf("read_time: %u\n", profile_p->SMBread_time); - d_printf("write_count: %u\n", profile_p->SMBwrite_count); - d_printf("write_time: %u\n", profile_p->SMBwrite_time); - d_printf("lock_count: %u\n", profile_p->SMBlock_count); - d_printf("lock_time: %u\n", profile_p->SMBlock_time); - d_printf("unlock_count: %u\n", profile_p->SMBunlock_count); - d_printf("unlock_time: %u\n", profile_p->SMBunlock_time); - d_printf("ctemp_count: %u\n", profile_p->SMBctemp_count); - d_printf("ctemp_time: %u\n", profile_p->SMBctemp_time); - d_printf("mknew_count: %u\n", profile_p->SMBmknew_count); - d_printf("mknew_time: %u\n", profile_p->SMBmknew_time); - d_printf("chkpth_count: %u\n", profile_p->SMBchkpth_count); - d_printf("chkpth_time: %u\n", profile_p->SMBchkpth_time); - d_printf("exit_count: %u\n", profile_p->SMBexit_count); - d_printf("exit_time: %u\n", profile_p->SMBexit_time); - d_printf("lseek_count: %u\n", profile_p->SMBlseek_count); - d_printf("lseek_time: %u\n", profile_p->SMBlseek_time); - d_printf("lockread_count: %u\n", profile_p->SMBlockread_count); - d_printf("lockread_time: %u\n", profile_p->SMBlockread_time); - d_printf("writeunlock_count: %u\n", profile_p->SMBwriteunlock_count); - d_printf("writeunlock_time: %u\n", profile_p->SMBwriteunlock_time); - d_printf("readbraw_count: %u\n", profile_p->SMBreadbraw_count); - d_printf("readbraw_time: %u\n", profile_p->SMBreadbraw_time); - d_printf("readBmpx_count: %u\n", profile_p->SMBreadBmpx_count); - d_printf("readBmpx_time: %u\n", profile_p->SMBreadBmpx_time); - d_printf("readBs_count: %u\n", profile_p->SMBreadBs_count); - d_printf("readBs_time: %u\n", profile_p->SMBreadBs_time); - d_printf("writebraw_count: %u\n", profile_p->SMBwritebraw_count); - d_printf("writebraw_time: %u\n", profile_p->SMBwritebraw_time); - d_printf("writeBmpx_count: %u\n", profile_p->SMBwriteBmpx_count); - d_printf("writeBmpx_time: %u\n", profile_p->SMBwriteBmpx_time); - d_printf("writeBs_count: %u\n", profile_p->SMBwriteBs_count); - d_printf("writeBs_time: %u\n", profile_p->SMBwriteBs_time); - d_printf("writec_count: %u\n", profile_p->SMBwritec_count); - d_printf("writec_time: %u\n", profile_p->SMBwritec_time); - d_printf("setattrE_count: %u\n", profile_p->SMBsetattrE_count); - d_printf("setattrE_time: %u\n", profile_p->SMBsetattrE_time); - d_printf("getattrE_count: %u\n", profile_p->SMBgetattrE_count); - d_printf("getattrE_time: %u\n", profile_p->SMBgetattrE_time); - d_printf("lockingX_count: %u\n", profile_p->SMBlockingX_count); - d_printf("lockingX_time: %u\n", profile_p->SMBlockingX_time); - d_printf("trans_count: %u\n", profile_p->SMBtrans_count); - d_printf("trans_time: %u\n", profile_p->SMBtrans_time); - d_printf("transs_count: %u\n", profile_p->SMBtranss_count); - d_printf("transs_time: %u\n", profile_p->SMBtranss_time); - d_printf("ioctl_count: %u\n", profile_p->SMBioctl_count); - d_printf("ioctl_time: %u\n", profile_p->SMBioctl_time); - d_printf("ioctls_count: %u\n", profile_p->SMBioctls_count); - d_printf("ioctls_time: %u\n", profile_p->SMBioctls_time); - d_printf("copy_count: %u\n", profile_p->SMBcopy_count); - d_printf("copy_time: %u\n", profile_p->SMBcopy_time); - d_printf("move_count: %u\n", profile_p->SMBmove_count); - d_printf("move_time: %u\n", profile_p->SMBmove_time); - d_printf("echo_count: %u\n", profile_p->SMBecho_count); - d_printf("echo_time: %u\n", profile_p->SMBecho_time); - d_printf("writeclose_count: %u\n", profile_p->SMBwriteclose_count); - d_printf("writeclose_time: %u\n", profile_p->SMBwriteclose_time); - d_printf("openX_count: %u\n", profile_p->SMBopenX_count); - d_printf("openX_time: %u\n", profile_p->SMBopenX_time); - d_printf("readX_count: %u\n", profile_p->SMBreadX_count); - d_printf("readX_time: %u\n", profile_p->SMBreadX_time); - d_printf("writeX_count: %u\n", profile_p->SMBwriteX_count); - d_printf("writeX_time: %u\n", profile_p->SMBwriteX_time); - d_printf("trans2_count: %u\n", profile_p->SMBtrans2_count); - d_printf("trans2_time: %u\n", profile_p->SMBtrans2_time); - d_printf("transs2_count: %u\n", profile_p->SMBtranss2_count); - d_printf("transs2_time: %u\n", profile_p->SMBtranss2_time); - d_printf("findclose_count: %u\n", profile_p->SMBfindclose_count); - d_printf("findclose_time: %u\n", profile_p->SMBfindclose_time); - d_printf("findnclose_count: %u\n", profile_p->SMBfindnclose_count); - d_printf("findnclose_time: %u\n", profile_p->SMBfindnclose_time); - d_printf("tcon_count: %u\n", profile_p->SMBtcon_count); - d_printf("tcon_time: %u\n", profile_p->SMBtcon_time); - d_printf("tdis_count: %u\n", profile_p->SMBtdis_count); - d_printf("tdis_time: %u\n", profile_p->SMBtdis_time); - d_printf("negprot_count: %u\n", profile_p->SMBnegprot_count); - d_printf("negprot_time: %u\n", profile_p->SMBnegprot_time); - d_printf("sesssetupX_count: %u\n", profile_p->SMBsesssetupX_count); - d_printf("sesssetupX_time: %u\n", profile_p->SMBsesssetupX_time); - d_printf("ulogoffX_count: %u\n", profile_p->SMBulogoffX_count); - d_printf("ulogoffX_time: %u\n", profile_p->SMBulogoffX_time); - d_printf("tconX_count: %u\n", profile_p->SMBtconX_count); - d_printf("tconX_time: %u\n", profile_p->SMBtconX_time); - d_printf("dskattr_count: %u\n", profile_p->SMBdskattr_count); - d_printf("dskattr_time: %u\n", profile_p->SMBdskattr_time); - d_printf("search_count: %u\n", profile_p->SMBsearch_count); - d_printf("search_time: %u\n", profile_p->SMBsearch_time); - d_printf("ffirst_count: %u\n", profile_p->SMBffirst_count); - d_printf("ffirst_time: %u\n", profile_p->SMBffirst_time); - d_printf("funique_count: %u\n", profile_p->SMBfunique_count); - d_printf("funique_time: %u\n", profile_p->SMBfunique_time); - d_printf("fclose_count: %u\n", profile_p->SMBfclose_count); - d_printf("fclose_time: %u\n", profile_p->SMBfclose_time); - d_printf("nttrans_count: %u\n", profile_p->SMBnttrans_count); - d_printf("nttrans_time: %u\n", profile_p->SMBnttrans_time); - d_printf("nttranss_count: %u\n", profile_p->SMBnttranss_count); - d_printf("nttranss_time: %u\n", profile_p->SMBnttranss_time); - d_printf("ntcreateX_count: %u\n", profile_p->SMBntcreateX_count); - d_printf("ntcreateX_time: %u\n", profile_p->SMBntcreateX_time); - d_printf("ntcancel_count: %u\n", profile_p->SMBntcancel_count); - d_printf("ntcancel_time: %u\n", profile_p->SMBntcancel_time); - d_printf("splopen_count: %u\n", profile_p->SMBsplopen_count); - d_printf("splopen_time: %u\n", profile_p->SMBsplopen_time); - d_printf("splwr_count: %u\n", profile_p->SMBsplwr_count); - d_printf("splwr_time: %u\n", profile_p->SMBsplwr_time); - d_printf("splclose_count: %u\n", profile_p->SMBsplclose_count); - d_printf("splclose_time: %u\n", profile_p->SMBsplclose_time); - d_printf("splretq_count: %u\n", profile_p->SMBsplretq_count); - d_printf("splretq_time: %u\n", profile_p->SMBsplretq_time); - d_printf("sends_count: %u\n", profile_p->SMBsends_count); - d_printf("sends_time: %u\n", profile_p->SMBsends_time); - d_printf("sendb_count: %u\n", profile_p->SMBsendb_count); - d_printf("sendb_time: %u\n", profile_p->SMBsendb_time); - d_printf("fwdname_count: %u\n", profile_p->SMBfwdname_count); - d_printf("fwdname_time: %u\n", profile_p->SMBfwdname_time); - d_printf("cancelf_count: %u\n", profile_p->SMBcancelf_count); - d_printf("cancelf_time: %u\n", profile_p->SMBcancelf_time); - d_printf("getmac_count: %u\n", profile_p->SMBgetmac_count); - d_printf("getmac_time: %u\n", profile_p->SMBgetmac_time); - d_printf("sendstrt_count: %u\n", profile_p->SMBsendstrt_count); - d_printf("sendstrt_time: %u\n", profile_p->SMBsendstrt_time); - d_printf("sendend_count: %u\n", profile_p->SMBsendend_count); - d_printf("sendend_time: %u\n", profile_p->SMBsendend_time); - d_printf("sendtxt_count: %u\n", profile_p->SMBsendtxt_count); - d_printf("sendtxt_time: %u\n", profile_p->SMBsendtxt_time); - d_printf("invalid_count: %u\n", profile_p->SMBinvalid_count); - d_printf("invalid_time: %u\n", profile_p->SMBinvalid_time); - d_printf("************************ Pathworks Calls *************************\n"); - d_printf("setdir_count: %u\n", profile_p->pathworks_setdir_count); - d_printf("setdir_time: %u\n", profile_p->pathworks_setdir_time); - d_printf("************************ Trans2 Calls ****************************\n"); - d_printf("open_count: %u\n", profile_p->Trans2_open_count); - d_printf("open_time: %u\n", profile_p->Trans2_open_time); - d_printf("findfirst_count: %u\n", profile_p->Trans2_findfirst_count); - d_printf("findfirst_time: %u\n", profile_p->Trans2_findfirst_time); - d_printf("findnext_count: %u\n", profile_p->Trans2_findnext_count); - d_printf("findnext_time: %u\n", profile_p->Trans2_findnext_time); - d_printf("qfsinfo_count: %u\n", profile_p->Trans2_qfsinfo_count); - d_printf("qfsinfo_time: %u\n", profile_p->Trans2_qfsinfo_time); - d_printf("setfsinfo_count: %u\n", profile_p->Trans2_setfsinfo_count); - d_printf("setfsinfo_time: %u\n", profile_p->Trans2_setfsinfo_time); - d_printf("qpathinfo_count: %u\n", profile_p->Trans2_qpathinfo_count); - d_printf("qpathinfo_time: %u\n", profile_p->Trans2_qpathinfo_time); - d_printf("setpathinfo_count: %u\n", profile_p->Trans2_setpathinfo_count); - d_printf("setpathinfo_time: %u\n", profile_p->Trans2_setpathinfo_time); - d_printf("qfileinfo_count: %u\n", profile_p->Trans2_qfileinfo_count); - d_printf("qfileinfo_time: %u\n", profile_p->Trans2_qfileinfo_time); - d_printf("setfileinfo_count: %u\n", profile_p->Trans2_setfileinfo_count); - d_printf("setfileinfo_time: %u\n", profile_p->Trans2_setfileinfo_time); - d_printf("fsctl_count: %u\n", profile_p->Trans2_fsctl_count); - d_printf("fsctl_time: %u\n", profile_p->Trans2_fsctl_time); - d_printf("ioctl_count: %u\n", profile_p->Trans2_ioctl_count); - d_printf("ioctl_time: %u\n", profile_p->Trans2_ioctl_time); - d_printf("findnotifyfirst_count: %u\n", profile_p->Trans2_findnotifyfirst_count); - d_printf("findnotifyfirst_time: %u\n", profile_p->Trans2_findnotifyfirst_time); - d_printf("findnotifynext_count: %u\n", profile_p->Trans2_findnotifynext_count); - d_printf("findnotifynext_time: %u\n", profile_p->Trans2_findnotifynext_time); - d_printf("mkdir_count: %u\n", profile_p->Trans2_mkdir_count); - d_printf("mkdir_time: %u\n", profile_p->Trans2_mkdir_time); - d_printf("session_setup_count: %u\n", profile_p->Trans2_session_setup_count); - d_printf("session_setup_time: %u\n", profile_p->Trans2_session_setup_time); - d_printf("get_dfs_referral_count: %u\n", profile_p->Trans2_get_dfs_referral_count); - d_printf("get_dfs_referral_time: %u\n", profile_p->Trans2_get_dfs_referral_time); - d_printf("report_dfs_inconsistancy_count: %u\n", profile_p->Trans2_report_dfs_inconsistancy_count); - d_printf("report_dfs_inconsistancy_time: %u\n", profile_p->Trans2_report_dfs_inconsistancy_time); - d_printf("************************ NT Transact Calls ***********************\n"); - d_printf("create_count: %u\n", profile_p->NT_transact_create_count); - d_printf("create_time: %u\n", profile_p->NT_transact_create_time); - d_printf("ioctl_count: %u\n", profile_p->NT_transact_ioctl_count); - d_printf("ioctl_time: %u\n", profile_p->NT_transact_ioctl_time); - d_printf("set_security_desc_count: %u\n", profile_p->NT_transact_set_security_desc_count); - d_printf("set_security_desc_time: %u\n", profile_p->NT_transact_set_security_desc_time); - d_printf("notify_change_count: %u\n", profile_p->NT_transact_notify_change_count); - d_printf("notify_change_time: %u\n", profile_p->NT_transact_notify_change_time); - d_printf("rename_count: %u\n", profile_p->NT_transact_rename_count); - d_printf("rename_time: %u\n", profile_p->NT_transact_rename_time); - d_printf("query_security_desc_count: %u\n", profile_p->NT_transact_query_security_desc_count); - d_printf("query_security_desc_time: %u\n", profile_p->NT_transact_query_security_desc_time); - d_printf("************************ ACL Calls *******************************\n"); - d_printf("get_nt_acl_count: %u\n", profile_p->get_nt_acl_count); - d_printf("get_nt_acl_time: %u\n", profile_p->get_nt_acl_time); - d_printf("fget_nt_acl_count: %u\n", profile_p->fget_nt_acl_count); - d_printf("fget_nt_acl_time: %u\n", profile_p->fget_nt_acl_time); - d_printf("set_nt_acl_count: %u\n", profile_p->set_nt_acl_count); - d_printf("set_nt_acl_time: %u\n", profile_p->set_nt_acl_time); - d_printf("fset_nt_acl_count: %u\n", profile_p->fset_nt_acl_count); - d_printf("fset_nt_acl_time: %u\n", profile_p->fset_nt_acl_time); - d_printf("chmod_acl_count: %u\n", profile_p->chmod_acl_count); - d_printf("chmod_acl_time: %u\n", profile_p->chmod_acl_time); - d_printf("fchmod_acl_count: %u\n", profile_p->fchmod_acl_count); - d_printf("fchmod_acl_time: %u\n", profile_p->fchmod_acl_time); - d_printf("************************ NMBD Calls ****************************\n"); - d_printf("name_release_count: %u\n", profile_p->name_release_count); - d_printf("name_release_time: %u\n", profile_p->name_release_time); - d_printf("name_refresh_count: %u\n", profile_p->name_refresh_count); - d_printf("name_refresh_time: %u\n", profile_p->name_refresh_time); - d_printf("name_registration_count: %u\n", profile_p->name_registration_count); - d_printf("name_registration_time: %u\n", profile_p->name_registration_time); - d_printf("node_status_count: %u\n", profile_p->node_status_count); - d_printf("node_status_time: %u\n", profile_p->node_status_time); - d_printf("name_query_count: %u\n", profile_p->name_query_count); - d_printf("name_query_time: %u\n", profile_p->name_query_time); - d_printf("host_announce_count: %u\n", profile_p->host_announce_count); - d_printf("host_announce_time: %u\n", profile_p->host_announce_time); - d_printf("workgroup_announce_count: %u\n", profile_p->workgroup_announce_count); - d_printf("workgroup_announce_time: %u\n", profile_p->workgroup_announce_time); - d_printf("local_master_announce_count: %u\n", profile_p->local_master_announce_count); - d_printf("local_master_announce_time: %u\n", profile_p->local_master_announce_time); - d_printf("master_browser_announce_count: %u\n", profile_p->master_browser_announce_count); - d_printf("master_browser_announce_time: %u\n", profile_p->master_browser_announce_time); - d_printf("lm_host_announce_count: %u\n", profile_p->lm_host_announce_count); - d_printf("lm_host_announce_time: %u\n", profile_p->lm_host_announce_time); - d_printf("get_backup_list_count: %u\n", profile_p->get_backup_list_count); - d_printf("get_backup_list_time: %u\n", profile_p->get_backup_list_time); - d_printf("reset_browser_count: %u\n", profile_p->reset_browser_count); - d_printf("reset_browser_time: %u\n", profile_p->reset_browser_time); - d_printf("announce_request_count: %u\n", profile_p->announce_request_count); - d_printf("announce_request_time: %u\n", profile_p->announce_request_time); - d_printf("lm_announce_request_count: %u\n", profile_p->lm_announce_request_count); - d_printf("lm_announce_request_time: %u\n", profile_p->lm_announce_request_time); - d_printf("domain_logon_count: %u\n", profile_p->domain_logon_count); - d_printf("domain_logon_time: %u\n", profile_p->domain_logon_time); - d_printf("sync_browse_lists_count: %u\n", profile_p->sync_browse_lists_count); - d_printf("sync_browse_lists_time: %u\n", profile_p->sync_browse_lists_time); - d_printf("run_elections_count: %u\n", profile_p->run_elections_count); - d_printf("run_elections_time: %u\n", profile_p->run_elections_time); - d_printf("election_count: %u\n", profile_p->election_count); - d_printf("election_time: %u\n", profile_p->election_time); -#else /* WITH_PROFILE */ - fprintf(stderr, "Profile data unavailable\n"); -#endif /* WITH_PROFILE */ - - return 0; -} - - static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) { struct connections_data crec; @@ -602,7 +243,7 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo int main(int argc, char *argv[]) { int c; - static int profile_only = 0; + int profile_only = 0; TDB_CONTEXT *tdb; BOOL show_processes, show_locks, show_shares; poptContext pc; @@ -614,9 +255,8 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo {"shares", 'S', POPT_ARG_NONE, &shares_only, 'S', "Show shares only" }, {"user", 'u', POPT_ARG_STRING, &username, 'u', "Switch to user" }, {"brief", 'b', POPT_ARG_NONE, &brief, 'b', "Be brief" }, -#ifdef WITH_PROFILE - {"profile", 'P', POPT_ARG_NONE, &profile_only, 'P', "Do profiling" }, -#endif /* WITH_PROFILE */ + {"profile", 'P', POPT_ARG_NONE, NULL, 'P', "Do profiling" }, + {"profile-rates", 'R', POPT_ARG_NONE, NULL, 'R', "Show call rates" }, {"byterange", 'B', POPT_ARG_NONE, &show_brl, 'B', "Include byte range locks"}, {"numeric", 'n', POPT_ARG_NONE, &numeric_only, 'n', "Numeric uid/gid"}, POPT_COMMON_SAMBA @@ -643,6 +283,9 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo case 'u': Ucrit_addUid(nametouid(poptGetOptArg(pc))); break; + case 'P': + case 'R': + profile_only = c; } } @@ -663,11 +306,18 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); return (-1); } - - if (profile_only) { - return profile_dump(); + + switch (profile_only) { + case 'P': + /* Dump profile data */ + return status_profile_dump(verbose); + case 'R': + /* Continuously display rate-converted data */ + return status_profile_rates(verbose); + default: + break; } - + if ( show_processes ) { tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0); if (!tdb) { diff --git a/source/utils/status_profile.c b/source/utils/status_profile.c new file mode 100644 index 00000000000..fc5b5e10ffd --- /dev/null +++ b/source/utils/status_profile.c @@ -0,0 +1,544 @@ +/* + * Unix SMB/CIFS implementation. + * status reporting + * Copyright (C) Andrew Tridgell 1994-1998 + * Copyright (C) James Peach 2005-2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +static void profile_separator(const char * title) +{ + char line[79 + 1]; + char * end; + + snprintf(line, sizeof(line), "**** %s ", title); + + for (end = line + strlen(line); end < &line[sizeof(line) -1]; ++end) { + *end = '*'; + } + + line[sizeof(line) - 1] = '\0'; + d_printf("%s\n", line); +} + +/******************************************************************* + dump the elements of the profile structure + ******************************************************************/ +BOOL status_profile_dump(BOOL verbose) +{ +#ifdef WITH_PROFILE + if (!profile_setup(True)) { + fprintf(stderr,"Failed to initialise profile memory\n"); + return False; + } + + d_printf("smb_count: %u\n", profile_p->smb_count); + d_printf("uid_changes: %u\n", profile_p->uid_changes); + + profile_separator("System Calls"); + d_printf("opendir_count: %u\n", profile_p->syscall_opendir_count); + d_printf("opendir_time: %u\n", profile_p->syscall_opendir_time); + d_printf("readdir_count: %u\n", profile_p->syscall_readdir_count); + d_printf("readdir_time: %u\n", profile_p->syscall_readdir_time); + d_printf("mkdir_count: %u\n", profile_p->syscall_mkdir_count); + d_printf("mkdir_time: %u\n", profile_p->syscall_mkdir_time); + d_printf("rmdir_count: %u\n", profile_p->syscall_rmdir_count); + d_printf("rmdir_time: %u\n", profile_p->syscall_rmdir_time); + d_printf("closedir_count: %u\n", profile_p->syscall_closedir_count); + d_printf("closedir_time: %u\n", profile_p->syscall_closedir_time); + d_printf("open_count: %u\n", profile_p->syscall_open_count); + d_printf("open_time: %u\n", profile_p->syscall_open_time); + d_printf("close_count: %u\n", profile_p->syscall_close_count); + d_printf("close_time: %u\n", profile_p->syscall_close_time); + d_printf("read_count: %u\n", profile_p->syscall_read_count); + d_printf("read_time: %u\n", profile_p->syscall_read_time); + d_printf("read_bytes: %u\n", profile_p->syscall_read_bytes); + d_printf("write_count: %u\n", profile_p->syscall_write_count); + d_printf("write_time: %u\n", profile_p->syscall_write_time); + d_printf("write_bytes: %u\n", profile_p->syscall_write_bytes); + d_printf("pread_count: %u\n", profile_p->syscall_pread_count); + d_printf("pread_time: %u\n", profile_p->syscall_pread_time); + d_printf("pread_bytes: %u\n", profile_p->syscall_pread_bytes); + d_printf("pwrite_count: %u\n", profile_p->syscall_pwrite_count); + d_printf("pwrite_time: %u\n", profile_p->syscall_pwrite_time); + d_printf("pwrite_bytes: %u\n", profile_p->syscall_pwrite_bytes); +#ifdef WITH_SENDFILE + d_printf("sendfile_count: %u\n", profile_p->syscall_sendfile_count); + d_printf("sendfile_time: %u\n", profile_p->syscall_sendfile_time); + d_printf("sendfile_bytes: %u\n", profile_p->syscall_sendfile_bytes); +#endif + d_printf("lseek_count: %u\n", profile_p->syscall_lseek_count); + d_printf("lseek_time: %u\n", profile_p->syscall_lseek_time); + d_printf("rename_count: %u\n", profile_p->syscall_rename_count); + d_printf("rename_time: %u\n", profile_p->syscall_rename_time); + d_printf("fsync_count: %u\n", profile_p->syscall_fsync_count); + d_printf("fsync_time: %u\n", profile_p->syscall_fsync_time); + d_printf("stat_count: %u\n", profile_p->syscall_stat_count); + d_printf("stat_time: %u\n", profile_p->syscall_stat_time); + d_printf("fstat_count: %u\n", profile_p->syscall_fstat_count); + d_printf("fstat_time: %u\n", profile_p->syscall_fstat_time); + d_printf("lstat_count: %u\n", profile_p->syscall_lstat_count); + d_printf("lstat_time: %u\n", profile_p->syscall_lstat_time); + d_printf("unlink_count: %u\n", profile_p->syscall_unlink_count); + d_printf("unlink_time: %u\n", profile_p->syscall_unlink_time); + d_printf("chmod_count: %u\n", profile_p->syscall_chmod_count); + d_printf("chmod_time: %u\n", profile_p->syscall_chmod_time); + d_printf("fchmod_count: %u\n", profile_p->syscall_fchmod_count); + d_printf("fchmod_time: %u\n", profile_p->syscall_fchmod_time); + d_printf("chown_count: %u\n", profile_p->syscall_chown_count); + d_printf("chown_time: %u\n", profile_p->syscall_chown_time); + d_printf("fchown_count: %u\n", profile_p->syscall_fchown_count); + d_printf("fchown_time: %u\n", profile_p->syscall_fchown_time); + d_printf("chdir_count: %u\n", profile_p->syscall_chdir_count); + d_printf("chdir_time: %u\n", profile_p->syscall_chdir_time); + d_printf("getwd_count: %u\n", profile_p->syscall_getwd_count); + d_printf("getwd_time: %u\n", profile_p->syscall_getwd_time); + d_printf("utime_count: %u\n", profile_p->syscall_utime_count); + d_printf("utime_time: %u\n", profile_p->syscall_utime_time); + d_printf("ftruncate_count: %u\n", profile_p->syscall_ftruncate_count); + d_printf("ftruncate_time: %u\n", profile_p->syscall_ftruncate_time); + d_printf("fcntl_lock_count: %u\n", profile_p->syscall_fcntl_lock_count); + d_printf("fcntl_lock_time: %u\n", profile_p->syscall_fcntl_lock_time); + d_printf("readlink_count: %u\n", profile_p->syscall_readlink_count); + d_printf("readlink_time: %u\n", profile_p->syscall_readlink_time); + d_printf("symlink_count: %u\n", profile_p->syscall_symlink_count); + d_printf("symlink_time: %u\n", profile_p->syscall_symlink_time); + + profile_separator("Stat Cache"); + d_printf("lookups: %u\n", profile_p->statcache_lookups); + d_printf("misses: %u\n", profile_p->statcache_misses); + d_printf("hits: %u\n", profile_p->statcache_hits); + + profile_separator("Write Cache"); + d_printf("read_hits: %u\n", profile_p->writecache_read_hits); + d_printf("abutted_writes: %u\n", profile_p->writecache_abutted_writes); + d_printf("total_writes: %u\n", profile_p->writecache_total_writes); + d_printf("non_oplock_writes: %u\n", profile_p->writecache_non_oplock_writes); + d_printf("direct_writes: %u\n", profile_p->writecache_direct_writes); + d_printf("init_writes: %u\n", profile_p->writecache_init_writes); + d_printf("flushed_writes[SEEK]: %u\n", profile_p->writecache_flushed_writes[SEEK_FLUSH]); + d_printf("flushed_writes[READ]: %u\n", profile_p->writecache_flushed_writes[READ_FLUSH]); + d_printf("flushed_writes[WRITE]: %u\n", profile_p->writecache_flushed_writes[WRITE_FLUSH]); + d_printf("flushed_writes[READRAW]: %u\n", profile_p->writecache_flushed_writes[READRAW_FLUSH]); + d_printf("flushed_writes[OPLOCK_RELEASE]: %u\n", profile_p->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH]); + d_printf("flushed_writes[CLOSE]: %u\n", profile_p->writecache_flushed_writes[CLOSE_FLUSH]); + d_printf("flushed_writes[SYNC]: %u\n", profile_p->writecache_flushed_writes[SYNC_FLUSH]); + d_printf("flushed_writes[SIZECHANGE]: %u\n", profile_p->writecache_flushed_writes[SIZECHANGE_FLUSH]); + d_printf("num_perfect_writes: %u\n", profile_p->writecache_num_perfect_writes); + d_printf("num_write_caches: %u\n", profile_p->writecache_num_write_caches); + d_printf("allocated_write_caches: %u\n", profile_p->writecache_allocated_write_caches); + + profile_separator("SMB Calls"); + d_printf("mkdir_count: %u\n", profile_p->SMBmkdir_count); + d_printf("mkdir_time: %u\n", profile_p->SMBmkdir_time); + d_printf("rmdir_count: %u\n", profile_p->SMBrmdir_count); + d_printf("rmdir_time: %u\n", profile_p->SMBrmdir_time); + d_printf("open_count: %u\n", profile_p->SMBopen_count); + d_printf("open_time: %u\n", profile_p->SMBopen_time); + d_printf("create_count: %u\n", profile_p->SMBcreate_count); + d_printf("create_time: %u\n", profile_p->SMBcreate_time); + d_printf("close_count: %u\n", profile_p->SMBclose_count); + d_printf("close_time: %u\n", profile_p->SMBclose_time); + d_printf("flush_count: %u\n", profile_p->SMBflush_count); + d_printf("flush_time: %u\n", profile_p->SMBflush_time); + d_printf("unlink_count: %u\n", profile_p->SMBunlink_count); + d_printf("unlink_time: %u\n", profile_p->SMBunlink_time); + d_printf("mv_count: %u\n", profile_p->SMBmv_count); + d_printf("mv_time: %u\n", profile_p->SMBmv_time); + d_printf("getatr_count: %u\n", profile_p->SMBgetatr_count); + d_printf("getatr_time: %u\n", profile_p->SMBgetatr_time); + d_printf("setatr_count: %u\n", profile_p->SMBsetatr_count); + d_printf("setatr_time: %u\n", profile_p->SMBsetatr_time); + d_printf("read_count: %u\n", profile_p->SMBread_count); + d_printf("read_time: %u\n", profile_p->SMBread_time); + d_printf("write_count: %u\n", profile_p->SMBwrite_count); + d_printf("write_time: %u\n", profile_p->SMBwrite_time); + d_printf("lock_count: %u\n", profile_p->SMBlock_count); + d_printf("lock_time: %u\n", profile_p->SMBlock_time); + d_printf("unlock_count: %u\n", profile_p->SMBunlock_count); + d_printf("unlock_time: %u\n", profile_p->SMBunlock_time); + d_printf("ctemp_count: %u\n", profile_p->SMBctemp_count); + d_printf("ctemp_time: %u\n", profile_p->SMBctemp_time); + d_printf("mknew_count: %u\n", profile_p->SMBmknew_count); + d_printf("mknew_time: %u\n", profile_p->SMBmknew_time); + d_printf("chkpth_count: %u\n", profile_p->SMBchkpth_count); + d_printf("chkpth_time: %u\n", profile_p->SMBchkpth_time); + d_printf("exit_count: %u\n", profile_p->SMBexit_count); + d_printf("exit_time: %u\n", profile_p->SMBexit_time); + d_printf("lseek_count: %u\n", profile_p->SMBlseek_count); + d_printf("lseek_time: %u\n", profile_p->SMBlseek_time); + d_printf("lockread_count: %u\n", profile_p->SMBlockread_count); + d_printf("lockread_time: %u\n", profile_p->SMBlockread_time); + d_printf("writeunlock_count: %u\n", profile_p->SMBwriteunlock_count); + d_printf("writeunlock_time: %u\n", profile_p->SMBwriteunlock_time); + d_printf("readbraw_count: %u\n", profile_p->SMBreadbraw_count); + d_printf("readbraw_time: %u\n", profile_p->SMBreadbraw_time); + d_printf("readBmpx_count: %u\n", profile_p->SMBreadBmpx_count); + d_printf("readBmpx_time: %u\n", profile_p->SMBreadBmpx_time); + d_printf("readBs_count: %u\n", profile_p->SMBreadBs_count); + d_printf("readBs_time: %u\n", profile_p->SMBreadBs_time); + d_printf("writebraw_count: %u\n", profile_p->SMBwritebraw_count); + d_printf("writebraw_time: %u\n", profile_p->SMBwritebraw_time); + d_printf("writeBmpx_count: %u\n", profile_p->SMBwriteBmpx_count); + d_printf("writeBmpx_time: %u\n", profile_p->SMBwriteBmpx_time); + d_printf("writeBs_count: %u\n", profile_p->SMBwriteBs_count); + d_printf("writeBs_time: %u\n", profile_p->SMBwriteBs_time); + d_printf("writec_count: %u\n", profile_p->SMBwritec_count); + d_printf("writec_time: %u\n", profile_p->SMBwritec_time); + d_printf("setattrE_count: %u\n", profile_p->SMBsetattrE_count); + d_printf("setattrE_time: %u\n", profile_p->SMBsetattrE_time); + d_printf("getattrE_count: %u\n", profile_p->SMBgetattrE_count); + d_printf("getattrE_time: %u\n", profile_p->SMBgetattrE_time); + d_printf("lockingX_count: %u\n", profile_p->SMBlockingX_count); + d_printf("lockingX_time: %u\n", profile_p->SMBlockingX_time); + d_printf("trans_count: %u\n", profile_p->SMBtrans_count); + d_printf("trans_time: %u\n", profile_p->SMBtrans_time); + d_printf("transs_count: %u\n", profile_p->SMBtranss_count); + d_printf("transs_time: %u\n", profile_p->SMBtranss_time); + d_printf("ioctl_count: %u\n", profile_p->SMBioctl_count); + d_printf("ioctl_time: %u\n", profile_p->SMBioctl_time); + d_printf("ioctls_count: %u\n", profile_p->SMBioctls_count); + d_printf("ioctls_time: %u\n", profile_p->SMBioctls_time); + d_printf("copy_count: %u\n", profile_p->SMBcopy_count); + d_printf("copy_time: %u\n", profile_p->SMBcopy_time); + d_printf("move_count: %u\n", profile_p->SMBmove_count); + d_printf("move_time: %u\n", profile_p->SMBmove_time); + d_printf("echo_count: %u\n", profile_p->SMBecho_count); + d_printf("echo_time: %u\n", profile_p->SMBecho_time); + d_printf("writeclose_count: %u\n", profile_p->SMBwriteclose_count); + d_printf("writeclose_time: %u\n", profile_p->SMBwriteclose_time); + d_printf("openX_count: %u\n", profile_p->SMBopenX_count); + d_printf("openX_time: %u\n", profile_p->SMBopenX_time); + d_printf("readX_count: %u\n", profile_p->SMBreadX_count); + d_printf("readX_time: %u\n", profile_p->SMBreadX_time); + d_printf("writeX_count: %u\n", profile_p->SMBwriteX_count); + d_printf("writeX_time: %u\n", profile_p->SMBwriteX_time); + d_printf("trans2_count: %u\n", profile_p->SMBtrans2_count); + d_printf("trans2_time: %u\n", profile_p->SMBtrans2_time); + d_printf("transs2_count: %u\n", profile_p->SMBtranss2_count); + d_printf("transs2_time: %u\n", profile_p->SMBtranss2_time); + d_printf("findclose_count: %u\n", profile_p->SMBfindclose_count); + d_printf("findclose_time: %u\n", profile_p->SMBfindclose_time); + d_printf("findnclose_count: %u\n", profile_p->SMBfindnclose_count); + d_printf("findnclose_time: %u\n", profile_p->SMBfindnclose_time); + d_printf("tcon_count: %u\n", profile_p->SMBtcon_count); + d_printf("tcon_time: %u\n", profile_p->SMBtcon_time); + d_printf("tdis_count: %u\n", profile_p->SMBtdis_count); + d_printf("tdis_time: %u\n", profile_p->SMBtdis_time); + d_printf("negprot_count: %u\n", profile_p->SMBnegprot_count); + d_printf("negprot_time: %u\n", profile_p->SMBnegprot_time); + d_printf("sesssetupX_count: %u\n", profile_p->SMBsesssetupX_count); + d_printf("sesssetupX_time: %u\n", profile_p->SMBsesssetupX_time); + d_printf("ulogoffX_count: %u\n", profile_p->SMBulogoffX_count); + d_printf("ulogoffX_time: %u\n", profile_p->SMBulogoffX_time); + d_printf("tconX_count: %u\n", profile_p->SMBtconX_count); + d_printf("tconX_time: %u\n", profile_p->SMBtconX_time); + d_printf("dskattr_count: %u\n", profile_p->SMBdskattr_count); + d_printf("dskattr_time: %u\n", profile_p->SMBdskattr_time); + d_printf("search_count: %u\n", profile_p->SMBsearch_count); + d_printf("search_time: %u\n", profile_p->SMBsearch_time); + d_printf("ffirst_count: %u\n", profile_p->SMBffirst_count); + d_printf("ffirst_time: %u\n", profile_p->SMBffirst_time); + d_printf("funique_count: %u\n", profile_p->SMBfunique_count); + d_printf("funique_time: %u\n", profile_p->SMBfunique_time); + d_printf("fclose_count: %u\n", profile_p->SMBfclose_count); + d_printf("fclose_time: %u\n", profile_p->SMBfclose_time); + d_printf("nttrans_count: %u\n", profile_p->SMBnttrans_count); + d_printf("nttrans_time: %u\n", profile_p->SMBnttrans_time); + d_printf("nttranss_count: %u\n", profile_p->SMBnttranss_count); + d_printf("nttranss_time: %u\n", profile_p->SMBnttranss_time); + d_printf("ntcreateX_count: %u\n", profile_p->SMBntcreateX_count); + d_printf("ntcreateX_time: %u\n", profile_p->SMBntcreateX_time); + d_printf("ntcancel_count: %u\n", profile_p->SMBntcancel_count); + d_printf("ntcancel_time: %u\n", profile_p->SMBntcancel_time); + d_printf("splopen_count: %u\n", profile_p->SMBsplopen_count); + d_printf("splopen_time: %u\n", profile_p->SMBsplopen_time); + d_printf("splwr_count: %u\n", profile_p->SMBsplwr_count); + d_printf("splwr_time: %u\n", profile_p->SMBsplwr_time); + d_printf("splclose_count: %u\n", profile_p->SMBsplclose_count); + d_printf("splclose_time: %u\n", profile_p->SMBsplclose_time); + d_printf("splretq_count: %u\n", profile_p->SMBsplretq_count); + d_printf("splretq_time: %u\n", profile_p->SMBsplretq_time); + d_printf("sends_count: %u\n", profile_p->SMBsends_count); + d_printf("sends_time: %u\n", profile_p->SMBsends_time); + d_printf("sendb_count: %u\n", profile_p->SMBsendb_count); + d_printf("sendb_time: %u\n", profile_p->SMBsendb_time); + d_printf("fwdname_count: %u\n", profile_p->SMBfwdname_count); + d_printf("fwdname_time: %u\n", profile_p->SMBfwdname_time); + d_printf("cancelf_count: %u\n", profile_p->SMBcancelf_count); + d_printf("cancelf_time: %u\n", profile_p->SMBcancelf_time); + d_printf("getmac_count: %u\n", profile_p->SMBgetmac_count); + d_printf("getmac_time: %u\n", profile_p->SMBgetmac_time); + d_printf("sendstrt_count: %u\n", profile_p->SMBsendstrt_count); + d_printf("sendstrt_time: %u\n", profile_p->SMBsendstrt_time); + d_printf("sendend_count: %u\n", profile_p->SMBsendend_count); + d_printf("sendend_time: %u\n", profile_p->SMBsendend_time); + d_printf("sendtxt_count: %u\n", profile_p->SMBsendtxt_count); + d_printf("sendtxt_time: %u\n", profile_p->SMBsendtxt_time); + d_printf("invalid_count: %u\n", profile_p->SMBinvalid_count); + d_printf("invalid_time: %u\n", profile_p->SMBinvalid_time); + + profile_separator("Pathworks Calls"); + d_printf("setdir_count: %u\n", profile_p->pathworks_setdir_count); + d_printf("setdir_time: %u\n", profile_p->pathworks_setdir_time); + + profile_separator("Trans2 Calls"); + d_printf("open_count: %u\n", profile_p->Trans2_open_count); + d_printf("open_time: %u\n", profile_p->Trans2_open_time); + d_printf("findfirst_count: %u\n", profile_p->Trans2_findfirst_count); + d_printf("findfirst_time: %u\n", profile_p->Trans2_findfirst_time); + d_printf("findnext_count: %u\n", profile_p->Trans2_findnext_count); + d_printf("findnext_time: %u\n", profile_p->Trans2_findnext_time); + d_printf("qfsinfo_count: %u\n", profile_p->Trans2_qfsinfo_count); + d_printf("qfsinfo_time: %u\n", profile_p->Trans2_qfsinfo_time); + d_printf("setfsinfo_count: %u\n", profile_p->Trans2_setfsinfo_count); + d_printf("setfsinfo_time: %u\n", profile_p->Trans2_setfsinfo_time); + d_printf("qpathinfo_count: %u\n", profile_p->Trans2_qpathinfo_count); + d_printf("qpathinfo_time: %u\n", profile_p->Trans2_qpathinfo_time); + d_printf("setpathinfo_count: %u\n", profile_p->Trans2_setpathinfo_count); + d_printf("setpathinfo_time: %u\n", profile_p->Trans2_setpathinfo_time); + d_printf("qfileinfo_count: %u\n", profile_p->Trans2_qfileinfo_count); + d_printf("qfileinfo_time: %u\n", profile_p->Trans2_qfileinfo_time); + d_printf("setfileinfo_count: %u\n", profile_p->Trans2_setfileinfo_count); + d_printf("setfileinfo_time: %u\n", profile_p->Trans2_setfileinfo_time); + d_printf("fsctl_count: %u\n", profile_p->Trans2_fsctl_count); + d_printf("fsctl_time: %u\n", profile_p->Trans2_fsctl_time); + d_printf("ioctl_count: %u\n", profile_p->Trans2_ioctl_count); + d_printf("ioctl_time: %u\n", profile_p->Trans2_ioctl_time); + d_printf("findnotifyfirst_count: %u\n", profile_p->Trans2_findnotifyfirst_count); + d_printf("findnotifyfirst_time: %u\n", profile_p->Trans2_findnotifyfirst_time); + d_printf("findnotifynext_count: %u\n", profile_p->Trans2_findnotifynext_count); + d_printf("findnotifynext_time: %u\n", profile_p->Trans2_findnotifynext_time); + d_printf("mkdir_count: %u\n", profile_p->Trans2_mkdir_count); + d_printf("mkdir_time: %u\n", profile_p->Trans2_mkdir_time); + d_printf("session_setup_count: %u\n", profile_p->Trans2_session_setup_count); + d_printf("session_setup_time: %u\n", profile_p->Trans2_session_setup_time); + d_printf("get_dfs_referral_count: %u\n", profile_p->Trans2_get_dfs_referral_count); + d_printf("get_dfs_referral_time: %u\n", profile_p->Trans2_get_dfs_referral_time); + d_printf("report_dfs_inconsistancy_count: %u\n", profile_p->Trans2_report_dfs_inconsistancy_count); + d_printf("report_dfs_inconsistancy_time: %u\n", profile_p->Trans2_report_dfs_inconsistancy_time); + + profile_separator("NT Transact Calls"); + d_printf("create_count: %u\n", profile_p->NT_transact_create_count); + d_printf("create_time: %u\n", profile_p->NT_transact_create_time); + d_printf("ioctl_count: %u\n", profile_p->NT_transact_ioctl_count); + d_printf("ioctl_time: %u\n", profile_p->NT_transact_ioctl_time); + d_printf("set_security_desc_count: %u\n", profile_p->NT_transact_set_security_desc_count); + d_printf("set_security_desc_time: %u\n", profile_p->NT_transact_set_security_desc_time); + d_printf("notify_change_count: %u\n", profile_p->NT_transact_notify_change_count); + d_printf("notify_change_time: %u\n", profile_p->NT_transact_notify_change_time); + d_printf("rename_count: %u\n", profile_p->NT_transact_rename_count); + d_printf("rename_time: %u\n", profile_p->NT_transact_rename_time); + d_printf("query_security_desc_count: %u\n", profile_p->NT_transact_query_security_desc_count); + d_printf("query_security_desc_time: %u\n", profile_p->NT_transact_query_security_desc_time); + + profile_separator("ACL Calls"); + d_printf("get_nt_acl_count: %u\n", profile_p->get_nt_acl_count); + d_printf("get_nt_acl_time: %u\n", profile_p->get_nt_acl_time); + d_printf("fget_nt_acl_count: %u\n", profile_p->fget_nt_acl_count); + d_printf("fget_nt_acl_time: %u\n", profile_p->fget_nt_acl_time); + d_printf("set_nt_acl_count: %u\n", profile_p->set_nt_acl_count); + d_printf("set_nt_acl_time: %u\n", profile_p->set_nt_acl_time); + d_printf("fset_nt_acl_count: %u\n", profile_p->fset_nt_acl_count); + d_printf("fset_nt_acl_time: %u\n", profile_p->fset_nt_acl_time); + d_printf("chmod_acl_count: %u\n", profile_p->chmod_acl_count); + d_printf("chmod_acl_time: %u\n", profile_p->chmod_acl_time); + d_printf("fchmod_acl_count: %u\n", profile_p->fchmod_acl_count); + d_printf("fchmod_acl_time: %u\n", profile_p->fchmod_acl_time); + + profile_separator("NMBD Calls"); + d_printf("name_release_count: %u\n", profile_p->name_release_count); + d_printf("name_release_time: %u\n", profile_p->name_release_time); + d_printf("name_refresh_count: %u\n", profile_p->name_refresh_count); + d_printf("name_refresh_time: %u\n", profile_p->name_refresh_time); + d_printf("name_registration_count: %u\n", profile_p->name_registration_count); + d_printf("name_registration_time: %u\n", profile_p->name_registration_time); + d_printf("node_status_count: %u\n", profile_p->node_status_count); + d_printf("node_status_time: %u\n", profile_p->node_status_time); + d_printf("name_query_count: %u\n", profile_p->name_query_count); + d_printf("name_query_time: %u\n", profile_p->name_query_time); + d_printf("host_announce_count: %u\n", profile_p->host_announce_count); + d_printf("host_announce_time: %u\n", profile_p->host_announce_time); + d_printf("workgroup_announce_count: %u\n", profile_p->workgroup_announce_count); + d_printf("workgroup_announce_time: %u\n", profile_p->workgroup_announce_time); + d_printf("local_master_announce_count: %u\n", profile_p->local_master_announce_count); + d_printf("local_master_announce_time: %u\n", profile_p->local_master_announce_time); + d_printf("master_browser_announce_count: %u\n", profile_p->master_browser_announce_count); + d_printf("master_browser_announce_time: %u\n", profile_p->master_browser_announce_time); + d_printf("lm_host_announce_count: %u\n", profile_p->lm_host_announce_count); + d_printf("lm_host_announce_time: %u\n", profile_p->lm_host_announce_time); + d_printf("get_backup_list_count: %u\n", profile_p->get_backup_list_count); + d_printf("get_backup_list_time: %u\n", profile_p->get_backup_list_time); + d_printf("reset_browser_count: %u\n", profile_p->reset_browser_count); + d_printf("reset_browser_time: %u\n", profile_p->reset_browser_time); + d_printf("announce_request_count: %u\n", profile_p->announce_request_count); + d_printf("announce_request_time: %u\n", profile_p->announce_request_time); + d_printf("lm_announce_request_count: %u\n", profile_p->lm_announce_request_count); + d_printf("lm_announce_request_time: %u\n", profile_p->lm_announce_request_time); + d_printf("domain_logon_count: %u\n", profile_p->domain_logon_count); + d_printf("domain_logon_time: %u\n", profile_p->domain_logon_time); + d_printf("sync_browse_lists_count: %u\n", profile_p->sync_browse_lists_count); + d_printf("sync_browse_lists_time: %u\n", profile_p->sync_browse_lists_time); + d_printf("run_elections_count: %u\n", profile_p->run_elections_count); + d_printf("run_elections_time: %u\n", profile_p->run_elections_time); + d_printf("election_count: %u\n", profile_p->election_count); + d_printf("election_time: %u\n", profile_p->election_time); +#else /* WITH_PROFILE */ + fprintf(stderr, "Profile data unavailable\n"); +#endif /* WITH_PROFILE */ + + return True; +} + +#ifdef WITH_PROFILE + +static void sample_delay(int delay_msec) +{ + poll(NULL, 0, delay_msec); +} + +/* Convert microseconds to milliseconds. */ +#define usec_to_msec(s) ((s) / 1000) +/* Convert microseconds to seconds. */ +#define usec_to_sec(s) ((s) / 1000000) +/* One second in microseconds. */ +#define one_second_usec (1000000) + +#define sample_interval_usec one_second_usec + +#define percent_time(used, period) ((double)(used) / (double)(period) * 100.0 ) + +static int print_count_samples( + const struct profile_stats * const current, + const struct profile_stats * const last, + SMB_BIG_UINT delta_usec) +{ + int i; + int count = 0; + unsigned step; + SMB_BIG_UINT spent; + int delta_sec; + const char * name; + char buf[40]; + + if (delta_usec == 0) { + return 0; + } + + buf[0] = '\0'; + delta_sec = usec_to_sec(delta_usec); + + for (i = 0; i < PR_VALUE_MAX; ++i) { + step = current->count[i] - last->count[i]; + spent = current->time[i] - last->time[i]; + + if (step) { + ++count; + + name = profile_value_name(i); + + if (buf[0] == '\0') { + snprintf(buf, sizeof(buf), + "%s %d/sec (%.2f%%)", + name, step / delta_sec, + percent_time(spent, delta_usec)); + } else { + printf("%-40s %s %d/sec (%.2f%%)\n", + buf, name, step / delta_sec, + percent_time(spent, delta_usec)); + buf[0] = '\0'; + } + } + } + + return count; +} + +static struct profile_stats sample_data[2]; +static SMB_BIG_UINT sample_time[2]; + +BOOL status_profile_rates(BOOL verbose) +{ + SMB_BIG_UINT remain_usec; + SMB_BIG_UINT next_usec; + SMB_BIG_UINT delta_usec; + + int last = 0; + int current = 1; + int tmp; + + if (verbose) { + fprintf(stderr, "Sampling stats at %d sec intervals\n", + usec_to_sec(sample_interval_usec)); + } + + if (!profile_setup(True)) { + fprintf(stderr,"Failed to initialise profile memory\n"); + return False; + } + + memcpy(&sample_data[last], profile_p, sizeof(*profile_p)); + for (;;) { + sample_time[current] = profile_timestamp(); + next_usec = sample_time[current] + sample_interval_usec; + + /* Take a sample. */ + memcpy(&sample_data[current], profile_p, sizeof(*profile_p)); + + /* Rate convert some values and print results. */ + delta_usec = sample_time[current] - sample_time[last]; + + if (print_count_samples(&sample_data[current], + &sample_data[last], delta_usec)) { + printf("\n"); + } + + /* Swap sampling buffers. */ + tmp = last; + last = current; + current = tmp; + + /* Delay until next sample time. */ + remain_usec = next_usec - profile_timestamp(); + if (remain_usec > sample_interval_usec) { + fprintf(stderr, "eek! falling behind sampling rate!\n"); + } else { + if (verbose) { + fprintf(stderr, + "delaying for %lu msec\n", + (unsigned long )usec_to_msec(remain_usec)); + } + + sample_delay(usec_to_msec(remain_usec)); + } + + } + + return True; +} + +#else /* WITH_PROFILE */ + +BOOL status_profile_rates(BOOL verbose) +{ + fprintf(stderr, "Profile data unavailable\n"); + return False; +} + +#endif /* WITH_PROFILE */ + diff --git a/source/web/diagnose.c b/source/web/diagnose.c index d259717da0b..b53e139ca94 100644 --- a/source/web/diagnose.c +++ b/source/web/diagnose.c @@ -60,16 +60,16 @@ BOOL nmbd_running(void) then closing it */ BOOL smbd_running(void) { - static struct cli_state cli; + struct cli_state *cli; - if (!cli_initialise(&cli)) + if ((cli = cli_initialise()) == NULL) return False; - if (!cli_connect(&cli, global_myname(), &loopback_ip)) { - cli_shutdown(&cli); + if (!cli_connect(cli, global_myname(), &loopback_ip)) { + cli_shutdown(cli); return False; } - cli_shutdown(&cli); + cli_shutdown(cli); return True; } diff --git a/source/web/neg_lang.c b/source/web/neg_lang.c index fb79f41f13c..207614655db 100644 --- a/source/web/neg_lang.c +++ b/source/web/neg_lang.c @@ -57,8 +57,8 @@ static int qsort_cmp_list(const void *x, const void *y) { struct pri_list *a = (struct pri_list *)x; struct pri_list *b = (struct pri_list *)y; if (a->pri > b->pri) return -1; - if (a->pri == b->pri) return 0; - return 1; + if (a->pri < b->pri) return 1; + return 0; } /* diff --git a/source/web/swat.c b/source/web/swat.c index d1fd0b4f9bc..d43f8941bc1 100644 --- a/source/web/swat.c +++ b/source/web/swat.c @@ -432,7 +432,7 @@ static void write_config(FILE *f, BOOL show_defaults) { fprintf(f, "# Samba config file created using SWAT\n"); fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr()); - fprintf(f, "# Date: %s\n\n", timestring(False)); + fprintf(f, "# Date: %s\n\n", current_timestring(False)); lp_dump(f, show_defaults, iNumNonAutoPrintServices); } |