mkisofs.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423
  1. /*
  2. * Program mkisofs.c - generate iso9660 filesystem based upon directory
  3. * tree on hard disk.
  4. Written by Eric Youngdale (1993).
  5. Copyright 1993 Yggdrasil Computing, Incorporated
  6. Copyright (C) 2009,2010 Free Software Foundation, Inc.
  7. This program 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 3, or (at your option)
  10. any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <errno.h>
  19. #include "config.h"
  20. #include "mkisofs.h"
  21. #include "match.h"
  22. #include "getopt.h"
  23. #include "iso9660.h"
  24. #include <ctype.h>
  25. #ifndef VMS
  26. #include <time.h>
  27. #else
  28. #include <sys/time.h>
  29. #include "vms.h"
  30. #endif
  31. #include <stdlib.h>
  32. #include <sys/stat.h>
  33. #ifndef VMS
  34. #ifdef HAVE_UNISTD_H
  35. #include <unistd.h>
  36. #endif
  37. #endif
  38. #include <fctldefs.h>
  39. #include "exclude.h"
  40. #ifdef __NetBSD__
  41. #include <sys/time.h>
  42. #include <sys/resource.h>
  43. #endif
  44. struct directory * root = NULL;
  45. static char version_string[] = "mkisofs 1.12b5";
  46. #include "progname.h"
  47. char * outfile;
  48. FILE * discimage;
  49. uint64_t next_extent = 0;
  50. uint64_t last_extent = 0;
  51. uint64_t session_start = 0;
  52. unsigned int path_table_size = 0;
  53. unsigned int path_table[4] = {0,};
  54. unsigned int path_blocks = 0;
  55. unsigned int jpath_table_size = 0;
  56. unsigned int jpath_table[4] = {0,};
  57. unsigned int jpath_blocks = 0;
  58. struct iso_directory_record root_record;
  59. struct iso_directory_record jroot_record;
  60. char * extension_record = NULL;
  61. int extension_record_extent = 0;
  62. int extension_record_size = 0;
  63. /* These variables are associated with command line options */
  64. int use_eltorito = 0;
  65. int use_eltorito_emul_floppy = 0;
  66. int use_embedded_boot = 0;
  67. int use_protective_msdos_label = 0;
  68. int use_boot_info_table = 0;
  69. int use_RockRidge = 0;
  70. int use_Joliet = 0;
  71. int verbose = 1;
  72. int all_files = 0;
  73. int follow_links = 0;
  74. int rationalize = 0;
  75. int generate_tables = 0;
  76. int print_size = 0;
  77. int split_output = 0;
  78. char *preparer = PREPARER_DEFAULT;
  79. char *publisher = PUBLISHER_DEFAULT;
  80. char *appid = APPID_DEFAULT;
  81. char *copyright = COPYRIGHT_DEFAULT;
  82. char *biblio = BIBLIO_DEFAULT;
  83. char *abstract = ABSTRACT_DEFAULT;
  84. char *volset_id = VOLSET_ID_DEFAULT;
  85. char *volume_id = VOLUME_ID_DEFAULT;
  86. char *system_id = SYSTEM_ID_DEFAULT;
  87. char *boot_catalog = BOOT_CATALOG_DEFAULT;
  88. char *boot_image = BOOT_IMAGE_DEFAULT;
  89. char *boot_image_embed = NULL;
  90. int volume_set_size = 1;
  91. int volume_sequence_number = 1;
  92. int omit_period = 0; /* Violates iso9660, but these are a pain */
  93. int transparent_compression = 0; /* So far only works with linux */
  94. int omit_version_number = 0; /* May violate iso9660, but noone uses vers*/
  95. unsigned int RR_relocation_depth = 6; /* Violates iso9660, but most systems work */
  96. int full_iso9660_filenames = 0; /* Used with Amiga. Disc will not work with
  97. DOS */
  98. int allow_leading_dots = 0; /* DOS cannot read names with leading dots */
  99. int split_SL_component = 1; /* circumvent a bug in the SunOS driver */
  100. int split_SL_field = 1; /* circumvent a bug in the SunOS */
  101. struct rcopts{
  102. char * tag;
  103. char ** variable;
  104. };
  105. struct rcopts rcopt[] = {
  106. {"PREP", &preparer},
  107. {"PUBL", &publisher},
  108. {"APPI", &appid},
  109. {"COPY", &copyright},
  110. {"BIBL", &biblio},
  111. {"ABST", &abstract},
  112. {"VOLS", &volset_id},
  113. {"VOLI", &volume_id},
  114. {"SYSI", &system_id},
  115. {NULL, NULL}
  116. };
  117. /*
  118. * In case it isn't obvious, the option handling code was ripped off from GNU-ld.
  119. */
  120. struct ld_option
  121. {
  122. /* The long option information. */
  123. struct option opt;
  124. /* The short option with the same meaning ('\0' if none). */
  125. char shortopt;
  126. /* The name of the argument (NULL if none). */
  127. const char *arg;
  128. /* The documentation string. If this is NULL, this is a synonym for
  129. the previous option. */
  130. const char *doc;
  131. enum
  132. {
  133. /* Use one dash before long option name. */
  134. ONE_DASH,
  135. /* Use two dashes before long option name. */
  136. TWO_DASHES,
  137. /* Don't mention this option in --help output. */
  138. NO_HELP
  139. } control;
  140. };
  141. /* Codes used for the long options with no short synonyms. 150 isn't
  142. special; it's just an arbitrary non-ASCII char value. */
  143. #define OPTION_HELP 150
  144. #define OPTION_QUIET 151
  145. #define OPTION_NOSPLIT_SL_COMPONENT 152
  146. #define OPTION_NOSPLIT_SL_FIELD 153
  147. #define OPTION_PRINT_SIZE 154
  148. #define OPTION_SPLIT_OUTPUT 155
  149. #define OPTION_ABSTRACT 156
  150. #define OPTION_BIBLIO 157
  151. #define OPTION_COPYRIGHT 158
  152. #define OPTION_SYSID 159
  153. #define OPTION_VOLSET 160
  154. #define OPTION_VOLSET_SIZE 161
  155. #define OPTION_VOLSET_SEQ_NUM 162
  156. #define OPTION_I_HIDE 163
  157. #define OPTION_J_HIDE 164
  158. #define OPTION_LOG_FILE 165
  159. #define OPTION_CREAT_DATE 166
  160. #define OPTION_MODIF_DATE 167
  161. #define OPTION_EXPIR_DATE 168
  162. #define OPTION_EFFEC_DATE 169
  163. #define OPTION_BOOT_INFO_TABLE 170
  164. #define OPTION_NO_EMUL_BOOT 171
  165. #define OPTION_ELTORITO_EMUL_FLOPPY 172
  166. #define OPTION_VERSION 173
  167. #define OPTION_PROTECTIVE_MSDOS_LABEL 174
  168. static const struct ld_option ld_options[] =
  169. {
  170. { {"all-files", no_argument, NULL, 'a'},
  171. 'a', NULL, N_("Process all files (don't skip backup files)"), ONE_DASH },
  172. { {"abstract", required_argument, NULL, OPTION_ABSTRACT},
  173. '\0', N_("FILE"), N_("Set Abstract filename"), ONE_DASH },
  174. { {"appid", required_argument, NULL, 'A'},
  175. 'A', N_("ID"), N_("Set Application ID"), ONE_DASH },
  176. { {"biblio", required_argument, NULL, OPTION_BIBLIO},
  177. '\0', N_("FILE"), N_("Set Bibliographic filename"), ONE_DASH },
  178. { {"copyright", required_argument, NULL, OPTION_COPYRIGHT},
  179. '\0', N_("FILE"), N_("Set Copyright filename"), ONE_DASH },
  180. { {"embedded-boot", required_argument, NULL, 'G'},
  181. 'G', N_("FILE"), N_("Set embedded boot image name"), TWO_DASHES },
  182. { {"protective-msdos-label", no_argument, NULL, OPTION_PROTECTIVE_MSDOS_LABEL },
  183. '\0', NULL, N_("Patch a protective DOS-style label in the image"), TWO_DASHES },
  184. { {"eltorito-boot", required_argument, NULL, 'b'},
  185. 'b', N_("FILE"), N_("Set El Torito boot image name"), ONE_DASH },
  186. { {"eltorito-catalog", required_argument, NULL, 'c'},
  187. 'c', N_("FILE"), N_("Set El Torito boot catalog name"), ONE_DASH },
  188. { {"boot-info-table", no_argument, NULL, OPTION_BOOT_INFO_TABLE },
  189. '\0', NULL, N_("Patch Boot Info Table in El Torito boot image"), ONE_DASH },
  190. { {"no-emul-boot", no_argument, NULL, OPTION_NO_EMUL_BOOT },
  191. '\0', NULL, N_("Dummy option for backward compatibility"), ONE_DASH },
  192. { {"eltorito-emul-floppy", no_argument, NULL, OPTION_ELTORITO_EMUL_FLOPPY },
  193. '\0', NULL, N_("Enable floppy drive emulation for El Torito"), TWO_DASHES },
  194. { {"cdwrite-params", required_argument, NULL, 'C'},
  195. 'C', N_("PARAMS"), N_("Magic parameters from cdrecord"), ONE_DASH },
  196. { {"omit-period", no_argument, NULL, 'd'},
  197. 'd', NULL, N_("Omit trailing periods from filenames"), ONE_DASH },
  198. { {"disable-deep-relocation", no_argument, NULL, 'D'},
  199. 'D', NULL, N_("Disable deep directory relocation"), ONE_DASH },
  200. { {"follow-links", no_argument, NULL, 'f'},
  201. 'f', NULL, N_("Follow symbolic links"), ONE_DASH },
  202. { {"help", no_argument, NULL, OPTION_HELP},
  203. '\0', NULL, N_("Print option help"), ONE_DASH },
  204. { {"help", no_argument, NULL, OPTION_HELP},
  205. '\0', NULL, N_("Print option help"), TWO_DASHES },
  206. { {"version", no_argument, NULL, OPTION_VERSION},
  207. '\0', NULL, N_("Print version information and exit"), TWO_DASHES },
  208. { {"hide", required_argument, NULL, OPTION_I_HIDE},
  209. '\0', N_("GLOBFILE"), N_("Hide ISO9660/RR file"), ONE_DASH },
  210. { {"hide-joliet", required_argument, NULL, OPTION_J_HIDE},
  211. '\0', N_("GLOBFILE"), N_("Hide Joliet file"), ONE_DASH },
  212. { {NULL, required_argument, NULL, 'i'},
  213. 'i', N_("ADD_FILES"), N_("No longer supported"), TWO_DASHES },
  214. { {"joliet", no_argument, NULL, 'J'},
  215. 'J', NULL, N_("Generate Joliet directory information"), ONE_DASH },
  216. { {"full-iso9660-filenames", no_argument, NULL, 'l'},
  217. 'l', NULL, N_("Allow full 32 character filenames for iso9660 names"), ONE_DASH },
  218. { {"allow-leading-dots", no_argument, NULL, 'L'},
  219. 'L', NULL, N_("Allow iso9660 filenames to start with '.'"), ONE_DASH },
  220. { {"log-file", required_argument, NULL, OPTION_LOG_FILE},
  221. '\0', N_("LOG_FILE"), N_("Re-direct messages to LOG_FILE"), ONE_DASH },
  222. { {"exclude", required_argument, NULL, 'm'},
  223. 'm', N_("GLOBFILE"), N_("Exclude file name"), ONE_DASH },
  224. { {"prev-session", required_argument, NULL, 'M'},
  225. 'M', N_("FILE"), N_("Set path to previous session to merge"), ONE_DASH },
  226. { {"omit-version-number", no_argument, NULL, 'N'},
  227. 'N', NULL, N_("Omit version number from iso9660 filename"), ONE_DASH },
  228. { {"no-split-symlink-components", no_argument, NULL, 0},
  229. 0, NULL, N_("Inhibit splitting symlink components"), ONE_DASH },
  230. { {"no-split-symlink-fields", no_argument, NULL, 0},
  231. 0, NULL, N_("Inhibit splitting symlink fields"), ONE_DASH },
  232. { {"output", required_argument, NULL, 'o'},
  233. 'o', N_("FILE"), N_("Set output file name"), ONE_DASH },
  234. { {"preparer", required_argument, NULL, 'p'},
  235. 'p', N_("PREP"), N_("Set Volume preparer"), ONE_DASH },
  236. { {"print-size", no_argument, NULL, OPTION_PRINT_SIZE},
  237. '\0', NULL, N_("Print estimated filesystem size and exit"), ONE_DASH },
  238. { {"publisher", required_argument, NULL, 'P'},
  239. 'P', N_("PUB"), N_("Set Volume publisher"), ONE_DASH },
  240. { {"quiet", no_argument, NULL, OPTION_QUIET},
  241. '\0', NULL, N_("Run quietly"), ONE_DASH },
  242. { {"rational-rock", no_argument, NULL, 'r'},
  243. 'r', NULL, N_("Generate rationalized Rock Ridge directory information"), ONE_DASH },
  244. { {"rock", no_argument, NULL, 'R'},
  245. 'R', NULL, N_("Generate Rock Ridge directory information"), ONE_DASH },
  246. { {"split-output", no_argument, NULL, OPTION_SPLIT_OUTPUT},
  247. '\0', NULL, N_("Split output into files of approx. 1GB size"), ONE_DASH },
  248. { {"sysid", required_argument, NULL, OPTION_SYSID},
  249. '\0', N_("ID"), N_("Set System ID"), ONE_DASH },
  250. { {"translation-table", no_argument, NULL, 'T'},
  251. 'T', NULL, N_("Generate translation tables for systems that don't understand long filenames"), ONE_DASH },
  252. { {"verbose", no_argument, NULL, 'v'},
  253. 'v', NULL, N_("Verbose"), ONE_DASH },
  254. { {"volid", required_argument, NULL, 'V'},
  255. 'V', N_("ID"), N_("Set Volume ID"), ONE_DASH },
  256. { {"volset", required_argument, NULL, OPTION_VOLSET},
  257. '\0', N_("ID"), N_("Set Volume set ID"), ONE_DASH },
  258. { {"volset-size", required_argument, NULL, OPTION_VOLSET_SIZE},
  259. '\0', "#", N_("Set Volume set size"), ONE_DASH },
  260. { {"volset-seqno", required_argument, NULL, OPTION_VOLSET_SEQ_NUM},
  261. '\0', "#", N_("Set Volume set sequence number"), ONE_DASH },
  262. { {"old-exclude", required_argument, NULL, 'x'},
  263. 'x', N_("FILE"), N_("Exclude file name (deprecated)"), ONE_DASH },
  264. #ifdef ERIC_neverdef
  265. { {"transparent-compression", no_argument, NULL, 'z'},
  266. 'z', NULL, "Enable transparent compression of files", ONE_DASH },
  267. #endif
  268. { {"creation-date", required_argument, NULL, OPTION_CREAT_DATE },
  269. '\0', NULL, N_("Override creation date"), TWO_DASHES },
  270. { {"modification-date", required_argument, NULL, OPTION_MODIF_DATE },
  271. '\0', NULL, N_("Override modification date"), TWO_DASHES },
  272. { {"expiration-date", required_argument, NULL, OPTION_EXPIR_DATE },
  273. '\0', NULL, N_("Override expiration date"), TWO_DASHES },
  274. { {"effective-date", required_argument, NULL, OPTION_EFFEC_DATE },
  275. '\0', NULL, N_("Override effective date"), TWO_DASHES },
  276. };
  277. #define OPTION_COUNT (sizeof ld_options / sizeof ld_options[0])
  278. #if defined(ultrix) || defined(_AUX_SOURCE)
  279. char *strdup(s)
  280. char *s;{char *c;if(c=(char *)malloc(strlen(s)+1))strcpy(c,s);return c;}
  281. #endif
  282. void read_rcfile __PR((char * appname));
  283. void usage __PR((void));
  284. static void hide_reloc_dir __PR((void));
  285. void FDECL1(read_rcfile, char *, appname)
  286. {
  287. FILE * rcfile;
  288. struct rcopts * rco;
  289. char * pnt, *pnt1;
  290. char linebuffer[256];
  291. static char rcfn[] = ".mkisofsrc";
  292. char filename[1000];
  293. int linum;
  294. strcpy(filename, rcfn);
  295. rcfile = fopen(filename, "r");
  296. if (!rcfile && errno != ENOENT)
  297. perror(filename);
  298. if (!rcfile)
  299. {
  300. pnt = getenv("MKISOFSRC");
  301. if (pnt && strlen(pnt) <= sizeof(filename))
  302. {
  303. strcpy(filename, pnt);
  304. rcfile = fopen(filename, "r");
  305. if (!rcfile && errno != ENOENT)
  306. perror(filename);
  307. }
  308. }
  309. if (!rcfile)
  310. {
  311. pnt = getenv("HOME");
  312. if (pnt && strlen(pnt) + strlen(rcfn) + 2 <= sizeof(filename))
  313. {
  314. strcpy(filename, pnt);
  315. strcat(filename, "/");
  316. strcat(filename, rcfn);
  317. rcfile = fopen(filename, "r");
  318. if (!rcfile && errno != ENOENT)
  319. perror(filename);
  320. }
  321. }
  322. if (!rcfile && strlen(appname)+sizeof(rcfn)+2 <= sizeof(filename))
  323. {
  324. strcpy(filename, appname);
  325. pnt = strrchr(filename, '/');
  326. if (pnt)
  327. {
  328. strcpy(pnt + 1, rcfn);
  329. rcfile = fopen(filename, "r");
  330. if (!rcfile && errno != ENOENT)
  331. perror(filename);
  332. }
  333. }
  334. if (!rcfile)
  335. return;
  336. if ( verbose > 0 )
  337. {
  338. fprintf (stderr, _("Using \"%s\"\n"), filename);
  339. }
  340. /* OK, we got it. Now read in the lines and parse them */
  341. linum = 0;
  342. while (fgets(linebuffer, sizeof(linebuffer), rcfile))
  343. {
  344. char *name;
  345. char *name_end;
  346. ++linum;
  347. /* skip any leading white space */
  348. pnt = linebuffer;
  349. while (*pnt == ' ' || *pnt == '\t')
  350. ++pnt;
  351. /* If we are looking at a # character, this line is a comment. */
  352. if (*pnt == '#')
  353. continue;
  354. /* The name should begin in the left margin. Make sure it is in
  355. upper case. Stop when we see white space or a comment. */
  356. name = pnt;
  357. while (*pnt && isalpha((unsigned char)*pnt))
  358. {
  359. if(islower((unsigned char)*pnt))
  360. *pnt = toupper((unsigned char)*pnt);
  361. pnt++;
  362. }
  363. if (name == pnt)
  364. {
  365. fprintf(stderr, _("%s:%d: name required\n"), filename, linum);
  366. continue;
  367. }
  368. name_end = pnt;
  369. /* Skip past white space after the name */
  370. while (*pnt == ' ' || *pnt == '\t')
  371. pnt++;
  372. /* silently ignore errors in the rc file. */
  373. if (*pnt != '=')
  374. {
  375. fprintf (stderr, _("%s:%d: equals sign required\n"), filename, linum);
  376. continue;
  377. }
  378. /* Skip pas the = sign, and any white space following it */
  379. pnt++; /* Skip past '=' sign */
  380. while (*pnt == ' ' || *pnt == '\t')
  381. pnt++;
  382. /* now it is safe to NUL terminate the name */
  383. *name_end = 0;
  384. /* Now get rid of trailing newline */
  385. pnt1 = pnt;
  386. while (*pnt1)
  387. {
  388. if (*pnt1 == '\n')
  389. {
  390. *pnt1 = 0;
  391. break;
  392. }
  393. pnt1++;
  394. };
  395. /* OK, now figure out which option we have */
  396. for(rco = rcopt; rco->tag; rco++) {
  397. if(strcmp(rco->tag, name) == 0)
  398. {
  399. *rco->variable = strdup(pnt);
  400. break;
  401. };
  402. }
  403. if (rco->tag == NULL)
  404. {
  405. fprintf (stderr, _("%s:%d: field name \"%s\" unknown\n"), filename, linum,
  406. name);
  407. }
  408. }
  409. if (ferror(rcfile))
  410. perror(filename);
  411. fclose(rcfile);
  412. }
  413. char * path_table_l = NULL;
  414. char * path_table_m = NULL;
  415. char * jpath_table_l = NULL;
  416. char * jpath_table_m = NULL;
  417. int goof = 0;
  418. #ifndef TRUE
  419. #define TRUE 1
  420. #endif
  421. #ifndef FALSE
  422. #define FALSE 0
  423. #endif
  424. void usage(){
  425. unsigned int i;
  426. /* const char **targets, **pp;*/
  427. printf (_("Usage: %s [options] file...\n"), program_name);
  428. printf (_("Options:\n"));
  429. for (i = 0; i < OPTION_COUNT; i++)
  430. {
  431. if (ld_options[i].doc != NULL)
  432. {
  433. int comma;
  434. int len;
  435. unsigned int j;
  436. const char *arg;
  437. printf (" ");
  438. comma = FALSE;
  439. len = 2;
  440. j = i;
  441. do
  442. {
  443. if (ld_options[j].shortopt != '\0'
  444. && ld_options[j].control != NO_HELP)
  445. {
  446. printf ("%s-%c", comma ? ", " : "", ld_options[j].shortopt);
  447. len += (comma ? 2 : 0) + 2;
  448. if (ld_options[j].arg != NULL)
  449. {
  450. if (ld_options[j].opt.has_arg != optional_argument)
  451. {
  452. putchar (' ');
  453. ++len;
  454. }
  455. arg = gettext (ld_options[j].arg);
  456. printf ("%s", arg);
  457. len += strlen (arg);
  458. }
  459. comma = TRUE;
  460. }
  461. ++j;
  462. }
  463. while (j < OPTION_COUNT && ld_options[j].doc == NULL);
  464. j = i;
  465. do
  466. {
  467. if (ld_options[j].opt.name != NULL
  468. && ld_options[j].control != NO_HELP)
  469. {
  470. printf ("%s-%s%s",
  471. comma ? ", " : "",
  472. ld_options[j].control == TWO_DASHES ? "-" : "",
  473. ld_options[j].opt.name);
  474. len += ((comma ? 2 : 0)
  475. + 1
  476. + (ld_options[j].control == TWO_DASHES ? 1 : 0)
  477. + strlen (ld_options[j].opt.name));
  478. if (ld_options[j].arg != NULL)
  479. {
  480. arg = gettext (ld_options[j].arg);
  481. printf (" %s", arg);
  482. len += 1 + strlen (arg);
  483. }
  484. comma = TRUE;
  485. }
  486. ++j;
  487. }
  488. while (j < OPTION_COUNT && ld_options[j].doc == NULL);
  489. if (len >= 30)
  490. {
  491. printf ("\n");
  492. len = 0;
  493. }
  494. for (; len < 30; len++)
  495. putchar (' ');
  496. printf ("%s\n", gettext (ld_options[i].doc));
  497. }
  498. }
  499. exit(1);
  500. }
  501. /*
  502. * Fill in date in the iso9660 format
  503. *
  504. * The standards state that the timezone offset is in multiples of 15
  505. * minutes, and is what you add to GMT to get the localtime. The U.S.
  506. * is always at a negative offset, from -5h to -8h (can vary a little
  507. * with DST, I guess). The Linux iso9660 filesystem has had the sign
  508. * of this wrong for ages (mkisofs had it wrong too for the longest time).
  509. */
  510. int FDECL2(iso9660_date,char *, result, time_t, crtime){
  511. struct tm *local;
  512. local = localtime(&crtime);
  513. result[0] = local->tm_year;
  514. result[1] = local->tm_mon + 1;
  515. result[2] = local->tm_mday;
  516. result[3] = local->tm_hour;
  517. result[4] = local->tm_min;
  518. result[5] = local->tm_sec;
  519. /*
  520. * Must recalculate proper timezone offset each time,
  521. * as some files use daylight savings time and some don't...
  522. */
  523. result[6] = local->tm_yday; /* save yday 'cause gmtime zaps it */
  524. local = gmtime(&crtime);
  525. local->tm_year -= result[0];
  526. local->tm_yday -= result[6];
  527. local->tm_hour -= result[3];
  528. local->tm_min -= result[4];
  529. if (local->tm_year < 0)
  530. {
  531. local->tm_yday = -1;
  532. }
  533. else
  534. {
  535. if (local->tm_year > 0) local->tm_yday = 1;
  536. }
  537. result[6] = -(local->tm_min + 60*(local->tm_hour + 24*local->tm_yday)) / 15;
  538. return 0;
  539. }
  540. /* hide "./rr_moved" if all its contents are hidden */
  541. static void
  542. hide_reloc_dir()
  543. {
  544. struct directory_entry * s_entry;
  545. for (s_entry = reloc_dir->contents; s_entry; s_entry = s_entry->next) {
  546. if(strcmp(s_entry->name,".")==0 || strcmp(s_entry->name,"..")==0)
  547. continue;
  548. if((s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == 0)
  549. return;
  550. }
  551. /* all entries are hidden, so hide this directory */
  552. reloc_dir->dir_flags |= INHIBIT_ISO9660_ENTRY;
  553. reloc_dir->self->de_flags |= INHIBIT_ISO9660_ENTRY;
  554. }
  555. extern char * cdwrite_data;
  556. int FDECL2(main, int, argc, char **, argv){
  557. struct directory_entry de;
  558. #ifdef HAVE_SBRK
  559. unsigned long mem_start;
  560. #endif
  561. struct stat statbuf;
  562. char * scan_tree;
  563. char * merge_image = NULL;
  564. struct iso_directory_record * mrootp = NULL;
  565. struct output_fragment * opnt;
  566. int longind;
  567. char shortopts[OPTION_COUNT * 3 + 2];
  568. struct option longopts[OPTION_COUNT + 1];
  569. int c;
  570. char *log_file = 0;
  571. set_program_name (argv[0]);
  572. #if (defined(ENABLE_NLS) && ENABLE_NLS)
  573. setlocale (LC_ALL, "");
  574. bindtextdomain (PACKAGE, LOCALEDIR);
  575. textdomain (PACKAGE);
  576. #endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */
  577. if (argc < 2)
  578. usage();
  579. /* Get the defaults from the .mkisofsrc file */
  580. read_rcfile(argv[0]);
  581. outfile = NULL;
  582. /*
  583. * Copy long option initialization from GNU-ld.
  584. */
  585. /* Starting the short option string with '-' is for programs that
  586. expect options and other ARGV-elements in any order and that care about
  587. the ordering of the two. We describe each non-option ARGV-element
  588. as if it were the argument of an option with character code 1. */
  589. {
  590. unsigned int i;
  591. int is, il;
  592. shortopts[0] = '-';
  593. is = 1;
  594. il = 0;
  595. for (i = 0; i < OPTION_COUNT; i++)
  596. {
  597. if (ld_options[i].shortopt != '\0')
  598. {
  599. shortopts[is] = ld_options[i].shortopt;
  600. ++is;
  601. if (ld_options[i].opt.has_arg == required_argument
  602. || ld_options[i].opt.has_arg == optional_argument)
  603. {
  604. shortopts[is] = ':';
  605. ++is;
  606. if (ld_options[i].opt.has_arg == optional_argument)
  607. {
  608. shortopts[is] = ':';
  609. ++is;
  610. }
  611. }
  612. }
  613. if (ld_options[i].opt.name != NULL)
  614. {
  615. longopts[il] = ld_options[i].opt;
  616. ++il;
  617. }
  618. }
  619. shortopts[is] = '\0';
  620. longopts[il].name = NULL;
  621. }
  622. while ((c = getopt_long_only (argc, argv, shortopts, longopts, &longind)) != EOF)
  623. switch (c)
  624. {
  625. case 1:
  626. /*
  627. * A filename that we take as input.
  628. */
  629. optind--;
  630. goto parse_input_files;
  631. case 'C':
  632. /*
  633. * This is a temporary hack until cdwrite gets the proper hooks in
  634. * it.
  635. */
  636. cdwrite_data = optarg;
  637. break;
  638. case 'i':
  639. fprintf (stderr, _("-i option no longer supported.\n"));
  640. exit(1);
  641. break;
  642. case 'J':
  643. use_Joliet++;
  644. break;
  645. case 'a':
  646. all_files++;
  647. break;
  648. case 'b':
  649. use_eltorito++;
  650. boot_image = optarg; /* pathname of the boot image on cd */
  651. if (boot_image == NULL)
  652. error (1, 0, _("Required boot image pathname missing"));
  653. break;
  654. case 'G':
  655. use_embedded_boot = 1;
  656. boot_image_embed = optarg; /* pathname of the boot image on host filesystem */
  657. if (boot_image_embed == NULL)
  658. error (1, 0, _("Required boot image pathname missing"));
  659. break;
  660. case OPTION_PROTECTIVE_MSDOS_LABEL:
  661. use_protective_msdos_label = 1;
  662. break;
  663. case 'c':
  664. use_eltorito++;
  665. boot_catalog = optarg; /* pathname of the boot image on cd */
  666. if (boot_catalog == NULL)
  667. {
  668. fprintf (stderr, _("Required boot catalog pathname missing\n"));
  669. exit (1);
  670. }
  671. break;
  672. case OPTION_BOOT_INFO_TABLE:
  673. use_boot_info_table = 1;
  674. break;
  675. case OPTION_NO_EMUL_BOOT:
  676. fprintf (stderr, _("Ignoring -no-emul-boot (no-emulation is the default behaviour)\n"));
  677. break;
  678. case OPTION_ELTORITO_EMUL_FLOPPY:
  679. use_eltorito_emul_floppy = 1;
  680. break;
  681. case OPTION_ABSTRACT:
  682. abstract = optarg;
  683. if(strlen(abstract) > 37)
  684. {
  685. fprintf (stderr, _("Abstract filename string too long\n"));
  686. exit (1);
  687. };
  688. break;
  689. case 'A':
  690. appid = optarg;
  691. if(strlen(appid) > 128)
  692. {
  693. fprintf (stderr, _("Application-id string too long\n"));
  694. exit (1);
  695. };
  696. break;
  697. case OPTION_BIBLIO:
  698. biblio = optarg;
  699. if(strlen(biblio) > 37)
  700. {
  701. fprintf (stderr, _("Bibliographic filename string too long\n"));
  702. exit (1);
  703. };
  704. break;
  705. case OPTION_COPYRIGHT:
  706. copyright = optarg;
  707. if(strlen(copyright) > 37)
  708. {
  709. fprintf (stderr, _("Copyright filename string too long\n"));
  710. exit (1);
  711. };
  712. break;
  713. case 'd':
  714. omit_period++;
  715. break;
  716. case 'D':
  717. RR_relocation_depth = 32767;
  718. break;
  719. case 'f':
  720. follow_links++;
  721. break;
  722. case 'l':
  723. full_iso9660_filenames++;
  724. break;
  725. case 'L':
  726. allow_leading_dots++;
  727. break;
  728. case OPTION_LOG_FILE:
  729. log_file = optarg;
  730. break;
  731. case 'M':
  732. merge_image = optarg;
  733. break;
  734. case 'N':
  735. omit_version_number++;
  736. break;
  737. case 'o':
  738. outfile = optarg;
  739. break;
  740. case 'p':
  741. preparer = optarg;
  742. if(strlen(preparer) > 128)
  743. {
  744. fprintf (stderr, _("Preparer string too long\n"));
  745. exit (1);
  746. };
  747. break;
  748. case OPTION_PRINT_SIZE:
  749. print_size++;
  750. break;
  751. case 'P':
  752. publisher = optarg;
  753. if(strlen(publisher) > 128)
  754. {
  755. fprintf (stderr, _("Publisher string too long\n"));
  756. exit (1);
  757. };
  758. break;
  759. case OPTION_QUIET:
  760. verbose = 0;
  761. break;
  762. case 'R':
  763. use_RockRidge++;
  764. break;
  765. case 'r':
  766. rationalize++;
  767. use_RockRidge++;
  768. break;
  769. case OPTION_SPLIT_OUTPUT:
  770. split_output++;
  771. break;
  772. case OPTION_SYSID:
  773. system_id = optarg;
  774. if(strlen(system_id) > 32)
  775. {
  776. fprintf (stderr, _("System ID string too long\n"));
  777. exit (1);
  778. };
  779. break;
  780. case 'T':
  781. generate_tables++;
  782. break;
  783. case 'V':
  784. volume_id = optarg;
  785. if(strlen(volume_id) > 32)
  786. {
  787. fprintf (stderr, _("Volume ID string too long\n"));
  788. exit (1);
  789. };
  790. break;
  791. case OPTION_VOLSET:
  792. volset_id = optarg;
  793. if(strlen(volset_id) > 128)
  794. {
  795. fprintf (stderr, _("Volume set ID string too long\n"));
  796. exit (1);
  797. };
  798. break;
  799. case OPTION_VOLSET_SIZE:
  800. volume_set_size = atoi(optarg);
  801. break;
  802. case OPTION_VOLSET_SEQ_NUM:
  803. volume_sequence_number = atoi(optarg);
  804. if (volume_sequence_number > volume_set_size)
  805. {
  806. fprintf (stderr, _("Volume set sequence number too big\n"));
  807. exit (1);
  808. }
  809. break;
  810. case 'v':
  811. verbose++;
  812. break;
  813. case 'z':
  814. transparent_compression++;
  815. break;
  816. case 'x':
  817. case 'm':
  818. /*
  819. * Somehow two options to do basically the same thing got added somewhere along
  820. * the way. The 'match' code supports limited globbing, so this is the one
  821. * that got selected. Unfortunately the 'x' switch is probably more intuitive.
  822. */
  823. add_match(optarg);
  824. break;
  825. case OPTION_I_HIDE:
  826. i_add_match(optarg);
  827. break;
  828. case OPTION_J_HIDE:
  829. j_add_match(optarg);
  830. break;
  831. case OPTION_HELP:
  832. usage ();
  833. exit (0);
  834. break;
  835. case OPTION_VERSION:
  836. printf ("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
  837. exit (0);
  838. break;
  839. case OPTION_NOSPLIT_SL_COMPONENT:
  840. split_SL_component = 0;
  841. break;
  842. case OPTION_NOSPLIT_SL_FIELD:
  843. split_SL_field = 0;
  844. break;
  845. case OPTION_CREAT_DATE:
  846. if (strlen (optarg) != 16)
  847. {
  848. fprintf (stderr, _("date string must be 16 characters.\n"));
  849. exit (1);
  850. }
  851. if (creation_date)
  852. free(creation_date);
  853. creation_date = strdup(optarg);
  854. break;
  855. case OPTION_MODIF_DATE:
  856. if (strlen (optarg) != 16)
  857. {
  858. fprintf (stderr, _("date string must be 16 characters.\n"));
  859. exit (1);
  860. }
  861. if (modification_date)
  862. free(modification_date);
  863. modification_date = strdup(optarg);
  864. break;
  865. case OPTION_EXPIR_DATE:
  866. if (strlen (optarg) != 16)
  867. {
  868. fprintf (stderr, _("date string must be 16 characters.\n"));
  869. exit (1);
  870. }
  871. if (expiration_date)
  872. free(expiration_date);
  873. expiration_date = strdup(optarg);
  874. break;
  875. case OPTION_EFFEC_DATE:
  876. if (strlen (optarg) != 16)
  877. {
  878. fprintf (stderr, _("date string must be 16 characters.\n"));
  879. exit (1);
  880. }
  881. if (effective_date)
  882. free(effective_date);
  883. effective_date = strdup(optarg);
  884. break;
  885. default:
  886. usage();
  887. exit(1);
  888. }
  889. parse_input_files:
  890. #ifdef __NetBSD__
  891. {
  892. int resource;
  893. struct rlimit rlp;
  894. if (getrlimit(RLIMIT_DATA,&rlp) == -1)
  895. perror (_("Warning: getrlimit"));
  896. else {
  897. rlp.rlim_cur=33554432;
  898. if (setrlimit(RLIMIT_DATA,&rlp) == -1)
  899. perror (_("Warning: setrlimit"));
  900. }
  901. }
  902. #endif
  903. #ifdef HAVE_SBRK
  904. mem_start = (unsigned long) sbrk(0);
  905. #endif
  906. /* if the -hide-joliet option has been given, set the Joliet option */
  907. if (!use_Joliet && j_ishidden())
  908. use_Joliet++;
  909. if(verbose > 1) fprintf(stderr,"%s\n", version_string);
  910. if(cdwrite_data == NULL && merge_image != NULL)
  911. {
  912. fprintf (stderr, _("Multisession usage bug: Must specify -C if -M is used.\n"));
  913. exit (0);
  914. }
  915. if(cdwrite_data != NULL && merge_image == NULL)
  916. {
  917. fprintf (stderr, _("Warning: -C specified without -M: old session data will not be merged.\n"));
  918. }
  919. /* The first step is to scan the directory tree, and take some notes */
  920. scan_tree = argv[optind];
  921. if(!scan_tree){
  922. usage();
  923. exit(1);
  924. };
  925. #ifndef VMS
  926. if(scan_tree[strlen(scan_tree)-1] != '/') {
  927. scan_tree = (char *) e_malloc(strlen(argv[optind])+2);
  928. strcpy(scan_tree, argv[optind]);
  929. strcat(scan_tree, "/");
  930. };
  931. #endif
  932. if(use_RockRidge){
  933. #if 1
  934. extension_record = generate_rr_extension_record("RRIP_1991A",
  935. "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS",
  936. "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.", &extension_record_size);
  937. #else
  938. extension_record = generate_rr_extension_record("IEEE_P1282",
  939. "THE IEEE P1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS",
  940. "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, PISCATAWAY, NJ, USA FOR THE P1282 SPECIFICATION.", &extension_record_size);
  941. #endif
  942. }
  943. if (log_file) {
  944. FILE *lfp;
  945. int i;
  946. /* open log file - test that we can open OK */
  947. if ((lfp = fopen(log_file, "w")) == NULL)
  948. error (1, errno, _("can't open logfile: %s"), log_file);
  949. fclose(lfp);
  950. /* redirect all stderr message to log_file */
  951. fprintf (stderr, _("re-directing all messages to %s\n"), log_file);
  952. fflush(stderr);
  953. /* associate stderr with the log file */
  954. if (freopen(log_file, "w", stderr) == NULL)
  955. error (1, errno, _("can't open logfile: %s\n"), log_file);
  956. if(verbose > 1) {
  957. for (i=0;i<argc;i++)
  958. fprintf(stderr,"%s ", argv[i]);
  959. fprintf(stderr,"\n%s\n", version_string);
  960. }
  961. }
  962. /*
  963. * See if boot catalog file exists in root directory, if not
  964. * we will create it.
  965. */
  966. if (use_eltorito)
  967. init_boot_catalog(argv[optind]);
  968. /*
  969. * Find the device and inode number of the root directory.
  970. * Record this in the hash table so we don't scan it more than
  971. * once.
  972. */
  973. stat_filter(argv[optind], &statbuf);
  974. add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
  975. memset(&de, 0, sizeof(de));
  976. de.filedir = root; /* We need this to bootstrap */
  977. if (cdwrite_data != NULL && merge_image == NULL) {
  978. /* in case we want to add a new session, but don't want to merge old one */
  979. get_session_start(NULL);
  980. }
  981. if( merge_image != NULL )
  982. {
  983. mrootp = merge_isofs(merge_image);
  984. if( mrootp == NULL )
  985. {
  986. /*
  987. * Complain and die.
  988. */
  989. error (1, 0, _("Unable to open previous session image %s\n"),
  990. merge_image);
  991. }
  992. memcpy(&de.isorec.extent, mrootp->extent, 8);
  993. }
  994. /*
  995. * Create an empty root directory. If we ever scan it for real, we will fill in the
  996. * contents.
  997. */
  998. find_or_create_directory(NULL, "", &de, TRUE);
  999. /*
  1000. * Scan the actual directory (and any we find below it)
  1001. * for files to write out to the output image. Note - we
  1002. * take multiple source directories and keep merging them
  1003. * onto the image.
  1004. */
  1005. while(optind < argc)
  1006. {
  1007. char * node;
  1008. struct directory * graft_dir;
  1009. struct stat st;
  1010. char * short_name;
  1011. int status;
  1012. char graft_point[1024];
  1013. /*
  1014. * We would like a syntax like:
  1015. *
  1016. * /tmp=/usr/tmp/xxx
  1017. *
  1018. * where the user can specify a place to graft each
  1019. * component of the tree. To do this, we may have to create
  1020. * directories along the way, of course.
  1021. * Secondly, I would like to allow the user to do something
  1022. * like:
  1023. *
  1024. * /home/baz/RMAIL=/u3/users/baz/RMAIL
  1025. *
  1026. * so that normal files could also be injected into the tree
  1027. * at an arbitrary point.
  1028. *
  1029. * The idea is that the last component of whatever is being
  1030. * entered would take the name from the last component of
  1031. * whatever the user specifies.
  1032. *
  1033. * The default will be that the file is injected at the
  1034. * root of the image tree.
  1035. */
  1036. node = strchr(argv[optind], '=');
  1037. short_name = NULL;
  1038. if( node != NULL )
  1039. {
  1040. char * pnt;
  1041. char * xpnt;
  1042. *node = '\0';
  1043. strcpy(graft_point, argv[optind]);
  1044. *node = '=';
  1045. node++;
  1046. graft_dir = root;
  1047. xpnt = graft_point;
  1048. if( *xpnt == PATH_SEPARATOR )
  1049. {
  1050. xpnt++;
  1051. }
  1052. /*
  1053. * Loop down deeper and deeper until we
  1054. * find the correct insertion spot.
  1055. */
  1056. while(1==1)
  1057. {
  1058. pnt = strchr(xpnt, PATH_SEPARATOR);
  1059. if( pnt == NULL )
  1060. {
  1061. if( *xpnt != '\0' )
  1062. {
  1063. short_name = xpnt;
  1064. }
  1065. break;
  1066. }
  1067. *pnt = '\0';
  1068. graft_dir = find_or_create_directory(graft_dir,
  1069. graft_point,
  1070. NULL, TRUE);
  1071. *pnt = PATH_SEPARATOR;
  1072. xpnt = pnt + 1;
  1073. }
  1074. }
  1075. else
  1076. {
  1077. graft_dir = root;
  1078. node = argv[optind];
  1079. }
  1080. /*
  1081. * Now see whether the user wants to add a regular file,
  1082. * or a directory at this point.
  1083. */
  1084. status = stat_filter(node, &st);
  1085. if( status != 0 )
  1086. {
  1087. /*
  1088. * This is a fatal error - the user won't be getting what
  1089. * they want if we were to proceed.
  1090. */
  1091. error (1, 0, _("Invalid node - %s\n"), node);
  1092. }
  1093. else
  1094. {
  1095. if( S_ISDIR(st.st_mode) )
  1096. {
  1097. if (!scan_directory_tree(graft_dir, node, &de))
  1098. {
  1099. exit(1);
  1100. }
  1101. }
  1102. else
  1103. {
  1104. if( short_name == NULL )
  1105. {
  1106. short_name = strrchr(node, PATH_SEPARATOR);
  1107. if( short_name == NULL || short_name < node )
  1108. {
  1109. short_name = node;
  1110. }
  1111. else
  1112. {
  1113. short_name++;
  1114. }
  1115. }
  1116. if( !insert_file_entry(graft_dir, node, short_name) )
  1117. {
  1118. exit(1);
  1119. }
  1120. }
  1121. }
  1122. optind++;
  1123. }
  1124. /*
  1125. * Now merge in any previous sessions. This is driven on the source
  1126. * side, since we may need to create some additional directories.
  1127. */
  1128. if( merge_image != NULL )
  1129. {
  1130. merge_previous_session(root, mrootp);
  1131. }
  1132. /* hide "./rr_moved" if all its contents have been hidden */
  1133. if (reloc_dir && i_ishidden())
  1134. hide_reloc_dir();
  1135. /*
  1136. * Sort the directories in the required order (by ISO9660). Also,
  1137. * choose the names for the 8.3 filesystem if required, and do
  1138. * any other post-scan work.
  1139. */
  1140. goof += sort_tree(root);
  1141. if( use_Joliet )
  1142. {
  1143. goof += joliet_sort_tree(root);
  1144. }
  1145. if (goof)
  1146. error (1, 0, _("Joliet tree sort failed.\n"));
  1147. /*
  1148. * Fix a couple of things in the root directory so that everything
  1149. * is self consistent.
  1150. */
  1151. root->self = root->contents; /* Fix this up so that the path
  1152. tables get done right */
  1153. /*
  1154. * OK, ready to write the file. Open it up, and generate the thing.
  1155. */
  1156. if (print_size){
  1157. discimage = fopen("/dev/null", "wb");
  1158. if (!discimage)
  1159. error (1, errno, _("Unable to open /dev/null\n"));
  1160. } else if (outfile){
  1161. discimage = fopen(outfile, "wb");
  1162. if (!discimage)
  1163. error (1, errno, _("Unable to open disc image file\n"));
  1164. } else {
  1165. discimage = stdout;
  1166. #if defined(__CYGWIN32__)
  1167. setmode(fileno(stdout), O_BINARY);
  1168. #endif
  1169. }
  1170. /* Now assign addresses on the disc for the path table. */
  1171. path_blocks = (path_table_size + (SECTOR_SIZE - 1)) >> 11;
  1172. if (path_blocks & 1) path_blocks++;
  1173. jpath_blocks = (jpath_table_size + (SECTOR_SIZE - 1)) >> 11;
  1174. if (jpath_blocks & 1) jpath_blocks++;
  1175. /*
  1176. * Start to set up the linked list that we use to track the
  1177. * contents of the disc.
  1178. */
  1179. outputlist_insert(&padblock_desc);
  1180. /*
  1181. * PVD for disc.
  1182. */
  1183. outputlist_insert(&voldesc_desc);
  1184. /*
  1185. * SVD for El Torito. MUST be immediately after the PVD!
  1186. */
  1187. if( use_eltorito)
  1188. {
  1189. outputlist_insert(&torito_desc);
  1190. }
  1191. /*
  1192. * SVD for Joliet.
  1193. */
  1194. if( use_Joliet)
  1195. {
  1196. outputlist_insert(&joliet_desc);
  1197. }
  1198. /*
  1199. * Finally the last volume desctiptor.
  1200. */
  1201. outputlist_insert(&end_vol);
  1202. outputlist_insert(&pathtable_desc);
  1203. if( use_Joliet)
  1204. {
  1205. outputlist_insert(&jpathtable_desc);
  1206. }
  1207. outputlist_insert(&dirtree_desc);
  1208. if( use_Joliet)
  1209. {
  1210. outputlist_insert(&jdirtree_desc);
  1211. }
  1212. outputlist_insert(&dirtree_clean);
  1213. if(extension_record)
  1214. {
  1215. outputlist_insert(&extension_desc);
  1216. }
  1217. outputlist_insert(&files_desc);
  1218. /*
  1219. * Allow room for the various headers we will be writing. There
  1220. * will always be a primary and an end volume descriptor.
  1221. */
  1222. last_extent = session_start;
  1223. /*
  1224. * Calculate the size of all of the components of the disc, and assign
  1225. * extent numbers.
  1226. */
  1227. for(opnt = out_list; opnt; opnt = opnt->of_next )
  1228. {
  1229. if( opnt->of_size != NULL )
  1230. {
  1231. (*opnt->of_size)(last_extent);
  1232. }
  1233. }
  1234. /*
  1235. * Generate the contents of any of the sections that we want to generate.
  1236. * Not all of the fragments will do anything here - most will generate the
  1237. * data on the fly when we get to the write pass.
  1238. */
  1239. for(opnt = out_list; opnt; opnt = opnt->of_next )
  1240. {
  1241. if( opnt->of_generate != NULL )
  1242. {
  1243. (*opnt->of_generate)();
  1244. }
  1245. }
  1246. if( in_image != NULL )
  1247. {
  1248. fclose(in_image);
  1249. }
  1250. /*
  1251. * Now go through the list of fragments and write the data that corresponds to
  1252. * each one.
  1253. */
  1254. for(opnt = out_list; opnt; opnt = opnt->of_next )
  1255. {
  1256. if( opnt->of_write != NULL )
  1257. {
  1258. (*opnt->of_write)(discimage);
  1259. }
  1260. }
  1261. if( verbose > 0 )
  1262. {
  1263. #ifdef HAVE_SBRK
  1264. fprintf (stderr, _("Max brk space used %x\n"),
  1265. (unsigned int)(((unsigned long)sbrk(0)) - mem_start));
  1266. #endif
  1267. fprintf (stderr, _("%llu extents written (%llu MiB)\n"), last_extent, last_extent >> 9);
  1268. }
  1269. #ifdef VMS
  1270. return 1;
  1271. #else
  1272. return 0;
  1273. #endif
  1274. }
  1275. void *
  1276. FDECL1(e_malloc, size_t, size)
  1277. {
  1278. void* pt = 0;
  1279. if( (size > 0) && ((pt = malloc (size)) == NULL))
  1280. error (1, errno, "malloc");
  1281. return pt;
  1282. }