cpio.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. /* Virtual File System: GNU Tar file system.
  2. Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
  3. Free Software Foundation, Inc.
  4. Written by: 2000 Jan Hudec
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public License
  7. as published by the Free Software Foundation; either version 2 of
  8. the License, or (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Library General Public License for more details.
  13. You should have received a copy of the GNU Library General Public
  14. License along with this program; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
  16. /** \file
  17. * \brief Source: Virtual File System: GNU Tar file system.
  18. * \author Jan Hudec
  19. * \date 2000
  20. */
  21. #include <config.h>
  22. #include <errno.h>
  23. #include <fcntl.h>
  24. #include "lib/global.h"
  25. #include "lib/unixcompat.h"
  26. #include "src/wtools.h" /* message() */
  27. #include "vfs-impl.h"
  28. #include "utilvfs.h"
  29. #include "xdirentry.h"
  30. #include "gc.h" /* vfs_rmstamp */
  31. /*** global variables ****************************************************************************/
  32. /*** file scope macro definitions ****************************************************************/
  33. #define CPIO_POS(super) cpio_position
  34. /* If some time reentrancy should be needed change it to */
  35. /* #define CPIO_POS(super) (super)->u.arch.fd */
  36. #define CPIO_SEEK_SET(super, where) mc_lseek((super)->u.arch.fd, CPIO_POS(super) = (where), SEEK_SET)
  37. #define CPIO_SEEK_CUR(super, where) mc_lseek((super)->u.arch.fd, CPIO_POS(super) += (where), SEEK_SET)
  38. #define MAGIC_LENGTH (6) /* How many bytes we have to read ahead */
  39. #define SEEKBACK CPIO_SEEK_CUR(super, ptr - top)
  40. #define RETURN(x) return(super->u.arch.type = (x))
  41. #define TYPEIS(x) ((super->u.arch.type == CPIO_UNKNOWN) || (super->u.arch.type == (x)))
  42. #define HEAD_LENGTH (26)
  43. /*** file scope type declarations ****************************************************************/
  44. enum
  45. {
  46. STATUS_START,
  47. STATUS_OK,
  48. STATUS_TRAIL,
  49. STATUS_FAIL,
  50. STATUS_EOF
  51. };
  52. enum
  53. {
  54. CPIO_UNKNOWN = 0, /* Not determined yet */
  55. CPIO_BIN, /* Binary format */
  56. CPIO_BINRE, /* Binary format, reverse endianity */
  57. CPIO_OLDC, /* Old ASCII format */
  58. CPIO_NEWC, /* New ASCII format */
  59. CPIO_CRC /* New ASCII format + CRC */
  60. };
  61. struct old_cpio_header
  62. {
  63. unsigned short c_magic;
  64. short c_dev;
  65. unsigned short c_ino;
  66. unsigned short c_mode;
  67. unsigned short c_uid;
  68. unsigned short c_gid;
  69. unsigned short c_nlink;
  70. short c_rdev;
  71. unsigned short c_mtimes[2];
  72. unsigned short c_namesize;
  73. unsigned short c_filesizes[2];
  74. };
  75. struct new_cpio_header
  76. {
  77. unsigned short c_magic;
  78. unsigned long c_ino;
  79. unsigned long c_mode;
  80. unsigned long c_uid;
  81. unsigned long c_gid;
  82. unsigned long c_nlink;
  83. unsigned long c_mtime;
  84. unsigned long c_filesize;
  85. long c_dev;
  86. long c_devmin;
  87. long c_rdev;
  88. long c_rdevmin;
  89. unsigned long c_namesize;
  90. unsigned long c_chksum;
  91. };
  92. struct defer_inode
  93. {
  94. struct defer_inode *next;
  95. unsigned long inumber;
  96. unsigned short device;
  97. struct vfs_s_inode *inode;
  98. };
  99. /*** file scope variables ************************************************************************/
  100. static struct vfs_class vfs_cpiofs_ops;
  101. /* FIXME: should be off_t instead of int. */
  102. static int cpio_position;
  103. /*** file scope functions ************************************************************************/
  104. /* --------------------------------------------------------------------------------------------- */
  105. static int cpio_find_head (struct vfs_class *me, struct vfs_s_super *super);
  106. static ssize_t cpio_read_bin_head (struct vfs_class *me, struct vfs_s_super *super);
  107. static ssize_t cpio_read_oldc_head (struct vfs_class *me, struct vfs_s_super *super);
  108. static ssize_t cpio_read_crc_head (struct vfs_class *me, struct vfs_s_super *super);
  109. static ssize_t cpio_read (void *fh, char *buffer, size_t count);
  110. /* --------------------------------------------------------------------------------------------- */
  111. static struct defer_inode *
  112. cpio_defer_find (struct defer_inode *l, struct defer_inode *i)
  113. {
  114. while (l && (l->inumber != i->inumber || l->device != i->device))
  115. l = l->next;
  116. return l;
  117. }
  118. /* --------------------------------------------------------------------------------------------- */
  119. static int
  120. cpio_skip_padding (struct vfs_s_super *super)
  121. {
  122. switch (super->u.arch.type)
  123. {
  124. case CPIO_BIN:
  125. case CPIO_BINRE:
  126. return CPIO_SEEK_CUR (super, (2 - (CPIO_POS (super) % 2)) % 2);
  127. case CPIO_NEWC:
  128. case CPIO_CRC:
  129. return CPIO_SEEK_CUR (super, (4 - (CPIO_POS (super) % 4)) % 4);
  130. case CPIO_OLDC:
  131. return CPIO_POS (super);
  132. default:
  133. g_assert_not_reached ();
  134. return 42; /* & the compiler is happy :-) */
  135. }
  136. }
  137. /* --------------------------------------------------------------------------------------------- */
  138. static void
  139. cpio_free_archive (struct vfs_class *me, struct vfs_s_super *super)
  140. {
  141. struct defer_inode *l, *lnext;
  142. (void) me;
  143. if (super->u.arch.fd != -1)
  144. mc_close (super->u.arch.fd);
  145. super->u.arch.fd = -1;
  146. for (l = super->u.arch.deferred; l; l = lnext)
  147. {
  148. lnext = l->next;
  149. g_free (l);
  150. }
  151. super->u.arch.deferred = NULL;
  152. }
  153. /* --------------------------------------------------------------------------------------------- */
  154. static int
  155. cpio_open_cpio_file (struct vfs_class *me, struct vfs_s_super *super, const char *name)
  156. {
  157. int fd, type;
  158. mode_t mode;
  159. struct vfs_s_inode *root;
  160. fd = mc_open (name, O_RDONLY);
  161. if (fd == -1)
  162. {
  163. message (D_ERROR, MSG_ERROR, _("Cannot open cpio archive\n%s"), name);
  164. return -1;
  165. }
  166. super->name = g_strdup (name);
  167. super->u.arch.fd = -1; /* for now */
  168. mc_stat (name, &(super->u.arch.st));
  169. super->u.arch.type = CPIO_UNKNOWN;
  170. type = get_compression_type (fd, name);
  171. if (type != COMPRESSION_NONE)
  172. {
  173. char *s;
  174. mc_close (fd);
  175. s = g_strconcat (name, decompress_extension (type), (char *) NULL);
  176. fd = mc_open (s, O_RDONLY);
  177. if (fd == -1)
  178. {
  179. message (D_ERROR, MSG_ERROR, _("Cannot open cpio archive\n%s"), s);
  180. g_free (s);
  181. return -1;
  182. }
  183. g_free (s);
  184. }
  185. super->u.arch.fd = fd;
  186. mode = super->u.arch.st.st_mode & 07777;
  187. mode |= (mode & 0444) >> 2; /* set eXec where Read is */
  188. mode |= S_IFDIR;
  189. root = vfs_s_new_inode (me, super, &(super->u.arch.st));
  190. root->st.st_mode = mode;
  191. root->data_offset = -1;
  192. root->st.st_nlink++;
  193. root->st.st_dev = MEDATA->rdev++;
  194. super->root = root;
  195. CPIO_SEEK_SET (super, 0);
  196. return fd;
  197. }
  198. /* --------------------------------------------------------------------------------------------- */
  199. static ssize_t
  200. cpio_read_head (struct vfs_class *me, struct vfs_s_super *super)
  201. {
  202. switch (cpio_find_head (me, super))
  203. {
  204. case CPIO_UNKNOWN:
  205. return -1;
  206. case CPIO_BIN:
  207. case CPIO_BINRE:
  208. return cpio_read_bin_head (me, super);
  209. case CPIO_OLDC:
  210. return cpio_read_oldc_head (me, super);
  211. case CPIO_NEWC:
  212. case CPIO_CRC:
  213. return cpio_read_crc_head (me, super);
  214. default:
  215. g_assert_not_reached ();
  216. return 42; /* & the compiler is happy :-) */
  217. }
  218. }
  219. /* --------------------------------------------------------------------------------------------- */
  220. static int
  221. cpio_find_head (struct vfs_class *me, struct vfs_s_super *super)
  222. {
  223. char buf[256];
  224. int ptr = 0;
  225. ssize_t top;
  226. ssize_t tmp;
  227. top = mc_read (super->u.arch.fd, buf, 256);
  228. if (top > 0)
  229. CPIO_POS (super) += top;
  230. for (;;)
  231. {
  232. if (ptr + MAGIC_LENGTH >= top)
  233. {
  234. if (top > 128)
  235. {
  236. memmove (buf, buf + top - 128, 128);
  237. ptr -= top - 128;
  238. top = 128;
  239. }
  240. tmp = mc_read (super->u.arch.fd, buf, top);
  241. if (tmp == 0 || tmp == -1)
  242. {
  243. message (D_ERROR, MSG_ERROR, _("Premature end of cpio archive\n%s"), super->name);
  244. cpio_free_archive (me, super);
  245. return CPIO_UNKNOWN;
  246. }
  247. top += tmp;
  248. }
  249. if (TYPEIS (CPIO_BIN) && ((*(unsigned short *) (buf + ptr)) == 070707))
  250. {
  251. SEEKBACK;
  252. RETURN (CPIO_BIN);
  253. }
  254. else if (TYPEIS (CPIO_BINRE)
  255. && ((*(unsigned short *) (buf + ptr)) == GUINT16_SWAP_LE_BE_CONSTANT (070707)))
  256. {
  257. SEEKBACK;
  258. RETURN (CPIO_BINRE);
  259. }
  260. else if (TYPEIS (CPIO_OLDC) && (!strncmp (buf + ptr, "070707", 6)))
  261. {
  262. SEEKBACK;
  263. RETURN (CPIO_OLDC);
  264. }
  265. else if (TYPEIS (CPIO_NEWC) && (!strncmp (buf + ptr, "070701", 6)))
  266. {
  267. SEEKBACK;
  268. RETURN (CPIO_NEWC);
  269. }
  270. else if (TYPEIS (CPIO_CRC) && (!strncmp (buf + ptr, "070702", 6)))
  271. {
  272. SEEKBACK;
  273. RETURN (CPIO_CRC);
  274. };
  275. ptr++;
  276. }
  277. }
  278. /* --------------------------------------------------------------------------------------------- */
  279. static int
  280. cpio_create_entry (struct vfs_class *me, struct vfs_s_super *super, struct stat *st, char *name)
  281. {
  282. struct vfs_s_inode *inode = NULL;
  283. struct vfs_s_inode *root = super->root;
  284. struct vfs_s_entry *entry = NULL;
  285. char *tn;
  286. switch (st->st_mode & S_IFMT)
  287. { /* For case of HP/UX archives */
  288. case S_IFCHR:
  289. case S_IFBLK:
  290. #ifdef S_IFSOCK
  291. case S_IFSOCK:
  292. #endif
  293. #ifdef S_IFIFO
  294. case S_IFIFO:
  295. #endif
  296. #ifdef S_IFNAM
  297. case S_IFNAM:
  298. #endif
  299. if ((st->st_size != 0) && (st->st_rdev == 0x0001))
  300. {
  301. /* FIXME: representation of major/minor differs between */
  302. /* different operating systems. */
  303. st->st_rdev = (unsigned) st->st_size;
  304. st->st_size = 0;
  305. }
  306. break;
  307. default:
  308. break;
  309. }
  310. if ((st->st_nlink > 1)
  311. && ((super->u.arch.type == CPIO_NEWC) || (super->u.arch.type == CPIO_CRC)))
  312. { /* For case of hardlinked files */
  313. struct defer_inode i, *l;
  314. i.inumber = st->st_ino;
  315. i.device = st->st_dev;
  316. i.inode = NULL;
  317. l = cpio_defer_find (super->u.arch.deferred, &i);
  318. if (l != NULL)
  319. {
  320. inode = l->inode;
  321. if (inode->st.st_size != 0 && st->st_size != 0 && (inode->st.st_size != st->st_size))
  322. {
  323. message (D_ERROR, MSG_ERROR,
  324. _("Inconsistent hardlinks of\n%s\nin cpio archive\n%s"),
  325. name, super->name);
  326. inode = NULL;
  327. }
  328. else if (inode->st.st_size == 0)
  329. inode->st.st_size = st->st_size;
  330. }
  331. }
  332. /* remove trailing slashes */
  333. for (tn = name + strlen (name) - 1; tn >= name && *tn == PATH_SEP; tn--)
  334. *tn = '\0';
  335. tn = strrchr (name, PATH_SEP);
  336. if (tn == NULL)
  337. tn = name;
  338. else if (tn == name + 1)
  339. {
  340. /* started with "./" -- directory in the root of archive */
  341. tn++;
  342. }
  343. else
  344. {
  345. *tn = '\0';
  346. root = vfs_s_find_inode (me, super, name, LINK_FOLLOW, FL_MKDIR);
  347. *tn = PATH_SEP;
  348. tn++;
  349. }
  350. entry = MEDATA->find_entry (me, root, tn, LINK_FOLLOW, FL_NONE); /* In case entry is already there */
  351. if (entry != NULL)
  352. {
  353. /* This shouldn't happen! (well, it can happen if there is a record for a
  354. file and than a record for a directory it is in; cpio would die with
  355. 'No such file or directory' is such case) */
  356. if (!S_ISDIR (entry->ino->st.st_mode))
  357. {
  358. /* This can be considered archive inconsistency */
  359. message (D_ERROR, MSG_ERROR,
  360. _("%s contains duplicate entries! Skipping!"), super->name);
  361. }
  362. else
  363. {
  364. entry->ino->st.st_mode = st->st_mode;
  365. entry->ino->st.st_uid = st->st_uid;
  366. entry->ino->st.st_gid = st->st_gid;
  367. entry->ino->st.st_atime = st->st_atime;
  368. entry->ino->st.st_mtime = st->st_mtime;
  369. entry->ino->st.st_ctime = st->st_ctime;
  370. }
  371. g_free (name);
  372. }
  373. else
  374. { /* !entry */
  375. if (inode == NULL)
  376. {
  377. inode = vfs_s_new_inode (me, super, st);
  378. if ((st->st_nlink > 0)
  379. && ((super->u.arch.type == CPIO_NEWC) || (super->u.arch.type == CPIO_CRC)))
  380. {
  381. /* For case of hardlinked files */
  382. struct defer_inode *i;
  383. i = g_new (struct defer_inode, 1);
  384. i->inumber = st->st_ino;
  385. i->device = st->st_dev;
  386. i->inode = inode;
  387. i->next = super->u.arch.deferred;
  388. super->u.arch.deferred = i;
  389. }
  390. }
  391. if (st->st_size != 0)
  392. inode->data_offset = CPIO_POS (super);
  393. entry = vfs_s_new_entry (me, tn, inode);
  394. vfs_s_insert_entry (me, root, entry);
  395. g_free (name);
  396. if (!S_ISLNK (st->st_mode))
  397. CPIO_SEEK_CUR (super, st->st_size);
  398. else
  399. {
  400. inode->linkname = g_malloc (st->st_size + 1);
  401. if (mc_read (super->u.arch.fd, inode->linkname, st->st_size) < st->st_size)
  402. {
  403. inode->linkname[0] = '\0';
  404. return STATUS_EOF;
  405. }
  406. inode->linkname[st->st_size] = '\0'; /* Linkname stored without terminating \0 !!! */
  407. CPIO_POS (super) += st->st_size;
  408. cpio_skip_padding (super);
  409. }
  410. } /* !entry */
  411. return STATUS_OK;
  412. }
  413. /* --------------------------------------------------------------------------------------------- */
  414. static ssize_t
  415. cpio_read_bin_head (struct vfs_class *me, struct vfs_s_super *super)
  416. {
  417. union
  418. {
  419. struct old_cpio_header buf;
  420. short shorts[HEAD_LENGTH >> 1];
  421. } u;
  422. ssize_t len;
  423. char *name;
  424. struct stat st;
  425. len = mc_read (super->u.arch.fd, (char *) &u.buf, HEAD_LENGTH);
  426. if (len < HEAD_LENGTH)
  427. return STATUS_EOF;
  428. CPIO_POS (super) += len;
  429. if (super->u.arch.type == CPIO_BINRE)
  430. {
  431. int i;
  432. for (i = 0; i < (HEAD_LENGTH >> 1); i++)
  433. u.shorts[i] = GUINT16_SWAP_LE_BE_CONSTANT (u.shorts[i]);
  434. }
  435. if (u.buf.c_magic != 070707 || u.buf.c_namesize == 0 || u.buf.c_namesize > MC_MAXPATHLEN)
  436. {
  437. message (D_ERROR, MSG_ERROR, _("Corrupted cpio header encountered in\n%s"), super->name);
  438. return STATUS_FAIL;
  439. }
  440. name = g_malloc (u.buf.c_namesize);
  441. len = mc_read (super->u.arch.fd, name, u.buf.c_namesize);
  442. if (len < u.buf.c_namesize)
  443. {
  444. g_free (name);
  445. return STATUS_EOF;
  446. }
  447. name[u.buf.c_namesize - 1] = '\0';
  448. CPIO_POS (super) += len;
  449. cpio_skip_padding (super);
  450. if (!strcmp ("TRAILER!!!", name))
  451. { /* We got to the last record */
  452. g_free (name);
  453. return STATUS_TRAIL;
  454. }
  455. st.st_dev = u.buf.c_dev;
  456. st.st_ino = u.buf.c_ino;
  457. st.st_mode = u.buf.c_mode;
  458. st.st_nlink = u.buf.c_nlink;
  459. st.st_uid = u.buf.c_uid;
  460. st.st_gid = u.buf.c_gid;
  461. st.st_rdev = u.buf.c_rdev;
  462. st.st_size = (u.buf.c_filesizes[0] << 16) | u.buf.c_filesizes[1];
  463. st.st_atime = st.st_mtime = st.st_ctime = (u.buf.c_mtimes[0] << 16) | u.buf.c_mtimes[1];
  464. return cpio_create_entry (me, super, &st, name);
  465. }
  466. /* --------------------------------------------------------------------------------------------- */
  467. #undef HEAD_LENGTH
  468. #define HEAD_LENGTH (76)
  469. static ssize_t
  470. cpio_read_oldc_head (struct vfs_class *me, struct vfs_s_super *super)
  471. {
  472. struct new_cpio_header hd;
  473. union
  474. {
  475. struct stat st;
  476. char buf[HEAD_LENGTH + 1];
  477. } u;
  478. ssize_t len;
  479. char *name;
  480. if (mc_read (super->u.arch.fd, u.buf, HEAD_LENGTH) != HEAD_LENGTH)
  481. return STATUS_EOF;
  482. CPIO_POS (super) += HEAD_LENGTH;
  483. u.buf[HEAD_LENGTH] = 0;
  484. if (sscanf (u.buf, "070707%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6lo%11lo",
  485. (unsigned long *) &hd.c_dev, &hd.c_ino, &hd.c_mode, &hd.c_uid, &hd.c_gid,
  486. &hd.c_nlink, (unsigned long *) &hd.c_rdev, &hd.c_mtime,
  487. &hd.c_namesize, &hd.c_filesize) < 10)
  488. {
  489. message (D_ERROR, MSG_ERROR, _("Corrupted cpio header encountered in\n%s"), super->name);
  490. return STATUS_FAIL;
  491. }
  492. if (hd.c_namesize == 0 || hd.c_namesize > MC_MAXPATHLEN)
  493. {
  494. message (D_ERROR, MSG_ERROR, _("Corrupted cpio header encountered in\n%s"), super->name);
  495. return STATUS_FAIL;
  496. }
  497. name = g_malloc (hd.c_namesize);
  498. len = mc_read (super->u.arch.fd, name, hd.c_namesize);
  499. if ((len == -1) || ((unsigned long) len < hd.c_namesize))
  500. {
  501. g_free (name);
  502. return STATUS_EOF;
  503. }
  504. name[hd.c_namesize - 1] = '\0';
  505. CPIO_POS (super) += len;
  506. cpio_skip_padding (super);
  507. if (!strcmp ("TRAILER!!!", name))
  508. { /* We got to the last record */
  509. g_free (name);
  510. return STATUS_TRAIL;
  511. }
  512. u.st.st_dev = hd.c_dev;
  513. u.st.st_ino = hd.c_ino;
  514. u.st.st_mode = hd.c_mode;
  515. u.st.st_nlink = hd.c_nlink;
  516. u.st.st_uid = hd.c_uid;
  517. u.st.st_gid = hd.c_gid;
  518. u.st.st_rdev = hd.c_rdev;
  519. u.st.st_size = hd.c_filesize;
  520. u.st.st_atime = u.st.st_mtime = u.st.st_ctime = hd.c_mtime;
  521. return cpio_create_entry (me, super, &u.st, name);
  522. }
  523. /* --------------------------------------------------------------------------------------------- */
  524. #undef HEAD_LENGTH
  525. #define HEAD_LENGTH (110)
  526. static ssize_t
  527. cpio_read_crc_head (struct vfs_class *me, struct vfs_s_super *super)
  528. {
  529. struct new_cpio_header hd;
  530. union
  531. {
  532. struct stat st;
  533. char buf[HEAD_LENGTH + 1];
  534. } u;
  535. ssize_t len;
  536. char *name;
  537. if (mc_read (super->u.arch.fd, u.buf, HEAD_LENGTH) != HEAD_LENGTH)
  538. return STATUS_EOF;
  539. CPIO_POS (super) += HEAD_LENGTH;
  540. u.buf[HEAD_LENGTH] = '\0';
  541. if (sscanf (u.buf, "%6ho%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx",
  542. &hd.c_magic, &hd.c_ino, &hd.c_mode, &hd.c_uid, &hd.c_gid,
  543. &hd.c_nlink, &hd.c_mtime, &hd.c_filesize,
  544. (unsigned long *) &hd.c_dev, (unsigned long *) &hd.c_devmin,
  545. (unsigned long *) &hd.c_rdev, (unsigned long *) &hd.c_rdevmin,
  546. &hd.c_namesize, &hd.c_chksum) < 14)
  547. {
  548. message (D_ERROR, MSG_ERROR, _("Corrupted cpio header encountered in\n%s"), super->name);
  549. return STATUS_FAIL;
  550. }
  551. if ((super->u.arch.type == CPIO_NEWC && hd.c_magic != 070701) ||
  552. (super->u.arch.type == CPIO_CRC && hd.c_magic != 070702))
  553. return STATUS_FAIL;
  554. if (hd.c_namesize == 0 || hd.c_namesize > MC_MAXPATHLEN)
  555. {
  556. message (D_ERROR, MSG_ERROR, _("Corrupted cpio header encountered in\n%s"), super->name);
  557. return STATUS_FAIL;
  558. }
  559. name = g_malloc (hd.c_namesize);
  560. len = mc_read (super->u.arch.fd, name, hd.c_namesize);
  561. if ((len == -1) || ((unsigned long) len < hd.c_namesize))
  562. {
  563. g_free (name);
  564. return STATUS_EOF;
  565. }
  566. name[hd.c_namesize - 1] = '\0';
  567. CPIO_POS (super) += len;
  568. cpio_skip_padding (super);
  569. if (strcmp ("TRAILER!!!", name) == 0)
  570. { /* We got to the last record */
  571. g_free (name);
  572. return STATUS_TRAIL;
  573. }
  574. u.st.st_dev = makedev (hd.c_dev, hd.c_devmin);
  575. u.st.st_ino = hd.c_ino;
  576. u.st.st_mode = hd.c_mode;
  577. u.st.st_nlink = hd.c_nlink;
  578. u.st.st_uid = hd.c_uid;
  579. u.st.st_gid = hd.c_gid;
  580. u.st.st_rdev = makedev (hd.c_rdev, hd.c_rdevmin);
  581. u.st.st_size = hd.c_filesize;
  582. u.st.st_atime = u.st.st_mtime = u.st.st_ctime = hd.c_mtime;
  583. return cpio_create_entry (me, super, &u.st, name);
  584. }
  585. /* --------------------------------------------------------------------------------------------- */
  586. /** Need to CPIO_SEEK_CUR to skip the file at the end of add entry!!!! */
  587. static int
  588. cpio_open_archive (struct vfs_class *me, struct vfs_s_super *super, const char *name, char *op)
  589. {
  590. int status = STATUS_START;
  591. (void) op;
  592. if (cpio_open_cpio_file (me, super, name) == -1)
  593. return -1;
  594. for (;;)
  595. {
  596. status = cpio_read_head (me, super);
  597. switch (status)
  598. {
  599. case STATUS_EOF:
  600. message (D_ERROR, MSG_ERROR, _("Unexpected end of file\n%s"), name);
  601. return 0;
  602. case STATUS_OK:
  603. continue;
  604. case STATUS_TRAIL:
  605. break;
  606. }
  607. break;
  608. }
  609. return 0;
  610. }
  611. /* --------------------------------------------------------------------------------------------- */
  612. /** Remaining functions are exactly same as for tarfs (and were in fact just copied) */
  613. static void *
  614. cpio_super_check (struct vfs_class *me, const char *archive_name, char *op)
  615. {
  616. static struct stat sb;
  617. (void) me;
  618. (void) op;
  619. if (mc_stat (archive_name, &sb))
  620. return NULL;
  621. return &sb;
  622. }
  623. /* --------------------------------------------------------------------------------------------- */
  624. static int
  625. cpio_super_same (struct vfs_class *me, struct vfs_s_super *parc,
  626. const char *archive_name, char *op, void *cookie)
  627. {
  628. struct stat *archive_stat = cookie; /* stat of main archive */
  629. (void) me;
  630. (void) op;
  631. if (strcmp (parc->name, archive_name))
  632. return 0;
  633. /* Has the cached archive been changed on the disk? */
  634. if (parc->u.arch.st.st_mtime < archive_stat->st_mtime)
  635. {
  636. /* Yes, reload! */
  637. (*vfs_cpiofs_ops.free) ((vfsid) parc);
  638. vfs_rmstamp (&vfs_cpiofs_ops, (vfsid) parc);
  639. return 2;
  640. }
  641. /* Hasn't been modified, give it a new timeout */
  642. vfs_stamp (&vfs_cpiofs_ops, (vfsid) parc);
  643. return 1;
  644. }
  645. /* --------------------------------------------------------------------------------------------- */
  646. static ssize_t
  647. cpio_read (void *fh, char *buffer, size_t count)
  648. {
  649. off_t begin = FH->ino->data_offset;
  650. int fd = FH_SUPER->u.arch.fd;
  651. struct vfs_class *me = FH_SUPER->me;
  652. ssize_t res;
  653. if (mc_lseek (fd, begin + FH->pos, SEEK_SET) != begin + FH->pos)
  654. ERRNOR (EIO, -1);
  655. count = MIN (count, (size_t) (FH->ino->st.st_size - FH->pos));
  656. res = mc_read (fd, buffer, count);
  657. if (res == -1)
  658. ERRNOR (errno, -1);
  659. FH->pos += res;
  660. return res;
  661. }
  662. /* --------------------------------------------------------------------------------------------- */
  663. static int
  664. cpio_fh_open (struct vfs_class *me, struct vfs_s_fh *fh, int flags, mode_t mode)
  665. {
  666. (void) fh;
  667. (void) mode;
  668. if ((flags & O_ACCMODE) != O_RDONLY)
  669. ERRNOR (EROFS, -1);
  670. return 0;
  671. }
  672. /* --------------------------------------------------------------------------------------------- */
  673. /*** public functions ****************************************************************************/
  674. /* --------------------------------------------------------------------------------------------- */
  675. void
  676. init_cpiofs (void)
  677. {
  678. static struct vfs_s_subclass cpio_subclass;
  679. cpio_subclass.flags = VFS_S_READONLY;
  680. cpio_subclass.archive_check = cpio_super_check;
  681. cpio_subclass.archive_same = cpio_super_same;
  682. cpio_subclass.open_archive = cpio_open_archive;
  683. cpio_subclass.free_archive = cpio_free_archive;
  684. cpio_subclass.fh_open = cpio_fh_open;
  685. vfs_s_init_class (&vfs_cpiofs_ops, &cpio_subclass);
  686. vfs_cpiofs_ops.name = "cpiofs";
  687. vfs_cpiofs_ops.prefix = "ucpio";
  688. vfs_cpiofs_ops.read = cpio_read;
  689. vfs_cpiofs_ops.setctl = NULL;
  690. vfs_register_class (&vfs_cpiofs_ops);
  691. }
  692. /* --------------------------------------------------------------------------------------------- */