void SFtpFileEngine::readDir(const QString &dir) { QString cacheDir(getCachePath(dir, true)); _fileInfoCache->removeDirInfo(cacheDir); // add an empty entry to distinguish a empty directory from // a non-existent directory _fileInfoCache->addFileInfo(cacheDir, QUrlInfo()); LIBSSH2_SFTP_HANDLE* dir_handle; dir_handle = libssh2_sftp_opendir(_sftp_session, _textCodec->fromUnicode(dir).data()); if (dir_handle) { QByteArray entry(512, 0); QByteArray longEntry(512, 0); LIBSSH2_SFTP_ATTRIBUTES attr; while (libssh2_sftp_readdir_ex(dir_handle, entry.data(), entry.capacity(), longEntry.data(), longEntry.capacity(), &attr) > 0) { QString entryUni(_textCodec->toUnicode(entry.data())); QUrlInfo urlInfo; attr2urlinfo(&urlInfo, entryUni, &attr); _fileInfoCache->addFileInfo(cacheDir, urlInfo); } libssh2_sftp_closedir(dir_handle); } }
/* sftp关闭文件夹 */ static int sftp_close_dir(protocol_data_t *protocol) { if (protocol == NULL || protocol->protocol_data == NULL) { return; } sftp_data_t *data = (sftp_data_t *)protocol->protocol_data; return libssh2_sftp_closedir(data->dir_handle); }
int sftpfs_closedir (void *data, GError ** error) { int rc; sftpfs_dir_data_t *sftpfs_dir = (sftpfs_dir_data_t *) data; (void) error; rc = libssh2_sftp_closedir (sftpfs_dir->handle); g_free (sftpfs_dir); return rc; }
/** * @function SFTP.readDir * * ### Synopsis * * var files = SFTP.readDir(handle, path); * * Read a directory from remote server, return an array of objects of the form: * * + name: name of file. * + longentry: a string? * + size: size of file in bytes. * + permissions: file permissions. * + uid: uid of owner of file. * + gid: gid of owner of file. * + mtime: modification time (timestamp) of file. * + atime: access time (timestamp) of file * * The above values may be undefined (except for name), if the SSH2 library and remote server don't allow extended information. * * @param {object} handle - opaque handle to existing SFTP connection (already connected). * @param {string} path - path on remote server to directory to get listing of. * @return {array} files - array of objects as specifed above, or string containing error message. */ JSVAL sftp_readdir (JSARGS args) { HandleScope scope; SFTP *handle = HANDLE(args[0]); String::Utf8Value path(args[1]); LIBSSH2_SFTP_HANDLE *sftp_handle = libssh2_sftp_opendir(handle->sftp_session, *path); if (!sftp_handle) { return scope.Close(String::New("Could not open remote directory")); } char mem[512], longentry[512]; LIBSSH2_SFTP_ATTRIBUTES attrs; Handle<String> _name = String::New("name"); Handle<String> _longentry = String::New("longentry"); Handle<String> _permissions = String::New("permissions"); Handle<String> _uid = String::New("uid"); Handle<String> _gid = String::New("gid"); Handle<String> _size = String::New("size"); Handle<String> _mtime = String::New("mtime"); Handle<String> _atime = String::New("atime"); Handle<Array>a = Array::New(); int aIndex = 0; while (1) { if (libssh2_sftp_readdir_ex(sftp_handle, mem, sizeof (mem), longentry, sizeof (longentry), &attrs) <= 0) { break; } JSOBJ o = Object::New(); o->Set(_name, String::New(mem)); o->Set(_longentry, String::New(longentry)); if (attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) { o->Set(_size, Integer::New(attrs.filesize)); } if (attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { o->Set(_permissions, Integer::New(attrs.permissions)); } if (attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID) { o->Set(_uid, Integer::New(attrs.uid)); o->Set(_gid, Integer::New(attrs.gid)); } if (attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) { o->Set(_mtime, Integer::New(attrs.mtime)); o->Set(_atime, Integer::New(attrs.atime)); } a->Set(aIndex++, o); } libssh2_sftp_closedir(sftp_handle); return scope.Close(a); }
/* sftp删除文件夹 */ static int sftp_rm_dir(protocol_data_t *protocol, char *dirname) { int rc; LIBSSH2_SFTP_ATTRIBUTES attrs; LIBSSH2_SFTP_HANDLE *dir_handle; char source[MAX_PATH_LEN] = {0}; if (protocol == NULL || protocol->protocol_data == NULL || dirname == NULL) { return -1; } sftp_data_t *data = (sftp_data_t *)protocol->protocol_data; strcpy(source, dirname); dir_handle = libssh2_sftp_opendir(data->sftp_session, source); if (!dir_handle) { return -1; } do { char filename[MAX_FILENAME_LEN] = {0}; /*255是文件名最大长度*/ rc = libssh2_sftp_readdir_ex(dir_handle, filename, sizeof(filename), NULL, 0, &attrs); if(rc > 0) { if (filename[0] != '\0' && filename[0] != '.') {/*略去隐藏文件*/ if (LIBSSH2_SFTP_S_ISREG(attrs.permissions)) { add_lastfilename(source, filename); libssh2_sftp_unlink(data->sftp_session, source); del_lastfilename(source); } if(LIBSSH2_SFTP_S_ISDIR(attrs.permissions)){ add_lastdirname(source, filename); sftp_rm_dir(protocol, source); del_lastdirname(source); } } } else if (rc == 0) { break; } else { continue; } } while (1); libssh2_sftp_closedir(dir_handle); libssh2_sftp_rmdir(data->sftp_session, source); return 0; }
bool SFTPChannel::updateLs() { int rc; if (mRequestState == Beginning) { mOperationHandle = libssh2_sftp_opendir(mHandle, mCurrentRequest->getPath().toUtf8()); if (mOperationHandle) mRequestState = Reading; else if ((rc = libssh2_session_last_errno(mSession->sessionHandle())) == LIBSSH2_ERROR_EAGAIN) return true; // try again else { criticalError(tr("Failed to open remote directory for reading: %1").arg(rc)); return false; } mResult.clear(); } if (mRequestState == Reading) { char buffer[1024]; LIBSSH2_SFTP_ATTRIBUTES attrs; rc = libssh2_sftp_readdir(mOperationHandle, buffer, sizeof(buffer), &attrs); if (rc == LIBSSH2_ERROR_EAGAIN) return true; // Try again else if (rc == 0) mRequestState = Finishing; else if (rc < 0) { criticalError(tr("Error while reading remote directory: %1").arg(rc)); return false; } else // Got a directory entry { // Skip hidden entries iff request says to if (mCurrentRequest->getIncludeHidden() || buffer[0] != '.') { // Can't determine if remote file is readable/writable, so report all as so. QString flags = "rw"; if (LIBSSH2_SFTP_S_ISDIR(attrs.permissions)) flags += 'd'; QVariantMap details; details.insert("f", flags); details.insert("s", attrs.filesize); details.insert("m", (qulonglong)attrs.mtime); mResult.insert(buffer, details); } } } if (mRequestState == Finishing) { rc = libssh2_sftp_closedir(mOperationHandle); if (rc == LIBSSH2_ERROR_EAGAIN) return true; else if (rc < 0) { criticalError(tr("Failed to cleanly close SFTP directory: %1").arg(rc)); return false; } // Success! Send a response and finish up. QVariantMap finalResult; finalResult.insert("entries", mResult); mCurrentRequest->triggerSuccess(finalResult); return false; } return true; }
int main(int argc, char *argv[]) { unsigned long hostaddr; int sock, i, auth_pw = 1; struct sockaddr_in sin; const char *fingerprint; LIBSSH2_SESSION *session; const char *username="******"; const char *password="******"; const char *sftppath="/tmp/secretdir"; int rc; LIBSSH2_SFTP *sftp_session; LIBSSH2_SFTP_HANDLE *sftp_handle; #ifdef WIN32 WSADATA wsadata; WSAStartup(MAKEWORD(2,0), &wsadata); #endif if (argc > 1) { hostaddr = inet_addr(argv[1]); } else { hostaddr = htonl(0x7F000001); } if(argc > 2) { username = argv[2]; } if(argc > 3) { password = argv[3]; } if(argc > 4) { sftppath = argv[4]; } /* * The application code is responsible for creating the socket * and establishing the connection */ sock = socket(AF_INET, SOCK_STREAM, 0); sin.sin_family = AF_INET; sin.sin_port = htons(22); sin.sin_addr.s_addr = hostaddr; if (connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) { fprintf(stderr, "failed to connect!\n"); return -1; } /* Create a session instance */ session = libssh2_session_init(); if(!session) return -1; /* ... start it up. This will trade welcome banners, exchange keys, * and setup crypto, compression, and MAC layers */ rc = libssh2_session_startup(session, sock); if(rc) { fprintf(stderr, "Failure establishing SSH session: %d\n", rc); return -1; } /* At this point we havn't yet authenticated. The first thing to do * is check the hostkey's fingerprint against our known hosts Your app * may have it hard coded, may go to a file, may present it to the * user, that's your call */ fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5); printf("Fingerprint: "); for(i = 0; i < 16; i++) { printf("%02X ", (unsigned char)fingerprint[i]); } printf("\n"); if (auth_pw) { /* We could authenticate via password */ if ((i = libssh2_userauth_password(session, username, password))) { printf("Authentication by password failed.\n"); goto shutdown; } } else { /* Or by public key */ if (libssh2_userauth_publickey_fromfile(session, username, "/home/username/.ssh/id_rsa.pub", "/home/username/.ssh/id_rsa", password)) { printf("\tAuthentication by public key failed\n"); goto shutdown; } } fprintf(stderr, "libssh2_sftp_init()!\n"); sftp_session = libssh2_sftp_init(session); if (!sftp_session) { fprintf(stderr, "Unable to init SFTP session\n"); goto shutdown; } /* Since we have not set non-blocking, tell libssh2 we are blocking */ libssh2_session_set_blocking(session, 1); fprintf(stderr, "libssh2_sftp_opendir()!\n"); /* Request a dir listing via SFTP */ sftp_handle = libssh2_sftp_opendir(sftp_session, sftppath); if (!sftp_handle) { fprintf(stderr, "Unable to open dir with SFTP\n"); goto shutdown; } fprintf(stderr, "libssh2_sftp_opendir() is done, now receive listing!\n"); do { char mem[512]; char longentry[512]; LIBSSH2_SFTP_ATTRIBUTES attrs; /* loop until we fail */ rc = libssh2_sftp_readdir_ex(sftp_handle, mem, sizeof(mem), longentry, sizeof(longentry), &attrs); if(rc > 0) { /* rc is the length of the file name in the mem buffer */ if (longentry[0] != '\0') { printf("%s\n", longentry); } else { if(attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { /* this should check what permissions it is and print the output accordingly */ printf("--fix----- "); } else { printf("---------- "); } if(attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID) { printf("%4ld %4ld ", attrs.uid, attrs.gid); } else { printf(" - - "); } if(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) { /* attrs.filesize is an uint64_t according to the docs but there is no really good and portable 64bit type for C before C99, and correspondingly there was no good printf() option for it... */ printf("%8lld ", attrs.filesize); } printf("%s\n", mem); } } else break; } while (1); libssh2_sftp_closedir(sftp_handle); libssh2_sftp_shutdown(sftp_session); shutdown: libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing"); libssh2_session_free(session); #ifdef WIN32 Sleep(1000); closesocket(sock); #else sleep(1); close(sock); #endif printf("all done\n"); return 0; }
CURLcode Curl_sftp_do(struct connectdata *conn, bool *done) { LIBSSH2_SFTP_ATTRIBUTES attrs; struct SSHPROTO *sftp = conn->data->reqdata.proto.ssh; CURLcode res = CURLE_OK; struct SessionHandle *data = conn->data; curl_off_t bytecount = 0; char *buf = data->state.buffer; *done = TRUE; /* unconditionally */ if (data->set.upload) { /* * NOTE!!! libssh2 requires that the destination path is a full path * that includes the destination file and name OR ends in a "/" . * If this is not done the destination file will be named the * same name as the last directory in the path. */ sftp->sftp_handle = libssh2_sftp_open(sftp->sftp_session, sftp->path, LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT, LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR| LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH); if (!sftp->sftp_handle) return CURLE_FAILED_INIT; /* upload data */ res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); } else { if (sftp->path[strlen(sftp->path)-1] == '/') { /* * This is a directory that we are trying to get, so produce a * directory listing * * **BLOCKING behaviour** This should be made into a state machine and * get a separate function called from Curl_sftp_recv() when there is * data to read from the network, instead of "hanging" here. */ char filename[PATH_MAX+1]; int len, totalLen, currLen; char *line; sftp->sftp_handle = libssh2_sftp_opendir(sftp->sftp_session, sftp->path); if (!sftp->sftp_handle) return CURLE_SSH; while ((len = libssh2_sftp_readdir(sftp->sftp_handle, filename, PATH_MAX, &attrs)) > 0) { filename[len] = '\0'; if (data->set.ftp_list_only) { if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) && ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFDIR)) { infof(data, "%s\n", filename); } } else { totalLen = 80 + len; line = (char *)malloc(totalLen); if (!line) return CURLE_OUT_OF_MEMORY; if (!(attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID)) attrs.uid = attrs.gid =0; currLen = snprintf(line, totalLen, "---------- 1 %5d %5d", attrs.uid, attrs.gid); if (attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFDIR) { line[0] = 'd'; } else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFLNK) { line[0] = 'l'; } else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFSOCK) { line[0] = 's'; } else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFCHR) { line[0] = 'c'; } else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFBLK) { line[0] = 'b'; } if (attrs.permissions & LIBSSH2_SFTP_S_IRUSR) { line[1] = 'r'; } if (attrs.permissions & LIBSSH2_SFTP_S_IWUSR) { line[2] = 'w'; } if (attrs.permissions & LIBSSH2_SFTP_S_IXUSR) { line[3] = 'x'; } if (attrs.permissions & LIBSSH2_SFTP_S_IRGRP) { line[4] = 'r'; } if (attrs.permissions & LIBSSH2_SFTP_S_IWGRP) { line[5] = 'w'; } if (attrs.permissions & LIBSSH2_SFTP_S_IXGRP) { line[6] = 'x'; } if (attrs.permissions & LIBSSH2_SFTP_S_IROTH) { line[7] = 'r'; } if (attrs.permissions & LIBSSH2_SFTP_S_IWOTH) { line[8] = 'w'; } if (attrs.permissions & LIBSSH2_SFTP_S_IXOTH) { line[9] = 'x'; } } if (attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) { currLen += snprintf(line+currLen, totalLen-currLen, "%11lld", attrs.filesize); } if (attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) { const char *months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; struct tm *nowParts; time_t now, remoteTime; now = time(NULL); remoteTime = (time_t)attrs.mtime; nowParts = localtime(&remoteTime); if ((time_t)attrs.mtime > (now - (3600 * 24 * 180))) { currLen += snprintf(line+currLen, totalLen-currLen, " %s %2d %2d:%02d", months[nowParts->tm_mon], nowParts->tm_mday, nowParts->tm_hour, nowParts->tm_min); } else { currLen += snprintf(line+currLen, totalLen-currLen, " %s %2d %5d", months[nowParts->tm_mon], nowParts->tm_mday, 1900+nowParts->tm_year); } } currLen += snprintf(line+currLen, totalLen-currLen, " %s", filename); if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) && ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFLNK)) { char linkPath[PATH_MAX + 1]; snprintf(linkPath, PATH_MAX, "%s%s", sftp->path, filename); len = libssh2_sftp_readlink(sftp->sftp_session, linkPath, filename, PATH_MAX); line = realloc(line, totalLen + 4 + len); if (!line) return CURLE_OUT_OF_MEMORY; currLen += snprintf(line+currLen, totalLen-currLen, " -> %s", filename); } currLen += snprintf(line+currLen, totalLen-currLen, "\n"); res = Curl_client_write(conn, CLIENTWRITE_BODY, line, 0); free(line); } } libssh2_sftp_closedir(sftp->sftp_handle); sftp->sftp_handle = NULL; /* no data to transfer */ res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); } else { /* * Work on getting the specified file */ sftp->sftp_handle = libssh2_sftp_open(sftp->sftp_session, sftp->path, LIBSSH2_FXF_READ, LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR| LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH); if (!sftp->sftp_handle) return CURLE_SSH; if (libssh2_sftp_stat(sftp->sftp_session, sftp->path, &attrs)) { /* * libssh2_sftp_open() didn't return an error, so maybe the server * just doesn't support stat() */ data->reqdata.size = -1; data->reqdata.maxdownload = -1; } else { data->reqdata.size = attrs.filesize; data->reqdata.maxdownload = attrs.filesize; Curl_pgrsSetDownloadSize(data, attrs.filesize); } Curl_pgrsTime(data, TIMER_STARTTRANSFER); /* Now download data. The libssh2 0.14 doesn't offer any way to do this without using this BLOCKING approach, so here's room for improvement once libssh2 can return EWOULDBLOCK to us. */ #if 0 /* code left here just because this is what this function will use the day libssh2 is improved */ res = Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL); #endif while (res == CURLE_OK) { size_t nread; /* NOTE: most *read() functions return ssize_t but this returns size_t which normally is unsigned! */ nread = libssh2_sftp_read(data->reqdata.proto.ssh->sftp_handle, buf, BUFSIZE-1); if (nread > 0) buf[nread] = 0; /* this check can be changed to a <= 0 when nread is changed to a signed variable type */ if ((nread == 0) || (nread == (size_t)~0)) break; bytecount += nread; res = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread); if(res) return res; Curl_pgrsSetDownloadCounter(data, bytecount); if(Curl_pgrsUpdate(conn)) res = CURLE_ABORTED_BY_CALLBACK; else { struct timeval now = Curl_tvnow(); res = Curl_speedcheck(data, now); } } if(Curl_pgrsUpdate(conn)) res = CURLE_ABORTED_BY_CALLBACK; /* no (more) data to transfer */ res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); } } return res; }