void set_file_times(WFile *f, unsigned long mtime, unsigned long atime) { FILETIME actime, wrtime; TIME_POSIX_TO_WIN(atime, actime); TIME_POSIX_TO_WIN(mtime, wrtime); SetFileTime(f->h, NULL, &actime, &wrtime); }
/* * Execute the sink part of the SCP protocol. */ static void sink(char *targ) { char buf[2048]; char namebuf[2048]; char ch; int targisdir = 0; int settime; int exists; DWORD attr; HANDLE f; unsigned long mtime, atime; unsigned int mode; unsigned long size, i; int wrerror = 0; unsigned long stat_bytes; time_t stat_starttime, stat_lasttime; char *stat_name; attr = GetFileAttributes(targ); if (attr != (DWORD)-1 && (attr & FILE_ATTRIBUTE_DIRECTORY) != 0) targisdir = 1; if (targetshouldbedirectory && !targisdir) bump("%s: Not a directory", targ); ssh_send("", 1); while (1) { settime = 0; gottime: if (ssh_recv(&ch, 1) <= 0) return; if (ch == '\n') bump("Protocol error: Unexpected newline"); i = 0; buf[i++] = ch; do { if (ssh_recv(&ch, 1) <= 0) bump("Lost connection"); buf[i++] = ch; } while (i < sizeof(buf) && ch != '\n'); buf[i-1] = '\0'; switch (buf[0]) { case '\01': /* error */ fprintf(stderr, "%s\n", buf+1); errs++; continue; case '\02': /* fatal error */ bump("%s", buf+1); case 'E': ssh_send("", 1); return; case 'T': if (sscanf(buf, "T%ld %*d %ld %*d", &mtime, &atime) == 2) { settime = 1; ssh_send("", 1); goto gottime; } bump("Protocol error: Illegal time format"); case 'C': case 'D': break; default: bump("Protocol error: Expected control record"); } if (sscanf(buf+1, "%u %lu %[^\n]", &mode, &size, namebuf) != 3) bump("Protocol error: Illegal file descriptor format"); if (targisdir) { char t[2048]; strcpy(t, targ); if (targ[0] != '\0') strcat(t, "/"); strcat(t, namebuf); strcpy(namebuf, t); } else { strcpy(namebuf, targ); } attr = GetFileAttributes(namebuf); exists = (attr != (DWORD)-1); if (buf[0] == 'D') { if (exists && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0) { run_err("%s: Not a directory", namebuf); continue; } if (!exists) { if (! CreateDirectory(namebuf, NULL)) { run_err("%s: Cannot create directory", namebuf); continue; } } sink(namebuf); /* can we set the timestamp for directories ? */ continue; } f = CreateFile(namebuf, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (f == INVALID_HANDLE_VALUE) { run_err("%s: Cannot create file", namebuf); continue; } ssh_send("", 1); if (statistics) { stat_bytes = 0; stat_starttime = time(NULL); stat_lasttime = 0; if ((stat_name = strrchr(namebuf, '/')) == NULL) stat_name = namebuf; else stat_name++; if (strrchr(stat_name, '\\') != NULL) stat_name = strrchr(stat_name, '\\') + 1; } for (i = 0; i < size; i += 4096) { char transbuf[4096]; DWORD j, k = 4096; if (i + k > size) k = size - i; if (ssh_recv(transbuf, k) == 0) bump("Lost connection"); if (wrerror) continue; if (! WriteFile(f, transbuf, k, &j, NULL) || j != k) { wrerror = 1; if (statistics) printf("\r%-25.25s | %50s\n", stat_name, "Write error.. waiting for end of file"); continue; } if (statistics) { stat_bytes += k; if (time(NULL) > stat_lasttime || i + k == size) { stat_lasttime = time(NULL); print_stats(stat_name, size, stat_bytes, stat_starttime, stat_lasttime); } } } (void) response(); if (settime) { FILETIME actime, wrtime; TIME_POSIX_TO_WIN(atime, actime); TIME_POSIX_TO_WIN(mtime, wrtime); SetFileTime(f, NULL, &actime, &wrtime); } CloseHandle(f); if (wrerror) { run_err("%s: Write error", namebuf); continue; } ssh_send("", 1); } }