1 /* 2 * Copyright (c) 1998, by Sun Microsystems, Inc. 3 * All rights reserved. 4 */ 5 6 #include <stdio.h> 7 #include <string.h> 8 #include <stdlib.h> 9 #include <unistd.h> 10 #include <sys/types.h> 11 #include <sys/stat.h> 12 #include <fcntl.h> 13 14 /* 15 * safechown changes the owner ship of src to uid. If the mode parameter 16 * does not equal -1 changes the mode of src as well. 17 * 18 * return -1 on failure and 0 on success. 19 */ 20 21 int 22 safechown(const char *src, uid_t uid, gid_t gid, int mode) 23 { 24 int fd; 25 struct stat fdbuf; 26 struct stat lbuf; 27 28 if ((fd = open(src, O_RDONLY, 0)) == -1) 29 return (-1); 30 31 if (fstat(fd, &fdbuf)) { 32 close(fd); 33 return (-1); 34 } 35 36 /* Make sure non directories are not hard links */ 37 if (!S_ISDIR(fdbuf.st_mode) && fdbuf.st_nlink != 1) { 38 close(fd); 39 return (-1); 40 } 41 42 if (lstat(src, &lbuf)) { 43 close(fd); 44 return (-1); 45 } 46 47 /* Make sure file is not a symlink */ 48 if (fdbuf.st_ino != lbuf.st_ino || fdbuf.st_dev != lbuf.st_dev || 49 fdbuf.st_mode != lbuf.st_mode) { 50 51 close(fd); 52 return (-1); 53 } 54 55 /* we should probably get the primary group id for uid here */ 56 if (fchown(fd, uid, gid)) { 57 close(fd); 58 return (-1); 59 } 60 61 if (mode != -1) { 62 if (fchmod(fd, (mode_t)mode)) { 63 close(fd); 64 return (-1); 65 } 66 } 67 68 close(fd); 69 70 return (0); 71 } 72 73 #ifdef TEST 74 void 75 usage(char *prg) 76 { 77 fprintf(stderr, "Usage %s [-u uid] [-m mode] source\n", prg); 78 exit(1); 79 } 80 81 main(int argc, char *argv[]) 82 { 83 int opt; 84 int mode = -1; 85 uid_t uid = 0; 86 87 while ((opt = getopt(argc, argv, "m:u:")) != EOF) { 88 switch (opt) { 89 case 'm': 90 mode = strtol(optarg, 0, 8); 91 break; 92 case 'u': 93 uid = atoi(optarg); 94 break; 95 default: 96 usage(argv[0]); 97 } 98 } 99 100 if (argc - optind != 1) 101 usage(argv[0]); 102 103 if (safechown(argv[optind], uid, getgid(), mode)) { 104 perror("safechown"); 105 exit(1); 106 } 107 108 return (0); 109 } 110 111 #endif /* TEST */ 112