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