smbfs.c 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235
  1. /* Virtual File System: Midnight Commander file system.
  2. Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
  3. Free Software Foundation, Inc.
  4. Written by Wayne Roberts <wroberts1@home.com>, 1997
  5. Andrew V. Samoilov <sav@bcs.zp.ua> 2002, 2003
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU Library General Public License
  8. as published by the Free Software Foundation; either version 2 of
  9. the License, or (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU Library General Public License for more details.
  14. You should have received a copy of the GNU Library General Public
  15. License along with this program; if not, write to the Free Software
  16. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
  17. /**
  18. * \file
  19. * \brief Source: Virtual File System: smb file system
  20. * \author Wayne Roberts <wroberts1@home.com>
  21. * \author Andrew V. Samoilov <sav@bcs.zp.ua>
  22. * \date 1997, 2002, 2003
  23. *
  24. * Namespace: exports init_smbfs, smbfs_set_debug(), smbfs_set_debugf()
  25. */
  26. #include <config.h>
  27. #include <stdio.h>
  28. #include <sys/types.h>
  29. #undef USE_NCURSES /* Don't include *curses.h */
  30. #undef USE_NCURSESW
  31. #include <string.h>
  32. #include "lib/global.h"
  33. #include "lib/strutil.h"
  34. #include "lib/util.h"
  35. #include "lib/widget.h" /* message() */
  36. #undef PACKAGE_BUGREPORT
  37. #undef PACKAGE_NAME
  38. #undef PACKAGE_STRING
  39. #undef PACKAGE_TARNAME
  40. #undef PACKAGE_VERSION
  41. #include "samba/include/config.h"
  42. /* don't load crap in "samba/include/includes.h" we don't use and which
  43. conflicts with definitions in other includes */
  44. #undef HAVE_LIBREADLINE
  45. #define NO_CONFIG_H
  46. #undef VERSION
  47. #include "samba/include/includes.h"
  48. #include "vfs-impl.h"
  49. #include "netutil.h"
  50. #include "utilvfs.h"
  51. #include "smbfs.h"
  52. /*** global variables ****************************************************************************/
  53. extern int DEBUGLEVEL;
  54. extern pstring myhostname;
  55. extern struct in_addr ipzero;
  56. extern pstring global_myname;
  57. extern pstring debugf;
  58. extern FILE *dbf;
  59. /*** file scope macro definitions ****************************************************************/
  60. #define SMBFS_MAX_CONNECTIONS 16
  61. #define HEADER_LEN 6
  62. #define CNV_LANG(s) dos_to_unix(s,False)
  63. #define GNAL_VNC(s) unix_to_dos(s,False)
  64. /* Extract the hostname and username from the path */
  65. /* path is in the form: [user@]hostname/share/remote-dir */
  66. #define smbfs_get_host_and_username(path, host, user, port, pass) \
  67. vfs_split_url (*path, host, user, port, pass, SMB_PORT, 0)
  68. #define smbfs_lstat smbfs_stat /* no symlinks on smb filesystem? */
  69. /*** file scope type declarations ****************************************************************/
  70. typedef struct _smbfs_connection smbfs_connection;
  71. typedef struct
  72. {
  73. struct cli_state *cli;
  74. int fnum;
  75. off_t nread;
  76. uint16 attr;
  77. } smbfs_handle;
  78. typedef struct dir_entry
  79. {
  80. char *text;
  81. struct dir_entry *next;
  82. struct stat my_stat;
  83. int merrno;
  84. } dir_entry;
  85. typedef struct
  86. {
  87. gboolean server_list;
  88. char *dirname;
  89. char *path; /* the dir originally passed to smbfs_opendir */
  90. smbfs_connection *conn;
  91. dir_entry *entries;
  92. dir_entry *current;
  93. } opendir_info;
  94. /*** file scope variables ************************************************************************/
  95. static const char *const IPC = "IPC$";
  96. static const char *const URL_HEADER = "/#smb:";
  97. static int my_errno;
  98. static uint32 err;
  99. /* stuff that is same with each connection */
  100. static mode_t myumask = 0755;
  101. static int smbfs_open_connections = 0;
  102. static gboolean got_user = FALSE;
  103. static gboolean got_pass = FALSE;
  104. static pstring password;
  105. static pstring username;
  106. static struct vfs_class vfs_smbfs_ops;
  107. static struct _smbfs_connection
  108. {
  109. struct cli_state *cli;
  110. struct in_addr dest_ip;
  111. BOOL have_ip;
  112. char *host; /* server name */
  113. char *service; /* share name */
  114. char *domain;
  115. char *user;
  116. char *home;
  117. char *password;
  118. int port;
  119. int name_type;
  120. time_t last_use;
  121. } smbfs_connections[SMBFS_MAX_CONNECTIONS];
  122. /* unique to each connection */
  123. static smbfs_connection *current_bucket;
  124. static GSList *auth_list;
  125. static opendir_info *previous_info, *current_info, *current_share_info, *current_server_info;
  126. static gboolean first_direntry;
  127. /* stat a single file, smbfs_get_remote_stat callback */
  128. static dir_entry *single_entry;
  129. /*** file scope functions ************************************************************************/
  130. /* --------------------------------------------------------------------------------------------- */
  131. /* modifies *share */
  132. static struct cli_state *smbfs_do_connect (const char *server, char *share);
  133. /* --------------------------------------------------------------------------------------------- */
  134. /* this function allows you to write:
  135. * char *s = g_strdup("hello, world");
  136. * s = free_after(g_strconcat(s, s, (char *)0), s);
  137. */
  138. static inline char *
  139. free_after (char *result, char *string_to_free)
  140. {
  141. g_free (string_to_free);
  142. return result;
  143. }
  144. /* --------------------------------------------------------------------------------------------- */
  145. static void
  146. smbfs_auth_free (struct smb_authinfo const *a)
  147. {
  148. g_free (a->host);
  149. g_free (a->share);
  150. g_free (a->domain);
  151. g_free (a->user);
  152. wipe_password (a->password);
  153. }
  154. /* --------------------------------------------------------------------------------------------- */
  155. static void
  156. smbfs_auth_free_all (void)
  157. {
  158. if (auth_list)
  159. {
  160. g_slist_foreach (auth_list, (GFunc) smbfs_auth_free, 0);
  161. g_slist_free (auth_list);
  162. auth_list = 0;
  163. }
  164. }
  165. /* --------------------------------------------------------------------------------------------- */
  166. static gint
  167. smbfs_auth_cmp_host_and_share (gconstpointer _a, gconstpointer _b)
  168. {
  169. struct smb_authinfo const *a = (struct smb_authinfo const *) _a;
  170. struct smb_authinfo const *b = (struct smb_authinfo const *) _b;
  171. if (!a->host || !a->share || !b->host || !b->share)
  172. return 1;
  173. if (strcmp (a->host, b->host) != 0)
  174. return 1;
  175. if (strcmp (a->share, b->share) != 0)
  176. return 1;
  177. return 0;
  178. }
  179. /* --------------------------------------------------------------------------------------------- */
  180. static gint
  181. smbfs_auth_cmp_host (gconstpointer _a, gconstpointer _b)
  182. {
  183. struct smb_authinfo const *a = (struct smb_authinfo const *) _a;
  184. struct smb_authinfo const *b = (struct smb_authinfo const *) _b;
  185. if (!a->host || !b->host)
  186. return 1;
  187. if (strcmp (a->host, b->host) != 0)
  188. return 1;
  189. if (strcmp (a->share, IPC) != 0)
  190. return 1;
  191. return 0;
  192. }
  193. /* --------------------------------------------------------------------------------------------- */
  194. static void
  195. smbfs_auth_add (const char *host, const char *share, const char *domain,
  196. const char *user, const char *pass)
  197. {
  198. struct smb_authinfo *auth;
  199. auth = vfs_smb_authinfo_new (host, share, domain, user, pass);
  200. if (auth != NULL)
  201. auth_list = g_slist_prepend (auth_list, auth);
  202. }
  203. /* --------------------------------------------------------------------------------------------- */
  204. static void
  205. smbfs_auth_remove (const char *host, const char *share)
  206. {
  207. struct smb_authinfo data;
  208. struct smb_authinfo *auth;
  209. GSList *list;
  210. data.host = g_strdup (host);
  211. data.share = g_strdup (share);
  212. list = g_slist_find_custom (auth_list, &data, smbfs_auth_cmp_host_and_share);
  213. g_free (data.host);
  214. g_free (data.share);
  215. if (!list)
  216. return;
  217. auth = list->data;
  218. auth_list = g_slist_remove (auth_list, auth);
  219. smbfs_auth_free (auth);
  220. }
  221. /* --------------------------------------------------------------------------------------------- */
  222. /* Set authentication information in bucket. Return 1 if successful, else 0 */
  223. /* Information in auth_list overrides user if pass is NULL. */
  224. /* bucket->host and bucket->service must be valid. */
  225. static int
  226. smbfs_bucket_set_authinfo (smbfs_connection * bucket,
  227. const char *domain, const char *user, const char *pass,
  228. int fallback_to_host)
  229. {
  230. struct smb_authinfo data;
  231. struct smb_authinfo *auth;
  232. GSList *list;
  233. if (domain && user && pass)
  234. {
  235. g_free (bucket->domain);
  236. g_free (bucket->user);
  237. g_free (bucket->password);
  238. bucket->domain = g_strdup (domain);
  239. bucket->user = g_strdup (user);
  240. bucket->password = g_strdup (pass);
  241. smbfs_auth_remove (bucket->host, bucket->service);
  242. smbfs_auth_add (bucket->host, bucket->service, domain, user, pass);
  243. return 1;
  244. }
  245. data.host = bucket->host;
  246. data.share = bucket->service;
  247. list = g_slist_find_custom (auth_list, &data, smbfs_auth_cmp_host_and_share);
  248. if (!list && fallback_to_host)
  249. list = g_slist_find_custom (auth_list, &data, smbfs_auth_cmp_host);
  250. if (list)
  251. {
  252. auth = list->data;
  253. bucket->domain = g_strdup (auth->domain);
  254. bucket->user = g_strdup (auth->user);
  255. bucket->password = g_strdup (auth->password);
  256. return 1;
  257. }
  258. if (got_pass)
  259. {
  260. bucket->domain = g_strdup (lp_workgroup ());
  261. bucket->user = g_strdup (got_user ? username : user);
  262. bucket->password = g_strdup (password);
  263. return 1;
  264. }
  265. auth = vfs_smb_get_authinfo (bucket->host,
  266. bucket->service, (domain ? domain : lp_workgroup ()), user);
  267. if (auth)
  268. {
  269. g_free (bucket->domain);
  270. g_free (bucket->user);
  271. g_free (bucket->password);
  272. bucket->domain = g_strdup (auth->domain);
  273. bucket->user = g_strdup (auth->user);
  274. bucket->password = g_strdup (auth->password);
  275. smbfs_auth_remove (bucket->host, bucket->service);
  276. auth_list = g_slist_prepend (auth_list, auth);
  277. return 1;
  278. }
  279. return 0;
  280. }
  281. /* --------------------------------------------------------------------------------------------- */
  282. void
  283. smbfs_set_debug (int arg)
  284. {
  285. DEBUGLEVEL = arg;
  286. }
  287. /* --------------------------------------------------------------------------------------------- */
  288. void
  289. smbfs_set_debugf (const char *filename)
  290. {
  291. if (DEBUGLEVEL > 0)
  292. {
  293. FILE *outfile = fopen (filename, "w");
  294. if (outfile)
  295. {
  296. setup_logging ("", True); /* No needs for timestamp for each message */
  297. dbf = outfile;
  298. setbuf (dbf, NULL);
  299. pstrcpy (debugf, filename);
  300. }
  301. }
  302. }
  303. /* --------------------------------------------------------------------------------------------- */
  304. /********************** The callbacks ******************************/
  305. static int
  306. smbfs_init (struct vfs_class *me)
  307. {
  308. const char *servicesf = CONFIGDIR PATH_SEP_STR "smb.conf";
  309. /* DEBUGLEVEL = 4; */
  310. TimeInit ();
  311. charset_initialise ();
  312. DEBUG (3, ("smbfs_init(%s)\n", me->name));
  313. if (!get_myname (myhostname, NULL))
  314. DEBUG (0, ("Failed to get my hostname.\n"));
  315. if (!lp_load (servicesf, True, False, False))
  316. DEBUG (0, ("Cannot load %s - run testparm to debug it\n", servicesf));
  317. codepage_initialise (lp_client_code_page ());
  318. load_interfaces ();
  319. myumask = umask (0);
  320. umask (myumask);
  321. myumask = ~myumask;
  322. if (getenv ("USER"))
  323. {
  324. char *p;
  325. pstrcpy (username, getenv ("USER"));
  326. got_user = TRUE;
  327. DEBUG (3, ("smbfs_init(): $USER:%s\n", username));
  328. if ((p = strchr (username, '%')))
  329. {
  330. *p = 0;
  331. pstrcpy (password, p + 1);
  332. got_pass = TRUE;
  333. memset (strchr (getenv ("USER"), '%') + 1, 'X', strlen (password));
  334. DEBUG (3, ("smbfs_init(): $USER%%pass: %s%%%s\n", username, password));
  335. }
  336. strupper (username);
  337. }
  338. if (getenv ("PASSWD"))
  339. {
  340. pstrcpy (password, getenv ("PASSWD"));
  341. got_pass = TRUE;
  342. }
  343. return 1;
  344. }
  345. /* --------------------------------------------------------------------------------------------- */
  346. static void
  347. smbfs_fill_names (struct vfs_class *me, fill_names_f func)
  348. {
  349. size_t i;
  350. char *path;
  351. (void) me;
  352. for (i = 0; i < SMBFS_MAX_CONNECTIONS; i++)
  353. {
  354. if (smbfs_connections[i].cli)
  355. {
  356. path = g_strconcat (URL_HEADER,
  357. smbfs_connections[i].user, "@",
  358. smbfs_connections[i].host,
  359. "/", smbfs_connections[i].service, (char *) NULL);
  360. (*func) (path);
  361. g_free (path);
  362. }
  363. }
  364. }
  365. /* --------------------------------------------------------------------------------------------- */
  366. /* does same as do_get() in client.c */
  367. /* called from vfs.c:1080, count = buffer size */
  368. static ssize_t
  369. smbfs_read (void *data, char *buffer, size_t count)
  370. {
  371. smbfs_handle *info = (smbfs_handle *) data;
  372. ssize_t n;
  373. DEBUG (3, ("smbfs_read(fnum:%d, nread:%d, count:%zu)\n", info->fnum, (int) info->nread, count));
  374. n = cli_read (info->cli, info->fnum, buffer, info->nread, count);
  375. if (n > 0)
  376. info->nread += n;
  377. return n;
  378. }
  379. /* --------------------------------------------------------------------------------------------- */
  380. static ssize_t
  381. smbfs_write (void *data, const char *buf, size_t nbyte)
  382. {
  383. smbfs_handle *info = (smbfs_handle *) data;
  384. ssize_t n;
  385. DEBUG (3, ("smbfs_write(fnum:%d, nread:%d, nbyte:%zu)\n",
  386. info->fnum, (int) info->nread, nbyte));
  387. n = cli_write (info->cli, info->fnum, 0, buf, info->nread, nbyte);
  388. if (n > 0)
  389. info->nread += n;
  390. return n;
  391. }
  392. /* --------------------------------------------------------------------------------------------- */
  393. static int
  394. smbfs_close (void *data)
  395. {
  396. smbfs_handle *info = (smbfs_handle *) data;
  397. DEBUG (3, ("smbfs_close(fnum:%d)\n", info->fnum));
  398. /* FIXME: Why too different cli have the same outbuf
  399. * if file is copied to share
  400. */
  401. if (info->cli->outbuf == NULL)
  402. {
  403. my_errno = EINVAL;
  404. return -1;
  405. }
  406. #if 0
  407. /* if imlementing archive_level: add rname to smbfs_handle */
  408. if (archive_level >= 2 && (inf->attr & aARCH))
  409. {
  410. cli_setatr (info->cli, rname, info->attr & ~(uint16) aARCH, 0);
  411. }
  412. #endif
  413. return (cli_close (info->cli, info->fnum) == True) ? 0 : -1;
  414. }
  415. /* --------------------------------------------------------------------------------------------- */
  416. static int
  417. smbfs_errno (struct vfs_class *me)
  418. {
  419. (void) me;
  420. DEBUG (3, ("smbfs_errno: %s\n", unix_error_string (my_errno)));
  421. return my_errno;
  422. }
  423. /* --------------------------------------------------------------------------------------------- */
  424. static dir_entry *
  425. smbfs_new_dir_entry (const char *name)
  426. {
  427. static int inode_counter;
  428. dir_entry *new_entry;
  429. new_entry = g_new0 (dir_entry, 1);
  430. new_entry->text = dos_to_unix (g_strdup (name), 1);
  431. if (first_direntry)
  432. {
  433. current_info->entries = new_entry;
  434. first_direntry = FALSE;
  435. }
  436. else
  437. {
  438. current_info->current->next = new_entry;
  439. }
  440. current_info->current = new_entry;
  441. new_entry->my_stat.st_ino = inode_counter++;
  442. return new_entry;
  443. }
  444. /* --------------------------------------------------------------------------------------------- */
  445. /* browse for shares on server */
  446. static void
  447. smbfs_browsing_helper (const char *name, uint32 type, const char *comment, void *state)
  448. {
  449. const char *typestr = "";
  450. dir_entry *new_entry = smbfs_new_dir_entry (name);
  451. (void) state;
  452. switch (type)
  453. {
  454. case STYPE_DISKTREE:
  455. typestr = "Disk";
  456. /* show this as dir */
  457. new_entry->my_stat.st_mode =
  458. (S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH) & myumask;
  459. break;
  460. case STYPE_PRINTQ:
  461. typestr = "Printer";
  462. break;
  463. case STYPE_DEVICE:
  464. typestr = "Device";
  465. break;
  466. case STYPE_IPC:
  467. typestr = "IPC";
  468. break;
  469. }
  470. DEBUG (3, ("\t%-15.15s%-10.10s%s\n", name, typestr, comment));
  471. }
  472. /* --------------------------------------------------------------------------------------------- */
  473. static void
  474. smbfs_loaddir_helper (file_info * finfo, const char *mask, void *entry)
  475. {
  476. dir_entry *new_entry = (dir_entry *) entry;
  477. time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
  478. (void) mask;
  479. #if 0 /* I want to see dot files */
  480. if (finfo->mode & aHIDDEN)
  481. return; /* don't bother with hidden files, "~$" screws up mc */
  482. #endif
  483. if (!entry)
  484. new_entry = smbfs_new_dir_entry (finfo->name);
  485. new_entry->my_stat.st_size = finfo->size;
  486. new_entry->my_stat.st_mtime = finfo->mtime;
  487. new_entry->my_stat.st_atime = finfo->atime;
  488. new_entry->my_stat.st_ctime = finfo->ctime;
  489. new_entry->my_stat.st_uid = finfo->uid;
  490. new_entry->my_stat.st_gid = finfo->gid;
  491. new_entry->my_stat.st_mode = /* rw-rw-rw */
  492. S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH;
  493. /* if (finfo->mode & aVOLID); nothing similar in real world */
  494. if (finfo->mode & aDIR)
  495. new_entry->my_stat.st_mode |= /* drwxrwxrwx */
  496. S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
  497. else
  498. new_entry->my_stat.st_mode |= S_IFREG; /* if not dir, regular file? */
  499. /* if (finfo->mode & aARCH); DOS archive */
  500. /* if (finfo->mode & aHIDDEN); like a dot file? */
  501. /* if (finfo->mode & aSYSTEM); like a kernel? */
  502. if (finfo->mode & aRONLY)
  503. new_entry->my_stat.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
  504. new_entry->my_stat.st_mode &= myumask;
  505. DEBUG (entry ? 3 : 6, (" %-30s%7.7s%8.0f %s",
  506. CNV_LANG (finfo->name),
  507. attrib_string (finfo->mode),
  508. (double) finfo->size, asctime (LocalTime (&t))));
  509. }
  510. /* --------------------------------------------------------------------------------------------- */
  511. /* takes "/foo/bar/file" and gives malloced "\\foo\\bar\\file" */
  512. static char *
  513. smbfs_convert_path (const char *remote_file, gboolean trailing_asterik)
  514. {
  515. const char *p, *my_remote;
  516. char *result;
  517. my_remote = remote_file;
  518. if (strncmp (my_remote, URL_HEADER, HEADER_LEN) == 0)
  519. { /* if passed directly */
  520. my_remote += HEADER_LEN;
  521. if (*my_remote == '/') /* from server browsing */
  522. my_remote++;
  523. p = strchr (my_remote, '/');
  524. if (p)
  525. my_remote = p + 1; /* advance to end of server name */
  526. }
  527. if (*my_remote == '/')
  528. my_remote++; /* strip off leading '/' */
  529. p = strchr (my_remote, '/');
  530. if (p)
  531. my_remote = p; /* strip off share/service name */
  532. /* create remote filename as understood by smb clientgen */
  533. result = g_strconcat (my_remote, trailing_asterik ? "/*" : "", (char *) NULL);
  534. unix_to_dos (result, /* inplace = */ 1); /* code page conversion */
  535. str_replace (result, '/', '\\');
  536. return result;
  537. }
  538. /* --------------------------------------------------------------------------------------------- */
  539. static void
  540. smbfs_srv_browsing_helper (const char *name, uint32 m, const char *comment, void *state)
  541. {
  542. dir_entry *new_entry = smbfs_new_dir_entry (name);
  543. (void) m;
  544. (void) state;
  545. /* show this as dir */
  546. new_entry->my_stat.st_mode =
  547. (S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH) & myumask;
  548. DEBUG (3, ("\t%-16.16s %s\n", name, comment));
  549. }
  550. /* --------------------------------------------------------------------------------------------- */
  551. static BOOL
  552. smbfs_reconnect (smbfs_connection * conn, int *retries)
  553. {
  554. char *host;
  555. DEBUG (3, ("RECONNECT\n"));
  556. if (*(conn->host) == 0)
  557. host = g_strdup (conn->cli->desthost); /* server browsing */
  558. else
  559. host = g_strdup (conn->host);
  560. cli_shutdown (conn->cli);
  561. if (!(conn->cli = smbfs_do_connect (host, conn->service)))
  562. {
  563. message (D_ERROR, MSG_ERROR, _("reconnect to %s failed"), conn->host);
  564. g_free (host);
  565. return False;
  566. }
  567. g_free (host);
  568. if (++(*retries) == 2)
  569. return False;
  570. return True;
  571. }
  572. /* --------------------------------------------------------------------------------------------- */
  573. static BOOL
  574. smbfs_send (struct cli_state *cli)
  575. {
  576. size_t len;
  577. size_t nwritten = 0;
  578. ssize_t ret;
  579. len = smb_len (cli->outbuf) + 4;
  580. while (nwritten < len)
  581. {
  582. ret = write_socket (cli->fd, cli->outbuf + nwritten, len - nwritten);
  583. if (ret <= 0)
  584. {
  585. if (errno == EPIPE)
  586. return False;
  587. }
  588. else
  589. nwritten += ret;
  590. }
  591. return True;
  592. }
  593. /* --------------------------------------------------------------------------------------------- */
  594. /****************************************************************************
  595. See if server has cut us off by checking for EPIPE when writing.
  596. Taken from cli_chkpath()
  597. ****************************************************************************/
  598. static BOOL
  599. smbfs_chkpath (struct cli_state *cli, const char *path, BOOL send_only)
  600. {
  601. fstring path2;
  602. char *p;
  603. fstrcpy (path2, path);
  604. unix_to_dos (path2, 1);
  605. trim_string (path2, NULL, "\\");
  606. if (!*path2)
  607. *path2 = '\\';
  608. memset (cli->outbuf, '\0', smb_size);
  609. set_message (cli->outbuf, 0, 4 + strlen (path2), True);
  610. SCVAL (cli->outbuf, smb_com, SMBchkpth);
  611. SSVAL (cli->outbuf, smb_tid, cli->cnum);
  612. cli->rap_error = 0;
  613. cli->nt_error = 0;
  614. SSVAL (cli->outbuf, smb_pid, cli->pid);
  615. SSVAL (cli->outbuf, smb_uid, cli->vuid);
  616. SSVAL (cli->outbuf, smb_mid, cli->mid);
  617. if (cli->protocol > PROTOCOL_CORE)
  618. {
  619. SCVAL (cli->outbuf, smb_flg, 0x8);
  620. SSVAL (cli->outbuf, smb_flg2, 0x1);
  621. }
  622. p = smb_buf (cli->outbuf);
  623. *p++ = 4;
  624. fstrcpy (p, path2);
  625. if (!smbfs_send (cli))
  626. {
  627. DEBUG (3, ("smbfs_chkpath: couldnt send\n"));
  628. return False;
  629. }
  630. if (send_only)
  631. {
  632. client_receive_smb (cli->fd, cli->inbuf, cli->timeout);
  633. DEBUG (3, ("smbfs_chkpath: send only OK\n"));
  634. return True; /* just testing for EPIPE */
  635. }
  636. if (!client_receive_smb (cli->fd, cli->inbuf, cli->timeout))
  637. {
  638. DEBUG (3, ("smbfs_chkpath: receive error\n"));
  639. return False;
  640. }
  641. if ((my_errno = cli_error (cli, NULL, NULL, NULL)))
  642. {
  643. if (my_errno == 20 || my_errno == 13)
  644. return True; /* ignore if 'not a directory' error */
  645. DEBUG (3, ("smbfs_chkpath: cli_error: %s\n", unix_error_string (my_errno)));
  646. return False;
  647. }
  648. return True;
  649. }
  650. /* --------------------------------------------------------------------------------------------- */
  651. #if 1
  652. static int
  653. smbfs_fs (const char *text)
  654. {
  655. const char *p = text;
  656. int count = 0;
  657. while ((p = strchr (p, '/')) != NULL)
  658. {
  659. count++;
  660. p++;
  661. }
  662. if (count == 1)
  663. return strlen (text);
  664. return count;
  665. }
  666. #endif
  667. /* --------------------------------------------------------------------------------------------- */
  668. static int
  669. smbfs_loaddir (opendir_info * smbfs_info)
  670. {
  671. uint16 attribute = aDIR | aSYSTEM | aHIDDEN;
  672. int servlen = strlen (smbfs_info->conn->service);
  673. const char *info_dirname = smbfs_info->dirname;
  674. char *my_dirname;
  675. DEBUG (3, ("smbfs_loaddir: dirname:%s\n", info_dirname));
  676. first_direntry = TRUE;
  677. if (current_info)
  678. {
  679. DEBUG (3, ("smbfs_loaddir: new:'%s', cached:'%s'\n", info_dirname, current_info->dirname));
  680. /* if new desired dir is longer than cached in current_info */
  681. if (smbfs_fs (info_dirname) > smbfs_fs (current_info->dirname))
  682. {
  683. DEBUG (3, ("saving to previous_info\n"));
  684. previous_info = current_info;
  685. }
  686. }
  687. current_info = smbfs_info;
  688. if (strcmp (info_dirname, "/") == 0)
  689. {
  690. if (!strcmp (smbfs_info->path, URL_HEADER))
  691. {
  692. DEBUG (6, ("smbfs_loaddir: browsing %s\n", IPC));
  693. /* browse for servers */
  694. if (!cli_NetServerEnum
  695. (smbfs_info->conn->cli, smbfs_info->conn->domain,
  696. SV_TYPE_ALL, smbfs_srv_browsing_helper, NULL))
  697. return 0;
  698. else
  699. current_server_info = smbfs_info;
  700. smbfs_info->server_list = TRUE;
  701. }
  702. else
  703. {
  704. /* browse for shares */
  705. if (cli_RNetShareEnum (smbfs_info->conn->cli, smbfs_browsing_helper, NULL) < 1)
  706. return 0;
  707. else
  708. current_share_info = smbfs_info;
  709. }
  710. goto done;
  711. }
  712. /* do regular directory listing */
  713. if (strncmp (smbfs_info->conn->service, info_dirname + 1, servlen) == 0)
  714. {
  715. /* strip share name from dir */
  716. my_dirname = g_strdup (info_dirname + servlen);
  717. *my_dirname = '/';
  718. my_dirname = free_after (smbfs_convert_path (my_dirname, TRUE), my_dirname);
  719. }
  720. else
  721. my_dirname = smbfs_convert_path (info_dirname, TRUE);
  722. DEBUG (6, ("smbfs_loaddir: service: %s\n", smbfs_info->conn->service));
  723. DEBUG (6, ("smbfs_loaddir: cli->share: %s\n", smbfs_info->conn->cli->share));
  724. DEBUG (6, ("smbfs_loaddir: calling cli_list with mask %s\n", my_dirname));
  725. /* do file listing: cli_list returns number of files */
  726. if (cli_list (smbfs_info->conn->cli, my_dirname, attribute, smbfs_loaddir_helper, NULL) < 0)
  727. {
  728. /* cli_list returns -1 if directory empty or cannot read socket */
  729. my_errno = cli_error (smbfs_info->conn->cli, NULL, &err, NULL);
  730. g_free (my_dirname);
  731. return 0;
  732. }
  733. if (*(my_dirname) == 0)
  734. smbfs_info->dirname = smbfs_info->conn->service;
  735. g_free (my_dirname);
  736. /* do_dskattr(); */
  737. done:
  738. /* current_info->parent = smbfs_info->dirname; */
  739. smbfs_info->current = smbfs_info->entries;
  740. return 1; /* 1 = ok */
  741. }
  742. /* --------------------------------------------------------------------------------------------- */
  743. #ifdef SMBFS_FREE_DIR
  744. static void
  745. smbfs_free_dir (dir_entry * de)
  746. {
  747. if (!de)
  748. return;
  749. smbfs_free_dir (de->next);
  750. g_free (de->text);
  751. g_free (de);
  752. }
  753. #endif
  754. /* --------------------------------------------------------------------------------------------- */
  755. /* The readdir routine loads the complete directory */
  756. /* It's too slow to ask the server each time */
  757. /* It now also sends the complete lstat information for each file */
  758. static void *
  759. smbfs_readdir (void *info)
  760. {
  761. static union vfs_dirent smbfs_readdir_data;
  762. static char *const dirent_dest = smbfs_readdir_data.dent.d_name;
  763. opendir_info *smbfs_info = (opendir_info *) info;
  764. DEBUG (4, ("smbfs_readdir(%s)\n", smbfs_info->dirname));
  765. if (!smbfs_info->entries)
  766. if (!smbfs_loaddir (smbfs_info))
  767. return NULL;
  768. if (smbfs_info->current == 0)
  769. { /* reached end of dir entries */
  770. DEBUG (3, ("smbfs_readdir: smbfs_info->current = 0\n"));
  771. #ifdef SMBFS_FREE_DIR
  772. smbfs_free_dir (smbfs_info->entries);
  773. smbfs_info->entries = 0;
  774. #endif
  775. return NULL;
  776. }
  777. g_strlcpy (dirent_dest, smbfs_info->current->text, MC_MAXPATHLEN);
  778. smbfs_info->current = smbfs_info->current->next;
  779. compute_namelen (&smbfs_readdir_data.dent);
  780. return &smbfs_readdir_data;
  781. }
  782. /* --------------------------------------------------------------------------------------------- */
  783. static int
  784. smbfs_closedir (void *info)
  785. {
  786. opendir_info *smbfs_info = (opendir_info *) info;
  787. /* dir_entry *p, *q; */
  788. DEBUG (3, ("smbfs_closedir(%s)\n", smbfs_info->dirname));
  789. /* CLOSE HERE */
  790. /* for (p = smbfs_info->entries; p;){
  791. q = p;
  792. p = p->next;
  793. g_free (q->text);
  794. g_free (q);
  795. }
  796. g_free (info); */
  797. return 0;
  798. }
  799. /* --------------------------------------------------------------------------------------------- */
  800. static int
  801. smbfs_chmod (struct vfs_class *me, const char *path, int mode)
  802. {
  803. (void) me;
  804. DEBUG (3, ("smbfs_chmod(path:%s, mode:%d)\n", path, mode));
  805. /* my_errno = EOPNOTSUPP;
  806. return -1; *//* cannot chmod on smb filesystem */
  807. return 0; /* make mc happy */
  808. }
  809. /* --------------------------------------------------------------------------------------------- */
  810. static int
  811. smbfs_chown (struct vfs_class *me, const char *path, uid_t owner, gid_t group)
  812. {
  813. (void) me;
  814. DEBUG (3, ("smbfs_chown(path:%s, owner:%d, group:%d)\n", path, owner, group));
  815. my_errno = EOPNOTSUPP; /* ready for your labotomy? */
  816. return -1;
  817. }
  818. /* --------------------------------------------------------------------------------------------- */
  819. static int
  820. smbfs_utime (struct vfs_class *me, const char *path, struct utimbuf *times)
  821. {
  822. (void) me;
  823. (void) times;
  824. DEBUG (3, ("smbfs_utime(path:%s)\n", path));
  825. my_errno = EOPNOTSUPP;
  826. return -1;
  827. }
  828. /* --------------------------------------------------------------------------------------------- */
  829. static int
  830. smbfs_readlink (struct vfs_class *me, const char *path, char *buf, size_t size)
  831. {
  832. (void) me;
  833. DEBUG (3, ("smbfs_readlink(path:%s, buf:%s, size:%zu)\n", path, buf, size));
  834. my_errno = EOPNOTSUPP;
  835. return -1; /* no symlinks on smb filesystem? */
  836. }
  837. /* --------------------------------------------------------------------------------------------- */
  838. static int
  839. smbfs_symlink (struct vfs_class *me, const char *n1, const char *n2)
  840. {
  841. (void) me;
  842. DEBUG (3, ("smbfs_symlink(n1:%s, n2:%s)\n", n1, n2));
  843. my_errno = EOPNOTSUPP;
  844. return -1; /* no symlinks on smb filesystem? */
  845. }
  846. /* --------------------------------------------------------------------------------------------- */
  847. /*****************************************************
  848. return a connection to a SMB server
  849. current_bucket needs to be set before calling
  850. *******************************************************/
  851. static struct cli_state *
  852. smbfs_do_connect (const char *server, char *share)
  853. {
  854. struct cli_state *c;
  855. struct nmb_name called, calling;
  856. struct in_addr ip;
  857. DEBUG (3, ("smbfs_do_connect(%s, %s)\n", server, share));
  858. if (*share == '\\')
  859. {
  860. server = share + 2;
  861. share = strchr (server, '\\');
  862. if (!share)
  863. return NULL;
  864. *share = 0;
  865. share++;
  866. }
  867. make_nmb_name (&calling, global_myname, 0x0);
  868. make_nmb_name (&called, server, current_bucket->name_type);
  869. for (;;)
  870. {
  871. ip = (current_bucket->have_ip) ? current_bucket->dest_ip : ipzero;
  872. /* have to open a new connection */
  873. if (!(c = cli_initialise (NULL)))
  874. {
  875. my_errno = ENOMEM;
  876. return NULL;
  877. }
  878. pwd_init (&(c->pwd)); /* should be moved into cli_initialise()? */
  879. pwd_set_cleartext (&(c->pwd), current_bucket->password);
  880. if ((cli_set_port (c, current_bucket->port) == 0) || !cli_connect (c, server, &ip))
  881. {
  882. DEBUG (1, ("Connection to %s failed\n", server));
  883. break;
  884. }
  885. if (!cli_session_request (c, &calling, &called))
  886. {
  887. my_errno = cli_error (c, NULL, &err, NULL);
  888. DEBUG (1, ("session request to %s failed\n", called.name));
  889. cli_shutdown (c);
  890. if (strcmp (called.name, "*SMBSERVER"))
  891. {
  892. make_nmb_name (&called, "*SMBSERVER", 0x20);
  893. continue;
  894. }
  895. return NULL;
  896. }
  897. DEBUG (3, (" session request ok\n"));
  898. if (!cli_negprot (c))
  899. {
  900. DEBUG (1, ("protocol negotiation failed\n"));
  901. break;
  902. }
  903. if (!cli_session_setup (c, current_bucket->user,
  904. current_bucket->password, strlen (current_bucket->password),
  905. current_bucket->password, strlen (current_bucket->password),
  906. current_bucket->domain))
  907. {
  908. DEBUG (1, ("session setup failed: %s\n", cli_errstr (c)));
  909. smbfs_auth_remove (server, share);
  910. break;
  911. }
  912. if (*c->server_domain || *c->server_os || *c->server_type)
  913. DEBUG (5, ("Domain=[%s] OS=[%s] Server=[%s]\n",
  914. c->server_domain, c->server_os, c->server_type));
  915. DEBUG (3, (" session setup ok\n"));
  916. if (!cli_send_tconX (c, share, "?????",
  917. current_bucket->password, strlen (current_bucket->password) + 1))
  918. {
  919. DEBUG (1, ("%s: tree connect failed: %s\n", share, cli_errstr (c)));
  920. break;
  921. }
  922. DEBUG (3, (" tconx ok\n"));
  923. my_errno = 0;
  924. return c;
  925. }
  926. my_errno = cli_error (c, NULL, &err, NULL);
  927. cli_shutdown (c);
  928. return NULL;
  929. }
  930. /* --------------------------------------------------------------------------------------------- */
  931. static int
  932. smbfs_get_master_browser (char **host)
  933. {
  934. static char so_broadcast[] = "SO_BROADCAST";
  935. int count;
  936. struct in_addr *ip_list, bcast_addr;
  937. /* does port = 137 for win95 master browser? */
  938. int fd = open_socket_in (SOCK_DGRAM, 0, 3,
  939. interpret_addr (lp_socket_address ()), True);
  940. if (fd == -1)
  941. return 0;
  942. set_socket_options (fd, so_broadcast);
  943. ip_list = iface_bcast (ipzero);
  944. bcast_addr = *ip_list;
  945. if ((ip_list = name_query (fd, "\01\02__MSBROWSE__\02", 1, True,
  946. True, bcast_addr, &count, NULL)))
  947. {
  948. if (!count)
  949. return 0;
  950. /* just return first master browser */
  951. *host = g_strdup (inet_ntoa (ip_list[0]));
  952. return 1;
  953. }
  954. return 0;
  955. }
  956. /* --------------------------------------------------------------------------------------------- */
  957. static void
  958. smbfs_free_bucket (smbfs_connection * bucket)
  959. {
  960. g_free (bucket->host);
  961. g_free (bucket->service);
  962. g_free (bucket->domain);
  963. g_free (bucket->user);
  964. wipe_password (bucket->password);
  965. g_free (bucket->home);
  966. memset (bucket, 0, sizeof (smbfs_connection));
  967. }
  968. /* --------------------------------------------------------------------------------------------- */
  969. static smbfs_connection *
  970. smbfs_get_free_bucket (void)
  971. {
  972. int i;
  973. for (i = 0; i < SMBFS_MAX_CONNECTIONS; i++)
  974. if (!smbfs_connections[i].cli)
  975. return &smbfs_connections[i];
  976. { /* search for most dormant connection */
  977. int oldest = 0; /* index */
  978. time_t oldest_time = smbfs_connections[0].last_use;
  979. for (i = 1; i < SMBFS_MAX_CONNECTIONS; i++)
  980. {
  981. if (smbfs_connections[i].last_use < oldest_time)
  982. {
  983. oldest_time = smbfs_connections[i].last_use;
  984. oldest = i;
  985. }
  986. }
  987. cli_shutdown (smbfs_connections[oldest].cli);
  988. smbfs_free_bucket (&smbfs_connections[oldest]);
  989. return &smbfs_connections[oldest];
  990. }
  991. /* This can't happend, since we have checked for max connections before */
  992. vfs_die ("Internal error: smbfs_get_free_bucket");
  993. return 0; /* shut up, stupid gcc */
  994. }
  995. /* --------------------------------------------------------------------------------------------- */
  996. /* This routine keeps track of open connections */
  997. /* Returns a connected socket to host */
  998. static smbfs_connection *
  999. smbfs_open_link (char *host, char *path, const char *user, int *port, char *this_pass)
  1000. {
  1001. int i;
  1002. smbfs_connection *bucket;
  1003. pstring service;
  1004. struct in_addr *dest_ip = NULL;
  1005. DEBUG (3, ("smbfs_open_link(host:%s, path:%s)\n", host, path));
  1006. if (strcmp (host, path) == 0) /* if host & path are same: */
  1007. pstrcpy (service, IPC); /* setup for browse */
  1008. else
  1009. { /* get share name from path, path starts with server name */
  1010. char *p;
  1011. if ((p = strchr (path, '/'))) /* get share aka */
  1012. pstrcpy (service, ++p); /* service name from path */
  1013. else
  1014. pstrcpy (service, "");
  1015. /* now check for trailing directory/filenames */
  1016. p = strchr (service, '/');
  1017. if (p)
  1018. *p = 0; /* cut off dir/files: sharename only */
  1019. if (!*service)
  1020. pstrcpy (service, IPC); /* setup for browse */
  1021. DEBUG (6, ("smbfs_open_link: service from path:%s\n", service));
  1022. }
  1023. if (got_user)
  1024. user = username; /* global from getenv */
  1025. /* Is the link actually open? */
  1026. for (i = 0; i < SMBFS_MAX_CONNECTIONS; i++)
  1027. {
  1028. if (!smbfs_connections[i].cli)
  1029. continue;
  1030. if ((strcmp (host, smbfs_connections[i].host) == 0) &&
  1031. (strcmp (user, smbfs_connections[i].user) == 0) &&
  1032. (strcmp (service, smbfs_connections[i].service) == 0))
  1033. {
  1034. int retries = 0;
  1035. BOOL inshare = (*host != 0 && *path != 0 && strchr (path, '/'));
  1036. /* check if this connection has died */
  1037. while (!smbfs_chkpath (smbfs_connections[i].cli, "\\", !inshare))
  1038. {
  1039. if (!smbfs_reconnect (&smbfs_connections[i], &retries))
  1040. return 0;
  1041. }
  1042. DEBUG (6, ("smbfs_open_link: returning smbfs_connection[%d]\n", i));
  1043. current_bucket = &smbfs_connections[i];
  1044. smbfs_connections[i].last_use = time (NULL);
  1045. return &smbfs_connections[i];
  1046. }
  1047. /* connection not found, find if we have ip for new connection */
  1048. if (strcmp (host, smbfs_connections[i].host) == 0)
  1049. dest_ip = &smbfs_connections[i].cli->dest_ip;
  1050. }
  1051. /* make new connection */
  1052. bucket = smbfs_get_free_bucket ();
  1053. bucket->name_type = 0x20;
  1054. bucket->home = 0;
  1055. bucket->port = *port;
  1056. bucket->have_ip = False;
  1057. if (dest_ip)
  1058. {
  1059. bucket->have_ip = True;
  1060. bucket->dest_ip = *dest_ip;
  1061. }
  1062. current_bucket = bucket;
  1063. bucket->user = g_strdup (user);
  1064. bucket->service = g_strdup (service);
  1065. if (!(*host))
  1066. { /* if blank host name, browse for servers */
  1067. if (!smbfs_get_master_browser (&host)) /* set host to ip of master browser */
  1068. return 0; /* could not find master browser? */
  1069. g_free (host);
  1070. bucket->host = g_strdup (""); /* blank host means master browser */
  1071. }
  1072. else
  1073. bucket->host = g_strdup (host);
  1074. if (!smbfs_bucket_set_authinfo (bucket, 0, /* domain currently not used */
  1075. user, this_pass, 1))
  1076. return 0;
  1077. /* connect to share */
  1078. while (!(bucket->cli = smbfs_do_connect (host, service)))
  1079. {
  1080. if (my_errno != EPERM)
  1081. return 0;
  1082. message (D_ERROR, MSG_ERROR, _("Authentication failed"));
  1083. /* authentication failed, try again */
  1084. smbfs_auth_remove (bucket->host, bucket->service);
  1085. if (!smbfs_bucket_set_authinfo (bucket, bucket->domain, bucket->user, 0, 0))
  1086. return 0;
  1087. }
  1088. smbfs_open_connections++;
  1089. DEBUG (3, ("smbfs_open_link:smbfs_open_connections: %d\n", smbfs_open_connections));
  1090. return bucket;
  1091. }
  1092. /* --------------------------------------------------------------------------------------------- */
  1093. static char *
  1094. smbfs_get_path (smbfs_connection ** sc, const char *path)
  1095. {
  1096. char *user, *host, *remote_path, *pass;
  1097. int port = SMB_PORT;
  1098. DEBUG (3, ("smbfs_get_path(%s)\n", path));
  1099. if (strncmp (path, URL_HEADER, HEADER_LEN))
  1100. return NULL;
  1101. path += HEADER_LEN;
  1102. if (*path == '/') /* '/' leading server name */
  1103. path++; /* probably came from server browsing */
  1104. if ((remote_path = smbfs_get_host_and_username (&path, &host, &user, &port, &pass)))
  1105. if ((*sc = smbfs_open_link (host, remote_path, user, &port, pass)) == NULL)
  1106. {
  1107. g_free (remote_path);
  1108. remote_path = NULL;
  1109. }
  1110. g_free (host);
  1111. g_free (user);
  1112. if (pass)
  1113. wipe_password (pass);
  1114. if (!remote_path)
  1115. return NULL;
  1116. /* NOTE: tildes are deprecated. See ftpfs.c */
  1117. {
  1118. int f = !strcmp (remote_path, "/~");
  1119. if (f || !strncmp (remote_path, "/~/", 3))
  1120. {
  1121. char *s;
  1122. s = concat_dir_and_file ((*sc)->home, remote_path + 3 - f);
  1123. g_free (remote_path);
  1124. return s;
  1125. }
  1126. }
  1127. return remote_path;
  1128. }
  1129. /* --------------------------------------------------------------------------------------------- */
  1130. #if 0
  1131. static int
  1132. is_error (int result, int errno_num)
  1133. {
  1134. if (!(result == -1))
  1135. return my_errno = 0;
  1136. else
  1137. my_errno = errno_num;
  1138. return 1;
  1139. }
  1140. #endif
  1141. /* --------------------------------------------------------------------------------------------- */
  1142. static void *
  1143. smbfs_opendir (struct vfs_class *me, const char *dirname)
  1144. {
  1145. opendir_info *smbfs_info;
  1146. smbfs_connection *sc;
  1147. char *remote_dir;
  1148. (void) me;
  1149. DEBUG (3, ("smbfs_opendir(dirname:%s)\n", dirname));
  1150. if (!(remote_dir = smbfs_get_path (&sc, dirname)))
  1151. return NULL;
  1152. /* FIXME: where freed? */
  1153. smbfs_info = g_new (opendir_info, 1);
  1154. smbfs_info->server_list = FALSE;
  1155. smbfs_info->path = g_strdup (dirname); /* keep original */
  1156. smbfs_info->dirname = remote_dir;
  1157. smbfs_info->conn = sc;
  1158. smbfs_info->entries = 0;
  1159. smbfs_info->current = 0;
  1160. return smbfs_info;
  1161. }
  1162. /* --------------------------------------------------------------------------------------------- */
  1163. static int
  1164. smbfs_fake_server_stat (const char *server_url, const char *path, struct stat *buf)
  1165. {
  1166. dir_entry *dentry;
  1167. const char *p;
  1168. (void) server_url;
  1169. if ((p = strrchr (path, '/')))
  1170. path = p + 1; /* advance until last '/' */
  1171. if (!current_info->entries)
  1172. {
  1173. if (!smbfs_loaddir (current_info)) /* browse host */
  1174. return -1;
  1175. }
  1176. if (current_info->server_list == True)
  1177. {
  1178. dentry = current_info->entries;
  1179. DEBUG (4, ("fake stat for SERVER \"%s\"\n", path));
  1180. while (dentry)
  1181. {
  1182. if (strcmp (dentry->text, path) == 0)
  1183. {
  1184. DEBUG (4, ("smbfs_fake_server_stat: %s:%4o\n",
  1185. dentry->text, (int) dentry->my_stat.st_mode));
  1186. memcpy (buf, &dentry->my_stat, sizeof (struct stat));
  1187. return 0;
  1188. }
  1189. dentry = dentry->next;
  1190. }
  1191. }
  1192. my_errno = ENOENT;
  1193. return -1;
  1194. }
  1195. /* --------------------------------------------------------------------------------------------- */
  1196. static int
  1197. smbfs_fake_share_stat (const char *server_url, const char *path, struct stat *buf)
  1198. {
  1199. dir_entry *dentry;
  1200. if (strlen (path) < strlen (server_url))
  1201. return -1;
  1202. if (!current_share_info)
  1203. { /* Server was not stat()ed */
  1204. /* Make sure there is such share at server */
  1205. smbfs_connection *sc;
  1206. char *p;
  1207. p = smbfs_get_path (&sc, path);
  1208. g_free (p);
  1209. if (p)
  1210. {
  1211. memset (buf, 0, sizeof (*buf));
  1212. /* show this as dir */
  1213. buf->st_mode =
  1214. (S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH) & myumask;
  1215. return 0;
  1216. }
  1217. return -1;
  1218. }
  1219. path += strlen (server_url); /* we only want share name */
  1220. path++;
  1221. if (*path == '/') /* '/' leading server name */
  1222. path++; /* probably came from server browsing */
  1223. if (!current_share_info->entries)
  1224. {
  1225. if (!smbfs_loaddir (current_share_info)) /* browse host */
  1226. return -1;
  1227. }
  1228. dentry = current_share_info->entries;
  1229. DEBUG (3, ("smbfs_fake_share_stat: %s on %s\n", path, server_url));
  1230. while (dentry)
  1231. {
  1232. if (strcmp (dentry->text, path) == 0)
  1233. {
  1234. DEBUG (6, ("smbfs_fake_share_stat: %s:%4o\n",
  1235. dentry->text, (int) dentry->my_stat.st_mode));
  1236. memcpy (buf, &dentry->my_stat, sizeof (struct stat));
  1237. return 0;
  1238. }
  1239. dentry = dentry->next;
  1240. }
  1241. my_errno = ENOENT;
  1242. return -1;
  1243. }
  1244. /* --------------------------------------------------------------------------------------------- */
  1245. /* stat a single file */
  1246. static int
  1247. smbfs_get_remote_stat (smbfs_connection * sc, const char *path, struct stat *buf)
  1248. {
  1249. uint16 attribute = aDIR | aSYSTEM | aHIDDEN;
  1250. char *mypath;
  1251. DEBUG (3, ("smbfs_get_remote_stat(): mypath:%s\n", path));
  1252. mypath = smbfs_convert_path (path, FALSE);
  1253. #if 0 /* single_entry is never free()d now. And only my_stat is used */
  1254. single_entry = g_new (dir_entry, 1);
  1255. single_entry->text = dos_to_unix (g_strdup (finfo->name), 1);
  1256. single_entry->next = 0;
  1257. #endif
  1258. if (!single_entry)
  1259. single_entry = g_new0 (dir_entry, 1);
  1260. if (cli_list (sc->cli, mypath, attribute, smbfs_loaddir_helper, single_entry) < 1)
  1261. {
  1262. my_errno = ENOENT;
  1263. g_free (mypath);
  1264. return -1; /* cli_list returns number of files */
  1265. }
  1266. memcpy (buf, &single_entry->my_stat, sizeof (struct stat));
  1267. /* don't free here, use for smbfs_fstat() */
  1268. /* g_free(single_entry->text);
  1269. g_free(single_entry); */
  1270. g_free (mypath);
  1271. return 0;
  1272. }
  1273. /* --------------------------------------------------------------------------------------------- */
  1274. static int
  1275. smbfs_search_dir_entry (dir_entry * dentry, const char *text, struct stat *buf)
  1276. {
  1277. while (dentry)
  1278. {
  1279. if (strcmp (text, dentry->text) == 0)
  1280. {
  1281. memcpy (buf, &dentry->my_stat, sizeof (struct stat));
  1282. memcpy (&single_entry->my_stat, &dentry->my_stat, sizeof (struct stat));
  1283. return 0;
  1284. }
  1285. dentry = dentry->next;
  1286. }
  1287. return -1;
  1288. }
  1289. /* --------------------------------------------------------------------------------------------- */
  1290. static int
  1291. smbfs_get_stat_info (smbfs_connection * sc, const char *path, struct stat *buf)
  1292. {
  1293. char *p;
  1294. #if 0
  1295. dir_entry *dentry = current_info->entries;
  1296. #endif
  1297. const char *mypath = path;
  1298. mypath++; /* cut off leading '/' */
  1299. if ((p = strrchr (mypath, '/')))
  1300. mypath = p + 1; /* advance until last file/dir name */
  1301. DEBUG (3, ("smbfs_get_stat_info: mypath:%s, current_info->dirname:%s\n",
  1302. mypath, current_info->dirname));
  1303. #if 0
  1304. if (!dentry)
  1305. {
  1306. DEBUG (1, ("No dir entries (empty dir) cached:'%s', wanted:'%s'\n",
  1307. current_info->dirname, path));
  1308. return -1;
  1309. }
  1310. #endif
  1311. if (!single_entry) /* when found, this will be written too */
  1312. single_entry = g_new (dir_entry, 1);
  1313. if (smbfs_search_dir_entry (current_info->entries, mypath, buf) == 0)
  1314. {
  1315. return 0;
  1316. }
  1317. /* now try to identify mypath as PARENT dir */
  1318. {
  1319. char *mdp;
  1320. char *mydir;
  1321. mdp = mydir = g_strdup (current_info->dirname);
  1322. if ((p = strrchr (mydir, '/')))
  1323. *p = 0; /* advance util last '/' */
  1324. if ((p = strrchr (mydir, '/')))
  1325. mydir = p + 1; /* advance util last '/' */
  1326. if (strcmp (mydir, mypath) == 0)
  1327. { /* fake a stat for ".." */
  1328. memset (buf, 0, sizeof (struct stat));
  1329. buf->st_mode = (S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH) & myumask;
  1330. memcpy (&single_entry->my_stat, buf, sizeof (struct stat));
  1331. g_free (mdp);
  1332. DEBUG (1, (" PARENT:found in %s\n", current_info->dirname));
  1333. return 0;
  1334. }
  1335. g_free (mdp);
  1336. }
  1337. /* now try to identify as CURRENT dir? */
  1338. {
  1339. char *dnp = current_info->dirname;
  1340. DEBUG (6, ("smbfs_get_stat_info: is %s current dir? this dir is: %s\n",
  1341. mypath, current_info->dirname));
  1342. if (*dnp == '/')
  1343. dnp++;
  1344. else
  1345. {
  1346. return -1;
  1347. }
  1348. if (strcmp (mypath, dnp) == 0)
  1349. {
  1350. memset (buf, 0, sizeof (struct stat));
  1351. buf->st_mode = (S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH) & myumask;
  1352. memcpy (&single_entry->my_stat, buf, sizeof (struct stat));
  1353. DEBUG (1, (" CURRENT:found in %s\n", current_info->dirname));
  1354. return 0;
  1355. }
  1356. }
  1357. DEBUG (3, ("'%s' not found in current_info '%s'\n", path, current_info->dirname));
  1358. /* try to find this in the PREVIOUS listing */
  1359. if (previous_info)
  1360. {
  1361. if (smbfs_search_dir_entry (previous_info->entries, mypath, buf) == 0)
  1362. return 0;
  1363. DEBUG (3, ("'%s' not found in previous_info '%s'\n", path, previous_info->dirname));
  1364. }
  1365. /* try to find this in the SHARE listing */
  1366. if (current_share_info)
  1367. {
  1368. if (smbfs_search_dir_entry (current_share_info->entries, mypath, buf) == 0)
  1369. return 0;
  1370. DEBUG (3, ("'%s' not found in share_info '%s'\n", path, current_share_info->dirname));
  1371. }
  1372. /* try to find this in the SERVER listing */
  1373. if (current_server_info)
  1374. {
  1375. if (smbfs_search_dir_entry (current_server_info->entries, mypath, buf) == 0)
  1376. return 0;
  1377. DEBUG (3, ("'%s' not found in server_info '%s'\n", path, current_server_info->dirname));
  1378. }
  1379. /* nothing found. get stat file info from server */
  1380. return smbfs_get_remote_stat (sc, path, buf);
  1381. }
  1382. /* --------------------------------------------------------------------------------------------- */
  1383. static int
  1384. smbfs_chdir (struct vfs_class *me, const char *path)
  1385. {
  1386. char *remote_dir;
  1387. smbfs_connection *sc;
  1388. (void) me;
  1389. DEBUG (3, ("smbfs_chdir(path:%s)\n", path));
  1390. if (!(remote_dir = smbfs_get_path (&sc, path)))
  1391. return -1;
  1392. g_free (remote_dir);
  1393. return 0;
  1394. }
  1395. /* --------------------------------------------------------------------------------------------- */
  1396. static int
  1397. smbfs_loaddir_by_name (struct vfs_class *me, const char *path)
  1398. {
  1399. void *info;
  1400. char *mypath, *p;
  1401. mypath = g_strdup (path);
  1402. p = strrchr (mypath, '/');
  1403. if (p > mypath)
  1404. *p = 0;
  1405. DEBUG (6, ("smbfs_loaddir_by_name(%s)\n", mypath));
  1406. smbfs_chdir (me, mypath);
  1407. info = smbfs_opendir (me, mypath);
  1408. g_free (mypath);
  1409. if (!info)
  1410. return -1;
  1411. smbfs_readdir (info);
  1412. smbfs_loaddir (info);
  1413. return 0;
  1414. }
  1415. /* --------------------------------------------------------------------------------------------- */
  1416. static int
  1417. smbfs_stat (struct vfs_class *me, const char *path, struct stat *buf)
  1418. {
  1419. smbfs_connection *sc;
  1420. pstring server_url;
  1421. char *service, *pp, *at;
  1422. const char *p;
  1423. DEBUG (3, ("smbfs_stat(path:%s)\n", path));
  1424. if (!current_info)
  1425. {
  1426. DEBUG (1, ("current_info = NULL: "));
  1427. if (smbfs_loaddir_by_name (me, path) < 0)
  1428. return -1;
  1429. }
  1430. /* check if stating server */
  1431. p = path;
  1432. if (strncmp (p, URL_HEADER, HEADER_LEN))
  1433. {
  1434. DEBUG (1, ("'%s' doesnt start with '%s' (length %d)\n", p, URL_HEADER, HEADER_LEN));
  1435. return -1;
  1436. }
  1437. p += HEADER_LEN;
  1438. if (*p == '/')
  1439. p++;
  1440. pp = strchr (p, '/'); /* advance past next '/' */
  1441. at = strchr (p, '@');
  1442. pstrcpy (server_url, URL_HEADER);
  1443. if (at && at < pp)
  1444. { /* user@server */
  1445. char *z = &(server_url[sizeof (server_url) - 1]);
  1446. const char *s = p;
  1447. at = &(server_url[HEADER_LEN]) + (at - p + 1);
  1448. if (z > at)
  1449. z = at;
  1450. at = &(server_url[HEADER_LEN]);
  1451. while (at < z)
  1452. *at++ = *s++;
  1453. *z = 0;
  1454. }
  1455. pstrcat (server_url, current_bucket->host);
  1456. if (!pp)
  1457. {
  1458. if (!current_info->server_list)
  1459. {
  1460. if (smbfs_loaddir_by_name (me, path) < 0)
  1461. return -1;
  1462. }
  1463. return smbfs_fake_server_stat (server_url, path, buf);
  1464. }
  1465. if (!strchr (++pp, '/'))
  1466. {
  1467. return smbfs_fake_share_stat (server_url, path, buf);
  1468. }
  1469. /* stating inside share at this point */
  1470. if (!(service = smbfs_get_path (&sc, path))) /* connects if necessary */
  1471. return -1;
  1472. {
  1473. int hostlen = strlen (current_bucket->host);
  1474. char *ppp = service + strlen (service) - hostlen;
  1475. char *sp = server_url + strlen (server_url) - hostlen;
  1476. if (strcmp (sp, ppp) == 0)
  1477. {
  1478. /* make server name appear as directory */
  1479. DEBUG (1, ("smbfs_stat: showing server as directory\n"));
  1480. memset (buf, 0, sizeof (struct stat));
  1481. buf->st_mode = (S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH) & myumask;
  1482. g_free (service);
  1483. return 0;
  1484. }
  1485. }
  1486. /* check if current_info is in share requested */
  1487. p = service;
  1488. pp = strchr (p, '/');
  1489. if (pp)
  1490. {
  1491. p = ++pp; /* advance past server name */
  1492. pp = strchr (p, '/');
  1493. }
  1494. if (pp)
  1495. *pp = 0; /* cut off everthing after service name */
  1496. else
  1497. p = IPC; /* browsing for services */
  1498. pp = current_info->dirname;
  1499. if (*pp == '/')
  1500. pp++;
  1501. if (strncmp (p, pp, strlen (p)) != 0)
  1502. {
  1503. DEBUG (6, ("desired '%s' is not loaded, we have '%s'\n", p, pp));
  1504. if (smbfs_loaddir_by_name (me, path) < 0)
  1505. {
  1506. g_free (service);
  1507. return -1;
  1508. }
  1509. DEBUG (6, ("loaded dir: '%s'\n", current_info->dirname));
  1510. }
  1511. g_free (service);
  1512. /* stat dirs & files under shares now */
  1513. return smbfs_get_stat_info (sc, path, buf);
  1514. }
  1515. /* --------------------------------------------------------------------------------------------- */
  1516. static off_t
  1517. smbfs_lseek (void *data, off_t offset, int whence)
  1518. {
  1519. smbfs_handle *info = (smbfs_handle *) data;
  1520. size_t size;
  1521. DEBUG (3,
  1522. ("smbfs_lseek(info->nread => %d, offset => %d, whence => %d) \n",
  1523. (int) info->nread, (int) offset, whence));
  1524. switch (whence)
  1525. {
  1526. case SEEK_SET:
  1527. info->nread = offset;
  1528. break;
  1529. case SEEK_CUR:
  1530. info->nread += offset;
  1531. break;
  1532. case SEEK_END:
  1533. if (!cli_qfileinfo (info->cli, info->fnum,
  1534. NULL, &size, NULL, NULL, NULL,
  1535. NULL, NULL) &&
  1536. !cli_getattrE (info->cli, info->fnum, NULL, &size, NULL, NULL, NULL))
  1537. {
  1538. errno = EINVAL;
  1539. return -1;
  1540. }
  1541. info->nread = size + offset;
  1542. break;
  1543. }
  1544. return info->nread;
  1545. }
  1546. /* --------------------------------------------------------------------------------------------- */
  1547. static int
  1548. smbfs_mknod (struct vfs_class *me, const char *path, mode_t mode, dev_t dev)
  1549. {
  1550. (void) me;
  1551. DEBUG (3, ("smbfs_mknod(path:%s, mode:%d, dev:%u)\n", path, mode, (unsigned int) dev));
  1552. my_errno = EOPNOTSUPP;
  1553. return -1;
  1554. }
  1555. /* --------------------------------------------------------------------------------------------- */
  1556. static int
  1557. smbfs_mkdir (struct vfs_class *me, const char *path, mode_t mode)
  1558. {
  1559. smbfs_connection *sc;
  1560. char *remote_file;
  1561. char *cpath;
  1562. (void) me;
  1563. DEBUG (3, ("smbfs_mkdir(path:%s, mode:%d)\n", path, (int) mode));
  1564. if ((remote_file = smbfs_get_path (&sc, path)) == 0)
  1565. return -1;
  1566. g_free (remote_file);
  1567. cpath = smbfs_convert_path (path, FALSE);
  1568. if (!cli_mkdir (sc->cli, cpath))
  1569. {
  1570. my_errno = cli_error (sc->cli, NULL, &err, NULL);
  1571. message (D_ERROR, MSG_ERROR, _("Error %s creating directory %s"),
  1572. cli_errstr (sc->cli), CNV_LANG (cpath));
  1573. g_free (cpath);
  1574. return -1;
  1575. }
  1576. g_free (cpath);
  1577. return 0;
  1578. }
  1579. /* --------------------------------------------------------------------------------------------- */
  1580. static int
  1581. smbfs_rmdir (struct vfs_class *me, const char *path)
  1582. {
  1583. smbfs_connection *sc;
  1584. char *remote_file;
  1585. char *cpath;
  1586. (void) me;
  1587. DEBUG (3, ("smbfs_rmdir(path:%s)\n", path));
  1588. if ((remote_file = smbfs_get_path (&sc, path)) == 0)
  1589. return -1;
  1590. g_free (remote_file);
  1591. cpath = smbfs_convert_path (path, FALSE);
  1592. if (!cli_rmdir (sc->cli, cpath))
  1593. {
  1594. my_errno = cli_error (sc->cli, NULL, &err, NULL);
  1595. message (D_ERROR, MSG_ERROR, _("Error %s removing directory %s"),
  1596. cli_errstr (sc->cli), CNV_LANG (cpath));
  1597. g_free (cpath);
  1598. return -1;
  1599. }
  1600. g_free (cpath);
  1601. return 0;
  1602. }
  1603. /* --------------------------------------------------------------------------------------------- */
  1604. static int
  1605. smbfs_link (struct vfs_class *me, const char *p1, const char *p2)
  1606. {
  1607. (void) me;
  1608. DEBUG (3, ("smbfs_link(p1:%s, p2:%s)\n", p1, p2));
  1609. my_errno = EOPNOTSUPP;
  1610. return -1;
  1611. }
  1612. /* --------------------------------------------------------------------------------------------- */
  1613. static void
  1614. smbfs_free (vfsid id)
  1615. {
  1616. DEBUG (3, ("smbfs_free(%p)\n", id));
  1617. smbfs_auth_free_all ();
  1618. }
  1619. /* --------------------------------------------------------------------------------------------- */
  1620. /* Gives up on a socket and reopens the connection, the child own the socket
  1621. * now
  1622. */
  1623. static void
  1624. smbfs_forget (const char *path)
  1625. {
  1626. char *host, *user, *p;
  1627. int port;
  1628. if (strncmp (path, URL_HEADER, HEADER_LEN))
  1629. return;
  1630. DEBUG (3, ("smbfs_forget(path:%s)\n", path));
  1631. path += 6;
  1632. if (path[0] == '/' && path[1] == '/')
  1633. path += 2;
  1634. if ((p = smbfs_get_host_and_username (&path, &host, &user, &port, NULL)))
  1635. {
  1636. size_t i;
  1637. g_free (p);
  1638. for (i = 0; i < SMBFS_MAX_CONNECTIONS; i++)
  1639. {
  1640. if (smbfs_connections[i].cli
  1641. && (strcmp (host, smbfs_connections[i].host) == 0)
  1642. && (strcmp (user, smbfs_connections[i].user) == 0)
  1643. && (port == smbfs_connections[i].port))
  1644. {
  1645. /* close socket: the child owns it now */
  1646. cli_shutdown (smbfs_connections[i].cli);
  1647. /* reopen the connection */
  1648. smbfs_connections[i].cli = smbfs_do_connect (host, smbfs_connections[i].service);
  1649. }
  1650. }
  1651. }
  1652. g_free (host);
  1653. g_free (user);
  1654. }
  1655. /* --------------------------------------------------------------------------------------------- */
  1656. static int
  1657. smbfs_setctl (struct vfs_class *me, const char *path, int ctlop, void *arg)
  1658. {
  1659. (void) me;
  1660. (void) arg;
  1661. DEBUG (3, ("smbfs_setctl(path:%s, ctlop:%d)\n", path, ctlop));
  1662. switch (ctlop)
  1663. {
  1664. case VFS_SETCTL_FORGET:
  1665. smbfs_forget (path);
  1666. return 0;
  1667. }
  1668. return 0;
  1669. }
  1670. /* --------------------------------------------------------------------------------------------- */
  1671. static smbfs_handle *
  1672. smbfs_open_readwrite (smbfs_handle * remote_handle, char *rname, int flags, mode_t mode)
  1673. {
  1674. size_t size;
  1675. (void) mode;
  1676. if (flags & O_TRUNC) /* if it exists truncate to zero */
  1677. DEBUG (3, ("smbfs_open: O_TRUNC\n"));
  1678. remote_handle->fnum =
  1679. #if 1 /* Don't play with flags, it is cli_open() headache */
  1680. cli_open (remote_handle->cli, rname, flags, DENY_NONE);
  1681. #else /* What's a reasons to has this code ? */
  1682. cli_open (remote_handle->cli, rname, ((flags & O_CREAT)
  1683. || (flags ==
  1684. (O_WRONLY | O_APPEND))) ?
  1685. flags : O_RDONLY, DENY_NONE);
  1686. #endif
  1687. if (remote_handle->fnum == -1)
  1688. {
  1689. message (D_ERROR, MSG_ERROR, _("%s opening remote file %s"),
  1690. cli_errstr (remote_handle->cli), CNV_LANG (rname));
  1691. DEBUG (1, ("smbfs_open(rname:%s) error:%s\n", rname, cli_errstr (remote_handle->cli)));
  1692. my_errno = cli_error (remote_handle->cli, NULL, &err, NULL);
  1693. return NULL;
  1694. }
  1695. if (flags & O_CREAT)
  1696. return remote_handle;
  1697. if (!cli_qfileinfo (remote_handle->cli, remote_handle->fnum,
  1698. &remote_handle->attr, &size, NULL, NULL, NULL, NULL,
  1699. NULL)
  1700. && !cli_getattrE (remote_handle->cli, remote_handle->fnum,
  1701. &remote_handle->attr, &size, NULL, NULL, NULL))
  1702. {
  1703. message (D_ERROR, MSG_ERROR, "getattrib: %s", cli_errstr (remote_handle->cli));
  1704. DEBUG (1, ("smbfs_open(rname:%s) getattrib:%s\n", rname, cli_errstr (remote_handle->cli)));
  1705. my_errno = cli_error (remote_handle->cli, NULL, &err, NULL);
  1706. cli_close (remote_handle->cli, remote_handle->fnum);
  1707. return NULL;
  1708. }
  1709. if ((flags == (O_WRONLY | O_APPEND)) /* file.c:copy_file_file() -> do_append */
  1710. && smbfs_lseek (remote_handle, 0, SEEK_END) == -1)
  1711. {
  1712. cli_close (remote_handle->cli, remote_handle->fnum);
  1713. return NULL;
  1714. }
  1715. return remote_handle;
  1716. }
  1717. /* --------------------------------------------------------------------------------------------- */
  1718. static void *
  1719. smbfs_open (struct vfs_class *me, const char *file, int flags, mode_t mode)
  1720. {
  1721. char *remote_file;
  1722. void *ret;
  1723. smbfs_connection *sc;
  1724. smbfs_handle *remote_handle;
  1725. (void) me;
  1726. DEBUG (3, ("smbfs_open(file:%s, flags:%d, mode:%o)\n", file, flags, mode));
  1727. if (!(remote_file = smbfs_get_path (&sc, file)))
  1728. return 0;
  1729. remote_file = free_after (smbfs_convert_path (remote_file, FALSE), remote_file);
  1730. remote_handle = g_new (smbfs_handle, 2);
  1731. remote_handle->cli = sc->cli;
  1732. remote_handle->nread = 0;
  1733. ret = smbfs_open_readwrite (remote_handle, remote_file, flags, mode);
  1734. g_free (remote_file);
  1735. if (!ret)
  1736. g_free (remote_handle);
  1737. return ret;
  1738. }
  1739. /* --------------------------------------------------------------------------------------------- */
  1740. static int
  1741. smbfs_unlink (struct vfs_class *me, const char *path)
  1742. {
  1743. smbfs_connection *sc;
  1744. char *remote_file;
  1745. (void) me;
  1746. if ((remote_file = smbfs_get_path (&sc, path)) == 0)
  1747. return -1;
  1748. remote_file = free_after (smbfs_convert_path (remote_file, FALSE), remote_file);
  1749. if (!cli_unlink (sc->cli, remote_file))
  1750. {
  1751. message (D_ERROR, MSG_ERROR, _("%s removing remote file %s"),
  1752. cli_errstr (sc->cli), CNV_LANG (remote_file));
  1753. g_free (remote_file);
  1754. return -1;
  1755. }
  1756. g_free (remote_file);
  1757. return 0;
  1758. }
  1759. /* --------------------------------------------------------------------------------------------- */
  1760. static int
  1761. smbfs_rename (struct vfs_class *me, const char *a, const char *b)
  1762. {
  1763. smbfs_connection *sc;
  1764. char *ra, *rb;
  1765. int retval;
  1766. (void) me;
  1767. if ((ra = smbfs_get_path (&sc, a)) == 0)
  1768. return -1;
  1769. if ((rb = smbfs_get_path (&sc, b)) == 0)
  1770. {
  1771. g_free (ra);
  1772. return -1;
  1773. }
  1774. ra = free_after (smbfs_convert_path (ra, FALSE), ra);
  1775. rb = free_after (smbfs_convert_path (rb, FALSE), rb);
  1776. retval = cli_rename (sc->cli, ra, rb);
  1777. g_free (ra);
  1778. g_free (rb);
  1779. if (!retval)
  1780. {
  1781. message (D_ERROR, MSG_ERROR, _("%s renaming files\n"), cli_errstr (sc->cli));
  1782. return -1;
  1783. }
  1784. return 0;
  1785. }
  1786. /* --------------------------------------------------------------------------------------------- */
  1787. static int
  1788. smbfs_fstat (void *data, struct stat *buf)
  1789. {
  1790. smbfs_handle *remote_handle = (smbfs_handle *) data;
  1791. DEBUG (3, ("smbfs_fstat(fnum:%d)\n", remote_handle->fnum));
  1792. /* use left over from previous smbfs_get_remote_stat, if available */
  1793. if (single_entry)
  1794. memcpy (buf, &single_entry->my_stat, sizeof (struct stat));
  1795. else
  1796. { /* single_entry not set up: bug */
  1797. my_errno = EFAULT;
  1798. return -EFAULT;
  1799. }
  1800. return 0;
  1801. }
  1802. /* --------------------------------------------------------------------------------------------- */
  1803. /*** public functions ****************************************************************************/
  1804. /* --------------------------------------------------------------------------------------------- */
  1805. smb_authinfo *
  1806. vfs_smb_authinfo_new (const char *host, const char *share, const char *domain,
  1807. const char *user, const char *pass)
  1808. {
  1809. smb_authinfo *auth;
  1810. auth = g_try_new (struct smb_authinfo, 1);
  1811. if (auth != NULL)
  1812. {
  1813. auth->host = g_strdup (host);
  1814. auth->share = g_strdup (share);
  1815. auth->domain = g_strdup (domain);
  1816. auth->user = g_strdup (user);
  1817. auth->password = g_strdup (pass);
  1818. }
  1819. return auth;
  1820. }
  1821. /* --------------------------------------------------------------------------------------------- */
  1822. void
  1823. init_smbfs (void)
  1824. {
  1825. tcp_init ();
  1826. vfs_smbfs_ops.name = "smbfs";
  1827. vfs_smbfs_ops.prefix = "smb:";
  1828. vfs_smbfs_ops.flags = VFSF_NOLINKS;
  1829. vfs_smbfs_ops.init = smbfs_init;
  1830. vfs_smbfs_ops.fill_names = smbfs_fill_names;
  1831. vfs_smbfs_ops.open = smbfs_open;
  1832. vfs_smbfs_ops.close = smbfs_close;
  1833. vfs_smbfs_ops.read = smbfs_read;
  1834. vfs_smbfs_ops.write = smbfs_write;
  1835. vfs_smbfs_ops.opendir = smbfs_opendir;
  1836. vfs_smbfs_ops.readdir = smbfs_readdir;
  1837. vfs_smbfs_ops.closedir = smbfs_closedir;
  1838. vfs_smbfs_ops.stat = smbfs_stat;
  1839. vfs_smbfs_ops.lstat = smbfs_lstat;
  1840. vfs_smbfs_ops.fstat = smbfs_fstat;
  1841. vfs_smbfs_ops.chmod = smbfs_chmod;
  1842. vfs_smbfs_ops.chown = smbfs_chown;
  1843. vfs_smbfs_ops.utime = smbfs_utime;
  1844. vfs_smbfs_ops.readlink = smbfs_readlink;
  1845. vfs_smbfs_ops.symlink = smbfs_symlink;
  1846. vfs_smbfs_ops.link = smbfs_link;
  1847. vfs_smbfs_ops.unlink = smbfs_unlink;
  1848. vfs_smbfs_ops.rename = smbfs_rename;
  1849. vfs_smbfs_ops.chdir = smbfs_chdir;
  1850. vfs_smbfs_ops.ferrno = smbfs_errno;
  1851. vfs_smbfs_ops.lseek = smbfs_lseek;
  1852. vfs_smbfs_ops.mknod = smbfs_mknod;
  1853. vfs_smbfs_ops.free = smbfs_free;
  1854. vfs_smbfs_ops.mkdir = smbfs_mkdir;
  1855. vfs_smbfs_ops.rmdir = smbfs_rmdir;
  1856. vfs_smbfs_ops.setctl = smbfs_setctl;
  1857. vfs_register_class (&vfs_smbfs_ops);
  1858. }
  1859. /* --------------------------------------------------------------------------------------------- */