tree.c 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867
  1. /*
  2. * File tree.c - scan directory tree and build memory structures for iso9660
  3. * filesystem
  4. Written by Eric Youngdale (1993).
  5. Copyright 1993 Yggdrasil Computing, Incorporated
  6. Copyright (C) 2009 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. /* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <time.h>
  22. #include <errno.h>
  23. #include <limits.h>
  24. #include "config.h"
  25. #ifndef VMS
  26. #if defined(MAJOR_IN_SYSMACROS)
  27. #include <sys/sysmacros.h>
  28. #endif
  29. #ifdef HAVE_UNISTD_H
  30. #include <unistd.h>
  31. #endif
  32. #include <fctldefs.h>
  33. #if defined(MAJOR_IN_MKDEV)
  34. #include <sys/types.h>
  35. #include <sys/mkdev.h>
  36. #endif
  37. #else
  38. #include <sys/file.h>
  39. #include <vms/fabdef.h>
  40. #include "vms.h"
  41. extern char * strdup(const char *);
  42. #endif
  43. /*
  44. * Autoconf should be able to figure this one out for us and let us know
  45. * whether the system has memmove or not.
  46. */
  47. # ifndef HAVE_MEMMOVE
  48. # define memmove(d, s, n) bcopy ((s), (d), (n))
  49. # endif
  50. #include "mkisofs.h"
  51. #include "iso9660.h"
  52. #include "match.h"
  53. #include <sys/stat.h>
  54. #include "exclude.h"
  55. #ifdef DOESNT_WORK
  56. #ifdef NON_UNIXFS
  57. #define S_ISLNK(m) (0)
  58. #define S_ISSOCK(m) (0)
  59. #define S_ISFIFO(m) (0)
  60. #else
  61. #ifndef S_ISLNK
  62. #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
  63. #endif
  64. #ifndef S_ISSOCK
  65. # ifdef S_IFSOCK
  66. # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
  67. # else
  68. # define S_ISSOCK(m) (0)
  69. # endif
  70. #endif
  71. #endif
  72. #else
  73. #include <statdefs.h>
  74. #endif
  75. #ifdef __SVR4
  76. extern char * strdup(const char *);
  77. #endif
  78. static unsigned char symlink_buff[256];
  79. static void stat_fix __PR((struct stat * st));
  80. static void generate_reloc_directory __PR((void));
  81. static void DECL(attach_dot_entries, (struct directory * dirnode,
  82. struct stat * parent_stat));
  83. static void DECL(delete_directory, (struct directory * parent, struct directory * child));
  84. extern int verbose;
  85. struct stat fstatbuf; /* We use this for the artificial entries we create */
  86. struct stat root_statbuf; /* Stat buffer for root directory */
  87. struct directory * reloc_dir = NULL;
  88. static void
  89. FDECL1(stat_fix, struct stat *, st)
  90. {
  91. /* Remove the uid and gid, they will only be useful on the author's
  92. system. */
  93. st->st_uid = 0;
  94. st->st_gid = 0;
  95. /*
  96. * Make sure the file modes make sense. Turn on all read bits. Turn
  97. * on all exec/search bits if any exec/search bit is set. Turn off
  98. * all write bits, and all special mode bits (on a r/o fs lock bits
  99. * are useless, and with uid+gid 0 don't want set-id bits, either).
  100. */
  101. st->st_mode |= 0444;
  102. #ifndef _WIN32 /* make all file "executable" */
  103. if (st->st_mode & 0111)
  104. #endif /* _WIN32 */
  105. st->st_mode |= 0111;
  106. st->st_mode &= ~07222;
  107. }
  108. int
  109. FDECL2(stat_filter, char *, path, struct stat *, st)
  110. {
  111. int result = stat(path, st);
  112. if (result >= 0 && rationalize)
  113. stat_fix(st);
  114. if ((unsigned) st->st_size > UINT32_MAX)
  115. result = -1;
  116. return result;
  117. }
  118. int
  119. FDECL2(lstat_filter, char *, path, struct stat *, st)
  120. {
  121. int result = lstat(path, st);
  122. if (result >= 0 && rationalize)
  123. stat_fix(st);
  124. if ((unsigned) st->st_size > UINT32_MAX)
  125. result = -1;
  126. return result;
  127. }
  128. static int FDECL1(sort_n_finish, struct directory *, this_dir)
  129. {
  130. struct directory_entry * s_entry;
  131. struct directory_entry * s_entry1;
  132. struct directory_entry * table;
  133. int count;
  134. int d1;
  135. int d2;
  136. int d3;
  137. int new_reclen;
  138. char * c;
  139. int status = 0;
  140. int tablesize = 0;
  141. char newname[34];
  142. char rootname[34];
  143. /* Here we can take the opportunity to toss duplicate entries from the
  144. directory. */
  145. /* ignore if it's hidden */
  146. if(this_dir->dir_flags & INHIBIT_ISO9660_ENTRY)
  147. {
  148. return 0;
  149. }
  150. table = NULL;
  151. init_fstatbuf();
  152. /*
  153. * If we had artificially created this directory, then we might be
  154. * missing the required '.' entries. Create these now if we need
  155. * them.
  156. */
  157. if( (this_dir->dir_flags & (DIR_HAS_DOT | DIR_HAS_DOTDOT)) !=
  158. (DIR_HAS_DOT | DIR_HAS_DOTDOT) )
  159. {
  160. attach_dot_entries(this_dir, &fstatbuf);
  161. }
  162. flush_file_hash();
  163. s_entry = this_dir->contents;
  164. while(s_entry)
  165. {
  166. /* ignore if it's hidden */
  167. if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
  168. {
  169. s_entry = s_entry->next;
  170. continue;
  171. }
  172. /*
  173. * First assume no conflict, and handle this case
  174. */
  175. if(!(s_entry1 = find_file_hash(s_entry->isorec.name)))
  176. {
  177. add_file_hash(s_entry);
  178. s_entry = s_entry->next;
  179. continue;
  180. }
  181. if(s_entry1 == s_entry)
  182. error (1, 0, _("Fatal goof\n"));
  183. /*
  184. * OK, handle the conflicts. Try substitute names until we come
  185. * up with a winner
  186. */
  187. strcpy(rootname, s_entry->isorec.name);
  188. if(full_iso9660_filenames)
  189. {
  190. if(strlen(rootname) > 27) rootname[27] = 0;
  191. }
  192. /*
  193. * Strip off the non-significant part of the name so that we are left
  194. * with a sensible root filename. If we don't find a '.', then try
  195. * a ';'.
  196. */
  197. c = strchr(rootname, '.');
  198. if (c)
  199. *c = 0;
  200. else
  201. {
  202. c = strchr(rootname, ';');
  203. if (c) *c = 0;
  204. }
  205. for(d1 = 0; d1 < 36; d1++)
  206. {
  207. for(d2 = 0; d2 < 36; d2++)
  208. {
  209. for(d3 = 0; d3 < 36; d3++)
  210. {
  211. sprintf(newname,"%s.%c%c%c%s", rootname,
  212. (d1 <= 9 ? '0' + d1 : 'A' + d1 - 10),
  213. (d2 <= 9 ? '0' + d2 : 'A' + d2 - 10),
  214. (d3 <= 9 ? '0' + d3 : 'A' + d3 - 10),
  215. (s_entry->isorec.flags[0] == 2 ||
  216. omit_version_number ? "" : ";1"));
  217. #ifdef VMS
  218. /* Sigh. VAXCRTL seems to be broken here */
  219. {
  220. int ijk = 0;
  221. while(newname[ijk])
  222. {
  223. if(newname[ijk] == ' ') newname[ijk] = '0';
  224. ijk++;
  225. }
  226. }
  227. #endif
  228. if(!find_file_hash(newname)) goto got_valid_name;
  229. }
  230. }
  231. }
  232. /*
  233. * If we fell off the bottom here, we were in real trouble.
  234. */
  235. error (1, 0, _("Unable to generate unique name for file %s\n"), s_entry->name);
  236. got_valid_name:
  237. /*
  238. * OK, now we have a good replacement name. Now decide which one
  239. * of these two beasts should get the name changed
  240. */
  241. if(s_entry->priority < s_entry1->priority)
  242. {
  243. if( verbose > 0 )
  244. {
  245. fprintf (stderr, _("Using %s for %s%s%s (%s)\n"), newname,
  246. this_dir->whole_name, SPATH_SEPARATOR,
  247. s_entry->name, s_entry1->name);
  248. }
  249. s_entry->isorec.name_len[0] = strlen(newname);
  250. new_reclen = sizeof(struct iso_directory_record) -
  251. sizeof(s_entry->isorec.name) +
  252. strlen(newname);
  253. if(use_RockRidge)
  254. {
  255. if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
  256. new_reclen += s_entry->rr_attr_size;
  257. }
  258. if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
  259. s_entry->isorec.length[0] = new_reclen;
  260. strcpy(s_entry->isorec.name, newname);
  261. }
  262. else
  263. {
  264. delete_file_hash(s_entry1);
  265. if( verbose > 0 )
  266. {
  267. fprintf(stderr, _("Using %s for %s%s%s (%s)\n"), newname,
  268. this_dir->whole_name, SPATH_SEPARATOR,
  269. s_entry1->name, s_entry->name);
  270. }
  271. s_entry1->isorec.name_len[0] = strlen(newname);
  272. new_reclen = sizeof(struct iso_directory_record) -
  273. sizeof(s_entry1->isorec.name) +
  274. strlen(newname);
  275. if(use_RockRidge)
  276. {
  277. if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
  278. new_reclen += s_entry1->rr_attr_size;
  279. }
  280. if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
  281. s_entry1->isorec.length[0] = new_reclen;
  282. strcpy(s_entry1->isorec.name, newname);
  283. add_file_hash(s_entry1);
  284. }
  285. add_file_hash(s_entry);
  286. s_entry = s_entry->next;
  287. }
  288. if(generate_tables
  289. && !find_file_hash("TRANS.TBL")
  290. && (reloc_dir != this_dir)
  291. && (this_dir->extent == 0) )
  292. {
  293. /*
  294. * First we need to figure out how big this table is
  295. */
  296. for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
  297. {
  298. if(strcmp(s_entry->name, ".") == 0 ||
  299. strcmp(s_entry->name, "..") == 0) continue;
  300. if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY) continue;
  301. if(s_entry->table) tablesize += 35 + strlen(s_entry->table);
  302. }
  303. }
  304. if( tablesize > 0 )
  305. {
  306. table = (struct directory_entry *)
  307. e_malloc(sizeof (struct directory_entry));
  308. memset(table, 0, sizeof(struct directory_entry));
  309. table->table = NULL;
  310. table->next = this_dir->contents;
  311. this_dir->contents = table;
  312. table->filedir = root;
  313. table->isorec.flags[0] = 0;
  314. table->priority = 32768;
  315. iso9660_date(table->isorec.date, fstatbuf.st_mtime);
  316. table->inode = TABLE_INODE;
  317. table->dev = (dev_t) UNCACHED_DEVICE;
  318. set_723(table->isorec.volume_sequence_number, volume_sequence_number);
  319. set_733((char *) table->isorec.size, tablesize);
  320. table->size = tablesize;
  321. table->filedir = this_dir;
  322. #ifdef ERIC_neverdef
  323. table->de_flags |= INHIBIT_JOLIET_ENTRY;
  324. #endif
  325. table->name = strdup("<translation table>");
  326. table->table = (char *) e_malloc(ROUND_UP(tablesize));
  327. memset(table->table, 0, ROUND_UP(tablesize));
  328. iso9660_file_length ("TRANS.TBL", table, 0);
  329. if(use_RockRidge)
  330. {
  331. fstatbuf.st_mode = 0444 | S_IFREG;
  332. fstatbuf.st_nlink = 1;
  333. generate_rock_ridge_attributes("",
  334. "TRANS.TBL", table,
  335. &fstatbuf, &fstatbuf, 0);
  336. }
  337. }
  338. /*
  339. * We have now chosen the 8.3 names and we should now know the length
  340. * of every entry in the directory.
  341. */
  342. for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
  343. {
  344. /* skip if it's hidden */
  345. if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
  346. {
  347. continue;
  348. }
  349. new_reclen = strlen(s_entry->isorec.name);
  350. /*
  351. * First update the path table sizes for directories.
  352. */
  353. if(s_entry->isorec.flags[0] == 2)
  354. {
  355. if (strcmp(s_entry->name,".") && strcmp(s_entry->name,".."))
  356. {
  357. path_table_size += new_reclen + sizeof(struct iso_path_table) - 1;
  358. if (new_reclen & 1) path_table_size++;
  359. }
  360. else
  361. {
  362. new_reclen = 1;
  363. if (this_dir == root && strlen(s_entry->name) == 1)
  364. {
  365. path_table_size += sizeof(struct iso_path_table);
  366. }
  367. }
  368. }
  369. if(path_table_size & 1) path_table_size++; /* For odd lengths we pad */
  370. s_entry->isorec.name_len[0] = new_reclen;
  371. new_reclen +=
  372. sizeof(struct iso_directory_record) -
  373. sizeof(s_entry->isorec.name);
  374. if (new_reclen & 1)
  375. new_reclen++;
  376. new_reclen += s_entry->rr_attr_size;
  377. if (new_reclen & 1) new_reclen++;
  378. if(new_reclen > 0xff)
  379. error (1, 0, _("Fatal error - RR overflow for file %s\n"),
  380. s_entry->name);
  381. s_entry->isorec.length[0] = new_reclen;
  382. }
  383. status = sort_directory(&this_dir->contents);
  384. if( status > 0 )
  385. {
  386. fprintf (stderr, _("Unable to sort directory %s\n"),
  387. this_dir->whole_name);
  388. }
  389. /*
  390. * If we are filling out a TRANS.TBL, generate the entries that will
  391. * go in the thing.
  392. */
  393. if(table)
  394. {
  395. count = 0;
  396. for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){
  397. if(s_entry == table) continue;
  398. if(!s_entry->table) continue;
  399. if(strcmp(s_entry->name, ".") == 0 ||
  400. strcmp(s_entry->name, "..") == 0) continue;
  401. if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY) continue;
  402. /*
  403. * Warning: we cannot use the return value of sprintf because
  404. * old BSD based sprintf() implementations will return
  405. * a pointer to the result instead of a count.
  406. */
  407. sprintf(table->table + count, "%c %-34s%s",
  408. s_entry->table[0],
  409. s_entry->isorec.name, s_entry->table+1);
  410. count += strlen(table->table + count);
  411. free(s_entry->table);
  412. s_entry->table = NULL;
  413. }
  414. if(count != tablesize)
  415. error (1, 0, _("Translation table size mismatch %d %d\n"),
  416. count, tablesize);
  417. }
  418. /*
  419. * Now go through the directory and figure out how large this one will be.
  420. * Do not split a directory entry across a sector boundary
  421. */
  422. s_entry = this_dir->contents;
  423. this_dir->ce_bytes = 0;
  424. while(s_entry)
  425. {
  426. /* skip if it's hidden */
  427. if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
  428. s_entry = s_entry->next;
  429. continue;
  430. }
  431. new_reclen = s_entry->isorec.length[0];
  432. if ((this_dir->size & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE)
  433. this_dir->size = (this_dir->size + (SECTOR_SIZE - 1)) &
  434. ~(SECTOR_SIZE - 1);
  435. this_dir->size += new_reclen;
  436. /* See if continuation entries were used on disc */
  437. if(use_RockRidge &&
  438. s_entry->rr_attr_size != s_entry->total_rr_attr_size)
  439. {
  440. unsigned char * pnt;
  441. int len;
  442. int nbytes;
  443. pnt = s_entry->rr_attributes;
  444. len = s_entry->total_rr_attr_size;
  445. /*
  446. * We make sure that each continuation entry record is not
  447. * split across sectors, but each file could in theory have more
  448. * than one CE, so we scan through and figure out what we need.
  449. */
  450. while(len > 3)
  451. {
  452. if(pnt[0] == 'C' && pnt[1] == 'E')
  453. {
  454. nbytes = get_733((char *) pnt+20);
  455. if((this_dir->ce_bytes & (SECTOR_SIZE - 1)) + nbytes >=
  456. SECTOR_SIZE) this_dir->ce_bytes =
  457. ROUND_UP(this_dir->ce_bytes);
  458. /* Now store the block in the ce buffer */
  459. this_dir->ce_bytes += nbytes;
  460. if(this_dir->ce_bytes & 1) this_dir->ce_bytes++;
  461. }
  462. len -= pnt[2];
  463. pnt += pnt[2];
  464. }
  465. }
  466. s_entry = s_entry->next;
  467. }
  468. return status;
  469. }
  470. static void generate_reloc_directory()
  471. {
  472. time_t current_time;
  473. struct directory_entry *s_entry;
  474. /* Create an entry for our internal tree */
  475. time (&current_time);
  476. reloc_dir = (struct directory *)
  477. e_malloc(sizeof(struct directory));
  478. memset(reloc_dir, 0, sizeof(struct directory));
  479. reloc_dir->parent = root;
  480. reloc_dir->next = root->subdir;
  481. root->subdir = reloc_dir;
  482. reloc_dir->depth = 1;
  483. reloc_dir->whole_name = strdup("./rr_moved");
  484. reloc_dir->de_name = strdup("rr_moved");
  485. reloc_dir->extent = 0;
  486. /* Now create an actual directory entry */
  487. s_entry = (struct directory_entry *)
  488. e_malloc(sizeof (struct directory_entry));
  489. memset(s_entry, 0, sizeof(struct directory_entry));
  490. s_entry->next = root->contents;
  491. reloc_dir->self = s_entry;
  492. /*
  493. * The rr_moved entry will not appear in the Joliet tree.
  494. */
  495. reloc_dir->dir_flags |= INHIBIT_JOLIET_ENTRY;
  496. s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
  497. root->contents = s_entry;
  498. root->contents->name = strdup(reloc_dir->de_name);
  499. root->contents->filedir = root;
  500. root->contents->isorec.flags[0] = 2;
  501. root->contents->priority = 32768;
  502. iso9660_date(root->contents->isorec.date, current_time);
  503. root->contents->inode = UNCACHED_INODE;
  504. root->contents->dev = (dev_t) UNCACHED_DEVICE;
  505. set_723(root->contents->isorec.volume_sequence_number, volume_sequence_number);
  506. iso9660_file_length (reloc_dir->de_name, root->contents, 1);
  507. if(use_RockRidge){
  508. fstatbuf.st_mode = 0555 | S_IFDIR;
  509. fstatbuf.st_nlink = 2;
  510. generate_rock_ridge_attributes("",
  511. "rr_moved", s_entry,
  512. &fstatbuf, &fstatbuf, 0);
  513. };
  514. /* Now create the . and .. entries in rr_moved */
  515. /* Now create an actual directory entry */
  516. attach_dot_entries(reloc_dir, &root_statbuf);
  517. }
  518. /*
  519. * Function: attach_dot_entries
  520. *
  521. * Purpose: Create . and .. entries for a new directory.
  522. *
  523. * Notes: Only used for artificial directories that
  524. * we are creating.
  525. */
  526. static void FDECL2(attach_dot_entries, struct directory *, dirnode,
  527. struct stat *, parent_stat)
  528. {
  529. struct directory_entry *s_entry;
  530. struct directory_entry *orig_contents;
  531. int deep_flag = 0;
  532. init_fstatbuf();
  533. orig_contents = dirnode->contents;
  534. if( (dirnode->dir_flags & DIR_HAS_DOTDOT) == 0 )
  535. {
  536. s_entry = (struct directory_entry *)
  537. e_malloc(sizeof (struct directory_entry));
  538. memcpy(s_entry, dirnode->self,
  539. sizeof(struct directory_entry));
  540. s_entry->name = strdup("..");
  541. s_entry->whole_name = NULL;
  542. s_entry->isorec.name_len[0] = 1;
  543. s_entry->isorec.flags[0] = 2; /* Mark as a directory */
  544. iso9660_file_length ("..", s_entry, 1);
  545. iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime);
  546. s_entry->filedir = dirnode->parent;
  547. dirnode->contents = s_entry;
  548. dirnode->contents->next = orig_contents;
  549. orig_contents = s_entry;
  550. if(use_RockRidge)
  551. {
  552. if( parent_stat == NULL )
  553. {
  554. parent_stat = &fstatbuf;
  555. }
  556. generate_rock_ridge_attributes("",
  557. "..", s_entry,
  558. parent_stat,
  559. parent_stat, 0);
  560. }
  561. dirnode->dir_flags |= DIR_HAS_DOTDOT;
  562. }
  563. if( (dirnode->dir_flags & DIR_HAS_DOT) == 0 )
  564. {
  565. s_entry = (struct directory_entry *)
  566. e_malloc(sizeof (struct directory_entry));
  567. memcpy(s_entry, dirnode->self,
  568. sizeof(struct directory_entry));
  569. s_entry->name = strdup(".");
  570. s_entry->whole_name = NULL;
  571. s_entry->isorec.name_len[0] = 1;
  572. s_entry->isorec.flags[0] = 2; /* Mark as a directory */
  573. iso9660_file_length (".", s_entry, 1);
  574. iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime);
  575. s_entry->filedir = dirnode;
  576. dirnode->contents = s_entry;
  577. dirnode->contents->next = orig_contents;
  578. if(use_RockRidge)
  579. {
  580. fstatbuf.st_mode = 0555 | S_IFDIR;
  581. fstatbuf.st_nlink = 2;
  582. if( dirnode == root )
  583. {
  584. deep_flag |= NEED_CE | NEED_SP; /* For extension record */
  585. }
  586. generate_rock_ridge_attributes("",
  587. ".", s_entry,
  588. &fstatbuf, &fstatbuf, deep_flag);
  589. }
  590. dirnode->dir_flags |= DIR_HAS_DOT;
  591. }
  592. }
  593. static void FDECL2(update_nlink, struct directory_entry *, s_entry, int, value)
  594. {
  595. unsigned char * pnt;
  596. int len;
  597. pnt = s_entry->rr_attributes;
  598. len = s_entry->total_rr_attr_size;
  599. while(len)
  600. {
  601. if(pnt[0] == 'P' && pnt[1] == 'X')
  602. {
  603. set_733((char *) pnt+12, value);
  604. break;
  605. }
  606. len -= pnt[2];
  607. pnt += pnt[2];
  608. }
  609. }
  610. static void FDECL1(increment_nlink, struct directory_entry *, s_entry)
  611. {
  612. unsigned char * pnt;
  613. int len, nlink;
  614. pnt = s_entry->rr_attributes;
  615. len = s_entry->total_rr_attr_size;
  616. while(len)
  617. {
  618. if(pnt[0] == 'P' && pnt[1] == 'X')
  619. {
  620. nlink = get_733((char *) pnt+12);
  621. set_733((char *) pnt+12, nlink+1);
  622. break;
  623. }
  624. len -= pnt[2];
  625. pnt += pnt[2];
  626. }
  627. }
  628. void finish_cl_pl_entries(){
  629. struct directory_entry *s_entry, *s_entry1;
  630. struct directory * d_entry;
  631. /* if the reloc_dir is hidden (empty), then return */
  632. if (reloc_dir->dir_flags & INHIBIT_ISO9660_ENTRY)
  633. return;
  634. s_entry = reloc_dir->contents;
  635. s_entry = s_entry->next->next; /* Skip past . and .. */
  636. for(; s_entry; s_entry = s_entry->next){
  637. /* skip if it's hidden */
  638. if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
  639. continue;
  640. }
  641. d_entry = reloc_dir->subdir;
  642. while(d_entry){
  643. if(d_entry->self == s_entry) break;
  644. d_entry = d_entry->next;
  645. };
  646. if(!d_entry)
  647. error (1, 0, _("Unable to locate directory parent\n"));
  648. /* First fix the PL pointer in the directory in the rr_reloc dir */
  649. s_entry1 = d_entry->contents->next;
  650. set_733((char *) s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8,
  651. s_entry->filedir->extent);
  652. /* Now fix the CL pointer */
  653. s_entry1 = s_entry->parent_rec;
  654. set_733((char *) s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8,
  655. d_entry->extent);
  656. s_entry->filedir = reloc_dir; /* Now we can fix this */
  657. }
  658. /* Next we need to modify the NLINK terms in the assorted root directory records
  659. to account for the presence of the RR_MOVED directory */
  660. increment_nlink(root->self);
  661. increment_nlink(root->self->next);
  662. d_entry = root->subdir;
  663. while(d_entry){
  664. increment_nlink(d_entry->contents->next);
  665. d_entry = d_entry->next;
  666. };
  667. }
  668. /*
  669. * Function: scan_directory_tree
  670. *
  671. * Purpose: Walk through a directory on the local machine
  672. * filter those things we don't want to include
  673. * and build our representation of a dir.
  674. *
  675. * Notes:
  676. */
  677. int
  678. FDECL3(scan_directory_tree,struct directory *, this_dir,
  679. char *, path,
  680. struct directory_entry *, de)
  681. {
  682. DIR * current_dir;
  683. char whole_path[1024];
  684. struct dirent * d_entry;
  685. struct directory * parent;
  686. int dflag;
  687. char * old_path;
  688. if (verbose > 1)
  689. {
  690. fprintf (stderr, _("Scanning %s\n"), path);
  691. }
  692. current_dir = opendir(path);
  693. d_entry = NULL;
  694. /* Apparently NFS sometimes allows you to open the directory, but
  695. then refuses to allow you to read the contents. Allow for this */
  696. old_path = path;
  697. if(current_dir) d_entry = readdir(current_dir);
  698. if(!current_dir || !d_entry)
  699. {
  700. fprintf (stderr, _("Unable to open directory %s\n"), path);
  701. de->isorec.flags[0] &= ~2; /* Mark as not a directory */
  702. if(current_dir) closedir(current_dir);
  703. return 0;
  704. }
  705. parent = de->filedir;
  706. /* Set up the struct for the current directory, and insert it into the
  707. tree */
  708. #ifdef VMS
  709. vms_path_fixup(path);
  710. #endif
  711. /*
  712. * if entry for this sub-directory is hidden, then hide this directory
  713. */
  714. if (de->de_flags & INHIBIT_ISO9660_ENTRY)
  715. this_dir->dir_flags |= INHIBIT_ISO9660_ENTRY;
  716. if (de->de_flags & INHIBIT_JOLIET_ENTRY)
  717. this_dir->dir_flags |= INHIBIT_JOLIET_ENTRY;
  718. /*
  719. * Now we scan the directory itself, and look at what is inside of it.
  720. */
  721. dflag = 0;
  722. while(1==1){
  723. /* The first time through, skip this, since we already asked for
  724. the first entry when we opened the directory. */
  725. if(dflag) d_entry = readdir(current_dir);
  726. dflag++;
  727. if(!d_entry) break;
  728. /* OK, got a valid entry */
  729. /* If we do not want all files, then pitch the backups. */
  730. if(!all_files){
  731. if( strchr(d_entry->d_name,'~')
  732. || strchr(d_entry->d_name,'#'))
  733. {
  734. if( verbose > 0 )
  735. {
  736. fprintf (stderr, _("Ignoring file %s\n"), d_entry->d_name);
  737. }
  738. continue;
  739. }
  740. }
  741. if(strlen(path)+strlen(d_entry->d_name) + 2 > sizeof(whole_path))
  742. error (1, 0, _("Overflow of stat buffer\n"));
  743. /* Generate the complete ASCII path for this file */
  744. strcpy(whole_path, path);
  745. #ifndef VMS
  746. if(whole_path[strlen(whole_path)-1] != '/')
  747. strcat(whole_path, "/");
  748. #endif
  749. strcat(whole_path, d_entry->d_name);
  750. /** Should we exclude this file ? */
  751. if (matches(d_entry->d_name) || matches(whole_path)) {
  752. if (verbose > 1) {
  753. fprintf (stderr, _("Excluded by match: %s\n"), whole_path);
  754. }
  755. continue;
  756. }
  757. if( generate_tables
  758. && strcmp(d_entry->d_name, "TRANS.TBL") == 0 )
  759. {
  760. /*
  761. * Ignore this entry. We are going to be generating new
  762. * versions of these files, and we need to ignore any
  763. * originals that we might have found.
  764. */
  765. if (verbose > 1)
  766. {
  767. fprintf (stderr, _("Excluded: %s\n"), whole_path);
  768. }
  769. continue;
  770. }
  771. /*
  772. * If we already have a '.' or a '..' entry, then don't
  773. * insert new ones.
  774. */
  775. if( strcmp(d_entry->d_name, ".") == 0
  776. && this_dir->dir_flags & DIR_HAS_DOT )
  777. {
  778. continue;
  779. }
  780. if( strcmp(d_entry->d_name, "..") == 0
  781. && this_dir->dir_flags & DIR_HAS_DOTDOT )
  782. {
  783. continue;
  784. }
  785. #if 0
  786. if (verbose > 1) fprintf(stderr, "%s\n",whole_path);
  787. #endif
  788. /*
  789. * This actually adds the entry to the directory in question.
  790. */
  791. insert_file_entry(this_dir, whole_path, d_entry->d_name);
  792. }
  793. closedir(current_dir);
  794. return 1;
  795. }
  796. /*
  797. * Function: insert_file_entry
  798. *
  799. * Purpose: Insert one entry into our directory node.
  800. *
  801. * Note:
  802. * This function inserts a single entry into the directory. It
  803. * is assumed that all filtering and decision making regarding what
  804. * we want to include has already been made, so the purpose of this
  805. * is to insert one entry (file, link, dir, etc), into this directory.
  806. * Note that if the entry is a dir (or if we are following links,
  807. * and the thing it points to is a dir), then we will scan those
  808. * trees before we return.
  809. */
  810. int
  811. FDECL3(insert_file_entry,struct directory *, this_dir,
  812. char *, whole_path,
  813. char *, short_name)
  814. {
  815. struct stat statbuf, lstatbuf;
  816. struct directory_entry * s_entry, *s_entry1;
  817. int lstatus;
  818. int status;
  819. int deep_flag;
  820. status = stat_filter(whole_path, &statbuf);
  821. lstatus = lstat_filter(whole_path, &lstatbuf);
  822. if( (status == -1) && (lstatus == -1) )
  823. {
  824. /*
  825. * This means that the file doesn't exist, or isn't accessible.
  826. * Sometimes this is because of NFS permissions problems.
  827. */
  828. fprintf (stderr, _("Non-existant or inaccessible: %s\n"),whole_path);
  829. return 0;
  830. }
  831. if(this_dir == root && strcmp(short_name, ".") == 0)
  832. root_statbuf = statbuf; /* Save this for later on */
  833. /* We do this to make sure that the root entries are consistent */
  834. if(this_dir == root && strcmp(short_name, "..") == 0)
  835. {
  836. statbuf = root_statbuf;
  837. lstatbuf = root_statbuf;
  838. }
  839. if(S_ISLNK(lstatbuf.st_mode))
  840. {
  841. /* Here we decide how to handle the symbolic links. Here
  842. we handle the general case - if we are not following
  843. links or there is an error, then we must change
  844. something. If RR is in use, it is easy, we let RR
  845. describe the file. If not, then we punt the file. */
  846. if((status || !follow_links))
  847. {
  848. if(use_RockRidge)
  849. {
  850. status = 0;
  851. statbuf.st_size = 0;
  852. STAT_INODE(statbuf) = UNCACHED_INODE;
  853. statbuf.st_dev = (dev_t) UNCACHED_DEVICE;
  854. statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG;
  855. } else {
  856. if(follow_links)
  857. {
  858. fprintf (stderr,
  859. _("Unable to stat file %s - ignoring and continuing.\n"),
  860. whole_path);
  861. }
  862. else
  863. {
  864. fprintf (stderr,
  865. _("Symlink %s ignored - continuing.\n"),
  866. whole_path);
  867. return 0; /* Non Rock Ridge discs - ignore all symlinks */
  868. }
  869. }
  870. }
  871. /* Here we handle a different kind of case. Here we have
  872. a symlink, but we want to follow symlinks. If we run
  873. across a directory loop, then we need to pretend that
  874. we are not following symlinks for this file. If this
  875. is the first time we have seen this, then make this
  876. seem as if there was no symlink there in the first
  877. place */
  878. if( follow_links
  879. && S_ISDIR(statbuf.st_mode) )
  880. {
  881. if( strcmp(short_name, ".")
  882. && strcmp(short_name, "..") )
  883. {
  884. if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)))
  885. {
  886. if(!use_RockRidge)
  887. {
  888. fprintf (stderr, _("Already cached directory seen (%s)\n"),
  889. whole_path);
  890. return 0;
  891. }
  892. statbuf.st_size = 0;
  893. STAT_INODE(statbuf) = UNCACHED_INODE;
  894. statbuf.st_dev = (dev_t) UNCACHED_DEVICE;
  895. statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG;
  896. }
  897. else
  898. {
  899. lstatbuf = statbuf;
  900. add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
  901. }
  902. }
  903. }
  904. /*
  905. * For non-directories, we just copy the stat information over
  906. * so we correctly include this file.
  907. */
  908. if( follow_links
  909. && !S_ISDIR(statbuf.st_mode) )
  910. {
  911. lstatbuf = statbuf;
  912. }
  913. }
  914. /*
  915. * Add directories to the cache so that we don't waste space even
  916. * if we are supposed to be following symlinks.
  917. */
  918. if( follow_links
  919. && strcmp(short_name, ".")
  920. && strcmp(short_name, "..")
  921. && S_ISDIR(statbuf.st_mode) )
  922. {
  923. add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
  924. }
  925. if(S_ISREG(lstatbuf.st_mode) && (status = access(whole_path, R_OK)))
  926. {
  927. fprintf (stderr, _("File %s is not readable (%s) - ignoring\n"),
  928. whole_path, strerror (errno));
  929. return 0;
  930. }
  931. /* Add this so that we can detect directory loops with hard links.
  932. If we are set up to follow symlinks, then we skip this checking. */
  933. if( !follow_links
  934. && S_ISDIR(lstatbuf.st_mode)
  935. && strcmp(short_name, ".")
  936. && strcmp(short_name, "..") )
  937. {
  938. if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)))
  939. error (1, 0, _("Directory loop - fatal goof (%s %lx %lu).\n"),
  940. whole_path, (unsigned long) statbuf.st_dev,
  941. (unsigned long) STAT_INODE(statbuf));
  942. add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
  943. }
  944. if (!S_ISCHR(lstatbuf.st_mode) && !S_ISBLK(lstatbuf.st_mode) &&
  945. !S_ISFIFO(lstatbuf.st_mode) && !S_ISSOCK(lstatbuf.st_mode)
  946. && !S_ISLNK(lstatbuf.st_mode) && !S_ISREG(lstatbuf.st_mode) &&
  947. !S_ISDIR(lstatbuf.st_mode)) {
  948. fprintf (stderr, _("Unknown file type %s - ignoring and continuing.\n"),
  949. whole_path);
  950. return 0;
  951. }
  952. /* Who knows what trash this is - ignore and continue */
  953. if(status)
  954. {
  955. fprintf (stderr,
  956. _("Unable to stat file %s - ignoring and continuing.\n"),
  957. whole_path);
  958. return 0;
  959. }
  960. /*
  961. * Check to see if we have already seen this directory node.
  962. * If so, then we don't create a new entry for it, but we do want
  963. * to recurse beneath it and add any new files we do find.
  964. */
  965. if (S_ISDIR(statbuf.st_mode))
  966. {
  967. int dflag;
  968. for( s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
  969. {
  970. if( strcmp(s_entry->name, short_name) == 0 )
  971. {
  972. break;
  973. }
  974. }
  975. if ( s_entry != NULL
  976. && strcmp(short_name,".")
  977. && strcmp(short_name,".."))
  978. {
  979. struct directory * child;
  980. if ( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0)
  981. {
  982. for( s_entry = reloc_dir->contents; s_entry; s_entry = s_entry->next)
  983. {
  984. if( strcmp(s_entry->name, short_name) == 0 )
  985. {
  986. break;
  987. }
  988. }
  989. child = find_or_create_directory(reloc_dir, whole_path,
  990. s_entry, 1);
  991. }
  992. else
  993. {
  994. child = find_or_create_directory(this_dir, whole_path,
  995. s_entry, 1);
  996. /* If unable to scan directory, mark this as a non-directory */
  997. }
  998. dflag = scan_directory_tree(child, whole_path, s_entry);
  999. if(!dflag)
  1000. {
  1001. lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG;
  1002. }
  1003. return 0;
  1004. }
  1005. }
  1006. s_entry = (struct directory_entry *)
  1007. e_malloc(sizeof (struct directory_entry));
  1008. s_entry->next = this_dir->contents;
  1009. memset(s_entry->isorec.extent, 0, 8);
  1010. this_dir->contents = s_entry;
  1011. deep_flag = 0;
  1012. s_entry->table = NULL;
  1013. s_entry->name = strdup(short_name);
  1014. s_entry->whole_name = strdup (whole_path);
  1015. s_entry->de_flags = 0;
  1016. /*
  1017. * If the current directory is hidden, then hide all it's members
  1018. * otherwise check if this entry needs to be hidden as well */
  1019. if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY) {
  1020. s_entry->de_flags |= INHIBIT_ISO9660_ENTRY;
  1021. }
  1022. else if (strcmp(short_name,".") && strcmp(short_name,"..")) {
  1023. if (i_matches(short_name) || i_matches(whole_path)) {
  1024. if (verbose > 1) {
  1025. fprintf (stderr, _("Hidden from ISO9660 tree: %s\n"), whole_path);
  1026. }
  1027. s_entry->de_flags |= INHIBIT_ISO9660_ENTRY;
  1028. }
  1029. }
  1030. if (this_dir != reloc_dir && this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) {
  1031. s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
  1032. }
  1033. else if (strcmp(short_name,".") && strcmp(short_name,"..")) {
  1034. if (j_matches(short_name) || j_matches(whole_path)) {
  1035. if (verbose > 1) {
  1036. fprintf (stderr, _("Hidden from Joliet tree: %s\n"), whole_path);
  1037. }
  1038. s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
  1039. }
  1040. }
  1041. s_entry->filedir = this_dir;
  1042. s_entry->isorec.flags[0] = 0;
  1043. s_entry->isorec.ext_attr_length[0] = 0;
  1044. iso9660_date(s_entry->isorec.date, statbuf.st_mtime);
  1045. s_entry->isorec.file_unit_size[0] = 0;
  1046. s_entry->isorec.interleave[0] = 0;
  1047. if( strcmp(short_name, ".") == 0)
  1048. {
  1049. this_dir->dir_flags |= DIR_HAS_DOT;
  1050. }
  1051. if( strcmp(short_name, "..") == 0)
  1052. {
  1053. this_dir->dir_flags |= DIR_HAS_DOTDOT;
  1054. }
  1055. if( this_dir->parent
  1056. && this_dir->parent == reloc_dir
  1057. && strcmp(short_name, "..") == 0)
  1058. {
  1059. s_entry->inode = UNCACHED_INODE;
  1060. s_entry->dev = (dev_t) UNCACHED_DEVICE;
  1061. deep_flag = NEED_PL;
  1062. }
  1063. else
  1064. {
  1065. s_entry->inode = STAT_INODE(statbuf);
  1066. s_entry->dev = statbuf.st_dev;
  1067. }
  1068. set_723(s_entry->isorec.volume_sequence_number, volume_sequence_number);
  1069. iso9660_file_length(short_name, s_entry, S_ISDIR(statbuf.st_mode));
  1070. s_entry->rr_attr_size = 0;
  1071. s_entry->total_rr_attr_size = 0;
  1072. s_entry->rr_attributes = NULL;
  1073. /* Directories are assigned sizes later on */
  1074. if (!S_ISDIR(statbuf.st_mode))
  1075. {
  1076. if (S_ISCHR(lstatbuf.st_mode) || S_ISBLK(lstatbuf.st_mode) ||
  1077. S_ISFIFO(lstatbuf.st_mode) || S_ISSOCK(lstatbuf.st_mode)
  1078. || S_ISLNK(lstatbuf.st_mode))
  1079. {
  1080. s_entry->size = 0;
  1081. statbuf.st_size = 0;
  1082. }
  1083. else
  1084. {
  1085. s_entry->size = statbuf.st_size;
  1086. }
  1087. set_733((char *) s_entry->isorec.size, statbuf.st_size);
  1088. }
  1089. else
  1090. {
  1091. s_entry->isorec.flags[0] = 2;
  1092. }
  1093. if (strcmp(short_name,".") && strcmp(short_name,"..") &&
  1094. S_ISDIR(statbuf.st_mode) && this_dir->depth > RR_relocation_depth)
  1095. {
  1096. struct directory * child;
  1097. if(!reloc_dir) generate_reloc_directory();
  1098. /*
  1099. * Replicate the entry for this directory. The old one will stay where it
  1100. * is, and it will be neutered so that it no longer looks like a directory.
  1101. * The new one will look like a directory, and it will be put in the reloc_dir.
  1102. */
  1103. s_entry1 = (struct directory_entry *)
  1104. e_malloc(sizeof (struct directory_entry));
  1105. memcpy(s_entry1, s_entry, sizeof(struct directory_entry));
  1106. s_entry1->table = NULL;
  1107. s_entry1->name = strdup(this_dir->contents->name);
  1108. s_entry1->whole_name = strdup(this_dir->contents->whole_name);
  1109. s_entry1->next = reloc_dir->contents;
  1110. reloc_dir->contents = s_entry1;
  1111. s_entry1->priority = 32768;
  1112. s_entry1->parent_rec = this_dir->contents;
  1113. deep_flag = NEED_RE;
  1114. if(use_RockRidge)
  1115. {
  1116. generate_rock_ridge_attributes(whole_path,
  1117. short_name, s_entry1,
  1118. &statbuf, &lstatbuf, deep_flag);
  1119. }
  1120. deep_flag = 0;
  1121. /* We need to set this temporarily so that the parent to this
  1122. is correctly determined. */
  1123. s_entry1->filedir = reloc_dir;
  1124. child = find_or_create_directory(reloc_dir, whole_path,
  1125. s_entry1, 0);
  1126. scan_directory_tree(child, whole_path, s_entry1);
  1127. s_entry1->filedir = this_dir;
  1128. statbuf.st_size = 0;
  1129. statbuf.st_mode &= 0777;
  1130. set_733((char *) s_entry->isorec.size, 0);
  1131. s_entry->size = 0;
  1132. s_entry->isorec.flags[0] = 0;
  1133. s_entry->inode = UNCACHED_INODE;
  1134. s_entry->de_flags |= RELOCATED_DIRECTORY;
  1135. deep_flag = NEED_CL;
  1136. }
  1137. if(generate_tables
  1138. && strcmp(s_entry->name, ".")
  1139. && strcmp(s_entry->name, ".."))
  1140. {
  1141. char buffer[2048];
  1142. int nchar;
  1143. switch(lstatbuf.st_mode & S_IFMT)
  1144. {
  1145. case S_IFDIR:
  1146. sprintf(buffer,"D\t%s\n",
  1147. s_entry->name);
  1148. break;
  1149. #ifdef S_IFBLK
  1150. /* extra for WIN32 - if it doesn't have the major/minor defined, then
  1151. S_IFBLK and S_IFCHR type files are unlikely to exist anyway ...
  1152. code similar to that in rock.c */
  1153. /* for some reason, MAJOR_IN_SYSMACROS isn't defined on a SunOS when
  1154. it should be, so see if major() is defined instead */
  1155. /*
  1156. #if !(defined(MAJOR_IN_SYSMACROS) || defined(MAJOR_IN_MKDEV))
  1157. */
  1158. #ifndef major
  1159. #define major(dev) (sizeof(dev_t) <= 2 ? ((dev) >> 8) : \
  1160. (sizeof(dev_t) <= 4 ? (((dev) >> 8) >> 8) : \
  1161. (((dev) >> 16) >> 16)))
  1162. #define minor(dev) (sizeof(dev_t) <= 2 ? (dev) & 0xff : \
  1163. (sizeof(dev_t) <= 4 ? (dev) & 0xffff : \
  1164. (dev) & 0xffffffff))
  1165. #endif
  1166. case S_IFBLK:
  1167. sprintf(buffer,"B\t%s\t%lu %lu\n",
  1168. s_entry->name,
  1169. (unsigned long) major(statbuf.st_rdev),
  1170. (unsigned long) minor(statbuf.st_rdev));
  1171. break;
  1172. #endif
  1173. #ifdef S_IFIFO
  1174. case S_IFIFO:
  1175. sprintf(buffer,"P\t%s\n",
  1176. s_entry->name);
  1177. break;
  1178. #endif
  1179. #ifdef S_IFCHR
  1180. case S_IFCHR:
  1181. sprintf(buffer,"C\t%s\t%lu %lu\n",
  1182. s_entry->name,
  1183. (unsigned long) major(statbuf.st_rdev),
  1184. (unsigned long) minor(statbuf.st_rdev));
  1185. break;
  1186. #endif
  1187. #ifdef S_IFLNK
  1188. case S_IFLNK:
  1189. nchar = readlink(whole_path,
  1190. (char *)symlink_buff,
  1191. sizeof(symlink_buff));
  1192. symlink_buff[nchar < 0 ? 0 : nchar] = 0;
  1193. sprintf(buffer,"L\t%s\t%s\n",
  1194. s_entry->name, symlink_buff);
  1195. break;
  1196. #endif
  1197. #ifdef S_IFSOCK
  1198. case S_IFSOCK:
  1199. sprintf(buffer,"S\t%s\n",
  1200. s_entry->name);
  1201. break;
  1202. #endif
  1203. case S_IFREG:
  1204. default:
  1205. sprintf(buffer,"F\t%s\n",
  1206. s_entry->name);
  1207. break;
  1208. };
  1209. s_entry->table = strdup(buffer);
  1210. }
  1211. if(S_ISDIR(statbuf.st_mode))
  1212. {
  1213. int dflag;
  1214. if (strcmp(short_name,".") && strcmp(short_name,".."))
  1215. {
  1216. struct directory * child;
  1217. child = find_or_create_directory(this_dir, whole_path,
  1218. s_entry, 1);
  1219. dflag = scan_directory_tree(child, whole_path, s_entry);
  1220. if(!dflag)
  1221. {
  1222. lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG;
  1223. if( child->contents == NULL )
  1224. {
  1225. delete_directory(this_dir, child);
  1226. }
  1227. }
  1228. }
  1229. /* If unable to scan directory, mark this as a non-directory */
  1230. }
  1231. if(use_RockRidge && this_dir == root && strcmp(s_entry->name, ".") == 0)
  1232. {
  1233. deep_flag |= NEED_CE | NEED_SP; /* For extension record */
  1234. }
  1235. /* Now figure out how much room this file will take in the
  1236. directory */
  1237. if(use_RockRidge)
  1238. {
  1239. generate_rock_ridge_attributes(whole_path,
  1240. short_name, s_entry,
  1241. &statbuf, &lstatbuf, deep_flag);
  1242. }
  1243. return 1;
  1244. }
  1245. void FDECL2(generate_iso9660_directories, struct directory *, node, FILE*, outfile){
  1246. struct directory * dpnt;
  1247. dpnt = node;
  1248. while (dpnt){
  1249. if( dpnt->extent > session_start )
  1250. {
  1251. generate_one_directory(dpnt, outfile);
  1252. }
  1253. if(dpnt->subdir) generate_iso9660_directories(dpnt->subdir, outfile);
  1254. dpnt = dpnt->next;
  1255. }
  1256. }
  1257. /*
  1258. * Function: find_or_create_directory
  1259. *
  1260. * Purpose: Locate a directory entry in the tree, create if needed.
  1261. *
  1262. * Arguments:
  1263. */
  1264. struct directory * FDECL4(find_or_create_directory, struct directory *, parent,
  1265. const char *, path,
  1266. struct directory_entry *, de, int, flag)
  1267. {
  1268. struct directory * dpnt;
  1269. struct directory_entry * orig_de;
  1270. struct directory * next_brother;
  1271. const char * cpnt;
  1272. const char * pnt;
  1273. orig_de = de;
  1274. pnt = strrchr(path, PATH_SEPARATOR);
  1275. if( pnt == NULL )
  1276. {
  1277. pnt = path;
  1278. }
  1279. else
  1280. {
  1281. pnt++;
  1282. }
  1283. if( parent != NULL )
  1284. {
  1285. dpnt = parent->subdir;
  1286. while (dpnt)
  1287. {
  1288. /*
  1289. * Weird hack time - if there are two directories by the
  1290. * same name in the reloc_dir, they are not treated as the
  1291. * same thing unless the entire path matches completely.
  1292. */
  1293. if( flag && strcmp(dpnt->de_name, pnt) == 0 )
  1294. {
  1295. return dpnt;
  1296. }
  1297. dpnt = dpnt->next;
  1298. }
  1299. }
  1300. /*
  1301. * We don't know if we have a valid directory entry for this one
  1302. * yet. If not, we need to create one.
  1303. */
  1304. if( de == NULL )
  1305. {
  1306. de = (struct directory_entry *)
  1307. e_malloc(sizeof (struct directory_entry));
  1308. memset(de, 0, sizeof(struct directory_entry));
  1309. de->next = parent->contents;
  1310. parent->contents = de;
  1311. de->name = strdup(pnt);
  1312. de->filedir = parent;
  1313. de->isorec.flags[0] = 2;
  1314. de->priority = 32768;
  1315. de->inode = UNCACHED_INODE;
  1316. de->dev = (dev_t) UNCACHED_DEVICE;
  1317. set_723(de->isorec.volume_sequence_number, volume_sequence_number);
  1318. iso9660_file_length (pnt, de, 1);
  1319. init_fstatbuf();
  1320. /*
  1321. * It doesn't exist for real, so we cannot add any Rock Ridge.
  1322. */
  1323. if(use_RockRidge)
  1324. {
  1325. fstatbuf.st_mode = 0555 | S_IFDIR;
  1326. fstatbuf.st_nlink = 2;
  1327. generate_rock_ridge_attributes("",
  1328. (char *) pnt, de,
  1329. &fstatbuf,
  1330. &fstatbuf, 0);
  1331. }
  1332. iso9660_date(de->isorec.date, fstatbuf.st_mtime);
  1333. }
  1334. /*
  1335. * If we don't have a directory for this one yet, then allocate it
  1336. * now, and patch it into the tree in the appropriate place.
  1337. */
  1338. dpnt = (struct directory *) e_malloc(sizeof(struct directory));
  1339. memset(dpnt, 0, sizeof(struct directory));
  1340. dpnt->next = NULL;
  1341. dpnt->subdir = NULL;
  1342. dpnt->self = de;
  1343. dpnt->contents = NULL;
  1344. dpnt->whole_name = strdup(path);
  1345. cpnt = strrchr(path, PATH_SEPARATOR);
  1346. if(cpnt)
  1347. cpnt++;
  1348. else
  1349. cpnt = path;
  1350. dpnt->de_name = strdup(cpnt);
  1351. dpnt->size = 0;
  1352. dpnt->extent = 0;
  1353. dpnt->jextent = 0;
  1354. dpnt->jsize = 0;
  1355. if( orig_de == NULL )
  1356. {
  1357. struct stat xstatbuf;
  1358. int sts;
  1359. /*
  1360. * Now add a . and .. entry in the directory itself.
  1361. * This is a little tricky - if the real directory
  1362. * exists, we need to stat it first. Otherwise, we
  1363. * use the fictitious fstatbuf which points to the time
  1364. * at which mkisofs was started.
  1365. */
  1366. sts = stat_filter(parent->whole_name, &xstatbuf);
  1367. if( sts == 0 )
  1368. {
  1369. attach_dot_entries(dpnt, &xstatbuf);
  1370. }
  1371. else
  1372. {
  1373. attach_dot_entries(dpnt, &fstatbuf);
  1374. }
  1375. }
  1376. if(!parent || parent == root)
  1377. {
  1378. if (!root)
  1379. {
  1380. root = dpnt; /* First time through for root directory only */
  1381. root->depth = 0;
  1382. root->parent = root;
  1383. } else {
  1384. dpnt->depth = 1;
  1385. if(!root->subdir)
  1386. {
  1387. root->subdir = dpnt;
  1388. }
  1389. else
  1390. {
  1391. next_brother = root->subdir;
  1392. while(next_brother->next) next_brother = next_brother->next;
  1393. next_brother->next = dpnt;
  1394. }
  1395. dpnt->parent = parent;
  1396. }
  1397. }
  1398. else
  1399. {
  1400. /* Come through here for normal traversal of tree */
  1401. #ifdef DEBUG
  1402. fprintf(stderr,"%s(%d) ", path, dpnt->depth);
  1403. #endif
  1404. if(parent->depth > RR_relocation_depth)
  1405. error (1, 0, _("Directories too deep %s\n"), path);
  1406. dpnt->parent = parent;
  1407. dpnt->depth = parent->depth + 1;
  1408. if(!parent->subdir)
  1409. {
  1410. parent->subdir = dpnt;
  1411. }
  1412. else
  1413. {
  1414. next_brother = parent->subdir;
  1415. while(next_brother->next) next_brother = next_brother->next;
  1416. next_brother->next = dpnt;
  1417. }
  1418. }
  1419. return dpnt;
  1420. }
  1421. /*
  1422. * Function: delete_directory
  1423. *
  1424. * Purpose: Locate a directory entry in the tree, create if needed.
  1425. *
  1426. * Arguments:
  1427. */
  1428. static void FDECL2(delete_directory, struct directory *, parent, struct directory *, child)
  1429. {
  1430. struct directory * tdir;
  1431. if( child->contents != NULL )
  1432. error (1, 0, _("Unable to delete non-empty directory\n"));
  1433. free(child->whole_name);
  1434. child->whole_name = NULL;
  1435. free(child->de_name);
  1436. child->de_name = NULL;
  1437. if( parent->subdir == child )
  1438. {
  1439. parent->subdir = child->next;
  1440. }
  1441. else
  1442. {
  1443. for( tdir = parent->subdir; tdir->next != NULL; tdir = tdir->next )
  1444. {
  1445. if( tdir->next == child )
  1446. {
  1447. tdir->next = child->next;
  1448. break;
  1449. }
  1450. }
  1451. if( tdir == NULL )
  1452. error (1, 0, _("Unable to locate child directory in parent list\n"));
  1453. }
  1454. free(child);
  1455. return;
  1456. }
  1457. int FDECL1(sort_tree, struct directory *, node){
  1458. struct directory * dpnt;
  1459. int ret = 0;
  1460. dpnt = node;
  1461. while (dpnt){
  1462. ret = sort_n_finish(dpnt);
  1463. if( ret )
  1464. {
  1465. break;
  1466. }
  1467. if(dpnt->subdir) sort_tree(dpnt->subdir);
  1468. dpnt = dpnt->next;
  1469. }
  1470. return ret;
  1471. }
  1472. void FDECL1(dump_tree, struct directory *, node){
  1473. struct directory * dpnt;
  1474. dpnt = node;
  1475. while (dpnt){
  1476. fprintf(stderr,"%4d %5d %s\n",dpnt->extent, dpnt->size, dpnt->de_name);
  1477. if(dpnt->subdir) dump_tree(dpnt->subdir);
  1478. dpnt = dpnt->next;
  1479. }
  1480. }
  1481. void FDECL1(update_nlink_field, struct directory *, node)
  1482. {
  1483. struct directory * dpnt;
  1484. struct directory * xpnt;
  1485. struct directory_entry * s_entry;
  1486. int i;
  1487. dpnt = node;
  1488. while (dpnt)
  1489. {
  1490. if (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) {
  1491. dpnt = dpnt->next;
  1492. continue;
  1493. }
  1494. /*
  1495. * First, count up the number of subdirectories this guy has.
  1496. */
  1497. for(i=0, xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next)
  1498. if ((xpnt->dir_flags & INHIBIT_ISO9660_ENTRY) == 0)
  1499. i++;
  1500. /*
  1501. * Next check to see if we have any relocated directories
  1502. * in this directory. The nlink field will include these
  1503. * as real directories when they are properly relocated.
  1504. *
  1505. * In the non-rockridge disk, the relocated entries appear
  1506. * as zero length files.
  1507. */
  1508. for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next)
  1509. {
  1510. if( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0 &&
  1511. (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == 0)
  1512. {
  1513. i++;
  1514. }
  1515. }
  1516. /*
  1517. * Now update the field in the Rock Ridge entry.
  1518. */
  1519. update_nlink(dpnt->self, i + 2);
  1520. /*
  1521. * Update the '.' entry for this directory.
  1522. */
  1523. update_nlink(dpnt->contents, i + 2);
  1524. /*
  1525. * Update all of the '..' entries that point to this guy.
  1526. */
  1527. for(xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next)
  1528. update_nlink(xpnt->contents->next, i + 2);
  1529. if(dpnt->subdir) update_nlink_field(dpnt->subdir);
  1530. dpnt = dpnt->next;
  1531. }
  1532. }
  1533. /*
  1534. * something quick and dirty to locate a file given a path
  1535. * recursively walks down path in filename until it finds the
  1536. * directory entry for the desired file
  1537. */
  1538. struct directory_entry * FDECL2(search_tree_file, struct directory *,
  1539. node,char *, filename)
  1540. {
  1541. struct directory_entry * depnt;
  1542. struct directory * dpnt;
  1543. char * p1;
  1544. char * rest;
  1545. char * subdir;
  1546. /*
  1547. * strip off next directory name from filename
  1548. */
  1549. subdir = strdup(filename);
  1550. if( (p1=strchr(subdir, '/')) == subdir )
  1551. {
  1552. fprintf (stderr, _("call to search_tree_file with an absolute path, stripping\n"));
  1553. fprintf (stderr, _("initial path separator. Hope this was intended...\n"));
  1554. memmove(subdir, subdir+1, strlen(subdir)-1);
  1555. p1 = strchr(subdir, '/');
  1556. }
  1557. /*
  1558. * do we need to find a subdirectory
  1559. */
  1560. if (p1)
  1561. {
  1562. *p1 = '\0';
  1563. #ifdef DEBUG_TORITO
  1564. fprintf(stderr,"Looking for subdir called %s\n",p1);
  1565. #endif
  1566. rest = p1+1;
  1567. #ifdef DEBUG_TORITO
  1568. fprintf(stderr,"Remainder of path name is now %s\n", rest);
  1569. #endif
  1570. dpnt = node->subdir;
  1571. while( dpnt )
  1572. {
  1573. #ifdef DEBUG_TORITO
  1574. fprintf(stderr,"%4d %5d %s\n", dpnt->extent, dpnt->size,
  1575. dpnt->de_name);
  1576. #endif
  1577. if (!strcmp(subdir, dpnt->de_name))
  1578. {
  1579. #ifdef DEBUG_TORITO
  1580. fprintf(stderr,"Calling next level with filename = %s", rest);
  1581. #endif
  1582. return(search_tree_file( dpnt, rest ));
  1583. }
  1584. dpnt = dpnt->next;
  1585. }
  1586. /* if we got here means we couldnt find the subdir */
  1587. return (NULL);
  1588. }
  1589. else
  1590. {
  1591. /*
  1592. * look for a normal file now
  1593. */
  1594. depnt = node->contents;
  1595. while (depnt)
  1596. {
  1597. #ifdef DEBUG_TORITO
  1598. fprintf(stderr,"%4d %5d %s\n",depnt->isorec.extent,
  1599. depnt->size, depnt->name);
  1600. #endif
  1601. if (!strcmp(filename, depnt->name))
  1602. {
  1603. #ifdef DEBUG_TORITO
  1604. fprintf(stderr,"Found our file %s", filename);
  1605. #endif
  1606. return(depnt);
  1607. }
  1608. depnt = depnt->next;
  1609. }
  1610. /*
  1611. * if we got here means we couldnt find the subdir
  1612. */
  1613. return (NULL);
  1614. }
  1615. fprintf (stderr, "We cant get here in search_tree_file :-/ \n");
  1616. }
  1617. void init_fstatbuf()
  1618. {
  1619. time_t current_time;
  1620. if(fstatbuf.st_ctime == 0)
  1621. {
  1622. time (&current_time);
  1623. if( rationalize )
  1624. {
  1625. fstatbuf.st_uid = 0;
  1626. fstatbuf.st_gid = 0;
  1627. }
  1628. else
  1629. {
  1630. fstatbuf.st_uid = getuid();
  1631. fstatbuf.st_gid = getgid();
  1632. }
  1633. fstatbuf.st_ctime = current_time;
  1634. fstatbuf.st_mtime = current_time;
  1635. fstatbuf.st_atime = current_time;
  1636. }
  1637. }