sftp.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445
  1. /*
  2. * sftp.c: SFTP generic client code.
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <assert.h>
  8. #include <limits.h>
  9. #include "misc.h"
  10. #include "int64.h"
  11. #include "tree234.h"
  12. #include "sftp.h"
  13. struct sftp_packet {
  14. char *data;
  15. unsigned length, maxlen;
  16. unsigned savedpos;
  17. int type;
  18. };
  19. static const char *fxp_error_message;
  20. static int fxp_errtype;
  21. static void fxp_internal_error(const char *msg);
  22. /* ----------------------------------------------------------------------
  23. * SFTP packet construction functions.
  24. */
  25. static void sftp_pkt_ensure(struct sftp_packet *pkt, int length)
  26. {
  27. if ((int)pkt->maxlen < length) {
  28. pkt->maxlen = length + 256;
  29. pkt->data = sresize(pkt->data, pkt->maxlen, char);
  30. }
  31. }
  32. static void sftp_pkt_adddata(struct sftp_packet *pkt,
  33. const void *data, int len)
  34. {
  35. pkt->length += len;
  36. sftp_pkt_ensure(pkt, pkt->length);
  37. memcpy(pkt->data + pkt->length - len, data, len);
  38. }
  39. static void sftp_pkt_addbyte(struct sftp_packet *pkt, unsigned char byte)
  40. {
  41. sftp_pkt_adddata(pkt, &byte, 1);
  42. }
  43. static void sftp_pkt_adduint32(struct sftp_packet *pkt,
  44. unsigned long value)
  45. {
  46. unsigned char x[4];
  47. PUT_32BIT(x, value);
  48. sftp_pkt_adddata(pkt, x, 4);
  49. }
  50. static struct sftp_packet *sftp_pkt_init(int pkt_type)
  51. {
  52. struct sftp_packet *pkt;
  53. pkt = snew(struct sftp_packet);
  54. pkt->data = NULL;
  55. pkt->savedpos = -1;
  56. pkt->length = 0;
  57. pkt->maxlen = 0;
  58. sftp_pkt_adduint32(pkt, 0); /* length field will be filled in later */
  59. sftp_pkt_addbyte(pkt, (unsigned char) pkt_type);
  60. return pkt;
  61. }
  62. /*
  63. static void sftp_pkt_addbool(struct sftp_packet *pkt, unsigned char value)
  64. {
  65. sftp_pkt_adddata(pkt, &value, 1);
  66. }
  67. */
  68. static void sftp_pkt_adduint64(struct sftp_packet *pkt, uint64 value)
  69. {
  70. unsigned char x[8];
  71. PUT_32BIT(x, value.hi);
  72. PUT_32BIT(x + 4, value.lo);
  73. sftp_pkt_adddata(pkt, x, 8);
  74. }
  75. static void sftp_pkt_addstring_start(struct sftp_packet *pkt)
  76. {
  77. sftp_pkt_adduint32(pkt, 0);
  78. pkt->savedpos = pkt->length;
  79. }
  80. static void sftp_pkt_addstring_str(struct sftp_packet *pkt, const char *data)
  81. {
  82. sftp_pkt_adddata(pkt, data, strlen(data));
  83. PUT_32BIT(pkt->data + pkt->savedpos - 4, pkt->length - pkt->savedpos);
  84. }
  85. static void sftp_pkt_addstring_data(struct sftp_packet *pkt,
  86. const char *data, int len)
  87. {
  88. sftp_pkt_adddata(pkt, data, len);
  89. PUT_32BIT(pkt->data + pkt->savedpos - 4, pkt->length - pkt->savedpos);
  90. }
  91. static void sftp_pkt_addstring(struct sftp_packet *pkt, const char *data)
  92. {
  93. sftp_pkt_addstring_start(pkt);
  94. sftp_pkt_addstring_str(pkt, data);
  95. }
  96. static void sftp_pkt_addattrs(struct sftp_packet *pkt, struct fxp_attrs attrs)
  97. {
  98. sftp_pkt_adduint32(pkt, attrs.flags);
  99. if (attrs.flags & SSH_FILEXFER_ATTR_SIZE) {
  100. sftp_pkt_adduint32(pkt, attrs.size.hi);
  101. sftp_pkt_adduint32(pkt, attrs.size.lo);
  102. }
  103. if (attrs.flags & SSH_FILEXFER_ATTR_UIDGID) {
  104. sftp_pkt_adduint32(pkt, attrs.uid);
  105. sftp_pkt_adduint32(pkt, attrs.gid);
  106. }
  107. if (attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) {
  108. sftp_pkt_adduint32(pkt, attrs.permissions);
  109. }
  110. if (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME) {
  111. sftp_pkt_adduint32(pkt, attrs.atime);
  112. sftp_pkt_adduint32(pkt, attrs.mtime);
  113. }
  114. if (attrs.flags & SSH_FILEXFER_ATTR_EXTENDED) {
  115. /*
  116. * We currently don't support sending any extended
  117. * attributes.
  118. */
  119. }
  120. }
  121. /* ----------------------------------------------------------------------
  122. * SFTP packet decode functions.
  123. */
  124. static int sftp_pkt_getbyte(struct sftp_packet *pkt, unsigned char *ret)
  125. {
  126. if (pkt->length - pkt->savedpos < 1)
  127. return 0;
  128. *ret = (unsigned char) pkt->data[pkt->savedpos];
  129. pkt->savedpos++;
  130. return 1;
  131. }
  132. static int sftp_pkt_getuint32(struct sftp_packet *pkt, unsigned long *ret)
  133. {
  134. if (pkt->length - pkt->savedpos < 4)
  135. return 0;
  136. *ret = GET_32BIT(pkt->data + pkt->savedpos);
  137. pkt->savedpos += 4;
  138. return 1;
  139. }
  140. static int sftp_pkt_getstring(struct sftp_packet *pkt,
  141. char **p, int *length)
  142. {
  143. *p = NULL;
  144. if (pkt->length - pkt->savedpos < 4)
  145. return 0;
  146. *length = toint(GET_32BIT(pkt->data + pkt->savedpos));
  147. pkt->savedpos += 4;
  148. if ((int)(pkt->length - pkt->savedpos) < *length || *length < 0) {
  149. *length = 0;
  150. return 0;
  151. }
  152. *p = pkt->data + pkt->savedpos;
  153. pkt->savedpos += *length;
  154. return 1;
  155. }
  156. static int sftp_pkt_getattrs(struct sftp_packet *pkt, struct fxp_attrs *ret)
  157. {
  158. if (!sftp_pkt_getuint32(pkt, &ret->flags))
  159. return 0;
  160. if (ret->flags & SSH_FILEXFER_ATTR_SIZE) {
  161. unsigned long hi, lo;
  162. if (!sftp_pkt_getuint32(pkt, &hi) ||
  163. !sftp_pkt_getuint32(pkt, &lo))
  164. return 0;
  165. ret->size = uint64_make(hi, lo);
  166. }
  167. if (ret->flags & SSH_FILEXFER_ATTR_UIDGID) {
  168. if (!sftp_pkt_getuint32(pkt, &ret->uid) ||
  169. !sftp_pkt_getuint32(pkt, &ret->gid))
  170. return 0;
  171. }
  172. if (ret->flags & SSH_FILEXFER_ATTR_PERMISSIONS) {
  173. if (!sftp_pkt_getuint32(pkt, &ret->permissions))
  174. return 0;
  175. }
  176. if (ret->flags & SSH_FILEXFER_ATTR_ACMODTIME) {
  177. if (!sftp_pkt_getuint32(pkt, &ret->atime) ||
  178. !sftp_pkt_getuint32(pkt, &ret->mtime))
  179. return 0;
  180. }
  181. if (ret->flags & SSH_FILEXFER_ATTR_EXTENDED) {
  182. unsigned long count;
  183. if (!sftp_pkt_getuint32(pkt, &count))
  184. return 0;
  185. while (count--) {
  186. char *str;
  187. int len;
  188. /*
  189. * We should try to analyse these, if we ever find one
  190. * we recognise.
  191. */
  192. if (!sftp_pkt_getstring(pkt, &str, &len) ||
  193. !sftp_pkt_getstring(pkt, &str, &len))
  194. return 0;
  195. }
  196. }
  197. return 1;
  198. }
  199. static void sftp_pkt_free(struct sftp_packet *pkt)
  200. {
  201. if (pkt->data)
  202. sfree(pkt->data);
  203. sfree(pkt);
  204. }
  205. /* ----------------------------------------------------------------------
  206. * Send and receive packet functions.
  207. */
  208. int sftp_send(struct sftp_packet *pkt)
  209. {
  210. int ret;
  211. PUT_32BIT(pkt->data, pkt->length - 4);
  212. ret = sftp_senddata(pkt->data, pkt->length);
  213. sftp_pkt_free(pkt);
  214. return ret;
  215. }
  216. struct sftp_packet *sftp_recv(void)
  217. {
  218. struct sftp_packet *pkt;
  219. char x[4];
  220. unsigned char uc;
  221. if (!sftp_recvdata(x, 4))
  222. return NULL;
  223. pkt = snew(struct sftp_packet);
  224. pkt->savedpos = 0;
  225. pkt->length = pkt->maxlen = GET_32BIT(x);
  226. pkt->data = snewn(pkt->length, char);
  227. if (!sftp_recvdata(pkt->data, pkt->length)) {
  228. sftp_pkt_free(pkt);
  229. return NULL;
  230. }
  231. if (!sftp_pkt_getbyte(pkt, &uc)) {
  232. sftp_pkt_free(pkt);
  233. return NULL;
  234. } else {
  235. pkt->type = uc;
  236. }
  237. return pkt;
  238. }
  239. /* ----------------------------------------------------------------------
  240. * Request ID allocation and temporary dispatch routines.
  241. */
  242. #define REQUEST_ID_OFFSET 256
  243. struct sftp_request {
  244. unsigned id;
  245. int registered;
  246. void *userdata;
  247. };
  248. static int sftp_reqcmp(void *av, void *bv)
  249. {
  250. struct sftp_request *a = (struct sftp_request *)av;
  251. struct sftp_request *b = (struct sftp_request *)bv;
  252. if (a->id < b->id)
  253. return -1;
  254. if (a->id > b->id)
  255. return +1;
  256. return 0;
  257. }
  258. static int sftp_reqfind(void *av, void *bv)
  259. {
  260. unsigned *a = (unsigned *) av;
  261. struct sftp_request *b = (struct sftp_request *)bv;
  262. if (*a < b->id)
  263. return -1;
  264. if (*a > b->id)
  265. return +1;
  266. return 0;
  267. }
  268. static tree234 *sftp_requests;
  269. static struct sftp_request *sftp_alloc_request(void)
  270. {
  271. unsigned low, high, mid;
  272. int tsize;
  273. struct sftp_request *r;
  274. if (sftp_requests == NULL)
  275. sftp_requests = newtree234(sftp_reqcmp);
  276. /*
  277. * First-fit allocation of request IDs: always pick the lowest
  278. * unused one. To do this, binary-search using the counted
  279. * B-tree to find the largest ID which is in a contiguous
  280. * sequence from the beginning. (Precisely everything in that
  281. * sequence must have ID equal to its tree index plus
  282. * REQUEST_ID_OFFSET.)
  283. */
  284. tsize = count234(sftp_requests);
  285. low = -1;
  286. high = tsize;
  287. while (high - low > 1) {
  288. mid = (high + low) / 2;
  289. r = index234(sftp_requests, mid);
  290. if (r->id == mid + REQUEST_ID_OFFSET)
  291. low = mid; /* this one is fine */
  292. else
  293. high = mid; /* this one is past it */
  294. }
  295. /*
  296. * Now low points to either -1, or the tree index of the
  297. * largest ID in the initial sequence.
  298. */
  299. {
  300. unsigned i = low + 1 + REQUEST_ID_OFFSET;
  301. assert(NULL == find234(sftp_requests, &i, sftp_reqfind));
  302. }
  303. /*
  304. * So the request ID we need to create is
  305. * low + 1 + REQUEST_ID_OFFSET.
  306. */
  307. r = snew(struct sftp_request);
  308. r->id = low + 1 + REQUEST_ID_OFFSET;
  309. r->registered = 0;
  310. r->userdata = NULL;
  311. add234(sftp_requests, r);
  312. return r;
  313. }
  314. void sftp_cleanup_request(void)
  315. {
  316. if (sftp_requests != NULL) {
  317. freetree234(sftp_requests);
  318. sftp_requests = NULL;
  319. }
  320. }
  321. void sftp_register(struct sftp_request *req)
  322. {
  323. req->registered = 1;
  324. }
  325. struct sftp_request *sftp_find_request(struct sftp_packet *pktin)
  326. {
  327. unsigned long id;
  328. struct sftp_request *req;
  329. if (!pktin) {
  330. fxp_internal_error("did not receive a valid SFTP packet\n");
  331. return NULL;
  332. }
  333. if (!sftp_pkt_getuint32(pktin, &id)) {
  334. fxp_internal_error("did not receive a valid SFTP packet\n");
  335. return NULL;
  336. }
  337. req = find234(sftp_requests, &id, sftp_reqfind);
  338. if (!req || !req->registered) {
  339. fxp_internal_error("request ID mismatch\n");
  340. return NULL;
  341. }
  342. del234(sftp_requests, req);
  343. return req;
  344. }
  345. /* ----------------------------------------------------------------------
  346. * String handling routines.
  347. */
  348. static char *mkstr(char *s, int len)
  349. {
  350. char *p = snewn(len + 1, char);
  351. memcpy(p, s, len);
  352. p[len] = '\0';
  353. return p;
  354. }
  355. /* ----------------------------------------------------------------------
  356. * SFTP primitives.
  357. */
  358. /*
  359. * Deal with (and free) an FXP_STATUS packet. Return 1 if
  360. * SSH_FX_OK, 0 if SSH_FX_EOF, and -1 for anything else (error).
  361. * Also place the status into fxp_errtype.
  362. */
  363. static int fxp_got_status(struct sftp_packet *pktin)
  364. {
  365. static const char *const messages[] = {
  366. /* SSH_FX_OK. The only time we will display a _message_ for this
  367. * is if we were expecting something other than FXP_STATUS on
  368. * success, so this is actually an error message! */
  369. "unexpected OK response",
  370. "end of file",
  371. "no such file or directory",
  372. "permission denied",
  373. "failure",
  374. "bad message",
  375. "no connection",
  376. "connection lost",
  377. "operation unsupported",
  378. };
  379. if (pktin->type != SSH_FXP_STATUS) {
  380. fxp_error_message = "expected FXP_STATUS packet";
  381. fxp_errtype = -1;
  382. } else {
  383. unsigned long ul;
  384. if (!sftp_pkt_getuint32(pktin, &ul)) {
  385. fxp_error_message = "malformed FXP_STATUS packet";
  386. fxp_errtype = -1;
  387. } else {
  388. fxp_errtype = ul;
  389. if (fxp_errtype < 0 ||
  390. fxp_errtype >= sizeof(messages) / sizeof(*messages))
  391. fxp_error_message = "unknown error code";
  392. else
  393. fxp_error_message = messages[fxp_errtype];
  394. }
  395. }
  396. if (fxp_errtype == SSH_FX_OK)
  397. return 1;
  398. else if (fxp_errtype == SSH_FX_EOF)
  399. return 0;
  400. else
  401. return -1;
  402. }
  403. static void fxp_internal_error(const char *msg)
  404. {
  405. fxp_error_message = msg;
  406. fxp_errtype = -1;
  407. }
  408. const char *fxp_error(void)
  409. {
  410. return fxp_error_message;
  411. }
  412. int fxp_error_type(void)
  413. {
  414. return fxp_errtype;
  415. }
  416. /*
  417. * Perform exchange of init/version packets. Return 0 on failure.
  418. */
  419. int fxp_init(void)
  420. {
  421. struct sftp_packet *pktout, *pktin;
  422. unsigned long remotever;
  423. pktout = sftp_pkt_init(SSH_FXP_INIT);
  424. sftp_pkt_adduint32(pktout, SFTP_PROTO_VERSION);
  425. sftp_send(pktout);
  426. pktin = sftp_recv();
  427. if (!pktin) {
  428. fxp_internal_error("could not connect");
  429. return 0;
  430. }
  431. if (pktin->type != SSH_FXP_VERSION) {
  432. fxp_internal_error("did not receive FXP_VERSION");
  433. sftp_pkt_free(pktin);
  434. return 0;
  435. }
  436. if (!sftp_pkt_getuint32(pktin, &remotever)) {
  437. fxp_internal_error("malformed FXP_VERSION packet");
  438. sftp_pkt_free(pktin);
  439. return 0;
  440. }
  441. if (remotever > SFTP_PROTO_VERSION) {
  442. fxp_internal_error
  443. ("remote protocol is more advanced than we support");
  444. sftp_pkt_free(pktin);
  445. return 0;
  446. }
  447. /*
  448. * In principle, this packet might also contain extension-
  449. * string pairs. We should work through them and look for any
  450. * we recognise. In practice we don't currently do so because
  451. * we know we don't recognise _any_.
  452. */
  453. sftp_pkt_free(pktin);
  454. return 1;
  455. }
  456. /*
  457. * Canonify a pathname.
  458. */
  459. struct sftp_request *fxp_realpath_send(const char *path)
  460. {
  461. struct sftp_request *req = sftp_alloc_request();
  462. struct sftp_packet *pktout;
  463. pktout = sftp_pkt_init(SSH_FXP_REALPATH);
  464. sftp_pkt_adduint32(pktout, req->id);
  465. sftp_pkt_addstring_start(pktout);
  466. sftp_pkt_addstring_str(pktout, path);
  467. sftp_send(pktout);
  468. return req;
  469. }
  470. char *fxp_realpath_recv(struct sftp_packet *pktin, struct sftp_request *req)
  471. {
  472. sfree(req);
  473. if (pktin->type == SSH_FXP_NAME) {
  474. unsigned long count;
  475. char *path;
  476. int len;
  477. if (!sftp_pkt_getuint32(pktin, &count) || count != 1) {
  478. fxp_internal_error("REALPATH did not return name count of 1\n");
  479. sftp_pkt_free(pktin);
  480. return NULL;
  481. }
  482. if (!sftp_pkt_getstring(pktin, &path, &len)) {
  483. fxp_internal_error("REALPATH returned malformed FXP_NAME\n");
  484. sftp_pkt_free(pktin);
  485. return NULL;
  486. }
  487. path = mkstr(path, len);
  488. sftp_pkt_free(pktin);
  489. return path;
  490. } else {
  491. fxp_got_status(pktin);
  492. sftp_pkt_free(pktin);
  493. return NULL;
  494. }
  495. }
  496. /*
  497. * Open a file.
  498. */
  499. struct sftp_request *fxp_open_send(const char *path, int type,
  500. struct fxp_attrs *attrs)
  501. {
  502. struct sftp_request *req = sftp_alloc_request();
  503. struct sftp_packet *pktout;
  504. pktout = sftp_pkt_init(SSH_FXP_OPEN);
  505. sftp_pkt_adduint32(pktout, req->id);
  506. sftp_pkt_addstring(pktout, path);
  507. sftp_pkt_adduint32(pktout, type);
  508. if (attrs)
  509. sftp_pkt_addattrs(pktout, *attrs);
  510. else
  511. sftp_pkt_adduint32(pktout, 0); /* empty ATTRS structure */
  512. sftp_send(pktout);
  513. return req;
  514. }
  515. struct fxp_handle *fxp_open_recv(struct sftp_packet *pktin,
  516. struct sftp_request *req)
  517. {
  518. sfree(req);
  519. if (pktin->type == SSH_FXP_HANDLE) {
  520. char *hstring;
  521. struct fxp_handle *handle;
  522. int len;
  523. if (!sftp_pkt_getstring(pktin, &hstring, &len)) {
  524. fxp_internal_error("OPEN returned malformed FXP_HANDLE\n");
  525. sftp_pkt_free(pktin);
  526. return NULL;
  527. }
  528. handle = snew(struct fxp_handle);
  529. handle->hstring = mkstr(hstring, len);
  530. handle->hlen = len;
  531. sftp_pkt_free(pktin);
  532. return handle;
  533. } else {
  534. fxp_got_status(pktin);
  535. sftp_pkt_free(pktin);
  536. return NULL;
  537. }
  538. }
  539. /*
  540. * Open a directory.
  541. */
  542. struct sftp_request *fxp_opendir_send(const char *path)
  543. {
  544. struct sftp_request *req = sftp_alloc_request();
  545. struct sftp_packet *pktout;
  546. pktout = sftp_pkt_init(SSH_FXP_OPENDIR);
  547. sftp_pkt_adduint32(pktout, req->id);
  548. sftp_pkt_addstring(pktout, path);
  549. sftp_send(pktout);
  550. return req;
  551. }
  552. struct fxp_handle *fxp_opendir_recv(struct sftp_packet *pktin,
  553. struct sftp_request *req)
  554. {
  555. sfree(req);
  556. if (pktin->type == SSH_FXP_HANDLE) {
  557. char *hstring;
  558. struct fxp_handle *handle;
  559. int len;
  560. if (!sftp_pkt_getstring(pktin, &hstring, &len)) {
  561. fxp_internal_error("OPENDIR returned malformed FXP_HANDLE\n");
  562. sftp_pkt_free(pktin);
  563. return NULL;
  564. }
  565. handle = snew(struct fxp_handle);
  566. handle->hstring = mkstr(hstring, len);
  567. handle->hlen = len;
  568. sftp_pkt_free(pktin);
  569. return handle;
  570. } else {
  571. fxp_got_status(pktin);
  572. sftp_pkt_free(pktin);
  573. return NULL;
  574. }
  575. }
  576. /*
  577. * Close a file/dir.
  578. */
  579. struct sftp_request *fxp_close_send(struct fxp_handle *handle)
  580. {
  581. struct sftp_request *req = sftp_alloc_request();
  582. struct sftp_packet *pktout;
  583. pktout = sftp_pkt_init(SSH_FXP_CLOSE);
  584. sftp_pkt_adduint32(pktout, req->id);
  585. sftp_pkt_addstring_start(pktout);
  586. sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
  587. sftp_send(pktout);
  588. sfree(handle->hstring);
  589. sfree(handle);
  590. return req;
  591. }
  592. void fxp_close_recv(struct sftp_packet *pktin, struct sftp_request *req)
  593. {
  594. sfree(req);
  595. fxp_got_status(pktin);
  596. sftp_pkt_free(pktin);
  597. }
  598. struct sftp_request *fxp_mkdir_send(const char *path)
  599. {
  600. struct sftp_request *req = sftp_alloc_request();
  601. struct sftp_packet *pktout;
  602. pktout = sftp_pkt_init(SSH_FXP_MKDIR);
  603. sftp_pkt_adduint32(pktout, req->id);
  604. sftp_pkt_addstring(pktout, path);
  605. sftp_pkt_adduint32(pktout, 0); /* (FIXME) empty ATTRS structure */
  606. sftp_send(pktout);
  607. return req;
  608. }
  609. int fxp_mkdir_recv(struct sftp_packet *pktin, struct sftp_request *req)
  610. {
  611. int id;
  612. sfree(req);
  613. id = fxp_got_status(pktin);
  614. sftp_pkt_free(pktin);
  615. if (id != 1) {
  616. return 0;
  617. }
  618. return 1;
  619. }
  620. struct sftp_request *fxp_rmdir_send(const char *path)
  621. {
  622. struct sftp_request *req = sftp_alloc_request();
  623. struct sftp_packet *pktout;
  624. pktout = sftp_pkt_init(SSH_FXP_RMDIR);
  625. sftp_pkt_adduint32(pktout, req->id);
  626. sftp_pkt_addstring(pktout, path);
  627. sftp_send(pktout);
  628. return req;
  629. }
  630. int fxp_rmdir_recv(struct sftp_packet *pktin, struct sftp_request *req)
  631. {
  632. int id;
  633. sfree(req);
  634. id = fxp_got_status(pktin);
  635. sftp_pkt_free(pktin);
  636. if (id != 1) {
  637. return 0;
  638. }
  639. return 1;
  640. }
  641. struct sftp_request *fxp_remove_send(const char *fname)
  642. {
  643. struct sftp_request *req = sftp_alloc_request();
  644. struct sftp_packet *pktout;
  645. pktout = sftp_pkt_init(SSH_FXP_REMOVE);
  646. sftp_pkt_adduint32(pktout, req->id);
  647. sftp_pkt_addstring(pktout, fname);
  648. sftp_send(pktout);
  649. return req;
  650. }
  651. int fxp_remove_recv(struct sftp_packet *pktin, struct sftp_request *req)
  652. {
  653. int id;
  654. sfree(req);
  655. id = fxp_got_status(pktin);
  656. sftp_pkt_free(pktin);
  657. if (id != 1) {
  658. return 0;
  659. }
  660. return 1;
  661. }
  662. struct sftp_request *fxp_rename_send(const char *srcfname,
  663. const char *dstfname)
  664. {
  665. struct sftp_request *req = sftp_alloc_request();
  666. struct sftp_packet *pktout;
  667. pktout = sftp_pkt_init(SSH_FXP_RENAME);
  668. sftp_pkt_adduint32(pktout, req->id);
  669. sftp_pkt_addstring(pktout, srcfname);
  670. sftp_pkt_addstring(pktout, dstfname);
  671. sftp_send(pktout);
  672. return req;
  673. }
  674. int fxp_rename_recv(struct sftp_packet *pktin, struct sftp_request *req)
  675. {
  676. int id;
  677. sfree(req);
  678. id = fxp_got_status(pktin);
  679. sftp_pkt_free(pktin);
  680. if (id != 1) {
  681. return 0;
  682. }
  683. return 1;
  684. }
  685. /*
  686. * Retrieve the attributes of a file. We have fxp_stat which works
  687. * on filenames, and fxp_fstat which works on open file handles.
  688. */
  689. struct sftp_request *fxp_stat_send(const char *fname)
  690. {
  691. struct sftp_request *req = sftp_alloc_request();
  692. struct sftp_packet *pktout;
  693. pktout = sftp_pkt_init(SSH_FXP_STAT);
  694. sftp_pkt_adduint32(pktout, req->id);
  695. sftp_pkt_addstring(pktout, fname);
  696. sftp_send(pktout);
  697. return req;
  698. }
  699. int fxp_stat_recv(struct sftp_packet *pktin, struct sftp_request *req,
  700. struct fxp_attrs *attrs)
  701. {
  702. sfree(req);
  703. if (pktin->type == SSH_FXP_ATTRS) {
  704. if (!sftp_pkt_getattrs(pktin, attrs)) {
  705. fxp_internal_error("malformed SSH_FXP_ATTRS packet");
  706. sftp_pkt_free(pktin);
  707. return 0;
  708. }
  709. sftp_pkt_free(pktin);
  710. return 1;
  711. } else {
  712. fxp_got_status(pktin);
  713. sftp_pkt_free(pktin);
  714. return 0;
  715. }
  716. }
  717. struct sftp_request *fxp_fstat_send(struct fxp_handle *handle)
  718. {
  719. struct sftp_request *req = sftp_alloc_request();
  720. struct sftp_packet *pktout;
  721. pktout = sftp_pkt_init(SSH_FXP_FSTAT);
  722. sftp_pkt_adduint32(pktout, req->id);
  723. sftp_pkt_addstring_start(pktout);
  724. sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
  725. sftp_send(pktout);
  726. return req;
  727. }
  728. int fxp_fstat_recv(struct sftp_packet *pktin, struct sftp_request *req,
  729. struct fxp_attrs *attrs)
  730. {
  731. sfree(req);
  732. if (pktin->type == SSH_FXP_ATTRS) {
  733. if (!sftp_pkt_getattrs(pktin, attrs)) {
  734. fxp_internal_error("malformed SSH_FXP_ATTRS packet");
  735. sftp_pkt_free(pktin);
  736. return 0;
  737. }
  738. sftp_pkt_free(pktin);
  739. return 1;
  740. } else {
  741. fxp_got_status(pktin);
  742. sftp_pkt_free(pktin);
  743. return 0;
  744. }
  745. }
  746. /*
  747. * Set the attributes of a file.
  748. */
  749. struct sftp_request *fxp_setstat_send(const char *fname,
  750. struct fxp_attrs attrs)
  751. {
  752. struct sftp_request *req = sftp_alloc_request();
  753. struct sftp_packet *pktout;
  754. pktout = sftp_pkt_init(SSH_FXP_SETSTAT);
  755. sftp_pkt_adduint32(pktout, req->id);
  756. sftp_pkt_addstring(pktout, fname);
  757. sftp_pkt_addattrs(pktout, attrs);
  758. sftp_send(pktout);
  759. return req;
  760. }
  761. int fxp_setstat_recv(struct sftp_packet *pktin, struct sftp_request *req)
  762. {
  763. int id;
  764. sfree(req);
  765. id = fxp_got_status(pktin);
  766. sftp_pkt_free(pktin);
  767. if (id != 1) {
  768. return 0;
  769. }
  770. return 1;
  771. }
  772. struct sftp_request *fxp_fsetstat_send(struct fxp_handle *handle,
  773. struct fxp_attrs attrs)
  774. {
  775. struct sftp_request *req = sftp_alloc_request();
  776. struct sftp_packet *pktout;
  777. pktout = sftp_pkt_init(SSH_FXP_FSETSTAT);
  778. sftp_pkt_adduint32(pktout, req->id);
  779. sftp_pkt_addstring_start(pktout);
  780. sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
  781. sftp_pkt_addattrs(pktout, attrs);
  782. sftp_send(pktout);
  783. return req;
  784. }
  785. int fxp_fsetstat_recv(struct sftp_packet *pktin, struct sftp_request *req)
  786. {
  787. int id;
  788. sfree(req);
  789. id = fxp_got_status(pktin);
  790. sftp_pkt_free(pktin);
  791. if (id != 1) {
  792. return 0;
  793. }
  794. return 1;
  795. }
  796. /*
  797. * Read from a file. Returns the number of bytes read, or -1 on an
  798. * error, or possibly 0 if EOF. (I'm not entirely sure whether it
  799. * will return 0 on EOF, or return -1 and store SSH_FX_EOF in the
  800. * error indicator. It might even depend on the SFTP server.)
  801. */
  802. struct sftp_request *fxp_read_send(struct fxp_handle *handle,
  803. uint64 offset, int len)
  804. {
  805. struct sftp_request *req = sftp_alloc_request();
  806. struct sftp_packet *pktout;
  807. pktout = sftp_pkt_init(SSH_FXP_READ);
  808. sftp_pkt_adduint32(pktout, req->id);
  809. sftp_pkt_addstring_start(pktout);
  810. sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
  811. sftp_pkt_adduint64(pktout, offset);
  812. sftp_pkt_adduint32(pktout, len);
  813. sftp_send(pktout);
  814. return req;
  815. }
  816. int fxp_read_recv(struct sftp_packet *pktin, struct sftp_request *req,
  817. char *buffer, int len)
  818. {
  819. sfree(req);
  820. if (pktin->type == SSH_FXP_DATA) {
  821. char *str;
  822. int rlen;
  823. if (!sftp_pkt_getstring(pktin, &str, &rlen)) {
  824. fxp_internal_error("READ returned malformed SSH_FXP_DATA packet");
  825. sftp_pkt_free(pktin);
  826. return -1;
  827. }
  828. if (rlen > len || rlen < 0) {
  829. fxp_internal_error("READ returned more bytes than requested");
  830. sftp_pkt_free(pktin);
  831. return -1;
  832. }
  833. memcpy(buffer, str, rlen);
  834. sftp_pkt_free(pktin);
  835. return rlen;
  836. } else {
  837. fxp_got_status(pktin);
  838. sftp_pkt_free(pktin);
  839. return -1;
  840. }
  841. }
  842. /*
  843. * Read from a directory.
  844. */
  845. struct sftp_request *fxp_readdir_send(struct fxp_handle *handle)
  846. {
  847. struct sftp_request *req = sftp_alloc_request();
  848. struct sftp_packet *pktout;
  849. pktout = sftp_pkt_init(SSH_FXP_READDIR);
  850. sftp_pkt_adduint32(pktout, req->id);
  851. sftp_pkt_addstring_start(pktout);
  852. sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
  853. sftp_send(pktout);
  854. return req;
  855. }
  856. struct fxp_names *fxp_readdir_recv(struct sftp_packet *pktin,
  857. struct sftp_request *req)
  858. {
  859. sfree(req);
  860. if (pktin->type == SSH_FXP_NAME) {
  861. struct fxp_names *ret;
  862. unsigned long i;
  863. /*
  864. * Sanity-check the number of names. Minimum is obviously
  865. * zero. Maximum is the remaining space in the packet
  866. * divided by the very minimum length of a name, which is
  867. * 12 bytes (4 for an empty filename, 4 for an empty
  868. * longname, 4 for a set of attribute flags indicating that
  869. * no other attributes are supplied).
  870. */
  871. if (!sftp_pkt_getuint32(pktin, &i) ||
  872. i > (pktin->length-pktin->savedpos)/12) {
  873. fxp_internal_error("malformed FXP_NAME packet");
  874. sftp_pkt_free(pktin);
  875. return NULL;
  876. }
  877. /*
  878. * Ensure the implicit multiplication in the snewn() call
  879. * doesn't suffer integer overflow and cause us to malloc
  880. * too little space.
  881. */
  882. if (i > INT_MAX / sizeof(struct fxp_name)) {
  883. fxp_internal_error("unreasonably large FXP_NAME packet");
  884. sftp_pkt_free(pktin);
  885. return NULL;
  886. }
  887. ret = snew(struct fxp_names);
  888. ret->nnames = i;
  889. ret->names = snewn(ret->nnames, struct fxp_name);
  890. for (i = 0; i < (unsigned long)ret->nnames; i++) {
  891. char *str1, *str2;
  892. int len1, len2;
  893. if (!sftp_pkt_getstring(pktin, &str1, &len1) ||
  894. !sftp_pkt_getstring(pktin, &str2, &len2) ||
  895. !sftp_pkt_getattrs(pktin, &ret->names[i].attrs)) {
  896. fxp_internal_error("malformed FXP_NAME packet");
  897. while (i--) {
  898. sfree(ret->names[i].filename);
  899. sfree(ret->names[i].longname);
  900. }
  901. sfree(ret->names);
  902. sfree(ret);
  903. sfree(pktin);
  904. return NULL;
  905. }
  906. ret->names[i].filename = mkstr(str1, len1);
  907. ret->names[i].longname = mkstr(str2, len2);
  908. }
  909. sftp_pkt_free(pktin);
  910. return ret;
  911. } else {
  912. fxp_got_status(pktin);
  913. sftp_pkt_free(pktin);
  914. return NULL;
  915. }
  916. }
  917. /*
  918. * Write to a file. Returns 0 on error, 1 on OK.
  919. */
  920. struct sftp_request *fxp_write_send(struct fxp_handle *handle,
  921. char *buffer, uint64 offset, int len)
  922. {
  923. struct sftp_request *req = sftp_alloc_request();
  924. struct sftp_packet *pktout;
  925. pktout = sftp_pkt_init(SSH_FXP_WRITE);
  926. sftp_pkt_adduint32(pktout, req->id);
  927. sftp_pkt_addstring_start(pktout);
  928. sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
  929. sftp_pkt_adduint64(pktout, offset);
  930. sftp_pkt_addstring_start(pktout);
  931. sftp_pkt_addstring_data(pktout, buffer, len);
  932. sftp_send(pktout);
  933. return req;
  934. }
  935. int fxp_write_recv(struct sftp_packet *pktin, struct sftp_request *req)
  936. {
  937. sfree(req);
  938. fxp_got_status(pktin);
  939. sftp_pkt_free(pktin);
  940. return fxp_errtype == SSH_FX_OK;
  941. }
  942. /*
  943. * Free up an fxp_names structure.
  944. */
  945. void fxp_free_names(struct fxp_names *names)
  946. {
  947. int i;
  948. for (i = 0; i < names->nnames; i++) {
  949. sfree(names->names[i].filename);
  950. sfree(names->names[i].longname);
  951. }
  952. sfree(names->names);
  953. sfree(names);
  954. }
  955. /*
  956. * Duplicate an fxp_name structure.
  957. */
  958. struct fxp_name *fxp_dup_name(struct fxp_name *name)
  959. {
  960. struct fxp_name *ret;
  961. ret = snew(struct fxp_name);
  962. ret->filename = dupstr(name->filename);
  963. ret->longname = dupstr(name->longname);
  964. ret->attrs = name->attrs; /* structure copy */
  965. return ret;
  966. }
  967. /*
  968. * Free up an fxp_name structure.
  969. */
  970. void fxp_free_name(struct fxp_name *name)
  971. {
  972. sfree(name->filename);
  973. sfree(name->longname);
  974. sfree(name);
  975. }
  976. /*
  977. * Store user data in an sftp_request structure.
  978. */
  979. void *fxp_get_userdata(struct sftp_request *req)
  980. {
  981. return req->userdata;
  982. }
  983. void fxp_set_userdata(struct sftp_request *req, void *data)
  984. {
  985. req->userdata = data;
  986. }
  987. /*
  988. * A wrapper to go round fxp_read_* and fxp_write_*, which manages
  989. * the queueing of multiple read/write requests.
  990. */
  991. struct req {
  992. char *buffer;
  993. int len, retlen, complete;
  994. uint64 offset;
  995. struct req *next, *prev;
  996. };
  997. struct fxp_xfer {
  998. uint64 offset, furthestdata, filesize;
  999. int req_totalsize, req_maxsize, eof, err;
  1000. struct fxp_handle *fh;
  1001. struct req *head, *tail;
  1002. };
  1003. static struct fxp_xfer *xfer_init(struct fxp_handle *fh, uint64 offset)
  1004. {
  1005. struct fxp_xfer *xfer = snew(struct fxp_xfer);
  1006. xfer->fh = fh;
  1007. xfer->offset = offset;
  1008. xfer->head = xfer->tail = NULL;
  1009. xfer->req_totalsize = 0;
  1010. xfer->req_maxsize = 1048576;
  1011. xfer->err = 0;
  1012. xfer->filesize = uint64_make(ULONG_MAX, ULONG_MAX);
  1013. xfer->furthestdata = uint64_make(0, 0);
  1014. return xfer;
  1015. }
  1016. int xfer_done(struct fxp_xfer *xfer)
  1017. {
  1018. /*
  1019. * We're finished if we've seen EOF _and_ there are no
  1020. * outstanding requests.
  1021. */
  1022. return (xfer->eof || xfer->err) && !xfer->head;
  1023. }
  1024. void xfer_download_queue(struct fxp_xfer *xfer)
  1025. {
  1026. while (xfer->req_totalsize < xfer->req_maxsize &&
  1027. !xfer->eof && !xfer->err) {
  1028. /*
  1029. * Queue a new read request.
  1030. */
  1031. struct req *rr;
  1032. struct sftp_request *req;
  1033. rr = snew(struct req);
  1034. rr->offset = xfer->offset;
  1035. rr->complete = 0;
  1036. if (xfer->tail) {
  1037. xfer->tail->next = rr;
  1038. rr->prev = xfer->tail;
  1039. } else {
  1040. xfer->head = rr;
  1041. rr->prev = NULL;
  1042. }
  1043. xfer->tail = rr;
  1044. rr->next = NULL;
  1045. rr->len = 32768;
  1046. rr->buffer = snewn(rr->len, char);
  1047. sftp_register(req = fxp_read_send(xfer->fh, rr->offset, rr->len));
  1048. fxp_set_userdata(req, rr);
  1049. xfer->offset = uint64_add32(xfer->offset, rr->len);
  1050. xfer->req_totalsize += rr->len;
  1051. #ifdef DEBUG_DOWNLOAD
  1052. { char buf[40]; uint64_decimal(rr->offset, buf); printf("queueing read request %p at %s\n", rr, buf); }
  1053. #endif
  1054. }
  1055. }
  1056. struct fxp_xfer *xfer_download_init(struct fxp_handle *fh, uint64 offset)
  1057. {
  1058. struct fxp_xfer *xfer = xfer_init(fh, offset);
  1059. xfer->eof = FALSE;
  1060. xfer_download_queue(xfer);
  1061. return xfer;
  1062. }
  1063. /*
  1064. * Returns INT_MIN to indicate that it didn't even get as far as
  1065. * fxp_read_recv and hence has not freed pktin.
  1066. */
  1067. int xfer_download_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
  1068. {
  1069. struct sftp_request *rreq;
  1070. struct req *rr;
  1071. rreq = sftp_find_request(pktin);
  1072. if (!rreq)
  1073. return INT_MIN; /* this packet doesn't even make sense */
  1074. rr = (struct req *)fxp_get_userdata(rreq);
  1075. if (!rr) {
  1076. fxp_internal_error("request ID is not part of the current download");
  1077. return INT_MIN; /* this packet isn't ours */
  1078. }
  1079. rr->retlen = fxp_read_recv(pktin, rreq, rr->buffer, rr->len);
  1080. #ifdef DEBUG_DOWNLOAD
  1081. printf("read request %p has returned [%d]\n", rr, rr->retlen);
  1082. #endif
  1083. if ((rr->retlen < 0 && fxp_error_type()==SSH_FX_EOF) || rr->retlen == 0) {
  1084. xfer->eof = TRUE;
  1085. rr->complete = -1;
  1086. #ifdef DEBUG_DOWNLOAD
  1087. printf("setting eof\n");
  1088. #endif
  1089. } else if (rr->retlen < 0) {
  1090. /* some error other than EOF; signal it back to caller */
  1091. xfer_set_error(xfer);
  1092. rr->complete = -1;
  1093. return -1;
  1094. }
  1095. rr->complete = 1;
  1096. /*
  1097. * Special case: if we have received fewer bytes than we
  1098. * actually read, we should do something. For the moment I'll
  1099. * just throw an ersatz FXP error to signal this; the SFTP
  1100. * draft I've got says that it can't happen except on special
  1101. * files, in which case seeking probably has very little
  1102. * meaning and so queueing an additional read request to fill
  1103. * up the gap sounds like the wrong answer. I'm not sure what I
  1104. * should be doing here - if it _was_ a special file, I suspect
  1105. * I simply shouldn't have been queueing multiple requests in
  1106. * the first place...
  1107. */
  1108. if (rr->retlen > 0 && uint64_compare(xfer->furthestdata, rr->offset) < 0) {
  1109. xfer->furthestdata = rr->offset;
  1110. #ifdef DEBUG_DOWNLOAD
  1111. { char buf[40];
  1112. uint64_decimal(xfer->furthestdata, buf);
  1113. printf("setting furthestdata = %s\n", buf); }
  1114. #endif
  1115. }
  1116. if (rr->retlen < rr->len) {
  1117. uint64 filesize = uint64_add32(rr->offset,
  1118. (rr->retlen < 0 ? 0 : rr->retlen));
  1119. #ifdef DEBUG_DOWNLOAD
  1120. { char buf[40];
  1121. uint64_decimal(filesize, buf);
  1122. printf("short block! trying filesize = %s\n", buf); }
  1123. #endif
  1124. if (uint64_compare(xfer->filesize, filesize) > 0) {
  1125. xfer->filesize = filesize;
  1126. #ifdef DEBUG_DOWNLOAD
  1127. printf("actually changing filesize\n");
  1128. #endif
  1129. }
  1130. }
  1131. if (uint64_compare(xfer->furthestdata, xfer->filesize) > 0) {
  1132. fxp_error_message = "received a short buffer from FXP_READ, but not"
  1133. " at EOF";
  1134. fxp_errtype = -1;
  1135. xfer_set_error(xfer);
  1136. return -1;
  1137. }
  1138. return 1;
  1139. }
  1140. void xfer_set_error(struct fxp_xfer *xfer)
  1141. {
  1142. xfer->err = 1;
  1143. }
  1144. int xfer_download_data(struct fxp_xfer *xfer, void **buf, int *len)
  1145. {
  1146. void *retbuf = NULL;
  1147. int retlen = 0;
  1148. /*
  1149. * Discard anything at the head of the rr queue with complete <
  1150. * 0; return the first thing with complete > 0.
  1151. */
  1152. while (xfer->head && xfer->head->complete && !retbuf) {
  1153. struct req *rr = xfer->head;
  1154. if (rr->complete > 0) {
  1155. retbuf = rr->buffer;
  1156. retlen = rr->retlen;
  1157. #ifdef DEBUG_DOWNLOAD
  1158. printf("handing back data from read request %p\n", rr);
  1159. #endif
  1160. }
  1161. #ifdef DEBUG_DOWNLOAD
  1162. else
  1163. printf("skipping failed read request %p\n", rr);
  1164. #endif
  1165. xfer->head = xfer->head->next;
  1166. if (xfer->head)
  1167. xfer->head->prev = NULL;
  1168. else
  1169. xfer->tail = NULL;
  1170. xfer->req_totalsize -= rr->len;
  1171. sfree(rr);
  1172. }
  1173. if (retbuf) {
  1174. *buf = retbuf;
  1175. *len = retlen;
  1176. return 1;
  1177. } else
  1178. return 0;
  1179. }
  1180. struct fxp_xfer *xfer_upload_init(struct fxp_handle *fh, uint64 offset)
  1181. {
  1182. struct fxp_xfer *xfer = xfer_init(fh, offset);
  1183. /*
  1184. * We set `eof' to 1 because this will cause xfer_done() to
  1185. * return true iff there are no outstanding requests. During an
  1186. * upload, our caller will be responsible for working out
  1187. * whether all the data has been sent, so all it needs to know
  1188. * from us is whether the outstanding requests have been
  1189. * handled once that's done.
  1190. */
  1191. xfer->eof = 1;
  1192. return xfer;
  1193. }
  1194. int xfer_upload_ready(struct fxp_xfer *xfer)
  1195. {
  1196. if (sftp_sendbuffer() == 0)
  1197. return 1;
  1198. else
  1199. return 0;
  1200. }
  1201. void xfer_upload_data(struct fxp_xfer *xfer, char *buffer, int len)
  1202. {
  1203. struct req *rr;
  1204. struct sftp_request *req;
  1205. rr = snew(struct req);
  1206. rr->offset = xfer->offset;
  1207. rr->complete = 0;
  1208. if (xfer->tail) {
  1209. xfer->tail->next = rr;
  1210. rr->prev = xfer->tail;
  1211. } else {
  1212. xfer->head = rr;
  1213. rr->prev = NULL;
  1214. }
  1215. xfer->tail = rr;
  1216. rr->next = NULL;
  1217. rr->len = len;
  1218. rr->buffer = NULL;
  1219. sftp_register(req = fxp_write_send(xfer->fh, buffer, rr->offset, len));
  1220. fxp_set_userdata(req, rr);
  1221. xfer->offset = uint64_add32(xfer->offset, rr->len);
  1222. xfer->req_totalsize += rr->len;
  1223. #ifdef DEBUG_UPLOAD
  1224. { char buf[40]; uint64_decimal(rr->offset, buf); printf("queueing write request %p at %s [len %d]\n", rr, buf, len); }
  1225. #endif
  1226. }
  1227. /*
  1228. * Returns INT_MIN to indicate that it didn't even get as far as
  1229. * fxp_write_recv and hence has not freed pktin.
  1230. */
  1231. int xfer_upload_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
  1232. {
  1233. struct sftp_request *rreq;
  1234. struct req *rr, *prev, *next;
  1235. int ret;
  1236. rreq = sftp_find_request(pktin);
  1237. if (!rreq)
  1238. return INT_MIN; /* this packet doesn't even make sense */
  1239. rr = (struct req *)fxp_get_userdata(rreq);
  1240. if (!rr) {
  1241. fxp_internal_error("request ID is not part of the current upload");
  1242. return INT_MIN; /* this packet isn't ours */
  1243. }
  1244. ret = fxp_write_recv(pktin, rreq);
  1245. #ifdef DEBUG_UPLOAD
  1246. printf("write request %p has returned [%d]\n", rr, ret);
  1247. #endif
  1248. /*
  1249. * Remove this one from the queue.
  1250. */
  1251. prev = rr->prev;
  1252. next = rr->next;
  1253. if (prev)
  1254. prev->next = next;
  1255. else
  1256. xfer->head = next;
  1257. if (next)
  1258. next->prev = prev;
  1259. else
  1260. xfer->tail = prev;
  1261. xfer->req_totalsize -= rr->len;
  1262. sfree(rr);
  1263. if (!ret)
  1264. return -1;
  1265. return 1;
  1266. }
  1267. void xfer_cleanup(struct fxp_xfer *xfer)
  1268. {
  1269. struct req *rr;
  1270. while (xfer->head) {
  1271. rr = xfer->head;
  1272. xfer->head = xfer->head->next;
  1273. sfree(rr->buffer);
  1274. sfree(rr);
  1275. }
  1276. sfree(xfer);
  1277. }