Render timing.c robust in the face of strangeness. The strangenesses
[u/mdw/putty] / unix / uxsftp.c
index 0862bc4..f5fc12e 100644 (file)
@@ -341,6 +341,17 @@ void finish_wildcard_matching(WildcardMatcher *dir) {
     sfree(dir);
 }
 
+int vet_filename(char *name)
+{
+    if (strchr(name, '/'))
+       return FALSE;
+
+    if (name[0] == '.' && (!name[1] || (name[1] == '.' && !name[2])))
+       return FALSE;
+
+    return TRUE;
+}
+
 int create_directory(char *name)
 {
     return mkdir(name, 0777) == 0;
@@ -355,7 +366,7 @@ char *dir_file_cat(char *dir, char *file)
  * Do a select() between all currently active network fds and
  * optionally stdin.
  */
-static int ssh_sftp_do_select(int include_stdin)
+static int ssh_sftp_do_select(int include_stdin, int no_fds_ok)
 {
     fd_set rset, wset, xset;
     int i, fdcount, fdsize, *fdlist;
@@ -372,7 +383,7 @@ static int ssh_sftp_do_select(int include_stdin)
        for (fd = first_fd(&fdstate, &rwx); fd >= 0;
             fd = next_fd(&fdstate, &rwx)) i++;
 
-       if (i < 1)
+       if (i < 1 && !no_fds_ok)
            return -1;                 /* doom */
 
        /* Expand the fdlist buffer if necessary. */
@@ -422,8 +433,27 @@ static int ssh_sftp_do_select(int include_stdin)
            ret = select(maxfd, &rset, &wset, &xset, ptv);
            if (ret == 0)
                now = next;
-           else
-               now = GETTICKCOUNT();
+           else {
+               long newnow = GETTICKCOUNT();
+               /*
+                * Check to see whether the system clock has
+                * changed massively during the select.
+                */
+               if (newnow - now < 0 || newnow - now > next - now) {
+                   /*
+                    * If so, look at the elapsed time in the
+                    * select and use it to compute a new
+                    * tickcount_offset.
+                    */
+                   long othernow = now + tv.tv_sec * 1000 + tv.tv_usec / 1000;
+                   /* So we'd like GETTICKCOUNT to have returned othernow,
+                    * but instead it return newnow. Hence ... */
+                   tickcount_offset += othernow - newnow;
+                   now = othernow;
+               } else {
+                   now = newnow;
+               }
+           }
        } while (ret < 0 && errno != EINTR);
     } while (ret == 0);
 
@@ -457,13 +487,13 @@ static int ssh_sftp_do_select(int include_stdin)
  */
 int ssh_sftp_loop_iteration(void)
 {
-    return ssh_sftp_do_select(FALSE);
+    return ssh_sftp_do_select(FALSE, FALSE);
 }
 
 /*
  * Read a PSFTP command line from stdin.
  */
-char *ssh_sftp_get_cmdline(char *prompt)
+char *ssh_sftp_get_cmdline(char *prompt, int no_fds_ok)
 {
     char *buf;
     int buflen, bufsize, ret;
@@ -475,7 +505,7 @@ char *ssh_sftp_get_cmdline(char *prompt)
     buflen = bufsize = 0;
 
     while (1) {
-       ret = ssh_sftp_do_select(TRUE);
+       ret = ssh_sftp_do_select(TRUE, no_fds_ok);
        if (ret < 0) {
            printf("connection died\n");
            return NULL;               /* woop woop */