int FSSftp::Stat ( FSPath& path, FSStat* st, int* err, FSCInfo* info ) { MutexLock lock( &mutex ); int ret = CheckSession( err, info ); if ( ret ) { return ret; } char* fullPath = ( char* ) path.GetString( _operParam.charset ); sftp_attributes la = sftp_lstat( sftpSession, fullPath ); if ( !la ) { if ( err ) { *err = sftp_get_error( sftpSession ); } return -1; } if ( la->type == SSH_FILEXFER_TYPE_SYMLINK ) { char* s = sftp_readlink( sftpSession, fullPath ); if ( s ) { st->link.Set( _operParam.charset, s ); } sftp_attributes_free( la ); //!!! } else { st->mode = la->permissions; st->size = la->size; st->uid = la->uid; st->gid = la->gid; st->mtime = la->mtime; sftp_attributes_free( la ); //!!! return 0; } sftp_attributes a = sftp_stat( sftpSession, fullPath ); if ( !a ) { if ( err ) { *err = sftp_get_error( sftpSession ); } return -1; } st->mode = la->permissions; st->size = la->size; st->uid = la->uid; st->gid = la->gid; st->mtime = la->mtime; sftp_attributes_free( a ); //!!! return 0; }
int CSFTPSession::Stat(const char *path, struct __stat64* buffer) { if(m_connected) { P8PLATFORM::CLockObject lock(m_lock); m_LastActive = P8PLATFORM::GetTimeMs(); sftp_attributes attributes = sftp_stat(m_sftp_session, CorrectPath(path).c_str()); if (attributes) { memset(buffer, 0, sizeof(struct __stat64)); buffer->st_size = attributes->size; buffer->st_mtime = attributes->mtime; buffer->st_atime = attributes->atime; if S_ISDIR(attributes->permissions) buffer->st_mode = S_IFDIR; else if S_ISREG(attributes->permissions) buffer->st_mode = S_IFREG; sftp_attributes_free(attributes); return 0; } else {
void clSFTP::Write(const wxMemoryBuffer& fileContent, const wxString& remotePath) throw(clException) { if(!m_sftp) { throw clException("SFTP is not initialized"); } int access_type = O_WRONLY | O_CREAT | O_TRUNC; sftp_file file; wxString tmpRemoteFile = remotePath; tmpRemoteFile << ".codelitesftp"; file = sftp_open(m_sftp, tmpRemoteFile.mb_str(wxConvUTF8).data(), access_type, 0644); if(file == NULL) { throw clException(wxString() << _("Can't open file: ") << tmpRemoteFile << ". " << ssh_get_error(m_ssh->GetSession()), sftp_get_error(m_sftp)); } char* p = (char*)fileContent.GetData(); const int maxChunkSize = 65536; wxInt64 bytesLeft = fileContent.GetDataLen(); while(bytesLeft > 0) { wxInt64 chunkSize = bytesLeft > maxChunkSize ? maxChunkSize : bytesLeft; wxInt64 bytesWritten = sftp_write(file, p, chunkSize); if(bytesWritten < 0) { sftp_close(file); throw clException(wxString() << _("Can't write data to file: ") << tmpRemoteFile << ". " << ssh_get_error(m_ssh->GetSession()), sftp_get_error(m_sftp)); } bytesLeft -= bytesWritten; p += bytesWritten; } sftp_close(file); // Unlink the original file if it exists bool needUnlink = false; { // Check if the file exists sftp_attributes attr = sftp_stat(m_sftp, remotePath.mb_str(wxConvISO8859_1).data()); if(attr) { needUnlink = true; sftp_attributes_free(attr); } } if(needUnlink && sftp_unlink(m_sftp, remotePath.mb_str(wxConvUTF8).data()) < 0) { throw clException(wxString() << _("Failed to unlink file: ") << remotePath << ". " << ssh_get_error(m_ssh->GetSession()), sftp_get_error(m_sftp)); } // Rename the file if(sftp_rename(m_sftp, tmpRemoteFile.mb_str(wxConvUTF8).data(), remotePath.mb_str(wxConvUTF8).data()) < 0) { throw clException(wxString() << _("Failed to rename file: ") << tmpRemoteFile << " -> " << remotePath << ". " << ssh_get_error(m_ssh->GetSession()), sftp_get_error(m_sftp)); } }
void clSFTP::Mkpath(const wxString& remoteDirFullpath) throw(clException) { if(!m_sftp) { throw clException("SFTP is not initialized"); } wxString tmpPath = remoteDirFullpath; tmpPath.Replace("\\", "/"); if(!tmpPath.StartsWith("/")) { throw clException("Mkpath: path must be absolute"); } wxFileName fn(remoteDirFullpath, ""); const wxArrayString& dirs = fn.GetDirs(); wxString curdir; curdir << "/"; for(size_t i = 0; i < dirs.GetCount(); ++i) { curdir << dirs.Item(i); sftp_attributes attr = sftp_stat(m_sftp, curdir.mb_str(wxConvISO8859_1).data()); if(!attr) { // directory does not exists CreateDir(curdir); } else { // directory already exists sftp_attributes_free(attr); } curdir << "/"; } }
static int ggnfs_getattr(const char *path, struct stat *stbuf) { int res = 0; char filePath[PATH_MAX]; strcpy(filePath, remotePath); strcat(filePath,"/"); strcat(filePath,path); sftp_dir dir; sftp_attributes attributes; attributes = sftp_lstat(ggnfs_data.sftp, filePath); if (attributes != NULL) { res = 1; // setting struct stat memset(stbuf, 0, sizeof(struct stat)); stbuf->st_uid = attributes->uid; stbuf->st_gid = attributes->gid; stbuf->st_atime = attributes->atime; stbuf->st_ctime = attributes->createtime; stbuf->st_mtime = attributes->mtime; stbuf->st_size = attributes->size; stbuf->st_mode = attributes->permissions; sftp_attributes_free(attributes); res = SSH_OK; } return EXIT_SUCCESS; }
int ssh_chdir(const char *path) { char* tmp = ftp_path_absolute(path); char *p = sftp_canonicalize_path(ftp->sftp_session, tmp); free(tmp); if (!p) { ftp_err("%s: %s\n", path, ssh_get_error(ftp->session)); return -1; } bool isdir = false; /* First check if this file is cached and is a directory, else we * need to stat the file to see if it really is a directory */ stripslash(p); isdir = (ftp_cache_get_directory(p) != 0); if(!isdir) { rfile *rf = ftp_cache_get_file(p); isdir = (rf && risdir(rf)); } if (!isdir) { sftp_attributes attrib = sftp_stat(ftp->sftp_session, p); if (!attrib) { ftp_err(_("Couldn't stat directory: %s\n"), ssh_get_error(ftp->session)); free(p); return -1; } if (!S_ISDIR(attrib->permissions)) { ftp_err(_("%s: not a directory\n"), p); sftp_attributes_free(attrib); free(p); return -1; } sftp_attributes_free(attrib); } ftp_update_curdir_x(p); free(p); return 0; }
uint64_t ssh_filesize(const char *path) { sftp_attributes attrib = sftp_stat(ftp->sftp_session, path); if (!attrib) return 0; uint64_t res = attrib->size; sftp_attributes_free(attrib); return res; }
time_t ssh_filetime(const char *filename) { sftp_attributes attrib = sftp_stat(ftp->sftp_session, filename); if (!attrib) return -1; time_t res = attrib->mtime; /* mtime 64? */ sftp_attributes_free(attrib); return res; }
void SFTPAttribute::DoClear() { if ( m_attributes ) { sftp_attributes_free( m_attributes ); } m_attributes = NULL; m_name.Clear(); m_flags = 0; m_size = 0; m_permissions = 0; }
int FSSftp::OpenCreate ( FSPath& path, bool overwrite, int mode, int* err, FSCInfo* info ) { MutexLock lock( &mutex ); int ret = CheckSession( err, info ); if ( ret ) { return ret; } if ( !overwrite ) { /* заебался выяснять почему sftp_open с O_EXCL выдает "generc error" при наличии файла, а не EEXIST какой нибудь поэтому встанил эту дурацкую проверку на наличие */ sftp_attributes a = sftp_lstat( sftpSession, ( char* ) path.GetString( _operParam.charset, '/' ) ); if ( a ) { sftp_attributes_free( a ); //!!! if ( err ) { *err = SSH_FX_FILE_ALREADY_EXISTS; } return -1; } } int n = 0; for ( ; n < MAX_FILES; n++ ) if ( !fileTable[n] ) { break; } if ( n >= MAX_FILES ) { if ( err ) { *err = SSH_INTERROR_OUTOF; } return -1; } sftp_file f = sftp_open( sftpSession, ( char* ) path.GetString( _operParam.charset, '/' ), O_CREAT | O_WRONLY | ( overwrite ? O_TRUNC : O_EXCL ), mode ); if ( !f ) { //printf("ssh-err:'%s'\n",ssh_get_error(sshSession)); if ( err ) { *err = sftp_get_error( sftpSession ); } return -1; } fileTable[n] = f; return n; }
void sftp_client_message_free(SFTP_CLIENT_MESSAGE *msg) { if(msg->filename) free(msg->filename); if(msg->data) free(msg->data); if(msg->attr) sftp_attributes_free(msg->attr); if(msg->handle) free(msg->handle); memset(msg,'X',sizeof(*msg)); free(msg); }
static csync_vio_file_stat_t *_sftp_readdir(csync_vio_method_handle_t *dhandle) { sftp_attributes dirent = NULL; csync_vio_file_stat_t *fs = NULL; /* TODO: consider adding the _sftp_connect function */ dirent = sftp_readdir(_sftp_session, dhandle); if (dirent == NULL) { errno = _sftp_portable_to_errno(sftp_get_error(_sftp_session)); return NULL; } fs = c_malloc(sizeof(csync_vio_file_stat_t)); if (fs == NULL) { sftp_attributes_free(dirent); return NULL; } fs->name = c_strdup(dirent->name); fs->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE; switch (dirent->type) { case SSH_FILEXFER_TYPE_REGULAR: fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; fs->type = CSYNC_VIO_FILE_TYPE_REGULAR; break; case SSH_FILEXFER_TYPE_DIRECTORY: fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; fs->type = CSYNC_VIO_FILE_TYPE_DIRECTORY; break; case SSH_FILEXFER_TYPE_SYMLINK: case SSH_FILEXFER_TYPE_SPECIAL: case SSH_FILEXFER_TYPE_UNKNOWN: break; } sftp_attributes_free(dirent); return fs; }
void sftp_client_message_free(sftp_client_message msg) { if (msg == NULL) { return; } SAFE_FREE(msg->filename); ssh_string_free(msg->data); ssh_string_free(msg->handle); sftp_attributes_free(msg->attr); ssh_buffer_free(msg->complete_message); SAFE_FREE(msg->str_data); ZERO_STRUCTP(msg); SAFE_FREE(msg); }
static int ggnfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { int res = 0; (void) offset; (void) fi; sftp_dir *dir; dir = (sftp_dir *)(uintptr_t) fi->fh; sftp_attributes attributes; int rc1; while ((attributes = sftp_readdir(ggnfs_data.sftp, dir)) != NULL) { struct stat stbuf; stbuf.st_uid = attributes->uid; stbuf.st_gid = attributes->gid; stbuf.st_atime = attributes->atime; stbuf.st_ctime = attributes->createtime; stbuf.st_mtime = attributes->mtime; stbuf.st_size = attributes->size; stbuf.st_mode = attributes->permissions; if(filler(buf, attributes->name, &stbuf, 0)) { fprintf(stderr, "Error ggnfs_readdir filler: buffer full"); return -ENOMEM; } sftp_attributes_free(attributes); } if (!sftp_dir_eof(dir)) { fprintf(stderr, "Can't list directory: %s\n", ssh_get_error(ggnfs_data.session)); sftp_closedir(dir); return SSH_ERROR; } rc1 = sftp_closedir(dir); if (rc1 != SSH_OK) { fprintf(stderr, " inside Readdir: Canftp_list_dirt close directory\n"); } return EXIT_SUCCESS; }
uint8_t* sn_sftp_load_file(ssh_session ssh, sftp_session sftp, std::string path) { uint8_t *data; int access_type, fd, nbytes, index, rc; char buffer[SFTP_MAX_XFER_BUFFER]; index = 0; sftp_file file; access_type = O_RDONLY; file = sftp_open(sftp, path.c_str(), access_type, 0); if (file == NULL) { std::cerr << "Can't open file for reading: " << strerror(errno) << std::endl; return NULL; } sftp_attributes attr = sftp_fstat(file); data = new uint8_t[attr->size + 1]; for(;;) { nbytes = sftp_read(file, buffer, sizeof(buffer)); if (nbytes == 0) { break; } else if (nbytes < 0) { std::cerr << "Error while reading file: " << ssh_get_error(ssh) << std::endl; sftp_close(file); delete[] data; return NULL; } memcpy(data + index, buffer, nbytes); index += nbytes; } rc = sftp_close(file); assert(rc == SSH_OK); data[attr->size] = '\0'; sftp_attributes_free(attr); return data; }
int sftp_list_dir(ssh_session session, sftp_session sftp) { sftp_dir dir; sftp_attributes attributes; int rc; dir = sftp_opendir(sftp, remotePath); if (!dir) { fprintf(stderr, "Directory not opened: %s\n", ssh_get_error(session)); return SSH_ERROR; } printf("Name Size Perms Owner\tGroup\n"); while ((attributes = sftp_readdir(sftp, dir)) != NULL) { printf("%-20s %10llu %.8o %s(%d)\t%s(%d)\n", attributes->name, (long long unsigned int) attributes->size, attributes->permissions, attributes->owner, attributes->uid, attributes->group, attributes->gid); sftp_attributes_free(attributes); } if (!sftp_dir_eof(dir)) { fprintf(stderr, "Can't list directory: %s\n", ssh_get_error(session)); sftp_closedir(dir); return SSH_ERROR; } rc = sftp_closedir(dir); if (rc != SSH_OK) { fprintf(stderr, "Can't close directory: %s\n", ssh_get_error(session)); return rc; } }
static void do_sftp(ssh_session session){ sftp_session sftp=sftp_new(session); sftp_dir dir; sftp_attributes file; sftp_statvfs_t sftpstatvfs; struct statvfs sysstatvfs; sftp_file fichier; sftp_file to; int len=1; unsigned int i; char data[DATALEN]={0}; char *lnk; unsigned int count; if(!sftp){ fprintf(stderr, "sftp error initialising channel: %s\n", ssh_get_error(session)); return; } if(sftp_init(sftp)){ fprintf(stderr, "error initialising sftp: %s\n", ssh_get_error(session)); return; } printf("Additional SFTP extensions provided by the server:\n"); count = sftp_extensions_get_count(sftp); for (i = 0; i < count; i++) { printf("\t%s, version: %s\n", sftp_extensions_get_name(sftp, i), sftp_extensions_get_data(sftp, i)); } /* test symlink and readlink */ if (sftp_symlink(sftp, "/tmp/this_is_the_link", "/tmp/sftp_symlink_test") < 0) { fprintf(stderr, "Could not create link (%s)\n", ssh_get_error(session)); return; } lnk = sftp_readlink(sftp, "/tmp/sftp_symlink_test"); if (lnk == NULL) { fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session)); return; } printf("readlink /tmp/sftp_symlink_test: %s\n", lnk); sftp_unlink(sftp, "/tmp/sftp_symlink_test"); if (sftp_extension_supported(sftp, "*****@*****.**", "2")) { sftpstatvfs = sftp_statvfs(sftp, "/tmp"); if (sftpstatvfs == NULL) { fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session)); return; } printf("sftp statvfs:\n" "\tfile system block size: %llu\n" "\tfundamental fs block size: %llu\n" "\tnumber of blocks (unit f_frsize): %llu\n" "\tfree blocks in file system: %llu\n" "\tfree blocks for non-root: %llu\n" "\ttotal file inodes: %llu\n" "\tfree file inodes: %llu\n" "\tfree file inodes for to non-root: %llu\n" "\tfile system id: %llu\n" "\tbit mask of f_flag values: %llu\n" "\tmaximum filename length: %llu\n", (unsigned long long) sftpstatvfs->f_bsize, (unsigned long long) sftpstatvfs->f_frsize, (unsigned long long) sftpstatvfs->f_blocks, (unsigned long long) sftpstatvfs->f_bfree, (unsigned long long) sftpstatvfs->f_bavail, (unsigned long long) sftpstatvfs->f_files, (unsigned long long) sftpstatvfs->f_ffree, (unsigned long long) sftpstatvfs->f_favail, (unsigned long long) sftpstatvfs->f_fsid, (unsigned long long) sftpstatvfs->f_flag, (unsigned long long) sftpstatvfs->f_namemax); sftp_statvfs_free(sftpstatvfs); if (statvfs("/tmp", &sysstatvfs) < 0) { fprintf(stderr, "statvfs failed (%s)\n", strerror(errno)); return; } printf("sys statvfs:\n" "\tfile system block size: %llu\n" "\tfundamental fs block size: %llu\n" "\tnumber of blocks (unit f_frsize): %llu\n" "\tfree blocks in file system: %llu\n" "\tfree blocks for non-root: %llu\n" "\ttotal file inodes: %llu\n" "\tfree file inodes: %llu\n" "\tfree file inodes for to non-root: %llu\n" "\tfile system id: %llu\n" "\tbit mask of f_flag values: %llu\n" "\tmaximum filename length: %llu\n", (unsigned long long) sysstatvfs.f_bsize, (unsigned long long) sysstatvfs.f_frsize, (unsigned long long) sysstatvfs.f_blocks, (unsigned long long) sysstatvfs.f_bfree, (unsigned long long) sysstatvfs.f_bavail, (unsigned long long) sysstatvfs.f_files, (unsigned long long) sysstatvfs.f_ffree, (unsigned long long) sysstatvfs.f_favail, (unsigned long long) sysstatvfs.f_fsid, (unsigned long long) sysstatvfs.f_flag, (unsigned long long) sysstatvfs.f_namemax); } /* the connection is made */ /* opening a directory */ dir=sftp_opendir(sftp,"./"); if(!dir) { fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session)); return ; } /* reading the whole directory, file by file */ while((file=sftp_readdir(sftp,dir))){ fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n", file->name, file->permissions, file->owner, file->uid, file->group, file->gid, (long long unsigned int) file->size); sftp_attributes_free(file); } /* when file=NULL, an error has occured OR the directory listing is end of file */ if(!sftp_dir_eof(dir)){ fprintf(stderr, "Error: %s\n", ssh_get_error(session)); return; } if(sftp_closedir(dir)){ fprintf(stderr, "Error: %s\n", ssh_get_error(session)); return; } /* this will open a file and copy it into your /home directory */ /* the small buffer size was intended to stress the library. of course, you can use a buffer till 20kbytes without problem */ fichier=sftp_open(sftp,"/usr/bin/ssh",O_RDONLY, 0); if(!fichier){ fprintf(stderr, "Error opening /usr/bin/ssh: %s\n", ssh_get_error(session)); return; } /* open a file for writing... */ to=sftp_open(sftp,"ssh-copy",O_WRONLY | O_CREAT, 0700); if(!to){ fprintf(stderr, "Error opening ssh-copy for writing: %s\n", ssh_get_error(session)); return; } while((len=sftp_read(fichier,data,4096)) > 0){ if(sftp_write(to,data,len)!=len){ fprintf(stderr, "Error writing %d bytes: %s\n", len, ssh_get_error(session)); return; } } printf("finished\n"); if(len<0) fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session)); sftp_close(fichier); sftp_close(to); printf("fichiers ferm\n"); to=sftp_open(sftp,"/tmp/grosfichier",O_WRONLY|O_CREAT, 0644); for(i=0;i<1000;++i){ len=sftp_write(to,data,DATALEN); printf("wrote %d bytes\n",len); if(len != DATALEN){ printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session)); } } sftp_close(to); /* close the sftp session */ sftp_free(sftp); printf("sftp session terminated\n"); }
static int sftp_list_file(ssh_session session,char *remote_dir,char *remote_file) { sftp_attributes file; char datex[22]; char mtemp[1024]; time_t mtime=0; #ifdef WIN32 struct tm *mytime=NULL; int x=0; #endif sftp_session sftp=sftp_new(session); if(!sftp) { prterr("sftp error initialising channel: %s\n",ssh_get_error(session)); return(1); } if(sftp_init(sftp)) { prterr("error initializing sftp: %s\n",ssh_get_error(session)); return(1); } memset(datex,0,22); memset(mtemp,0,1024); if(isEMPTY(remote_dir) || !RDAstrcmp(remote_dir,"\"\"")) { sprintf(mtemp,"%s",remote_file); } else { sprintf(mtemp,"%s/%s",remote_dir,remote_file); } file=sftp_stat(sftp,mtemp); if(file==NULL) { /* when file=NULL, an error has occured OR the directory listing is end of file */ prterr("Error getting file info for [%s]",mtemp); sftp_free(sftp); return(1); }else{ #ifndef WIN32 #ifdef _POSIX_SOURCE mtime=file->mtime; //strftime(datex,22,"%b %d %Y %l:%M %p",localtime(&file->mtime)); strftime(datex,22,"%b %d %Y %l:%M %p",localtime(&mtime)); #else TRACE; ascftime(datex,"%b %d %Y %l:%M %p",localtime(&file->mtime)); #endif /* _POSIX_SOURCE */ #else /* WIN32 */ TRACE; mytime=localctime(&file->mtime); x=mytime->tm_year; while(x>=200) x-=100; sprintf(datex,"%02d/%02d/%04d ",mytime->tm_mon+1,mytime->tm_mday,1900+my_time->tm_year); #endif fprintf(stdout,"%s\t\t%llu\t\t%s\r\n",remote_file,(long long unsigned int) file->size,datex); if(diagapps) { prterr("\"%30s\"(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes %.10llu\n", file->name, file->permissions, file->owner, file->uid, file->group, file->gid, (long long unsigned int) file->size, (long long unsigned int) file->mtime); } sftp_attributes_free(file); } sftp_free(sftp); return(0); }
static void do_sftp(ssh_session session) { sftp_session sftp=sftp_new(session); sftp_dir dir; sftp_attributes file; char datex[11]; time_t atime=0; #ifdef WIN32 struct tm *mytime=NULL; int x=0; #endif if(!sftp) { prterr("sftp error initialising channel: %s\n",ssh_get_error(session)); return; } if(sftp_init(sftp)) { prterr("error initializing sftp: %s\n",ssh_get_error(session)); return; } dir=sftp_opendir(sftp,docfolder); if(!dir) { prterr("Directory not opened(%s)\n", ssh_get_error(session)); return; } /* reading the whole directory, file by file */ while((file=sftp_readdir(sftp,dir))) { if(strncmp(file->name,".",1)) { if(details==FALSE) { fprintf(stdout,"%s\r\n",file->name); } else { #ifndef WIN32 #ifdef _POSIX_SOURCE atime=file->atime; strftime(datex,11,"%m/%d/%Y",localtime(&atime)); #else ascftime(datex,"%m/%d/%Y",localtime(&file->atime)); #endif /* _POSIX_SOURCE */ #else /* WIN32 */ mytime=localctime(&file->atime); x=mytime->tm_year; while(x>=200) x-=100; sprintf(datex,"%02d/%02d/%04d",mytime->tm_mon+1,mytime->tm_mday,1900+my_time->tm_year); #endif fprintf(stdout,"%s\t%llu\t%s\r\n",file->name,(long long unsigned int) file->size,datex); } } if(diagapps) { prterr("%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n", file->name, file->permissions, file->owner, file->uid, file->group, file->gid, (long long unsigned int) file->size); } sftp_attributes_free(file); } /* when file=NULL, an error has occured OR the directory listing is end of file */ if(!sftp_dir_eof(dir)) { prterr("Error: %s\n", ssh_get_error(session)); return; } if(sftp_closedir(dir)) { prterr("Error: %s\n", ssh_get_error(session)); return; } sftp_free(sftp); }
int ftp_getfile(const char *infile, const char *outfile, getmode_t how, transfer_mode_t mode, ftp_transfer_func hookf) { FILE *fp; int r; struct stat statbuf; long rp = 0; int (*close_func)(FILE *fp); if(stat(outfile, &statbuf) == 0) { if(S_ISDIR(statbuf.st_mode)) { ftp_err(_("%s: is a directory\n"), outfile); return -1; } if(!(statbuf.st_mode & S_IWRITE)) { ftp_err(_("%s: permission denied\n"), outfile); return -1; } if(how == getResume) ftp->restart_offset = statbuf.st_size; } else ftp->restart_offset = 0L; ftp->ti.total_size = -1; /* we need to save this, because ftp_init_receive() sets it to zero */ rp = ftp->restart_offset; reset_transfer_info(); #ifdef HAVE_LIBSSH if (ftp->session) { /* we need to stat the remote file, so we are sure we can read it * this needs to be done before we call ssh_do_receive, because by * then, the file is created, and would leave a zero-size file opon * failure */ sftp_attributes a = sftp_stat(ftp->sftp_session, infile); if(!a) { ftp_err(_("Unable to stat file '%s': %s\n"), infile, ssh_get_error(ftp->session)); return -1; } sftp_attributes_free(a); /* FIXME: how can we check if it will be possible to transfer * the specified file? */ } else #endif if (ftp_init_receive(infile, mode, hookf) != 0) return -1; if(how == getPipe) { fp = popen(outfile, "w"); close_func = pclose; } else { fp = fopen(outfile, (rp > 0L || (how == getAppend)) ? "a" : "w"); close_func = fclose; } if(!fp) { ftp_err("%s: %s\n", outfile, strerror(errno)); ftp->restart_offset = 0L; return -1; } if(rp > 0L) { if(fseek(fp, rp, SEEK_SET) != 0) { ftp_err(_("%s: %s, transfer cancelled\n"), outfile, strerror(errno)); close_func(fp); ftp->restart_offset = 0L; return -1; } } free(ftp->ti.remote_name); free(ftp->ti.local_name); ftp->ti.remote_name = xstrdup(infile); ftp->ti.local_name = xstrdup(outfile); foo_hookf = hookf; #ifdef HAVE_LIBSSH if(ftp->session) r = ssh_do_receive(infile, fp, mode, hookf); else #endif r = ftp_do_receive(fp, mode, hookf); close_func(fp); return r; }
bool CSFTPSession::GetDirectory(const std::string& base, const std::string& folder, std::vector<kodi::vfs::CDirEntry>& items) { int sftp_error = SSH_FX_OK; if (m_connected) { sftp_dir dir = NULL; P8PLATFORM::CLockObject lock(m_lock); m_LastActive = P8PLATFORM::GetTimeMs(); dir = sftp_opendir(m_sftp_session, CorrectPath(folder).c_str()); //Doing as little work as possible within the critical section if (!dir) sftp_error = sftp_get_error(m_sftp_session); lock.Unlock(); if (!dir) { kodi::Log(ADDON_LOG_ERROR, "%s: %s for '%s'", __FUNCTION__, SFTPErrorText(sftp_error), folder.c_str()); } else { bool read = true; while (read) { sftp_attributes attributes = NULL; lock.Lock(); read = sftp_dir_eof(dir) == 0; attributes = sftp_readdir(m_sftp_session, dir); lock.Unlock(); if (attributes && (attributes->name == NULL || strcmp(attributes->name, "..") == 0 || strcmp(attributes->name, ".") == 0)) { lock.Lock(); sftp_attributes_free(attributes); lock.Unlock(); continue; } if (attributes) { std::string itemName = attributes->name; std::string localPath = folder; localPath.append(itemName); if (attributes->type == SSH_FILEXFER_TYPE_SYMLINK) { lock.Lock(); sftp_attributes_free(attributes); attributes = sftp_stat(m_sftp_session, CorrectPath(localPath).c_str()); lock.Unlock(); if (attributes == NULL) continue; } kodi::vfs::CDirEntry entry; entry.SetLabel(itemName); if (itemName[0] == '.') entry.AddProperty("file:hidden", "true"); entry.SetDateTime(attributes->mtime64); if (attributes->type & SSH_FILEXFER_TYPE_DIRECTORY) { localPath.append("/"); entry.SetFolder(true); } else entry.SetSize(attributes->size); entry.SetPath(base+localPath); items.push_back(entry); lock.Lock(); sftp_attributes_free(attributes); lock.Unlock(); } else read = false; } lock.Lock(); sftp_closedir(dir); lock.Unlock(); return true; } } else kodi::Log(ADDON_LOG_ERROR, "SFTPSession: Not connected, can't list directory '%s'", folder.c_str()); return false; }
static int _sftp_stat(const char *uri, csync_vio_file_stat_t *buf) { sftp_attributes attrs; char *path = NULL; int rc = -1; if (_sftp_connect(uri) < 0) { return -1; } if (c_parse_uri(uri, NULL, NULL, NULL, NULL, NULL, &path) < 0) { return -1; } attrs = sftp_lstat(_sftp_session, path); if (attrs == NULL) { rc = -1; goto out; } buf->name = c_basename(path); if (buf->name == NULL) { csync_vio_file_stat_destroy(buf); goto out; } buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE; switch (attrs->type) { case SSH_FILEXFER_TYPE_REGULAR: buf->type = CSYNC_VIO_FILE_TYPE_REGULAR; break; case SSH_FILEXFER_TYPE_DIRECTORY: buf->type = CSYNC_VIO_FILE_TYPE_DIRECTORY; break; case SSH_FILEXFER_TYPE_SYMLINK: buf->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK; break; case SSH_FILEXFER_TYPE_SPECIAL: case SSH_FILEXFER_TYPE_UNKNOWN: buf->type = CSYNC_VIO_FILE_TYPE_UNKNOWN; break; } buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; buf->mode = attrs->permissions; buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS; if (buf->type == CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK) { /* FIXME: handle symlink */ buf->flags = CSYNC_VIO_FILE_FLAGS_SYMLINK; } else { buf->flags = CSYNC_VIO_FILE_FLAGS_NONE; } buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FLAGS; buf->uid = attrs->uid; buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_UID; buf->uid = attrs->gid; buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_GID; buf->size = attrs->size; buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE; buf->atime = attrs->atime; buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME; buf->mtime = attrs->mtime; buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME; buf->ctime = attrs->createtime; buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME; rc = 0; out: if (rc < 0) { errno = _sftp_portable_to_errno(sftp_get_error(_sftp_session)); } SAFE_FREE(path); sftp_attributes_free(attrs); return rc; }
int FSSftp::ReadDir ( FSList* list, FSPath& path, int* err, FSCInfo* info ) { MutexLock lock( &mutex ); int ret = CheckSession( err, info ); if ( ret ) { return ret; } if ( !list ) { return 0; } list->Clear(); sftp_dir dir = sftp_opendir( sftpSession, ( char* )path.GetString( _operParam.charset ) ); if ( !dir ) { if ( err ) { *err = sftp_get_error( sftpSession ); } return -1; } try { while ( true ) { if ( info && info->Stopped() ) { sftp_closedir( dir ); return -2; } sftp_attributes attr = sftp_readdir( sftpSession, dir ); if ( !attr ) { if ( sftp_dir_eof( dir ) ) { break; } if ( err ) { *err = sftp_get_error( sftpSession ); } return -1; } try { //skip . and .. if ( !attr->name || attr->name[0] == '.' && ( !attr->name[1] || ( attr->name[1] == '.' && !attr->name[2] ) ) ) { continue; } clPtr<FSNode> pNode = new FSNode(); pNode->name.Set( _operParam.charset, attr->name ); pNode->st.size = attr->size; pNode->st.uid = attr->uid; pNode->st.gid = attr->gid; pNode->st.mtime = attr->mtime; if ( attr->type == SSH_FILEXFER_TYPE_SYMLINK ) { FSPath pt = path; pt.Push( _operParam.charset, attr->name ); char* fullPath = ( char* )pt.GetString( _operParam.charset ); char* s = sftp_readlink( sftpSession, fullPath ); if ( s ) { pNode->st.link.Set( _operParam.charset, s ); } sftp_attributes a = sftp_stat( sftpSession, fullPath ); if ( a ) { pNode->st.mode = a->permissions; pNode->st.mtime = a->mtime; sftp_attributes_free( a ); } else { pNode->st.mode = 0; } } else { pNode->st.mode = attr->permissions; } list->Append( pNode ); sftp_attributes_free( attr ); } catch ( ... ) { sftp_attributes_free( attr ); throw; } }; sftp_closedir( dir ); } catch ( ... ) { sftp_closedir( dir ); throw; } return 0; }
/* it's just a proof of concept code for sftp, till i write a real documentation about it */ void do_sftp(SSH_SESSION *session){ SFTP_SESSION *sftp=sftp_new(session); SFTP_DIR *dir; SFTP_ATTRIBUTES *file; SFTP_FILE *fichier; SFTP_FILE *to; int len=1; int i; char data[8000]; if(!sftp){ ssh_say(0,"sftp error initialising channel : %s\n",ssh_get_error(session)); return; } if(sftp_init(sftp)){ ssh_say(0,"error initialising sftp : %s\n",ssh_get_error(session)); return; } /* the connection is made */ /* opening a directory */ dir=sftp_opendir(sftp,"./"); if(!dir) { ssh_say(0,"Directory not opened(%s)\n",ssh_get_error(session)); return ; } /* reading the whole directory, file by file */ while((file=sftp_readdir(sftp,dir))){ ssh_say(0,"%30s(%.8lo) : %.5d.%.5d : %.10lld bytes\n",file->name,file->permissions,file->uid,file->gid,file->size); sftp_attributes_free(file); } /* when file=NULL, an error has occured OR the directory listing is end of file */ if(!sftp_dir_eof(dir)){ ssh_say(0,"error : %s\n",ssh_get_error(session)); return; } if(sftp_dir_close(dir)){ ssh_say(0,"Error : %s\n",ssh_get_error(session)); return; } /* this will open a file and copy it into your /home directory */ /* the small buffer size was intended to stress the library. of course, you can use a buffer till 20kbytes without problem */ fichier=sftp_open(sftp,"/usr/bin/ssh",O_RDONLY,NULL); if(!fichier){ ssh_say(0,"Error opening /usr/bin/ssh : %s\n",ssh_get_error(session)); return; } /* open a file for writing... */ to=sftp_open(sftp,"ssh-copy",O_WRONLY | O_CREAT,NULL); if(!to){ ssh_say(0,"Error opening ssh-copy for writing : %s\n",ssh_get_error(session)); return; } while((len=sftp_read(fichier,data,4096)) > 0){ if(sftp_write(to,data,len)!=len){ ssh_say(0,"error writing %d bytes : %s\n",len,ssh_get_error(session)); return; } } printf("finished\n"); if(len<0) ssh_say(0,"Error reading file : %s\n",ssh_get_error(session)); sftp_file_close(fichier); sftp_file_close(to); printf("fichiers ferm�\n"); to=sftp_open(sftp,"/tmp/grosfichier",O_WRONLY|O_CREAT,NULL); for(i=0;i<1000;++i){ len=sftp_write(to,data,8000); printf("wrote %d bytes\n",len); if(len != 8000){ printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session)); } } sftp_file_close(to); /* close the sftp session */ sftp_free(sftp); printf("session sftp termin�\n"); }
static int do_read(const char* infile, FILE* fp, getmode_t mode, ftp_transfer_func hookf, uint64_t offset) { if (gvSSHTrySCP && !offset) { char* escaped = bash_backslash_quote(infile); /* try to set up a scp connection */ ssh_scp scp = ssh_scp_new(ftp->session, SSH_SCP_READ, escaped); free(escaped); if (scp != NULL) { int rc = ssh_scp_init(scp); if (rc == SSH_OK) return do_scp_read(scp, infile, fp, mode, hookf); ssh_scp_free(scp); } } time_t then = time(NULL) - 1; ftp_set_close_handler(); if (hookf) hookf(&ftp->ti); ftp->ti.begin = false; /* check if remote file is not a directory */ sftp_attributes attrib = sftp_stat(ftp->sftp_session, infile); if (!attrib) return -1; if (S_ISDIR(attrib->permissions)) { ftp_err(_("Cannot download a directory: %s\n"), infile); sftp_attributes_free(attrib); return -1; } sftp_attributes_free(attrib); /* open remote file */ sftp_file file = sftp_open(ftp->sftp_session, infile, O_RDONLY, 0); if (!file) { ftp_err(_("Cannot open file for reading: %s\n"), ssh_get_error(ftp->session)); return -1; } /* seek to offset */ int r = sftp_seek64(file, offset); if (r != SSH_OK) { ftp_err(_("Failed to seek: %s\n"), ssh_get_error(ftp->session)); sftp_close(file); return -1; } /* read file */ char buffer[SSH_BUFSIZ]; ssize_t nbytes = 0; while ((nbytes = sftp_read(file, buffer, sizeof(buffer))) > 0) { if (ftp_sigints() > 0) { ftp_trace("break due to sigint\n"); break; } errno = 0; if (fwrite(buffer, nbytes, 1, fp) != 1) { ftp_err(_("Error while writing to file: %s\n"), strerror(errno)); ftp->ti.ioerror = true; sftp_close(file); return -1; } ftp->ti.size += nbytes; if (hookf) { time_t now = time(NULL); if (now > then) { hookf(&ftp->ti); then = now; } } } if (nbytes < 0) { ftp_err(_("Error while reading from file: %s\n"), ssh_get_error(ftp->session)); r = -1; } sftp_close(file); return r; }
rdirectory *ssh_read_directory(const char *path) { char *p = ftp_path_absolute(path); stripslash(p); sftp_dir dir = sftp_opendir(ftp->sftp_session, p); if (!dir) { free(p); return 0; } ftp_trace("*** start parsing directory listing ***\n"); rdirectory* rdir = rdir_create(); sftp_attributes attrib = NULL; while ((attrib = sftp_readdir(ftp->sftp_session, dir)) != NULL) { ftp_trace("%s\n", attrib->longname); rfile* rf = rfile_create(); rf->perm = perm2string(attrib->permissions); rf->nhl = 0; // atoi(e); if (attrib->owner) rf->owner = xstrdup(attrib->owner); if (attrib->group) rf->group = xstrdup(attrib->group); if (asprintf(&rf->path, "%s/%s", p, attrib->name) == -1) { ftp_err(_("Failed to allocate memory.\n")); sftp_closedir(dir); free(p); rdir_destroy(rdir); rfile_destroy(rf); } rf->mtime = attrib->mtime; rf->date = time_to_string(rf->mtime); rf->size = attrib->size; rfile_parse_colors(rf); rf->link = NULL; if (rislink(rf) && ftp->ssh_version > 2) rf->link = sftp_readlink(ftp->sftp_session, rf->path); list_additem(rdir->files, (void *)rf); sftp_attributes_free(attrib); } ftp_trace("*** end parsing directory listing ***\n"); if (!sftp_dir_eof(dir)) { ftp_err(_("Couldn't list directory: %s\n"), ssh_get_error(ftp->session)); sftp_closedir(dir); free(p); rdir_destroy(rdir); return NULL; } sftp_closedir(dir); rdir->path = p; ftp_trace("added directory '%s' to cache\n", p); list_additem(ftp->cache, rdir); return rdir; }