24 |
#include <assert.h> |
#include <assert.h> |
25 |
#include <errno.h> |
#include <errno.h> |
26 |
#include <getopt.h> |
#include <getopt.h> |
27 |
|
#include <grp.h> |
28 |
#include <libgen.h> |
#include <libgen.h> |
29 |
#include <limits.h> |
#include <limits.h> |
30 |
|
#include <linux/limits.h> |
31 |
#include <math.h> |
#include <math.h> |
32 |
|
#include <pwd.h> |
33 |
#include <stdarg.h> |
#include <stdarg.h> |
34 |
#include <stdbool.h> |
#include <stdbool.h> |
35 |
#include <stdio.h> |
#include <stdio.h> |
236 |
if (params.verbose) |
if (params.verbose) |
237 |
pinfo ("creating archive: %s\n", params.file); |
pinfo ("creating archive: %s\n", params.file); |
238 |
|
|
239 |
struct uar_archive *uar = uar_create_stream (); |
struct uar_archive *uar = uar_stream_create (); |
240 |
|
|
241 |
if (uar == NULL) |
if (uar == NULL) |
242 |
{ |
{ |
258 |
return; |
return; |
259 |
} |
} |
260 |
|
|
261 |
|
const char *base = basename (params.rtargets[i]); |
262 |
|
|
263 |
|
if (strcmp (base, ".") == 0 || strcmp (base, "..") == 0) |
264 |
|
base = basename (params.targets[i]); |
265 |
|
|
266 |
struct uar_file *file |
struct uar_file *file |
267 |
= uar_stream_add_entry (uar, basename (params.rtargets[i]), |
= uar_stream_add_entry (uar, base, params.rtargets[i], &stinfo); |
|
params.rtargets[i], &stinfo); |
|
268 |
|
|
269 |
if (file == NULL || uar_has_error (uar)) |
if (file == NULL || uar_has_error (uar)) |
270 |
{ |
{ |
360 |
format_iec_size (uint64_t size) |
format_iec_size (uint64_t size) |
361 |
{ |
{ |
362 |
static char buf[32] = { 0 }; |
static char buf[32] = { 0 }; |
363 |
const char suffix[] = { ' ', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' }; |
const char suffix[] = { 0, 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' }; |
364 |
size_t i = 0; |
size_t i = 0; |
365 |
long double computed = size; |
long double computed = size; |
366 |
|
|
370 |
i++; |
i++; |
371 |
} |
} |
372 |
|
|
373 |
snprintf (buf, sizeof (buf), "%.02Lf%c", computed, suffix[i]); |
if (computed == 0.00) |
374 |
|
{ |
375 |
|
snprintf (buf, sizeof (buf), "0%c", suffix[i]); |
376 |
|
return buf; |
377 |
|
} |
378 |
|
|
379 |
|
snprintf (buf, sizeof (buf), "%.2Lf%c", computed, suffix[i]); |
380 |
return buf; |
return buf; |
381 |
} |
} |
382 |
|
|
383 |
struct archive_file_info |
struct archive_file_info |
384 |
{ |
{ |
|
mode_t mode; |
|
385 |
const char *name; |
const char *name; |
386 |
|
char owner[128]; |
387 |
|
char group[128]; |
388 |
|
mode_t mode; |
389 |
time_t mtime; |
time_t mtime; |
390 |
union |
union |
391 |
{ |
{ |
399 |
{ |
{ |
400 |
struct archive_file_info *files; |
struct archive_file_info *files; |
401 |
size_t nfiles; |
size_t nfiles; |
402 |
int widths[1]; |
int widths[3]; |
403 |
}; |
}; |
404 |
|
|
405 |
#define TABLE_WIDTH_SIZE 1 |
#define TABLE_WIDTH_SIZE 0 |
406 |
|
#define TABLE_WIDTH_OWNER 1 |
407 |
|
#define TABLE_WIDTH_GROUP 2 |
408 |
|
|
409 |
static bool |
static bool |
410 |
list_archive_callback_analyze (struct uar_file *file, void *data) |
list_archive_callback_analyze (struct uar_file *file, void *data) |
421 |
info.name = name; |
info.name = name; |
422 |
info.mtime = uar_file_get_mtime (file); |
info.mtime = uar_file_get_mtime (file); |
423 |
|
|
424 |
|
uid_t uid = uar_file_get_uid (file); |
425 |
|
gid_t gid = uar_file_get_gid (file); |
426 |
|
|
427 |
|
struct passwd *pw = getpwuid (uid); |
428 |
|
struct group *gr = getgrgid (gid); |
429 |
|
|
430 |
|
if (pw == NULL) |
431 |
|
{ |
432 |
|
if (params.verbose) |
433 |
|
perr ("warning: failed to get user info (%i): %s\n", uid, |
434 |
|
strerror (errno)); |
435 |
|
|
436 |
|
strncpy (info.owner, "unknown", sizeof (info.owner) - 1); |
437 |
|
} |
438 |
|
else |
439 |
|
strncpy (info.owner, pw->pw_name, sizeof (info.owner) - 1); |
440 |
|
|
441 |
|
if (gr == NULL) |
442 |
|
{ |
443 |
|
if (params.verbose) |
444 |
|
perr ("warning: failed to get group info (%i): %s\n", gid, |
445 |
|
strerror (errno)); |
446 |
|
|
447 |
|
strncpy (info.group, "unknown", sizeof (info.group) - 1); |
448 |
|
} |
449 |
|
else |
450 |
|
strncpy (info.group, gr->gr_name, sizeof (info.group) - 1); |
451 |
|
|
452 |
if (params.hr_sizes) |
if (params.hr_sizes) |
453 |
{ |
{ |
454 |
char *str = format_iec_size (size); |
char *str = format_iec_size (size); |
464 |
if (size_len > table->widths[TABLE_WIDTH_SIZE]) |
if (size_len > table->widths[TABLE_WIDTH_SIZE]) |
465 |
table->widths[TABLE_WIDTH_SIZE] = size_len; |
table->widths[TABLE_WIDTH_SIZE] = size_len; |
466 |
|
|
467 |
|
int owner_len = strlen (info.owner); |
468 |
|
int group_len = strlen (info.group); |
469 |
|
|
470 |
|
if (owner_len > table->widths[TABLE_WIDTH_OWNER]) |
471 |
|
table->widths[TABLE_WIDTH_OWNER] = owner_len; |
472 |
|
|
473 |
|
if (group_len > table->widths[TABLE_WIDTH_GROUP]) |
474 |
|
table->widths[TABLE_WIDTH_GROUP] = group_len; |
475 |
|
|
476 |
table->files[table->nfiles++] = info; |
table->files[table->nfiles++] = info; |
477 |
return true; |
return true; |
478 |
} |
} |
482 |
{ |
{ |
483 |
assert (params.mode == MODE_LIST); |
assert (params.mode == MODE_LIST); |
484 |
struct archive_file_table *table = NULL; |
struct archive_file_table *table = NULL; |
485 |
struct uar_archive *uar = uar_open (params.file); |
struct uar_archive *uar = uar_stream_open (params.file); |
486 |
|
|
487 |
if (uar == NULL || uar_has_error (uar)) |
if (uar == NULL) |
488 |
{ |
{ |
489 |
pinfo ("failed to open archive: %s\n", strerror (errno)); |
pinfo ("failed to open archive file: %s\n", strerror (errno)); |
490 |
|
goto list_archive_end; |
491 |
|
} |
492 |
|
|
493 |
|
if (uar_has_error (uar)) |
494 |
|
{ |
495 |
|
pinfo ("failed to read archive: %s\n", uar_strerror (uar)); |
496 |
goto list_archive_end; |
goto list_archive_end; |
497 |
} |
} |
498 |
|
|
512 |
{ |
{ |
513 |
struct archive_file_info info = table->files[i]; |
struct archive_file_info info = table->files[i]; |
514 |
struct tm *tm = localtime (&info.mtime); |
struct tm *tm = localtime (&info.mtime); |
515 |
char mtime_str[10] = "none"; |
char mtime_str[10] = "never"; |
516 |
const char *mode_str = stringify_mode (info.mode); |
const char *mode_str = stringify_mode (info.mode); |
517 |
|
|
518 |
if (tm == NULL) |
if (tm == NULL) |
519 |
{ |
{ |
520 |
fprintf (stderr, |
if (params.verbose) |
521 |
"%s: warning: failed to convert time: %s\n", |
perr ("warning: failed to convert time: %s\n", |
522 |
progname, strerror (errno)); |
strerror (errno)); |
523 |
} |
} |
524 |
else |
else |
525 |
{ |
strftime (mtime_str, sizeof (mtime_str), "%b %d", tm); |
|
strftime (mtime_str, sizeof (mtime_str), "%b %d", tm); |
|
|
} |
|
526 |
|
|
527 |
if (params.hr_sizes) |
if (params.hr_sizes) |
528 |
{ |
fprintf (stdout, "%s %-*s %-*s %*s %s %s\n", mode_str, |
529 |
|
table->widths[TABLE_WIDTH_OWNER], info.owner, |
530 |
|
table->widths[TABLE_WIDTH_GROUP], info.group, |
531 |
|
table->widths[TABLE_WIDTH_SIZE], info.size.str, |
532 |
|
mtime_str, info.name); |
533 |
|
|
|
fprintf (stdout, "%s %*s %s %s\n", mode_str, |
|
|
table->widths[TABLE_WIDTH_SIZE], info.size.str, |
|
|
mtime_str, info.name); |
|
|
} |
|
534 |
else |
else |
535 |
{ |
fprintf (stdout, "%s %-*s %-*s %*lu %s %s\n", mode_str, |
536 |
|
table->widths[TABLE_WIDTH_OWNER], info.owner, |
537 |
fprintf (stdout, "%s %*lu %s %s\n", mode_str, |
table->widths[TABLE_WIDTH_GROUP], info.group, |
538 |
table->widths[TABLE_WIDTH_SIZE], info.size.bytes, |
table->widths[TABLE_WIDTH_SIZE], info.size.bytes, |
539 |
mtime_str, info.name); |
mtime_str, info.name); |
|
} |
|
540 |
} |
} |
541 |
|
|
542 |
list_archive_end: |
list_archive_end: |