direntry.c 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706
  1. /*
  2. Directory cache support
  3. Copyright (C) 1998, 2011, 2013
  4. The Free Software Foundation, Inc.
  5. Written by:
  6. Pavel Machek <pavel@ucw.cz>, 1998
  7. Slava Zanko <slavazanko@gmail.com>, 2013
  8. This file is part of the Midnight Commander.
  9. The Midnight Commander is free software: you can redistribute it
  10. and/or modify it under the terms of the GNU General Public License as
  11. published by the Free Software Foundation, either version 3 of the License,
  12. or (at your option) any later version.
  13. The Midnight Commander is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. GNU General Public License for more details.
  17. You should have received a copy of the GNU General Public License
  18. along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. \warning Paths here do _not_ begin with '/', so root directory of
  20. archive/site is simply "".
  21. */
  22. /** \file
  23. * \brief Source: directory cache support
  24. *
  25. * So that you do not have copy of this in each and every filesystem.
  26. *
  27. * Very loosely based on tar.c from midnight and archives.[ch] from
  28. * avfs by Miklos Szeredi (mszeredi@inf.bme.hu)
  29. *
  30. * Unfortunately, I was unable to keep all filesystems
  31. * uniform. tar-like filesystems use tree structure where each
  32. * directory has pointers to its subdirectories. We can do this
  33. * because we have full information about our archive.
  34. *
  35. * At ftp-like filesystems, situation is a little bit different. When
  36. * you cd /usr/src/linux/drivers/char, you do _not_ want /usr,
  37. * /usr/src, /usr/src/linux and /usr/src/linux/drivers to be
  38. * listed. That means that we do not have complete information, and if
  39. * /usr is symlink to /4, we will not know. Also we have to time out
  40. * entries and things would get messy with tree-like approach. So we
  41. * do different trick: root directory is completely special and
  42. * completely fake, it contains entries such as 'usr', 'usr/src', ...,
  43. * and we'll try to use custom find_entry function.
  44. *
  45. * \author Pavel Machek <pavel@ucw.cz>
  46. * \date 1998
  47. *
  48. */
  49. #include <config.h>
  50. #include <errno.h>
  51. #include <fcntl.h> /* include fcntl.h -> sys/fcntl.h only */
  52. /* includes fcntl.h see IEEE Std 1003.1-2008 */
  53. #include <time.h>
  54. #include <sys/time.h> /* gettimeofday() */
  55. #include <inttypes.h> /* uintmax_t */
  56. #include <stdarg.h>
  57. #include "lib/global.h"
  58. #include "lib/tty/tty.h" /* enable/disable interrupt key */
  59. #include "lib/util.h" /* custom_canonicalize_pathname() */
  60. #if 0
  61. #include "lib/widget.h" /* message() */
  62. #endif
  63. #include "vfs.h"
  64. #include "utilvfs.h"
  65. #include "xdirentry.h"
  66. #include "gc.h" /* vfs_rmstamp */
  67. /*** global variables ****************************************************************************/
  68. /*** file scope macro definitions ****************************************************************/
  69. #define CALL(x) if (MEDATA->x) MEDATA->x
  70. /*** file scope type declarations ****************************************************************/
  71. struct dirhandle
  72. {
  73. GList *cur;
  74. struct vfs_s_inode *dir;
  75. };
  76. typedef struct
  77. {
  78. vfs_path_t *vpath_archive;
  79. const vfs_path_element_t *path_element;
  80. void *cookie;
  81. } vfs_get_by_vpath_data_t;
  82. /*** file scope variables ************************************************************************/
  83. static volatile int total_inodes = 0, total_entries = 0;
  84. /*** file scope functions ************************************************************************/
  85. /* --------------------------------------------------------------------------------------------- */
  86. static int
  87. vfs_s_entry_compare (const void *a, const void *b)
  88. {
  89. const struct vfs_s_entry *e = (const struct vfs_s_entry *) a;
  90. const char *name = (const char *) b;
  91. return strcmp (e->name, name);
  92. }
  93. /* --------------------------------------------------------------------------------------------- */
  94. /* We were asked to create entries automagically */
  95. static struct vfs_s_entry *
  96. vfs_s_automake (struct vfs_class *me, struct vfs_s_inode *dir, char *path, int flags)
  97. {
  98. struct vfs_s_entry *res;
  99. char *sep;
  100. sep = strchr (path, PATH_SEP);
  101. if (sep != NULL)
  102. *sep = '\0';
  103. res = vfs_s_generate_entry (me, path, dir, flags & FL_MKDIR ? (0777 | S_IFDIR) : 0777);
  104. vfs_s_insert_entry (me, dir, res);
  105. if (sep != NULL)
  106. *sep = PATH_SEP;
  107. return res;
  108. }
  109. /* --------------------------------------------------------------------------------------------- */
  110. /* If the entry is a symlink, find the entry for its target */
  111. static struct vfs_s_entry *
  112. vfs_s_resolve_symlink (struct vfs_class *me, struct vfs_s_entry *entry, int follow)
  113. {
  114. char *linkname;
  115. char *fullname = NULL;
  116. struct vfs_s_entry *target;
  117. if (follow == LINK_NO_FOLLOW)
  118. return entry;
  119. if (follow == 0)
  120. ERRNOR (ELOOP, NULL);
  121. if (!entry)
  122. ERRNOR (ENOENT, NULL);
  123. if (!S_ISLNK (entry->ino->st.st_mode))
  124. return entry;
  125. linkname = entry->ino->linkname;
  126. if (linkname == NULL)
  127. ERRNOR (EFAULT, NULL);
  128. /* make full path from relative */
  129. if (*linkname != PATH_SEP)
  130. {
  131. char *fullpath = vfs_s_fullpath (me, entry->dir);
  132. if (fullpath)
  133. {
  134. fullname = g_strconcat (fullpath, "/", linkname, (char *) NULL);
  135. linkname = fullname;
  136. g_free (fullpath);
  137. }
  138. }
  139. target = (MEDATA->find_entry) (me, entry->dir->super->root, linkname, follow - 1, 0);
  140. g_free (fullname);
  141. return target;
  142. }
  143. /* --------------------------------------------------------------------------------------------- */
  144. /*
  145. * Follow > 0: follow links, serves as loop protect,
  146. * == -1: do not follow links
  147. */
  148. static struct vfs_s_entry *
  149. vfs_s_find_entry_tree (struct vfs_class *me, struct vfs_s_inode *root,
  150. const char *a_path, int follow, int flags)
  151. {
  152. size_t pseg;
  153. struct vfs_s_entry *ent = NULL;
  154. char *const pathref = g_strdup (a_path);
  155. char *path = pathref;
  156. /* canonicalize as well, but don't remove '../' from path */
  157. custom_canonicalize_pathname (path, CANON_PATH_ALL & (~CANON_PATH_REMDOUBLEDOTS));
  158. while (root != NULL)
  159. {
  160. GList *iter;
  161. while (*path == PATH_SEP) /* Strip leading '/' */
  162. path++;
  163. if (path[0] == '\0')
  164. {
  165. g_free (pathref);
  166. return ent;
  167. }
  168. for (pseg = 0; path[pseg] != '\0' && path[pseg] != PATH_SEP; pseg++)
  169. ;
  170. for (iter = root->subdir; iter != NULL; iter = g_list_next (iter))
  171. {
  172. ent = (struct vfs_s_entry *) iter->data;
  173. if (strlen (ent->name) == pseg && strncmp (ent->name, path, pseg) == 0)
  174. /* FOUND! */
  175. break;
  176. }
  177. ent = iter != NULL ? (struct vfs_s_entry *) iter->data : NULL;
  178. if (ent == NULL && (flags & (FL_MKFILE | FL_MKDIR)) != 0)
  179. ent = vfs_s_automake (me, root, path, flags);
  180. if (ent == NULL)
  181. {
  182. me->verrno = ENOENT;
  183. goto cleanup;
  184. }
  185. path += pseg;
  186. /* here we must follow leading directories always;
  187. only the actual file is optional */
  188. ent = vfs_s_resolve_symlink (me, ent,
  189. strchr (path, PATH_SEP) != NULL ? LINK_FOLLOW : follow);
  190. if (ent == NULL)
  191. goto cleanup;
  192. root = ent->ino;
  193. }
  194. cleanup:
  195. g_free (pathref);
  196. return NULL;
  197. }
  198. /* --------------------------------------------------------------------------------------------- */
  199. static struct vfs_s_entry *
  200. vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root,
  201. const char *a_path, int follow, int flags)
  202. {
  203. struct vfs_s_entry *ent = NULL;
  204. char *const path = g_strdup (a_path);
  205. GList *iter;
  206. if (root->super->root != root)
  207. vfs_die ("We have to use _real_ root. Always. Sorry.");
  208. /* canonicalize as well, but don't remove '../' from path */
  209. custom_canonicalize_pathname (path, CANON_PATH_ALL & (~CANON_PATH_REMDOUBLEDOTS));
  210. if ((flags & FL_DIR) == 0)
  211. {
  212. char *dirname, *name;
  213. struct vfs_s_inode *ino;
  214. dirname = g_path_get_dirname (path);
  215. name = g_path_get_basename (path);
  216. ino = vfs_s_find_inode (me, root->super, dirname, follow, flags | FL_DIR);
  217. ent = vfs_s_find_entry_tree (me, ino, name, follow, flags);
  218. g_free (dirname);
  219. g_free (name);
  220. g_free (path);
  221. return ent;
  222. }
  223. iter = g_list_find_custom (root->subdir, path, (GCompareFunc) vfs_s_entry_compare);
  224. ent = iter != NULL ? (struct vfs_s_entry *) iter->data : NULL;
  225. if (ent != NULL && !MEDATA->dir_uptodate (me, ent->ino))
  226. {
  227. #if 1
  228. vfs_print_message (_("Directory cache expired for %s"), path);
  229. #endif
  230. vfs_s_free_entry (me, ent);
  231. ent = NULL;
  232. }
  233. if (ent == NULL)
  234. {
  235. struct vfs_s_inode *ino;
  236. ino = vfs_s_new_inode (me, root->super, vfs_s_default_stat (me, S_IFDIR | 0755));
  237. ent = vfs_s_new_entry (me, path, ino);
  238. if (MEDATA->dir_load (me, ino, path) == -1)
  239. {
  240. vfs_s_free_entry (me, ent);
  241. g_free (path);
  242. return NULL;
  243. }
  244. vfs_s_insert_entry (me, root, ent);
  245. iter = g_list_find_custom (root->subdir, path, (GCompareFunc) vfs_s_entry_compare);
  246. ent = iter != NULL ? (struct vfs_s_entry *) iter->data : NULL;
  247. }
  248. if (ent == NULL)
  249. vfs_die ("find_linear: success but directory is not there\n");
  250. #if 0
  251. if (!vfs_s_resolve_symlink (me, ent, follow))
  252. {
  253. g_free (path);
  254. return NULL;
  255. }
  256. #endif
  257. g_free (path);
  258. return ent;
  259. }
  260. /* --------------------------------------------------------------------------------------------- */
  261. /* Ook, these were functions around directory entries / inodes */
  262. /* -------------------------------- superblock games -------------------------- */
  263. static struct vfs_s_super *
  264. vfs_s_new_super (struct vfs_class *me)
  265. {
  266. struct vfs_s_super *super;
  267. super = g_new0 (struct vfs_s_super, 1);
  268. super->me = me;
  269. return super;
  270. }
  271. /* --------------------------------------------------------------------------------------------- */
  272. static inline void
  273. vfs_s_insert_super (struct vfs_class *me, struct vfs_s_super *super)
  274. {
  275. MEDATA->supers = g_list_prepend (MEDATA->supers, super);
  276. }
  277. /* --------------------------------------------------------------------------------------------- */
  278. static void
  279. vfs_s_free_super (struct vfs_class *me, struct vfs_s_super *super)
  280. {
  281. if (super->root != NULL)
  282. {
  283. vfs_s_free_inode (me, super->root);
  284. super->root = NULL;
  285. }
  286. #if 0
  287. /* FIXME: We currently leak small ammount of memory, sometimes. Fix it if you can. */
  288. if (super->ino_usage)
  289. message (D_ERROR, "Direntry warning",
  290. "Super ino_usage is %d, memory leak", super->ino_usage);
  291. if (super->want_stale)
  292. message (D_ERROR, "Direntry warning", "%s", "Super has want_stale set");
  293. #endif
  294. MEDATA->supers = g_list_remove (MEDATA->supers, super);
  295. CALL (free_archive) (me, super);
  296. #ifdef ENABLE_VFS_NET
  297. vfs_path_element_free (super->path_element);
  298. #endif
  299. g_free (super->name);
  300. g_free (super);
  301. }
  302. /* --------------------------------------------------------------------------------------------- */
  303. /* Support of archives */
  304. /* ------------------------ readdir & friends ----------------------------- */
  305. static struct vfs_s_inode *
  306. vfs_s_inode_from_path (const vfs_path_t * vpath, int flags)
  307. {
  308. struct vfs_s_super *super;
  309. struct vfs_s_inode *ino;
  310. const vfs_path_element_t *path_element;
  311. super = vfs_get_super_by_vpath (vpath, TRUE);
  312. if (super == NULL)
  313. return NULL;
  314. path_element = vfs_path_get_by_index (vpath, -1);
  315. ino =
  316. vfs_s_find_inode (path_element->class, super, path_element->path,
  317. flags & FL_FOLLOW ? LINK_FOLLOW : LINK_NO_FOLLOW, flags & ~FL_FOLLOW);
  318. if ((!ino) && (!*path_element->path))
  319. /* We are asking about / directory of ftp server: assume it exists */
  320. ino =
  321. vfs_s_find_inode (path_element->class, super, path_element->path,
  322. flags & FL_FOLLOW ? LINK_FOLLOW :
  323. LINK_NO_FOLLOW, FL_DIR | (flags & ~FL_FOLLOW));
  324. return ino;
  325. }
  326. /* --------------------------------------------------------------------------------------------- */
  327. static void *
  328. vfs_s_opendir (const vfs_path_t * vpath)
  329. {
  330. struct vfs_s_inode *dir;
  331. struct dirhandle *info;
  332. const vfs_path_element_t *path_element;
  333. path_element = vfs_path_get_by_index (vpath, -1);
  334. dir = vfs_s_inode_from_path (vpath, FL_DIR | FL_FOLLOW);
  335. if (dir == NULL)
  336. return NULL;
  337. if (!S_ISDIR (dir->st.st_mode))
  338. {
  339. path_element->class->verrno = ENOTDIR;
  340. return NULL;
  341. }
  342. dir->st.st_nlink++;
  343. #if 0
  344. if (dir->subdir == NULL) /* This can actually happen if we allow empty directories */
  345. {
  346. path_element->class->verrno = EAGAIN;
  347. return NULL;
  348. }
  349. #endif
  350. info = g_new (struct dirhandle, 1);
  351. info->cur = dir->subdir;
  352. info->dir = dir;
  353. return info;
  354. }
  355. /* --------------------------------------------------------------------------------------------- */
  356. static void *
  357. vfs_s_readdir (void *data)
  358. {
  359. static union vfs_dirent dir;
  360. struct dirhandle *info = (struct dirhandle *) data;
  361. const char *name;
  362. if (info->cur == NULL || info->cur->data == NULL)
  363. return NULL;
  364. name = ((struct vfs_s_entry *) info->cur->data)->name;
  365. if (name != NULL)
  366. g_strlcpy (dir.dent.d_name, name, MC_MAXPATHLEN);
  367. else
  368. vfs_die ("Null in structure-cannot happen");
  369. compute_namelen (&dir.dent);
  370. info->cur = g_list_next (info->cur);
  371. return (void *) &dir;
  372. }
  373. /* --------------------------------------------------------------------------------------------- */
  374. static int
  375. vfs_s_closedir (void *data)
  376. {
  377. struct dirhandle *info = (struct dirhandle *) data;
  378. struct vfs_s_inode *dir = info->dir;
  379. vfs_s_free_inode (dir->super->me, dir);
  380. g_free (data);
  381. return 0;
  382. }
  383. /* --------------------------------------------------------------------------------------------- */
  384. static int
  385. vfs_s_chdir (const vfs_path_t * vpath)
  386. {
  387. void *data;
  388. data = vfs_s_opendir (vpath);
  389. if (data == NULL)
  390. return -1;
  391. vfs_s_closedir (data);
  392. return 0;
  393. }
  394. /* --------------------------------------------------------------------------------------------- */
  395. /* --------------------------- stat and friends ---------------------------- */
  396. static int
  397. vfs_s_internal_stat (const vfs_path_t * vpath, struct stat *buf, int flag)
  398. {
  399. struct vfs_s_inode *ino;
  400. ino = vfs_s_inode_from_path (vpath, flag);
  401. if (ino == NULL)
  402. return -1;
  403. *buf = ino->st;
  404. return 0;
  405. }
  406. /* --------------------------------------------------------------------------------------------- */
  407. static int
  408. vfs_s_stat (const vfs_path_t * vpath, struct stat *buf)
  409. {
  410. return vfs_s_internal_stat (vpath, buf, FL_FOLLOW);
  411. }
  412. /* --------------------------------------------------------------------------------------------- */
  413. static int
  414. vfs_s_lstat (const vfs_path_t * vpath, struct stat *buf)
  415. {
  416. return vfs_s_internal_stat (vpath, buf, FL_NONE);
  417. }
  418. /* --------------------------------------------------------------------------------------------- */
  419. static int
  420. vfs_s_fstat (void *fh, struct stat *buf)
  421. {
  422. *buf = FH->ino->st;
  423. return 0;
  424. }
  425. /* --------------------------------------------------------------------------------------------- */
  426. static int
  427. vfs_s_readlink (const vfs_path_t * vpath, char *buf, size_t size)
  428. {
  429. struct vfs_s_inode *ino;
  430. size_t len;
  431. const vfs_path_element_t *path_element;
  432. path_element = vfs_path_get_by_index (vpath, -1);
  433. ino = vfs_s_inode_from_path (vpath, 0);
  434. if (!ino)
  435. return -1;
  436. if (!S_ISLNK (ino->st.st_mode))
  437. {
  438. path_element->class->verrno = EINVAL;
  439. return -1;
  440. }
  441. if (ino->linkname == NULL)
  442. {
  443. path_element->class->verrno = EFAULT;
  444. return -1;
  445. }
  446. len = strlen (ino->linkname);
  447. if (size < len)
  448. len = size;
  449. /* readlink() does not append a NUL character to buf */
  450. memcpy (buf, ino->linkname, len);
  451. return len;
  452. }
  453. /* --------------------------------------------------------------------------------------------- */
  454. static ssize_t
  455. vfs_s_read (void *fh, char *buffer, size_t count)
  456. {
  457. struct vfs_class *me = FH_SUPER->me;
  458. if (FH->linear == LS_LINEAR_PREOPEN)
  459. {
  460. if (!MEDATA->linear_start (me, FH, FH->pos))
  461. return -1;
  462. }
  463. if (FH->linear == LS_LINEAR_CLOSED)
  464. vfs_die ("linear_start() did not set linear_state!");
  465. if (FH->linear == LS_LINEAR_OPEN)
  466. return MEDATA->linear_read (me, FH, buffer, count);
  467. if (FH->handle != -1)
  468. {
  469. ssize_t n;
  470. n = read (FH->handle, buffer, count);
  471. if (n < 0)
  472. me->verrno = errno;
  473. return n;
  474. }
  475. vfs_die ("vfs_s_read: This should not happen\n");
  476. return -1;
  477. }
  478. /* --------------------------------------------------------------------------------------------- */
  479. static ssize_t
  480. vfs_s_write (void *fh, const char *buffer, size_t count)
  481. {
  482. struct vfs_class *me = FH_SUPER->me;
  483. if (FH->linear)
  484. vfs_die ("no writing to linear files, please");
  485. FH->changed = 1;
  486. if (FH->handle != -1)
  487. {
  488. ssize_t n;
  489. n = write (FH->handle, buffer, count);
  490. if (n < 0)
  491. me->verrno = errno;
  492. return n;
  493. }
  494. vfs_die ("vfs_s_write: This should not happen\n");
  495. return 0;
  496. }
  497. /* --------------------------------------------------------------------------------------------- */
  498. static off_t
  499. vfs_s_lseek (void *fh, off_t offset, int whence)
  500. {
  501. off_t size = FH->ino->st.st_size;
  502. if (FH->linear == LS_LINEAR_OPEN)
  503. vfs_die ("cannot lseek() after linear_read!");
  504. if (FH->handle != -1)
  505. { /* If we have local file opened, we want to work with it */
  506. off_t retval = lseek (FH->handle, offset, whence);
  507. if (retval == -1)
  508. FH->ino->super->me->verrno = errno;
  509. return retval;
  510. }
  511. switch (whence)
  512. {
  513. case SEEK_CUR:
  514. offset += FH->pos;
  515. break;
  516. case SEEK_END:
  517. offset += size;
  518. break;
  519. }
  520. if (offset < 0)
  521. FH->pos = 0;
  522. else if (offset < size)
  523. FH->pos = offset;
  524. else
  525. FH->pos = size;
  526. return FH->pos;
  527. }
  528. /* --------------------------------------------------------------------------------------------- */
  529. static int
  530. vfs_s_close (void *fh)
  531. {
  532. int res = 0;
  533. struct vfs_class *me = FH_SUPER->me;
  534. FH_SUPER->fd_usage--;
  535. if (!FH_SUPER->fd_usage)
  536. vfs_stamp_create (me, FH_SUPER);
  537. if (FH->linear == LS_LINEAR_OPEN)
  538. MEDATA->linear_close (me, fh);
  539. if (MEDATA->fh_close)
  540. res = MEDATA->fh_close (me, fh);
  541. if ((MEDATA->flags & VFS_S_USETMP) && FH->changed && MEDATA->file_store)
  542. {
  543. char *s = vfs_s_fullpath (me, FH->ino);
  544. if (!s)
  545. res = -1;
  546. else
  547. {
  548. res = MEDATA->file_store (me, fh, s, FH->ino->localname);
  549. g_free (s);
  550. }
  551. vfs_s_invalidate (me, FH_SUPER);
  552. }
  553. if (FH->handle != -1)
  554. close (FH->handle);
  555. vfs_s_free_inode (me, FH->ino);
  556. if (MEDATA->fh_free_data != NULL)
  557. MEDATA->fh_free_data (fh);
  558. g_free (fh);
  559. return res;
  560. }
  561. /* --------------------------------------------------------------------------------------------- */
  562. static void
  563. vfs_s_print_stats (const char *fs_name, const char *action,
  564. const char *file_name, off_t have, off_t need)
  565. {
  566. static const char *i18n_percent_transf_format = NULL;
  567. static const char *i18n_transf_format = NULL;
  568. if (i18n_percent_transf_format == NULL)
  569. {
  570. i18n_percent_transf_format = "%s: %s: %s %3d%% (%" PRIuMAX " %s";
  571. i18n_transf_format = "%s: %s: %s %" PRIuMAX " %s";
  572. }
  573. if (need)
  574. vfs_print_message (i18n_percent_transf_format, fs_name, action,
  575. file_name, (int) ((double) have * 100 / need), (uintmax_t) have,
  576. _("bytes transferred"));
  577. else
  578. vfs_print_message (i18n_transf_format, fs_name, action, file_name, (uintmax_t) have,
  579. _("bytes transferred"));
  580. }
  581. /* --------------------------------------------------------------------------------------------- */
  582. /* ------------------------------- mc support ---------------------------- */
  583. static void
  584. vfs_s_fill_names (struct vfs_class *me, fill_names_f func)
  585. {
  586. GList *iter;
  587. for (iter = MEDATA->supers; iter != NULL; iter = g_list_next (iter))
  588. {
  589. const struct vfs_s_super *super = (const struct vfs_s_super *) iter->data;
  590. char *name;
  591. name = g_strconcat (super->name, "/", me->prefix, VFS_PATH_URL_DELIMITER,
  592. /* super->current_dir->name, */ (char *) NULL);
  593. func (name);
  594. g_free (name);
  595. }
  596. }
  597. /* --------------------------------------------------------------------------------------------- */
  598. static int
  599. vfs_s_ferrno (struct vfs_class *me)
  600. {
  601. return me->verrno;
  602. }
  603. /* --------------------------------------------------------------------------------------------- */
  604. /**
  605. * Get local copy of the given file. We reuse the existing file cache
  606. * for remote filesystems. Archives use standard VFS facilities.
  607. */
  608. static vfs_path_t *
  609. vfs_s_getlocalcopy (const vfs_path_t * vpath)
  610. {
  611. vfs_file_handler_t *fh;
  612. vfs_path_t *local = NULL;
  613. if (vpath == NULL)
  614. return NULL;
  615. fh = vfs_s_open (vpath, O_RDONLY, 0);
  616. if (fh != NULL)
  617. {
  618. const struct vfs_class *me;
  619. me = vfs_path_get_by_index (vpath, -1)->class;
  620. if ((MEDATA->flags & VFS_S_USETMP) != 0 && (fh->ino != NULL))
  621. local = vfs_path_from_str_flags (fh->ino->localname, VPF_NO_CANON);
  622. vfs_s_close (fh);
  623. }
  624. return local;
  625. }
  626. /* --------------------------------------------------------------------------------------------- */
  627. /**
  628. * Return the local copy. Since we are using our cache, we do nothing -
  629. * the cache will be removed when the archive is closed.
  630. */
  631. static int
  632. vfs_s_ungetlocalcopy (const vfs_path_t * vpath, const vfs_path_t * local, gboolean has_changed)
  633. {
  634. (void) vpath;
  635. (void) local;
  636. (void) has_changed;
  637. return 0;
  638. }
  639. /* --------------------------------------------------------------------------------------------- */
  640. static int
  641. vfs_s_setctl (const vfs_path_t * vpath, int ctlop, void *arg)
  642. {
  643. const vfs_path_element_t *path_element;
  644. path_element = vfs_path_get_by_index (vpath, -1);
  645. switch (ctlop)
  646. {
  647. case VFS_SETCTL_STALE_DATA:
  648. {
  649. struct vfs_s_inode *ino;
  650. ino = vfs_s_inode_from_path (vpath, 0);
  651. if (ino == NULL)
  652. return 0;
  653. if (arg)
  654. ino->super->want_stale = 1;
  655. else
  656. {
  657. ino->super->want_stale = 0;
  658. vfs_s_invalidate (path_element->class, ino->super);
  659. }
  660. return 1;
  661. }
  662. case VFS_SETCTL_LOGFILE:
  663. ((struct vfs_s_subclass *) path_element->class->data)->logfile = fopen ((char *) arg, "w");
  664. return 1;
  665. case VFS_SETCTL_FLUSH:
  666. ((struct vfs_s_subclass *) path_element->class->data)->flush = 1;
  667. return 1;
  668. }
  669. return 0;
  670. }
  671. /* --------------------------------------------------------------------------------------------- */
  672. /* ----------------------------- Stamping support -------------------------- */
  673. static vfsid
  674. vfs_s_getid (const vfs_path_t * vpath)
  675. {
  676. return (vfsid) vfs_get_super_by_vpath (vpath, FALSE);
  677. }
  678. /* --------------------------------------------------------------------------------------------- */
  679. static int
  680. vfs_s_nothingisopen (vfsid id)
  681. {
  682. (void) id;
  683. /* Our data structures should survive free of superblock at any time */
  684. return 1;
  685. }
  686. /* --------------------------------------------------------------------------------------------- */
  687. static void
  688. vfs_s_free (vfsid id)
  689. {
  690. vfs_s_free_super (((struct vfs_s_super *) id)->me, (struct vfs_s_super *) id);
  691. }
  692. /* --------------------------------------------------------------------------------------------- */
  693. static int
  694. vfs_s_dir_uptodate (struct vfs_class *me, struct vfs_s_inode *ino)
  695. {
  696. struct timeval tim;
  697. if (MEDATA->flush)
  698. {
  699. MEDATA->flush = 0;
  700. return 0;
  701. }
  702. gettimeofday (&tim, NULL);
  703. if (tim.tv_sec < ino->timestamp.tv_sec)
  704. return 1;
  705. return 0;
  706. }
  707. /* --------------------------------------------------------------------------------------------- */
  708. /**
  709. * Callback for search superblock via subclass->archive_same() call
  710. *
  711. * @param me class for search superblocks
  712. * @param cb_data some data for callback
  713. * @param super superblock for comparsion
  714. * @return TRUE if superblock is what we need, FALSE otherwise
  715. */
  716. static gboolean
  717. vfs_cb_archive_same (struct vfs_class *me, void *cb_data, struct vfs_s_super *super)
  718. {
  719. vfs_get_by_vpath_data_t *vfs_get_by_vpath_data;
  720. struct vfs_s_subclass *subclass;
  721. int ret;
  722. vfs_get_by_vpath_data = (vfs_get_by_vpath_data_t *) cb_data;
  723. subclass = (struct vfs_s_subclass *) me->data;
  724. ret = subclass->archive_same (vfs_get_by_vpath_data->path_element, super,
  725. vfs_get_by_vpath_data->vpath_archive,
  726. vfs_get_by_vpath_data->cookie);
  727. return (ret != 0);
  728. }
  729. /* --------------------------------------------------------------------------------------------- */
  730. /*** public functions ****************************************************************************/
  731. /* --------------------------------------------------------------------------------------------- */
  732. struct vfs_s_inode *
  733. vfs_s_new_inode (struct vfs_class *me, struct vfs_s_super *super, struct stat *initstat)
  734. {
  735. struct vfs_s_inode *ino;
  736. ino = g_try_new0 (struct vfs_s_inode, 1);
  737. if (ino == NULL)
  738. return NULL;
  739. if (initstat)
  740. ino->st = *initstat;
  741. ino->super = super;
  742. ino->st.st_nlink = 0;
  743. ino->st.st_ino = MEDATA->inode_counter++;
  744. ino->st.st_dev = MEDATA->rdev;
  745. super->ino_usage++;
  746. total_inodes++;
  747. CALL (init_inode) (me, ino);
  748. return ino;
  749. }
  750. /* --------------------------------------------------------------------------------------------- */
  751. void
  752. vfs_s_free_inode (struct vfs_class *me, struct vfs_s_inode *ino)
  753. {
  754. if (ino == NULL)
  755. vfs_die ("Don't pass NULL to me");
  756. /* ==0 can happen if freshly created entry is deleted */
  757. if (ino->st.st_nlink > 1)
  758. {
  759. ino->st.st_nlink--;
  760. return;
  761. }
  762. while (ino->subdir != NULL)
  763. vfs_s_free_entry (me, (struct vfs_s_entry *) ino->subdir->data);
  764. CALL (free_inode) (me, ino);
  765. g_free (ino->linkname);
  766. if ((MEDATA->flags & VFS_S_USETMP) != 0 && ino->localname != NULL)
  767. {
  768. unlink (ino->localname);
  769. g_free (ino->localname);
  770. }
  771. total_inodes--;
  772. ino->super->ino_usage--;
  773. g_free (ino);
  774. }
  775. /* --------------------------------------------------------------------------------------------- */
  776. struct vfs_s_entry *
  777. vfs_s_new_entry (struct vfs_class *me, const char *name, struct vfs_s_inode *inode)
  778. {
  779. struct vfs_s_entry *entry;
  780. entry = g_new0 (struct vfs_s_entry, 1);
  781. total_entries++;
  782. entry->name = g_strdup (name);
  783. entry->ino = inode;
  784. entry->ino->ent = entry;
  785. CALL (init_entry) (me, entry);
  786. return entry;
  787. }
  788. /* --------------------------------------------------------------------------------------------- */
  789. void
  790. vfs_s_free_entry (struct vfs_class *me, struct vfs_s_entry *ent)
  791. {
  792. if (ent->dir != NULL)
  793. ent->dir->subdir = g_list_remove (ent->dir->subdir, ent);
  794. g_free (ent->name);
  795. /* ent->name = NULL; */
  796. if (ent->ino != NULL)
  797. {
  798. ent->ino->ent = NULL;
  799. vfs_s_free_inode (me, ent->ino);
  800. }
  801. total_entries--;
  802. g_free (ent);
  803. }
  804. /* --------------------------------------------------------------------------------------------- */
  805. void
  806. vfs_s_insert_entry (struct vfs_class *me, struct vfs_s_inode *dir, struct vfs_s_entry *ent)
  807. {
  808. (void) me;
  809. ent->dir = dir;
  810. ent->ino->st.st_nlink++;
  811. dir->subdir = g_list_append (dir->subdir, ent);
  812. }
  813. /* --------------------------------------------------------------------------------------------- */
  814. struct stat *
  815. vfs_s_default_stat (struct vfs_class *me, mode_t mode)
  816. {
  817. static struct stat st;
  818. int myumask;
  819. (void) me;
  820. myumask = umask (022);
  821. umask (myumask);
  822. mode &= ~myumask;
  823. st.st_mode = mode;
  824. st.st_ino = 0;
  825. st.st_dev = 0;
  826. st.st_rdev = 0;
  827. st.st_uid = getuid ();
  828. st.st_gid = getgid ();
  829. st.st_size = 0;
  830. st.st_mtime = st.st_atime = st.st_ctime = time (NULL);
  831. return &st;
  832. }
  833. /* --------------------------------------------------------------------------------------------- */
  834. struct vfs_s_entry *
  835. vfs_s_generate_entry (struct vfs_class *me, const char *name, struct vfs_s_inode *parent,
  836. mode_t mode)
  837. {
  838. struct vfs_s_inode *inode;
  839. struct stat *st;
  840. st = vfs_s_default_stat (me, mode);
  841. inode = vfs_s_new_inode (me, parent->super, st);
  842. return vfs_s_new_entry (me, name, inode);
  843. }
  844. /* --------------------------------------------------------------------------------------------- */
  845. struct vfs_s_inode *
  846. vfs_s_find_inode (struct vfs_class *me, const struct vfs_s_super *super,
  847. const char *path, int follow, int flags)
  848. {
  849. struct vfs_s_entry *ent;
  850. if (((MEDATA->flags & VFS_S_REMOTE) == 0) && (*path == '\0'))
  851. return super->root;
  852. ent = (MEDATA->find_entry) (me, super->root, path, follow, flags);
  853. return (ent != NULL) ? ent->ino : NULL;
  854. }
  855. /* --------------------------------------------------------------------------------------------- */
  856. vfs_file_handler_t *
  857. vfs_s_create_file_handler (const struct vfs_s_super * super, const vfs_path_t * vpath, int flags)
  858. {
  859. vfs_file_handler_t *file_handler;
  860. struct vfs_s_inode *path_inode;
  861. const vfs_path_element_t *path_element;
  862. gboolean was_created = FALSE;
  863. path_element = vfs_path_get_by_index (vpath, -1);
  864. path_inode =
  865. vfs_s_find_inode (path_element->class, super, path_element->path, LINK_FOLLOW, FL_NONE);
  866. if (path_inode != NULL && ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)))
  867. {
  868. path_element->class->verrno = EEXIST;
  869. return NULL;
  870. }
  871. if (path_inode == NULL)
  872. {
  873. char *dirname, *name;
  874. struct vfs_s_entry *ent;
  875. struct vfs_s_inode *dir;
  876. dirname = g_path_get_dirname (path_element->path);
  877. name = g_path_get_basename (path_element->path);
  878. dir = vfs_s_find_inode (path_element->class, super, dirname, LINK_FOLLOW, FL_DIR);
  879. if (dir == NULL)
  880. {
  881. g_free (dirname);
  882. g_free (name);
  883. return NULL;
  884. }
  885. ent = vfs_s_generate_entry (path_element->class, name, dir, 0755);
  886. path_inode = ent->ino;
  887. vfs_s_insert_entry (path_element->class, dir, ent);
  888. g_free (dirname);
  889. g_free (name);
  890. was_created = TRUE;
  891. }
  892. if (S_ISDIR (path_inode->st.st_mode))
  893. {
  894. path_element->class->verrno = EISDIR;
  895. return NULL;
  896. }
  897. file_handler = g_new0 (vfs_file_handler_t, 1);
  898. file_handler->pos = 0;
  899. file_handler->ino = path_inode;
  900. file_handler->handle = -1;
  901. file_handler->changed = was_created;
  902. file_handler->linear = 0;
  903. file_handler->data = NULL;
  904. return file_handler;
  905. }
  906. /* --------------------------------------------------------------------------------------------- */
  907. void
  908. vfs_s_open_file_post_action (const vfs_path_t * vpath, struct vfs_s_super *super,
  909. vfs_file_handler_t * file_handler)
  910. {
  911. const vfs_path_element_t *path_element;
  912. path_element = vfs_path_get_by_index (vpath, -1);
  913. vfs_rmstamp (path_element->class, (vfsid) super);
  914. super->fd_usage++;
  915. file_handler->ino->st.st_nlink++;
  916. }
  917. /* --------------------------------------------------------------------------------------------- */
  918. /* Ook, these were functions around directory entries / inodes */
  919. /* -------------------------------- superblock games -------------------------- */
  920. /**
  921. * Get superblock. Create if needed.
  922. *
  923. * @param vpath source path object
  924. * @param is_create_new Should we create new super block if it doesn't exists before
  925. *
  926. * @return archive pointer to object for store superblock
  927. */
  928. struct vfs_s_super *
  929. vfs_get_super_by_vpath (const vfs_path_t * vpath, gboolean is_create_new)
  930. {
  931. int result = -1;
  932. struct vfs_s_super *super = NULL;
  933. const vfs_path_element_t *path_element;
  934. struct vfs_s_subclass *subclass;
  935. vfs_get_by_vpath_data_t vfs_get_by_vpath_data;
  936. path_element = vfs_path_get_by_index (vpath, -1);
  937. subclass = ((struct vfs_s_subclass *) path_element->class->data);
  938. if (subclass == NULL)
  939. return NULL;
  940. vfs_get_by_vpath_data.path_element = path_element;
  941. vfs_get_by_vpath_data.vpath_archive = vfs_path_clone (vpath);
  942. vfs_path_remove_element_by_index (vfs_get_by_vpath_data.vpath_archive, -1);
  943. {
  944. gboolean is_search_called = TRUE;
  945. if (subclass->archive_check != NULL)
  946. {
  947. vfs_get_by_vpath_data.cookie =
  948. subclass->archive_check (vfs_get_by_vpath_data.vpath_archive);
  949. if (vfs_get_by_vpath_data.cookie == NULL)
  950. is_search_called = FALSE;
  951. }
  952. else
  953. vfs_get_by_vpath_data.cookie = NULL;
  954. if (is_search_called)
  955. super =
  956. vfs_get_super_by_cb_conditions (path_element->class, vfs_cb_archive_same,
  957. (void *) &vfs_get_by_vpath_data);
  958. }
  959. vfs_path_free (vfs_get_by_vpath_data.vpath_archive);
  960. if (super != NULL)
  961. goto return_success;
  962. if (!is_create_new)
  963. {
  964. path_element->class->verrno = EIO;
  965. return NULL;
  966. }
  967. super = vfs_s_new_super (path_element->class);
  968. if (subclass->open_archive != NULL)
  969. {
  970. vfs_path_t *vpath_archive;
  971. vpath_archive = vfs_path_clone (vpath);
  972. vfs_path_remove_element_by_index (vpath_archive, -1);
  973. result = subclass->open_archive (super, vpath_archive, path_element);
  974. vfs_path_free (vpath_archive);
  975. }
  976. if (result == -1)
  977. {
  978. vfs_s_free_super (path_element->class, super);
  979. path_element->class->verrno = EIO;
  980. return NULL;
  981. }
  982. if (!super->name)
  983. vfs_die ("You have to fill name\n");
  984. if (!super->root)
  985. vfs_die ("You have to fill root inode\n");
  986. vfs_s_insert_super (path_element->class, super);
  987. vfs_stamp_create (path_element->class, super);
  988. return_success:
  989. return super;
  990. }
  991. /* --------------------------------------------------------------------------------------------- */
  992. /**
  993. * Get superblock by callback function.
  994. *
  995. * @param me class for search superblocks
  996. * @param cb_conditions callback function for getting needed superblock
  997. * @param cb_data some data for callback
  998. *
  999. * @return if found, archive pointer to object for store superblock; NULL otherwise
  1000. */
  1001. struct vfs_s_super *
  1002. vfs_get_super_by_cb_conditions (struct vfs_class *me, cb_conditions_t * cb_conditions,
  1003. void *cb_data)
  1004. {
  1005. GList *iter;
  1006. struct vfs_s_subclass *subclass;
  1007. subclass = ((struct vfs_s_subclass *) me->data);
  1008. if (subclass == NULL)
  1009. return NULL;
  1010. for (iter = subclass->supers; iter != NULL; iter = g_list_next (iter))
  1011. {
  1012. struct vfs_s_super *super;
  1013. super = (struct vfs_s_super *) iter->data;
  1014. if (cb_conditions (me, cb_data, super))
  1015. return super;
  1016. }
  1017. return NULL;
  1018. }
  1019. /* --------------------------------------------------------------------------------------------- */
  1020. void
  1021. vfs_s_invalidate (struct vfs_class *me, struct vfs_s_super *super)
  1022. {
  1023. if (!super->want_stale)
  1024. {
  1025. vfs_s_free_inode (me, super->root);
  1026. super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755));
  1027. }
  1028. }
  1029. /* --------------------------------------------------------------------------------------------- */
  1030. char *
  1031. vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino)
  1032. {
  1033. if (!ino->ent)
  1034. ERRNOR (EAGAIN, NULL);
  1035. if ((MEDATA->flags & VFS_S_USETMP) == 0)
  1036. {
  1037. /* archives */
  1038. char *newpath;
  1039. char *path = g_strdup (ino->ent->name);
  1040. while (1)
  1041. {
  1042. ino = ino->ent->dir;
  1043. if (ino == ino->super->root)
  1044. break;
  1045. newpath = g_strconcat (ino->ent->name, "/", path, (char *) NULL);
  1046. g_free (path);
  1047. path = newpath;
  1048. }
  1049. return path;
  1050. }
  1051. /* remote systems */
  1052. if ((!ino->ent->dir) || (!ino->ent->dir->ent))
  1053. return g_strdup (ino->ent->name);
  1054. return g_strconcat (ino->ent->dir->ent->name, PATH_SEP_STR, ino->ent->name, (char *) NULL);
  1055. }
  1056. /* --------------------------------------------------------------------------------------------- */
  1057. /* --------------------------- stat and friends ---------------------------- */
  1058. void *
  1059. vfs_s_open (const vfs_path_t * vpath, int flags, mode_t mode)
  1060. {
  1061. int was_changed = 0;
  1062. vfs_file_handler_t *fh;
  1063. struct vfs_s_super *super;
  1064. struct vfs_s_inode *ino;
  1065. const vfs_path_element_t *path_element;
  1066. super = vfs_get_super_by_vpath (vpath, TRUE);
  1067. if (super == NULL)
  1068. return NULL;
  1069. path_element = vfs_path_get_by_index (vpath, -1);
  1070. ino = vfs_s_find_inode (path_element->class, super, path_element->path, LINK_FOLLOW, FL_NONE);
  1071. if (ino && ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)))
  1072. {
  1073. path_element->class->verrno = EEXIST;
  1074. return NULL;
  1075. }
  1076. if (!ino)
  1077. {
  1078. char *dirname, *name;
  1079. struct vfs_s_entry *ent;
  1080. struct vfs_s_inode *dir;
  1081. /* If the filesystem is read-only, disable file creation */
  1082. if (!(flags & O_CREAT) || !(path_element->class->write))
  1083. return NULL;
  1084. dirname = g_path_get_dirname (path_element->path);
  1085. name = g_path_get_basename (path_element->path);
  1086. dir = vfs_s_find_inode (path_element->class, super, dirname, LINK_FOLLOW, FL_DIR);
  1087. if (dir == NULL)
  1088. {
  1089. g_free (dirname);
  1090. g_free (name);
  1091. return NULL;
  1092. }
  1093. ent = vfs_s_generate_entry (path_element->class, name, dir, 0755);
  1094. ino = ent->ino;
  1095. vfs_s_insert_entry (path_element->class, dir, ent);
  1096. if ((VFSDATA (path_element)->flags & VFS_S_USETMP) != 0)
  1097. {
  1098. int tmp_handle;
  1099. vfs_path_t *tmp_vpath;
  1100. tmp_handle = vfs_mkstemps (&tmp_vpath, path_element->class->name, name);
  1101. ino->localname = g_strdup (vfs_path_as_str (tmp_vpath));
  1102. vfs_path_free (tmp_vpath);
  1103. if (tmp_handle == -1)
  1104. {
  1105. g_free (dirname);
  1106. g_free (name);
  1107. return NULL;
  1108. }
  1109. close (tmp_handle);
  1110. }
  1111. g_free (dirname);
  1112. g_free (name);
  1113. was_changed = 1;
  1114. }
  1115. if (S_ISDIR (ino->st.st_mode))
  1116. {
  1117. path_element->class->verrno = EISDIR;
  1118. return NULL;
  1119. }
  1120. fh = g_new (vfs_file_handler_t, 1);
  1121. fh->pos = 0;
  1122. fh->ino = ino;
  1123. fh->handle = -1;
  1124. fh->changed = was_changed;
  1125. fh->linear = 0;
  1126. fh->data = NULL;
  1127. if (IS_LINEAR (flags))
  1128. {
  1129. if (VFSDATA (path_element)->linear_start)
  1130. {
  1131. vfs_print_message (_("Starting linear transfer..."));
  1132. fh->linear = LS_LINEAR_PREOPEN;
  1133. }
  1134. }
  1135. else
  1136. {
  1137. struct vfs_s_subclass *s;
  1138. s = VFSDATA (path_element);
  1139. if (s->fh_open != NULL && s->fh_open (path_element->class, fh, flags, mode) != 0)
  1140. {
  1141. if (s->fh_free_data != NULL)
  1142. s->fh_free_data (fh);
  1143. g_free (fh);
  1144. return NULL;
  1145. }
  1146. }
  1147. if ((VFSDATA (path_element)->flags & VFS_S_USETMP) != 0 && fh->ino->localname != NULL)
  1148. {
  1149. fh->handle = open (fh->ino->localname, NO_LINEAR (flags), mode);
  1150. if (fh->handle == -1)
  1151. {
  1152. g_free (fh);
  1153. path_element->class->verrno = errno;
  1154. return NULL;
  1155. }
  1156. }
  1157. /* i.e. we had no open files and now we have one */
  1158. vfs_rmstamp (path_element->class, (vfsid) super);
  1159. super->fd_usage++;
  1160. fh->ino->st.st_nlink++;
  1161. return fh;
  1162. }
  1163. /* --------------------------------------------------------------------------------------------- */
  1164. int
  1165. vfs_s_retrieve_file (struct vfs_class *me, struct vfs_s_inode *ino)
  1166. {
  1167. /* If you want reget, you'll have to open file with O_LINEAR */
  1168. off_t total = 0;
  1169. char buffer[8192];
  1170. int handle;
  1171. ssize_t n;
  1172. off_t stat_size = ino->st.st_size;
  1173. vfs_file_handler_t fh;
  1174. vfs_path_t *tmp_vpath;
  1175. if ((MEDATA->flags & VFS_S_USETMP) == 0)
  1176. return -1;
  1177. memset (&fh, 0, sizeof (fh));
  1178. fh.ino = ino;
  1179. fh.handle = -1;
  1180. handle = vfs_mkstemps (&tmp_vpath, me->name, ino->ent->name);
  1181. ino->localname = g_strdup (vfs_path_as_str (tmp_vpath));
  1182. vfs_path_free (tmp_vpath);
  1183. if (handle == -1)
  1184. {
  1185. me->verrno = errno;
  1186. goto error_4;
  1187. }
  1188. if (!MEDATA->linear_start (me, &fh, 0))
  1189. goto error_3;
  1190. /* Clear the interrupt status */
  1191. tty_got_interrupt ();
  1192. tty_enable_interrupt_key ();
  1193. while ((n = MEDATA->linear_read (me, &fh, buffer, sizeof (buffer))))
  1194. {
  1195. int t;
  1196. if (n < 0)
  1197. goto error_1;
  1198. total += n;
  1199. vfs_s_print_stats (me->name, _("Getting file"), ino->ent->name, total, stat_size);
  1200. if (tty_got_interrupt ())
  1201. goto error_1;
  1202. t = write (handle, buffer, n);
  1203. if (t != n)
  1204. {
  1205. if (t == -1)
  1206. me->verrno = errno;
  1207. goto error_1;
  1208. }
  1209. }
  1210. MEDATA->linear_close (me, &fh);
  1211. close (handle);
  1212. tty_disable_interrupt_key ();
  1213. g_free (fh.data);
  1214. return 0;
  1215. error_1:
  1216. MEDATA->linear_close (me, &fh);
  1217. error_3:
  1218. tty_disable_interrupt_key ();
  1219. close (handle);
  1220. unlink (ino->localname);
  1221. error_4:
  1222. g_free (ino->localname);
  1223. ino->localname = NULL;
  1224. g_free (fh.data);
  1225. return -1;
  1226. }
  1227. /* --------------------------------------------------------------------------------------------- */
  1228. /* ----------------------------- Stamping support -------------------------- */
  1229. /* Initialize one of our subclasses - fill common functions */
  1230. void
  1231. vfs_s_init_class (struct vfs_class *vclass, struct vfs_s_subclass *sub)
  1232. {
  1233. vclass->data = sub;
  1234. vclass->fill_names = vfs_s_fill_names;
  1235. vclass->open = vfs_s_open;
  1236. vclass->close = vfs_s_close;
  1237. vclass->read = vfs_s_read;
  1238. if (!(sub->flags & VFS_S_READONLY))
  1239. {
  1240. vclass->write = vfs_s_write;
  1241. }
  1242. vclass->opendir = vfs_s_opendir;
  1243. vclass->readdir = vfs_s_readdir;
  1244. vclass->closedir = vfs_s_closedir;
  1245. vclass->stat = vfs_s_stat;
  1246. vclass->lstat = vfs_s_lstat;
  1247. vclass->fstat = vfs_s_fstat;
  1248. vclass->readlink = vfs_s_readlink;
  1249. vclass->chdir = vfs_s_chdir;
  1250. vclass->ferrno = vfs_s_ferrno;
  1251. vclass->lseek = vfs_s_lseek;
  1252. vclass->getid = vfs_s_getid;
  1253. vclass->nothingisopen = vfs_s_nothingisopen;
  1254. vclass->free = vfs_s_free;
  1255. if ((sub->flags & VFS_S_USETMP) != 0)
  1256. {
  1257. vclass->getlocalcopy = vfs_s_getlocalcopy;
  1258. vclass->ungetlocalcopy = vfs_s_ungetlocalcopy;
  1259. sub->find_entry = vfs_s_find_entry_linear;
  1260. }
  1261. else if ((sub->flags & VFS_S_REMOTE) != 0)
  1262. sub->find_entry = vfs_s_find_entry_linear;
  1263. else
  1264. sub->find_entry = vfs_s_find_entry_tree;
  1265. vclass->setctl = vfs_s_setctl;
  1266. sub->dir_uptodate = vfs_s_dir_uptodate;
  1267. }
  1268. /* --------------------------------------------------------------------------------------------- */
  1269. /** Find VFS id for given directory name */
  1270. vfsid
  1271. vfs_getid (const vfs_path_t * vpath)
  1272. {
  1273. const vfs_path_element_t *path_element;
  1274. path_element = vfs_path_get_by_index (vpath, -1);
  1275. if (!vfs_path_element_valid (path_element) || path_element->class->getid == NULL)
  1276. return NULL;
  1277. return (*path_element->class->getid) (vpath);
  1278. }
  1279. /* --------------------------------------------------------------------------------------------- */
  1280. /* ----------- Utility functions for networked filesystems -------------- */
  1281. #ifdef ENABLE_VFS_NET
  1282. int
  1283. vfs_s_select_on_two (int fd1, int fd2)
  1284. {
  1285. fd_set set;
  1286. struct timeval time_out;
  1287. int v;
  1288. int maxfd = (fd1 > fd2 ? fd1 : fd2) + 1;
  1289. time_out.tv_sec = 1;
  1290. time_out.tv_usec = 0;
  1291. FD_ZERO (&set);
  1292. FD_SET (fd1, &set);
  1293. FD_SET (fd2, &set);
  1294. v = select (maxfd, &set, 0, 0, &time_out);
  1295. if (v <= 0)
  1296. return v;
  1297. if (FD_ISSET (fd1, &set))
  1298. return 1;
  1299. if (FD_ISSET (fd2, &set))
  1300. return 2;
  1301. return -1;
  1302. }
  1303. /* --------------------------------------------------------------------------------------------- */
  1304. int
  1305. vfs_s_get_line (struct vfs_class *me, int sock, char *buf, int buf_len, char term)
  1306. {
  1307. FILE *logfile = MEDATA->logfile;
  1308. int i;
  1309. char c;
  1310. for (i = 0; i < buf_len - 1; i++, buf++)
  1311. {
  1312. if (read (sock, buf, sizeof (char)) <= 0)
  1313. return 0;
  1314. if (logfile)
  1315. {
  1316. size_t ret1;
  1317. int ret2;
  1318. ret1 = fwrite (buf, 1, 1, logfile);
  1319. ret2 = fflush (logfile);
  1320. (void) ret1;
  1321. (void) ret2;
  1322. }
  1323. if (*buf == term)
  1324. {
  1325. *buf = 0;
  1326. return 1;
  1327. }
  1328. }
  1329. /* Line is too long - terminate buffer and discard the rest of line */
  1330. *buf = 0;
  1331. while (read (sock, &c, sizeof (c)) > 0)
  1332. {
  1333. if (logfile)
  1334. {
  1335. size_t ret1;
  1336. int ret2;
  1337. ret1 = fwrite (&c, 1, 1, logfile);
  1338. ret2 = fflush (logfile);
  1339. (void) ret1;
  1340. (void) ret2;
  1341. }
  1342. if (c == '\n')
  1343. return 1;
  1344. }
  1345. return 0;
  1346. }
  1347. /* --------------------------------------------------------------------------------------------- */
  1348. int
  1349. vfs_s_get_line_interruptible (struct vfs_class *me, char *buffer, int size, int fd)
  1350. {
  1351. int i;
  1352. (void) me;
  1353. tty_enable_interrupt_key ();
  1354. for (i = 0; i < size - 1; i++)
  1355. {
  1356. int n;
  1357. n = read (fd, buffer + i, 1);
  1358. tty_disable_interrupt_key ();
  1359. if (n == -1 && errno == EINTR)
  1360. {
  1361. buffer[i] = 0;
  1362. return EINTR;
  1363. }
  1364. if (n == 0)
  1365. {
  1366. buffer[i] = 0;
  1367. return 0;
  1368. }
  1369. if (buffer[i] == '\n')
  1370. {
  1371. buffer[i] = 0;
  1372. return 1;
  1373. }
  1374. }
  1375. buffer[size - 1] = 0;
  1376. return 0;
  1377. }
  1378. #endif /* ENABLE_VFS_NET */
  1379. /* --------------------------------------------------------------------------------------------- */
  1380. /**
  1381. * Normalize filenames start position
  1382. */
  1383. void
  1384. vfs_s_normalize_filename_leading_spaces (struct vfs_s_inode *root_inode, size_t final_num_spaces)
  1385. {
  1386. GList *iter;
  1387. for (iter = root_inode->subdir; iter != NULL; iter = g_list_next (iter))
  1388. {
  1389. struct vfs_s_entry *entry = (struct vfs_s_entry *) iter->data;
  1390. if ((size_t) entry->ino->data_offset > final_num_spaces)
  1391. {
  1392. char *source_name = entry->name;
  1393. char *spacer = g_strnfill (entry->ino->data_offset - final_num_spaces, ' ');
  1394. entry->name = g_strdup_printf ("%s%s", spacer, source_name);
  1395. g_free (spacer);
  1396. g_free (source_name);
  1397. }
  1398. entry->ino->data_offset = -1;
  1399. }
  1400. }
  1401. /* --------------------------------------------------------------------------------------------- */