configure-list-all-volumes   [plain text]


Index: samba/source/smbd/service.c
===================================================================
--- samba/source/smbd/service.c.orig
+++ samba/source/smbd/service.c
@@ -249,7 +249,7 @@ int add_home_service(const char *service
 	if (!lp_add_home(service, iHomeService, username, homedir)) {
 		return -1;
 	}
-	
+
 	return lp_servicenumber(service);
 
 }
@@ -288,6 +288,11 @@ int find_service(fstring service)
 		iService = add_home_service(service,service /* 'username' */, phome_dir);
 	}
 
+	if (iService < 0 && lp_parm_bool(GLOBAL_SECTION_SNUM, "com.apple",
+					    "show admin all volumes", False)) {
+		iService = apple_clone_local_volumes(service);
+	}
+
 	/* If we still don't have a service, attempt to add it as a printer. */
 	if (iService < 0) {
 		int iPrinterService;
Index: samba/source/smbd/darwin_clone_local_volumes.c
===================================================================
--- /dev/null
+++ samba/source/smbd/darwin_clone_local_volumes.c
@@ -0,0 +1,159 @@
+/*
+ * Darwin Show all volumes for admin users
+ *
+ * Copyright (c) 2007-2008 Apple Inc. All rights reserved.
+ *
+ * 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 header has to be here due to preprocessor conflicts with Samba
+ * headers.
+ */
+#include "includes.h"
+#include "smb_macros.h"
+#include <sys/attr.h>
+
+#define APPLE_SLASH_VOLUMES "/Volumes"
+
+/*
+ * We have a path to a mounted volume, use getattrlist to get its real name. If
+ * we fail then just use the last component of the path name.
+ */
+static void get_volume_name(const char *path, char *volname)
+{
+	struct attrlist attrlist;
+	char attrbuf[sizeof(struct attrreference) + sizeof(u_int32_t) + NAME_MAX + 1];
+	struct attrreference * data = (struct attrreference *)attrbuf;
+	u_int32_t *nmlen;
+	char *name = NULL;
+	int len, maxlen;
+
+	ZERO_STRUCT(attrlist);
+	ZERO_STRUCT(attrbuf);
+	attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
+	attrlist.commonattr = ATTR_CMN_NAME;
+	/* Call getattrlist to get the real volume name */
+	if (getattrlist(path, &attrlist, attrbuf, sizeof(attrbuf), 0) != 0) {
+		DEBUG(5, ("getattrlist for %s failed: %s\n", path, strerror(errno)));
+		return;
+	}
+	/* Make sure we didn't get something bad */
+	maxlen = data->attr_dataoffset - (sizeof(struct attrreference) +  sizeof(u_int32_t));
+	nmlen = (u_int32_t *)(attrbuf+sizeof(struct attrreference));
+	/* Should never happen, but just to be safe */
+	if (*nmlen > maxlen) {
+		DEBUG(5, ("name length to large for buffer nmlen=%u maxlen=%u\n",
+			    (unsigned)nmlen, (unsigned)maxlen));
+		return;
+	}
+	len = *nmlen++;
+	name = (char *)nmlen;
+	strlcpy(volname, name, NAME_MAX + 1);
+	return;
+}
+
+static int add_admin_volume(const char * name, const char * path)
+{
+	int snum;
+
+	snum = lp_servicenumber(name);
+	if (VALID_SNUM(snum)) {
+	    return snum;
+	}
+
+	snum = lp_add_default_service(name);
+	if (!VALID_SNUM(snum)) {
+		return -1;
+	}
+
+	lp_do_parameter(snum, "path", path);
+	lp_do_parameter(snum, "valid users", "+BUILTIN\\Administrators");
+	lp_do_parameter(snum, "read only", "no");
+	return snum;
+}
+
+/*
+ * Get all the mounted volumes and search for local volumes that are either the root mount
+ * point or have been mounted under /Volumes. Call getattrlist to get the real volume name
+ * to display in the share list.
+ */
+int apple_clone_local_volumes(const char * svcname)
+{
+	struct statfs *sb, *stat_p = NULL;
+	int n = getfsstat(NULL, 0, MNT_NOWAIT);
+	char volname[NAME_MAX + 1];
+	int ii;
+
+	if (n <= 0)	/* nothing to do just return */
+		goto out;
+
+	stat_p = (struct statfs *)SMB_MALLOC(n * sizeof(*stat_p));
+	if (stat_p == NULL)  /* nothing to do just return */
+		goto out;
+
+	/* Never wait gettng the list of mounted volumes */
+	if (getfsstat(stat_p, n * sizeof(*stat_p), MNT_NOWAIT) <= 0)
+		goto out;
+
+	sb = stat_p;
+	for (ii = 0; ii < n; ii++, sb++) {
+		/* Must be local mount and either the root volume or mount under /Volumes */
+		if (!(sb->f_flags & MNT_LOCAL)) {
+			continue;
+		}
+
+		if (sb->f_flags & MNT_DONTBROWSE)  {
+		    continue;
+		}
+
+		if (strncmp(sb->f_mntonname, "/", 2) == 0) {
+		    continue;
+		}
+
+		if (strncmp(sb->f_mntonname, APPLE_SLASH_VOLUMES,
+			    strlen(APPLE_SLASH_VOLUMES)) == 0) {
+
+			int snum;
+
+			get_volume_name(sb->f_mntonname, volname);
+
+			/* If we were asked to add a service for a specific
+			 * admin volume, check whether we have the right one.
+			 */
+			if (svcname && !strequal(svcname, volname)) {
+			    continue;
+			}
+
+			snum = add_admin_volume(volname, sb->f_mntonname);
+			if (VALID_SNUM(snum)) {
+				DEBUG(5,("Sharing %s with path = %s\n",
+					    volname, sb->f_mntonname));
+			} else {
+				DEBUG(5,("Failed to share %s with path = %s\n",
+					    volname, sb->f_mntonname));
+			}
+
+			if (svcname) {
+				return snum;
+			}
+		}
+	}
+
+out:
+	/* Clean up */
+	SAFE_FREE(stat_p);
+
+	return GLOBAL_SECTION_SNUM;
+}
Index: samba/source/Makefile.in
===================================================================
--- samba/source/Makefile.in.orig
+++ samba/source/Makefile.in
@@ -481,6 +481,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpass
 	       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 \
+	       smbd/darwin_clone_local_volumes.o \
 	       smbd/dmapi.o lib/opendirectory.o \
 	       lib/launchd.o smbd/sockinit.o \
 	       $(MANGLE_OBJ) @VFS_STATIC@
Index: samba/source/smbd/password.c
===================================================================
--- samba/source/smbd/password.c.orig
+++ samba/source/smbd/password.c
@@ -366,6 +366,17 @@ int register_vuid(auth_serversupplied_in
 			vuser->homes_snum = servicenumber;
 		}
 	} 
+
+	/*
+	 * If the user is part of the admin group then the shae
+	 * list should include all local volumes.
+	 */
+	if (!vuser->guest &&
+	    lp_parm_bool(GLOBAL_SECTION_SNUM, "com.apple", "show admin all volumes", False) &&
+	    user_in_group(vuser->user.unix_name, "admin")) {
+		extern int apple_clone_local_volumes(const char *);
+		apple_clone_local_volumes(NULL);
+	}
 	
 	if (srv_is_signing_negotiated() && !vuser->guest &&
 	    !srv_signing_started()) {
Index: samba/source/param/loadparm.c
===================================================================
--- samba/source/param/loadparm.c.orig
+++ samba/source/param/loadparm.c
@@ -2704,6 +2704,22 @@ int lp_add_service(const char *pszServic
 	return (add_a_service(ServicePtrs[iDefaultService], pszService));
 }
 
+int lp_add_default_service(const char * pszService)
+{
+	int snum;
+
+	snum = add_a_service(&sDefault, pszService);
+	if (snum < 0) {
+		return snum;
+	}
+
+	ServicePtrs[snum]->bAvailable = True;
+	ServicePtrs[snum]->bBrowseable = True;
+	ServicePtrs[snum]->autoloaded = True;
+	ServicePtrs[snum]->bGuest_ok = False;
+	return snum;
+}
+
 /***************************************************************************
  Add the IPC service.
 ***************************************************************************/