Index: sbin/mksnap_ffs/mksnap_ffs.c
===================================================================
RCS file: /home/ncvs/src/sbin/mksnap_ffs/mksnap_ffs.c,v
retrieving revision 1.2
retrieving revision 1.2.2.1
diff -u -r1.2 -r1.2.2.1
--- sbin/mksnap_ffs/mksnap_ffs.c	2 Mar 2003 08:07:57 -0000	1.2
+++ sbin/mksnap_ffs/mksnap_ffs.c	27 Jan 2004 19:33:16 -0000	1.2.2.1
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sbin/mksnap_ffs/mksnap_ffs.c,v 1.2 2003/03/02 08:07:57 mckusick Exp $
+ * $FreeBSD: src/sbin/mksnap_ffs/mksnap_ffs.c,v 1.2.2.1 2004/01/27 19:33:16 des Exp $
  */
 
 #include <sys/param.h>
@@ -43,24 +43,20 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <grp.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sysexits.h>
 #include <unistd.h>
 
-void
-usage()
-{
-
-	fprintf(stderr, "usage: mksnap_ffs mountpoint file\n");
-	exit(EX_USAGE);
-}
+void usage(void);
 
 int
 main(int argc, char **argv)
 {
-	const char *dir;
+	char *dir, *cp, path[PATH_MAX];
+	struct statfs stfsbuf;
 	struct ufs_args args;
 	struct group *grp;
 	struct stat stbuf;
@@ -72,9 +68,43 @@
 	dir = argv[1];
 	args.fspec = argv[2];
 
+	/*
+	 * Check that the user running this program has permission
+	 * to create and remove a snapshot file from the directory
+	 * in which they have requested to have it made. If the 
+	 * directory is sticky and not owned by the user, then they
+	 * will not be able to remove the snapshot when they are
+	 * done with it.
+	 */
+	if (strlen(args.fspec) >= PATH_MAX)
+		errx(1, "pathname too long %s", args.fspec);
+	cp = strrchr(args.fspec, '/');
+	if (cp == NULL) {
+		strlcpy(path, ".", PATH_MAX);
+	} else if (cp == args.fspec) {
+		strlcpy(path, "/", PATH_MAX);
+	} else {
+		strlcpy(path, args.fspec, cp - args.fspec + 1);
+	}
+	if(statfs(path, &stfsbuf) < 0)
+		err(1, "%s", path);
+	if (stat(path, &stbuf) < 0)
+		err(1, "%s", path);
+	if (!S_ISDIR(stbuf.st_mode))
+		errx(1, "%s: Not a directory", path);
+	if (access(path, W_OK) < 0)
+		err(1, "Lack write permission in %s", path);
+	if ((stbuf.st_mode & S_ISTXT) && stbuf.st_uid != getuid())
+		errx(1, "Lack write permission in %s: Sticky bit set", path);
+
+	/*
+	 * Having verified access to the directory in which the
+	 * snapshot is to be built, proceed with creating it.
+	 */
 	if ((grp = getgrnam("operator")) == NULL)
 		errx(1, "Cannot retrieve operator gid");
-	if (mount("ffs", dir, MNT_UPDATE | MNT_SNAPSHOT, &args) < 0)
+	if (mount("ffs", dir, MNT_UPDATE | MNT_SNAPSHOT | stfsbuf.f_flags,
+	    &args) < 0)
 		err(1, "Cannot create %s", args.fspec);
 	if ((fd = open(args.fspec, O_RDONLY)) < 0)
 		err(1, "Cannot open %s", args.fspec);
@@ -88,4 +118,12 @@
 		err(1, "Cannot chmod %s", args.fspec);
 
 	exit(EXIT_SUCCESS);
+}
+
+void
+usage()
+{
+
+	fprintf(stderr, "usage: mksnap_ffs mountpoint snapshot_name\n");
+	exit(EX_USAGE);
 }
