--- config.h.in 2008-08-25 16:16:23.000000000 -0500 +++ samba-3.0.32/source/include/config.h.in 2008-09-10 11:18:07.000000000 -0500 @@ -2484,6 +2484,9 @@ /* Whether to use disk quota support */ #undef WITH_QUOTAS +/* Whether to include Sun samfs support */ +#undef WITH_SAMFS + /* Whether to include sendfile() support */ #undef WITH_SENDFILE --- configure.in-1st Thu Sep 11 07:28:09 2008 +++ samba-3.0.32/source/configure.in Thu Sep 11 17:42:40 2008 @@ -305,6 +305,7 @@ AC_SUBST(KRB5_LIBS) AC_SUBST(UUID_LIBS) AC_SUBST(LDAP_LIBS) +AC_SUBST(SAMFS_LIBS) AC_SUBST(PAM_MODULES) AC_SUBST(INSTALL_PAM_MODULES) AC_SUBST(UNINSTALL_PAM_MODULES) @@ -5494,6 +5495,28 @@ ) ################################################# +# check for samfs support + +#with_samfs_support=no +AC_MSG_CHECKING(whether to support samfs) +AC_ARG_WITH(samfs-support, +[ --with-samfs-support Include Solaris SamFS support (default=no)], +[ case "$withval" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(WITH_SAMFS,1,[Whether to include Sun SamFS support]) + SAMFS_LIBS="-R/opt/SUNWsamfs/lib -zlazyload -lsam -znolazyload" + ;; + *) + AC_MSG_RESULT(no) + SAMFS_LIBS="" + ;; + esac ], + AC_MSG_RESULT(no) +) + + +################################################# # check for sendfile support with_sendfile_support=yes --- includes.h Thu Sep 11 08:04:14 2008 +++ samba-3.0.32/source/include/includes.h Thu Sep 11 08:13:28 2008 @@ -216,6 +216,31 @@ #include #endif +#ifdef WITH_SAMFS +/* Michael Adam : sun samfs stuff + * should be included after sys/stat.h but this breaks compilation + * since some macros are undefined, some redefined differently. + * so I undo some defines done by samfs stat.h */ + +#include +/* repare samfs-stat.h */ +#undef S_ISUID +#define S_ISUID 0x800 /* set user id on execution */ +#undef S_ISGID +#define S_ISGID 0x400 /* set group id on execution */ + +#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE) || \ + defined(__EXTENSIONS__) +#define st_atime st_atim.tv_sec +#define st_mtime st_mtim.tv_sec +#define st_ctime st_ctim.tv_sec +#else +#define st_atime st_atim.__tv_sec +#define st_mtime st_mtim.__tv_sec +#define st_ctime st_ctim.__tv_sec +#endif /* !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE) || ... */ +#endif /* defined WITH_SAMFS */ + #if HAVE_COM_ERR_H #include #endif --- makefile.in-1st Thu Sep 11 07:49:05 2008 +++ samba-3.0.32/source/Makefile.in Thu Sep 11 08:00:55 2008 @@ -42,6 +42,7 @@ IDMAP_LIBS=@IDMAP_LIBS@ KRB5LIBS=@KRB5_LIBS@ LDAP_LIBS=@LDAP_LIBS@ +SAMFS_LIBS=@SAMFS_LIBS@ NSCD_LIBS=@NSCD_LIBS@ UUID_LIBS=@UUID_LIBS@ @@ -235,6 +236,8 @@ TALLOC_OBJ = lib/talloc/talloc.o +SAMFS_OBJ = smbd/samfs.o + LIB_WITHOUT_PROTO_OBJ = $(LIBREPLACE_OBJ) $(SOCKET_WRAPPER_OBJ) $(TALLOC_OBJ) LIB_WITH_PROTO_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \ @@ -474,6 +477,7 @@ smbd/change_trust_pw.o smbd/fake_file.o \ smbd/quotas.o smbd/ntquotas.o $(AFS_OBJ) smbd/msdfs.o \ $(AFS_SETTOKEN_OBJ) smbd/aio.o smbd/statvfs.o \ + $(SAMFS_OBJ) \ smbd/dmapi.o $(MANGLE_OBJ) @VFS_STATIC@ SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \ @@ -966,7 +970,8 @@ @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \ $(KRB5LIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \ - $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@ @SMBD_LIBS@ + $(ACL_LIBS) $(PASSDB_LIBS) $(SAMFS_LIBS) \ + $(LIBS) @POPTLIBS@ @SMBD_LIBS@ bin/nmbd@EXEEXT@: proto_exists $(NMBD_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ --- loadparm.c Thu Sep 11 08:19:03 2008 +++ samba-3.0.32/source/param/loadparm.c Thu Sep 11 08:24:32 2008 @@ -449,6 +449,7 @@ BOOL bProfileAcls; BOOL bMap_acl_inherit; BOOL bAfs_Share; + BOOL bSamfs_Share; BOOL bEASupport; BOOL bAclCheckPermissions; BOOL bAclMapFullControl; @@ -592,6 +593,7 @@ False, /* bProfileAcls */ False, /* bMap_acl_inherit */ False, /* bAfs_Share */ + False, /* bSamfs_Share */ False, /* bEASupport */ True, /* bAclCheckPermissions */ True, /* bAclMapFullControl */ @@ -1015,6 +1017,7 @@ {"enable asu support", P_BOOL, P_GLOBAL, &Globals.bASUSupport, NULL, NULL, FLAG_ADVANCED}, {"svcctl list", P_LIST, P_GLOBAL, &Globals.szServicesList, NULL, NULL, FLAG_ADVANCED}, + {"samfs share", P_BOOL, P_LOCAL, &sDefault.bSamfs_Share, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, {N_("Tuning Options"), P_SEP, P_SEPARATOR}, @@ -2137,6 +2140,7 @@ FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls) FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit) FN_LOCAL_BOOL(lp_afs_share, bAfs_Share) +FN_LOCAL_BOOL(lp_samfs_share, bSamfs_Share) FN_LOCAL_BOOL(lp_acl_check_permissions, bAclCheckPermissions) FN_LOCAL_BOOL(lp_acl_group_control, bAclGroupControl) FN_LOCAL_BOOL(lp_acl_map_full_control, bAclMapFullControl) --- dosmode.c Thu Sep 11 08:26:11 2008 +++ samba-3.0.32/source/smbd/dosmode.c Thu Sep 11 08:27:43 2008 @@ -406,6 +406,8 @@ result |= aHIDDEN; } + result |= samfs_mode(conn, path); + DEBUG(8,("dos_mode returning ")); if (result & aHIDDEN) DEBUG(8, ("h")); @@ -414,6 +416,7 @@ if (result & aDIR ) DEBUG(8, ("d")); if (result & aARCH ) DEBUG(8, ("a")); if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]")); + if (result & FILE_ATTRIBUTE_OFFLINE ) DEBUG(8, ("[offline]")); DEBUG(8,("\n")); @@ -463,6 +466,15 @@ return(0); } + if (samfs_make_file_worm(conn, fname, st, dosmode)) { + DEBUG(5,("file_set_dosmode: samfs_make_file worm tells "\ + "me to use mode 0%o on file %s\n", unixmode, fname)); + unixmode = S_ISUID; + /* I'm doing a direct chmod call here because SMB_VFS_CHMOD + * uses chmod_acl and this drops the SUID flag... */ + return chmod(fname, unixmode); + } + /* Store the DOS attributes in an EA by preference. */ if (set_ea_dos_attribute(conn, fname, st, dosmode)) { st->st_mode = unixmode; --- samfs.c Mon Sep 22 19:58:36 2008 +++ samba-3.0.32/source/smbd/samfs.c Mon Sep 22 19:51:51 2008 @@ -1,0 +1,211 @@ +/* + Unix SMB/CIFS implementation. + Solaris SamFS handling functions. + Copyright (C) Michael Adam 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" + +/* + This module implements a mapping of the Solaris SamFS Offline + and WORM flags to dos-modes: + + - The offline flag is read from samfs_stat call and if set, + the FILE_ATTRIBUTE_OFFLINE is added to the dosmode. + + - The offline flag can not be set by a samba-client. + This is done by the releaser daemon. + + - The WORM flag ist mapped bidirectionally to the system+readonly + dosmode flags. + + */ + +#ifdef WITH_SAMFS + +#define WORM_TRIGGER (aRONLY|aSYSTEM) + +static BOOL samfs_worm_capable(const char *path, SMB_STRUCT_STAT *st); + +/******************************************************************* + Get samfs flags from samfs stat call (offline and WORM) + and map them to dos mode flags. +*******************************************************************/ +uint32 samfs_mode(connection_struct *conn, const char *path) +{ + struct sam_stat file_info; + struct sam_stat *segment_info; + int num_segs; + int num_segs_offline; + int i; + int sam_stat_result; + uint32 mode = 0; + pstring pathreal; + + if (!lp_samfs_share(SNUM(conn))) { + DEBUG(5,("samfs_mode: share '%s' is not a samfs share\n", + lp_servicename(SNUM(conn)))); + goto SAMFS_MODE_EXIT; + } + + pstrcpy(pathreal,path); + canonicalize_path(conn, pathreal); + DEBUG(8,("samfs_mode: conn->dirpath '%s', fname '%s', pathreal '%s'\n", + conn->dirpath, path, pathreal)); + + DEBUG(5,("samfs_mode: testing sam_stat properties of file %s\n", + pathreal)); + + ZERO_STRUCT(file_info); + sam_stat_result = sam_stat(pathreal, &file_info, sizeof(struct sam_stat)); + if (sam_stat_result != 0) { + DEBUG(5,("samfs_mode: " \ + "sam_stat call on file %s returned " \ + "with error code %d\n", + pathreal, sam_stat_result)); + goto SAMFS_MODE_EXIT; + + } + if (SS_ISOFFLINE(file_info.attr)) { + DEBUG(5,("samfs_mode: file %s is offline\n", pathreal)); + mode |= FILE_ATTRIBUTE_OFFLINE; + } + if (SS_ISREADONLY(file_info.attr)) { + DEBUG(5,("samfs_mode: file %s is a WORM file\n", pathreal)); + mode |= WORM_TRIGGER; + } + if (SS_ISSEGMENT_F(file_info.attr)) { + DEBUG(5,("samfs_mode: file %s is segmented\n", pathreal)); + num_segs = NUM_SEGS(&file_info); + printf("segmented (%d segments)\n", num_segs); + segment_info = (struct sam_stat *)malloc(num_segs * + sizeof(struct sam_stat)); + if (segment_info == NULL) { + DEBUG(5, ("samfs_mode: error allocating memory for " \ + "data segment stat info\n")); + } + memset((void *)segment_info, 0, + num_segs * sizeof(struct sam_stat)); + sam_stat_result = sam_segment_stat(pathreal, segment_info, + num_segs * sizeof(struct sam_stat)); + if (sam_stat_result != 0) { + DEBUG(5,("samfs_mode: ERROR %d returned from " \ + "sam_segment_stat\n", sam_stat_result)); + } + num_segs_offline = 0; + for (i=0; i < num_segs; i++) { + if (SS_ISOFFLINE(segment_info[i].attr)) { + num_segs_offline++; + } + } + if (num_segs_offline) { + DEBUG(5,("samfs_stat: offline (%d segments offline)\n", + num_segs_offline)); + mode |= FILE_ATTRIBUTE_OFFLINE; + } + SAFE_FREE(segment_info); + } +SAMFS_MODE_EXIT: + DEBUG(5,("samfs_mode: returning 0x%x\n", mode)); + return mode; +} + +/******************************************************************* + Check if the resulting mode triggers the convert-to-WORM action. +*******************************************************************/ +BOOL samfs_make_file_worm(connection_struct *conn, const char *path, + SMB_STRUCT_STAT *st, uint32 dosmode) +{ + pstring pathreal; + + pstrcpy(pathreal,path); + canonicalize_path(conn, pathreal); + + if (!lp_samfs_share(SNUM(conn))) { + DEBUG(5,("samfs_mode: '%s' is not a samfs share\n", + lp_servicename(SNUM(conn)))); + return False; + } + + DEBUG(8,("samfs_make_file_worm: called with dosmode 0x%x for file %s\n", + dosmode, path)); + + if (!(dosmode & aDIR) && !samfs_worm_capable(pathreal, st)) { + DEBUG(8,("samfs_make_worm_file: %s is not worm capable\n", + pathreal)); + return False; + } + + if ((dosmode & WORM_TRIGGER) != WORM_TRIGGER) { + DEBUG(8,("samfs_make_worm_file: dos mode 0x%x " \ + "does not trigger WORM status\n", + dosmode)); + return False; + } + DEBUG(8,("samfs_make_file_worm: WORM status triggered for file %s\n", + path)); + return True; +} + +/******************************************************************* + Check if file is worm capable. + (File is worm capable if parent dir is worm.) +*******************************************************************/ +static BOOL samfs_worm_capable(const char *path, SMB_STRUCT_STAT *st) +{ + struct sam_stat file_info; + int sam_stat_result; + char *parent_dir = parent_dirname(path); + + if (S_ISDIR(st->st_mode)) { + return True; + } + + ZERO_STRUCT(file_info); + sam_stat_result = sam_stat(parent_dir, &file_info, + sizeof(struct sam_stat)); + if (sam_stat_result != 0) { + DEBUG(5,("samfs_worm_capable: " \ + "sam_stat call on file %s returned " \ + "with error code %d\n", + parent_dir, sam_stat_result)); + return False; + } + if (SS_ISREADONLY(file_info.attr)) { + return True; + } + return False; +} + +#else /* defined WITH_SAMFS */ + +/* provide stubs for configure without "--with-samfs-support" */ + +uint32 samfs_mode(connection_struct *conn, const char *path) +{ + return 0; +} + +BOOL samfs_make_file_worm(connection_struct *conn, const char *path, + SMB_STRUCT_STAT *st, uint32 dosmode) +{ + return False; +} + +#endif + +/* END smbd/samfs.c */ --- service.c Wed Sep 17 17:17:30 2008 +++ samba-3.0.32/source/smbd/service.c Wed Sep 17 17:18:32 2008 @@ -22,7 +22,7 @@ extern userdom_struct current_user_info; -static BOOL canonicalize_path(connection_struct *conn, pstring path) +BOOL canonicalize_path(connection_struct *conn, pstring path) { #ifdef REALPATH_TAKES_NULL char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL);