geom_gate userland utility improvements
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

299 lines
7.6 KiB

  1. /*
  2. * Sample showing how to do SFTP non-blocking write transfers.
  3. *
  4. * The sample code has default values for host name, user name, password
  5. * and path to copy, but you can specify them on the command line like:
  6. *
  7. * "sftp 192.168.0.1 user password file /tmp/storehere"
  8. */
  9. #include "libssh2_config.h"
  10. #include <libssh2.h>
  11. #include <libssh2_sftp.h>
  12. #ifdef HAVE_WINSOCK2_H
  13. # include <winsock2.h>
  14. #endif
  15. #ifdef HAVE_SYS_SOCKET_H
  16. # include <sys/socket.h>
  17. #endif
  18. #ifdef HAVE_NETINET_IN_H
  19. # include <netinet/in.h>
  20. #endif
  21. #ifdef HAVE_SYS_SELECT_H
  22. # include <sys/select.h>
  23. #endif
  24. # ifdef HAVE_UNISTD_H
  25. #include <unistd.h>
  26. #endif
  27. #ifdef HAVE_ARPA_INET_H
  28. # include <arpa/inet.h>
  29. #endif
  30. #ifdef HAVE_SYS_TIME_H
  31. # include <sys/time.h>
  32. #endif
  33. #include <sys/types.h>
  34. #include <fcntl.h>
  35. #include <errno.h>
  36. #include <stdio.h>
  37. #include <ctype.h>
  38. #include <time.h>
  39. static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
  40. {
  41. struct timeval timeout;
  42. int rc;
  43. fd_set fd;
  44. fd_set *writefd = NULL;
  45. fd_set *readfd = NULL;
  46. int dir;
  47. timeout.tv_sec = 10;
  48. timeout.tv_usec = 0;
  49. FD_ZERO(&fd);
  50. FD_SET(socket_fd, &fd);
  51. /* now make sure we wait in the correct direction */
  52. dir = libssh2_session_block_directions(session);
  53. if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
  54. readfd = &fd;
  55. if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
  56. writefd = &fd;
  57. rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
  58. return rc;
  59. }
  60. int main(int argc, char *argv[])
  61. {
  62. unsigned long hostaddr;
  63. int sock, i, auth_pw = 1;
  64. struct sockaddr_in sin;
  65. const char *fingerprint;
  66. LIBSSH2_SESSION *session;
  67. const char *username = "username";
  68. const char *password = "password";
  69. const char *loclfile = "sftp_write_nonblock.c";
  70. const char *sftppath = "/tmp/sftp_write_nonblock.c";
  71. int rc;
  72. FILE *local;
  73. LIBSSH2_SFTP *sftp_session;
  74. LIBSSH2_SFTP_HANDLE *sftp_handle;
  75. char mem[1024 * 1000];
  76. size_t nread;
  77. size_t memuse;
  78. time_t start;
  79. long total = 0;
  80. int duration;
  81. #ifdef WIN32
  82. WSADATA wsadata;
  83. int err;
  84. err = WSAStartup(MAKEWORD(2, 0), &wsadata);
  85. if(err != 0) {
  86. fprintf(stderr, "WSAStartup failed with error: %d\n", err);
  87. return 1;
  88. }
  89. #endif
  90. if(argc > 1) {
  91. hostaddr = inet_addr(argv[1]);
  92. }
  93. else {
  94. hostaddr = htonl(0x7F000001);
  95. }
  96. if(argc > 2) {
  97. username = argv[2];
  98. }
  99. if(argc > 3) {
  100. password = argv[3];
  101. }
  102. if(argc > 4) {
  103. loclfile = argv[4];
  104. }
  105. if(argc > 5) {
  106. sftppath = argv[5];
  107. }
  108. rc = libssh2_init(0);
  109. if(rc != 0) {
  110. fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
  111. return 1;
  112. }
  113. local = fopen(loclfile, "rb");
  114. if(!local) {
  115. fprintf(stderr, "Can't open local file %s\n", loclfile);
  116. return -1;
  117. }
  118. /*
  119. * The application code is responsible for creating the socket
  120. * and establishing the connection
  121. */
  122. sock = socket(AF_INET, SOCK_STREAM, 0);
  123. sin.sin_family = AF_INET;
  124. sin.sin_port = htons(22);
  125. sin.sin_addr.s_addr = hostaddr;
  126. if(connect(sock, (struct sockaddr*)(&sin),
  127. sizeof(struct sockaddr_in)) != 0) {
  128. fprintf(stderr, "failed to connect!\n");
  129. return -1;
  130. }
  131. /* Create a session instance
  132. */
  133. session = libssh2_session_init();
  134. if(!session)
  135. return -1;
  136. /* Since we have set non-blocking, tell libssh2 we are non-blocking */
  137. libssh2_session_set_blocking(session, 0);
  138. /* ... start it up. This will trade welcome banners, exchange keys,
  139. * and setup crypto, compression, and MAC layers
  140. */
  141. while((rc = libssh2_session_handshake(session, sock))
  142. == LIBSSH2_ERROR_EAGAIN);
  143. if(rc) {
  144. fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
  145. return -1;
  146. }
  147. /* At this point we havn't yet authenticated. The first thing to do is
  148. * check the hostkey's fingerprint against our known hosts Your app may
  149. * have it hard coded, may go to a file, may present it to the user,
  150. * that's your call
  151. */
  152. fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
  153. fprintf(stderr, "Fingerprint: ");
  154. for(i = 0; i < 20; i++) {
  155. fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
  156. }
  157. fprintf(stderr, "\n");
  158. if(auth_pw) {
  159. /* We could authenticate via password */
  160. while((rc = libssh2_userauth_password(session, username, password)) ==
  161. LIBSSH2_ERROR_EAGAIN);
  162. if(rc) {
  163. fprintf(stderr, "Authentication by password failed.\n");
  164. goto shutdown;
  165. }
  166. }
  167. else {
  168. /* Or by public key */
  169. #define PUBKEY "/home/username/.ssh/id_rsa.pub"
  170. #define PRIVKEY "/home/username/.ssh/id_rsa"
  171. while((rc = libssh2_userauth_publickey_fromfile(session, username,
  172. PUBKEY, PRIVKEY,
  173. password)) ==
  174. LIBSSH2_ERROR_EAGAIN);
  175. if(rc) {
  176. fprintf(stderr, "\tAuthentication by public key failed\n");
  177. goto shutdown;
  178. }
  179. }
  180. fprintf(stderr, "libssh2_sftp_init()!\n");
  181. do {
  182. sftp_session = libssh2_sftp_init(session);
  183. if(!sftp_session &&
  184. (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN)) {
  185. fprintf(stderr, "Unable to init SFTP session\n");
  186. goto shutdown;
  187. }
  188. } while(!sftp_session);
  189. fprintf(stderr, "libssh2_sftp_open()!\n");
  190. /* Request a file via SFTP */
  191. do {
  192. sftp_handle =
  193. libssh2_sftp_open(sftp_session, sftppath,
  194. LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|
  195. LIBSSH2_FXF_TRUNC,
  196. LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
  197. LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
  198. if(!sftp_handle &&
  199. (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN)) {
  200. fprintf(stderr, "Unable to open file with SFTP\n");
  201. goto shutdown;
  202. }
  203. } while(!sftp_handle);
  204. fprintf(stderr, "libssh2_sftp_open() is done, now send data!\n");
  205. start = time(NULL);
  206. memuse = 0; /* it starts blank */
  207. do {
  208. nread = fread(&mem[memuse], 1, sizeof(mem)-memuse, local);
  209. if(nread <= 0) {
  210. /* end of file */
  211. if(memuse > 0)
  212. /* the previous sending is not finished */
  213. nread = 0;
  214. else
  215. break;
  216. }
  217. memuse += nread;
  218. total += nread;
  219. /* write data in a loop until we block */
  220. while((rc = libssh2_sftp_write(sftp_handle, mem, memuse)) ==
  221. LIBSSH2_ERROR_EAGAIN) {
  222. waitsocket(sock, session);
  223. }
  224. if(rc < 0)
  225. break;
  226. if(memuse - rc) {
  227. /* make room for more data at the end of the buffer */
  228. memmove(&mem[0], &mem[rc], memuse - rc);
  229. memuse -= rc;
  230. }
  231. else
  232. /* 'mem' was consumed fully */
  233. memuse = 0;
  234. } while(rc > 0);
  235. duration = (int)(time(NULL)-start);
  236. fprintf(stderr, "%ld bytes in %d seconds makes %.1f bytes/sec\n",
  237. total, duration, total/(double)duration);
  238. fclose(local);
  239. libssh2_sftp_close(sftp_handle);
  240. libssh2_sftp_shutdown(sftp_session);
  241. shutdown:
  242. while(libssh2_session_disconnect(session, "Normal Shutdown")
  243. == LIBSSH2_ERROR_EAGAIN);
  244. libssh2_session_free(session);
  245. #ifdef WIN32
  246. closesocket(sock);
  247. #else
  248. close(sock);
  249. #endif
  250. fprintf(stderr, "all done\n");
  251. libssh2_exit();
  252. return 0;
  253. }