Line data Source code
1 : //
2 : // utils.c
3 : // deployctl
4 : //
5 : // Created by Danny Goossen on 10/5/17.
6 : // Copyright (c) 2017 Danny Goossen. All rights reserved.
7 : //
8 :
9 : #define _XOPEN_SOURCE 500
10 : #include <ftw.h>
11 : typedef unsigned short int u_short;
12 : #include <fts.h>
13 :
14 : #include "deployd.h"
15 :
16 :
17 :
18 :
19 : #ifndef OPEN_MAX
20 : #define OPEN_MAX 1023
21 : #endif
22 :
23 :
24 : /*------------------------------------------------------------------------
25 : * Convert string to uppercase
26 : *------------------------------------------------------------------------*/
27 8 : void upper_string(char s[]) {
28 16 : if (!s) return;
29 : int c = 0;
30 :
31 44 : while (s[c] != '\0') {
32 37 : if (s[c] >= 'a' && s[c] <= 'z') {
33 17 : s[c] = s[c] - 32;
34 : }
35 37 : c++;
36 : }
37 : }
38 : /*------------------------------------------------------------------------
39 : * Convert string to lower case
40 : *------------------------------------------------------------------------*/
41 6 : void lower_string(char s[]) {
42 12 : if (!s) return;
43 : int c = 0;
44 :
45 82 : while (s[c] != '\0') {
46 76 : if (s[c] >= 'A' && s[c] <= 'Z') {
47 0 : s[c] = s[c] + 32;
48 : }
49 76 : c++;
50 : }
51 : }
52 :
53 10 : void upper_string_n(char s[],size_t n) {
54 20 : if (!s) return;
55 : int c = 0;
56 :
57 41 : while (s[c] != '\0' && c<n) {
58 31 : if (s[c] >= 'a' && s[c] <= 'z') {
59 15 : s[c] = s[c] - 32;
60 : }
61 31 : c++;
62 : }
63 : }
64 :
65 0 : void split_path_file(char** p, char** f,const char *pf) {
66 0 : if (!pf || strlen(pf)==0) return;
67 : const char *slash = pf;
68 : char *next;
69 0 : while ((next = strpbrk(slash + 1, "\\/"))) slash = next;
70 0 : if (pf != slash) slash++;
71 0 : *p = cJSON_strdup_n((const unsigned char *)pf, slash - pf);
72 0 : *f = strdup(slash);
73 : }
74 :
75 4 : void split_path_file_2_path(char** p, const char *pf) {
76 8 : if (!pf || strlen(pf)==0) return;
77 : const char *slash = pf;
78 : char *next;
79 8 : while ((next = strpbrk(slash + 1, "\\/"))) slash = next;
80 4 : if (pf != slash) slash++;
81 4 : *p =cJSON_strdup_n((const unsigned char *)pf, slash - pf);
82 : }
83 :
84 : int
85 0 : nftw_x(const char *path, int (*fn)(const char *, const struct stat *, int,
86 : struct FTW *,void * data), int nfds, int ftwflags,void * data)
87 : {
88 : const char *paths[2];
89 : struct FTW ftw;
90 : FTSENT *cur;
91 : FTS *ftsp;
92 : int ftsflags, fnflag, error, postorder, sverrno;
93 :
94 : /* XXX - nfds is currently unused */
95 0 : if (nfds < 1 || nfds > OPEN_MAX) {
96 0 : errno = EINVAL;
97 0 : return (-1);
98 : }
99 :
100 0 : ftsflags = FTS_COMFOLLOW;
101 0 : if (!(ftwflags & FTW_CHDIR))
102 0 : ftsflags |= FTS_NOCHDIR;
103 0 : if (ftwflags & FTW_MOUNT)
104 0 : ftsflags |= FTS_XDEV;
105 0 : if (ftwflags & FTW_PHYS)
106 0 : ftsflags |= FTS_PHYSICAL;
107 0 : postorder = (ftwflags & FTW_DEPTH) != 0;
108 0 : paths[0] = path;
109 0 : paths[1] = NULL;
110 0 : ftsp = fts_open((char * const *)paths, ftsflags, NULL);
111 0 : if (ftsp == NULL)
112 : return (-1);
113 : error = 0;
114 0 : while ((cur = fts_read(ftsp)) != NULL) {
115 0 : switch (cur->fts_info) {
116 : case FTS_D:
117 0 : if (postorder)
118 0 : continue;
119 : fnflag = FTW_D;
120 : break;
121 : case FTS_DNR:
122 : fnflag = FTW_DNR;
123 : break;
124 : case FTS_DP:
125 0 : if (!postorder)
126 0 : continue;
127 : fnflag = FTW_DP;
128 : break;
129 : case FTS_F:
130 : case FTS_DEFAULT:
131 0 : fnflag = FTW_F;
132 0 : break;
133 : case FTS_NS:
134 : case FTS_NSOK:
135 0 : fnflag = FTW_NS;
136 0 : break;
137 : case FTS_SL:
138 0 : fnflag = FTW_SL;
139 0 : break;
140 : case FTS_SLNONE:
141 0 : fnflag = FTW_SLN;
142 0 : break;
143 : case FTS_DC:
144 0 : errno = ELOOP;
145 : /* FALLTHROUGH */
146 : default:
147 : error = -1;
148 : goto done;
149 : }
150 0 : ftw.base = cur->fts_pathlen - cur->fts_namelen;
151 0 : ftw.level = cur->fts_level;
152 0 : error = fn(cur->fts_path, cur->fts_statp, fnflag, &ftw,data);
153 0 : if (error != 0)
154 : break;
155 : }
156 : done:
157 0 : sverrno = errno;
158 0 : (void) fts_close(ftsp);
159 0 : errno = sverrno;
160 0 : return (error);
161 : }
162 :
163 214 : int remove_it(const char *path, const struct stat *s, int flag, struct FTW *f)
164 : {
165 214 : int status=0;
166 : int (*rm_func)( const char * );
167 :
168 214 : switch( flag ) {
169 : default: rm_func = unlink; break;
170 152 : case FTW_DP: rm_func = rmdir;
171 : }
172 214 : status = (rm_func( path ), status != 0 );
173 : // perror( path );
174 214 : return status;
175 : }
176 :
177 : struct payload{
178 : cJSON ** filelist;
179 : };
180 :
181 :
182 0 : int add_to_file_list(const char *path,int mode,cJSON ** filelist)
183 : {
184 0 : int result=0;
185 0 : size_t len=strlen(path);
186 0 : if ((S_ISDIR(mode) && len>2 && strcmp(path+len-2, ".")!=0 && len >3 && strcmp(path+len-3, "..")!=0 )|| !S_ISDIR(mode))
187 : {
188 0 : if (!*filelist) *filelist=cJSON_CreateArray();
189 0 : if (*filelist)
190 : {
191 0 : cJSON * tmpo=cJSON_CreateObject();
192 0 : cJSON_AddStringToObject(tmpo, "path", path);
193 0 : cJSON_AddNumberToObject(tmpo, "mode", mode);
194 0 : cJSON_AddItemToArray(*filelist,tmpo);
195 : }
196 : else
197 : result=1;
198 : }
199 0 : return result;
200 : }
201 :
202 0 : int list_it(const char *path, const struct stat *s, int flag, struct FTW *f,void* data)
203 : {
204 0 : int status=0;
205 : switch( flag ) {
206 : default: ; break;
207 : /* we'll handle dir/symlinks/files */
208 : case FTW_SL:
209 : case FTW_F:
210 : case FTW_D:
211 0 : status=add_to_file_list( path,s->st_mode ,data) ;break;
212 : }
213 0 : return status;
214 : }
215 :
216 :
217 0 : int getfilelist(char * projectdir,cJSON * paths,cJSON ** filelist)
218 : {
219 :
220 0 : if (!projectdir || !paths || !filelist ) return -1;
221 : char tmp[1024];
222 : cJSON * path;
223 0 : cJSON_ArrayForEach(path,paths)
224 : {
225 0 : snprintf((char*)tmp,1024,"%s%s",projectdir,path->valuestring);
226 0 : debug("get filelist for path %s\n",tmp);
227 :
228 :
229 : struct stat sb;
230 :
231 0 : if (stat(tmp, &sb) == 0 && S_ISDIR(sb.st_mode))
232 : {
233 :
234 0 : add_to_file_list(path->valuestring, sb.st_mode, filelist);
235 0 : if (nftw_x((char*)tmp, list_it, 6 ,FTW_PHYS ,(void*)filelist)) //| FTW_DEPTH
236 : {
237 0 : perror( tmp );
238 0 : error("nftw return non 0\n");
239 0 : return 1;
240 : }
241 : }
242 0 : else if (stat(tmp, &sb) == 0 && (S_ISLNK(sb.st_mode)|| S_ISREG(sb.st_mode)))
243 0 : add_to_file_list(path->valuestring, sb.st_mode, filelist);
244 :
245 : }
246 : return 0;
247 : }
248 :
249 : // Recursive remove directory
250 61 : void _rmdir(const char * dir, const char * base)
251 : {
252 : char tmp[1024];
253 61 : if (!dir || strlen(dir)==0)
254 : {
255 14 : if (!base || strlen(base)==0) return;
256 7 : else snprintf((char*)tmp,1024,"%s",base);
257 : }
258 54 : else if (!base || strlen(base)==0)
259 : {
260 86 : if (!dir || strlen(dir)==0) return;
261 43 : else snprintf((char*)tmp,1024,"%s",dir);
262 : }
263 : else
264 : {
265 11 : if (dir[0]=='/')
266 11 : snprintf((char*)tmp,1024,"%s%s",base,dir);
267 : else
268 0 : snprintf((char*)tmp,1024,"%s/%s",base,dir);
269 : }
270 :
271 : struct stat sb;
272 :
273 61 : if (stat(tmp, &sb) == 0 && S_ISDIR(sb.st_mode))
274 : {
275 47 : if (nftw((char*)tmp, remove_it, 6 ,FTW_PHYS | FTW_DEPTH))
276 : {
277 0 : perror( tmp );
278 : }
279 : }
280 : }
281 :
282 : // mdir -p
283 43 : void _mkdir(const char *dir, const char * base) {
284 : char tmp[1024];
285 43 : char *p = NULL;
286 : size_t len;
287 43 : if (!dir || strlen(dir)==0)
288 : {
289 26 : if (!base || strlen(base)==0) return;
290 13 : else snprintf((char*)tmp,1024,"%s",base);
291 : }
292 30 : else if (!base || strlen(base)==0)
293 : {
294 6 : if (!dir || strlen(dir)==0) return;
295 3 : else snprintf((char*)tmp,1024,"%s",dir);
296 : }
297 : else
298 : {
299 27 : if (dir[0]=='/')
300 24 : snprintf((char*)tmp,1024,"%s%s",base,dir);
301 : else
302 3 : snprintf((char*)tmp,1024,"%s/%s",base,dir);
303 : }
304 : struct stat sb;
305 43 : if (stat(tmp, &sb) == 0 && S_ISDIR(sb.st_mode))
306 : {
307 : //debug("directory %s exists\n",tmp);
308 : }
309 : else
310 : {
311 43 : len = strlen(tmp);
312 43 : if(tmp[len - 1] == '/')
313 1 : tmp[len - 1] = 0;
314 : //debug("mkdir %s\n",tmp);
315 3147 : for(p = tmp + 1; *p; p++)
316 3147 : if(*p == '/') {
317 270 : *p = 0;
318 270 : if (stat(tmp, &sb) == 0 && S_ISDIR(sb.st_mode))
319 : {
320 : //debug("sub directory %s exists\n",tmp);
321 : }
322 : else{
323 : //debug("mkdir sub %s\n",tmp);
324 139 : mkdir(tmp,S_IRWXG | S_IRWXU);
325 : }
326 270 : *p = '/';
327 : }
328 : //debug("mkdir sub %s\n",tmp);
329 43 : mkdir(tmp, S_IRWXG | S_IRWXU);
330 : }
331 : }
332 :
333 : /*
334 :
335 : */
|