/* * Copyright (c) 1998, by Sun Microsystems, Inc. * All rights reserved. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include #include #include #include #include /* * 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 */