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