command/commit

Added load of (local) files

authorJan Wielemaker
Fri Mar 11 11:10:03 2011 +0100
committerJan Wielemaker
Fri Mar 11 11:10:03 2011 +0100
commit43abee76d1ac01a8d9296906a8972985e8330509
tree464754555ea768d7ab3ee94d9a7db89d2549dcb3
parent7b144a58042bf5310a67c5c63a240028f8c12496
Diff style: patch stat
diff --git a/api/command.pl b/api/command.pl
index cdd44c8..905f0d5 100644
--- a/api/command.pl
+++ b/api/command.pl
@@ -44,7 +44,7 @@
 http:location(cmd, root(cmd), []).
 
 :- http_handler(cmd(ping), ping, []).
-:- http_handler(cmd(load), load, []).
+:- http_handler(cmd(load), load, [time_limit(infinite)]).
 
 %%	ping(+Request)
 %
diff --git a/client/cp-client.c b/client/cp-client.c
index 1816d41..add0ec1 100644
--- a/client/cp-client.c
+++ b/client/cp-client.c
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
+#include <ctype.h>
 
 char *program = NULL;
 char *prefix  = "";
@@ -40,6 +41,10 @@ int   debug   = 0;
 
 #define FALSE 0
 #define TRUE 1
+#define EOS 0
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
 
 static int
 isoption(const char *arg, const char *name, const char **val)
@@ -69,6 +74,151 @@ file_base_name(const char *f)
 }
 
 
+#ifdef O_HASDRIVES
+
+#define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\')
+
+static int
+IsAbsolutePath(const char *p)				/* /d:/ */
+{ if ( p[0] == '/' && p[2] == ':' && isalpha(p[1]) &&
+       (p[3] == '/' || p[3] == '\0') )
+    succeed;
+
+  if ( p[1] == ':' && isalpha(p[0]) &&			/* d:/ or d:\ */
+       (IS_DIR_SEPARATOR(p[2]) || p[2] == '\0') )
+    succeed;
+
+#ifdef O_HASSHARES
+  if ( (p[0] == '/' && p[1] == '/') ||	/* //host/share */
+       (p[0] == '\\' && p[1] == '\\') )	/* \\host\share */
+    succeed;
+#endif
+
+  fail;
+}
+
+#else
+
+int
+IsAbsolutePath(const char *p)				/* /d:/ */
+{ return p[0] == '/';
+}
+
+#endif
+
+
+static char *
+canoniseFileName(char *path)
+{ char *out = path, *in = path, *start = path;
+  char *osave[100];
+  int  osavep = 0;
+
+#ifdef O_HASDRIVES			/* C: */
+  if ( in[1] == ':' && isalpha(in[0]) )
+  { in += 2;
+
+    out = start = in;
+  }
+#endif
+#ifdef O_HASSHARES			/* //host/ */
+  if ( in[0] == '/' && in[1] == '/' && isAlpha(in[2]) )
+  { char *s;
+
+    for(s = in+3; *s && (isalnum(*s) || *s == '.'); s++)
+      ;
+    if ( *s == '/' )
+    { in = out = s+1;
+      start = in-1;
+    }
+  }
+#endif
+
+  while( in[0] == '/' && in[1] == '.' && in[2] == '.' && in[3] == '/' )
+    in += 3;
+  while( in[0] == '.' && in[1] == '/' )
+    in += 2;
+  if ( in[0] == '/' )
+    *out++ = '/';
+  osave[osavep++] = out;
+
+  while(*in)
+  { if (*in == '/')
+    {
+    again:
+      if ( *in )
+      { while( in[1] == '/' )		/* delete multiple / */
+	  in++;
+	if ( in[1] == '.' )
+	{ if ( in[2] == '/' )		/* delete /./ */
+	  { in += 2;
+	    goto again;
+	  }
+	  if ( in[2] == EOS )		/* delete trailing /. */
+	  { *out = EOS;
+	    return path;
+	  }
+	  if ( in[2] == '.' && (in[3] == '/' || in[3] == EOS) )
+	  { if ( osavep > 0 )		/* delete /foo/../ */
+	    { out = osave[--osavep];
+	      in += 3;
+	      if ( in[0] == EOS && out > start+1 )
+	      { out[-1] = EOS;		/* delete trailing / */
+		return path;
+	      }
+	      goto again;
+	    } else if (	start[0] == '/' && out == start+1 )
+	    { in += 3;
+	      goto again;
+	    }
+	  }
+	}
+      }
+      if ( *in )
+	in++;
+      if ( out > path && out[-1] != '/' )
+	*out++ = '/';
+      osave[osavep++] = out;
+    } else
+      *out++ = *in++;
+  }
+  *out++ = *in++;
+
+  return path;
+}
+
+
+char *
+to_url(const char *data)
+{ if ( strncmp(data, "http://", 7) == 0 ||
+       strncmp(data, "https://", 8) == 0 )
+    return strdup(data);
+
+  if ( IsAbsolutePath(data) )
+  { char *url = malloc(strlen(data)+strlen("file://")+1);
+
+    strcpy(url, "file://");
+    strcpy(url+strlen("file://"), data);
+
+    return strdup(url);
+  } else
+  { char url[MAXPATHLEN];
+    char *o;
+
+    if ( !getcwd(url, sizeof(url)) )
+    { perror("getcwd");
+      exit(1);
+    }
+
+    o = url+strlen(url);
+    if ( !(o>url && o[-1] == '/') )
+      *o++ = '/';
+    strcpy(o, data);
+
+    return to_url(canoniseFileName(url));
+  }
+}
+
+
 static int
 usage(int code)
 { fprintf(stderr, "Usage: %s [option ...] command [arg ...]\n\n", program);
@@ -179,12 +329,14 @@ ping()
 static int
 load_one(const char *data)
 { CURLcode rc;
-  const char *url = cmd_url("/cmd/load", A_STRING, "url", data, A_END);
+  char *dataurl = to_url(data);
+  const char *url = cmd_url("/cmd/load", A_STRING, "url", dataurl, A_END);
 
   if ( debug > 0 )
     fprintf(stderr, "URL=%s\n", url);
   curl_easy_setopt(curl, CURLOPT_URL, url);
   rc = curl_easy_perform(curl);
+  free(dataurl);
 
   return curl_status(rc);
 }