static int fudge_stat(const char *path, struct stat *st) { Attrib *a; if (!(a = do_stat(cur.conn, (char *)path, 0))) return(-1); attrib_to_stat(a, st); return(0); }
void SFTP::process_fsetstat(void) { Attrib a; u_int32_t id; int handle; int status = SSH2_FX_OK; id = get_int(); handle = get_handle(); a = get_attrib(this->iqueue); debug("request %u: fsetstat handle %d", id, handle); HANDLE fh = handle_to_fh(handle); if (fh == INVALID_HANDLE_VALUE) { status = SSH2_FX_FAILURE; } else { if (status == SSH2_FX_OK && a.flags & SSH2_FILEXFER_ATTR_UIDGID) { #if 0 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(::GetLastError ()); #endif status = SSH2_FX_OP_UNSUPPORTED; } if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { logit("set \"%s\" size %llu", "???", (unsigned long long)a.size); LARGE_INTEGER largeOffset; largeOffset.QuadPart = a.size; if (!::SetFilePointerEx (fh, largeOffset, NULL, FILE_BEGIN) || !::SetEndOfFile (fh) ) { status = errno_to_portable(::GetLastError ()); } } if (status == SSH2_FX_OK) { BY_HANDLE_FILE_INFORMATION stBefore; FILE_BASIC_INFO stAfter; WIN32_FILE_ATTRIBUTE_DATA stRequested; if (::GetFileInformationByHandle (fh, &stBefore)) { attrib_to_stat (&a, &stRequested); if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { logit("set \"%s\" mode %04o", "???", a.perm); stAfter.FileAttributes = stRequested.dwFileAttributes; } else stAfter.FileAttributes = stBefore.dwFileAttributes; 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);*/ //TODO COPY_TO_LARGE_INTEGER (stAfter.LastAccessTime, stRequested.ftLastAccessTime.dwLowDateTime, stRequested.ftLastAccessTime.dwHighDateTime); COPY_TO_LARGE_INTEGER (stAfter.LastWriteTime, stRequested.ftLastWriteTime.dwLowDateTime, stRequested.ftLastWriteTime.dwHighDateTime); } else { COPY_TO_LARGE_INTEGER (stAfter.LastAccessTime, stBefore.ftLastAccessTime.dwLowDateTime, stBefore.ftLastAccessTime.dwHighDateTime); COPY_TO_LARGE_INTEGER (stAfter.LastWriteTime, stBefore.ftLastWriteTime.dwLowDateTime, stBefore.ftLastWriteTime.dwHighDateTime); } COPY_TO_LARGE_INTEGER (stAfter.CreationTime, stBefore.ftCreationTime.dwLowDateTime, stBefore.ftCreationTime.dwHighDateTime); SYSTEMTIME systemTime; FILETIME currentTime; ::GetSystemTime(&systemTime); ::SystemTimeToFileTime(&systemTime, ¤tTime); COPY_TO_LARGE_INTEGER (stAfter.ChangeTime, currentTime.dwLowDateTime, currentTime.dwHighDateTime); if (!::SetFileInformationByHandle (fh, FileBasicInfo, &stAfter, sizeof (stAfter) ) ) status = errno_to_portable(::GetLastError ()); } else { status = errno_to_portable(::GetLastError ()); } } } send_status(id, status); }
/* sftp ls.1 replacement which handles path globs */ static int do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path, int lflag) { glob_t g; u_int i, c = 1, colspace = 0, columns = 1; Attrib *a = NULL; memset(&g, 0, sizeof(g)); if (remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE, NULL, &g) || (g.gl_pathc && !g.gl_matchc)) { if (g.gl_pathc) globfree(&g); error("Can't ls: \"%s\" not found", path); return (-1); } if (interrupted) goto out; /* * If the glob returns a single match and it is a directory, * then just list its contents. */ if (g.gl_matchc == 1) { if ((a = do_lstat(conn, g.gl_pathv[0], 1)) == NULL) { globfree(&g); return (-1); } if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && S_ISDIR(a->perm)) { int err; err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag); globfree(&g); return (err); } } if (!(lflag & LS_SHORT_VIEW)) { u_int m = 0, width = 80; struct winsize ws; /* Count entries for sort and find longest filename */ for (i = 0; g.gl_pathv[i]; i++) m = MAX(m, strlen(g.gl_pathv[i])); if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) width = ws.ws_col; columns = width / (m + 2); columns = MAX(columns, 1); colspace = width / columns; } for (i = 0; g.gl_pathv[i] && !interrupted; i++, a = NULL) { char *fname; fname = path_strip(g.gl_pathv[i], strip_path); if (lflag & LS_LONG_VIEW) { char *lname; struct stat sb; /* * XXX: this is slow - 1 roundtrip per path * A solution to this is to fork glob() and * build a sftp specific version which keeps the * attribs (which currently get thrown away) * that the server returns as well as the filenames. */ memset(&sb, 0, sizeof(sb)); if (a == NULL) a = do_lstat(conn, g.gl_pathv[i], 1); if (a != NULL) attrib_to_stat(a, &sb); lname = ls_file(fname, &sb, 1); printf("%s\n", lname); xfree(lname); } else { printf("%-*s", colspace, fname); if (c >= columns) { printf("\n"); c = 1; } else c++; } xfree(fname); } if (!(lflag & LS_LONG_VIEW) && (c != 1)) printf("\n"); out: if (g.gl_pathc) globfree(&g); return (0); }
void SFTP::process_setstat(void) { Attrib a; u_int32_t id; char *utf8_name; int status = SSH2_FX_OK; WIN32_FILE_ATTRIBUTE_DATA st; try { id = get_int(); utf8_name = (char*) get_string(NULL); a = get_attrib(this->iqueue); debug("request %u: setstat name \"%s\"", id, utf8_name); const SFTPFilePath path = pathFact.create_path (utf8_name); attrib_to_stat (&a, &st); if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { #if 0 logit("set \"%s\" size %llu", utf8_name, (unsigned long long)a->size); LARGE_INTEGER largeOffset; largeOffset.QuadPart = a->size; if (!::SetFilePointerEx (fh, largeOffset, NULL, FILE_BEGIN) || !::SetEndOfFile (fh) ) { status = errno_to_portable(::GetLastError ()); } #endif status = SSH2_FX_OP_UNSUPPORTED; } if (status == SSH2_FX_OK && a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { #if 0 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 = utimes(name, attrib_to_tv(a)); if (ret == -1) status = errno_to_portable(::GetLastError ()); #endif status = SSH2_FX_OP_UNSUPPORTED; } if (status == SSH2_FX_OK && a.flags & SSH2_FILEXFER_ATTR_UIDGID) { #if 0 logit("set \"%s\" owner %lu group %lu", name, (u_long)a->uid, (u_long)a->gid); ret = chown(name, a->uid, a->gid); if (ret == -1) status = errno_to_portable(::GetLastError ()); #endif status = SSH2_FX_OP_UNSUPPORTED; } // access premissions if (status == SSH2_FX_OK && a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { logit("set \"%s\" mode %04o", utf8_name, a.perm); if (!::SetFileAttributesW (path.get_for_call ().c_str (), st.dwFileAttributes) ) { status = errno_to_portable(::GetLastError ()); } } } catch (Path::InvalidPath&) { //logit status = SSH2_FX_FAILURE; // TODO return the reason } catch (...) { status = SSH2_FX_FAILURE; error ("unhandled exception in %s", __FUNCTION__); } send_status(id, status); if (utf8_name) xfree(utf8_name); }
/* sftp ls.1 replacement for directories */ static int do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag) { int n; u_int c = 1, colspace = 0, columns = 1; SFTP_DIRENT **d; if ((n = do_readdir(conn, path, &d)) != 0) return (n); if (!(lflag & LS_SHORT_VIEW)) { u_int m = 0, width = 80; struct winsize ws; char *tmp; /* Count entries for sort and find longest filename */ for (n = 0; d[n] != NULL; n++) { if (d[n]->filename[0] != '.' || (lflag & LS_SHOW_ALL)) m = MAX(m, strlen(d[n]->filename)); } /* Add any subpath that also needs to be counted */ tmp = path_strip(path, strip_path); m += strlen(tmp); xfree(tmp); if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) width = ws.ws_col; columns = width / (m + 2); columns = MAX(columns, 1); colspace = width / columns; colspace = MIN(colspace, width); } if (lflag & SORT_FLAGS) { for (n = 0; d[n] != NULL; n++) ; /* count entries */ sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT); qsort(d, n, sizeof(*d), sdirent_comp); } for (n = 0; d[n] != NULL && !interrupted; n++) { char *tmp, *fname; if (d[n]->filename[0] == '.' && !(lflag & LS_SHOW_ALL)) continue; tmp = path_append(path, d[n]->filename); fname = path_strip(tmp, strip_path); xfree(tmp); if (lflag & LS_LONG_VIEW) { if (lflag & LS_NUMERIC_VIEW) { char *lname; struct stat sb; memset(&sb, 0, sizeof(sb)); attrib_to_stat(&d[n]->a, &sb); lname = ls_file(fname, &sb, 1); printf("%s\n", lname); xfree(lname); } else printf("%s\n", d[n]->longname); } else { printf("%-*s", colspace, fname); if (c >= columns) { printf("\n"); c = 1; } else c++; } xfree(fname); } if (!(lflag & LS_LONG_VIEW) && (c != 1)) printf("\n"); free_sftp_dirents(d); return (0); }