0c184a5b6e5e2ec461ed9b57716a548bbfac6d9c
[src/app-framework-main.git] / src / wgtpkg-workdir.c
1 /*
2  Copyright 2015 IoT.bzh
3
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7
8      http://www.apache.org/licenses/LICENSE-2.0
9
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16
17
18 #include <unistd.h>
19 #include <string.h>
20 #include <dirent.h>
21 #include <syslog.h>
22 #include <errno.h>
23 #include <sys/stat.h>
24
25 #include "wgtpkg.h"
26
27 #ifndef PREDIR
28 #define PREDIR  "./"
29 #endif
30
31 static int mode = 0700;
32 static char workdir[PATH_MAX];
33
34 /* removes recursively the content of a directory */
35 static int clean_dir()
36 {
37         int cr;
38         DIR *dir;
39         struct dirent *ent;
40         struct {
41                 struct dirent entry;
42                 char spare[PATH_MAX];
43         } entry;
44
45         dir = opendir(".");
46         if (dir == NULL) {
47                 syslog(LOG_ERR, "opendir failed in clean_dir");
48                 return -1;
49         }
50
51         cr = -1;
52         for (;;) {
53                 if (readdir_r(dir, &entry.entry, &ent) != 0) {
54                         syslog(LOG_ERR, "readdir_r failed in clean_dir");
55                         goto error;
56                 }
57                 if (ent == NULL)
58                         break;
59                 if (ent->d_name[0] == '.' && (ent->d_name[1] == 0
60                                 || (ent->d_name[1] == '.' && ent->d_name[2] == 0)))
61                         continue;
62                 cr = unlink(ent->d_name);
63                 if (!cr)
64                         continue;
65                 if (errno != EISDIR) {
66                         syslog(LOG_ERR, "unlink of %s failed in clean_dir", ent->d_name);
67                         goto error;
68                 }
69                 if (chdir(ent->d_name)) {
70                         syslog(LOG_ERR, "enter directory %s failed in clean_dir", ent->d_name);
71                         goto error;
72                 }
73                 cr = clean_dir();
74                 if (cr)
75                         goto error;
76                 if (chdir(".."))
77                         goto error;
78                 cr = rmdir(ent->d_name);
79                 if (cr) {
80                         syslog(LOG_ERR, "rmdir of %s failed in clean_dir", ent->d_name);
81                         goto error;
82                 }
83         }
84         cr = 0;
85 error:
86         closedir(dir);
87         return cr;
88 }
89
90 /* removes the content of the working directory */
91 int enter_workdir(int clean)
92 {
93         int rc = chdir(workdir);
94         if (rc)
95                 syslog(LOG_ERR, "entring workdir %s failed", workdir);
96         else if (clean)
97                 rc = clean_dir();
98         return rc;
99 }
100
101 /* removes the working directory */
102 void remove_workdir()
103 {
104         enter_workdir(1);
105         chdir("..");
106         unlink(workdir);
107 }
108
109 int set_workdir(const char *name, int create)
110 {
111         int rc;
112         size_t length;
113         struct stat s;
114
115         /* check the length */
116         length = strlen(name);
117         if (length >= sizeof workdir) {
118                 syslog(LOG_ERR, "workdir name too long");
119                 return -1;
120         }
121
122         rc = stat(name, &s);
123         if (rc) {
124                 if (!create) {
125                         syslog(LOG_ERR, "no workdir %s", name);
126                         return -1;
127                 }
128                 rc = mkdir(name, mode);
129                 if (rc) {
130                         syslog(LOG_ERR, "can't create workdir %s", name);
131                         return -1;
132                 }
133
134         } else if (!S_ISDIR(s.st_mode)) {
135                 syslog(LOG_ERR, "%s isn't a directory", name);
136                 return -1;
137         }
138         memcpy(workdir, name, 1+length);
139         return 0;
140 }
141
142 /* install the widgets of the list */
143 int make_workdir(int reuse)
144 {
145         int i;
146
147         /* create a temporary directory */
148         for (i = 0 ; ; i++) {
149                 if (i == INT_MAX) {
150                         syslog(LOG_ERR, "exhaustion of workdirs");
151                         return -1;
152                 }
153                 sprintf(workdir, PREDIR "PACK%d", i);
154                 if (!mkdir(workdir, mode))
155                         break;
156                 if (errno != EEXIST) {
157                         syslog(LOG_ERR, "error in creation of workdir %s: %m", workdir);
158                         return -1;
159                 }
160                 if (reuse)
161                         break;
162         }
163
164         return 0;
165 }
166