2N/A/*
2N/A * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A/* Solaris Kerberos: this file is unique to Solaris. */
2N/A
2N/A#include <stdio.h>
2N/A#include <string.h>
2N/A#include <stdlib.h>
2N/A#include <unistd.h>
2N/A#include <sys/types.h>
2N/A#include <sys/stat.h>
2N/A#include <fcntl.h>
2N/A
2N/A/*
2N/A * safechown changes the owner ship of src to uid. If the mode parameter
2N/A * does not equal -1 changes the mode of src as well.
2N/A *
2N/A * return -1 on failure and 0 on success.
2N/A */
2N/A
2N/Aint
2N/Asafechown(const char *src, uid_t uid, gid_t gid, int mode)
2N/A{
2N/Aint fd;
2N/Astruct stat fdbuf;
2N/Astruct stat lbuf;
2N/A
2N/A if ((fd = open(src, O_RDONLY, 0)) == -1)
2N/A return (-1);
2N/A
2N/A if (fstat(fd, &fdbuf)) {
2N/A close(fd);
2N/A return (-1);
2N/A }
2N/A
2N/A /* Make sure non directories are not hard links */
2N/A if (!S_ISDIR(fdbuf.st_mode) && fdbuf.st_nlink != 1) {
2N/A close(fd);
2N/A return (-1);
2N/A }
2N/A
2N/A if (lstat(src, &lbuf)) {
2N/A close(fd);
2N/A return (-1);
2N/A }
2N/A
2N/A /* Make sure file is not a symlink */
2N/A if (fdbuf.st_ino != lbuf.st_ino || fdbuf.st_dev != lbuf.st_dev ||
2N/A fdbuf.st_mode != lbuf.st_mode) {
2N/A
2N/A close(fd);
2N/A return (-1);
2N/A }
2N/A
2N/A /* we should probably get the primary group id for uid here */
2N/A if (fchown(fd, uid, gid)) {
2N/A close(fd);
2N/A return (-1);
2N/A }
2N/A
2N/A if (mode != -1) {
2N/A if (fchmod(fd, (mode_t)mode)) {
2N/A close(fd);
2N/A return (-1);
2N/A }
2N/A }
2N/A
2N/A close(fd);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A#ifdef TEST
2N/Avoid
2N/Ausage(char *prg)
2N/A{
2N/A fprintf(stderr, "Usage %s [-u uid] [-m mode] source\n", prg);
2N/A exit(1);
2N/A}
2N/A
2N/Amain(int argc, char *argv[])
2N/A{
2N/A int opt;
2N/A int mode = -1;
2N/A uid_t uid = 0;
2N/A
2N/A while ((opt = getopt(argc, argv, "m:u:")) != EOF) {
2N/A switch (opt) {
2N/A case 'm':
2N/A mode = strtol(optarg, 0, 8);
2N/A break;
2N/A case 'u':
2N/A uid = atoi(optarg);
2N/A break;
2N/A default:
2N/A usage(argv[0]);
2N/A }
2N/A }
2N/A
2N/A if (argc - optind != 1)
2N/A usage(argv[0]);
2N/A
2N/A if (safechown(argv[optind], uid, getgid(), mode)) {
2N/A perror("safechown");
2N/A exit(1);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A#endif /* TEST */