blob: f9f604f7985b0d2eb6e4cea3e280c1d88beadaaa [file] [log] [blame]
Stephen Smalley8290d102012-01-13 08:53:56 -05001#include <unistd.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <errno.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <fts.h>
8#include <selinux/selinux.h>
9#include <selinux/label.h>
Stephen Smalleyae6f3d72012-05-01 15:02:53 -040010#include <selinux/android.h>
Stephen Smalley8290d102012-01-13 08:53:56 -050011
12static struct selabel_handle *sehandle;
13static const char *progname;
14static int nochange;
15static int verbose;
16
17static void usage(void)
18{
Stephen Smalleyae6f3d72012-05-01 15:02:53 -040019 fprintf(stderr, "usage: %s [-nrRv] pathname...\n", progname);
Stephen Smalley8290d102012-01-13 08:53:56 -050020 exit(1);
21}
22
23static int restore(const char *pathname, const struct stat *sb)
24{
25 char *oldcontext, *newcontext;
26
27 if (lgetfilecon(pathname, &oldcontext) < 0) {
28 fprintf(stderr, "Could not get context of %s: %s\n",
29 pathname, strerror(errno));
30 return -1;
31 }
32 if (selabel_lookup(sehandle, &newcontext, pathname, sb->st_mode) < 0) {
33 fprintf(stderr, "Could not lookup context for %s: %s\n", pathname,
34 strerror(errno));
35 return -1;
36 }
37 if (strcmp(newcontext, "<<none>>") &&
38 strcmp(oldcontext, newcontext)) {
39 if (verbose)
40 printf("Relabeling %s from %s to %s.\n", pathname, oldcontext, newcontext);
41 if (!nochange) {
42 if (lsetfilecon(pathname, newcontext) < 0) {
43 fprintf(stderr, "Could not label %s with %s: %s\n",
44 pathname, newcontext, strerror(errno));
45 return -1;
46 }
47 }
48 }
49 freecon(oldcontext);
50 freecon(newcontext);
51 return 0;
52}
53
54int restorecon_main(int argc, char **argv)
55{
Stephen Smalley8290d102012-01-13 08:53:56 -050056 int ch, recurse = 0, ftsflags = FTS_PHYSICAL;
Stephen Smalleyae6f3d72012-05-01 15:02:53 -040057 int i = 0;
Stephen Smalley8290d102012-01-13 08:53:56 -050058
59 progname = argv[0];
60
61 do {
Stephen Smalleyae6f3d72012-05-01 15:02:53 -040062 ch = getopt(argc, argv, "nrRv");
Stephen Smalley8290d102012-01-13 08:53:56 -050063 if (ch == EOF)
64 break;
65 switch (ch) {
Stephen Smalley8290d102012-01-13 08:53:56 -050066 case 'n':
67 nochange = 1;
68 break;
69 case 'r':
70 case 'R':
71 recurse = 1;
72 break;
73 case 'v':
74 verbose = 1;
75 break;
76 default:
77 usage();
78 }
79 } while (1);
80
81 argc -= optind;
82 argv += optind;
83 if (!argc)
84 usage();
85
Stephen Smalleyae6f3d72012-05-01 15:02:53 -040086 sehandle = selinux_android_file_context_handle();
87
Stephen Smalley8290d102012-01-13 08:53:56 -050088 if (!sehandle) {
Stephen Smalleyae6f3d72012-05-01 15:02:53 -040089 fprintf(stderr, "Could not load file_contexts: %s\n",
Stephen Smalley8290d102012-01-13 08:53:56 -050090 strerror(errno));
91 return -1;
92 }
93
94 if (recurse) {
95 FTS *fts;
96 FTSENT *ftsent;
97 fts = fts_open(argv, ftsflags, NULL);
98 if (!fts) {
99 fprintf(stderr, "Could not traverse filesystems (first was %s): %s\n",
100 argv[0], strerror(errno));
101 return -1;
102 }
103 while ((ftsent = fts_read(fts))) {
104 switch (ftsent->fts_info) {
105 case FTS_DP:
106 break;
107 case FTS_DNR:
108 case FTS_ERR:
109 case FTS_NS:
110 fprintf(stderr, "Could not access %s: %s\n", ftsent->fts_path,
111 strerror(errno));
112 fts_set(fts, ftsent, FTS_SKIP);
113 break;
114 default:
115 if (restore(ftsent->fts_path, ftsent->fts_statp) < 0)
116 fts_set(fts, ftsent, FTS_SKIP);
117 break;
118 }
119 }
120 } else {
121 int i, rc;
122 struct stat sb;
123
124 for (i = 0; i < argc; i++) {
125 rc = lstat(argv[i], &sb);
126 if (rc < 0) {
127 fprintf(stderr, "Could not stat %s: %s\n", argv[i],
128 strerror(errno));
129 continue;
130 }
131 restore(argv[i], &sb);
132 }
133 }
134
135 return 0;
136}