Branch data Line data Source code
1 : : /*
2 : : * dpkg-split - splitting and joining of multipart *.deb archives
3 : : * join.c - joining
4 : : *
5 : : * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
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 <https://www.gnu.org/licenses/>.
19 : : */
20 : :
21 : : #include <config.h>
22 : : #include <compat.h>
23 : :
24 : : #include <limits.h>
25 : : #include <string.h>
26 : : #include <fcntl.h>
27 : : #include <unistd.h>
28 : : #include <stdlib.h>
29 : : #include <stdio.h>
30 : :
31 : : #include <dpkg/i18n.h>
32 : : #include <dpkg/dpkg.h>
33 : : #include <dpkg/dpkg-db.h>
34 : : #include <dpkg/buffer.h>
35 : : #include <dpkg/options.h>
36 : :
37 : : #include "dpkg-split.h"
38 : :
39 : 1 : void reassemble(struct partinfo **partlist, const char *outputfile) {
40 : : struct dpkg_error err;
41 : : int fd_out;
42 : : int i;
43 : :
44 : 1 : printf(P_("Putting package %s together from %d part: ",
45 : : "Putting package %s together from %d parts: ",
46 : : partlist[0]->maxpartn),
47 : 1 : partlist[0]->package,partlist[0]->maxpartn);
48 : :
49 : 1 : fd_out = creat(outputfile, 0644);
50 [ - + ]: 1 : if (fd_out < 0)
51 : 0 : ohshite(_("unable to open output file '%.250s'"), outputfile);
52 [ + + ]: 11 : for (i=0; i<partlist[0]->maxpartn; i++) {
53 : 10 : struct partinfo *pi = partlist[i];
54 : : int fd_in;
55 : :
56 : 10 : fd_in = open(pi->filename, O_RDONLY);
57 [ - + ]: 10 : if (fd_in < 0)
58 : 0 : ohshite(_("unable to (re)open input part file '%.250s'"), pi->filename);
59 [ - + ]: 10 : if (fd_skip(fd_in, pi->headerlen, &err) < 0)
60 : 0 : ohshit(_("cannot skip split package header for '%s': %s"), pi->filename,
61 : : err.str);
62 [ - + ]: 10 : if (fd_fd_copy(fd_in, fd_out, pi->thispartlen, &err) < 0)
63 : 0 : ohshit(_("cannot append split package part '%s' to '%s': %s"),
64 : : pi->filename, outputfile, err.str);
65 : 10 : close(fd_in);
66 : :
67 : 10 : printf("%d ", i + 1);
68 : : }
69 [ - + ]: 1 : if (fsync(fd_out))
70 : 0 : ohshite(_("unable to sync file '%s'"), outputfile);
71 [ - + ]: 1 : if (close(fd_out))
72 : 0 : ohshite(_("unable to close file '%s'"), outputfile);
73 : :
74 : 1 : printf(_("done\n"));
75 : 1 : }
76 : :
77 : :
78 : 10 : void addtopartlist(struct partinfo **partlist,
79 : : struct partinfo *pi, struct partinfo *refi) {
80 : : int i;
81 : :
82 [ + - ]: 10 : if (strcmp(pi->package,refi->package) ||
83 [ + - ]: 10 : strcmp(pi->version,refi->version) ||
84 [ + - ]: 10 : strcmp(pi->md5sum,refi->md5sum) ||
85 [ + - ]: 10 : pi->orglength != refi->orglength ||
86 [ + - ]: 10 : pi->maxpartn != refi->maxpartn ||
87 [ - + ]: 10 : pi->maxpartlen != refi->maxpartlen) {
88 : 0 : print_info(pi);
89 : 0 : print_info(refi);
90 : 0 : ohshit(_("files '%.250s' and '%.250s' are not parts of the same file"),
91 : : pi->filename,refi->filename);
92 : : }
93 : 10 : i= pi->thispartn-1;
94 [ - + ]: 10 : if (partlist[i])
95 : 0 : ohshit(_("there are several versions of part %d - at least '%.250s' and '%.250s'"),
96 : 0 : pi->thispartn, pi->filename, partlist[i]->filename);
97 : 10 : partlist[i]= pi;
98 : 10 : }
99 : :
100 : : int
101 : 1 : do_join(const char *const *argv)
102 : : {
103 : : const char *thisarg;
104 : 1 : struct partqueue *queue = NULL;
105 : : struct partqueue *pq;
106 : : struct partinfo *refi, **partlist;
107 : : int i;
108 : :
109 [ - + ]: 1 : if (!*argv)
110 : 0 : badusage(_("--%s requires one or more part file arguments"),
111 : 0 : cipaction->olong);
112 [ + + ]: 11 : while ((thisarg= *argv++)) {
113 : 10 : pq = nfmalloc(sizeof(*pq));
114 : :
115 : 10 : mustgetpartinfo(thisarg,&pq->info);
116 : :
117 : 10 : pq->nextinqueue= queue;
118 : 10 : queue= pq;
119 : : }
120 : 1 : refi= NULL;
121 [ + + ]: 11 : for (pq= queue; pq; pq= pq->nextinqueue)
122 [ + + + + ]: 10 : if (!refi || pq->info.thispartn < refi->thispartn) refi= &pq->info;
123 [ - + ]: 1 : if (refi == NULL)
124 : 0 : internerr("empty deb part queue");
125 : :
126 : 1 : partlist = nfmalloc(sizeof(*partlist) * refi->maxpartn);
127 [ + + ]: 11 : for (i = 0; i < refi->maxpartn; i++)
128 : 10 : partlist[i] = NULL;
129 [ + + ]: 11 : for (pq= queue; pq; pq= pq->nextinqueue) {
130 : 10 : struct partinfo *pi = &pq->info;
131 : :
132 : 10 : addtopartlist(partlist,pi,refi);
133 : : }
134 [ + + ]: 11 : for (i=0; i<refi->maxpartn; i++) {
135 [ - + ]: 10 : if (!partlist[i]) ohshit(_("part %d is missing"),i+1);
136 : : }
137 [ - + ]: 1 : if (!opt_outputfile) {
138 : : char *p;
139 : :
140 : 0 : p= nfmalloc(strlen(refi->package)+1+strlen(refi->version)+sizeof(DEBEXT));
141 : 0 : strcpy(p,refi->package);
142 : 0 : strcat(p, "_");
143 : 0 : strcat(p,refi->version);
144 : 0 : strcat(p, "_");
145 [ # # ]: 0 : strcat(p, refi->arch ? refi->arch : "unknown");
146 : 0 : strcat(p,DEBEXT);
147 : 0 : opt_outputfile = p;
148 : : }
149 : 1 : reassemble(partlist, opt_outputfile);
150 : :
151 : 1 : return 0;
152 : : }
|