static void process_readdir(u_int32_t id) { DIR *dirp; struct dirent *dp; char *path; int handle; handle = get_handle(); debug("request %u: readdir \"%s\" (handle %d)", id, handle_to_name(handle), handle); dirp = handle_to_dir(handle); path = handle_to_name(handle); if (dirp == NULL || path == NULL) { send_status(id, SSH2_FX_FAILURE); } else { struct stat st; char pathname[MAXPATHLEN]; Stat *stats; int nstats = 10, count = 0, i; stats = xcalloc(nstats, sizeof(Stat)); while ((dp = readdir(dirp)) != NULL) { if (count >= nstats) { nstats *= 2; stats = xrealloc(stats, nstats, sizeof(Stat)); } /* XXX OVERFLOW ? */ snprintf(pathname, sizeof pathname, "%s%s%s", path, strcmp(path, "/") ? "/" : "", dp->d_name); if (lstat(pathname, &st) < 0) continue; stat_to_attrib(&st, &(stats[count].attrib)); stats[count].name = xstrdup(dp->d_name); stats[count].long_name = ls_file(dp->d_name, &st, 0, 0); count++; /* send up to 100 entries in one message */ /* XXX check packet size instead */ if (count == 100) break; } if (count > 0) { send_names(id, count, stats); for (i = 0; i < count; i++) { free(stats[i].name); free(stats[i].long_name); } } else { send_status(id, SSH2_FX_EOF); } #ifdef NERSC_MOD char* t1buf = encode_string(path, strlen(path)); s_audit("sftp_process_readdir_3", "count=%i int=%d uristring=%s", get_client_session_id(), (int)getppid(), t1buf); #endif free(stats); } }
static void process_readdir(u_int32_t id) { DIR *dirp; struct dirent *dp; char *path; int r, handle; if ((r = get_handle(iqueue, &handle)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("request %u: readdir \"%s\" (handle %d)", id, handle_to_name(handle), handle); dirp = handle_to_dir(handle); path = handle_to_name(handle); if (dirp == NULL || path == NULL) { send_status(id, SSH2_FX_FAILURE); } else { struct stat st; char pathname[PATH_MAX]; Stat *stats; int nstats = 10, count = 0, i; stats = xcalloc(nstats, sizeof(Stat)); while ((dp = readdir(dirp)) != NULL) { if (count >= nstats) { nstats *= 2; stats = xreallocarray(stats, nstats, sizeof(Stat)); } /* XXX OVERFLOW ? */ snprintf(pathname, sizeof pathname, "%s%s%s", path, strcmp(path, "/") ? "/" : "", dp->d_name); if (lstat(pathname, &st) < 0) continue; stat_to_attrib(&st, &(stats[count].attrib)); stats[count].name = xstrdup(dp->d_name); stats[count].long_name = ls_file(dp->d_name, &st, 0, 0); count++; /* send up to 100 entries in one message */ /* XXX check packet size instead */ if (count == 100) break; } if (count > 0) { send_names(id, count, stats); for (i = 0; i < count; i++) { free(stats[i].name); free(stats[i].long_name); } } else { send_status(id, SSH2_FX_EOF); } free(stats); } }
void SFTP::handle_log_close(int handle, char *emsg) { if (handle_is_ok(handle, HANDLE_FILE)) { logit("%s%sclose \"%s\" bytes read %llu written %llu", emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ", toUTF8(handle_to_name(handle)).c_str (), (unsigned long long)handle_bytes_read(handle), (unsigned long long)handle_bytes_write(handle)); } else { logit("%s%sclosedir \"%s\"", emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ", toUTF8(handle_to_name(handle)).c_str ()); } }
static void process_fstat(void) { Attrib a; struct stat st; u_int32_t id; int fd, ret, handle, status = SSH2_FX_FAILURE; id = get_int(); handle = get_handle(); debug("request %u: fstat \"%s\" (handle %u)", id, handle_to_name(handle), handle); fd = handle_to_fd(handle); if (fd >= 0) { ret = fstat(fd, &st); if (ret < 0) { status = errno_to_portable(errno); } else { stat_to_attrib(&st, &a); send_attrib(id, &a); status = SSH2_FX_OK; } } if (status != SSH2_FX_OK) send_status(id, status); }
void SFTP::process_fstat(void) { Attrib a; BY_HANDLE_FILE_INFORMATION st; u_int32_t id; int handle, status = SSH2_FX_FAILURE; id = get_int(); handle = get_handle(); debug("request %u: fstat \"%s\" (handle %u)", id, toUTF8(handle_to_name(handle)).c_str (), handle); const HANDLE fh = handle_to_fh(handle); if (fh != INVALID_HANDLE_VALUE) { if (!::GetFileInformationByHandle (fh, &st)) { status = errno_to_portable(::GetLastError ()); } else { stat_to_attrib(&st, &a); send_attrib(id, &a); status = SSH2_FX_OK; } } if (status != SSH2_FX_OK) send_status(id, status); }
static void process_fstat(u_int32_t id) { Attrib a; struct stat st; int fd, ret, handle, status = SSH2_FX_FAILURE; handle = get_handle(); debug("request %u: fstat \"%s\" (handle %u)", id, handle_to_name(handle), handle); fd = handle_to_fd(handle); if (fd >= 0) { ret = fstat(fd, &st); if (ret < 0) { status = errno_to_portable(errno); } else { stat_to_attrib(&st, &a); send_attrib(id, &a); status = SSH2_FX_OK; } } if (status != SSH2_FX_OK) send_status(id, status); #ifdef NERSC_MOD s_audit("sftp_process_fstat_3", "count=%i int=%d int=%d", get_client_session_id(), (int)getppid(), handle); #endif }
static void process_fstat(u_int32_t id) { Attrib a; struct stat st; int fd, r, handle, status = SSH2_FX_FAILURE; if ((r = get_handle(iqueue, &handle)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("request %u: fstat \"%s\" (handle %u)", id, handle_to_name(handle), handle); fd = handle_to_fd(handle); if (fd >= 0) { r = fstat(fd, &st); if (r < 0) { status = errno_to_portable(errno); } else { stat_to_attrib(&st, &a); send_attrib(id, &a); status = SSH2_FX_OK; } } if (status != SSH2_FX_OK) send_status(id, status); }
void SFTP::process_write(void) { u_int32_t id; u_int64_t off; u_int len; int handle, status = SSH2_FX_FAILURE; char *data; id = get_int(); handle = get_handle(); off = get_int64(); data = (char*) get_string(&len); #ifdef SLOW_DEBUG debug("request %u: write \"%s\" (handle %d) off %llu len %d", id, toUTF8 (handle_to_name(handle)).c_str (), handle, (unsigned long long)off, len); #endif HANDLE fh = handle_to_fh(handle); if (fh != INVALID_HANDLE_VALUE) { LARGE_INTEGER largeOffset; largeOffset.QuadPart = off; if (!::SetFilePointerEx (fh, largeOffset, NULL, FILE_BEGIN) ) { status = errno_to_portable(::GetLastError ()); error("process_write: seek failed"); } else { /* XXX ATOMICIO ? */ DWORD nBytesWritten; if (!::WriteFile (fh, data, len, &nBytesWritten, 0)) { error("process_write: write failed"); int err = ::GetLastError (); if (err != 0) status = errno_to_portable(err); else status = SSH2_FX_FAILURE; //TODO reason? } else if ((size_t) nBytesWritten == len) { status = SSH2_FX_OK; handle_update_write(handle, (ssize_t) nBytesWritten); } else { debug2("nothing at all written"); } } } send_status(id, status); xfree(data); }
static void process_fsetstat(void) { Attrib *a; u_int32_t id; int handle, fd, ret; int status = SSH2_FX_OK; id = get_int(); handle = get_handle(); a = get_attrib(); debug("request %u: fsetstat handle %d", id, handle); fd = handle_to_fd(handle); if (fd < 0) status = SSH2_FX_FAILURE; else if (readonly) status = SSH2_FX_PERMISSION_DENIED; else { char *name = handle_to_name(handle); if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { logit("set \"%s\" size %llu", name, (unsigned long long)a->size); ret = ftruncate(fd, a->size); if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { logit("set \"%s\" mode %04o", name, a->perm); ret = fchmod(fd, a->perm & 07777); if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { char buf[64]; time_t t = a->mtime; strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", localtime(&t)); logit("set \"%s\" modtime %s", name, buf); ret = futimes(fd, attrib_to_tv(a)); if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { logit("set \"%s\" owner %lu group %lu", name, (u_long)a->uid, (u_long)a->gid); ret = fchown(fd, a->uid, a->gid); if (ret == -1) status = errno_to_portable(errno); } } send_status(id, status); }
static void process_readdir(void) { DIR *dirp; struct dirent *dp; char *path; int handle; u_int32_t id; id = get_int(); handle = get_handle(); TRACE("readdir id %u handle %d", id, handle); dirp = handle_to_dir(handle); path = handle_to_name(handle); if (dirp == NULL || path == NULL) { send_status(id, SSH2_FX_FAILURE); } else { struct stat st; char pathname[1024]; Stat *stats; int nstats = 10, count = 0, i; stats = xmalloc(nstats * sizeof(Stat)); while ((dp = readdir(dirp)) != NULL) { if (count >= nstats) { nstats *= 2; stats = xrealloc(stats, nstats * sizeof(Stat)); } /* XXX OVERFLOW ? */ snprintf(pathname, sizeof pathname, "%s%s%s", path, strcmp(path, "/") ? "/" : "", dp->d_name); if (lstat(pathname, &st) < 0) continue; stat_to_attrib(&st, &(stats[count].attrib)); stats[count].name = xstrdup(dp->d_name); stats[count].long_name = ls_file(dp->d_name, &st); count++; /* send up to 100 entries in one message */ /* XXX check packet size instead */ if (count == 100) break; } if (count > 0) { send_names(id, count, stats); for (i = 0; i < count; i++) { xfree(stats[i].name); xfree(stats[i].long_name); } } else { send_status(id, SSH2_FX_EOF); } xfree(stats); } }
static void process_fsetstat(void) { Attrib *a; u_int32_t id; int handle, fd, ret; int status = SSH2_FX_OK; char *name; id = get_int(); handle = get_handle(); a = get_attrib(); TRACE("fsetstat id %u handle %d", id, handle); fd = handle_to_fd(handle); name = handle_to_name(handle); if (fd < 0 || name == NULL) { status = SSH2_FX_FAILURE; } else { if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { ret = ftruncate(fd, a->size); if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { #ifdef HAVE_FCHMOD ret = fchmod(fd, a->perm & 0777); #else ret = chmod(name, a->perm & 0777); #endif if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { #ifdef HAVE_FUTIMES ret = futimes(fd, attrib_to_tv(a)); #else ret = utimes(name, attrib_to_tv(a)); #endif if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { #ifdef HAVE_FCHOWN ret = fchown(fd, a->uid, a->gid); #else ret = chown(name, a->uid, a->gid); #endif if (ret == -1) status = errno_to_portable(errno); } } send_status(id, status); }
static void process_fsetstat(u_int32_t id) { Attrib a; int handle, fd, r; int status = SSH2_FX_OK; if ((r = get_handle(iqueue, &handle)) != 0 || (r = decode_attrib(iqueue, &a)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("request %u: fsetstat handle %d", id, handle); fd = handle_to_fd(handle); if (fd < 0) status = SSH2_FX_FAILURE; else { char *name = handle_to_name(handle); if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { logit("set \"%s\" size %llu", name, (unsigned long long)a.size); r = ftruncate(fd, a.size); if (r == -1) status = errno_to_portable(errno); } if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { logit("set \"%s\" mode %04o", name, a.perm); r = fchmod(fd, a.perm & 07777); if (r == -1) status = errno_to_portable(errno); } if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { char buf[64]; time_t t = a.mtime; strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", localtime(&t)); logit("set \"%s\" modtime %s", name, buf); r = futimes(fd, attrib_to_tv(&a)); if (r == -1) status = errno_to_portable(errno); } if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { logit("set \"%s\" owner %lu group %lu", name, (u_long)a.uid, (u_long)a.gid); r = fchown(fd, a.uid, a.gid); if (r == -1) status = errno_to_portable(errno); } } send_status(id, status); }
static void process_extended_fsync(u_int32_t id) { int handle, fd, ret, status = SSH2_FX_OP_UNSUPPORTED; handle = get_handle(); debug3("request %u: fsync (handle %u)", id, handle); verbose("fsync \"%s\"", handle_to_name(handle)); if ((fd = handle_to_fd(handle)) < 0) status = SSH2_FX_NO_SUCH_FILE; else if (handle_is_ok(handle, HANDLE_FILE)) { ret = fsync(fd); status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; } send_status(id, status); }
static void process_extended_fsync(u_int32_t id) { int handle, fd, r, status = SSH2_FX_OP_UNSUPPORTED; if ((r = get_handle(iqueue, &handle)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug3("request %u: fsync (handle %u)", id, handle); verbose("fsync \"%s\"", handle_to_name(handle)); if ((fd = handle_to_fd(handle)) < 0) status = SSH2_FX_NO_SUCH_FILE; else if (handle_is_ok(handle, HANDLE_FILE)) { r = fsync(fd); status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; } send_status(id, status); }
static void process_extended_fstatvfs(u_int32_t id) { int handle, fd; struct statvfs st; handle = get_handle(); debug("request %u: fstatvfs \"%s\" (handle %u)", id, handle_to_name(handle), handle); if ((fd = handle_to_fd(handle)) < 0) { send_status(id, SSH2_FX_FAILURE); return; } if (fstatvfs(fd, &st) != 0) send_status(id, errno_to_portable(errno)); else send_statvfs(id, &st); }
static void process_write(void) { u_int32_t id; u_int64_t off; u_int len; int handle, fd, ret, status; char *data; id = get_int(); handle = get_handle(); off = get_int64(); data = get_string(&len); debug("request %u: write \"%s\" (handle %d) off %llu len %d", id, handle_to_name(handle), handle, (unsigned long long)off, len); fd = handle_to_fd(handle); if (fd < 0) status = SSH2_FX_FAILURE; else if (readonly) status = SSH2_FX_PERMISSION_DENIED; else { if (lseek(fd, off, SEEK_SET) < 0) { status = errno_to_portable(errno); error("process_write: seek failed"); } else { /* XXX ATOMICIO ? */ ret = write(fd, data, len); if (ret < 0) { error("process_write: write failed"); status = errno_to_portable(errno); } else if ((size_t)ret == len) { status = SSH2_FX_OK; handle_update_write(handle, ret); } else { debug2("nothing at all written"); status = SSH2_FX_FAILURE; } } } send_status(id, status); xfree(data); }
static void process_extended_fstatvfs(u_int32_t id) { int r, handle, fd; struct statvfs st; if ((r = get_handle(iqueue, &handle)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("request %u: fstatvfs \"%s\" (handle %u)", id, handle_to_name(handle), handle); if ((fd = handle_to_fd(handle)) < 0) { send_status(id, SSH2_FX_FAILURE); return; } if (fstatvfs(fd, &st) != 0) send_status(id, errno_to_portable(errno)); else send_statvfs(id, &st); }
static void process_write(u_int32_t id) { u_int64_t off; size_t len; int r, handle, fd, ret, status; u_char *data; if ((r = get_handle(iqueue, &handle)) != 0 || (r = sshbuf_get_u64(iqueue, &off)) != 0 || (r = sshbuf_get_string(iqueue, &data, &len)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("request %u: write \"%s\" (handle %d) off %llu len %zu", id, handle_to_name(handle), handle, (unsigned long long)off, len); fd = handle_to_fd(handle); if (fd < 0) status = SSH2_FX_FAILURE; else { if (!(handle_to_flags(handle) & O_APPEND) && lseek(fd, off, SEEK_SET) < 0) { status = errno_to_portable(errno); error("process_write: seek failed"); } else { /* XXX ATOMICIO ? */ ret = write(fd, data, len); if (ret < 0) { error("process_write: write failed"); status = errno_to_portable(errno); } else if ((size_t)ret == len) { status = SSH2_FX_OK; handle_update_write(handle, ret); } else { debug2("nothing at all written"); status = SSH2_FX_FAILURE; } } } send_status(id, status); free(data); }
static void process_read(u_int32_t id) { u_char buf[64*1024]; u_int32_t len; int r, handle, fd, ret, status = SSH2_FX_FAILURE; u_int64_t off; if ((r = get_handle(iqueue, &handle)) != 0 || (r = sshbuf_get_u64(iqueue, &off)) != 0 || (r = sshbuf_get_u32(iqueue, &len)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("request %u: read \"%s\" (handle %d) off %llu len %d", id, handle_to_name(handle), handle, (unsigned long long)off, len); if (len > sizeof buf) { len = sizeof buf; debug2("read change len %d", len); } fd = handle_to_fd(handle); if (fd >= 0) { if (lseek(fd, off, SEEK_SET) < 0) { error("process_read: seek failed"); status = errno_to_portable(errno); } else { ret = read(fd, buf, len); if (ret < 0) { status = errno_to_portable(errno); } else if (ret == 0) { status = SSH2_FX_EOF; } else { send_data(id, buf, ret); status = SSH2_FX_OK; handle_update_read(handle, ret); } } } if (status != SSH2_FX_OK) send_status(id, status); }
static void process_read(void) { char buf[64*1024]; u_int32_t id, len; int handle, fd, ret, status = SSH2_FX_FAILURE; u_int64_t off; id = get_int(); handle = get_handle(); off = get_int64(); len = get_int(); debug("request %u: read \"%s\" (handle %d) off %llu len %d", id, handle_to_name(handle), handle, (unsigned long long)off, len); if (len > sizeof buf) { len = sizeof buf; debug2("read change len %d", len); } fd = handle_to_fd(handle); if (fd >= 0) { if (lseek(fd, off, SEEK_SET) < 0) { error("process_read: seek failed"); status = errno_to_portable(errno); } else { ret = read(fd, buf, len); if (ret < 0) { status = errno_to_portable(errno); } else if (ret == 0) { status = SSH2_FX_EOF; } else { send_data(id, buf, ret); status = SSH2_FX_OK; handle_update_read(handle, ret); } } } if (status != SSH2_FX_OK) send_status(id, status); }
static void process_fsetstat(u_int32_t id) { Attrib *a; int handle, fd, ret; int status = SSH2_FX_OK; handle = get_handle(); a = get_attrib(); debug("request %u: fsetstat handle %d", id, handle); fd = handle_to_fd(handle); if (fd < 0) status = SSH2_FX_FAILURE; else { char *name = handle_to_name(handle); if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { logit("set \"%s\" size %llu", name, (unsigned long long)a->size); ret = ftruncate(fd, a->size); if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { logit("set \"%s\" mode %04o", name, a->perm); #ifdef HAVE_FCHMOD ret = fchmod(fd, a->perm & 07777); #else ret = chmod(name, a->perm & 07777); #endif if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { char buf[64]; time_t t = a->mtime; strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", localtime(&t)); logit("set \"%s\" modtime %s", name, buf); #ifdef HAVE_FUTIMES ret = futimes(fd, attrib_to_tv(a)); #else ret = utimes(name, attrib_to_tv(a)); #endif if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { logit("set \"%s\" owner %lu group %lu", name, (u_long)a->uid, (u_long)a->gid); #ifdef HAVE_FCHOWN ret = fchown(fd, a->uid, a->gid); #else ret = chown(name, a->uid, a->gid); #endif if (ret == -1) status = errno_to_portable(errno); } } send_status(id, status); #ifdef NERSC_MOD char* t1buf = encode_string( handle_to_name(handle), strlen(handle_to_name(handle)) ); s_audit("sftp_process_fsetstat_3", "count=%i int=%d int=%d uristring=%s", get_client_session_id(), (int)getppid(), id, t1buf); free(t1buf); #endif }
void SFTP::process_read(void) { char buf[64*1024]; u_int32_t id, len; int handle, status = SSH2_FX_FAILURE; u_int64_t off; id = get_int(); handle = get_handle(); off = get_int64(); len = get_int(); #ifdef SLOW_DEBUG debug("request %u: read \"%s\" (handle %d) off %llu len %d", id, toUTF8(handle_to_name(handle)).c_str (), handle, (unsigned long long)off, len); #endif if (len > sizeof buf) { len = sizeof buf; debug2("read change len %d", len); } HANDLE fh = handle_to_fh(handle); if (fh != INVALID_HANDLE_VALUE) { LARGE_INTEGER largeOffset; largeOffset.QuadPart = off; if (!::SetFilePointerEx (fh, largeOffset, NULL, FILE_BEGIN)) { int err = ::GetLastError (); if (!err) status = SSH2_FX_EOF; else { error("process_read: seek failed"); status = errno_to_portable(err); } } else { DWORD nBytesRed = 0; if (!::ReadFile (fh, buf, len, &nBytesRed, 0)) { status = errno_to_portable(::GetLastError ()); } else if (nBytesRed == 0) { status = SSH2_FX_EOF; } else { if (nBytesRed < len) debug ("process_read: requested %u, " "%u was red", (unsigned) len, (unsigned) nBytesRed); send_data(id, buf, (u_int) nBytesRed); status = SSH2_FX_OK; handle_update_read(handle, (u_int) nBytesRed); } } } if (status != SSH2_FX_OK) send_status(id, status); }
void SFTP::process_readdir(void) { int handle; u_int32_t id; id = get_int(); handle = get_handle(); debug("request %u: readdir \"%s\" (handle %d)", id, toUTF8(handle_to_name(handle)).c_str (), handle); HANDLE dh = handle_to_dir(handle); const SFTPFilePath dirPath (handle_to_path (handle)); if (dh == INVALID_HANDLE_VALUE || dirPath.to_string ().length () == 0 ) { send_status(id, SSH2_FX_FAILURE); } else { WIN32_FIND_DATA st; //char pathname[MAXPATHLEN]; Stat *stats; int nstats = 10, count = 0, i; stats = (Stat*) xcalloc(nstats, sizeof(Stat)); HANDLE& searchHandle = handles[handle].searchHandle; bool& searchDone = handles[handle].searchDone; if (!searchDone && searchHandle == INVALID_HANDLE_VALUE) { assert (!searchDone); searchHandle = ::FindFirstFile (dirPath.get_mask_for_dir_search ().c_str (), &st ); } if (!searchDone && searchHandle != INVALID_HANDLE_VALUE ) { searchDone = true; while (::FindNextFileW (searchHandle, &st)) { if (count >= nstats) { nstats *= 2; stats = (Stat*) xrealloc(stats, nstats, sizeof(Stat)); } stat_to_attrib(&st, &(stats[count].attrib)); stats[count].name = xstrdup (toUTF8(st.cFileName).c_str ()); stats[count].long_name = xstrdup (toUTF8 (ls_file(st.cFileName, &st, 0)).c_str ()); count++; /* send up to 100 entries in one message */ /* XXX check packet size instead */ if (count == 100) { searchDone = false; break; } } /*if (searchDone) ::GetLastError (); // read error of FindNextFile*/ } if (searchDone && searchHandle != INVALID_HANDLE_VALUE) { ::FindClose (searchHandle); searchHandle = 0; } if (count > 0) { send_names(id, count, stats); for (i = 0; i < count; i++) { xfree(stats[i].name); xfree(stats[i].long_name); } } else { searchHandle = INVALID_HANDLE_VALUE; searchDone = false; send_status(id, SSH2_FX_EOF); } xfree(stats); } }