Subject: How to append to remote file?

How to append to remote file?

From: Mark Riordan <mriordan_at_ipswitch.com>
Date: Wed, 24 Nov 2010 16:19:34 -0600

How does one append to a remote file using libssh2?
(Nevermind that appending to a file usually isn't a good idea.)

I tried doing a libssh2_sftp_fstat_ex on the remote file to find its size,
then seeking to the end of the file using libssh2_sftp_seek64.
But libssh2_sftp_seek64 isn't a real seek. In this case, it
causes subsequent calls to libssh2_sftp_write to write 0 bytes.

Is there a real remote seek or append capability?

I'm reluctant to open the file with LIBSSH2_FXF_APPEND,
because of this comment in the code:
"Danger will robinson... APPEND doesn't have any effect on OpenSSH servers"

At any rate, I eventually tried the LIBSSH2_FXF_APPEND approach
and got the same problem.

I used a different SSH client to append a file to the same OpenSSH
server and it did work.

Sample code below.

Thanks.

Mark R

   remotemode = LIBSSH2_FXF_READ;
   if ("put" == settings.action || "append" == settings.action)
      remotemode = LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT;
   sftp_handle =
     libssh2_sftp_open(sftp_session, settings.remotefile.c_str(),
remotemode, 0777);

   if (!sftp_handle) {
      fprintf(stderr, "Unable to open file with SFTP\n");
      goto shutdown;
   }
   if(settings.debug > 0) fprintf(stderr, "libssh2_sftp_open()
succeeded.\n");
   if ("put" == settings.action || "append" == settings.action) {
      if("append" == settings.action) {
         LIBSSH2_SFTP_ATTRIBUTES attrs;
         if(libssh2_sftp_fstat_ex(sftp_handle, &attrs, 0) < 0) {
            printf("libssh2_sftp_fstat_ex failed\n");
         }
         libssh2_sftp_seek64(sftp_handle, attrs.filesize);
         printf("Did a seek to position %ld\n", (long) attrs.filesize);
      }
      hand = open(settings.localfile.c_str(), O_BINARY | O_RDONLY,
_S_IREAD);
      if (-1 == hand) {
         perror("opening local file");
         exit(2);
      }
      char mem[32500];
      long bytes_sent = 0;
      do {
         /* loop until we fail */
         int nbytes = read(hand, mem, sizeof(mem));

         if (nbytes > 0) {
            filesize += nbytes;
            int offset = 0, bytes_to_send = nbytes;

            do {
               rc = libssh2_sftp_write(sftp_handle, mem + offset,
bytes_to_send);
               if (rc < 0) {
                  printf("libssh2_sftp_write failed with code %d\n", rc);
                  char *errmsg=NULL;
                  int errmsg_len=0;
                  rc = libssh2_session_last_error(session, &errmsg,
&errmsg_len, 0);
                  printf("libssh2_session_last_error() returned %s\n",
errmsg);
                  break;
               } else if(0==rc) {
                  printf("libssh2_sftp_write returned 0, probably due to
seek problems.\n");
                  rc = -1;
                  break;
               }
               offset += rc;
               bytes_to_send -= rc;
            } while (bytes_to_send > 0);
         } else {
            break;
         }
      } while (rc >= 0);
   }
   close(hand);
   libssh2_sftp_close(sftp_handle);
   

_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel
Received on 2010-11-24