direntry.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258
  1. /** \file
  2. * \brief Source: directory cache support
  3. *
  4. * So that you do not have copy of this in each and every filesystem.
  5. *
  6. * Very loosely based on tar.c from midnight and archives.[ch] from
  7. * avfs by Miklos Szeredi (mszeredi@inf.bme.hu)
  8. *
  9. * Unfortunately, I was unable to keep all filesystems
  10. * uniform. tar-like filesystems use tree structure where each
  11. * directory has pointers to its subdirectories. We can do this
  12. * because we have full information about our archive.
  13. *
  14. * At ftp-like filesystems, situation is a little bit different. When
  15. * you cd /usr/src/linux/drivers/char, you do _not_ want /usr,
  16. * /usr/src, /usr/src/linux and /usr/src/linux/drivers to be
  17. * listed. That means that we do not have complete information, and if
  18. * /usr is symlink to /4, we will not know. Also we have to time out
  19. * entries and things would get messy with tree-like approach. So we
  20. * do different trick: root directory is completely special and
  21. * completely fake, it contains entries such as 'usr', 'usr/src', ...,
  22. * and we'll try to use custom find_entry function.
  23. *
  24. * \author Pavel Machek <pavel@ucw.cz>, distribute under LGPL.
  25. * \date 1998
  26. *
  27. * \warning Paths here do _not_ begin with '/', so root directory of
  28. * archive/site is simply "".
  29. */
  30. #include <config.h>
  31. #include <errno.h>
  32. #include "../src/global.h"
  33. #include "../src/tty.h" /* enable/disable interrupt key */
  34. #include "../src/wtools.h" /* message() */
  35. #include "../src/main.h" /* print_vfs_message */
  36. #include "utilvfs.h"
  37. #include "vfs-impl.h"
  38. #include "gc.h" /* vfs_rmstamp */
  39. #include "xdirentry.h"
  40. #define CALL(x) if (MEDATA->x) MEDATA->x
  41. static volatile int total_inodes = 0, total_entries = 0;
  42. struct vfs_s_inode *
  43. vfs_s_new_inode (struct vfs_class *me, struct vfs_s_super *super, struct stat *initstat)
  44. {
  45. struct vfs_s_inode *ino;
  46. ino = g_new0 (struct vfs_s_inode, 1);
  47. if (!ino)
  48. return NULL;
  49. if (initstat)
  50. ino->st = *initstat;
  51. ino->super = super;
  52. ino->st.st_nlink = 0;
  53. ino->st.st_ino = MEDATA->inode_counter++;
  54. ino->st.st_dev = MEDATA->rdev;
  55. super->ino_usage++;
  56. total_inodes++;
  57. CALL (init_inode) (me, ino);
  58. return ino;
  59. }
  60. struct vfs_s_entry *
  61. vfs_s_new_entry (struct vfs_class *me, const char *name, struct vfs_s_inode *inode)
  62. {
  63. struct vfs_s_entry *entry;
  64. entry = g_new0 (struct vfs_s_entry, 1);
  65. total_entries++;
  66. if (name)
  67. entry->name = g_strdup (name);
  68. entry->ino = inode;
  69. entry->ino->ent = entry;
  70. CALL (init_entry) (me, entry);
  71. return entry;
  72. }
  73. static void
  74. vfs_s_free_inode (struct vfs_class *me, struct vfs_s_inode *ino)
  75. {
  76. if (!ino)
  77. vfs_die ("Don't pass NULL to me");
  78. /* ==0 can happen if freshly created entry is deleted */
  79. if (ino->st.st_nlink <= 1){
  80. while (ino->subdir){
  81. vfs_s_free_entry (me, ino->subdir);
  82. }
  83. CALL (free_inode) (me, ino);
  84. g_free (ino->linkname);
  85. if (ino->localname){
  86. unlink (ino->localname);
  87. g_free(ino->localname);
  88. }
  89. total_inodes--;
  90. ino->super->ino_usage--;
  91. g_free(ino);
  92. } else ino->st.st_nlink--;
  93. }
  94. void
  95. vfs_s_free_entry (struct vfs_class *me, struct vfs_s_entry *ent)
  96. {
  97. if (ent->prevp){ /* It is possible that we are deleting freshly created entry */
  98. *ent->prevp = ent->next;
  99. if (ent->next)
  100. ent->next->prevp = ent->prevp;
  101. }
  102. g_free (ent->name);
  103. ent->name = NULL;
  104. if (ent->ino){
  105. ent->ino->ent = NULL;
  106. vfs_s_free_inode (me, ent->ino);
  107. ent->ino = NULL;
  108. }
  109. total_entries--;
  110. g_free(ent);
  111. }
  112. void
  113. vfs_s_insert_entry (struct vfs_class *me, struct vfs_s_inode *dir, struct vfs_s_entry *ent)
  114. {
  115. struct vfs_s_entry **ep;
  116. (void) me;
  117. for (ep = &dir->subdir; *ep != NULL; ep = &((*ep)->next))
  118. ;
  119. ent->prevp = ep;
  120. ent->next = NULL;
  121. ent->dir = dir;
  122. *ep = ent;
  123. ent->ino->st.st_nlink++;
  124. }
  125. struct stat *
  126. vfs_s_default_stat (struct vfs_class *me, mode_t mode)
  127. {
  128. static struct stat st;
  129. int myumask;
  130. (void) me;
  131. myumask = umask (022);
  132. umask (myumask);
  133. mode &= ~myumask;
  134. st.st_mode = mode;
  135. st.st_ino = 0;
  136. st.st_dev = 0;
  137. st.st_rdev = 0;
  138. st.st_uid = getuid ();
  139. st.st_gid = getgid ();
  140. st.st_size = 0;
  141. st.st_mtime = st.st_atime = st.st_ctime = time (NULL);
  142. return &st;
  143. }
  144. struct vfs_s_entry *
  145. vfs_s_generate_entry (struct vfs_class *me, const char *name, struct vfs_s_inode *parent, mode_t mode)
  146. {
  147. struct vfs_s_inode *inode;
  148. struct stat *st;
  149. st = vfs_s_default_stat (me, mode);
  150. inode = vfs_s_new_inode (me, parent->super, st);
  151. return vfs_s_new_entry (me, name, inode);
  152. }
  153. /* We were asked to create entries automagically */
  154. static struct vfs_s_entry *
  155. vfs_s_automake (struct vfs_class *me, struct vfs_s_inode *dir, char *path, int flags)
  156. {
  157. struct vfs_s_entry *res;
  158. char *sep = strchr (path, PATH_SEP);
  159. if (sep)
  160. *sep = 0;
  161. res = vfs_s_generate_entry (me, path, dir, flags & FL_MKDIR ? (0777 | S_IFDIR) : 0777);
  162. vfs_s_insert_entry (me, dir, res);
  163. if (sep)
  164. *sep = PATH_SEP;
  165. return res;
  166. }
  167. /* If the entry is a symlink, find the entry for its target */
  168. static struct vfs_s_entry *
  169. vfs_s_resolve_symlink (struct vfs_class *me, struct vfs_s_entry *entry,
  170. int follow)
  171. {
  172. char *linkname;
  173. char *fullname = NULL;
  174. struct vfs_s_entry *target;
  175. if (follow == LINK_NO_FOLLOW)
  176. return entry;
  177. if (follow == 0)
  178. ERRNOR (ELOOP, NULL);
  179. if (!entry)
  180. ERRNOR (ENOENT, NULL);
  181. if (!S_ISLNK (entry->ino->st.st_mode))
  182. return entry;
  183. linkname = entry->ino->linkname;
  184. if (linkname == NULL)
  185. ERRNOR (EFAULT, NULL);
  186. /* make full path from relative */
  187. if (*linkname != PATH_SEP) {
  188. char *fullpath = vfs_s_fullpath (me, entry->dir);
  189. if (fullpath) {
  190. fullname = g_strconcat (fullpath, "/", linkname, NULL);
  191. linkname = fullname;
  192. g_free (fullpath);
  193. }
  194. }
  195. target =
  196. (MEDATA->find_entry) (me, entry->dir->super->root, linkname,
  197. follow - 1, 0);
  198. g_free (fullname);
  199. return target;
  200. }
  201. /*
  202. * Follow > 0: follow links, serves as loop protect,
  203. * == -1: do not follow links
  204. */
  205. static struct vfs_s_entry *
  206. vfs_s_find_entry_tree (struct vfs_class *me, struct vfs_s_inode *root,
  207. const char *a_path, int follow, int flags)
  208. {
  209. size_t pseg;
  210. struct vfs_s_entry *ent = NULL;
  211. char * const pathref = g_strdup (a_path);
  212. char *path = pathref;
  213. canonicalize_pathname (path);
  214. while (root) {
  215. while (*path == PATH_SEP) /* Strip leading '/' */
  216. path++;
  217. if (!path[0]) {
  218. g_free (pathref);
  219. return ent;
  220. }
  221. for (pseg = 0; path[pseg] && path[pseg] != PATH_SEP; pseg++);
  222. for (ent = root->subdir; ent != NULL; ent = ent->next)
  223. if (strlen (ent->name) == pseg
  224. && (!strncmp (ent->name, path, pseg)))
  225. /* FOUND! */
  226. break;
  227. if (!ent && (flags & (FL_MKFILE | FL_MKDIR)))
  228. ent = vfs_s_automake (me, root, path, flags);
  229. if (!ent) {
  230. me->verrno = ENOENT;
  231. goto cleanup;
  232. }
  233. path += pseg;
  234. /* here we must follow leading directories always;
  235. only the actual file is optional */
  236. ent =
  237. vfs_s_resolve_symlink (me, ent,
  238. strchr (path,
  239. PATH_SEP) ? LINK_FOLLOW :
  240. follow);
  241. if (!ent)
  242. goto cleanup;
  243. root = ent->ino;
  244. }
  245. cleanup:
  246. g_free (pathref);
  247. return NULL;
  248. }
  249. static void
  250. split_dir_name (struct vfs_class *me, char *path, char **dir, char **name, char **save)
  251. {
  252. char *s;
  253. (void) me;
  254. s = strrchr (path, PATH_SEP);
  255. if (s == NULL) {
  256. *save = NULL;
  257. *name = path;
  258. *dir = path + strlen(path); /* an empty string */
  259. } else {
  260. *save = s;
  261. *dir = path;
  262. *s++ = '\0';
  263. *name = s;
  264. }
  265. }
  266. static struct vfs_s_entry *
  267. vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root,
  268. const char *a_path, int follow, int flags)
  269. {
  270. struct vfs_s_entry *ent = NULL;
  271. char * const path = g_strdup (a_path);
  272. struct vfs_s_entry *retval = NULL;
  273. if (root->super->root != root)
  274. vfs_die ("We have to use _real_ root. Always. Sorry.");
  275. canonicalize_pathname (path);
  276. if (!(flags & FL_DIR)) {
  277. char *dirname, *name, *save;
  278. struct vfs_s_inode *ino;
  279. split_dir_name (me, path, &dirname, &name, &save);
  280. ino =
  281. vfs_s_find_inode (me, root->super, dirname, follow,
  282. flags | FL_DIR);
  283. if (save)
  284. *save = PATH_SEP;
  285. retval = vfs_s_find_entry_tree (me, ino, name, follow, flags);
  286. g_free (path);
  287. return retval;
  288. }
  289. for (ent = root->subdir; ent != NULL; ent = ent->next)
  290. if (!strcmp (ent->name, path))
  291. break;
  292. if (ent && (!(MEDATA->dir_uptodate) (me, ent->ino))) {
  293. #if 1
  294. print_vfs_message (_("Directory cache expired for %s"), path);
  295. #endif
  296. vfs_s_free_entry (me, ent);
  297. ent = NULL;
  298. }
  299. if (!ent) {
  300. struct vfs_s_inode *ino;
  301. ino =
  302. vfs_s_new_inode (me, root->super,
  303. vfs_s_default_stat (me, S_IFDIR | 0755));
  304. ent = vfs_s_new_entry (me, path, ino);
  305. if ((MEDATA->dir_load) (me, ino, path) == -1) {
  306. vfs_s_free_entry (me, ent);
  307. g_free (path);
  308. return NULL;
  309. }
  310. vfs_s_insert_entry (me, root, ent);
  311. for (ent = root->subdir; ent != NULL; ent = ent->next)
  312. if (!strcmp (ent->name, path))
  313. break;
  314. }
  315. if (!ent)
  316. vfs_die ("find_linear: success but directory is not there\n");
  317. #if 0
  318. if (!vfs_s_resolve_symlink (me, ent, follow)) {
  319. g_free (path);
  320. return NULL;
  321. }
  322. #endif
  323. g_free (path);
  324. return ent;
  325. }
  326. struct vfs_s_inode *
  327. vfs_s_find_inode (struct vfs_class *me, const struct vfs_s_super *super,
  328. const char *path, int follow, int flags)
  329. {
  330. struct vfs_s_entry *ent;
  331. if (!(MEDATA->flags & VFS_S_REMOTE) && (!*path))
  332. return super->root;
  333. ent = (MEDATA->find_entry) (me, super->root, path, follow, flags);
  334. if (!ent)
  335. return NULL;
  336. return ent->ino;
  337. }
  338. /* Ook, these were functions around directory entries / inodes */
  339. /* -------------------------------- superblock games -------------------------- */
  340. static struct vfs_s_super *
  341. vfs_s_new_super (struct vfs_class *me)
  342. {
  343. struct vfs_s_super *super;
  344. super = g_new0 (struct vfs_s_super, 1);
  345. super->me = me;
  346. return super;
  347. }
  348. static void
  349. vfs_s_insert_super (struct vfs_class *me, struct vfs_s_super *super)
  350. {
  351. super->next = MEDATA->supers;
  352. super->prevp = &MEDATA->supers;
  353. if (MEDATA->supers != NULL)
  354. MEDATA->supers->prevp = &super->next;
  355. MEDATA->supers = super;
  356. }
  357. static void
  358. vfs_s_free_super (struct vfs_class *me, struct vfs_s_super *super)
  359. {
  360. if (super->root){
  361. vfs_s_free_inode (me, super->root);
  362. super->root = NULL;
  363. }
  364. #if 0
  365. /* FIXME: We currently leak small ammount of memory, sometimes. Fix it if you can. */
  366. if (super->ino_usage)
  367. message (D_ERROR, " Direntry warning ",
  368. "Super ino_usage is %d, memory leak",
  369. super->ino_usage);
  370. if (super->want_stale)
  371. message (D_ERROR, " Direntry warning ", "Super has want_stale set");
  372. #endif
  373. if (super->prevp){
  374. *super->prevp = super->next;
  375. if (super->next)
  376. super->next->prevp = super->prevp;
  377. }
  378. CALL (free_archive) (me, super);
  379. g_free (super->name);
  380. g_free(super);
  381. }
  382. /*
  383. * Dissect the path and create corresponding superblock. Note that inname
  384. * can be changed and the result may point inside the original string.
  385. */
  386. const char *
  387. vfs_s_get_path_mangle (struct vfs_class *me, char *inname,
  388. struct vfs_s_super **archive, int flags)
  389. {
  390. const char *retval;
  391. char *local, *op;
  392. const char *archive_name;
  393. int result = -1;
  394. struct vfs_s_super *super;
  395. void *cookie = NULL;
  396. archive_name = inname;
  397. vfs_split (inname, &local, &op);
  398. retval = (local) ? local : "";
  399. if (MEDATA->archive_check)
  400. if (!(cookie = MEDATA->archive_check (me, archive_name, op)))
  401. return NULL;
  402. for (super = MEDATA->supers; super != NULL; super = super->next) {
  403. /* 0 == other, 1 == same, return it, 2 == other but stop scanning */
  404. int i;
  405. if ((i =
  406. MEDATA->archive_same (me, super, archive_name, op, cookie))) {
  407. if (i == 1)
  408. goto return_success;
  409. else
  410. break;
  411. }
  412. }
  413. if (flags & FL_NO_OPEN)
  414. ERRNOR (EIO, NULL);
  415. super = vfs_s_new_super (me);
  416. result = MEDATA->open_archive (me, super, archive_name, op);
  417. if (result == -1) {
  418. vfs_s_free_super (me, super);
  419. ERRNOR (EIO, NULL);
  420. }
  421. if (!super->name)
  422. vfs_die ("You have to fill name\n");
  423. if (!super->root)
  424. vfs_die ("You have to fill root inode\n");
  425. vfs_s_insert_super (me, super);
  426. vfs_stamp_create (me, super);
  427. return_success:
  428. *archive = super;
  429. return retval;
  430. }
  431. /*
  432. * Dissect the path and create corresponding superblock.
  433. * The result should be freed.
  434. */
  435. static char *
  436. vfs_s_get_path (struct vfs_class *me, const char *inname,
  437. struct vfs_s_super **archive, int flags)
  438. {
  439. char *buf, *retval;
  440. buf = g_strdup (inname);
  441. retval = g_strdup (vfs_s_get_path_mangle (me, buf, archive, flags));
  442. g_free (buf);
  443. return retval;
  444. }
  445. void
  446. vfs_s_invalidate (struct vfs_class *me, struct vfs_s_super *super)
  447. {
  448. if (!super->want_stale){
  449. vfs_s_free_inode (me, super->root);
  450. super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755));
  451. }
  452. }
  453. char *
  454. vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino)
  455. {
  456. if (!ino->ent)
  457. ERRNOR (EAGAIN, NULL);
  458. if (!(MEDATA->flags & VFS_S_REMOTE)) {
  459. /* archives */
  460. char *newpath;
  461. char *path = g_strdup (ino->ent->name);
  462. while (1) {
  463. ino = ino->ent->dir;
  464. if (ino == ino->super->root)
  465. break;
  466. newpath = g_strconcat (ino->ent->name, "/", path, (char *) NULL);
  467. g_free (path);
  468. path = newpath;
  469. }
  470. return path;
  471. }
  472. /* remote systems */
  473. if ((!ino->ent->dir) || (!ino->ent->dir->ent))
  474. return g_strdup (ino->ent->name);
  475. return g_strconcat (ino->ent->dir->ent->name, PATH_SEP_STR,
  476. ino->ent->name, (char *) NULL);
  477. }
  478. /* Support of archives */
  479. /* ------------------------ readdir & friends ----------------------------- */
  480. static struct vfs_s_inode *
  481. vfs_s_inode_from_path (struct vfs_class *me, const char *name, int flags)
  482. {
  483. struct vfs_s_super *super;
  484. struct vfs_s_inode *ino;
  485. char *q;
  486. if (!(q = vfs_s_get_path (me, name, &super, 0)))
  487. return NULL;
  488. ino =
  489. vfs_s_find_inode (me, super, q,
  490. flags & FL_FOLLOW ? LINK_FOLLOW : LINK_NO_FOLLOW,
  491. flags & ~FL_FOLLOW);
  492. if ((!ino) && (!*q))
  493. /* We are asking about / directory of ftp server: assume it exists */
  494. ino =
  495. vfs_s_find_inode (me, super, q,
  496. flags & FL_FOLLOW ? LINK_FOLLOW :
  497. LINK_NO_FOLLOW,
  498. FL_DIR | (flags & ~FL_FOLLOW));
  499. g_free (q);
  500. return ino;
  501. }
  502. struct dirhandle {
  503. struct vfs_s_entry *cur;
  504. struct vfs_s_inode *dir;
  505. };
  506. static void *
  507. vfs_s_opendir (struct vfs_class *me, const char *dirname)
  508. {
  509. struct vfs_s_inode *dir;
  510. struct dirhandle *info;
  511. dir = vfs_s_inode_from_path (me, dirname, FL_DIR | FL_FOLLOW);
  512. if (!dir)
  513. return NULL;
  514. if (!S_ISDIR (dir->st.st_mode))
  515. ERRNOR (ENOTDIR, NULL);
  516. dir->st.st_nlink++;
  517. #if 0
  518. if (!dir->subdir) /* This can actually happen if we allow empty directories */
  519. ERRNOR (EAGAIN, NULL);
  520. #endif
  521. info = g_new (struct dirhandle, 1);
  522. info->cur = dir->subdir;
  523. info->dir = dir;
  524. return info;
  525. }
  526. static void *
  527. vfs_s_readdir(void *data)
  528. {
  529. static union vfs_dirent dir;
  530. struct dirhandle *info = (struct dirhandle *) data;
  531. if (!(info->cur))
  532. return NULL;
  533. if (info->cur->name) {
  534. g_strlcpy (dir.dent.d_name, info->cur->name, MC_MAXPATHLEN);
  535. } else {
  536. vfs_die("Null in structure-cannot happen");
  537. }
  538. compute_namelen(&dir.dent);
  539. info->cur = info->cur->next;
  540. return (void *) &dir;
  541. }
  542. static int
  543. vfs_s_closedir (void *data)
  544. {
  545. struct dirhandle *info = (struct dirhandle *) data;
  546. struct vfs_s_inode *dir = info->dir;
  547. vfs_s_free_inode (dir->super->me, dir);
  548. g_free (data);
  549. return 0;
  550. }
  551. static int
  552. vfs_s_chdir (struct vfs_class *me, const char *path)
  553. {
  554. void *data;
  555. if (!(data = vfs_s_opendir (me, path)))
  556. return -1;
  557. vfs_s_closedir (data);
  558. return 0;
  559. }
  560. /* --------------------------- stat and friends ---------------------------- */
  561. static int
  562. vfs_s_internal_stat (struct vfs_class *me, const char *path, struct stat *buf, int flag)
  563. {
  564. struct vfs_s_inode *ino;
  565. if (!(ino = vfs_s_inode_from_path (me, path, flag)))
  566. return -1;
  567. *buf = ino->st;
  568. return 0;
  569. }
  570. static int
  571. vfs_s_stat (struct vfs_class *me, const char *path, struct stat *buf)
  572. {
  573. return vfs_s_internal_stat (me, path, buf, FL_FOLLOW);
  574. }
  575. static int
  576. vfs_s_lstat (struct vfs_class *me, const char *path, struct stat *buf)
  577. {
  578. return vfs_s_internal_stat (me, path, buf, FL_NONE);
  579. }
  580. static int
  581. vfs_s_fstat (void *fh, struct stat *buf)
  582. {
  583. *buf = FH->ino->st;
  584. return 0;
  585. }
  586. static int
  587. vfs_s_readlink (struct vfs_class *me, const char *path, char *buf, size_t size)
  588. {
  589. struct vfs_s_inode *ino;
  590. size_t len;
  591. ino = vfs_s_inode_from_path (me, path, 0);
  592. if (!ino)
  593. return -1;
  594. if (!S_ISLNK (ino->st.st_mode))
  595. ERRNOR (EINVAL, -1);
  596. if (ino->linkname == NULL)
  597. ERRNOR (EFAULT, -1);
  598. len = strlen (ino->linkname);
  599. if (size < len)
  600. len = size;
  601. /* readlink() does not append a NUL character to buf */
  602. memcpy (buf, ino->linkname, len);
  603. return len;
  604. }
  605. static void *
  606. vfs_s_open (struct vfs_class *me, const char *file, int flags, int mode)
  607. {
  608. int was_changed = 0;
  609. struct vfs_s_fh *fh;
  610. struct vfs_s_super *super;
  611. char *q;
  612. struct vfs_s_inode *ino;
  613. if ((q = vfs_s_get_path (me, file, &super, 0)) == NULL)
  614. return NULL;
  615. ino = vfs_s_find_inode (me, super, q, LINK_FOLLOW, FL_NONE);
  616. if (ino && ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))) {
  617. g_free (q);
  618. ERRNOR (EEXIST, NULL);
  619. }
  620. if (!ino) {
  621. char *dirname, *name, *save;
  622. struct vfs_s_entry *ent;
  623. struct vfs_s_inode *dir;
  624. int tmp_handle;
  625. /* If the filesystem is read-only, disable file creation */
  626. if (!(flags & O_CREAT) || !(me->write)) {
  627. g_free (q);
  628. return NULL;
  629. }
  630. split_dir_name (me, q, &dirname, &name, &save);
  631. /* FIXME: check if vfs_s_find_inode returns NULL */
  632. dir = vfs_s_find_inode (me, super, dirname, LINK_FOLLOW, FL_DIR);
  633. if (save)
  634. *save = PATH_SEP;
  635. ent = vfs_s_generate_entry (me, name, dir, 0755);
  636. ino = ent->ino;
  637. vfs_s_insert_entry (me, dir, ent);
  638. tmp_handle = vfs_mkstemps (&ino->localname, me->name, name);
  639. if (tmp_handle == -1) {
  640. g_free (q);
  641. return NULL;
  642. }
  643. close (tmp_handle);
  644. was_changed = 1;
  645. }
  646. g_free (q);
  647. if (S_ISDIR (ino->st.st_mode))
  648. ERRNOR (EISDIR, NULL);
  649. fh = g_new (struct vfs_s_fh, 1);
  650. fh->pos = 0;
  651. fh->ino = ino;
  652. fh->handle = -1;
  653. fh->changed = was_changed;
  654. fh->linear = 0;
  655. if (IS_LINEAR (flags)) {
  656. if (MEDATA->linear_start) {
  657. print_vfs_message (_("Starting linear transfer..."));
  658. fh->linear = LS_LINEAR_PREOPEN;
  659. }
  660. } else if ((MEDATA->fh_open)
  661. && (MEDATA->fh_open (me, fh, flags, mode))) {
  662. g_free (fh);
  663. return NULL;
  664. }
  665. if (fh->ino->localname) {
  666. fh->handle = open (fh->ino->localname, NO_LINEAR (flags), mode);
  667. if (fh->handle == -1) {
  668. g_free (fh);
  669. ERRNOR (errno, NULL);
  670. }
  671. }
  672. /* i.e. we had no open files and now we have one */
  673. vfs_rmstamp (me, (vfsid) super);
  674. super->fd_usage++;
  675. fh->ino->st.st_nlink++;
  676. return fh;
  677. }
  678. static ssize_t
  679. vfs_s_read (void *fh, char *buffer, int count)
  680. {
  681. int n;
  682. struct vfs_class *me = FH_SUPER->me;
  683. if (FH->linear == LS_LINEAR_PREOPEN) {
  684. if (!MEDATA->linear_start (me, FH, FH->pos))
  685. return -1;
  686. }
  687. if (FH->linear == LS_LINEAR_CLOSED)
  688. vfs_die ("linear_start() did not set linear_state!");
  689. if (FH->linear == LS_LINEAR_OPEN)
  690. return MEDATA->linear_read (me, FH, buffer, count);
  691. if (FH->handle != -1){
  692. n = read (FH->handle, buffer, count);
  693. if (n < 0)
  694. me->verrno = errno;
  695. return n;
  696. }
  697. vfs_die ("vfs_s_read: This should not happen\n");
  698. return -1;
  699. }
  700. static ssize_t
  701. vfs_s_write (void *fh, const char *buffer, int count)
  702. {
  703. int n;
  704. struct vfs_class *me = FH_SUPER->me;
  705. if (FH->linear)
  706. vfs_die ("no writing to linear files, please");
  707. FH->changed = 1;
  708. if (FH->handle != -1){
  709. n = write (FH->handle, buffer, count);
  710. if (n < 0)
  711. me->verrno = errno;
  712. return n;
  713. }
  714. vfs_die ("vfs_s_write: This should not happen\n");
  715. return 0;
  716. }
  717. static off_t
  718. vfs_s_lseek (void *fh, off_t offset, int whence)
  719. {
  720. off_t size = FH->ino->st.st_size;
  721. if (FH->linear == LS_LINEAR_OPEN)
  722. vfs_die ("cannot lseek() after linear_read!");
  723. if (FH->handle != -1){ /* If we have local file opened, we want to work with it */
  724. int retval = lseek (FH->handle, offset, whence);
  725. if (retval == -1)
  726. FH->ino->super->me->verrno = errno;
  727. return retval;
  728. }
  729. switch (whence){
  730. case SEEK_CUR:
  731. offset += FH->pos; break;
  732. case SEEK_END:
  733. offset += size; break;
  734. }
  735. if (offset < 0)
  736. FH->pos = 0;
  737. else if (offset < size)
  738. FH->pos = offset;
  739. else
  740. FH->pos = size;
  741. return FH->pos;
  742. }
  743. static int
  744. vfs_s_close (void *fh)
  745. {
  746. int res = 0;
  747. struct vfs_class *me = FH_SUPER->me;
  748. FH_SUPER->fd_usage--;
  749. if (!FH_SUPER->fd_usage)
  750. vfs_stamp_create (me, FH_SUPER);
  751. if (FH->linear == LS_LINEAR_OPEN)
  752. MEDATA->linear_close (me, fh);
  753. if (MEDATA->fh_close)
  754. res = MEDATA->fh_close (me, fh);
  755. if (FH->changed && MEDATA->file_store){
  756. char *s = vfs_s_fullpath (me, FH->ino);
  757. if (!s)
  758. res = -1;
  759. else {
  760. res = MEDATA->file_store (me, fh, s, FH->ino->localname);
  761. g_free (s);
  762. }
  763. vfs_s_invalidate (me, FH_SUPER);
  764. }
  765. if (FH->handle != -1)
  766. close (FH->handle);
  767. vfs_s_free_inode (me, FH->ino);
  768. g_free (fh);
  769. return res;
  770. }
  771. static void
  772. vfs_s_print_stats (const char *fs_name, const char *action,
  773. const char *file_name, off_t have, off_t need)
  774. {
  775. static const char *i18n_percent_transf_format = NULL;
  776. static const char *i18n_transf_format = NULL;
  777. if (i18n_percent_transf_format == NULL) {
  778. i18n_percent_transf_format =
  779. _("%s: %s: %s %3d%% (%lu bytes transferred)");
  780. i18n_transf_format = _("%s: %s: %s %lu bytes transferred");
  781. }
  782. if (need)
  783. print_vfs_message (i18n_percent_transf_format, fs_name, action,
  784. file_name, (int) ((double) have * 100 / need),
  785. (unsigned long) have);
  786. else
  787. print_vfs_message (i18n_transf_format, fs_name, action, file_name,
  788. (unsigned long) have);
  789. }
  790. int
  791. vfs_s_retrieve_file (struct vfs_class *me, struct vfs_s_inode *ino)
  792. {
  793. /* If you want reget, you'll have to open file with O_LINEAR */
  794. off_t total = 0;
  795. char buffer[8192];
  796. int handle, n;
  797. off_t stat_size = ino->st.st_size;
  798. struct vfs_s_fh fh;
  799. memset (&fh, 0, sizeof (fh));
  800. fh.ino = ino;
  801. fh.handle = -1;
  802. handle = vfs_mkstemps (&ino->localname, me->name, ino->ent->name);
  803. if (handle == -1) {
  804. me->verrno = errno;
  805. goto error_4;
  806. }
  807. if (!MEDATA->linear_start (me, &fh, 0))
  808. goto error_3;
  809. /* Clear the interrupt status */
  810. got_interrupt ();
  811. enable_interrupt_key ();
  812. while ((n = MEDATA->linear_read (me, &fh, buffer, sizeof (buffer)))) {
  813. int t;
  814. if (n < 0)
  815. goto error_1;
  816. total += n;
  817. vfs_s_print_stats (me->name, _("Getting file"), ino->ent->name,
  818. total, stat_size);
  819. if (got_interrupt ())
  820. goto error_1;
  821. t = write (handle, buffer, n);
  822. if (t != n) {
  823. if (t == -1)
  824. me->verrno = errno;
  825. goto error_1;
  826. }
  827. }
  828. MEDATA->linear_close (me, &fh);
  829. close (handle);
  830. disable_interrupt_key ();
  831. return 0;
  832. error_1:
  833. MEDATA->linear_close (me, &fh);
  834. error_3:
  835. disable_interrupt_key ();
  836. close (handle);
  837. unlink (ino->localname);
  838. error_4:
  839. g_free (ino->localname);
  840. ino->localname = NULL;
  841. return -1;
  842. }
  843. /* ------------------------------- mc support ---------------------------- */
  844. static void
  845. vfs_s_fill_names (struct vfs_class *me, fill_names_f func)
  846. {
  847. struct vfs_s_super *a = MEDATA->supers;
  848. char *name;
  849. while (a){
  850. name = g_strconcat ( a->name, "#", me->prefix, "/", /* a->current_dir->name, */ NULL);
  851. (*func)(name);
  852. g_free (name);
  853. a = a->next;
  854. }
  855. }
  856. static int
  857. vfs_s_ferrno (struct vfs_class *me)
  858. {
  859. return me->verrno;
  860. }
  861. /*
  862. * Get local copy of the given file. We reuse the existing file cache
  863. * for remote filesystems. Archives use standard VFS facilities.
  864. */
  865. static char *
  866. vfs_s_getlocalcopy (struct vfs_class *me, const char *path)
  867. {
  868. struct vfs_s_fh *fh;
  869. char *local;
  870. fh = vfs_s_open (me, path, O_RDONLY, 0);
  871. if (!fh || !fh->ino || !fh->ino->localname)
  872. return NULL;
  873. local = g_strdup (fh->ino->localname);
  874. vfs_s_close (fh);
  875. return local;
  876. }
  877. /*
  878. * Return the local copy. Since we are using our cache, we do nothing -
  879. * the cache will be removed when the archive is closed.
  880. */
  881. static int
  882. vfs_s_ungetlocalcopy (struct vfs_class *me, const char *path,
  883. const char *local, int has_changed)
  884. {
  885. (void) me;
  886. (void) path;
  887. (void) local;
  888. (void) has_changed;
  889. return 0;
  890. }
  891. static int
  892. vfs_s_setctl (struct vfs_class *me, const char *path, int ctlop, void *arg)
  893. {
  894. switch (ctlop) {
  895. case VFS_SETCTL_STALE_DATA:
  896. {
  897. struct vfs_s_inode *ino = vfs_s_inode_from_path (me, path, 0);
  898. if (!ino)
  899. return 0;
  900. if (arg)
  901. ino->super->want_stale = 1;
  902. else {
  903. ino->super->want_stale = 0;
  904. vfs_s_invalidate (me, ino->super);
  905. }
  906. return 1;
  907. }
  908. case VFS_SETCTL_LOGFILE:
  909. MEDATA->logfile = fopen ((char *) arg, "w");
  910. return 1;
  911. case VFS_SETCTL_FLUSH:
  912. MEDATA->flush = 1;
  913. return 1;
  914. }
  915. return 0;
  916. }
  917. /* ----------------------------- Stamping support -------------------------- */
  918. static vfsid
  919. vfs_s_getid (struct vfs_class *me, const char *path)
  920. {
  921. struct vfs_s_super *archive;
  922. char *p;
  923. if (!(p = vfs_s_get_path (me, path, &archive, FL_NO_OPEN)))
  924. return NULL;
  925. g_free(p);
  926. return (vfsid) archive;
  927. }
  928. static int
  929. vfs_s_nothingisopen (vfsid id)
  930. {
  931. (void) id;
  932. /* Our data structures should survive free of superblock at any time */
  933. return 1;
  934. }
  935. static void
  936. vfs_s_free (vfsid id)
  937. {
  938. vfs_s_free_super (((struct vfs_s_super *)id)->me, (struct vfs_s_super *)id);
  939. }
  940. static int
  941. vfs_s_dir_uptodate (struct vfs_class *me, struct vfs_s_inode *ino)
  942. {
  943. struct timeval tim;
  944. if (MEDATA->flush) {
  945. MEDATA->flush = 0;
  946. return 0;
  947. }
  948. gettimeofday(&tim, NULL);
  949. if (tim.tv_sec < ino->timestamp.tv_sec)
  950. return 1;
  951. return 0;
  952. }
  953. /* Initialize one of our subclasses - fill common functions */
  954. void
  955. vfs_s_init_class (struct vfs_class *vclass, struct vfs_s_subclass *sub)
  956. {
  957. vclass->data = sub;
  958. vclass->fill_names = vfs_s_fill_names;
  959. vclass->open = vfs_s_open;
  960. vclass->close = vfs_s_close;
  961. vclass->read = vfs_s_read;
  962. if (!(sub->flags & VFS_S_READONLY)) {
  963. vclass->write = vfs_s_write;
  964. }
  965. vclass->opendir = vfs_s_opendir;
  966. vclass->readdir = vfs_s_readdir;
  967. vclass->closedir = vfs_s_closedir;
  968. vclass->stat = vfs_s_stat;
  969. vclass->lstat = vfs_s_lstat;
  970. vclass->fstat = vfs_s_fstat;
  971. vclass->readlink = vfs_s_readlink;
  972. vclass->chdir = vfs_s_chdir;
  973. vclass->ferrno = vfs_s_ferrno;
  974. vclass->lseek = vfs_s_lseek;
  975. vclass->getid = vfs_s_getid;
  976. vclass->nothingisopen = vfs_s_nothingisopen;
  977. vclass->free = vfs_s_free;
  978. if (sub->flags & VFS_S_REMOTE) {
  979. vclass->getlocalcopy = vfs_s_getlocalcopy;
  980. vclass->ungetlocalcopy = vfs_s_ungetlocalcopy;
  981. sub->find_entry = vfs_s_find_entry_linear;
  982. } else {
  983. sub->find_entry = vfs_s_find_entry_tree;
  984. }
  985. vclass->setctl = vfs_s_setctl;
  986. sub->dir_uptodate = vfs_s_dir_uptodate;
  987. }
  988. /* ----------- Utility functions for networked filesystems -------------- */
  989. #ifdef USE_NETCODE
  990. int
  991. vfs_s_select_on_two (int fd1, int fd2)
  992. {
  993. fd_set set;
  994. struct timeval timeout;
  995. int v;
  996. int maxfd = (fd1 > fd2 ? fd1 : fd2) + 1;
  997. timeout.tv_sec = 1;
  998. timeout.tv_usec = 0;
  999. FD_ZERO (&set);
  1000. FD_SET (fd1, &set);
  1001. FD_SET (fd2, &set);
  1002. v = select (maxfd, &set, 0, 0, &timeout);
  1003. if (v <= 0)
  1004. return v;
  1005. if (FD_ISSET (fd1, &set))
  1006. return 1;
  1007. if (FD_ISSET (fd2, &set))
  1008. return 2;
  1009. return -1;
  1010. }
  1011. int
  1012. vfs_s_get_line (struct vfs_class *me, int sock, char *buf, int buf_len, char term)
  1013. {
  1014. FILE *logfile = MEDATA->logfile;
  1015. int i;
  1016. char c;
  1017. for (i = 0; i < buf_len - 1; i++, buf++){
  1018. if (read (sock, buf, sizeof(char)) <= 0)
  1019. return 0;
  1020. if (logfile){
  1021. fwrite (buf, 1, 1, logfile);
  1022. fflush (logfile);
  1023. }
  1024. if (*buf == term){
  1025. *buf = 0;
  1026. return 1;
  1027. }
  1028. }
  1029. /* Line is too long - terminate buffer and discard the rest of line */
  1030. *buf = 0;
  1031. while (read (sock, &c, sizeof (c)) > 0) {
  1032. if (logfile){
  1033. fwrite (&c, 1, 1, logfile);
  1034. fflush (logfile);
  1035. }
  1036. if (c == '\n')
  1037. return 1;
  1038. }
  1039. return 0;
  1040. }
  1041. int
  1042. vfs_s_get_line_interruptible (struct vfs_class *me, char *buffer, int size, int fd)
  1043. {
  1044. int n;
  1045. int i;
  1046. (void) me;
  1047. enable_interrupt_key ();
  1048. for (i = 0; i < size-1; i++){
  1049. n = read (fd, buffer+i, 1);
  1050. disable_interrupt_key ();
  1051. if (n == -1 && errno == EINTR){
  1052. buffer [i] = 0;
  1053. return EINTR;
  1054. }
  1055. if (n == 0){
  1056. buffer [i] = 0;
  1057. return 0;
  1058. }
  1059. if (buffer [i] == '\n'){
  1060. buffer [i] = 0;
  1061. return 1;
  1062. }
  1063. }
  1064. buffer [size-1] = 0;
  1065. return 0;
  1066. }
  1067. #endif /* USE_NETCODE */