rdlar.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /* ----------------------------------------------------------------------- *
  2. *
  3. * Copyright 1996-2009 The NASM Authors - All Rights Reserved
  4. * See the file AUTHORS included with the NASM distribution for
  5. * the specific copyright holders.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following
  9. * conditions are met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * * Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following
  15. * disclaimer in the documentation and/or other materials provided
  16. * with the distribution.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  19. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  20. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  29. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  30. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. * ----------------------------------------------------------------------- */
  33. /*
  34. * rdlar.c - new librarian/archiver for RDOFF2.
  35. */
  36. #include "compiler.h"
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <ctype.h>
  40. #include <stdarg.h>
  41. #include <string.h>
  42. #include <errno.h>
  43. #include <time.h>
  44. #include <sys/types.h>
  45. #include <sys/stat.h>
  46. #include "rdlar.h"
  47. #define PROGRAM_VERSION "0.1"
  48. /** Constants **/
  49. const char commands[] = "adnrtx";
  50. const char modifiers[] = "cflouvV";
  51. /** Global variables **/
  52. char *progname = "rdlar";
  53. char **_argv = NULL;
  54. struct {
  55. bool createok;
  56. bool usefname;
  57. bool align;
  58. bool odate;
  59. bool fresh;
  60. int verbose;
  61. } options = {
  62. 0, 0, 0, 0, 0, 0};
  63. #define _ENDIANNESS 0 /* 0 for little, 1 for big */
  64. /*
  65. * Convert int32_t to little endian (if we were compiled on big-endian machine)
  66. */
  67. static void int32_ttolocal(int32_t *l)
  68. {
  69. #if _ENDIANNESS
  70. uint8_t t;
  71. uint8_t *p = (uint8_t *)l;
  72. t = p[0];
  73. p[0] = p[3];
  74. p[3] = t;
  75. t = p[1];
  76. p[1] = p[2];
  77. p[2] = p[1];
  78. #endif
  79. }
  80. /*
  81. * Print version information
  82. */
  83. void show_version(void)
  84. {
  85. puts("New RDOFF2 librarian/archiver, version " PROGRAM_VERSION);
  86. }
  87. /*
  88. * Print usage instructions
  89. */
  90. void usage(void)
  91. {
  92. printf("Usage: %s [-]{%s}[%s] libfile [module-name] [files]\n",
  93. progname, commands, modifiers);
  94. puts(" commands:\n"
  95. " a - add module(s) to the library\n"
  96. " d - delete module(s) from the library\n"
  97. " n - create the library\n"
  98. " r - replace module(s)\n"
  99. " t - display contents of library\n"
  100. " x - extract module(s)\n"
  101. " command specific modifiers:\n"
  102. " o - preserve original dates\n"
  103. " u - only replace modules that are newer than library contents\n"
  104. " generic modifiers:\n"
  105. " c - do not warn if the library had to be created\n"
  106. " f - use file name as a module name\n"
  107. " v - be verbose\n"
  108. " V - display version information");
  109. }
  110. /*
  111. * Print an error message and exit
  112. */
  113. void error_exit(int errcode, bool useperror, const char *fmt, ...)
  114. {
  115. va_list ap;
  116. fprintf(stderr, "%s: ", progname);
  117. va_start(ap, fmt);
  118. vfprintf(stderr, fmt, ap);
  119. va_end(ap);
  120. putc('\n', stderr);
  121. if (useperror)
  122. perror(progname);
  123. exit(errcode);
  124. }
  125. /*
  126. * Fill in and write a header
  127. */
  128. void put_header(struct rdlm_hdr *hdr, FILE * libfp, char *modname)
  129. {
  130. int n = 0;
  131. hdr->hdrsize = sizeof(*hdr);
  132. if (modname)
  133. hdr->hdrsize += (n = strlen(modname) + 1);
  134. if (libfp == NULL)
  135. return;
  136. if (fwrite(hdr, 1, sizeof(*hdr), libfp) != sizeof(*hdr) ||
  137. (modname && (fwrite(modname, 1, n, libfp) != n)))
  138. error_exit(3, true, "could not write header");
  139. }
  140. /*
  141. * Copy n bytes from one file to another and return last character read.
  142. */
  143. char copybytes(FILE * fp, FILE * fp2, int n)
  144. {
  145. int i, t = 0;
  146. for (i = 0; i < n; i++) {
  147. t = fgetc(fp);
  148. if (t == EOF)
  149. error_exit(1, false, "premature end of file in '%s'",
  150. _argv[2]);
  151. if (fp2)
  152. if (fputc(t, fp2) == EOF)
  153. error_exit(1, false, "write error");
  154. }
  155. return (char)t;
  156. }
  157. /*
  158. * Copy uint32_t from one file to another.
  159. * Return local presentation of int32_t.
  160. */
  161. int32_t copyint32_t(FILE * fp, FILE * fp2)
  162. {
  163. int32_t l;
  164. int i, t;
  165. uint8_t *p = (uint8_t *)&l;
  166. for (i = 0; i < 4; i++) {
  167. t = fgetc(fp);
  168. if (t == EOF)
  169. error_exit(1, false, "premature end of file in '%s'",
  170. _argv[2]);
  171. if (fp2)
  172. if (fputc(t, fp2) == EOF)
  173. error_exit(1, false, "write error");
  174. *p++ = t;
  175. }
  176. int32_ttolocal(&l);
  177. return l;
  178. }
  179. /*
  180. * Create a new library
  181. */
  182. int create_library(char *libname)
  183. {
  184. FILE *libfp;
  185. struct rdlm_hdr hdr;
  186. hdr.magic = RDLAMAG;
  187. hdr.hdrsize = 0;
  188. hdr.date = time(NULL);
  189. hdr.owner = getuid();
  190. hdr.group = getgid();
  191. hdr.mode = umask(022);
  192. hdr.size = 0;
  193. libfp = fopen(libname, "wb");
  194. if (!libfp)
  195. error_exit(1, true, "could not open '%s'\n", libname);
  196. /* Write library header */
  197. put_header(&hdr, libfp, NULL);
  198. fclose(libfp);
  199. return true;
  200. }
  201. /*
  202. * Add a module to the library
  203. */
  204. int add_module(FILE * libfp, const char *fname, char *modname)
  205. {
  206. FILE *modfp;
  207. struct rdlm_hdr hdr = { RDLMMAG, 0, 0, 0, 0, 0, 0 };
  208. struct stat finfo;
  209. int i;
  210. if (options.verbose)
  211. fprintf(stderr, "adding module %s\n", modname);
  212. /* Initialize some fields in the module header */
  213. if (stat(fname, &finfo) < 0)
  214. error_exit(1, true, "could not stat '%s'", fname);
  215. hdr.date = finfo.st_mtime;
  216. hdr.owner = finfo.st_uid;
  217. hdr.group = finfo.st_gid;
  218. hdr.size = finfo.st_size;
  219. modfp = fopen(fname, "rb");
  220. if (!modfp)
  221. error_exit(1, true, "could not open '%s'", fname);
  222. /* Write module header */
  223. put_header(&hdr, libfp, modname);
  224. /* Put the module itself */
  225. while (!feof(modfp)) {
  226. i = fgetc(modfp);
  227. if (i == EOF)
  228. break;
  229. if (fputc(i, libfp) == EOF)
  230. error_exit(1, false, "write error");
  231. }
  232. fclose(modfp);
  233. return true;
  234. }
  235. /*
  236. * Main
  237. */
  238. int main(int argc, char **argv)
  239. {
  240. FILE *libfp, *tmpfp, *modfp = NULL;
  241. struct stat finfo;
  242. struct rdlm_hdr hdr;
  243. char buf[MAXMODNAMELEN], *p = NULL;
  244. char c;
  245. int i;
  246. progname = argv[0];
  247. _argv = argv;
  248. if (argc < 2) {
  249. usage();
  250. exit(1);
  251. }
  252. rdoff_init();
  253. /* Check whether some modifiers were specified */
  254. for (i = 1; i < strlen(argv[1]); i++) {
  255. switch (c = argv[1][i]) {
  256. case 'c':
  257. options.createok = true;
  258. break;
  259. case 'f':
  260. options.usefname = true;
  261. break;
  262. case 'l':
  263. options.align = true;
  264. break;
  265. case 'o':
  266. options.odate = true;
  267. break;
  268. case 'u':
  269. options.fresh = true;
  270. break;
  271. case 'v':
  272. options.verbose++;
  273. break;
  274. case 'V':
  275. show_version();
  276. exit(0);
  277. default:
  278. if (strchr(commands, c) == NULL)
  279. error_exit(2, false, "invalid command or modifier '%c'",
  280. c);
  281. }
  282. }
  283. if (argc < 3)
  284. error_exit(2, false, "missing library name");
  285. /* Process the command */
  286. if (argv[1][0] == '-')
  287. argv[1]++;
  288. switch (c = argv[1][0]) {
  289. case 'a': /* add a module */
  290. if (argc < 4 || (!options.usefname && argc != 5))
  291. error_exit(2, false, "invalid number of arguments");
  292. /* Check if a library already exists. If not - create it */
  293. if (access(argv[2], F_OK) < 0) {
  294. if (!options.createok)
  295. fprintf(stderr, "creating library %s\n", argv[2]);
  296. create_library(argv[2]);
  297. }
  298. libfp = fopen(argv[2], "ab");
  299. if (!libfp)
  300. error_exit(1, true, "could not open '%s'", argv[2]);
  301. if (!options.usefname)
  302. add_module(libfp, argv[4], argv[3]);
  303. else
  304. for (i = 3; i < argc; i++)
  305. add_module(libfp, argv[i], argv[i]);
  306. fclose(libfp);
  307. break;
  308. case 'n': /* create library */
  309. create_library(argv[2]);
  310. break;
  311. case 'x': /* extract module(s) */
  312. if (!options.usefname)
  313. argc--;
  314. if (argc < 4)
  315. error_exit(2, false, "required parameter missing");
  316. p = options.usefname ? argv[3] : argv[4];
  317. case 't': /* list library contents */
  318. libfp = fopen(argv[2], "rb");
  319. if (!libfp)
  320. error_exit(1, true, "could not open '%s'\n", argv[2]);
  321. /* Read library header */
  322. if (fread(&hdr, 1, sizeof(hdr), libfp) != sizeof(hdr) ||
  323. hdr.magic != RDLAMAG)
  324. error_exit(1, false, "invalid library format");
  325. /* Walk through the library looking for requested module */
  326. while (!feof(libfp)) {
  327. /* Read module header */
  328. i = fread(&hdr, 1, sizeof(hdr), libfp);
  329. if (feof(libfp))
  330. break;
  331. if (i != sizeof(hdr) || hdr.magic != RDLMMAG)
  332. error_exit(1, false, "invalid module header");
  333. /* Read module name */
  334. i = hdr.hdrsize - sizeof(hdr);
  335. if (i > sizeof(buf) || fread(buf, 1, i, libfp) != i)
  336. error_exit(1, false, "invalid module name");
  337. if (c == 'x') {
  338. /* Check against desired name */
  339. if (!strcmp(buf, argv[3])) {
  340. if (options.verbose)
  341. fprintf(stderr,
  342. "extracting module %s to file %s\n", buf,
  343. p);
  344. modfp = fopen(p, "wb");
  345. if (!modfp)
  346. error_exit(1, true, "could not open '%s'", p);
  347. }
  348. } else {
  349. printf("%-40s ", buf);
  350. if (options.verbose) {
  351. printf("%ld bytes", hdr.size);
  352. }
  353. putchar('\n');
  354. }
  355. copybytes(libfp, modfp, hdr.size);
  356. if (modfp)
  357. break;
  358. }
  359. fclose(libfp);
  360. if (modfp)
  361. fclose(modfp);
  362. else if (c == 'x')
  363. error_exit(1, false, "module '%s' not found in '%s'",
  364. argv[3], argv[2]);
  365. break;
  366. case 'r': /* replace module(s) */
  367. argc--;
  368. if (stat(argv[4], &finfo) < 0)
  369. error_exit(1, true, "could not stat '%s'", argv[4]);
  370. case 'd': /* delete module(s) */
  371. if (argc < 4)
  372. error_exit(2, false, "required parameter missing");
  373. libfp = fopen(argv[2], "rb");
  374. if (!libfp)
  375. error_exit(1, true, "could not open '%s'", argv[2]);
  376. /* Copy the library into a temporary file */
  377. tmpfp = tmpfile();
  378. if (!tmpfp)
  379. error_exit(1, true, "could not open temporary file");
  380. stat(argv[2], &finfo);
  381. copybytes(libfp, tmpfp, finfo.st_size);
  382. rewind(tmpfp);
  383. freopen(argv[2], "wb", libfp);
  384. /* Read library header and write it to a new file */
  385. if (fread(&hdr, 1, sizeof(hdr), tmpfp) != sizeof(hdr) ||
  386. hdr.magic != RDLAMAG)
  387. error_exit(1, false, "invalid library format");
  388. put_header(&hdr, libfp, NULL);
  389. /* Walk through the library looking for requested module */
  390. while (!feof(tmpfp)) {
  391. /* Read module header */
  392. if (fread(&hdr, 1, sizeof(hdr), tmpfp) != sizeof(hdr) ||
  393. hdr.magic != RDLMMAG)
  394. error_exit(1, false, "invalid module header");
  395. /* Read module name */
  396. i = hdr.hdrsize - sizeof(hdr);
  397. if (i > sizeof(buf) || fread(buf, 1, i, tmpfp) != i)
  398. error_exit(1, false, "invalid module name");
  399. /* Check against desired name */
  400. if (!strcmp(buf, argv[3]) &&
  401. (c == 'd' || !options.odate
  402. || finfo.st_mtime <= hdr.date)) {
  403. if (options.verbose)
  404. fprintf(stderr, "deleting module %s\n", buf);
  405. fseek(tmpfp, hdr.size, SEEK_CUR);
  406. break;
  407. } else {
  408. put_header(&hdr, libfp, buf);
  409. copybytes(tmpfp, libfp, hdr.size);
  410. }
  411. }
  412. if (c == 'r') {
  413. /* Copy new module into library */
  414. p = options.usefname ? argv[4] : argv[3];
  415. add_module(libfp, argv[4], p);
  416. }
  417. /* Copy rest of library if any */
  418. while (!feof(tmpfp)) {
  419. if ((i = fgetc(tmpfp)) == EOF)
  420. break;
  421. if (fputc(i, libfp) == EOF)
  422. error_exit(1, false, "write error");
  423. }
  424. fclose(libfp);
  425. fclose(tmpfp);
  426. break;
  427. default:
  428. error_exit(2, false, "invalid command '%c'\n", c);
  429. }
  430. return 0;
  431. }