ftpfs.c 73 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582
  1. /* Virtual File System: FTP file system.
  2. Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  3. 2006, 2007 Free Software Foundation, Inc.
  4. Written by:
  5. 1995 Ching Hui
  6. 1995 Jakub Jelinek
  7. 1995, 1996, 1997 Miguel de Icaza
  8. 1997 Norbert Warmuth
  9. 1998 Pavel Machek
  10. 2010 Yury V. Zaytsev
  11. This program is free software; you can redistribute it and/or
  12. modify it under the terms of the GNU Library General Public License
  13. as published by the Free Software Foundation; either version 2 of
  14. the License, or (at your option) any later version.
  15. This program is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. GNU Library General Public License for more details.
  19. You should have received a copy of the GNU Library General Public
  20. License along with this program; if not, write to the Free Software
  21. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
  22. /**
  23. * \file
  24. * \brief Source: Virtual File System: FTP file system
  25. * \author Ching Hui
  26. * \author Jakub Jelinek
  27. * \author Miguel de Icaza
  28. * \author Norbert Warmuth
  29. * \author Pavel Machek
  30. * \date 1995, 1997, 1998
  31. *
  32. * \todo
  33. - make it more robust - all the connects etc. should handle EADDRINUSE and
  34. ERETRY (have I spelled these names correctly?)
  35. - make the user able to flush a connection - all the caches will get empty
  36. etc., (tarfs as well), we should give there a user selectable timeout
  37. and assign a key sequence.
  38. - use hash table instead of linklist to cache ftpfs directory.
  39. What to do with this?
  40. * NOTE: Usage of tildes is deprecated, consider:
  41. * \verbatim
  42. cd /#ftp:pavel@hobit
  43. cd ~
  44. \endverbatim
  45. * And now: what do I want to do? Do I want to go to /home/pavel or to
  46. * /#ftp:hobit/home/pavel? I think first has better sense...
  47. *
  48. \verbatim
  49. {
  50. int f = !strcmp( remote_path, "/~" );
  51. if (f || !strncmp( remote_path, "/~/", 3 )) {
  52. char *s;
  53. s = concat_dir_and_file( qhome (*bucket), remote_path +3-f );
  54. g_free (remote_path);
  55. remote_path = s;
  56. }
  57. }
  58. \endverbatim
  59. */
  60. /* \todo Fix: Namespace pollution: horrible */
  61. #include <config.h>
  62. #include <stdio.h> /* sscanf() */
  63. #include <stdlib.h> /* atoi() */
  64. #include <sys/types.h> /* POSIX-required by sys/socket.h and netdb.h */
  65. #include <netdb.h> /* struct hostent */
  66. #include <sys/socket.h> /* AF_INET */
  67. #include <netinet/in.h> /* struct in_addr */
  68. #ifdef HAVE_ARPA_INET_H
  69. #include <arpa/inet.h>
  70. #endif
  71. #include <arpa/ftp.h>
  72. #include <arpa/telnet.h>
  73. #include <sys/param.h>
  74. #include <errno.h>
  75. #include <ctype.h>
  76. #include <fcntl.h>
  77. #include <sys/time.h> /* gettimeofday() */
  78. #include <inttypes.h> /* uintmax_t */
  79. #include "lib/global.h"
  80. #include "lib/util.h"
  81. #include "lib/tty/tty.h" /* enable/disable interrupt key */
  82. #include "lib/widget.h" /* message() */
  83. #include "src/filemanager/layout.h" /* print_vfs_message */
  84. #include "src/history.h"
  85. #include "src/setup.h" /* for load_anon_passwd */
  86. #include "vfs-impl.h"
  87. #include "utilvfs.h"
  88. #include "netutil.h"
  89. #include "xdirentry.h"
  90. #include "gc.h" /* vfs_stamp_create */
  91. #include "ftpfs.h"
  92. /*** global variables ****************************************************************************/
  93. /* Delay to retry a connection */
  94. int ftpfs_retry_seconds = 30;
  95. /* Method to use to connect to ftp sites */
  96. int ftpfs_use_passive_connections = 1;
  97. int ftpfs_use_passive_connections_over_proxy = 0;
  98. /* Method used to get directory listings:
  99. * 1: try 'LIST -la <path>', if it fails
  100. * fall back to CWD <path>; LIST
  101. * 0: always use CWD <path>; LIST
  102. */
  103. int ftpfs_use_unix_list_options = 1;
  104. /* First "CWD <path>", then "LIST -la ." */
  105. int ftpfs_first_cd_then_ls = 1;
  106. /* Use the ~/.netrc */
  107. int ftpfs_use_netrc = 1;
  108. /* Anonymous setup */
  109. char *ftpfs_anonymous_passwd = NULL;
  110. int ftpfs_directory_timeout = 900;
  111. /* Proxy host */
  112. char *ftpfs_proxy_host = NULL;
  113. /* wether we have to use proxy by default? */
  114. int ftpfs_always_use_proxy = 0;
  115. int ftpfs_ignore_chattr_errors = 1;
  116. /*** file scope macro definitions ****************************************************************/
  117. #ifndef MAXHOSTNAMELEN
  118. #define MAXHOSTNAMELEN 64
  119. #endif
  120. #define UPLOAD_ZERO_LENGTH_FILE
  121. #define SUP super->u.ftp
  122. #define FH_SOCK fh->u.ftp.sock
  123. #ifndef INADDR_NONE
  124. #define INADDR_NONE 0xffffffff
  125. #endif
  126. #define RFC_AUTODETECT 0
  127. #define RFC_DARING 1
  128. #define RFC_STRICT 2
  129. /* ftpfs_command wait_flag: */
  130. #define NONE 0x00
  131. #define WAIT_REPLY 0x01
  132. #define WANT_STRING 0x02
  133. #define FTP_COMMAND_PORT 21
  134. /* some defines only used by ftpfs_changetype */
  135. /* These two are valid values for the second parameter */
  136. #define TYPE_ASCII 0
  137. #define TYPE_BINARY 1
  138. /* This one is only used to initialize bucket->isbinary, don't use it as
  139. second parameter to ftpfs_changetype. */
  140. #define TYPE_UNKNOWN -1
  141. #define ABORT_TIMEOUT 5
  142. /*** file scope type declarations ****************************************************************/
  143. #ifndef HAVE_SOCKLEN_T
  144. typedef int socklen_t;
  145. #endif
  146. /* This should match the keywords[] array below */
  147. typedef enum
  148. {
  149. NETRC_NONE = 0,
  150. NETRC_DEFAULT,
  151. NETRC_MACHINE,
  152. NETRC_LOGIN,
  153. NETRC_PASSWORD,
  154. NETRC_PASSWD,
  155. NETRC_ACCOUNT,
  156. NETRC_MACDEF,
  157. NETRC_UNKNOWN
  158. } keyword_t;
  159. /*** file scope variables ************************************************************************/
  160. static int ftpfs_errno;
  161. static int code;
  162. #ifdef FIXME_LATER_ALIGATOR
  163. static struct linklist *connections_list;
  164. #endif
  165. static char reply_str[80];
  166. static struct vfs_class vfs_ftpfs_ops;
  167. static struct no_proxy_entry
  168. {
  169. char *domain;
  170. void *next;
  171. } *no_proxy;
  172. static char buffer[BUF_MEDIUM];
  173. static char *netrc;
  174. static const char *netrcp;
  175. /*** file scope functions ************************************************************************/
  176. /* --------------------------------------------------------------------------------------------- */
  177. /* char *ftpfs_translate_path (struct ftpfs_connection *bucket, char *remote_path)
  178. Translate a Unix path, i.e. MC's internal path representation (e.g.
  179. /somedir/somefile) to a path valid for the remote server. Every path
  180. transfered to the remote server has to be mangled by this function
  181. right prior to sending it.
  182. Currently only Amiga ftp servers are handled in a special manner.
  183. When the remote server is an amiga:
  184. a) strip leading slash if necesarry
  185. b) replace first occurance of ":/" with ":"
  186. c) strip trailing "/."
  187. */
  188. static char *ftpfs_get_current_directory (struct vfs_class *me, struct vfs_s_super *super);
  189. static int ftpfs_chdir_internal (struct vfs_class *me, struct vfs_s_super *super,
  190. const char *remote_path);
  191. static int ftpfs_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply,
  192. const char *fmt, ...) __attribute__ ((format (__printf__, 4, 5)));
  193. static int ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super);
  194. static int ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super,
  195. const char *netrcpass);
  196. static int ftpfs_netrc_lookup (const char *host, char **login, char **pass);
  197. /* --------------------------------------------------------------------------------------------- */
  198. static char *
  199. ftpfs_translate_path (struct vfs_class *me, struct vfs_s_super *super, const char *remote_path)
  200. {
  201. if (!SUP.remote_is_amiga)
  202. return g_strdup (remote_path);
  203. else
  204. {
  205. char *ret, *p;
  206. if (MEDATA->logfile)
  207. {
  208. fprintf (MEDATA->logfile, "MC -- ftpfs_translate_path: %s\n", remote_path);
  209. fflush (MEDATA->logfile);
  210. }
  211. /* strip leading slash(es) */
  212. while (*remote_path == '/')
  213. remote_path++;
  214. /*
  215. * Don't change "/" into "", e.g. "CWD " would be
  216. * invalid.
  217. */
  218. if (*remote_path == '\0')
  219. return g_strdup (".");
  220. ret = g_strdup (remote_path);
  221. /* replace first occurance of ":/" with ":" */
  222. p = strchr (ret, ':');
  223. if ((p != NULL) && (*(p + 1) == '/'))
  224. memmove (p + 1, p + 2, strlen (p + 2) + 1);
  225. /* strip trailing "/." */
  226. p = strrchr (ret, '/');
  227. if ((p != NULL) && (*(p + 1) == '.') && (*(p + 2) == '\0'))
  228. *p = '\0';
  229. return ret;
  230. }
  231. }
  232. /* --------------------------------------------------------------------------------------------- */
  233. /** Extract the hostname and username from the path */
  234. /*
  235. * path is in the form: [user@]hostname:port/remote-dir, e.g.:
  236. * ftp://sunsite.unc.edu/pub/linux
  237. * ftp://miguel@sphinx.nuclecu.unam.mx/c/nc
  238. * ftp://tsx-11.mit.edu:8192/
  239. * ftp://joe@foo.edu:11321/private
  240. * If the user is empty, e.g. ftp://@roxanne/private, then your login name
  241. * is supplied.
  242. *
  243. */
  244. static void
  245. ftpfs_split_url (char *path, char **host, char **user, int *port, char **pass)
  246. {
  247. char *p;
  248. p = vfs_split_url (path, host, user, port, pass, FTP_COMMAND_PORT, URL_USE_ANONYMOUS);
  249. if (!*user)
  250. {
  251. /* Look up user and password in netrc */
  252. if (ftpfs_use_netrc)
  253. ftpfs_netrc_lookup (*host, user, pass);
  254. if (!*user)
  255. *user = g_strdup ("anonymous");
  256. }
  257. /* Look up password in netrc for known user */
  258. if (ftpfs_use_netrc && *user && pass && !*pass)
  259. {
  260. char *new_user;
  261. ftpfs_netrc_lookup (*host, &new_user, pass);
  262. /* If user is different, remove password */
  263. if (new_user && strcmp (*user, new_user))
  264. {
  265. g_free (*pass);
  266. *pass = NULL;
  267. }
  268. g_free (new_user);
  269. }
  270. g_free (p);
  271. }
  272. /* --------------------------------------------------------------------------------------------- */
  273. /* Returns a reply code, check /usr/include/arpa/ftp.h for possible values */
  274. static int
  275. ftpfs_get_reply (struct vfs_class *me, int sock, char *string_buf, int string_len)
  276. {
  277. char answer[BUF_1K];
  278. int i;
  279. for (;;)
  280. {
  281. if (!vfs_s_get_line (me, sock, answer, sizeof (answer), '\n'))
  282. {
  283. if (string_buf)
  284. *string_buf = 0;
  285. code = 421;
  286. return 4;
  287. }
  288. switch (sscanf (answer, "%d", &code))
  289. {
  290. case 0:
  291. if (string_buf)
  292. g_strlcpy (string_buf, answer, string_len);
  293. code = 500;
  294. return 5;
  295. case 1:
  296. if (answer[3] == '-')
  297. {
  298. while (1)
  299. {
  300. if (!vfs_s_get_line (me, sock, answer, sizeof (answer), '\n'))
  301. {
  302. if (string_buf)
  303. *string_buf = 0;
  304. code = 421;
  305. return 4;
  306. }
  307. if ((sscanf (answer, "%d", &i) > 0) && (code == i) && (answer[3] == ' '))
  308. break;
  309. }
  310. }
  311. if (string_buf)
  312. g_strlcpy (string_buf, answer, string_len);
  313. return code / 100;
  314. }
  315. }
  316. }
  317. /* --------------------------------------------------------------------------------------------- */
  318. static int
  319. ftpfs_reconnect (struct vfs_class *me, struct vfs_s_super *super)
  320. {
  321. int sock = ftpfs_open_socket (me, super);
  322. if (sock != -1)
  323. {
  324. char *cwdir = SUP.cwdir;
  325. close (SUP.sock);
  326. SUP.sock = sock;
  327. SUP.cwdir = NULL;
  328. if (ftpfs_login_server (me, super, SUP.password))
  329. {
  330. if (!cwdir)
  331. return 1;
  332. sock = ftpfs_chdir_internal (me, super, cwdir);
  333. g_free (cwdir);
  334. return sock == COMPLETE;
  335. }
  336. SUP.cwdir = cwdir;
  337. }
  338. return 0;
  339. }
  340. /* --------------------------------------------------------------------------------------------- */
  341. static int
  342. ftpfs_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, const char *fmt,
  343. ...)
  344. {
  345. va_list ap;
  346. char *cmdstr;
  347. int status, cmdlen;
  348. static int retry = 0;
  349. static int level = 0; /* ftpfs_login_server() use ftpfs_command() */
  350. va_start (ap, fmt);
  351. cmdstr = g_strdup_vprintf (fmt, ap);
  352. va_end (ap);
  353. cmdlen = strlen (cmdstr);
  354. cmdstr = g_realloc (cmdstr, cmdlen + 3);
  355. strcpy (cmdstr + cmdlen, "\r\n");
  356. cmdlen += 2;
  357. if (MEDATA->logfile)
  358. {
  359. if (strncmp (cmdstr, "PASS ", 5) == 0)
  360. {
  361. fputs ("PASS <Password not logged>\r\n", MEDATA->logfile);
  362. }
  363. else
  364. {
  365. size_t ret;
  366. ret = fwrite (cmdstr, cmdlen, 1, MEDATA->logfile);
  367. }
  368. fflush (MEDATA->logfile);
  369. }
  370. got_sigpipe = 0;
  371. tty_enable_interrupt_key ();
  372. status = write (SUP.sock, cmdstr, cmdlen);
  373. if (status < 0)
  374. {
  375. code = 421;
  376. if (errno == EPIPE)
  377. { /* Remote server has closed connection */
  378. if (level == 0)
  379. {
  380. level = 1;
  381. status = ftpfs_reconnect (me, super);
  382. level = 0;
  383. if (status && (write (SUP.sock, cmdstr, cmdlen) > 0))
  384. {
  385. goto ok;
  386. }
  387. }
  388. got_sigpipe = 1;
  389. }
  390. g_free (cmdstr);
  391. tty_disable_interrupt_key ();
  392. return TRANSIENT;
  393. }
  394. retry = 0;
  395. ok:
  396. tty_disable_interrupt_key ();
  397. if (wait_reply)
  398. {
  399. status = ftpfs_get_reply (me, SUP.sock,
  400. (wait_reply & WANT_STRING) ? reply_str : NULL,
  401. sizeof (reply_str) - 1);
  402. if ((wait_reply & WANT_STRING) && !retry && !level && code == 421)
  403. {
  404. retry = 1;
  405. level = 1;
  406. status = ftpfs_reconnect (me, super);
  407. level = 0;
  408. if (status && (write (SUP.sock, cmdstr, cmdlen) > 0))
  409. {
  410. goto ok;
  411. }
  412. }
  413. retry = 0;
  414. g_free (cmdstr);
  415. return status;
  416. }
  417. g_free (cmdstr);
  418. return COMPLETE;
  419. }
  420. /* --------------------------------------------------------------------------------------------- */
  421. static void
  422. ftpfs_free_archive (struct vfs_class *me, struct vfs_s_super *super)
  423. {
  424. if (SUP.sock != -1)
  425. {
  426. print_vfs_message (_("ftpfs: Disconnecting from %s"), SUP.host);
  427. ftpfs_command (me, super, NONE, "QUIT");
  428. close (SUP.sock);
  429. }
  430. g_free (SUP.host);
  431. g_free (SUP.user);
  432. g_free (SUP.cwdir);
  433. g_free (SUP.password);
  434. }
  435. /* --------------------------------------------------------------------------------------------- */
  436. static int
  437. ftpfs_changetype (struct vfs_class *me, struct vfs_s_super *super, int binary)
  438. {
  439. if (binary != SUP.isbinary)
  440. {
  441. if (ftpfs_command (me, super, WAIT_REPLY, "TYPE %c", binary ? 'I' : 'A') != COMPLETE)
  442. ERRNOR (EIO, -1);
  443. SUP.isbinary = binary;
  444. }
  445. return binary;
  446. }
  447. /* --------------------------------------------------------------------------------------------- */
  448. /* This routine logs the user in */
  449. static int
  450. ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char *netrcpass)
  451. {
  452. char *pass;
  453. char *op;
  454. char *name; /* login user name */
  455. int anon = 0;
  456. char reply_string[BUF_MEDIUM];
  457. SUP.isbinary = TYPE_UNKNOWN;
  458. if (SUP.password) /* explicit password */
  459. op = g_strdup (SUP.password);
  460. else if (netrcpass) /* password from netrc */
  461. op = g_strdup (netrcpass);
  462. else if (!strcmp (SUP.user, "anonymous") || !strcmp (SUP.user, "ftp"))
  463. {
  464. if (!ftpfs_anonymous_passwd) /* default anonymous password */
  465. ftpfs_init_passwd ();
  466. op = g_strdup (ftpfs_anonymous_passwd);
  467. anon = 1;
  468. }
  469. else
  470. { /* ask user */
  471. char *p;
  472. p = g_strdup_printf (_("FTP: Password required for %s"), SUP.user);
  473. op = vfs_get_password (p);
  474. g_free (p);
  475. if (op == NULL)
  476. ERRNOR (EPERM, 0);
  477. SUP.password = g_strdup (op);
  478. }
  479. if (!anon || MEDATA->logfile)
  480. pass = op;
  481. else
  482. {
  483. pass = g_strconcat ("-", op, (char *) NULL);
  484. wipe_password (op);
  485. }
  486. /* Proxy server accepts: username@host-we-want-to-connect */
  487. if (SUP.proxy)
  488. {
  489. name =
  490. g_strconcat (SUP.user, "@",
  491. SUP.host[0] == '!' ? SUP.host + 1 : SUP.host, (char *) NULL);
  492. }
  493. else
  494. name = g_strdup (SUP.user);
  495. if (ftpfs_get_reply (me, SUP.sock, reply_string, sizeof (reply_string) - 1) == COMPLETE)
  496. {
  497. char *reply_up;
  498. reply_up = g_ascii_strup (reply_string, -1);
  499. SUP.remote_is_amiga = strstr (reply_up, "AMIGA") != 0;
  500. if (strstr (reply_up, " SPFTP/1.0.0000 SERVER ")) /* handles `LIST -la` in a weird way */
  501. SUP.strict = RFC_STRICT;
  502. g_free (reply_up);
  503. if (MEDATA->logfile)
  504. {
  505. fprintf (MEDATA->logfile, "MC -- remote_is_amiga = %d\n", SUP.remote_is_amiga);
  506. fflush (MEDATA->logfile);
  507. }
  508. print_vfs_message (_("ftpfs: sending login name"));
  509. switch (ftpfs_command (me, super, WAIT_REPLY, "USER %s", name))
  510. {
  511. case CONTINUE:
  512. print_vfs_message (_("ftpfs: sending user password"));
  513. code = ftpfs_command (me, super, WAIT_REPLY, "PASS %s", pass);
  514. if (code == CONTINUE)
  515. {
  516. char *p;
  517. p = g_strdup_printf (_("FTP: Account required for user %s"), SUP.user);
  518. op = input_dialog (p, _("Account:"), MC_HISTORY_FTPFS_ACCOUNT, "");
  519. g_free (p);
  520. if (op == NULL)
  521. ERRNOR (EPERM, 0);
  522. print_vfs_message (_("ftpfs: sending user account"));
  523. code = ftpfs_command (me, super, WAIT_REPLY, "ACCT %s", op);
  524. g_free (op);
  525. }
  526. if (code != COMPLETE)
  527. break;
  528. /* fall through */
  529. case COMPLETE:
  530. print_vfs_message (_("ftpfs: logged in"));
  531. wipe_password (pass);
  532. g_free (name);
  533. return 1;
  534. default:
  535. SUP.failed_on_login = 1;
  536. if (SUP.password)
  537. wipe_password (SUP.password);
  538. SUP.password = 0;
  539. goto login_fail;
  540. }
  541. }
  542. message (D_ERROR, MSG_ERROR, _("ftpfs: Login incorrect for user %s "), SUP.user);
  543. login_fail:
  544. wipe_password (pass);
  545. g_free (name);
  546. ERRNOR (EPERM, 0);
  547. }
  548. /* --------------------------------------------------------------------------------------------- */
  549. static void
  550. ftpfs_load_no_proxy_list (void)
  551. {
  552. /* FixMe: shouldn't be hardcoded!!! */
  553. char s[BUF_LARGE]; /* provide for BUF_LARGE characters */
  554. struct no_proxy_entry *np, *current = 0;
  555. FILE *npf;
  556. int c;
  557. char *p;
  558. static char *mc_file;
  559. if (mc_file)
  560. return;
  561. mc_file = concat_dir_and_file (mc_home, "mc.no_proxy");
  562. if (exist_file (mc_file))
  563. {
  564. npf = fopen (mc_file, "r");
  565. if (npf != NULL)
  566. {
  567. while (fgets (s, sizeof (s), npf) != NULL)
  568. {
  569. p = strchr (s, '\n');
  570. if (p == NULL) /* skip bogus entries */
  571. {
  572. while ((c = fgetc (npf)) != EOF && c != '\n')
  573. ;
  574. continue;
  575. }
  576. if (p == s)
  577. continue;
  578. *p = '\0';
  579. np = g_new (struct no_proxy_entry, 1);
  580. np->domain = g_strdup (s);
  581. np->next = NULL;
  582. if (no_proxy)
  583. current->next = np;
  584. else
  585. no_proxy = np;
  586. current = np;
  587. }
  588. fclose (npf);
  589. }
  590. }
  591. g_free (mc_file);
  592. }
  593. /* --------------------------------------------------------------------------------------------- */
  594. /* Return 1 if FTP proxy should be used for this host, 0 otherwise */
  595. static int
  596. ftpfs_check_proxy (const char *host)
  597. {
  598. struct no_proxy_entry *npe;
  599. if (!ftpfs_proxy_host || !*ftpfs_proxy_host || !host || !*host)
  600. return 0; /* sanity check */
  601. if (*host == '!')
  602. return 1;
  603. if (!ftpfs_always_use_proxy)
  604. return 0;
  605. if (!strchr (host, '.'))
  606. return 0;
  607. ftpfs_load_no_proxy_list ();
  608. for (npe = no_proxy; npe; npe = npe->next)
  609. {
  610. char *domain = npe->domain;
  611. if (domain[0] == '.')
  612. {
  613. int ld = strlen (domain);
  614. int lh = strlen (host);
  615. while (ld && lh && host[lh - 1] == domain[ld - 1])
  616. {
  617. ld--;
  618. lh--;
  619. }
  620. if (!ld)
  621. return 0;
  622. }
  623. else if (g_ascii_strcasecmp (host, domain) == 0)
  624. return 0;
  625. }
  626. return 1;
  627. }
  628. /* --------------------------------------------------------------------------------------------- */
  629. static void
  630. ftpfs_get_proxy_host_and_port (const char *proxy, char **host, int *port)
  631. {
  632. char *user, *dir;
  633. dir = vfs_split_url (proxy, host, &user, port, 0, FTP_COMMAND_PORT, URL_USE_ANONYMOUS);
  634. g_free (user);
  635. g_free (dir);
  636. }
  637. /* --------------------------------------------------------------------------------------------- */
  638. static int
  639. ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
  640. {
  641. struct addrinfo hints, *res, *curr_res;
  642. int my_socket = 0;
  643. char *host = NULL;
  644. char *port = NULL;
  645. int tmp_port;
  646. int e;
  647. (void) me;
  648. /* Use a proxy host? */
  649. host = g_strdup (SUP.host);
  650. if (!host || !*host)
  651. {
  652. print_vfs_message (_("ftpfs: Invalid host name."));
  653. ftpfs_errno = EINVAL;
  654. g_free (host);
  655. return -1;
  656. }
  657. /* Hosts to connect to that start with a ! should use proxy */
  658. tmp_port = SUP.port;
  659. if (SUP.proxy)
  660. {
  661. ftpfs_get_proxy_host_and_port (ftpfs_proxy_host, &host, &tmp_port);
  662. }
  663. port = g_strdup_printf ("%hu", (unsigned short) tmp_port);
  664. if (port == NULL)
  665. {
  666. g_free (host);
  667. ftpfs_errno = errno;
  668. return -1;
  669. }
  670. tty_enable_interrupt_key (); /* clear the interrupt flag */
  671. memset (&hints, 0, sizeof (struct addrinfo));
  672. hints.ai_family = AF_UNSPEC;
  673. hints.ai_socktype = SOCK_STREAM;
  674. #ifdef AI_ADDRCONFIG
  675. /* By default, only look up addresses using address types for
  676. * which a local interface is configured (i.e. no IPv6 if no IPv6
  677. * interfaces, likewise for IPv4 (see RFC 3493 for details). */
  678. hints.ai_flags = AI_ADDRCONFIG;
  679. #endif
  680. e = getaddrinfo (host, port, &hints, &res);
  681. #ifdef AI_ADDRCONFIG
  682. if (e == EAI_BADFLAGS)
  683. {
  684. /* Retry with no flags if AI_ADDRCONFIG was rejected. */
  685. hints.ai_flags = 0;
  686. e = getaddrinfo (host, port, &hints, &res);
  687. }
  688. #endif
  689. g_free (port);
  690. port = NULL;
  691. if (e != 0)
  692. {
  693. tty_disable_interrupt_key ();
  694. print_vfs_message (_("ftpfs: %s"), gai_strerror (e));
  695. g_free (host);
  696. ftpfs_errno = EINVAL;
  697. return -1;
  698. }
  699. for (curr_res = res; curr_res != NULL; curr_res = curr_res->ai_next)
  700. {
  701. my_socket = socket (curr_res->ai_family, curr_res->ai_socktype, curr_res->ai_protocol);
  702. if (my_socket < 0)
  703. {
  704. if (curr_res->ai_next != NULL)
  705. continue;
  706. tty_disable_interrupt_key ();
  707. print_vfs_message (_("ftpfs: %s"), unix_error_string (errno));
  708. g_free (host);
  709. freeaddrinfo (res);
  710. ftpfs_errno = errno;
  711. return -1;
  712. }
  713. print_vfs_message (_("ftpfs: making connection to %s"), host);
  714. g_free (host);
  715. host = NULL;
  716. if (connect (my_socket, curr_res->ai_addr, curr_res->ai_addrlen) >= 0)
  717. break;
  718. ftpfs_errno = errno;
  719. close (my_socket);
  720. if (errno == EINTR && tty_got_interrupt ())
  721. {
  722. print_vfs_message (_("ftpfs: connection interrupted by user"));
  723. }
  724. else if (res->ai_next == NULL)
  725. {
  726. print_vfs_message (_("ftpfs: connection to server failed: %s"),
  727. unix_error_string (errno));
  728. }
  729. else
  730. {
  731. continue;
  732. }
  733. freeaddrinfo (res);
  734. tty_disable_interrupt_key ();
  735. return -1;
  736. }
  737. freeaddrinfo (res);
  738. tty_disable_interrupt_key ();
  739. return my_socket;
  740. }
  741. /* --------------------------------------------------------------------------------------------- */
  742. static int
  743. ftpfs_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
  744. {
  745. int retry_seconds, count_down;
  746. /* We do not want to use the passive if we are using proxies */
  747. if (SUP.proxy)
  748. SUP.use_passive_connection = ftpfs_use_passive_connections_over_proxy;
  749. retry_seconds = 0;
  750. do
  751. {
  752. SUP.failed_on_login = 0;
  753. SUP.sock = ftpfs_open_socket (me, super);
  754. if (SUP.sock == -1)
  755. return -1;
  756. if (ftpfs_login_server (me, super, NULL))
  757. {
  758. /* Logged in, no need to retry the connection */
  759. break;
  760. }
  761. else
  762. {
  763. if (SUP.failed_on_login)
  764. {
  765. /* Close only the socket descriptor */
  766. close (SUP.sock);
  767. }
  768. else
  769. {
  770. return -1;
  771. }
  772. if (ftpfs_retry_seconds)
  773. {
  774. retry_seconds = ftpfs_retry_seconds;
  775. tty_enable_interrupt_key ();
  776. for (count_down = retry_seconds; count_down; count_down--)
  777. {
  778. print_vfs_message (_("Waiting to retry... %d (Control-C to cancel)"),
  779. count_down);
  780. sleep (1);
  781. if (tty_got_interrupt ())
  782. {
  783. /* ftpfs_errno = E; */
  784. tty_disable_interrupt_key ();
  785. return 0;
  786. }
  787. }
  788. tty_disable_interrupt_key ();
  789. }
  790. }
  791. }
  792. while (retry_seconds);
  793. SUP.cwdir = ftpfs_get_current_directory (me, super);
  794. if (!SUP.cwdir)
  795. SUP.cwdir = g_strdup (PATH_SEP_STR);
  796. return 0;
  797. }
  798. /* --------------------------------------------------------------------------------------------- */
  799. static int
  800. ftpfs_open_archive (struct vfs_class *me, struct vfs_s_super *super,
  801. const char *archive_name, char *op)
  802. {
  803. char *host, *user, *password;
  804. int port;
  805. (void) archive_name;
  806. ftpfs_split_url (strchr (op, ':') + 1, &host, &user, &port, &password);
  807. SUP.host = host;
  808. SUP.user = user;
  809. SUP.port = port;
  810. SUP.cwdir = NULL;
  811. SUP.proxy = 0;
  812. if (ftpfs_check_proxy (host))
  813. SUP.proxy = ftpfs_proxy_host;
  814. SUP.password = password;
  815. SUP.use_passive_connection = ftpfs_use_passive_connections;
  816. SUP.strict = ftpfs_use_unix_list_options ? RFC_AUTODETECT : RFC_STRICT;
  817. SUP.isbinary = TYPE_UNKNOWN;
  818. SUP.remote_is_amiga = 0;
  819. super->name = g_strdup ("/");
  820. super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755));
  821. return ftpfs_open_archive_int (me, super);
  822. }
  823. /* --------------------------------------------------------------------------------------------- */
  824. static int
  825. ftpfs_archive_same (struct vfs_class *me, struct vfs_s_super *super,
  826. const char *archive_name, char *op, void *cookie)
  827. {
  828. char *host, *user;
  829. int port;
  830. (void) me;
  831. (void) archive_name;
  832. (void) cookie;
  833. ftpfs_split_url (strchr (op, ':') + 1, &host, &user, &port, 0);
  834. port = ((strcmp (host, SUP.host) == 0) && (strcmp (user, SUP.user) == 0) && (port == SUP.port));
  835. g_free (host);
  836. g_free (user);
  837. return port;
  838. }
  839. /* --------------------------------------------------------------------------------------------- */
  840. /* The returned directory should always contain a trailing slash */
  841. static char *
  842. ftpfs_get_current_directory (struct vfs_class *me, struct vfs_s_super *super)
  843. {
  844. char buf[BUF_8K], *bufp, *bufq;
  845. if (ftpfs_command (me, super, NONE, "PWD") == COMPLETE &&
  846. ftpfs_get_reply (me, SUP.sock, buf, sizeof (buf)) == COMPLETE)
  847. {
  848. bufp = NULL;
  849. for (bufq = buf; *bufq; bufq++)
  850. if (*bufq == '"')
  851. {
  852. if (!bufp)
  853. {
  854. bufp = bufq + 1;
  855. }
  856. else
  857. {
  858. *bufq = 0;
  859. if (*bufp)
  860. {
  861. if (*(bufq - 1) != '/')
  862. {
  863. *bufq++ = '/';
  864. *bufq = 0;
  865. }
  866. if (*bufp == '/')
  867. return g_strdup (bufp);
  868. else
  869. {
  870. /* If the remote server is an Amiga a leading slash
  871. might be missing. MC needs it because it is used
  872. as separator between hostname and path internally. */
  873. return g_strconcat ("/", bufp, (char *) NULL);
  874. }
  875. }
  876. else
  877. {
  878. ftpfs_errno = EIO;
  879. return NULL;
  880. }
  881. }
  882. }
  883. }
  884. ftpfs_errno = EIO;
  885. return NULL;
  886. }
  887. /* --------------------------------------------------------------------------------------------- */
  888. /* Setup Passive PASV FTP connection */
  889. static int
  890. ftpfs_setup_passive_pasv (struct vfs_class *me, struct vfs_s_super *super,
  891. int my_socket, struct sockaddr_storage *sa, socklen_t * salen)
  892. {
  893. char *c;
  894. char n[6];
  895. int xa, xb, xc, xd, xe, xf;
  896. if (ftpfs_command (me, super, WAIT_REPLY | WANT_STRING, "PASV") != COMPLETE)
  897. return 0;
  898. /* Parse remote parameters */
  899. for (c = reply_str + 4; (*c) && (!isdigit ((unsigned char) *c)); c++);
  900. if (!*c)
  901. return 0;
  902. if (!isdigit ((unsigned char) *c))
  903. return 0;
  904. if (sscanf (c, "%d,%d,%d,%d,%d,%d", &xa, &xb, &xc, &xd, &xe, &xf) != 6)
  905. return 0;
  906. n[0] = (unsigned char) xa;
  907. n[1] = (unsigned char) xb;
  908. n[2] = (unsigned char) xc;
  909. n[3] = (unsigned char) xd;
  910. n[4] = (unsigned char) xe;
  911. n[5] = (unsigned char) xf;
  912. memcpy (&(((struct sockaddr_in *) sa)->sin_addr.s_addr), (void *) n, 4);
  913. memcpy (&(((struct sockaddr_in *) sa)->sin_port), (void *) &n[4], 2);
  914. if (connect (my_socket, (struct sockaddr *) sa, *salen) < 0)
  915. return 0;
  916. return 1;
  917. }
  918. /* --------------------------------------------------------------------------------------------- */
  919. /* Setup Passive EPSV FTP connection */
  920. static int
  921. ftpfs_setup_passive_epsv (struct vfs_class *me, struct vfs_s_super *super,
  922. int my_socket, struct sockaddr_storage *sa, socklen_t * salen)
  923. {
  924. char *c;
  925. int port;
  926. if (ftpfs_command (me, super, WAIT_REPLY | WANT_STRING, "EPSV") != COMPLETE)
  927. return 0;
  928. /* (|||<port>|) */
  929. c = strchr (reply_str, '|');
  930. if (c == NULL)
  931. return 0;
  932. if (strlen (c) > 3)
  933. c += 3;
  934. else
  935. return 0;
  936. port = atoi (c);
  937. if (port < 0 || port > 65535)
  938. return 0;
  939. port = htons (port);
  940. switch (sa->ss_family)
  941. {
  942. case AF_INET:
  943. ((struct sockaddr_in *) sa)->sin_port = port;
  944. break;
  945. case AF_INET6:
  946. ((struct sockaddr_in6 *) sa)->sin6_port = port;
  947. break;
  948. }
  949. if (connect (my_socket, (struct sockaddr *) sa, *salen) < 0)
  950. return 0;
  951. return 1;
  952. }
  953. /* --------------------------------------------------------------------------------------------- */
  954. /* Setup Passive ftp connection, we use it for source routed connections */
  955. static int
  956. ftpfs_setup_passive (struct vfs_class *me, struct vfs_s_super *super,
  957. int my_socket, struct sockaddr_storage *sa, socklen_t * salen)
  958. {
  959. /* It's IPV4, so try PASV first, some servers and ALGs get confused by EPSV */
  960. if (sa->ss_family == AF_INET)
  961. {
  962. if (!ftpfs_setup_passive_pasv (me, super, my_socket, sa, salen))
  963. /* An IPV4 FTP server might support EPSV, so if PASV fails we can try EPSV anyway */
  964. if (!ftpfs_setup_passive_epsv (me, super, my_socket, sa, salen))
  965. return 0;
  966. }
  967. /* It's IPV6, so EPSV is our only hope */
  968. else
  969. {
  970. if (!ftpfs_setup_passive_epsv (me, super, my_socket, sa, salen))
  971. return 0;
  972. }
  973. return 1;
  974. }
  975. /* --------------------------------------------------------------------------------------------- */
  976. /* Setup Active PORT or EPRT FTP connection */
  977. static int
  978. ftpfs_setup_active (struct vfs_class *me, struct vfs_s_super *super,
  979. struct sockaddr_storage data_addr, socklen_t data_addrlen)
  980. {
  981. unsigned short int port;
  982. char *addr;
  983. unsigned int af;
  984. switch (data_addr.ss_family)
  985. {
  986. case AF_INET:
  987. af = FTP_INET;
  988. port = ((struct sockaddr_in *) &data_addr)->sin_port;
  989. break;
  990. case AF_INET6:
  991. af = FTP_INET6;
  992. port = ((struct sockaddr_in6 *) &data_addr)->sin6_port;
  993. break;
  994. /* Not implemented */
  995. default:
  996. return 0;
  997. }
  998. addr = g_try_malloc (NI_MAXHOST);
  999. if (addr == NULL)
  1000. ERRNOR (ENOMEM, -1);
  1001. if (getnameinfo
  1002. ((struct sockaddr *) &data_addr, data_addrlen, addr, NI_MAXHOST, NULL, 0,
  1003. NI_NUMERICHOST) != 0)
  1004. {
  1005. g_free (addr);
  1006. ERRNOR (EIO, -1);
  1007. }
  1008. /* If we are talking to an IPV4 server, try PORT, and, only if it fails, go for EPRT */
  1009. if (af == FTP_INET)
  1010. {
  1011. unsigned char *a = (unsigned char *) &((struct sockaddr_in *) &data_addr)->sin_addr;
  1012. unsigned char *p = (unsigned char *) &port;
  1013. if (ftpfs_command (me, super, WAIT_REPLY,
  1014. "PORT %u,%u,%u,%u,%u,%u", a[0], a[1], a[2], a[3],
  1015. p[0], p[1]) == COMPLETE)
  1016. {
  1017. g_free (addr);
  1018. return 1;
  1019. }
  1020. }
  1021. /*
  1022. * Converts network MSB first order to host byte order (LSB
  1023. * first on i386). If we do it earlier, we will run into an
  1024. * endianness issue, because the server actually expects to see
  1025. * "PORT A,D,D,R,MSB,LSB" in the PORT command.
  1026. */
  1027. port = ntohs (port);
  1028. /* We are talking to an IPV6 server or PORT failed, so we can try EPRT anyway */
  1029. if (ftpfs_command (me, super, WAIT_REPLY, "EPRT |%u|%s|%hu|", af, addr, port) == COMPLETE)
  1030. {
  1031. g_free (addr);
  1032. return 1;
  1033. }
  1034. g_free (addr);
  1035. return 0;
  1036. }
  1037. /* --------------------------------------------------------------------------------------------- */
  1038. /* Initialize a socket for FTP DATA connection */
  1039. static int
  1040. ftpfs_init_data_socket (struct vfs_class *me, struct vfs_s_super *super,
  1041. struct sockaddr_storage *data_addr, socklen_t * data_addrlen)
  1042. {
  1043. int result;
  1044. memset (data_addr, 0, sizeof (struct sockaddr_storage));
  1045. *data_addrlen = sizeof (struct sockaddr_storage);
  1046. if (SUP.use_passive_connection)
  1047. result = getpeername (SUP.sock, (struct sockaddr *) data_addr, data_addrlen);
  1048. else
  1049. result = getsockname (SUP.sock, (struct sockaddr *) data_addr, data_addrlen);
  1050. if (result == -1)
  1051. return -1;
  1052. switch (data_addr->ss_family)
  1053. {
  1054. case AF_INET:
  1055. ((struct sockaddr_in *) data_addr)->sin_port = 0;
  1056. break;
  1057. case AF_INET6:
  1058. ((struct sockaddr_in6 *) data_addr)->sin6_port = 0;
  1059. break;
  1060. default:
  1061. print_vfs_message (_("ftpfs: invalid address family"));
  1062. ERRNOR (EINVAL, -1);
  1063. }
  1064. result = socket (data_addr->ss_family, SOCK_STREAM, IPPROTO_TCP);
  1065. if (result < 0)
  1066. {
  1067. print_vfs_message (_("ftpfs: could not create socket: %s"), unix_error_string (errno));
  1068. return -1;
  1069. }
  1070. else
  1071. return result;
  1072. }
  1073. /* --------------------------------------------------------------------------------------------- */
  1074. /* Initialize FTP DATA connection */
  1075. static int
  1076. ftpfs_initconn (struct vfs_class *me, struct vfs_s_super *super)
  1077. {
  1078. struct sockaddr_storage data_addr;
  1079. socklen_t data_addrlen;
  1080. /*
  1081. * Don't factor socket initialization out of these conditionals,
  1082. * because ftpfs_init_data_socket initializes it in different way
  1083. * depending on use_passive_connection flag.
  1084. */
  1085. /* Try to establish a passive connection first (if requested) */
  1086. if (SUP.use_passive_connection)
  1087. {
  1088. int data_sock;
  1089. data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
  1090. if (data_sock < 0)
  1091. return -1;
  1092. if (ftpfs_setup_passive (me, super, data_sock, &data_addr, &data_addrlen))
  1093. return data_sock;
  1094. print_vfs_message (_("ftpfs: could not setup passive mode"));
  1095. SUP.use_passive_connection = 0;
  1096. close (data_sock);
  1097. }
  1098. /* If passive setup is diabled or failed, fallback to active connections */
  1099. if (!SUP.use_passive_connection)
  1100. {
  1101. int data_sock;
  1102. data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
  1103. if (data_sock < 0)
  1104. return -1;
  1105. if ((bind (data_sock, (struct sockaddr *) &data_addr, data_addrlen) == 0) &&
  1106. (getsockname (data_sock, (struct sockaddr *) &data_addr, &data_addrlen) == 0) &&
  1107. (listen (data_sock, 1) == 0))
  1108. {
  1109. if (ftpfs_setup_active (me, super, data_addr, data_addrlen))
  1110. return data_sock;
  1111. }
  1112. close (data_sock);
  1113. }
  1114. /* Restore the initial value of use_passive_connection (for subsequent retries) */
  1115. SUP.use_passive_connection = SUP.proxy ? ftpfs_use_passive_connections_over_proxy :
  1116. ftpfs_use_passive_connections;
  1117. ftpfs_errno = EIO;
  1118. return -1;
  1119. }
  1120. /* --------------------------------------------------------------------------------------------- */
  1121. static int
  1122. ftpfs_open_data_connection (struct vfs_class *me, struct vfs_s_super *super, const char *cmd,
  1123. const char *remote, int isbinary, int reget)
  1124. {
  1125. struct sockaddr_storage from;
  1126. int s, j, data;
  1127. socklen_t fromlen = sizeof (from);
  1128. s = ftpfs_initconn (me, super);
  1129. if (s == -1)
  1130. return -1;
  1131. if (ftpfs_changetype (me, super, isbinary) == -1)
  1132. return -1;
  1133. if (reget > 0)
  1134. {
  1135. j = ftpfs_command (me, super, WAIT_REPLY, "REST %d", reget);
  1136. if (j != CONTINUE)
  1137. return -1;
  1138. }
  1139. if (remote)
  1140. {
  1141. char *remote_path = ftpfs_translate_path (me, super, remote);
  1142. j = ftpfs_command (me, super, WAIT_REPLY, "%s /%s", cmd,
  1143. /* WarFtpD can't STORE //filename */
  1144. (*remote_path == '/') ? remote_path + 1 : remote_path);
  1145. g_free (remote_path);
  1146. }
  1147. else
  1148. j = ftpfs_command (me, super, WAIT_REPLY, "%s", cmd);
  1149. if (j != PRELIM)
  1150. ERRNOR (EPERM, -1);
  1151. tty_enable_interrupt_key ();
  1152. if (SUP.use_passive_connection)
  1153. data = s;
  1154. else
  1155. {
  1156. data = accept (s, (struct sockaddr *) &from, &fromlen);
  1157. if (data < 0)
  1158. {
  1159. ftpfs_errno = errno;
  1160. close (s);
  1161. return -1;
  1162. }
  1163. close (s);
  1164. }
  1165. tty_disable_interrupt_key ();
  1166. return data;
  1167. }
  1168. /* --------------------------------------------------------------------------------------------- */
  1169. static void
  1170. ftpfs_linear_abort (struct vfs_class *me, struct vfs_s_fh *fh)
  1171. {
  1172. struct vfs_s_super *super = FH_SUPER;
  1173. static unsigned char const ipbuf[3] = { IAC, IP, IAC };
  1174. fd_set mask;
  1175. char buf[1024];
  1176. int dsock = FH_SOCK;
  1177. FH_SOCK = -1;
  1178. SUP.ctl_connection_busy = 0;
  1179. print_vfs_message (_("ftpfs: aborting transfer."));
  1180. if (send (SUP.sock, ipbuf, sizeof (ipbuf), MSG_OOB) != sizeof (ipbuf))
  1181. {
  1182. print_vfs_message (_("ftpfs: abort error: %s"), unix_error_string (errno));
  1183. if (dsock != -1)
  1184. close (dsock);
  1185. return;
  1186. }
  1187. if (ftpfs_command (me, super, NONE, "%cABOR", DM) != COMPLETE)
  1188. {
  1189. print_vfs_message (_("ftpfs: abort failed"));
  1190. if (dsock != -1)
  1191. close (dsock);
  1192. return;
  1193. }
  1194. if (dsock != -1)
  1195. {
  1196. FD_ZERO (&mask);
  1197. FD_SET (dsock, &mask);
  1198. if (select (dsock + 1, &mask, NULL, NULL, NULL) > 0)
  1199. {
  1200. struct timeval start_tim, tim;
  1201. gettimeofday (&start_tim, NULL);
  1202. /* flush the remaining data */
  1203. while (read (dsock, buf, sizeof (buf)) > 0)
  1204. {
  1205. gettimeofday (&tim, NULL);
  1206. if (tim.tv_sec > start_tim.tv_sec + ABORT_TIMEOUT)
  1207. {
  1208. /* server keeps sending, drop the connection and ftpfs_reconnect */
  1209. close (dsock);
  1210. ftpfs_reconnect (me, super);
  1211. return;
  1212. }
  1213. }
  1214. }
  1215. close (dsock);
  1216. }
  1217. if ((ftpfs_get_reply (me, SUP.sock, NULL, 0) == TRANSIENT) && (code == 426))
  1218. ftpfs_get_reply (me, SUP.sock, NULL, 0);
  1219. }
  1220. /* --------------------------------------------------------------------------------------------- */
  1221. #if 0
  1222. static void
  1223. resolve_symlink_without_ls_options (struct vfs_class *me, struct vfs_s_super *super,
  1224. struct vfs_s_inode *dir)
  1225. {
  1226. struct linklist *flist;
  1227. struct direntry *fe, *fel;
  1228. char tmp[MC_MAXPATHLEN];
  1229. int depth;
  1230. dir->symlink_status = FTPFS_RESOLVING_SYMLINKS;
  1231. for (flist = dir->file_list->next; flist != dir->file_list; flist = flist->next)
  1232. {
  1233. /* flist->data->l_stat is alread initialized with 0 */
  1234. fel = flist->data;
  1235. if (S_ISLNK (fel->s.st_mode) && fel->linkname)
  1236. {
  1237. if (fel->linkname[0] == '/')
  1238. {
  1239. if (strlen (fel->linkname) >= MC_MAXPATHLEN)
  1240. continue;
  1241. strcpy (tmp, fel->linkname);
  1242. }
  1243. else
  1244. {
  1245. if ((strlen (dir->remote_path) + strlen (fel->linkname)) >= MC_MAXPATHLEN)
  1246. continue;
  1247. strcpy (tmp, dir->remote_path);
  1248. if (tmp[1] != '\0')
  1249. strcat (tmp, "/");
  1250. strcat (tmp + 1, fel->linkname);
  1251. }
  1252. for (depth = 0; depth < 100; depth++)
  1253. { /* depth protects against recursive symbolic links */
  1254. canonicalize_pathname (tmp);
  1255. fe = _get_file_entry (bucket, tmp, 0, 0);
  1256. if (fe)
  1257. {
  1258. if (S_ISLNK (fe->s.st_mode) && fe->l_stat == 0)
  1259. {
  1260. /* Symlink points to link which isn't resolved, yet. */
  1261. if (fe->linkname[0] == '/')
  1262. {
  1263. if (strlen (fe->linkname) >= MC_MAXPATHLEN)
  1264. break;
  1265. strcpy (tmp, fe->linkname);
  1266. }
  1267. else
  1268. {
  1269. /* at this point tmp looks always like this
  1270. /directory/filename, i.e. no need to check
  1271. strrchr's return value */
  1272. *(strrchr (tmp, '/') + 1) = '\0'; /* dirname */
  1273. if ((strlen (tmp) + strlen (fe->linkname)) >= MC_MAXPATHLEN)
  1274. break;
  1275. strcat (tmp, fe->linkname);
  1276. }
  1277. continue;
  1278. }
  1279. else
  1280. {
  1281. fel->l_stat = g_new (struct stat, 1);
  1282. if (S_ISLNK (fe->s.st_mode))
  1283. *fel->l_stat = *fe->l_stat;
  1284. else
  1285. *fel->l_stat = fe->s;
  1286. (*fel->l_stat).st_ino = bucket->__inode_counter++;
  1287. }
  1288. }
  1289. break;
  1290. }
  1291. }
  1292. }
  1293. dir->symlink_status = FTPFS_RESOLVED_SYMLINKS;
  1294. }
  1295. /* --------------------------------------------------------------------------------------------- */
  1296. static void
  1297. resolve_symlink_with_ls_options (struct vfs_class *me, struct vfs_s_super *super,
  1298. struct vfs_s_inode *dir)
  1299. {
  1300. char buffer[2048] = "", *filename;
  1301. int sock;
  1302. FILE *fp;
  1303. struct stat s;
  1304. struct linklist *flist;
  1305. struct direntry *fe;
  1306. int switch_method = 0;
  1307. dir->symlink_status = FTPFS_RESOLVED_SYMLINKS;
  1308. if (strchr (dir->remote_path, ' '))
  1309. {
  1310. if (ftpfs_chdir_internal (bucket, dir->remote_path) != COMPLETE)
  1311. {
  1312. print_vfs_message (_("ftpfs: CWD failed."));
  1313. return;
  1314. }
  1315. sock = ftpfs_open_data_connection (bucket, "LIST -lLa", ".", TYPE_ASCII, 0);
  1316. }
  1317. else
  1318. sock = ftpfs_open_data_connection (bucket, "LIST -lLa", dir->remote_path, TYPE_ASCII, 0);
  1319. if (sock == -1)
  1320. {
  1321. print_vfs_message (_("ftpfs: couldn't resolve symlink"));
  1322. return;
  1323. }
  1324. fp = fdopen (sock, "r");
  1325. if (fp == NULL)
  1326. {
  1327. close (sock);
  1328. print_vfs_message (_("ftpfs: couldn't resolve symlink"));
  1329. return;
  1330. }
  1331. tty_enable_interrupt_key ();
  1332. flist = dir->file_list->next;
  1333. while (1)
  1334. {
  1335. do
  1336. {
  1337. if (flist == dir->file_list)
  1338. goto done;
  1339. fe = flist->data;
  1340. flist = flist->next;
  1341. }
  1342. while (!S_ISLNK (fe->s.st_mode));
  1343. while (1)
  1344. {
  1345. if (fgets (buffer, sizeof (buffer), fp) == NULL)
  1346. goto done;
  1347. if (MEDATA->logfile)
  1348. {
  1349. fputs (buffer, MEDATA->logfile);
  1350. fflush (MEDATA->logfile);
  1351. }
  1352. vfs_die ("This code should be commented out\n");
  1353. if (vfs_parse_ls_lga (buffer, &s, &filename, NULL))
  1354. {
  1355. int r = strcmp (fe->name, filename);
  1356. g_free (filename);
  1357. if (r == 0)
  1358. {
  1359. if (S_ISLNK (s.st_mode))
  1360. {
  1361. /* This server doesn't understand LIST -lLa */
  1362. switch_method = 1;
  1363. goto done;
  1364. }
  1365. fe->l_stat = g_new (struct stat, 1);
  1366. if (fe->l_stat == NULL)
  1367. goto done;
  1368. *fe->l_stat = s;
  1369. (*fe->l_stat).st_ino = bucket->__inode_counter++;
  1370. break;
  1371. }
  1372. if (r < 0)
  1373. break;
  1374. }
  1375. }
  1376. }
  1377. done:
  1378. while (fgets (buffer, sizeof (buffer), fp) != NULL);
  1379. tty_disable_interrupt_key ();
  1380. fclose (fp);
  1381. ftpfs_get_reply (me, SUP.sock, NULL, 0);
  1382. }
  1383. /* --------------------------------------------------------------------------------------------- */
  1384. static void
  1385. resolve_symlink (struct vfs_class *me, struct vfs_s_super *super, struct vfs_s_inode *dir)
  1386. {
  1387. print_vfs_message (_("Resolving symlink..."));
  1388. if (SUP.strict_rfc959_list_cmd)
  1389. resolve_symlink_without_ls_options (me, super, dir);
  1390. else
  1391. resolve_symlink_with_ls_options (me, super, dir);
  1392. }
  1393. #endif
  1394. /* --------------------------------------------------------------------------------------------- */
  1395. static int
  1396. ftpfs_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
  1397. {
  1398. struct vfs_s_entry *ent;
  1399. struct vfs_s_super *super = dir->super;
  1400. int sock, num_entries = 0;
  1401. char lc_buffer[BUF_8K];
  1402. int cd_first;
  1403. cd_first = ftpfs_first_cd_then_ls || (SUP.strict == RFC_STRICT)
  1404. || (strchr (remote_path, ' ') != NULL);
  1405. again:
  1406. print_vfs_message (_("ftpfs: Reading FTP directory %s... %s%s"),
  1407. remote_path,
  1408. SUP.strict ==
  1409. RFC_STRICT ? _("(strict rfc959)") : "", cd_first ? _("(chdir first)") : "");
  1410. if (cd_first)
  1411. {
  1412. if (ftpfs_chdir_internal (me, super, remote_path) != COMPLETE)
  1413. {
  1414. ftpfs_errno = ENOENT;
  1415. print_vfs_message (_("ftpfs: CWD failed."));
  1416. return -1;
  1417. }
  1418. }
  1419. gettimeofday (&dir->timestamp, NULL);
  1420. dir->timestamp.tv_sec += ftpfs_directory_timeout;
  1421. if (SUP.strict == RFC_STRICT)
  1422. sock = ftpfs_open_data_connection (me, super, "LIST", 0, TYPE_ASCII, 0);
  1423. else if (cd_first)
  1424. /* Dirty hack to avoid autoprepending / to . */
  1425. /* Wu-ftpd produces strange output for '/' if 'LIST -la .' used */
  1426. sock = ftpfs_open_data_connection (me, super, "LIST -la", 0, TYPE_ASCII, 0);
  1427. else
  1428. {
  1429. /* Trailing "/." is necessary if remote_path is a symlink */
  1430. char *path = concat_dir_and_file (remote_path, ".");
  1431. sock = ftpfs_open_data_connection (me, super, "LIST -la", path, TYPE_ASCII, 0);
  1432. g_free (path);
  1433. }
  1434. if (sock == -1)
  1435. goto fallback;
  1436. /* Clear the interrupt flag */
  1437. tty_enable_interrupt_key ();
  1438. vfs_parse_ls_lga_init ();
  1439. while (1)
  1440. {
  1441. int i;
  1442. size_t count_spaces = 0;
  1443. int res = vfs_s_get_line_interruptible (me, lc_buffer, sizeof (lc_buffer),
  1444. sock);
  1445. if (!res)
  1446. break;
  1447. if (res == EINTR)
  1448. {
  1449. me->verrno = ECONNRESET;
  1450. close (sock);
  1451. tty_disable_interrupt_key ();
  1452. ftpfs_get_reply (me, SUP.sock, NULL, 0);
  1453. print_vfs_message (_("%s: failure"), me->name);
  1454. return -1;
  1455. }
  1456. if (MEDATA->logfile)
  1457. {
  1458. fputs (lc_buffer, MEDATA->logfile);
  1459. fputs ("\n", MEDATA->logfile);
  1460. fflush (MEDATA->logfile);
  1461. }
  1462. ent = vfs_s_generate_entry (me, NULL, dir, 0);
  1463. i = ent->ino->st.st_nlink;
  1464. if (!vfs_parse_ls_lga
  1465. (lc_buffer, &ent->ino->st, &ent->name, &ent->ino->linkname, &count_spaces))
  1466. {
  1467. vfs_s_free_entry (me, ent);
  1468. continue;
  1469. }
  1470. ent->ino->st.st_nlink = i; /* Ouch, we need to preserve our counts :-( */
  1471. num_entries++;
  1472. vfs_s_store_filename_leading_spaces (ent, count_spaces);
  1473. vfs_s_insert_entry (me, dir, ent);
  1474. }
  1475. close (sock);
  1476. me->verrno = E_REMOTE;
  1477. if ((ftpfs_get_reply (me, SUP.sock, NULL, 0) != COMPLETE))
  1478. goto fallback;
  1479. if (num_entries == 0 && cd_first == 0)
  1480. {
  1481. /* The LIST command may produce an empty output. In such scenario
  1482. it is not clear whether this is caused by `remote_path' being
  1483. a non-existent path or for some other reason (listing emtpy
  1484. directory without the -a option, non-readable directory, etc.).
  1485. Since `dir_load' is a crucial method, when it comes to determine
  1486. whether a given path is a _directory_, the code must try its best
  1487. to determine the type of `remote_path'. The only reliable way to
  1488. achieve this is trough issuing a CWD command. */
  1489. cd_first = 1;
  1490. goto again;
  1491. }
  1492. vfs_s_normalize_filename_leading_spaces (dir, vfs_parse_ls_lga_get_final_spaces ());
  1493. if (SUP.strict == RFC_AUTODETECT)
  1494. SUP.strict = RFC_DARING;
  1495. print_vfs_message (_("%s: done."), me->name);
  1496. return 0;
  1497. fallback:
  1498. if (SUP.strict == RFC_AUTODETECT)
  1499. {
  1500. /* It's our first attempt to get a directory listing from this
  1501. server (UNIX style LIST command) */
  1502. SUP.strict = RFC_STRICT;
  1503. /* I hate goto, but recursive call needs another 8K on stack */
  1504. /* return ftpfs_dir_load (me, dir, remote_path); */
  1505. cd_first = 1;
  1506. goto again;
  1507. }
  1508. print_vfs_message (_("ftpfs: failed; nowhere to fallback to"));
  1509. ERRNOR (EACCES, -1);
  1510. }
  1511. /* --------------------------------------------------------------------------------------------- */
  1512. static int
  1513. ftpfs_file_store (struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *localname)
  1514. {
  1515. int h, sock, n_read, n_written;
  1516. off_t n_stored;
  1517. #ifdef HAVE_STRUCT_LINGER_L_LINGER
  1518. struct linger li;
  1519. #else
  1520. int flag_one = 1;
  1521. #endif
  1522. char lc_buffer[8192];
  1523. struct stat s;
  1524. char *w_buf;
  1525. struct vfs_s_super *super = FH_SUPER;
  1526. h = open (localname, O_RDONLY);
  1527. if (h == -1)
  1528. ERRNOR (EIO, -1);
  1529. sock =
  1530. ftpfs_open_data_connection (me, super,
  1531. fh->u.ftp.append ? "APPE" : "STOR", name, TYPE_BINARY, 0);
  1532. if (sock < 0 || fstat (h, &s) == -1)
  1533. {
  1534. close (h);
  1535. return -1;
  1536. }
  1537. #ifdef HAVE_STRUCT_LINGER_L_LINGER
  1538. li.l_onoff = 1;
  1539. li.l_linger = 120;
  1540. setsockopt (sock, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof (li));
  1541. #else
  1542. setsockopt (sock, SOL_SOCKET, SO_LINGER, &flag_one, sizeof (flag_one));
  1543. #endif
  1544. n_stored = 0;
  1545. tty_enable_interrupt_key ();
  1546. while (1)
  1547. {
  1548. while ((n_read = read (h, lc_buffer, sizeof (lc_buffer))) == -1)
  1549. {
  1550. if (errno == EINTR)
  1551. {
  1552. if (tty_got_interrupt ())
  1553. {
  1554. ftpfs_errno = EINTR;
  1555. goto error_return;
  1556. }
  1557. else
  1558. continue;
  1559. }
  1560. ftpfs_errno = errno;
  1561. goto error_return;
  1562. }
  1563. if (n_read == 0)
  1564. break;
  1565. n_stored += n_read;
  1566. w_buf = lc_buffer;
  1567. while ((n_written = write (sock, w_buf, n_read)) != n_read)
  1568. {
  1569. if (n_written == -1)
  1570. {
  1571. if (errno == EINTR && !tty_got_interrupt ())
  1572. {
  1573. continue;
  1574. }
  1575. ftpfs_errno = errno;
  1576. goto error_return;
  1577. }
  1578. w_buf += n_written;
  1579. n_read -= n_written;
  1580. }
  1581. print_vfs_message ("%s: %" PRIuMAX "/%" PRIuMAX,
  1582. _("ftpfs: storing file"), (uintmax_t) n_stored, (uintmax_t) s.st_size);
  1583. }
  1584. tty_disable_interrupt_key ();
  1585. close (sock);
  1586. close (h);
  1587. if (ftpfs_get_reply (me, SUP.sock, NULL, 0) != COMPLETE)
  1588. ERRNOR (EIO, -1);
  1589. return 0;
  1590. error_return:
  1591. tty_disable_interrupt_key ();
  1592. close (sock);
  1593. close (h);
  1594. ftpfs_get_reply (me, SUP.sock, NULL, 0);
  1595. return -1;
  1596. }
  1597. /* --------------------------------------------------------------------------------------------- */
  1598. static int
  1599. ftpfs_linear_start (struct vfs_class *me, struct vfs_s_fh *fh, off_t offset)
  1600. {
  1601. char *name = vfs_s_fullpath (me, fh->ino);
  1602. if (!name)
  1603. return 0;
  1604. FH_SOCK = ftpfs_open_data_connection (me, FH_SUPER, "RETR", name, TYPE_BINARY, offset);
  1605. g_free (name);
  1606. if (FH_SOCK == -1)
  1607. ERRNOR (EACCES, 0);
  1608. fh->linear = LS_LINEAR_OPEN;
  1609. FH_SUPER->u.ftp.ctl_connection_busy = 1;
  1610. fh->u.ftp.append = 0;
  1611. return 1;
  1612. }
  1613. /* --------------------------------------------------------------------------------------------- */
  1614. static int
  1615. ftpfs_linear_read (struct vfs_class *me, struct vfs_s_fh *fh, void *buf, size_t len)
  1616. {
  1617. ssize_t n;
  1618. struct vfs_s_super *super = FH_SUPER;
  1619. while ((n = read (FH_SOCK, buf, len)) < 0)
  1620. {
  1621. if ((errno == EINTR) && !tty_got_interrupt ())
  1622. continue;
  1623. break;
  1624. }
  1625. if (n < 0)
  1626. ftpfs_linear_abort (me, fh);
  1627. if (n == 0)
  1628. {
  1629. SUP.ctl_connection_busy = 0;
  1630. close (FH_SOCK);
  1631. FH_SOCK = -1;
  1632. if ((ftpfs_get_reply (me, SUP.sock, NULL, 0) != COMPLETE))
  1633. ERRNOR (E_REMOTE, -1);
  1634. return 0;
  1635. }
  1636. ERRNOR (errno, n);
  1637. }
  1638. /* --------------------------------------------------------------------------------------------- */
  1639. static void
  1640. ftpfs_linear_close (struct vfs_class *me, struct vfs_s_fh *fh)
  1641. {
  1642. if (FH_SOCK != -1)
  1643. ftpfs_linear_abort (me, fh);
  1644. }
  1645. /* --------------------------------------------------------------------------------------------- */
  1646. static int
  1647. ftpfs_ctl (void *fh, int ctlop, void *arg)
  1648. {
  1649. (void) arg;
  1650. switch (ctlop)
  1651. {
  1652. case VFS_CTL_IS_NOTREADY:
  1653. {
  1654. int v;
  1655. if (!FH->linear)
  1656. vfs_die ("You may not do this");
  1657. if (FH->linear == LS_LINEAR_CLOSED || FH->linear == LS_LINEAR_PREOPEN)
  1658. return 0;
  1659. v = vfs_s_select_on_two (FH->u.ftp.sock, 0);
  1660. if (((v < 0) && (errno == EINTR)) || v == 0)
  1661. return 1;
  1662. return 0;
  1663. }
  1664. default:
  1665. return 0;
  1666. }
  1667. }
  1668. /* --------------------------------------------------------------------------------------------- */
  1669. static int
  1670. ftpfs_send_command (struct vfs_class *me, const char *filename, const char *cmd, int flags)
  1671. {
  1672. const char *rpath;
  1673. char *p, *mpath = g_strdup (filename);
  1674. struct vfs_s_super *super;
  1675. int r;
  1676. int flush_directory_cache = (flags & OPT_FLUSH);
  1677. rpath = vfs_s_get_path_mangle (me, mpath, &super, 0);
  1678. if (rpath == NULL)
  1679. {
  1680. g_free (mpath);
  1681. return -1;
  1682. }
  1683. p = ftpfs_translate_path (me, super, rpath);
  1684. r = ftpfs_command (me, super, WAIT_REPLY, cmd, p);
  1685. g_free (p);
  1686. vfs_stamp_create (&vfs_ftpfs_ops, super);
  1687. if (flags & OPT_IGNORE_ERROR)
  1688. r = COMPLETE;
  1689. if (r != COMPLETE)
  1690. {
  1691. me->verrno = EPERM;
  1692. g_free (mpath);
  1693. return -1;
  1694. }
  1695. if (flush_directory_cache)
  1696. vfs_s_invalidate (me, super);
  1697. g_free (mpath);
  1698. return 0;
  1699. }
  1700. /* --------------------------------------------------------------------------------------------- */
  1701. static int
  1702. ftpfs_chmod (struct vfs_class *me, const char *path, int mode)
  1703. {
  1704. char buf[BUF_SMALL];
  1705. int ret;
  1706. g_snprintf (buf, sizeof (buf), "SITE CHMOD %4.4o /%%s", mode & 07777);
  1707. ret = ftpfs_send_command (me, path, buf, OPT_FLUSH);
  1708. return ftpfs_ignore_chattr_errors ? 0 : ret;
  1709. }
  1710. /* --------------------------------------------------------------------------------------------- */
  1711. static int
  1712. ftpfs_chown (struct vfs_class *me, const char *path, uid_t owner, gid_t group)
  1713. {
  1714. #if 0
  1715. ftpfs_errno = EPERM;
  1716. return -1;
  1717. #else
  1718. /* Everyone knows it is not possible to chown remotely, so why bother them.
  1719. If someone's root, then copy/move will always try to chown it... */
  1720. (void) me;
  1721. (void) path;
  1722. (void) owner;
  1723. (void) group;
  1724. return 0;
  1725. #endif
  1726. }
  1727. /* --------------------------------------------------------------------------------------------- */
  1728. static int
  1729. ftpfs_unlink (struct vfs_class *me, const char *path)
  1730. {
  1731. return ftpfs_send_command (me, path, "DELE /%s", OPT_FLUSH);
  1732. }
  1733. /* --------------------------------------------------------------------------------------------- */
  1734. /* Return 1 if path is the same directory as the one we are in now */
  1735. static int
  1736. ftpfs_is_same_dir (struct vfs_class *me, struct vfs_s_super *super, const char *path)
  1737. {
  1738. (void) me;
  1739. if (!SUP.cwdir)
  1740. return 0;
  1741. if (strcmp (path, SUP.cwdir) == 0)
  1742. return 1;
  1743. return 0;
  1744. }
  1745. /* --------------------------------------------------------------------------------------------- */
  1746. static int
  1747. ftpfs_chdir_internal (struct vfs_class *me, struct vfs_s_super *super, const char *remote_path)
  1748. {
  1749. int r;
  1750. char *p;
  1751. if (!SUP.cwd_deferred && ftpfs_is_same_dir (me, super, remote_path))
  1752. return COMPLETE;
  1753. p = ftpfs_translate_path (me, super, remote_path);
  1754. r = ftpfs_command (me, super, WAIT_REPLY, "CWD /%s", p);
  1755. g_free (p);
  1756. if (r != COMPLETE)
  1757. {
  1758. ftpfs_errno = EIO;
  1759. }
  1760. else
  1761. {
  1762. g_free (SUP.cwdir);
  1763. SUP.cwdir = g_strdup (remote_path);
  1764. SUP.cwd_deferred = 0;
  1765. }
  1766. return r;
  1767. }
  1768. /* --------------------------------------------------------------------------------------------- */
  1769. static int
  1770. ftpfs_rename (struct vfs_class *me, const char *path1, const char *path2)
  1771. {
  1772. ftpfs_send_command (me, path1, "RNFR /%s", OPT_FLUSH);
  1773. return ftpfs_send_command (me, path2, "RNTO /%s", OPT_FLUSH);
  1774. }
  1775. /* --------------------------------------------------------------------------------------------- */
  1776. static int
  1777. ftpfs_mkdir (struct vfs_class *me, const char *path, mode_t mode)
  1778. {
  1779. (void) mode; /* FIXME: should be used */
  1780. return ftpfs_send_command (me, path, "MKD /%s", OPT_FLUSH);
  1781. }
  1782. /* --------------------------------------------------------------------------------------------- */
  1783. static int
  1784. ftpfs_rmdir (struct vfs_class *me, const char *path)
  1785. {
  1786. return ftpfs_send_command (me, path, "RMD /%s", OPT_FLUSH);
  1787. }
  1788. /* --------------------------------------------------------------------------------------------- */
  1789. static int
  1790. ftpfs_fh_open (struct vfs_class *me, struct vfs_s_fh *fh, int flags, mode_t mode)
  1791. {
  1792. (void) mode;
  1793. fh->u.ftp.append = 0;
  1794. /* File will be written only, so no need to retrieve it from ftp server */
  1795. if (((flags & O_WRONLY) == O_WRONLY) && !(flags & (O_RDONLY | O_RDWR)))
  1796. {
  1797. #ifdef HAVE_STRUCT_LINGER_L_LINGER
  1798. struct linger li;
  1799. #else
  1800. int li = 1;
  1801. #endif
  1802. char *name;
  1803. /* ftpfs_linear_start() called, so data will be written
  1804. * to local temporary file and stored to ftp server
  1805. * by vfs_s_close later
  1806. */
  1807. if (FH_SUPER->u.ftp.ctl_connection_busy)
  1808. {
  1809. if (!fh->ino->localname)
  1810. {
  1811. int handle = vfs_mkstemps (&fh->ino->localname, me->name,
  1812. fh->ino->ent->name);
  1813. if (handle == -1)
  1814. return -1;
  1815. close (handle);
  1816. fh->u.ftp.append = flags & O_APPEND;
  1817. }
  1818. return 0;
  1819. }
  1820. name = vfs_s_fullpath (me, fh->ino);
  1821. if (!name)
  1822. return -1;
  1823. fh->handle =
  1824. ftpfs_open_data_connection (me, fh->ino->super,
  1825. (flags & O_APPEND) ? "APPE" : "STOR", name, TYPE_BINARY, 0);
  1826. g_free (name);
  1827. if (fh->handle < 0)
  1828. return -1;
  1829. #ifdef HAVE_STRUCT_LINGER_L_LINGER
  1830. li.l_onoff = 1;
  1831. li.l_linger = 120;
  1832. #endif
  1833. setsockopt (fh->handle, SOL_SOCKET, SO_LINGER, &li, sizeof (li));
  1834. if (fh->ino->localname)
  1835. {
  1836. unlink (fh->ino->localname);
  1837. g_free (fh->ino->localname);
  1838. fh->ino->localname = NULL;
  1839. }
  1840. return 0;
  1841. }
  1842. if (!fh->ino->localname)
  1843. if (vfs_s_retrieve_file (me, fh->ino) == -1)
  1844. return -1;
  1845. if (!fh->ino->localname)
  1846. vfs_die ("retrieve_file failed to fill in localname");
  1847. return 0;
  1848. }
  1849. /* --------------------------------------------------------------------------------------------- */
  1850. static int
  1851. ftpfs_fh_close (struct vfs_class *me, struct vfs_s_fh *fh)
  1852. {
  1853. if (fh->handle != -1 && !fh->ino->localname)
  1854. {
  1855. close (fh->handle);
  1856. fh->handle = -1;
  1857. /* File is stored to destination already, so
  1858. * we prevent MEDATA->ftpfs_file_store() call from vfs_s_close ()
  1859. */
  1860. fh->changed = 0;
  1861. if (ftpfs_get_reply (me, fh->ino->SUP.sock, NULL, 0) != COMPLETE)
  1862. ERRNOR (EIO, -1);
  1863. vfs_s_invalidate (me, FH_SUPER);
  1864. }
  1865. return 0;
  1866. }
  1867. /* --------------------------------------------------------------------------------------------- */
  1868. static void
  1869. ftpfs_done (struct vfs_class *me)
  1870. {
  1871. struct no_proxy_entry *np;
  1872. (void) me;
  1873. while (no_proxy)
  1874. {
  1875. np = no_proxy->next;
  1876. g_free (no_proxy->domain);
  1877. g_free (no_proxy);
  1878. no_proxy = np;
  1879. }
  1880. g_free (ftpfs_anonymous_passwd);
  1881. g_free (ftpfs_proxy_host);
  1882. }
  1883. /* --------------------------------------------------------------------------------------------- */
  1884. static void
  1885. ftpfs_fill_names (struct vfs_class *me, fill_names_f func)
  1886. {
  1887. struct vfs_s_super *super = MEDATA->supers;
  1888. char *name;
  1889. while (super)
  1890. {
  1891. name = g_strconcat ("/#ftp:", SUP.user, "@", SUP.host, "/", SUP.cwdir, (char *) NULL);
  1892. (*func) (name);
  1893. g_free (name);
  1894. super = super->next;
  1895. }
  1896. }
  1897. /* --------------------------------------------------------------------------------------------- */
  1898. static keyword_t
  1899. ftpfs_netrc_next (void)
  1900. {
  1901. char *p;
  1902. keyword_t i;
  1903. static const char *const keywords[] = { "default", "machine",
  1904. "login", "password", "passwd", "account", "macdef", NULL
  1905. };
  1906. while (1)
  1907. {
  1908. netrcp = skip_separators (netrcp);
  1909. if (*netrcp != '\n')
  1910. break;
  1911. netrcp++;
  1912. }
  1913. if (!*netrcp)
  1914. return NETRC_NONE;
  1915. p = buffer;
  1916. if (*netrcp == '"')
  1917. {
  1918. for (netrcp++; *netrcp != '"' && *netrcp; netrcp++)
  1919. {
  1920. if (*netrcp == '\\')
  1921. netrcp++;
  1922. *p++ = *netrcp;
  1923. }
  1924. }
  1925. else
  1926. {
  1927. for (; *netrcp != '\n' && *netrcp != '\t' && *netrcp != ' ' &&
  1928. *netrcp != ',' && *netrcp; netrcp++)
  1929. {
  1930. if (*netrcp == '\\')
  1931. netrcp++;
  1932. *p++ = *netrcp;
  1933. }
  1934. }
  1935. *p = 0;
  1936. if (!*buffer)
  1937. return NETRC_NONE;
  1938. i = NETRC_DEFAULT;
  1939. while (keywords[i - 1])
  1940. {
  1941. if (!strcmp (keywords[i - 1], buffer))
  1942. return i;
  1943. i++;
  1944. }
  1945. return NETRC_UNKNOWN;
  1946. }
  1947. /* --------------------------------------------------------------------------------------------- */
  1948. static int
  1949. ftpfs_netrc_bad_mode (const char *netrcname)
  1950. {
  1951. static int be_angry = 1;
  1952. struct stat mystat;
  1953. if (stat (netrcname, &mystat) >= 0 && (mystat.st_mode & 077))
  1954. {
  1955. if (be_angry)
  1956. {
  1957. message (D_ERROR, MSG_ERROR,
  1958. _("~/.netrc file has incorrect mode\nRemove password or correct mode"));
  1959. be_angry = 0;
  1960. }
  1961. return 1;
  1962. }
  1963. return 0;
  1964. }
  1965. /* --------------------------------------------------------------------------------------------- */
  1966. /* Scan .netrc until we find matching "machine" or "default"
  1967. * domain is used for additional matching
  1968. * No search is done after "default" in compliance with "man netrc"
  1969. * Return 0 if found, -1 otherwise */
  1970. static int
  1971. ftpfs_find_machine (const char *host, const char *domain)
  1972. {
  1973. keyword_t keyword;
  1974. if (!host)
  1975. host = "";
  1976. if (!domain)
  1977. domain = "";
  1978. while ((keyword = ftpfs_netrc_next ()) != NETRC_NONE)
  1979. {
  1980. if (keyword == NETRC_DEFAULT)
  1981. return 0;
  1982. if (keyword == NETRC_MACDEF)
  1983. {
  1984. /* Scan for an empty line, which concludes "macdef" */
  1985. do
  1986. {
  1987. while (*netrcp && *netrcp != '\n')
  1988. netrcp++;
  1989. if (*netrcp != '\n')
  1990. break;
  1991. netrcp++;
  1992. }
  1993. while (*netrcp && *netrcp != '\n');
  1994. continue;
  1995. }
  1996. if (keyword != NETRC_MACHINE)
  1997. continue;
  1998. /* Take machine name */
  1999. if (ftpfs_netrc_next () == NETRC_NONE)
  2000. break;
  2001. if (g_ascii_strcasecmp (host, buffer) != 0)
  2002. {
  2003. /* Try adding our domain to short names in .netrc */
  2004. const char *host_domain = strchr (host, '.');
  2005. if (!host_domain)
  2006. continue;
  2007. /* Compare domain part */
  2008. if (g_ascii_strcasecmp (host_domain, domain) != 0)
  2009. continue;
  2010. /* Compare local part */
  2011. if (g_ascii_strncasecmp (host, buffer, host_domain - host) != 0)
  2012. continue;
  2013. }
  2014. return 0;
  2015. }
  2016. /* end of .netrc */
  2017. return -1;
  2018. }
  2019. /* --------------------------------------------------------------------------------------------- */
  2020. /* Extract login and password from .netrc for the host.
  2021. * pass may be NULL.
  2022. * Returns 0 for success, -1 for error */
  2023. static int
  2024. ftpfs_netrc_lookup (const char *host, char **login, char **pass)
  2025. {
  2026. char *netrcname;
  2027. char *tmp_pass = NULL;
  2028. char hostname[MAXHOSTNAMELEN];
  2029. const char *domain;
  2030. keyword_t keyword;
  2031. static struct rupcache
  2032. {
  2033. struct rupcache *next;
  2034. char *host;
  2035. char *login;
  2036. char *pass;
  2037. } *rup_cache = NULL, *rupp;
  2038. /* Initialize *login and *pass */
  2039. if (!login)
  2040. return 0;
  2041. *login = NULL;
  2042. if (pass)
  2043. *pass = NULL;
  2044. /* Look up in the cache first */
  2045. for (rupp = rup_cache; rupp != NULL; rupp = rupp->next)
  2046. {
  2047. if (!strcmp (host, rupp->host))
  2048. {
  2049. if (rupp->login)
  2050. *login = g_strdup (rupp->login);
  2051. if (pass && rupp->pass)
  2052. *pass = g_strdup (rupp->pass);
  2053. return 0;
  2054. }
  2055. }
  2056. /* Load current .netrc */
  2057. netrcname = g_build_filename (home_dir, ".netrc", (char *) NULL);
  2058. if (!g_file_get_contents (netrcname, &netrc, NULL, NULL))
  2059. {
  2060. g_free (netrcname);
  2061. return 0;
  2062. }
  2063. netrcp = netrc;
  2064. /* Find our own domain name */
  2065. if (gethostname (hostname, sizeof (hostname)) < 0)
  2066. *hostname = '\0';
  2067. domain = strchr (hostname, '.');
  2068. if (domain == NULL)
  2069. domain = "";
  2070. /* Scan for "default" and matching "machine" keywords */
  2071. ftpfs_find_machine (host, domain);
  2072. /* Scan for keywords following "default" and "machine" */
  2073. while (1)
  2074. {
  2075. int need_break = 0;
  2076. keyword = ftpfs_netrc_next ();
  2077. switch (keyword)
  2078. {
  2079. case NETRC_LOGIN:
  2080. if (ftpfs_netrc_next () == NETRC_NONE)
  2081. {
  2082. need_break = 1;
  2083. break;
  2084. }
  2085. /* We have another name already - should not happen */
  2086. if (*login)
  2087. {
  2088. need_break = 1;
  2089. break;
  2090. }
  2091. /* We have login name now */
  2092. *login = g_strdup (buffer);
  2093. break;
  2094. case NETRC_PASSWORD:
  2095. case NETRC_PASSWD:
  2096. if (ftpfs_netrc_next () == NETRC_NONE)
  2097. {
  2098. need_break = 1;
  2099. break;
  2100. }
  2101. /* Ignore unsafe passwords */
  2102. if (strcmp (*login, "anonymous") && strcmp (*login, "ftp")
  2103. && ftpfs_netrc_bad_mode (netrcname))
  2104. {
  2105. need_break = 1;
  2106. break;
  2107. }
  2108. /* Remember password. pass may be NULL, so use tmp_pass */
  2109. if (tmp_pass == NULL)
  2110. tmp_pass = g_strdup (buffer);
  2111. break;
  2112. case NETRC_ACCOUNT:
  2113. /* "account" is followed by a token which we ignore */
  2114. if (ftpfs_netrc_next () == NETRC_NONE)
  2115. {
  2116. need_break = 1;
  2117. break;
  2118. }
  2119. /* Ignore account, but warn user anyways */
  2120. ftpfs_netrc_bad_mode (netrcname);
  2121. break;
  2122. default:
  2123. /* Unexpected keyword or end of file */
  2124. need_break = 1;
  2125. break;
  2126. }
  2127. if (need_break)
  2128. break;
  2129. }
  2130. g_free (netrc);
  2131. g_free (netrcname);
  2132. rupp = g_new (struct rupcache, 1);
  2133. rupp->host = g_strdup (host);
  2134. rupp->login = rupp->pass = 0;
  2135. if (*login != NULL)
  2136. {
  2137. rupp->login = g_strdup (*login);
  2138. }
  2139. if (tmp_pass != NULL)
  2140. rupp->pass = g_strdup (tmp_pass);
  2141. rupp->next = rup_cache;
  2142. rup_cache = rupp;
  2143. if (pass)
  2144. *pass = tmp_pass;
  2145. return 0;
  2146. }
  2147. /* --------------------------------------------------------------------------------------------- */
  2148. /*** public functions ****************************************************************************/
  2149. /* --------------------------------------------------------------------------------------------- */
  2150. /** This routine is called as the last step in load_setup */
  2151. void
  2152. ftpfs_init_passwd (void)
  2153. {
  2154. ftpfs_anonymous_passwd = load_anon_passwd ();
  2155. if (ftpfs_anonymous_passwd)
  2156. return;
  2157. /* If there is no anonymous ftp password specified
  2158. * then we'll just use anonymous@
  2159. * We don't send any other thing because:
  2160. * - We want to remain anonymous
  2161. * - We want to stop SPAM
  2162. * - We don't want to let ftp sites to discriminate by the user,
  2163. * host or country.
  2164. */
  2165. ftpfs_anonymous_passwd = g_strdup ("anonymous@");
  2166. }
  2167. /* --------------------------------------------------------------------------------------------- */
  2168. void
  2169. init_ftpfs (void)
  2170. {
  2171. static struct vfs_s_subclass ftpfs_subclass;
  2172. tcp_init ();
  2173. ftpfs_subclass.flags = VFS_S_REMOTE;
  2174. ftpfs_subclass.archive_same = ftpfs_archive_same;
  2175. ftpfs_subclass.open_archive = ftpfs_open_archive;
  2176. ftpfs_subclass.free_archive = ftpfs_free_archive;
  2177. ftpfs_subclass.fh_open = ftpfs_fh_open;
  2178. ftpfs_subclass.fh_close = ftpfs_fh_close;
  2179. ftpfs_subclass.dir_load = ftpfs_dir_load;
  2180. ftpfs_subclass.file_store = ftpfs_file_store;
  2181. ftpfs_subclass.linear_start = ftpfs_linear_start;
  2182. ftpfs_subclass.linear_read = ftpfs_linear_read;
  2183. ftpfs_subclass.linear_close = ftpfs_linear_close;
  2184. vfs_s_init_class (&vfs_ftpfs_ops, &ftpfs_subclass);
  2185. vfs_ftpfs_ops.name = "ftpfs";
  2186. vfs_ftpfs_ops.flags = VFSF_NOLINKS;
  2187. vfs_ftpfs_ops.prefix = "ftp:";
  2188. vfs_ftpfs_ops.done = &ftpfs_done;
  2189. vfs_ftpfs_ops.fill_names = ftpfs_fill_names;
  2190. vfs_ftpfs_ops.chmod = ftpfs_chmod;
  2191. vfs_ftpfs_ops.chown = ftpfs_chown;
  2192. vfs_ftpfs_ops.unlink = ftpfs_unlink;
  2193. vfs_ftpfs_ops.rename = ftpfs_rename;
  2194. vfs_ftpfs_ops.mkdir = ftpfs_mkdir;
  2195. vfs_ftpfs_ops.rmdir = ftpfs_rmdir;
  2196. vfs_ftpfs_ops.ctl = ftpfs_ctl;
  2197. vfs_register_class (&vfs_ftpfs_ops);
  2198. }
  2199. /* --------------------------------------------------------------------------------------------- */