| Stephen Smalley | 8290d10 | 2012-01-13 08:53:56 -0500 | [diff] [blame] | 1 | #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 Smalley | ae6f3d7 | 2012-05-01 15:02:53 -0400 | [diff] [blame] | 10 | #include <selinux/android.h> | 
| Stephen Smalley | 8290d10 | 2012-01-13 08:53:56 -0500 | [diff] [blame] | 11 |  | 
|  | 12 | static struct selabel_handle *sehandle; | 
|  | 13 | static const char *progname; | 
|  | 14 | static int nochange; | 
|  | 15 | static int verbose; | 
|  | 16 |  | 
|  | 17 | static void usage(void) | 
|  | 18 | { | 
| Stephen Smalley | ae6f3d7 | 2012-05-01 15:02:53 -0400 | [diff] [blame] | 19 | fprintf(stderr, "usage:  %s [-nrRv] pathname...\n", progname); | 
| Stephen Smalley | 8290d10 | 2012-01-13 08:53:56 -0500 | [diff] [blame] | 20 | exit(1); | 
|  | 21 | } | 
|  | 22 |  | 
|  | 23 | static 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 |  | 
|  | 54 | int restorecon_main(int argc, char **argv) | 
|  | 55 | { | 
| Stephen Smalley | 8290d10 | 2012-01-13 08:53:56 -0500 | [diff] [blame] | 56 | int ch, recurse = 0, ftsflags = FTS_PHYSICAL; | 
| Stephen Smalley | ae6f3d7 | 2012-05-01 15:02:53 -0400 | [diff] [blame] | 57 | int i = 0; | 
| Stephen Smalley | 8290d10 | 2012-01-13 08:53:56 -0500 | [diff] [blame] | 58 |  | 
|  | 59 | progname = argv[0]; | 
|  | 60 |  | 
|  | 61 | do { | 
| Stephen Smalley | ae6f3d7 | 2012-05-01 15:02:53 -0400 | [diff] [blame] | 62 | ch = getopt(argc, argv, "nrRv"); | 
| Stephen Smalley | 8290d10 | 2012-01-13 08:53:56 -0500 | [diff] [blame] | 63 | if (ch == EOF) | 
|  | 64 | break; | 
|  | 65 | switch (ch) { | 
| Stephen Smalley | 8290d10 | 2012-01-13 08:53:56 -0500 | [diff] [blame] | 66 | 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 Smalley | ae6f3d7 | 2012-05-01 15:02:53 -0400 | [diff] [blame] | 86 | sehandle = selinux_android_file_context_handle(); | 
|  | 87 |  | 
| Stephen Smalley | 8290d10 | 2012-01-13 08:53:56 -0500 | [diff] [blame] | 88 | if (!sehandle) { | 
| Stephen Smalley | ae6f3d7 | 2012-05-01 15:02:53 -0400 | [diff] [blame] | 89 | fprintf(stderr, "Could not load file_contexts:  %s\n", | 
| Stephen Smalley | 8290d10 | 2012-01-13 08:53:56 -0500 | [diff] [blame] | 90 | 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 | } |