\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
}\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
h = FindFirstFile(findfile, &fdat);
if (h == INVALID_HANDLE_VALUE)
return NULL;
+ sfree(findfile);
ret = snew(DirHandle);
ret->h = h;
char *read_filename(DirHandle *dir)
{
- if (!dir->name) {
+ while (!dir->name) {
WIN32_FIND_DATA fdat;
int ok = FindNextFile(dir->h, &fdat);
- if (ok)
+ if (!ok)
+ return NULL;
+
+ if (fdat.cFileName[0] == '.' &&
+ (fdat.cFileName[1] == '\0' ||
+ (fdat.cFileName[1] == '.' && fdat.cFileName[2] == '\0')))
+ dir->name = NULL;
+ else
dir->name = dupstr(fdat.cFileName);
}
return CreateDirectory(name, NULL) != 0;
}
+char *dir_file_cat(char *dir, char *file)
+{
+ return dupcat(dir, "\\", file, NULL);
+}
+
/* ----------------------------------------------------------------------
* Platform-specific network handling.
*/