1 /* Copyright 2015 the unarr project authors (see AUTHORS file).
2    License: LGPLv3 */
3 
4 #include "unarr-imp.h"
5 
ar_open_archive(ar_stream * stream,size_t struct_size,ar_archive_close_fn close,ar_parse_entry_fn parse_entry,ar_entry_get_name_fn get_name,ar_entry_uncompress_fn uncompress,ar_get_global_comment_fn get_comment,off64_t first_entry_offset)6 ar_archive *ar_open_archive(ar_stream *stream, size_t struct_size, ar_archive_close_fn close, ar_parse_entry_fn parse_entry,
7                             ar_entry_get_name_fn get_name, ar_entry_uncompress_fn uncompress, ar_get_global_comment_fn get_comment,
8                             off64_t first_entry_offset)
9 {
10     ar_archive *ar = malloc(struct_size);
11     if (!ar)
12         return NULL;
13     memset(ar, 0, struct_size);
14     ar->close = close;
15     ar->parse_entry = parse_entry;
16     ar->get_name = get_name;
17     ar->uncompress = uncompress;
18     ar->get_comment = get_comment;
19     ar->stream = stream;
20     ar->entry_offset_first = first_entry_offset;
21     ar->entry_offset_next = first_entry_offset;
22     return ar;
23 }
24 
ar_close_archive(ar_archive * ar)25 void ar_close_archive(ar_archive *ar)
26 {
27     if (ar)
28         ar->close(ar);
29     free(ar);
30 }
31 
ar_at_eof(ar_archive * ar)32 bool ar_at_eof(ar_archive *ar)
33 {
34     return ar->at_eof;
35 }
36 
ar_parse_entry(ar_archive * ar)37 bool ar_parse_entry(ar_archive *ar)
38 {
39     return ar->parse_entry(ar, ar->entry_offset_next);
40 }
41 
ar_parse_entry_at(ar_archive * ar,off64_t offset)42 bool ar_parse_entry_at(ar_archive *ar, off64_t offset)
43 {
44     ar->at_eof = false;
45     return ar->parse_entry(ar, offset ? offset : ar->entry_offset_first);
46 }
47 
ar_parse_entry_for(ar_archive * ar,const char * entry_name)48 bool ar_parse_entry_for(ar_archive *ar, const char *entry_name)
49 {
50     ar->at_eof = false;
51     if (!entry_name)
52         return false;
53     if (!ar_parse_entry_at(ar, ar->entry_offset_first))
54         return false;
55     do {
56         const char *name = ar_entry_get_name(ar);
57         if (name && strcmp(name, entry_name) == 0)
58             return true;
59     } while (ar_parse_entry(ar));
60     return false;
61 }
62 
ar_entry_get_name(ar_archive * ar)63 const char *ar_entry_get_name(ar_archive *ar)
64 {
65     return ar->get_name(ar);
66 }
67 
ar_entry_get_offset(ar_archive * ar)68 off64_t ar_entry_get_offset(ar_archive *ar)
69 {
70     return ar->entry_offset;
71 }
72 
ar_entry_get_size(ar_archive * ar)73 size_t ar_entry_get_size(ar_archive *ar)
74 {
75     return ar->entry_size_uncompressed;
76 }
77 
ar_entry_get_filetime(ar_archive * ar)78 time64_t ar_entry_get_filetime(ar_archive *ar)
79 {
80     return ar->entry_filetime;
81 }
82 
ar_entry_uncompress(ar_archive * ar,void * buffer,size_t count)83 bool ar_entry_uncompress(ar_archive *ar, void *buffer, size_t count)
84 {
85     return ar->uncompress(ar, buffer, count);
86 }
87 
ar_get_global_comment(ar_archive * ar,void * buffer,size_t count)88 size_t ar_get_global_comment(ar_archive *ar, void *buffer, size_t count)
89 {
90     if (!ar->get_comment)
91         return 0;
92     return ar->get_comment(ar, buffer, count);
93 }
94 
ar_log(const char * prefix,const char * file,int line,const char * msg,...)95 void ar_log(const char *prefix, const char *file, int line, const char *msg, ...)
96 {
97     va_list args;
98     va_start(args, msg);
99     if (prefix)
100         fprintf(stderr, "%s ", prefix);
101     if (strrchr(file, '/'))
102         file = strrchr(file, '/') + 1;
103     if (strrchr(file, '\\'))
104         file = strrchr(file, '\\') + 1;
105     fprintf(stderr, "%s:%d: ", file, line);
106     vfprintf(stderr, msg, args);
107     fprintf(stderr, "\n");
108     va_end(args);
109 }
110