]>
Commit | Line | Data |
---|---|---|
221cc3ce MT |
1 | /*############################################################################# |
2 | # # | |
3 | # Pakfire - The IPFire package management system # | |
4 | # Copyright (C) 2014 Pakfire development team # | |
5 | # # | |
6 | # This program is free software: you can redistribute it and/or modify # | |
7 | # it under the terms of the GNU General Public License as published by # | |
8 | # the Free Software Foundation, either version 3 of the License, or # | |
9 | # (at your option) any later version. # | |
10 | # # | |
11 | # This program is distributed in the hope that it will be useful, # | |
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
14 | # GNU General Public License for more details. # | |
15 | # # | |
16 | # You should have received a copy of the GNU General Public License # | |
17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
18 | # # | |
19 | #############################################################################*/ | |
20 | ||
21 | #include <assert.h> | |
22 | #include <stdio.h> | |
23 | #include <stdlib.h> | |
24 | #include <string.h> | |
25 | #include <sys/stat.h> | |
26 | #include <sys/types.h> | |
27 | #include <tar.h> | |
28 | #include <time.h> | |
29 | ||
30 | #include <pakfire/constants.h> | |
31 | #include <pakfire/file.h> | |
9f953e68 | 32 | #include <pakfire/private.h> |
221cc3ce MT |
33 | #include <pakfire/util.h> |
34 | ||
9f953e68 | 35 | PAKFIRE_EXPORT PakfireFile pakfire_file_create() { |
221cc3ce MT |
36 | PakfireFile file = pakfire_calloc(1, sizeof(*file)); |
37 | if (file) { | |
38 | file->name = NULL; | |
39 | ||
40 | file->prev = NULL; | |
41 | file->next = NULL; | |
42 | } | |
43 | ||
44 | return file; | |
45 | } | |
46 | ||
d03fa9a3 MT |
47 | PAKFIRE_EXPORT PakfireFile pakfire_file_ref(PakfireFile file) { |
48 | return file; | |
49 | } | |
50 | ||
51 | PAKFIRE_EXPORT PakfireFile pakfire_file_unref(PakfireFile file) { | |
52 | return file; | |
53 | } | |
54 | ||
9f953e68 | 55 | PAKFIRE_EXPORT void pakfire_file_free(PakfireFile file) { |
221cc3ce MT |
56 | if (file->name) |
57 | pakfire_free(file->name); | |
58 | ||
59 | if (file->user) | |
60 | pakfire_free(file->user); | |
61 | if (file->group) | |
62 | pakfire_free(file->group); | |
63 | ||
64 | // Update pointers in the previous and next element in the list. | |
65 | if (file->next) | |
66 | file->next->prev = NULL; | |
67 | if (file->prev) | |
68 | file->prev->next = NULL; | |
69 | ||
70 | pakfire_free(file); | |
71 | } | |
72 | ||
9f953e68 | 73 | PAKFIRE_EXPORT void pakfire_file_free_all(PakfireFile file) { |
221cc3ce MT |
74 | file = pakfire_file_get_first(file); |
75 | ||
76 | while (file) { | |
77 | PakfireFile next = file->next; | |
78 | pakfire_file_free(file); | |
79 | ||
80 | file = next; | |
81 | } | |
82 | } | |
83 | ||
9f953e68 | 84 | PAKFIRE_EXPORT int pakfire_file_cmp(PakfireFile file1, PakfireFile file2) { |
221cc3ce MT |
85 | const char* name1 = pakfire_file_get_name(file1); |
86 | const char* name2 = pakfire_file_get_name(file2); | |
87 | ||
88 | return strcmp(name1, name2); | |
89 | } | |
90 | ||
9f953e68 | 91 | PAKFIRE_EXPORT void pakfire_file_swap(PakfireFile file1, PakfireFile file2) { |
221cc3ce MT |
92 | PakfireFile file_prev = file1->prev; |
93 | PakfireFile file_next = file2->next; | |
94 | ||
95 | if (file_prev) | |
96 | file_prev->next = file2; | |
97 | file2->prev = file_prev; | |
98 | ||
99 | if (file_next) | |
100 | file_next->prev = file1; | |
101 | file1->next = file_next; | |
102 | ||
103 | file2->next = file1; | |
104 | file1->prev = file2; | |
105 | } | |
106 | ||
9f953e68 | 107 | PAKFIRE_EXPORT PakfireFile pakfire_file_sort(PakfireFile head) { |
221cc3ce MT |
108 | unsigned int count = pakfire_file_count(head); |
109 | ||
110 | for (unsigned int i = 0; i < count; i++) { | |
111 | PakfireFile file = head; | |
112 | PakfireFile next = pakfire_file_get_next(file); | |
113 | ||
114 | while (next) { | |
115 | if (pakfire_file_cmp(file, next) > 0) { | |
116 | if (head == file) | |
117 | head = next; | |
118 | ||
119 | pakfire_file_swap(file, next); | |
120 | } | |
121 | ||
122 | file = next; | |
123 | next = pakfire_file_get_next(file); | |
124 | } | |
125 | } | |
126 | ||
127 | return head; | |
128 | } | |
129 | ||
9f953e68 | 130 | PAKFIRE_EXPORT PakfireFile pakfire_file_get_prev(PakfireFile file) { |
221cc3ce MT |
131 | return file->prev; |
132 | } | |
133 | ||
9f953e68 | 134 | PAKFIRE_EXPORT PakfireFile pakfire_file_get_next(PakfireFile file) { |
221cc3ce MT |
135 | return file->next; |
136 | } | |
137 | ||
9f953e68 | 138 | PAKFIRE_EXPORT PakfireFile pakfire_file_get_first(PakfireFile file) { |
221cc3ce MT |
139 | if (file->prev) |
140 | return pakfire_file_get_first(file->prev); | |
141 | ||
142 | return file; | |
143 | } | |
144 | ||
9f953e68 | 145 | PAKFIRE_EXPORT PakfireFile pakfire_file_get_last(PakfireFile file) { |
221cc3ce MT |
146 | if (file->next) |
147 | return pakfire_file_get_last(file->next); | |
148 | ||
149 | return file; | |
150 | } | |
151 | ||
152 | static PakfireFile __pakfire_file_append(PakfireFile file, PakfireFile appended_file) { | |
153 | // Get the last file in the queue. | |
154 | file = pakfire_file_get_last(file); | |
155 | ||
156 | // Set the links. | |
157 | file->next = appended_file; | |
158 | appended_file->prev = file; | |
159 | ||
160 | return appended_file; | |
161 | } | |
162 | ||
9f953e68 | 163 | PAKFIRE_EXPORT PakfireFile pakfire_file_append(PakfireFile file) { |
221cc3ce MT |
164 | // Create a new file object. |
165 | PakfireFile appended_file = pakfire_file_create(); | |
166 | ||
167 | return __pakfire_file_append(file, appended_file); | |
168 | } | |
169 | ||
9f953e68 | 170 | PAKFIRE_EXPORT unsigned int pakfire_file_count(PakfireFile file) { |
221cc3ce MT |
171 | unsigned int counter = 0; |
172 | ||
173 | while (file) { | |
174 | file = pakfire_file_get_next(file); | |
175 | ++counter; | |
176 | } | |
177 | ||
178 | return counter; | |
179 | } | |
180 | ||
181 | static char pakfire_file_sprintf_type(PakfireFile file) { | |
182 | if (pakfire_file_is_dir(file)) | |
183 | return 'd'; | |
184 | ||
185 | if (pakfire_file_is_symlink(file)) | |
186 | return 'l'; | |
187 | ||
188 | if (pakfire_file_is_char(file)) | |
189 | return 'c'; | |
190 | ||
191 | return '-'; | |
192 | } | |
193 | ||
194 | static char* pakfire_file_format_perms(PakfireFile file) { | |
195 | char buffer[11]; | |
196 | ||
197 | mode_t mode = pakfire_file_get_mode(file); | |
198 | ||
199 | buffer[0] = pakfire_file_sprintf_type(file); | |
200 | buffer[1] = (S_IRUSR & mode) ? 'r' : '-'; | |
201 | buffer[2] = (S_IWUSR & mode) ? 'w' : '-'; | |
202 | buffer[3] = (S_IXUSR & mode) ? 'x' : '-'; | |
203 | buffer[4] = (S_IRGRP & mode) ? 'r' : '-'; | |
204 | buffer[5] = (S_IWGRP & mode) ? 'w' : '-'; | |
205 | buffer[6] = (S_IXGRP & mode) ? 'x' : '-'; | |
206 | buffer[7] = (S_IROTH & mode) ? 'r' : '-'; | |
207 | buffer[8] = (S_IWOTH & mode) ? 'w' : '-'; | |
208 | buffer[9] = (S_IXOTH & mode) ? 'x' : '-'; | |
209 | buffer[10] = '\0'; | |
210 | ||
211 | #warning TODO SUID bits, etc... | |
212 | ||
213 | return pakfire_strdup(buffer); | |
214 | } | |
215 | ||
216 | static char* pakfire_file_format_mtime(PakfireFile file) { | |
217 | struct tm* timer = gmtime((time_t *)&file->time); | |
218 | ||
219 | char buffer[STRING_SIZE]; | |
220 | strftime(buffer, sizeof(buffer), "%d %b %Y %T", timer); | |
221 | ||
222 | return pakfire_strdup(buffer); | |
223 | } | |
224 | ||
9f953e68 | 225 | PAKFIRE_EXPORT void pakfire_file_sprintf(PakfireFile file, char* str, size_t len) { |
221cc3ce MT |
226 | const char* name = pakfire_file_get_name(file); |
227 | ssize_t size = pakfire_file_get_size(file); | |
228 | ||
229 | const char* user = pakfire_file_get_user(file); | |
230 | const char* group = pakfire_file_get_group(file); | |
231 | ||
232 | char* perms = pakfire_file_format_perms(file); | |
233 | char* mtime = pakfire_file_format_mtime(file); | |
234 | ||
235 | snprintf(str, len, "%s %-8s %-8s %8d %s %s", perms, user, group, | |
236 | (int)size, mtime, name); | |
237 | ||
238 | pakfire_free(perms); | |
239 | pakfire_free(mtime); | |
240 | } | |
241 | ||
9f953e68 | 242 | PAKFIRE_EXPORT const char* pakfire_file_get_name(PakfireFile file) { |
221cc3ce MT |
243 | return file->name; |
244 | } | |
245 | ||
9f953e68 | 246 | PAKFIRE_EXPORT void pakfire_file_set_name(PakfireFile file, const char* name) { |
221cc3ce MT |
247 | if (file->name) |
248 | pakfire_free(file->name); | |
249 | ||
250 | if (*name == '/') { | |
251 | file->name = pakfire_strdup(name); | |
252 | } else { | |
253 | asprintf(&file->name, "/%s", name); | |
254 | } | |
255 | } | |
256 | ||
9f953e68 | 257 | PAKFIRE_EXPORT char pakfire_file_get_type(PakfireFile file) { |
221cc3ce MT |
258 | return file->type; |
259 | } | |
260 | ||
9f953e68 | 261 | PAKFIRE_EXPORT void pakfire_file_set_type(PakfireFile file, char type) { |
221cc3ce MT |
262 | file->type = type; |
263 | } | |
264 | ||
9f953e68 | 265 | PAKFIRE_EXPORT int pakfire_file_is_file(PakfireFile file) { |
221cc3ce MT |
266 | return (file->type == REGTYPE) || (file->type == AREGTYPE); |
267 | } | |
268 | ||
9f953e68 | 269 | PAKFIRE_EXPORT int pakfire_file_is_link(PakfireFile file) { |
221cc3ce MT |
270 | return (file->type == LNKTYPE); |
271 | } | |
272 | ||
9f953e68 | 273 | PAKFIRE_EXPORT int pakfire_file_is_symlink(PakfireFile file) { |
221cc3ce MT |
274 | return (file->type == SYMTYPE); |
275 | } | |
276 | ||
9f953e68 | 277 | PAKFIRE_EXPORT int pakfire_file_is_char(PakfireFile file) { |
221cc3ce MT |
278 | return (file->type == CHRTYPE); |
279 | } | |
280 | ||
9f953e68 | 281 | PAKFIRE_EXPORT int pakfire_file_is_block(PakfireFile file) { |
221cc3ce MT |
282 | return (file->type == BLKTYPE); |
283 | } | |
284 | ||
9f953e68 | 285 | PAKFIRE_EXPORT int pakfire_file_is_dir(PakfireFile file) { |
221cc3ce MT |
286 | return (file->type == DIRTYPE); |
287 | } | |
288 | ||
9f953e68 | 289 | PAKFIRE_EXPORT ssize_t pakfire_file_get_size(PakfireFile file) { |
221cc3ce MT |
290 | return file->size; |
291 | } | |
292 | ||
9f953e68 | 293 | PAKFIRE_EXPORT void pakfire_file_set_size(PakfireFile file, ssize_t size) { |
221cc3ce MT |
294 | file->size = size; |
295 | } | |
296 | ||
9f953e68 | 297 | PAKFIRE_EXPORT const char* pakfire_file_get_user(PakfireFile file) { |
221cc3ce MT |
298 | return file->user; |
299 | } | |
300 | ||
9f953e68 | 301 | PAKFIRE_EXPORT void pakfire_file_set_user(PakfireFile file, const char* user) { |
221cc3ce MT |
302 | file->user = pakfire_strdup(user); |
303 | } | |
304 | ||
9f953e68 | 305 | PAKFIRE_EXPORT const char* pakfire_file_get_group(PakfireFile file) { |
221cc3ce MT |
306 | return file->group; |
307 | } | |
308 | ||
9f953e68 | 309 | PAKFIRE_EXPORT void pakfire_file_set_group(PakfireFile file, const char* group) { |
221cc3ce MT |
310 | file->group = pakfire_strdup(group); |
311 | } | |
312 | ||
9f953e68 | 313 | PAKFIRE_EXPORT mode_t pakfire_file_get_mode(PakfireFile file) { |
221cc3ce MT |
314 | return file->mode; |
315 | } | |
316 | ||
9f953e68 | 317 | PAKFIRE_EXPORT void pakfire_file_set_mode(PakfireFile file, mode_t mode) { |
221cc3ce MT |
318 | file->mode = mode; |
319 | } | |
320 | ||
9f953e68 | 321 | PAKFIRE_EXPORT time_t pakfire_file_get_time(PakfireFile file) { |
221cc3ce MT |
322 | return file->time; |
323 | } | |
324 | ||
9f953e68 | 325 | PAKFIRE_EXPORT void pakfire_file_set_time(PakfireFile file, time_t time) { |
221cc3ce MT |
326 | file->time = time; |
327 | } | |
328 | ||
9f953e68 | 329 | PAKFIRE_EXPORT const char* pakfire_file_get_chksum(PakfireFile file) { |
221cc3ce MT |
330 | return file->chksum; |
331 | } | |
332 | ||
9f953e68 | 333 | PAKFIRE_EXPORT void pakfire_file_set_chksum(PakfireFile file, const char* chksum) { |
221cc3ce MT |
334 | file->chksum = pakfire_strdup(chksum); |
335 | } | |
336 | ||
337 | static PakfireFile pakfire_file_parse_line(char* line, unsigned int format) { | |
338 | unsigned int i = 0; | |
339 | ||
340 | PakfireFile file = pakfire_file_create(); | |
341 | ssize_t size; | |
342 | mode_t mode; | |
343 | time_t time; | |
344 | ||
345 | unsigned int bytes_read = 0; | |
346 | ||
347 | char* word = strtok(line, " "); | |
348 | while (word) { | |
349 | if (format >= 4) { | |
350 | switch (i) { | |
351 | // type | |
352 | case 0: | |
353 | pakfire_file_set_type(file, *word); | |
354 | break; | |
355 | ||
356 | // size | |
357 | case 1: | |
358 | size = atoi(word); | |
359 | pakfire_file_set_size(file, size); | |
360 | break; | |
361 | ||
362 | // user | |
363 | case 2: | |
364 | pakfire_file_set_user(file, word); | |
365 | break; | |
366 | ||
367 | // group | |
368 | case 3: | |
369 | pakfire_file_set_group(file, word); | |
370 | break; | |
371 | ||
372 | // mode | |
373 | case 4: | |
374 | mode = atoi(word); | |
375 | pakfire_file_set_mode(file, mode); | |
376 | break; | |
377 | ||
378 | // time | |
379 | case 5: | |
380 | time = atoi(word); | |
381 | pakfire_file_set_time(file, time); | |
382 | break; | |
383 | ||
384 | // checksum | |
385 | case 6: | |
386 | pakfire_file_set_chksum(file, word); | |
387 | break; | |
388 | ||
389 | // name | |
390 | #warning handle filenames with spaces | |
391 | case 8: | |
392 | pakfire_file_set_name(file, line + bytes_read); | |
393 | break; | |
394 | } | |
395 | ||
396 | } else if (format >= 3) { | |
397 | switch (i) { | |
398 | // name | |
399 | case 0: | |
400 | pakfire_file_set_name(file, word); | |
401 | break; | |
402 | ||
403 | // type | |
404 | case 1: | |
405 | pakfire_file_set_type(file, *word); | |
406 | break; | |
407 | ||
408 | // size | |
409 | case 2: | |
410 | size = atoi(word); | |
411 | pakfire_file_set_size(file, size); | |
412 | break; | |
413 | ||
414 | // user | |
415 | case 3: | |
416 | pakfire_file_set_user(file, word); | |
417 | break; | |
418 | ||
419 | // group | |
420 | case 4: | |
421 | pakfire_file_set_group(file, word); | |
422 | break; | |
423 | ||
424 | // mode | |
425 | case 5: | |
426 | mode = atoi(word); | |
427 | pakfire_file_set_mode(file, mode); | |
428 | break; | |
429 | ||
430 | // time | |
431 | case 6: | |
432 | time = atoi(word); | |
433 | pakfire_file_set_time(file, time); | |
434 | break; | |
435 | ||
436 | // checksum | |
437 | case 7: | |
438 | pakfire_file_set_chksum(file, word); | |
439 | break; | |
440 | } | |
441 | } | |
442 | ||
443 | // Count the bytes of the line that have been processed so far | |
444 | // (Skip all padding spaces) | |
445 | bytes_read += strlen(word) + 1; | |
446 | while (*(line + bytes_read) == ' ') | |
447 | bytes_read += 1; | |
448 | ||
449 | word = strtok(NULL, " "); | |
450 | ++i; | |
451 | } | |
452 | ||
453 | return file; | |
454 | } | |
455 | ||
9f953e68 | 456 | PAKFIRE_EXPORT PakfireFile pakfire_file_parse_from_file(const char* list, unsigned int format) { |
221cc3ce MT |
457 | PakfireFile head = NULL; |
458 | ||
459 | char* plist = (char *)list; | |
460 | char line[32 * 1024]; | |
461 | ||
462 | for (;;) { | |
463 | line[0] = '\0'; | |
464 | ||
465 | pakfire_sgets(line, sizeof(line), &plist); | |
466 | pakfire_remove_trailing_newline(line); | |
467 | ||
468 | if (*line == '\0') | |
469 | break; | |
470 | ||
471 | PakfireFile file = pakfire_file_parse_line(line, format); | |
472 | ||
473 | if (!file) | |
474 | continue; | |
475 | ||
476 | if (head) | |
477 | file = __pakfire_file_append(head, file); | |
478 | else | |
479 | head = file; | |
480 | } | |
481 | ||
482 | return head; | |
483 | } |