TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / external / nsexec / uidmapshift.c
1 /*
2  * Copyright © 2012-2016 Canonical, Inc
3  *
4  * Author: Serge Hallyn <serge.hallyn@ubuntu.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation, version 2 of the
9  * License.
10  *
11  */
12 #define _XOPEN_SOURCE 500
13 #include <errno.h>
14 #include <ftw.h>
15 #include <getopt.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22
23 #define min(a,b) (a) < (b) ? (a) : (b)
24 #define max(a,b) (a) > (b) ? (a) : (b)
25
26 static int verbose = 0;
27 static int convert_uids = 0;
28 static int convert_gids = 0;
29 static uid_t srcid;
30 static uid_t dstid;
31 static uid_t range;
32 static uid_t range_uid_max = 0;
33 static uid_t range_uid_min = ~0;
34 static gid_t range_gid_max = 0;
35 static gid_t range_gid_min = ~0;
36
37 void usage(void)
38 {
39         extern const char *__progname;
40         printf("Usage: %s [OPTIONS] directory [src dst range]\n\n", __progname);
41         printf("  -u, --uid                      convert uids in directory\n");
42         printf("  -g, --gid                      convert gids in directory\n");
43         printf("  -b, --both                     convert uids and gids in directory\n");
44         printf("  -r, --range                    find min,max uid/gid used in directory\n");
45         printf("  -v, --verbose                  increate verbosity\n\n");
46         printf("Note this program always recursively walks all of directory.\n");
47         printf("If -u,-g, or -b is given, then [src dst range] are required to convert the \n");
48         printf("ids within the range [src..src+range] to [dst..dst+range].\n\n");
49         printf("Examples:\n");
50         printf("  %s -r /path/to/directory                # show min/max uid/gid\n", __progname);
51         printf("  %s -b /path/to/directory 0 100000 500   # map uids and gids up\n", __progname);
52         printf("  %s -u /path/to/directory 100000 0 500   # map the uids back down\n", __progname);
53 }
54
55 int ftw_callback(const char *fpath, const struct stat *st,
56                  int typeflag, struct FTW *ftw)
57 {
58         uid_t new_uid = -1;
59         uid_t new_gid = -1;
60         int ret;
61
62         range_uid_max = max(range_uid_max, st->st_uid);
63         range_uid_min = min(range_uid_min, st->st_uid);
64         range_gid_max = max(range_gid_max, st->st_gid);
65         range_gid_min = min(range_gid_min, st->st_gid);
66
67         if (convert_uids && st->st_uid >= srcid && st->st_uid < srcid+range)
68                 new_uid = (st->st_uid-srcid) + dstid;
69         if (convert_gids && st->st_gid >= srcid && st->st_gid < srcid+range)
70                 new_gid = (st->st_gid-srcid) + dstid;
71         if (new_uid != -1 || new_gid != -1) {
72                 ret = lchown(&fpath[ftw->base], new_uid, new_gid);
73                 if (ret) {
74                         fprintf(stderr, "failed to chown %d:%d %s\n",
75                                 new_uid, new_gid, fpath);
76                         /* well, let's keep going */
77                 } else {
78                         if (!S_ISLNK(st->st_mode)) {
79                                 if (verbose > 1)
80                                         fprintf(stderr, "resetting mode to %o on %s\n",
81                                                 st->st_mode, fpath);
82                                 ret = chmod(&fpath[ftw->base], st->st_mode);
83                                 if (ret) {
84                                         fprintf(stderr, "failed to reset mode %o on %s\n",
85                                                 st->st_mode, fpath);
86                                         /* well, let's keep going */
87                                 }
88                         }
89                         if (verbose)
90                                 printf("u:%07d=%07d g:%07d=%07d m:%#07o %s %s\n",
91                                        st->st_uid, new_uid,
92                                        st->st_gid, new_gid,
93                                        st->st_mode, fpath, &fpath[ftw->base]);
94                 }
95         }
96         return 0;
97 }
98
99 int main(int argc, char *argv[])
100 {
101         const char *base;
102         int show_range = 0;
103         int opt,ret;
104
105         static const struct option long_opts[] = {
106                 { "help",    no_argument, NULL, 'h' },
107                 { "uids",    no_argument, NULL, 'u' },
108                 { "gids",    no_argument, NULL, 'g' },
109                 { "both",    no_argument, NULL, 'b' },
110                 { "range",   no_argument, NULL, 'r' },
111                 { "verbose", no_argument, NULL, 'v' },
112                 { NULL,      0,           NULL, 0   }
113         };
114
115         while ((opt = getopt_long(argc, argv, "hugbrv", long_opts, NULL)) >= 0) {
116                 switch (opt) {
117                 case 'h': usage(); exit(EXIT_SUCCESS);
118                 case 'u': convert_uids = 1; break;
119                 case 'g': convert_gids = 1; break;
120                 case 'b': convert_uids = convert_gids = 1; break;
121                 case 'r': show_range = 1; break;
122                 case 'v': verbose++; break;
123                 }
124         }
125
126         argc -= optind;
127         argv += optind;
128
129         if (argc < 1) {
130                 usage();
131                 exit(EXIT_FAILURE);
132         }
133
134         base = argv[0];
135         if (convert_uids || convert_gids) {
136                 if (argc < 4) {
137                         usage();
138                         exit(EXIT_FAILURE);
139                 }
140                 srcid = atoi(argv[1]);
141                 dstid = atoi(argv[2]);
142                 range = atoi(argv[3]);
143         }
144
145         ret = nftw(base, ftw_callback, 1000, FTW_PHYS|FTW_CHDIR);
146         if (ret < 0) {
147                 fprintf(stderr, "Failed to walk path %s %s\n", base, strerror(errno));
148                 usage();
149                 return EXIT_FAILURE;
150         }
151
152         if (show_range) {
153                 printf("UIDs %d - %d\n"
154                        "GIDs %d - %d\n",
155                        range_uid_min, range_uid_max,
156                        range_gid_min, range_gid_max);
157         }
158
159         return EXIT_SUCCESS;
160 }