/[gentoo-projects]/pax-utils/paxinc.c
Gentoo

Contents of /pax-utils/paxinc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.16 - (show annotations) (download) (as text)
Wed Apr 10 22:16:45 2013 UTC (16 months, 2 weeks ago) by vapier
Branch: MAIN
CVS Tags: HEAD
Changes since 1.15: +6 -4 lines
File MIME type: text/x-csrc
ar_next: fix signed warnings from gcc, and clean up memory when closing archives

1 /*
2 * Copyright 2003-2012 Gentoo Foundation
3 * Distributed under the terms of the GNU General Public License v2
4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/paxinc.c,v 1.15 2012/11/04 07:26:24 vapier Exp $
5 *
6 * Copyright 2005-2012 Ned Ludd - <solar@gentoo.org>
7 * Copyright 2005-2012 Mike Frysinger - <vapier@gentoo.org>
8 */
9
10 /* stick common symbols here that are needed by paxinc.h */
11
12 #define IN_paxinc
13 #include "paxinc.h"
14
15 char do_reverse_endian;
16
17 /* some of this ar code was taken from busybox */
18
19 #define AR_MAGIC "!<arch>"
20 #define AR_MAGIC_SIZE (sizeof(AR_MAGIC)-1) /* dont count null byte */
21 archive_handle *ar_open_fd(const char *filename, int fd)
22 {
23 static archive_handle ret;
24 char buf[AR_MAGIC_SIZE];
25
26 ret.filename = filename;
27 ret.fd = fd;
28 ret.skip = 0;
29 ret.extfn = NULL;
30
31 if (read(ret.fd, buf, AR_MAGIC_SIZE) != AR_MAGIC_SIZE)
32 return NULL;
33 if (strncmp(buf, AR_MAGIC, AR_MAGIC_SIZE))
34 return NULL;
35
36 return &ret;
37 }
38 archive_handle *ar_open(const char *filename)
39 {
40 int fd;
41 archive_handle *ret;
42
43 if ((fd=open(filename, O_RDONLY)) == -1)
44 err("Could not open '%s'", filename);
45
46 ret = ar_open_fd(filename, fd);
47 if (ret == NULL)
48 close(fd);
49
50 return ret;
51 }
52
53 archive_member *ar_next(archive_handle *ar)
54 {
55 char *s;
56 ssize_t len = 0;
57 static archive_member ret;
58
59 if (ar->skip && lseek(ar->fd, ar->skip, SEEK_CUR) == -1) {
60 close_and_ret:
61 free(ar->extfn);
62 close(ar->fd);
63 ar->extfn = NULL;
64 ar->fd = -1;
65 return NULL;
66 }
67
68 if (read(ar->fd, ret.buf.raw, sizeof(ret.buf.raw)) != sizeof(ret.buf.raw))
69 goto close_and_ret;
70
71 /* ar header starts on an even byte (2 byte aligned)
72 * '\n' is used for padding */
73 if (ret.buf.raw[0] == '\n') {
74 memmove(ret.buf.raw, ret.buf.raw+1, 59);
75 if (read(ar->fd, ret.buf.raw+59, 1) != 1)
76 goto close_and_ret;
77 }
78
79 if ((ret.buf.formatted.magic[0] != '`') || (ret.buf.formatted.magic[1] != '\n')) {
80 warn("Invalid ar entry");
81 goto close_and_ret;
82 }
83
84 if (ret.buf.formatted.name[0] == '/' && ret.buf.formatted.name[1] == '/') {
85 if (ar->extfn != NULL) {
86 warn("Duplicate GNU extended filename section");
87 goto close_and_ret;
88 }
89 len = atoi(ret.buf.formatted.size);
90 ar->extfn = xmalloc(sizeof(char) * (len + 1));
91 if (read(ar->fd, ar->extfn, len) != len)
92 goto close_and_ret;
93 ar->extfn[len--] = '\0';
94 for (; len > 0; len--)
95 if (ar->extfn[len] == '\n')
96 ar->extfn[len] = '\0';
97 ar->skip = 0;
98 return ar_next(ar);
99 }
100
101 s = ret.buf.formatted.name;
102 if (s[0] == '#' && s[1] == '1' && s[2] == '/') {
103 /* BSD extended filename, always in use on Darwin */
104 len = atoi(s + 3);
105 if (len <= (ssize_t)sizeof(ret.buf.formatted.name)) {
106 if (read(ar->fd, ret.buf.formatted.name, len) != len)
107 goto close_and_ret;
108 } else {
109 s = alloca(sizeof(char) * len);
110 if (read(ar->fd, s, len) != len)
111 goto close_and_ret;
112 }
113 } else if (s[0] == '/' && s[1] >= '0' && s[1] <= '9') {
114 /* GNU extended filename */
115 if (ar->extfn == NULL) {
116 warn("GNU extended filename without special data section");
117 goto close_and_ret;
118 }
119 s = ar->extfn + atoi(s + 1);
120 }
121
122 snprintf(ret.name, sizeof(ret.name), "%s:%s", ar->filename, s);
123 if ((s=strchr(ret.name+strlen(ar->filename), '/')) != NULL)
124 *s = '\0';
125 ret.date = atoi(ret.buf.formatted.date);
126 ret.uid = atoi(ret.buf.formatted.uid);
127 ret.gid = atoi(ret.buf.formatted.gid);
128 ret.mode = strtol(ret.buf.formatted.mode, NULL, 8);
129 ret.size = atoi(ret.buf.formatted.size);
130 ar->skip = ret.size - len;
131
132 return &ret;
133 }
134
135 /* Convert file perms into octal string */
136 const char *strfileperms(const char *fname)
137 {
138 struct stat st;
139 static char buf[8];
140
141 if (stat(fname, &st) == -1)
142 return "";
143
144 snprintf(buf, sizeof(buf), "%o", st.st_mode);
145
146 return buf + 2;
147 }
148
149 /* Color helpers */
150 #define COLOR(c,b) "\e[" c ";" b "m"
151 const char *NORM = COLOR("00", "00");
152 const char *RED = COLOR("31", "01");
153 const char *YELLOW = COLOR("33", "01");
154
155 void color_init(bool disable)
156 {
157 if (!disable) {
158 const char *nocolor = getenv("NOCOLOR");
159 if (nocolor)
160 disable = !strcmp(nocolor, "yes") || !strcmp(nocolor, "true");
161 }
162 if (disable)
163 NORM = RED = YELLOW = "";
164 }

  ViewVC Help
Powered by ViewVC 1.1.20