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