... and there's a Unix port of PSCP. Ooh.
[u/mdw/putty] / unix / uxsftp.c
index e9c9f6e..69d4c45 100644 (file)
@@ -1,12 +1,16 @@
 /*\r
- * uxsftp.c: the Unix-specific parts of PSFTP.\r
+ * uxsftp.c: the Unix-specific parts of PSFTP and PSCP.\r
  */\r
 \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 <pwd.h>\r
+#include <assert.h>\r
 \r
 #include "putty.h"\r
 #include "psftp.h"\r
@@ -34,45 +38,6 @@ void platform_get_x11_auth(char *display, int *protocol,
  */\r
 char *platform_default_s(const char *name)\r
 {\r
-    if (!strcmp(name, "UserName")) {\r
-       /*\r
-        * Remote login username will default to the local username.\r
-        */\r
-       struct passwd *p;\r
-       uid_t uid = getuid();\r
-       char *user, *ret = NULL;\r
-\r
-       /*\r
-        * First, find who we think we are using getlogin. If this\r
-        * agrees with our uid, we'll go along with it. This should\r
-        * allow sharing of uids between several login names whilst\r
-        * coping correctly with people who have su'ed.\r
-        */\r
-       user = getlogin();\r
-       setpwent();\r
-       if (user)\r
-           p = getpwnam(user);\r
-       else\r
-           p = NULL;\r
-       if (p && p->pw_uid == uid) {\r
-           /*\r
-            * The result of getlogin() really does correspond to\r
-            * our uid. Fine.\r
-            */\r
-           ret = user;\r
-       } else {\r
-           /*\r
-            * If that didn't work, for whatever reason, we'll do\r
-            * the simpler version: look up our uid in the password\r
-            * file and map it straight to a name.\r
-            */\r
-           p = getpwuid(uid);\r
-           ret = p->pw_name;\r
-       }\r
-       endpwent();\r
-\r
-       return ret;\r
-    }\r
     return NULL;\r
 }\r
 \r
@@ -99,6 +64,18 @@ Filename platform_default_filename(const char *name)
 }\r
 \r
 /*\r
+ * Stubs for the GUI feedback mechanism in Windows PSCP.\r
+ */\r
+void gui_update_stats(char *name, unsigned long size,\r
+                     int percentage, unsigned long elapsed,\r
+                     unsigned long done, unsigned long eta,\r
+                     unsigned long ratebs) {}\r
+void gui_send_errcount(int list, int errs) {}\r
+void gui_send_char(int is_stderr, int c) {}\r
+void gui_enable(char *arg) {}\r
+\r
+\r
+/*\r
  * Set local current directory. Returns NULL on success, or else an\r
  * error message which must be freed after printing.\r
  */\r
@@ -137,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