1 #include "restore.h"
2 #include <glob.h>
3
4 #ifndef GLOB_TILDE
5 #define GLOB_TILDE 0
6 #endif
7
8 #ifndef GLOB_BRACE
9 #define GLOB_BRACE 0
10 #endif
11
12 char **exclude_list;
13 int exclude_count;
14
15 struct restore_opts *r_opts;
16
restore_init(struct restore_opts * opts)17 void restore_init(struct restore_opts *opts)
18 {
19 int rc;
20
21 r_opts = opts;
22 struct selinux_opt selinux_opts[] = {
23 { SELABEL_OPT_VALIDATE, r_opts->selabel_opt_validate },
24 { SELABEL_OPT_PATH, r_opts->selabel_opt_path },
25 { SELABEL_OPT_DIGEST, r_opts->selabel_opt_digest }
26 };
27
28 r_opts->hnd = selabel_open(SELABEL_CTX_FILE, selinux_opts, 3);
29 if (!r_opts->hnd) {
30 perror(r_opts->selabel_opt_path);
31 exit(1);
32 }
33
34 r_opts->restorecon_flags = 0;
35 r_opts->restorecon_flags = r_opts->nochange | r_opts->verbose |
36 r_opts->progress | r_opts->set_specctx |
37 r_opts->add_assoc | r_opts->ignore_digest |
38 r_opts->recurse | r_opts->userealpath |
39 r_opts->xdev | r_opts->abort_on_error |
40 r_opts->syslog_changes | r_opts->log_matches |
41 r_opts->ignore_noent | r_opts->ignore_mounts;
42
43 /* Use setfiles, restorecon and restorecond own handles */
44 selinux_restorecon_set_sehandle(r_opts->hnd);
45
46 if (r_opts->rootpath) {
47 rc = selinux_restorecon_set_alt_rootpath(r_opts->rootpath);
48 if (rc) {
49 fprintf(stderr,
50 "selinux_restorecon_set_alt_rootpath error: %s.\n",
51 strerror(errno));
52 exit(-1);
53 }
54 }
55
56 if (exclude_list)
57 selinux_restorecon_set_exclude_list
58 ((const char **)exclude_list);
59 }
60
restore_finish(void)61 void restore_finish(void)
62 {
63 int i;
64
65 if (exclude_list) {
66 for (i = 0; exclude_list[i]; i++)
67 free(exclude_list[i]);
68 free(exclude_list);
69 }
70 }
71
process_glob(char * name,struct restore_opts * opts)72 int process_glob(char *name, struct restore_opts *opts)
73 {
74 glob_t globbuf;
75 size_t i = 0;
76 int len, rc, errors;
77
78 r_opts = opts;
79 memset(&globbuf, 0, sizeof(globbuf));
80
81 errors = glob(name, GLOB_TILDE | GLOB_PERIOD |
82 GLOB_NOCHECK | GLOB_BRACE, NULL, &globbuf);
83 if (errors)
84 return errors;
85
86 for (i = 0; i < globbuf.gl_pathc; i++) {
87 len = strlen(globbuf.gl_pathv[i]) - 2;
88 if (len > 0 && strcmp(&globbuf.gl_pathv[i][len--], "/.") == 0)
89 continue;
90 if (len > 0 && strcmp(&globbuf.gl_pathv[i][len], "/..") == 0)
91 continue;
92 rc = selinux_restorecon(globbuf.gl_pathv[i],
93 r_opts->restorecon_flags);
94 if (rc < 0)
95 errors = rc;
96 }
97
98 globfree(&globbuf);
99
100 return errors;
101 }
102
add_exclude(const char * directory)103 void add_exclude(const char *directory)
104 {
105 char **tmp_list;
106
107 if (directory == NULL || directory[0] != '/') {
108 fprintf(stderr, "Full path required for exclude: %s.\n",
109 directory);
110 exit(-1);
111 }
112
113 /* Add another two entries, one for directory, and the other to
114 * terminate the list.
115 */
116 tmp_list = realloc(exclude_list, sizeof(char *) * (exclude_count + 2));
117 if (!tmp_list) {
118 fprintf(stderr, "realloc failed while excluding %s.\n",
119 directory);
120 exit(-1);
121 }
122 exclude_list = tmp_list;
123
124 exclude_list[exclude_count] = strdup(directory);
125 if (!exclude_list[exclude_count]) {
126 fprintf(stderr, "strdup failed while excluding %s.\n",
127 directory);
128 exit(-1);
129 }
130 exclude_count++;
131 exclude_list[exclude_count] = NULL;
132 }
133