components/krb5/Solaris/safechown.c
changeset 5490 9bf0bc57423a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/safechown.c	Wed Feb 24 10:43:57 2016 -0600
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/* Solaris Kerberos: this file is unique to Solaris. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/*
+ * safechown changes the owner ship of src to uid. If the mode parameter
+ * does not equal -1 changes the mode of src as well.
+ *
+ * return -1 on failure and 0 on success.
+ */
+
+int
+safechown(const char *src, uid_t uid, gid_t gid, int mode)
+{
+int fd;
+struct stat fdbuf;
+struct stat lbuf;
+
+	if ((fd = open(src, O_RDONLY, 0)) == -1)
+		return (-1);
+
+	if (fstat(fd, &fdbuf)) {
+		close(fd);
+		return (-1);
+	}
+
+	/* Make sure non directories are not hard links */
+	if (!S_ISDIR(fdbuf.st_mode) && fdbuf.st_nlink != 1) {
+		close(fd);
+		return (-1);
+	}
+
+	if (lstat(src, &lbuf)) {
+		close(fd);
+		return (-1);
+	}
+
+	/* Make sure file is not a symlink */
+	if (fdbuf.st_ino != lbuf.st_ino || fdbuf.st_dev != lbuf.st_dev ||
+	    fdbuf.st_mode != lbuf.st_mode) {
+
+		close(fd);
+		return (-1);
+	}
+
+	/* we should probably get the primary group id for uid here */
+	if (fchown(fd, uid, gid)) {
+		close(fd);
+		return (-1);
+	}
+
+	if (mode != -1) {
+		if (fchmod(fd, (mode_t)mode)) {
+			close(fd);
+			return (-1);
+		}
+	}
+
+	close(fd);
+
+	return (0);
+}
+
+#ifdef TEST
+void
+usage(char *prg)
+{
+	fprintf(stderr, "Usage %s [-u uid] [-m mode] source\n", prg);
+	exit(1);
+}
+
+main(int argc, char *argv[])
+{
+	int opt;
+	int mode = -1;
+	uid_t uid = 0;
+
+	while ((opt = getopt(argc, argv, "m:u:")) != EOF) {
+		switch (opt) {
+		case 'm':
+			mode = strtol(optarg, 0, 8);
+			break;
+		case 'u':
+			uid = atoi(optarg);
+			break;
+		default:
+			usage(argv[0]);
+		}
+	}
+
+	if (argc - optind != 1)
+		usage(argv[0]);
+
+	if (safechown(argv[optind], uid, getgid(), mode)) {
+		perror("safechown");
+		exit(1);
+	}
+
+	return (0);
+}
+
+#endif  /* TEST */