Update Swedish translation
[dpkg/dpkg.git] / lib / dpkg / ar.c
1 /*
2  * libdpkg - Debian packaging suite library routines
3  * ar.c - primitives for ar handling
4  *
5  * Copyright © 2010 Guillem Jover <guillem@debian.org>
6  *
7  * This is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <compat.h>
23
24 #include <sys/types.h>
25 #include <sys/stat.h>
26
27 #include <time.h>
28 #include <stdint.h>
29 #include <unistd.h>
30
31 #include <dpkg/i18n.h>
32 #include <dpkg/dpkg.h>
33 #include <dpkg/fdio.h>
34 #include <dpkg/buffer.h>
35 #include <dpkg/ar.h>
36
37 void
38 dpkg_ar_normalize_name(struct ar_hdr *arh)
39 {
40         char *name = arh->ar_name;
41         int i;
42
43         /* Remove trailing spaces from the member name. */
44         for (i = sizeof(arh->ar_name) - 1; i >= 0 && name[i] == ' '; i--)
45                 name[i] = '\0';
46
47         /* Remove optional slash terminator (on GNU-style archives). */
48         if (name[i] == '/')
49                 name[i] = '\0';
50 }
51
52 off_t
53 dpkg_ar_member_get_size(const char *ar_name, struct ar_hdr *arh)
54 {
55         const char *str = arh->ar_size;
56         int len = sizeof(arh->ar_size);
57         off_t size = 0;
58
59         while (len && *str == ' ')
60                 str++, len--;
61
62         while (len--) {
63                 if (*str == ' ')
64                         break;
65                 if (*str < '0' || *str > '9')
66                         ohshit(_("invalid character '%c' in archive '%.250s' "
67                                  "member '%.16s' size"),
68                                *str, arh->ar_name, ar_name);
69
70                 size *= 10;
71                 size += *str++ - '0';
72         }
73
74         return size;
75 }
76
77 bool
78 dpkg_ar_member_is_illegal(struct ar_hdr *arh)
79 {
80         return memcmp(arh->ar_fmag, ARFMAG, sizeof(arh->ar_fmag)) != 0;
81 }
82
83 void
84 dpkg_ar_put_magic(const char *ar_name, int ar_fd)
85 {
86         if (fd_write(ar_fd, DPKG_AR_MAGIC, strlen(DPKG_AR_MAGIC)) < 0)
87                 ohshite(_("unable to write file '%s'"), ar_name);
88 }
89
90 void
91 dpkg_ar_member_put_header(const char *ar_name, int ar_fd,
92                           const char *name, off_t size)
93 {
94         char header[sizeof(struct ar_hdr) + 1];
95         int n;
96
97         if (strlen(name) > 15)
98                 ohshit(_("ar member name '%s' length too long"), name);
99         if (size > 9999999999L)
100                 ohshit(_("ar member size %jd too large"), size);
101
102         n = sprintf(header, "%-16s%-12lu0     0     100644  %-10jd`\n",
103                     name, time(NULL), (intmax_t)size);
104         if (n != sizeof(struct ar_hdr))
105                 ohshit(_("generated corrupt ar header for '%s'"), ar_name);
106
107         if (fd_write(ar_fd, header, n) < 0)
108                 ohshite(_("unable to write file '%s'"), ar_name);
109 }
110
111 void
112 dpkg_ar_member_put_mem(const char *ar_name, int ar_fd,
113                        const char *name, const void *data, size_t size)
114 {
115         dpkg_ar_member_put_header(ar_name, ar_fd, name, size);
116
117         /* Copy data contents. */
118         if (fd_write(ar_fd, data, size) < 0)
119                 ohshite(_("unable to write file '%s'"), ar_name);
120
121         if (size & 1)
122                 if (fd_write(ar_fd, "\n", 1) < 0)
123                         ohshite(_("unable to write file '%s'"), ar_name);
124 }
125
126 void
127 dpkg_ar_member_put_file(const char *ar_name, int ar_fd,
128                         const char *name, int fd, off_t size)
129 {
130         struct dpkg_error err;
131
132         if (size <= 0) {
133                 struct stat st;
134
135                 if (fstat(fd, &st))
136                         ohshite(_("failed to fstat ar member file (%s)"), name);
137                 size = st.st_size;
138         }
139
140         dpkg_ar_member_put_header(ar_name, ar_fd, name, size);
141
142         /* Copy data contents. */
143         if (fd_fd_copy(fd, ar_fd, size, &err) < 0)
144                 ohshit(_("cannot append ar member file (%s) to '%s': %s"),
145                        name, ar_name, err.str);
146
147         if (size & 1)
148                 if (fd_write(ar_fd, "\n", 1) < 0)
149                         ohshite(_("unable to write file '%s'"), ar_name);
150 }