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