]> Cypherpunks repositories - gostls13.git/commitdiff
lib9: add mktempdir, removeall, runprog
authorRuss Cox <rsc@golang.org>
Wed, 6 Mar 2013 20:48:28 +0000 (15:48 -0500)
committerRuss Cox <rsc@golang.org>
Wed, 6 Mar 2013 20:48:28 +0000 (15:48 -0500)
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/7523043

include/libc.h
src/cmd/dist/windows.c
src/lib9/run_plan9.c [new file with mode: 0644]
src/lib9/run_unix.c [new file with mode: 0644]
src/lib9/run_windows.c [new file with mode: 0644]
src/lib9/tempdir_plan9.c [new file with mode: 0644]
src/lib9/tempdir_unix.c [new file with mode: 0644]
src/lib9/tempdir_windows.c [new file with mode: 0644]
src/lib9/win.h [new file with mode: 0644]

index 1440209e30a9585f61b56435db0c2cacf1906914..5fd56b8bfe7da4d3685ceb5a5f155d7eae89cdcf 100644 (file)
@@ -292,6 +292,10 @@ extern     char*   getgoversion(void);
 extern char*   getgoarm(void);
 extern char*   getgo386(void);
 
+extern char*   mktempdir(void);
+extern void    removeall(char*);
+extern int     runcmd(char**);
+
 extern void    flagcount(char*, char*, int*);
 extern void    flagint32(char*, char*, int32*);
 extern void    flagint64(char*, char*, int64*);
index 7bcda4508f414eeabbab16bf485d1ccb3b505706..ba23a7ae82814625a11d0321a9fc8024c656963c 100644 (file)
@@ -271,6 +271,8 @@ static void bgwait1(void);
 static void
 genrun(Buf *b, char *dir, int mode, Vec *argv, int wait)
 {
+       // Another copy of this logic is in ../../lib9/run_windows.c.
+       // If there's a bug here, fix the logic there too.
        int i, j, nslash;
        Buf cmd;
        char *q;
diff --git a/src/lib9/run_plan9.c b/src/lib9/run_plan9.c
new file mode 100644 (file)
index 0000000..7feb48d
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <u.h>
+#include <libc.h>
+
+int
+runcmd(char **argv)
+{
+       int pid;
+       Waitmsg *w;
+       
+       switch(pid = fork()) {
+       case -1:
+               return -1;
+       case 0:
+               execvp(argv[0], argv);
+               fprint(2, "exec %s: %r", argv[0]);
+               _exit(1);
+       }
+       
+       w = wait();
+       if(w == nil)
+               return -1;
+       if(w->pid != pid) {
+               werrstr("unexpected pid in wait");
+               free(w);
+               return -1;
+       }
+       if(w->msg[0]) {
+               werrstr("unsuccessful exit status: %s", w->msg);
+               free(w);
+               return -1;
+       }
+       free(w);
+       return 0;
+}
diff --git a/src/lib9/run_unix.c b/src/lib9/run_unix.c
new file mode 100644 (file)
index 0000000..1b4c6de
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux netbsd openbsd
+
+#include <u.h>
+#include <errno.h>
+#include <sys/wait.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+
+int
+runcmd(char **argv)
+{
+       int pid, pid1, status;
+       
+       switch(pid = fork()) {
+       case -1:
+               return -1;
+       case 0:
+               execvp(argv[0], argv);
+               fprint(2, "exec %s: %r", argv[0]);
+               _exit(1);
+       }
+       
+       while((pid1 = wait(&status)) < 0) {
+               if(errno != EINTR) {
+                       werrstr("waitpid: %r");
+                       return -1;
+               }
+       }
+       if(pid1 != pid) {
+               werrstr("unexpected pid in wait");
+               return -1;
+       }
+       if(!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+               werrstr("unsuccessful exit status %#x", status);
+               return -1;
+       }
+       return 0;
+}
+
diff --git a/src/lib9/run_windows.c b/src/lib9/run_windows.c
new file mode 100644 (file)
index 0000000..87875b4
--- /dev/null
@@ -0,0 +1,83 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <u.h>
+#include <windows.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+#include "win.h"
+
+int
+runcmd(char **argv)
+{
+       // Mostly copied from ../cmd/dist/windows.c.
+       // If there's a bug here, fix the logic there too.
+       int i, j, nslash;
+       Fmt fmt;
+       char *q;
+       WinRune *r;
+       STARTUPINFOW si;
+       PROCESS_INFORMATION pi;
+       DWORD code;
+
+       fmtstrinit(&fmt);
+       for(i=0; argv[i]; i++) {
+               if(i > 0)
+                       fmtprint(&fmt, " ");
+               q = argv[i];
+               if(strstr(q, " ") || strstr(q, "\t") || strstr(q, "\"") || strstr(q, "\\\\") || (strlen(q) > 0 && q[strlen(q)-1] == '\\')) {
+                       fmtprint(&fmt, "\"");
+                       nslash = 0;
+                       for(; *q; q++) {
+                               if(*q == '\\') {
+                                       nslash++;
+                                       continue;
+                               }
+                               if(*q == '"') {
+                                       for(j=0; j<2*nslash+1; j++)
+                                               fmtprint(&fmt, "\\");
+                                       nslash = 0;
+                               }
+                               for(j=0; j<nslash; j++)
+                                       fmtprint(&fmt, "\\");
+                               nslash = 0;
+                               fmtprint(&fmt, "\"");
+                       }
+                       for(j=0; j<2*nslash; j++)
+                               fmtprint(&fmt, "\\");
+                       fmtprint(&fmt, "\"");
+               } else {
+                       fmtprint(&fmt, "%s", q);
+               }
+       }
+       
+       q = fmtstrflush(&fmt);
+       r = torune(q);
+       free(q);
+
+       memset(&si, 0, sizeof si);
+       si.cb = sizeof si;
+       si.dwFlags = STARTF_USESTDHANDLES;
+       si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+       si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+
+       if(!CreateProcessW(nil, r, nil, nil, TRUE, 0, nil, nil, &si, &pi)) {
+               free(r);
+               return -1;
+       }
+
+       free(r);
+       if(WaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE) != 0)
+               return -1;
+       i = GetExitCodeProcess(pi.hProcess, &code);
+       CloseHandle(pi.hProcess);
+       CloseHandle(pi.hThread);
+       if(!i)
+               return -1;
+       if(code != 0) {
+               werrstr("unsuccessful exit status: %d", (int)code);
+               return -1;
+       }
+       return 0;
+}
diff --git a/src/lib9/tempdir_plan9.c b/src/lib9/tempdir_plan9.c
new file mode 100644 (file)
index 0000000..9c14d6d
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <u.h>
+#include <libc.h>
+
+char*
+mktempdir(void)
+{
+       char *p;
+       int i;
+       
+       p = smprint("/tmp/go-link-XXXXXX");
+       for(i=0; i<1000; i++) {
+               sprint(p, "/tmp/go-link-%06x", nrand((1<<24)-1));
+               fd = create(p, OREAD|OEXCL, 0700|DMDIR);
+               if(fd >= 0) {
+                       close(fd);
+                       return p;
+               }
+       }
+       free(p);
+       return nil;
+}
+
+void
+removeall(char *p)
+{
+       int fd, n;
+       Dir *d;
+       char *q;
+       
+       if(remove(p) >= 0)
+               return;
+       if((d = dirstat(p)) == nil)
+               return;
+       if(!(d->mode & DMDIR)) {
+               free(d);
+               return;
+       }
+       free(d);
+       
+       if((fd = open(p, OREAD)) < 0)
+               return;
+       n = dirreadall(fd, &d);
+       close(fd);
+       for(i=0; i<n; i++) {
+               q = smprint("%s/%s", p, d[i].name);
+               removeall(q);
+               free(q);
+       }
+       free(d);
+}
diff --git a/src/lib9/tempdir_unix.c b/src/lib9/tempdir_unix.c
new file mode 100644 (file)
index 0000000..7b7e58b
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux netbsd openbsd
+
+#include <u.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+
+char*
+mktempdir(void)
+{
+       char *tmp, *p;
+       
+       tmp = getenv("TMPDIR");
+       if(tmp == nil)
+               tmp = "/var/tmp";
+       p = smprint("%s/go-link-XXXXXX", tmp);
+       if(mkdtemp(p) == nil)
+               return nil;
+       return p;
+}
+
+void
+removeall(char *p)
+{
+       DIR *d;
+       struct dirent *dp;
+       char *q;
+       struct stat st;
+
+       if(stat(p, &st) < 0)
+               return;
+       if(!S_ISDIR(st.st_mode)) {
+               unlink(p);
+               return;
+       }
+
+       d = opendir(p);
+       while((dp = readdir(d)) != nil) {
+               if(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
+                       continue;
+               q = smprint("%s/%s", p, dp->d_name);
+               removeall(q);
+               free(q);
+       }
+       closedir(d);
+       rmdir(p);
+}
diff --git a/src/lib9/tempdir_windows.c b/src/lib9/tempdir_windows.c
new file mode 100644 (file)
index 0000000..8e9322d
--- /dev/null
@@ -0,0 +1,112 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <u.h>
+#include <windows.h>
+#include <libc.h>
+#include "win.h"
+
+char*
+toutf(WinRune *r)
+{
+       Rune *r1;
+       int i, n;
+       char *p;
+       
+       n = 0;
+       while(r[n] != '\0')
+               n++;
+       n++;
+       r1 = malloc(n*sizeof r1[0]);
+       for(i=0; i<n; i++)
+               r1[i] = r[i];
+       p = smprint("%S", r1);
+       free(r1);
+       return p;
+}
+
+WinRune*
+torune(char *p)
+{
+       int i, n;
+       Rune *r1;
+       WinRune *r;
+       
+       r1 = runesmprint("%s", p);
+       n = 0;
+       while(r1[n] != '\0')
+               n++;
+       n++;
+       r = malloc(n*sizeof r[0]);
+       for(i=0; i<n; i++)
+               r[i] = r1[i];
+       free(r1);
+       return r;
+}
+
+char*
+mktempdir(void)
+{
+       WinRune buf[1024];
+       WinRune tmp[MAX_PATH];
+       WinRune golink[] = {'g', 'o', 'l', 'i', 'n', 'k', '\0'};
+       int n;
+       
+       n = GetTempPathW(nelem(buf), buf);
+       if(n <= 0)
+               return nil;
+       buf[n] = '\0';
+       
+       if(GetTempFileNameW(buf, golink, 0, tmp) == 0)
+               return nil;
+       DeleteFileW(tmp);
+       if(!CreateDirectoryW(tmp, nil))
+               return nil;
+       
+       return toutf(tmp);
+}
+
+void
+removeall(char *p)
+{
+       WinRune *r, *r1;
+       DWORD attr;
+       char *q, *elem;
+       HANDLE h;
+       WIN32_FIND_DATAW data;
+       
+       r = torune(p);
+       attr = GetFileAttributesW(r);
+       if(attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY)) {
+               DeleteFileW(r);
+               free(r);
+               return;
+       }
+
+       q = smprint("%s\\*", p);
+       r1 = torune(q);
+       free(q);
+       h = FindFirstFileW(r1, &data);
+       if(h == INVALID_HANDLE_VALUE)
+               goto done;
+       do{
+               q = toutf(data.cFileName);
+               elem = strrchr(q, '\\');
+               if(elem != nil) {
+                       elem++;
+                       if(strcmp(elem, ".") == 0 || strcmp(elem, "..") == 0) {
+                               free(q);
+                               continue;
+                       }
+               }
+               removeall(q);
+               free(q);                
+       }while(FindNextFileW(h, &data));
+       FindClose(h);
+
+done:
+       free(r1);
+       RemoveDirectoryW(r);
+       free(r);
+}
diff --git a/src/lib9/win.h b/src/lib9/win.h
new file mode 100644 (file)
index 0000000..d9df319
--- /dev/null
@@ -0,0 +1,8 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+typedef unsigned short WinRune;
+
+WinRune* torune(char*);
+char *toutf(WinRune*);