1 /*
2  * dpkg-split - splitting and joining of multipart *.deb archives
3  * main.c - main program
4  *
5  * Copyright © 1994-1996 Ian Jackson <ijackson@chiark.greenend.org.uk>
6  * Copyright © 2006-2012 Guillem Jover <guillem@debian.org>
7  *
8  * This is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 #include <config.h>
22 #include <compat.h>
23 
24 #include <sys/types.h>
25 
26 #include <errno.h>
27 #include <limits.h>
28 #include <inttypes.h>
29 #if HAVE_LOCALE_H
30 #include <locale.h>
31 #endif
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 
36 #include <dpkg/macros.h>
37 #include <dpkg/i18n.h>
38 #include <dpkg/dpkg.h>
39 #include <dpkg/dpkg-db.h>
40 #include <dpkg/options.h>
41 
42 #include "dpkg-split.h"
43 
44 static void DPKG_ATTR_NORET
printversion(const struct cmdinfo * cip,const char * value)45 printversion(const struct cmdinfo *cip, const char *value)
46 {
47   printf(_("Debian '%s' package split/join tool; version %s.\n"),
48          SPLITTER, PACKAGE_RELEASE);
49 
50   printf(_(
51 "This is free software; see the GNU General Public License version 2 or\n"
52 "later for copying conditions. There is NO warranty.\n"));
53 
54   m_output(stdout, _("<standard output>"));
55 
56   exit(0);
57 }
58 
59 static void DPKG_ATTR_NORET
usage(const struct cmdinfo * cip,const char * value)60 usage(const struct cmdinfo *cip, const char *value)
61 {
62   printf(_(
63 "Usage: %s [<option> ...] <command>\n"
64 "\n"), SPLITTER);
65 
66   printf(_(
67 "Commands:\n"
68 "  -s|--split <file> [<prefix>]     Split an archive.\n"
69 "  -j|--join <part> <part> ...      Join parts together.\n"
70 "  -I|--info <part> ...             Display info about a part.\n"
71 "  -a|--auto -o <complete> <part>   Auto-accumulate parts.\n"
72 "  -l|--listq                       List unmatched pieces.\n"
73 "  -d|--discard [<filename> ...]    Discard unmatched pieces.\n"
74 "\n"));
75 
76   printf(_(
77 "  -?, --help                       Show this help message.\n"
78 "      --version                    Show the version.\n"
79 "\n"));
80 
81   printf(_(
82 "Options:\n"
83 "  --depotdir <directory>           Use <directory> instead of %s/%s.\n"
84 "  -S|--partsize <size>             In KiB, for -s (default is 450).\n"
85 "  -o|--output <file>               Filename, for -j (default is\n"
86 "                                     <package>_<version>_<arch>.deb).\n"
87 "  -Q|--npquiet                     Be quiet when -a is not a part.\n"
88 "  --msdos                          Generate 8.3 filenames.\n"
89 "\n"), ADMINDIR, PARTSDIR);
90 
91   printf(_(
92 "Exit status:\n"
93 "  0 = ok\n"
94 "  1 = with --auto, file is not a part\n"
95 "  2 = trouble\n"));
96 
97 
98   m_output(stdout, _("<standard output>"));
99 
100   exit(0);
101 }
102 
103 static const char printforhelp[] = N_("Type dpkg-split --help for help.");
104 
105 off_t opt_maxpartsize = SPLITPARTDEFMAX;
106 static const char *admindir;
107 const char *opt_depotdir;
108 const char *opt_outputfile = NULL;
109 int opt_npquiet = 0;
110 int opt_msdos = 0;
111 
112 void DPKG_ATTR_NORET
read_fail(int rc,const char * filename,const char * what)113 read_fail(int rc, const char *filename, const char *what)
114 {
115   if (rc >= 0)
116     ohshit(_("unexpected end of file in %s in %.255s"), what, filename);
117   else
118     ohshite(_("error reading %s from file %.255s"), what, filename);
119 }
120 
121 static void
set_part_size(const struct cmdinfo * cip,const char * value)122 set_part_size(const struct cmdinfo *cip, const char *value)
123 {
124   off_t newpartsize;
125   char *endp;
126 
127   errno = 0;
128   newpartsize = strtoimax(value, &endp, 10);
129   if (value == endp || *endp)
130     badusage(_("invalid integer for --%s: '%.250s'"), cip->olong, value);
131   if (newpartsize <= 0 || newpartsize > (INT_MAX >> 10) || errno == ERANGE)
132     badusage(_("part size is far too large or is not positive"));
133 
134   opt_maxpartsize = newpartsize << 10;
135   if (opt_maxpartsize <= HEADERALLOWANCE)
136     badusage(_("part size must be at least %d KiB (to allow for header)"),
137              (HEADERALLOWANCE >> 10) + 1);
138 }
139 
140 static const struct cmdinfo cmdinfos[]= {
141   ACTION("split",   's',  0,  do_split),
142   ACTION("join",    'j',  0,  do_join),
143   ACTION("info",    'I',  0,  do_info),
144   ACTION("auto",    'a',  0,  do_auto),
145   ACTION("listq",   'l',  0,  do_queue),
146   ACTION("discard", 'd',  0,  do_discard),
147 
148   { "help",         '?',  0,  NULL, NULL,             usage               },
149   { "version",       0,   0,  NULL, NULL,             printversion        },
150   { "depotdir",      0,   1,  NULL, &opt_depotdir,    NULL                },
151   { "partsize",     'S',  1,  NULL, NULL,             set_part_size       },
152   { "output",       'o',  1,  NULL, &opt_outputfile,  NULL                },
153   { "npquiet",      'Q',  0,  &opt_npquiet, NULL,     NULL,           1   },
154   { "msdos",         0,   0,  &opt_msdos, NULL,       NULL,           1   },
155   {  NULL,              0                                              }
156 };
157 
main(int argc,const char * const * argv)158 int main(int argc, const char *const *argv) {
159   int ret;
160 
161   dpkg_locales_init(PACKAGE);
162   dpkg_program_init(SPLITTER);
163   dpkg_options_parse(&argv, cmdinfos, printforhelp);
164 
165   admindir = dpkg_db_set_dir(admindir);
166   if (opt_depotdir == NULL)
167     opt_depotdir = dpkg_db_get_path(PARTSDIR);
168 
169   if (!cipaction) badusage(_("need an action option"));
170 
171   ret = cipaction->action(argv);
172 
173   m_output(stderr, _("<standard error>"));
174 
175   dpkg_program_done();
176 
177   return ret;
178 }
179