Home | History | Annotate | Download | only in toolbox
      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>
     10 #include <selinux/android.h>
     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 {
     19     fprintf(stderr, "usage:  %s [-nrRv] pathname...\n", progname);
     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 {
     56     int ch, recurse = 0, ftsflags = FTS_PHYSICAL;
     57     int i = 0;
     58 
     59     progname = argv[0];
     60 
     61     do {
     62         ch = getopt(argc, argv, "nrRv");
     63         if (ch == EOF)
     64             break;
     65         switch (ch) {
     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 
     86     sehandle = selinux_android_file_context_handle();
     87 
     88     if (!sehandle) {
     89         fprintf(stderr, "Could not load file_contexts:  %s\n",
     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 }
    137