multi.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. /*
  2. * File multi.c - scan existing iso9660 image and merge into
  3. * iso9660 filesystem. Used for multisession support.
  4. *
  5. * Written by Eric Youngdale (1996).
  6. *
  7. * Copyright (C) 2009 Free Software Foundation, Inc.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 3, or (at your option)
  12. * any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, see <http://www.gnu.org/licenses/>.
  21. */
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <time.h>
  25. #include <errno.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include "config.h"
  29. #ifndef VMS
  30. #ifdef HAVE_UNISTD_H
  31. #include <unistd.h>
  32. #endif
  33. #else
  34. #include <sys/file.h>
  35. #include <vms/fabdef.h>
  36. #include "vms.h"
  37. extern char * strdup(const char *);
  38. #endif
  39. #include "mkisofs.h"
  40. #include "iso9660.h"
  41. #define TF_CREATE 1
  42. #define TF_MODIFY 2
  43. #define TF_ACCESS 4
  44. #define TF_ATTRIBUTES 8
  45. static int isonum_711 __PR((unsigned char * p));
  46. static int isonum_721 __PR((unsigned char * p));
  47. static int isonum_723 __PR((unsigned char * p));
  48. static int isonum_731 __PR((unsigned char * p));
  49. static int DECL(merge_old_directory_into_tree, (struct directory_entry *,
  50. struct directory *));
  51. #ifdef __STDC__
  52. static int
  53. isonum_711 (unsigned char * p)
  54. #else
  55. static int
  56. isonum_711 (p)
  57. unsigned char * p;
  58. #endif
  59. {
  60. return (*p & 0xff);
  61. }
  62. #ifdef __STDC__
  63. static int
  64. isonum_721 (unsigned char * p)
  65. #else
  66. static int
  67. isonum_721 (p)
  68. unsigned char * p;
  69. #endif
  70. {
  71. return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
  72. }
  73. #ifdef __STDC__
  74. static int
  75. isonum_723 (unsigned char * p)
  76. #else
  77. static int
  78. isonum_723 (p)
  79. unsigned char * p;
  80. #endif
  81. {
  82. #if 0
  83. if (p[0] != p[3] || p[1] != p[2]) {
  84. fprintf (stderr, "invalid format 7.2.3 number\n");
  85. exit (1);
  86. }
  87. #endif
  88. return (isonum_721 (p));
  89. }
  90. #ifdef __STDC__
  91. static int
  92. isonum_731 (unsigned char * p)
  93. #else
  94. static int
  95. isonum_731 (p)
  96. unsigned char * p;
  97. #endif
  98. {
  99. return ((p[0] & 0xff)
  100. | ((p[1] & 0xff) << 8)
  101. | ((p[2] & 0xff) << 16)
  102. | ((p[3] & 0xff) << 24));
  103. }
  104. #ifdef __STDC__
  105. int
  106. isonum_733 (unsigned char * p)
  107. #else
  108. int
  109. isonum_733 (p)
  110. unsigned char * p;
  111. #endif
  112. {
  113. return (isonum_731 (p));
  114. }
  115. FILE * in_image = NULL;
  116. #ifndef USE_SCG
  117. /*
  118. * Don't define readsecs if mkisofs is linked with
  119. * the SCSI library.
  120. * readsecs() will be implemented as SCSI command in this case.
  121. *
  122. * Use global var in_image directly in readsecs()
  123. * the SCSI equivalent will not use a FILE* for I/O.
  124. *
  125. * The main point of this pointless abstraction is that Solaris won't let
  126. * you read 2K sectors from the cdrom driver. The fact that 99.9% of the
  127. * discs out there have a 2K sectorsize doesn't seem to matter that much.
  128. * Anyways, this allows the use of a scsi-generics type of interface on
  129. * Solaris.
  130. */
  131. #ifdef __STDC__
  132. static int
  133. readsecs(int startsecno, void *buffer, int sectorcount)
  134. #else
  135. static int
  136. readsecs(startsecno, buffer, sectorcount)
  137. int startsecno;
  138. void *buffer;
  139. int sectorcount;
  140. #endif
  141. {
  142. int f = fileno(in_image);
  143. if (lseek(f, (off_t)startsecno * SECTOR_SIZE, 0) == (off_t)-1)
  144. error (10, errno, _("Seek error on old image\n"));
  145. return (read(f, buffer, sectorcount * SECTOR_SIZE));
  146. }
  147. #endif
  148. /*
  149. * Parse the RR attributes so we can find the file name.
  150. */
  151. static int
  152. FDECL3(parse_rr, unsigned char *, pnt, int, len, struct directory_entry *,dpnt)
  153. {
  154. int cont_extent, cont_offset, cont_size;
  155. char name_buf[256];
  156. cont_extent = cont_offset = cont_size = 0;
  157. while(len >= 4){
  158. if(pnt[3] != 1) {
  159. fprintf (stderr, _("**Bad RR version attribute"));
  160. return -1;
  161. };
  162. if(strncmp((char *) pnt, "NM", 2) == 0) {
  163. strncpy(name_buf, (char *) pnt+5, pnt[2] - 5);
  164. name_buf[pnt[2] - 5] = 0;
  165. dpnt->name = strdup(name_buf);
  166. dpnt->got_rr_name = 1;
  167. return 0;
  168. }
  169. if(strncmp((char *) pnt, "CE", 2) == 0) {
  170. cont_extent = isonum_733(pnt+4);
  171. cont_offset = isonum_733(pnt+12);
  172. cont_size = isonum_733(pnt+20);
  173. };
  174. len -= pnt[2];
  175. pnt += pnt[2];
  176. if(len <= 3 && cont_extent) {
  177. unsigned char sector[SECTOR_SIZE];
  178. readsecs(cont_extent, sector, 1);
  179. parse_rr(&sector[cont_offset], cont_size, dpnt);
  180. };
  181. };
  182. /* Fall back to the iso name if no RR name found */
  183. if (dpnt->name == NULL) {
  184. char *cp;
  185. strcpy(name_buf, dpnt->isorec.name);
  186. cp = strchr(name_buf, ';');
  187. if (cp != NULL) {
  188. *cp = '\0';
  189. }
  190. dpnt->name = strdup(name_buf);
  191. }
  192. return 0;
  193. } /* parse_rr */
  194. static int
  195. FDECL4(check_rr_dates, struct directory_entry *, dpnt,
  196. struct directory_entry *, current,
  197. struct stat *, statbuf,
  198. struct stat *,lstatbuf)
  199. {
  200. int cont_extent, cont_offset, cont_size;
  201. int offset;
  202. unsigned char * pnt;
  203. int len;
  204. int same_file;
  205. int same_file_type;
  206. mode_t mode;
  207. char time_buf[7];
  208. cont_extent = cont_offset = cont_size = 0;
  209. same_file = 1;
  210. same_file_type = 1;
  211. pnt = dpnt->rr_attributes;
  212. len = dpnt->rr_attr_size;
  213. /*
  214. * We basically need to parse the rr attributes again, and
  215. * dig out the dates and file types.
  216. */
  217. while(len >= 4){
  218. if(pnt[3] != 1) {
  219. fprintf (stderr, _("**Bad RR version attribute"));
  220. return -1;
  221. };
  222. /*
  223. * If we have POSIX file modes, make sure that the file type
  224. * is the same. If it isn't, then we must always
  225. * write the new file.
  226. */
  227. if(strncmp((char *) pnt, "PX", 2) == 0) {
  228. mode = isonum_733(pnt + 4);
  229. if( (lstatbuf->st_mode & S_IFMT) != (mode & S_IFMT) )
  230. {
  231. same_file_type = 0;
  232. same_file = 0;
  233. }
  234. }
  235. if(strncmp((char *) pnt, "TF", 2) == 0) {
  236. offset = 5;
  237. if( pnt[4] & TF_CREATE )
  238. {
  239. iso9660_date((char *) time_buf, lstatbuf->st_ctime);
  240. if(memcmp(time_buf, pnt+offset, 7) == 0)
  241. same_file = 0;
  242. offset += 7;
  243. }
  244. if( pnt[4] & TF_MODIFY )
  245. {
  246. iso9660_date((char *) time_buf, lstatbuf->st_mtime);
  247. if(memcmp(time_buf, pnt+offset, 7) == 0)
  248. same_file = 0;
  249. offset += 7;
  250. }
  251. }
  252. if(strncmp((char *) pnt, "CE", 2) == 0) {
  253. cont_extent = isonum_733(pnt+4);
  254. cont_offset = isonum_733(pnt+12);
  255. cont_size = isonum_733(pnt+20);
  256. };
  257. len -= pnt[2];
  258. pnt += pnt[2];
  259. if(len <= 3 && cont_extent) {
  260. unsigned char sector[SECTOR_SIZE];
  261. readsecs(cont_extent, sector, 1);
  262. parse_rr(&sector[cont_offset], cont_size, dpnt);
  263. };
  264. };
  265. /*
  266. * If we have the same fundamental file type, then it is clearly
  267. * safe to reuse the TRANS.TBL entry.
  268. */
  269. if( same_file_type )
  270. {
  271. current->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
  272. }
  273. return same_file;
  274. }
  275. struct directory_entry **
  276. FDECL2(read_merging_directory, struct iso_directory_record *, mrootp,
  277. int *, nent)
  278. {
  279. unsigned char * cpnt;
  280. unsigned char * cpnt1;
  281. char * dirbuff;
  282. int i;
  283. struct iso_directory_record * idr;
  284. int len;
  285. struct directory_entry **pnt;
  286. int rlen;
  287. struct directory_entry **rtn;
  288. int seen_rockridge;
  289. unsigned char * tt_buf;
  290. int tt_extent;
  291. int tt_size;
  292. static int warning_given = 0;
  293. /*
  294. * First, allocate a buffer large enough to read in the entire
  295. * directory.
  296. */
  297. dirbuff = (char *) e_malloc(isonum_733((unsigned char *)mrootp->size));
  298. readsecs(isonum_733((unsigned char *)mrootp->extent), dirbuff,
  299. isonum_733((unsigned char *)mrootp->size)/SECTOR_SIZE);
  300. /*
  301. * Next look over the directory, and count up how many entries we
  302. * have.
  303. */
  304. len = isonum_733((unsigned char *)mrootp->size);
  305. i = 0;
  306. *nent = 0;
  307. while(i < len )
  308. {
  309. idr = (struct iso_directory_record *) &dirbuff[i];
  310. if(idr->length[0] == 0)
  311. {
  312. i = (i + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1);
  313. continue;
  314. }
  315. (*nent)++;
  316. i += idr->length[0];
  317. }
  318. /*
  319. * Now allocate the buffer which will hold the array we are
  320. * about to return.
  321. */
  322. rtn = (struct directory_entry **) e_malloc(*nent * sizeof(*rtn));
  323. /*
  324. * Finally, scan the directory one last time, and pick out the
  325. * relevant bits of information, and store it in the relevant
  326. * bits of the structure.
  327. */
  328. i = 0;
  329. pnt = rtn;
  330. tt_extent = 0;
  331. seen_rockridge = 0;
  332. tt_size = 0;
  333. while(i < len )
  334. {
  335. idr = (struct iso_directory_record *) &dirbuff[i];
  336. if(idr->length[0] == 0)
  337. {
  338. i = (i + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1);
  339. continue;
  340. }
  341. *pnt = (struct directory_entry *) e_malloc(sizeof(**rtn));
  342. (*pnt)->next = NULL;
  343. (*pnt)->isorec = *idr;
  344. (*pnt)->starting_block = isonum_733((unsigned char *)idr->extent);
  345. (*pnt)->size = isonum_733((unsigned char *)idr->size);
  346. (*pnt)->priority = 0;
  347. (*pnt)->name = NULL;
  348. (*pnt)->got_rr_name = 0;
  349. (*pnt)->table = NULL;
  350. (*pnt)->whole_name = NULL;
  351. (*pnt)->filedir = NULL;
  352. (*pnt)->parent_rec = NULL;
  353. /*
  354. * Set this information so that we correctly cache previous
  355. * session bits of information.
  356. */
  357. (*pnt)->inode = (*pnt)->starting_block;
  358. (*pnt)->dev = PREV_SESS_DEV;
  359. (*pnt)->rr_attributes = NULL;
  360. (*pnt)->rr_attr_size = 0;
  361. (*pnt)->total_rr_attr_size = 0;
  362. (*pnt)->de_flags = SAFE_TO_REUSE_TABLE_ENTRY;
  363. /*
  364. * Check for and parse any RR attributes for the file.
  365. * All we are really looking for here is the original name
  366. * of the file.
  367. */
  368. rlen = idr->length[0] & 0xff;
  369. cpnt = (unsigned char *) idr;
  370. rlen -= sizeof(struct iso_directory_record);
  371. cpnt += sizeof(struct iso_directory_record);
  372. rlen += sizeof(idr->name);
  373. cpnt -= sizeof(idr->name);
  374. rlen -= idr->name_len[0];
  375. cpnt += idr->name_len[0];
  376. if((idr->name_len[0] & 1) == 0){
  377. cpnt++;
  378. rlen--;
  379. };
  380. if( rlen != 0 )
  381. {
  382. (*pnt)->total_rr_attr_size = (*pnt)->rr_attr_size = rlen;
  383. (*pnt)->rr_attributes = e_malloc(rlen);
  384. memcpy((*pnt)->rr_attributes, cpnt, rlen);
  385. seen_rockridge = 1;
  386. }
  387. /*
  388. * Now zero out the remainder of the name field.
  389. */
  390. cpnt = (unsigned char *) &(*pnt)->isorec.name;
  391. cpnt += idr->name_len[0];
  392. memset(cpnt, 0, sizeof((*pnt)->isorec.name) - idr->name_len[0]);
  393. parse_rr((*pnt)->rr_attributes, rlen, *pnt);
  394. if( ((*pnt)->isorec.name_len[0] == 1)
  395. && ( ((*pnt)->isorec.name[0] == 0)
  396. || ((*pnt)->isorec.name[0] == 1)) )
  397. {
  398. if( (*pnt)->name != NULL )
  399. {
  400. free((*pnt)->name);
  401. }
  402. if( (*pnt)->whole_name != NULL )
  403. {
  404. free((*pnt)->whole_name);
  405. }
  406. if( (*pnt)->isorec.name[0] == 0 )
  407. {
  408. (*pnt)->name = strdup(".");
  409. }
  410. else
  411. {
  412. (*pnt)->name = strdup("..");
  413. }
  414. }
  415. #ifdef DEBUG
  416. fprintf(stderr, "got DE name: %s\n", (*pnt)->name);
  417. #endif
  418. if( strncmp(idr->name, "TRANS.TBL", 9) == 0)
  419. {
  420. if( (*pnt)->name != NULL )
  421. {
  422. free((*pnt)->name);
  423. }
  424. if( (*pnt)->whole_name != NULL )
  425. {
  426. free((*pnt)->whole_name);
  427. }
  428. (*pnt)->name = strdup("<translation table>");
  429. tt_extent = isonum_733((unsigned char *)idr->extent);
  430. tt_size = isonum_733((unsigned char *)idr->size);
  431. }
  432. pnt++;
  433. i += idr->length[0];
  434. }
  435. /*
  436. * If there was a TRANS.TBL;1 entry, then grab it, read it, and use it
  437. * to get the filenames of the files. Also, save the table info, just
  438. * in case we need to use it.
  439. */
  440. if( tt_extent != 0 && tt_size != 0 )
  441. {
  442. tt_buf = (unsigned char *) e_malloc(tt_size);
  443. readsecs(tt_extent, tt_buf, tt_size/SECTOR_SIZE);
  444. /*
  445. * Loop through the file, examine each entry, and attempt to
  446. * attach it to the correct entry.
  447. */
  448. cpnt = tt_buf;
  449. cpnt1 = tt_buf;
  450. while( cpnt - tt_buf < tt_size )
  451. {
  452. while(*cpnt1 != '\n' && *cpnt1 != '\0') cpnt1++;
  453. *cpnt1 = '\0';
  454. for(pnt = rtn, i = 0; i <*nent; i++, pnt++)
  455. {
  456. rlen = isonum_711((*pnt)->isorec.name_len);
  457. if( strncmp((char *) cpnt + 2, (*pnt)->isorec.name,
  458. rlen) == 0
  459. && cpnt[2+rlen] == ' ')
  460. {
  461. (*pnt)->table = e_malloc(strlen((char*)cpnt) - 33);
  462. sprintf((*pnt)->table, "%c\t%s\n",
  463. *cpnt, cpnt+37);
  464. if( !(*pnt)->got_rr_name )
  465. {
  466. if ((*pnt)->name != NULL) {
  467. free((*pnt)->name);
  468. }
  469. (*pnt)->name = strdup((char *) cpnt+37);
  470. }
  471. break;
  472. }
  473. }
  474. cpnt = cpnt1 + 1;
  475. cpnt1 = cpnt;
  476. }
  477. free(tt_buf);
  478. }
  479. else if( !seen_rockridge && !warning_given )
  480. {
  481. /*
  482. * Warn the user that iso (8.3) names were used because neither
  483. * Rock Ridge (-R) nor TRANS.TBL (-T) name translations were found.
  484. */
  485. fprintf (stderr, _("Warning: Neither Rock Ridge (-R) nor TRANS.TBL (-T) "
  486. "name translations were found on previous session. "
  487. "ISO (8.3) file names have been used instead.\n"));
  488. warning_given = 1;
  489. }
  490. if( dirbuff != NULL )
  491. {
  492. free(dirbuff);
  493. }
  494. return rtn;
  495. } /* read_merging_directory */
  496. /*
  497. * Free any associated data related to the structures.
  498. */
  499. int
  500. FDECL2(free_mdinfo, struct directory_entry ** , ptr, int, len )
  501. {
  502. int i;
  503. struct directory_entry **p;
  504. p = ptr;
  505. for(i=0; i<len; i++, p++)
  506. {
  507. /*
  508. * If the tree-handling code decided that it needed an entry,
  509. * it will have removed it from the list. Thus we must allow
  510. * for null pointers here.
  511. */
  512. if( *p == NULL )
  513. {
  514. continue;
  515. }
  516. if( (*p)->name != NULL )
  517. {
  518. free((*p)->name);
  519. }
  520. if( (*p)->whole_name != NULL )
  521. {
  522. free((*p)->whole_name);
  523. }
  524. if( (*p)->rr_attributes != NULL )
  525. {
  526. free((*p)->rr_attributes);
  527. }
  528. if( (*p)->table != NULL )
  529. {
  530. free((*p)->table);
  531. }
  532. free(*p);
  533. }
  534. free(ptr);
  535. return 0;
  536. }
  537. /*
  538. * Search the list to see if we have any entries from the previous
  539. * session that match this entry. If so, copy the extent number
  540. * over so we don't bother to write it out to the new session.
  541. */
  542. int
  543. FDECL6(check_prev_session, struct directory_entry ** , ptr, int, len,
  544. struct directory_entry *, curr_entry,
  545. struct stat *, statbuf, struct stat *, lstatbuf,
  546. struct directory_entry **, odpnt)
  547. {
  548. int i;
  549. for( i=0; i < len; i++ )
  550. {
  551. if( ptr[i] == NULL )
  552. {
  553. continue;
  554. }
  555. #if 0
  556. if( ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1
  557. && ptr[i]->name[0] == '\0' )
  558. {
  559. continue;
  560. }
  561. if( ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1
  562. && ptr[i]->name[0] == 1)
  563. {
  564. continue;
  565. }
  566. #else
  567. if( ptr[i]->name != NULL && strcmp(ptr[i]->name, ".") == 0 )
  568. {
  569. continue;
  570. }
  571. if( ptr[i]->name != NULL && strcmp(ptr[i]->name, "..") == 0 )
  572. {
  573. continue;
  574. }
  575. #endif
  576. if( ptr[i]->name != NULL
  577. && strcmp(ptr[i]->name, curr_entry->name) != 0 )
  578. {
  579. continue;
  580. }
  581. /*
  582. * We know that the files have the same name. If they also have
  583. * the same file type (i.e. file, dir, block, etc), then we
  584. * can safely reuse the TRANS.TBL entry for this file.
  585. * The check_rr_dates function will do this for us.
  586. *
  587. * Verify that the file type and dates are consistent.
  588. * If not, we probably have a different file, and we need
  589. * to write it out again.
  590. */
  591. if( (ptr[i]->rr_attributes != NULL)
  592. && (check_rr_dates(ptr[i], curr_entry, statbuf, lstatbuf)) )
  593. {
  594. goto found_it;
  595. }
  596. /*
  597. * Verify size and timestamp. If rock ridge is in use, we need
  598. * to compare dates from RR too. Directories are special, we
  599. * calculate their size later.
  600. */
  601. if( (curr_entry->isorec.flags[0] & 2) == 0
  602. && ptr[i]->size != curr_entry->size )
  603. {
  604. goto found_it;
  605. }
  606. if( memcmp(ptr[i]->isorec.date, curr_entry->isorec.date,7) != 0 )
  607. {
  608. goto found_it;
  609. }
  610. /*
  611. * Never ever reuse directory extents. See comments in
  612. * tree.c for an explaination of why this must be the case.
  613. */
  614. if( (curr_entry->isorec.flags[0] & 2) != 0 )
  615. {
  616. goto found_it;
  617. }
  618. memcpy(curr_entry->isorec.extent, ptr[i]->isorec.extent, 8);
  619. curr_entry->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
  620. goto found_it;
  621. }
  622. return 0;
  623. found_it:
  624. if( odpnt != NULL )
  625. {
  626. *odpnt = ptr[i];
  627. }
  628. else
  629. {
  630. free(ptr[i]);
  631. }
  632. ptr[i] = NULL;
  633. return 0;
  634. }
  635. /*
  636. * merge_isofs: Scan an existing image, and return a pointer
  637. * to the root directory for this image.
  638. */
  639. struct iso_directory_record * FDECL1(merge_isofs, char *, path)
  640. {
  641. char buffer[SECTOR_SIZE];
  642. int file_addr;
  643. int i;
  644. struct iso_primary_descriptor * pri = NULL;
  645. struct iso_directory_record * rootp;
  646. struct iso_volume_descriptor * vdp;
  647. /*
  648. * Start by opening up the image and searching for the volume header.
  649. * Ultimately, we need to search for volume headers in multiple places
  650. * because we might be starting with a multisession image.
  651. * FIXME(eric).
  652. */
  653. #ifndef USE_SCG
  654. in_image = fopen(path, "rb");
  655. if( in_image == NULL )
  656. {
  657. return NULL;
  658. }
  659. #else
  660. if (strchr(path, '/')) {
  661. in_image = fopen(path, "rb");
  662. if( in_image == NULL ) {
  663. return NULL;
  664. }
  665. } else {
  666. if (scsidev_open(path) < 0)
  667. return NULL;
  668. }
  669. #endif
  670. get_session_start(&file_addr);
  671. for(i = 0; i< 100; i++)
  672. {
  673. if (readsecs(file_addr/SECTOR_SIZE, &buffer,
  674. sizeof(buffer)/SECTOR_SIZE) != sizeof(buffer))
  675. error (10, errno, _("Read error on old image %s\n"), path);
  676. vdp = (struct iso_volume_descriptor *)buffer;
  677. if( (strncmp(vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0)
  678. && (isonum_711((unsigned char *) vdp->type) == ISO_VD_PRIMARY) )
  679. {
  680. break;
  681. }
  682. file_addr += SECTOR_SIZE;
  683. }
  684. if( i == 100 )
  685. {
  686. return NULL;
  687. }
  688. pri = (struct iso_primary_descriptor *)vdp;
  689. /*
  690. * Check the blocksize of the image to make sure it is compatible.
  691. */
  692. if( (isonum_723 ((unsigned char *) pri->logical_block_size) != SECTOR_SIZE)
  693. || (isonum_723 ((unsigned char *) pri->volume_set_size) != 1) )
  694. {
  695. return NULL;
  696. }
  697. /*
  698. * Get the location and size of the root directory.
  699. */
  700. rootp = (struct iso_directory_record *)
  701. malloc(sizeof(struct iso_directory_record));
  702. memcpy(rootp, pri->root_directory_record, sizeof(*rootp));
  703. return rootp;
  704. }
  705. void FDECL3(merge_remaining_entries, struct directory *, this_dir,
  706. struct directory_entry **, pnt,
  707. int, n_orig)
  708. {
  709. int i;
  710. struct directory_entry * s_entry;
  711. unsigned int ttbl_extent = 0;
  712. unsigned int ttbl_index = 0;
  713. char whole_path[1024];
  714. /*
  715. * Whatever is leftover in the list needs to get merged back
  716. * into the directory.
  717. */
  718. for( i=0; i < n_orig; i++ )
  719. {
  720. if( pnt[i] == NULL )
  721. {
  722. continue;
  723. }
  724. if( pnt[i]->name != NULL && pnt[i]->whole_name == NULL)
  725. {
  726. /*
  727. * Set the name for this directory.
  728. */
  729. strcpy(whole_path, this_dir->de_name);
  730. strcat(whole_path, SPATH_SEPARATOR);
  731. strcat(whole_path, pnt[i]->name);
  732. pnt[i]->whole_name = strdup(whole_path);
  733. }
  734. if( pnt[i]->name != NULL
  735. && strcmp(pnt[i]->name, "<translation table>") == 0 )
  736. {
  737. ttbl_extent = isonum_733((unsigned char *) pnt[i]->isorec.extent);
  738. ttbl_index = i;
  739. continue;
  740. }
  741. /*
  742. * Skip directories for now - these need to be treated
  743. * differently.
  744. */
  745. if( (pnt[i]->isorec.flags[0] & 2) != 0 )
  746. {
  747. /*
  748. * FIXME - we need to insert this directory into the
  749. * tree, so that the path tables we generate will
  750. * be correct.
  751. */
  752. if( (strcmp(pnt[i]->name, ".") == 0)
  753. || (strcmp(pnt[i]->name, "..") == 0) )
  754. {
  755. free(pnt[i]);
  756. pnt[i] = NULL;
  757. continue;
  758. }
  759. else
  760. {
  761. merge_old_directory_into_tree(pnt[i], this_dir);
  762. }
  763. }
  764. pnt[i]->next = this_dir->contents;
  765. pnt[i]->filedir = this_dir;
  766. this_dir->contents = pnt[i];
  767. pnt[i] = NULL;
  768. }
  769. /*
  770. * If we don't have an entry for the translation table, then
  771. * don't bother trying to copy the starting extent over.
  772. * Note that it is possible that if we are copying the entire
  773. * directory, the entry for the translation table will have already
  774. * been inserted into the linked list and removed from the old
  775. * entries list, in which case we want to leave the extent number
  776. * as it was before.
  777. */
  778. if( ttbl_extent == 0 )
  779. {
  780. return;
  781. }
  782. /*
  783. * Finally, check the directory we are creating to see whether
  784. * there are any new entries in it. If there are not, we can
  785. * reuse the same translation table.
  786. */
  787. for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
  788. {
  789. /*
  790. * Don't care about '.' or '..'. They are never in the table
  791. * anyways.
  792. */
  793. if( s_entry->name != NULL && strcmp(s_entry->name, ".") == 0 )
  794. {
  795. continue;
  796. }
  797. if( s_entry->name != NULL && strcmp(s_entry->name, "..") == 0 )
  798. {
  799. continue;
  800. }
  801. if( strcmp(s_entry->name, "<translation table>") == 0)
  802. {
  803. continue;
  804. }
  805. if( (s_entry->de_flags & SAFE_TO_REUSE_TABLE_ENTRY) == 0 )
  806. {
  807. return;
  808. }
  809. }
  810. /*
  811. * Locate the translation table, and re-use the same extent.
  812. * It isn't clear that there should ever be one in there already
  813. * so for now we try and muddle through the best we can.
  814. */
  815. for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
  816. {
  817. if( strcmp(s_entry->name, "<translation table>") == 0)
  818. {
  819. fprintf (stderr, "Should never get here\n");
  820. set_733(s_entry->isorec.extent, ttbl_extent);
  821. return;
  822. }
  823. }
  824. pnt[ttbl_index]->next = this_dir->contents;
  825. pnt[ttbl_index]->filedir = this_dir;
  826. this_dir->contents = pnt[ttbl_index];
  827. pnt[ttbl_index] = NULL;
  828. }
  829. /*
  830. * Here we have a case of a directory that has completely disappeared from
  831. * the face of the earth on the tree we are mastering from. Go through and
  832. * merge it into the tree, as well as everything beneath it.
  833. *
  834. * Note that if a directory has been moved for some reason, this will
  835. * incorrectly pick it up and attempt to merge it back into the old
  836. * location. FIXME(eric).
  837. */
  838. static int
  839. FDECL2(merge_old_directory_into_tree, struct directory_entry *, dpnt,
  840. struct directory *, parent)
  841. {
  842. struct directory_entry **contents = NULL;
  843. int i;
  844. int n_orig;
  845. struct directory * this_dir, *next_brother;
  846. char whole_path[1024];
  847. this_dir = (struct directory *) e_malloc(sizeof(struct directory));
  848. memset(this_dir, 0, sizeof(struct directory));
  849. this_dir->next = NULL;
  850. this_dir->subdir = NULL;
  851. this_dir->self = dpnt;
  852. this_dir->contents = NULL;
  853. this_dir->size = 0;
  854. this_dir->extent = 0;
  855. this_dir->depth = parent->depth + 1;
  856. this_dir->parent = parent;
  857. if(!parent->subdir)
  858. parent->subdir = this_dir;
  859. else {
  860. next_brother = parent->subdir;
  861. while(next_brother->next) next_brother = next_brother->next;
  862. next_brother->next = this_dir;
  863. }
  864. /*
  865. * Set the name for this directory.
  866. */
  867. strcpy(whole_path, parent->de_name);
  868. strcat(whole_path, SPATH_SEPARATOR);
  869. strcat(whole_path, dpnt->name);
  870. this_dir->de_name = strdup(whole_path);
  871. this_dir->whole_name = strdup(whole_path);
  872. /*
  873. * Now fill this directory using information from the previous
  874. * session.
  875. */
  876. contents = read_merging_directory(&dpnt->isorec, &n_orig);
  877. /*
  878. * Start by simply copying the '.', '..' and non-directory
  879. * entries to this directory. Technically we could let
  880. * merge_remaining_entries handle this, but it gets rather confused
  881. * by the '.' and '..' entries.
  882. */
  883. for(i=0; i < n_orig; i ++ )
  884. {
  885. /*
  886. * We can always reuse the TRANS.TBL in this particular case.
  887. */
  888. contents[i]->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
  889. if( ((contents[i]->isorec.flags[0] & 2) != 0)
  890. && (i >= 2) )
  891. {
  892. continue;
  893. }
  894. /*
  895. * If we have a directory, don't reuse the extent number.
  896. */
  897. if( (contents[i]->isorec.flags[0] & 2) != 0 )
  898. {
  899. memset(contents[i]->isorec.extent, 0, 8);
  900. if( strcmp(contents[i]->name, ".") == 0 )
  901. this_dir->dir_flags |= DIR_HAS_DOT;
  902. if( strcmp(contents[i]->name, "..") == 0 )
  903. this_dir->dir_flags |= DIR_HAS_DOTDOT;
  904. }
  905. /*
  906. * Set the whole name for this file.
  907. */
  908. strcpy(whole_path, this_dir->whole_name);
  909. strcat(whole_path, SPATH_SEPARATOR);
  910. strcat(whole_path, contents[i]->name);
  911. contents[i]->whole_name = strdup(whole_path);
  912. contents[i]->next = this_dir->contents;
  913. contents[i]->filedir = this_dir;
  914. this_dir->contents = contents[i];
  915. contents[i] = NULL;
  916. }
  917. /*
  918. * Zero the extent number for ourselves.
  919. */
  920. memset(dpnt->isorec.extent, 0, 8);
  921. /*
  922. * Anything that is left are other subdirectories that need to be merged.
  923. */
  924. merge_remaining_entries(this_dir, contents, n_orig);
  925. free_mdinfo(contents, n_orig);
  926. #if 0
  927. /*
  928. * This is no longer required. The post-scan sort will handle
  929. * all of this for us.
  930. */
  931. sort_n_finish(this_dir);
  932. #endif
  933. return 0;
  934. }
  935. char * cdwrite_data = NULL;
  936. int
  937. FDECL1(get_session_start, int *, file_addr)
  938. {
  939. char * pnt;
  940. #ifdef CDWRITE_DETERMINES_FIRST_WRITABLE_ADDRESS
  941. /*
  942. * FIXME(eric). We need to coordinate with cdwrite to obtain
  943. * the parameters. For now, we assume we are writing the 2nd session,
  944. * so we start from the session that starts at 0.
  945. */
  946. *file_addr = (16 << 11);
  947. /*
  948. * We need to coordinate with cdwrite to get the next writable address
  949. * from the device. Here is where we use it.
  950. */
  951. session_start = last_extent = last_extent_written = cdwrite_result();
  952. #else
  953. if( cdwrite_data == NULL )
  954. error (1, 0, _("Special parameters for cdwrite not specified with -C\n"));
  955. /*
  956. * Next try and find the ',' in there which delimits the two numbers.
  957. */
  958. pnt = strchr(cdwrite_data, ',');
  959. if( pnt == NULL )
  960. error (1, 0, _("Malformed cdwrite parameters\n"));
  961. *pnt = '\0';
  962. if (file_addr != NULL) {
  963. *file_addr = atol(cdwrite_data) * SECTOR_SIZE;
  964. }
  965. pnt++;
  966. session_start = last_extent = last_extent_written = atol(pnt);
  967. pnt--;
  968. *pnt = ',';
  969. #endif
  970. return 0;
  971. }
  972. /*
  973. * This function scans the directory tree, looking for files, and it makes
  974. * note of everything that is found. We also begin to construct the ISO9660
  975. * directory entries, so that we can determine how large each directory is.
  976. */
  977. int
  978. FDECL2(merge_previous_session,struct directory *, this_dir,
  979. struct iso_directory_record *, mrootp)
  980. {
  981. struct directory_entry **orig_contents = NULL;
  982. struct directory_entry * odpnt = NULL;
  983. int n_orig;
  984. struct directory_entry * s_entry;
  985. int status, lstatus;
  986. struct stat statbuf, lstatbuf;
  987. /*
  988. * Parse the same directory in the image that we are merging
  989. * for multisession stuff.
  990. */
  991. orig_contents = read_merging_directory(mrootp, &n_orig);
  992. if( orig_contents == NULL )
  993. {
  994. return 0;
  995. }
  996. /* Now we scan the directory itself, and look at what is inside of it. */
  997. for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
  998. {
  999. status = stat_filter(s_entry->whole_name, &statbuf);
  1000. lstatus = lstat_filter(s_entry->whole_name, &lstatbuf);
  1001. /*
  1002. * We always should create an entirely new directory tree whenever
  1003. * we generate a new session, unless there were *no* changes whatsoever
  1004. * to any of the directories, in which case it would be kind of pointless
  1005. * to generate a new session.
  1006. *
  1007. * I believe it is possible to rigorously prove that any change anywhere
  1008. * in the filesystem will force the entire tree to be regenerated
  1009. * because the modified directory will get a new extent number. Since
  1010. * each subdirectory of the changed directory has a '..' entry, all of
  1011. * them will need to be rewritten too, and since the parent directory
  1012. * of the modified directory will have an extent pointer to the directory
  1013. * it too will need to be rewritten. Thus we will never be able to reuse
  1014. * any directory information when writing new sessions.
  1015. *
  1016. * We still check the previous session so we can mark off the equivalent
  1017. * entry in the list we got from the original disc, however.
  1018. */
  1019. /*
  1020. * The check_prev_session function looks for an identical entry in
  1021. * the previous session. If we see it, then we copy the extent
  1022. * number to s_entry, and cross it off the list.
  1023. */
  1024. check_prev_session(orig_contents, n_orig, s_entry,
  1025. &statbuf, &lstatbuf, &odpnt);
  1026. if(S_ISDIR(statbuf.st_mode) && odpnt != NULL)
  1027. {
  1028. int dflag;
  1029. if (strcmp(s_entry->name,".") && strcmp(s_entry->name,".."))
  1030. {
  1031. struct directory * child;
  1032. child = find_or_create_directory(this_dir,
  1033. s_entry->whole_name,
  1034. s_entry, 1);
  1035. dflag = merge_previous_session(child,
  1036. &odpnt->isorec);
  1037. /* If unable to scan directory, mark this as a non-directory */
  1038. if(!dflag)
  1039. lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG;
  1040. free(odpnt);
  1041. odpnt = NULL;
  1042. }
  1043. }
  1044. }
  1045. /*
  1046. * Whatever is left over, are things which are no longer in the tree
  1047. * on disk. We need to also merge these into the tree.
  1048. */
  1049. merge_remaining_entries(this_dir, orig_contents, n_orig);
  1050. free_mdinfo(orig_contents, n_orig);
  1051. return 1;
  1052. }