... and there's a Unix port of PSCP. Ooh.
[u/mdw/putty] / unix / uxsftp.c
index d1989f8..69d4c45 100644 (file)
@@ -4,8 +4,13 @@
 \r
 #include <sys/time.h>\r
 #include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <fcntl.h>\r
+#include <dirent.h>\r
 #include <unistd.h>\r
+#include <utime.h>\r
 #include <errno.h>\r
+#include <assert.h>\r
 \r
 #include "putty.h"\r
 #include "psftp.h"\r
@@ -109,6 +114,211 @@ char *psftp_getcwd(void)
     }\r
 }\r
 \r
+struct RFile {\r
+    int fd;\r
+};\r
+\r
+RFile *open_existing_file(char *name, unsigned long *size,\r
+                         unsigned long *mtime, unsigned long *atime)\r
+{\r
+    int fd;\r
+    RFile *ret;\r
+\r
+    fd = open(name, O_RDONLY);\r
+    if (fd < 0)\r
+       return NULL;\r
+\r
+    ret = snew(RFile);\r
+    ret->fd = fd;\r
+\r
+    if (size || mtime || atime) {\r
+       struct stat statbuf;\r
+       if (fstat(fd, &statbuf) < 0) {\r
+           fprintf(stderr, "%s: stat: %s\n", name, strerror(errno));\r
+           memset(&statbuf, 0, sizeof(statbuf));\r
+       }\r
+\r
+       if (size)\r
+           *size = statbuf.st_size;\r
+\r
+       if (mtime)\r
+           *mtime = statbuf.st_mtime;\r
+\r
+       if (atime)\r
+           *atime = statbuf.st_atime;\r
+    }\r
+\r
+    return ret;\r
+}\r
+\r
+int read_from_file(RFile *f, void *buffer, int length)\r
+{\r
+    return read(f->fd, buffer, length);\r
+}\r
+\r
+void close_rfile(RFile *f)\r
+{\r
+    close(f->fd);\r
+    sfree(f);\r
+}\r
+\r
+struct WFile {\r
+    int fd;\r
+    char *name;\r
+};\r
+\r
+WFile *open_new_file(char *name)\r
+{\r
+    int fd;\r
+    WFile *ret;\r
+\r
+    fd = open(name, O_CREAT | O_TRUNC | O_WRONLY, 0666);\r
+    if (fd < 0)\r
+       return NULL;\r
+\r
+    ret = snew(WFile);\r
+    ret->fd = fd;\r
+    ret->name = dupstr(name);\r
+\r
+    return ret;\r
+}\r
+\r
+int write_to_file(WFile *f, void *buffer, int length)\r
+{\r
+    char *p = (char *)buffer;\r
+    int so_far = 0;\r
+\r
+    /* Keep trying until we've really written as much as we can. */\r
+    while (length > 0) {\r
+       int ret = write(f->fd, p, length);\r
+\r
+       if (ret < 0)\r
+           return ret;\r
+\r
+       if (ret == 0)\r
+           break;\r
+\r
+       p += ret;\r
+       length -= ret;\r
+       so_far += ret;\r
+    }\r
+\r
+    return so_far;\r
+}\r
+\r
+void set_file_times(WFile *f, unsigned long mtime, unsigned long atime)\r
+{\r
+    struct utimbuf ut;\r
+\r
+    ut.actime = atime;\r
+    ut.modtime = mtime;\r
+\r
+    utime(f->name, &ut);\r
+}\r
+\r
+/* Closes and frees the WFile */\r
+void close_wfile(WFile *f)\r
+{\r
+    close(f->fd);\r
+    sfree(f->name);\r
+    sfree(f);\r
+}\r
+\r
+int file_type(char *name)\r
+{\r
+    struct stat statbuf;\r
+\r
+    if (stat(name, &statbuf) < 0) {\r
+       if (errno != ENOENT)\r
+           fprintf(stderr, "%s: stat: %s\n", name, strerror(errno));\r
+       return FILE_TYPE_NONEXISTENT;\r
+    }\r
+\r
+    if (S_ISREG(statbuf.st_mode))\r
+       return FILE_TYPE_FILE;\r
+\r
+    if (S_ISDIR(statbuf.st_mode))\r
+       return FILE_TYPE_DIRECTORY;\r
+\r
+    return FILE_TYPE_WEIRD;\r
+}\r
+\r
+struct DirHandle {\r
+    DIR *dir;\r
+};\r
+\r
+DirHandle *open_directory(char *name)\r
+{\r
+    DIR *dir;\r
+    DirHandle *ret;\r
+\r
+    dir = opendir(name);\r
+    if (!dir)\r
+       return NULL;\r
+\r
+    ret = snew(DirHandle);\r
+    ret->dir = dir;\r
+    return ret;\r
+}\r
+\r
+char *read_filename(DirHandle *dir)\r
+{\r
+    struct dirent *de;\r
+\r
+    do {\r
+       de = readdir(dir->dir);\r
+       if (de == NULL)\r
+           return NULL;\r
+    } while ((de->d_name[0] == '.' &&\r
+             (de->d_name[1] == '\0' ||\r
+              (de->d_name[1] == '.' && de->d_name[2] == '\0'))));\r
+\r
+    return dupstr(de->d_name);\r
+}\r
+\r
+void close_directory(DirHandle *dir)\r
+{\r
+    closedir(dir->dir);\r
+    sfree(dir);\r
+}\r
+\r
+int test_wildcard(char *name, int cmdline)\r
+{\r
+    /*\r
+     * On Unix, we currently don't support local wildcards at all.\r
+     * We will have to do so (FIXME) once PSFTP starts implementing\r
+     * mput, but until then we can assume `cmdline' is always set.\r
+     */\r
+    struct stat statbuf;\r
+\r
+    assert(cmdline);\r
+    if (stat(name, &statbuf) < 0)\r
+       return WCTYPE_NONEXISTENT;\r
+    else\r
+       return WCTYPE_FILENAME;\r
+}\r
+\r
+/*\r
+ * Actually return matching file names for a local wildcard. FIXME:\r
+ * we currently don't support this at all.\r
+ */\r
+struct WildcardMatcher {\r
+    int x;\r
+};\r
+WildcardMatcher *begin_wildcard_matching(char *name) { return NULL; }\r
+char *wildcard_get_filename(WildcardMatcher *dir) { return NULL; }\r
+void finish_wildcard_matching(WildcardMatcher *dir) {}\r
+\r
+int create_directory(char *name)\r
+{\r
+    return mkdir(name, 0777) == 0;\r
+}\r
+\r
+char *dir_file_cat(char *dir, char *file)\r
+{\r
+    return dupcat(dir, "/", file, NULL);\r
+}\r
+\r
 /*\r
  * Wait for some network data and process it.\r
  */\r