diff options
-rw-r--r-- | include/libc.h | 4 | ||||
-rw-r--r-- | src/cmd/dist/windows.c | 2 | ||||
-rw-r--r-- | src/lib9/run_plan9.c | 38 | ||||
-rw-r--r-- | src/lib9/run_unix.c | 43 | ||||
-rw-r--r-- | src/lib9/run_windows.c | 83 | ||||
-rw-r--r-- | src/lib9/tempdir_plan9.c | 54 | ||||
-rw-r--r-- | src/lib9/tempdir_unix.c | 52 | ||||
-rw-r--r-- | src/lib9/tempdir_windows.c | 112 | ||||
-rw-r--r-- | src/lib9/win.h | 8 |
9 files changed, 396 insertions, 0 deletions
diff --git a/include/libc.h b/include/libc.h index 1440209e3..5fd56b8bf 100644 --- a/include/libc.h +++ b/include/libc.h @@ -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*); diff --git a/src/cmd/dist/windows.c b/src/cmd/dist/windows.c index 7bcda4508..ba23a7ae8 100644 --- a/src/cmd/dist/windows.c +++ b/src/cmd/dist/windows.c @@ -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 index 000000000..7feb48d98 --- /dev/null +++ b/src/lib9/run_plan9.c @@ -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 index 000000000..1b4c6de1b --- /dev/null +++ b/src/lib9/run_unix.c @@ -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 index 000000000..87875b42d --- /dev/null +++ b/src/lib9/run_windows.c @@ -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 index 000000000..9c14d6dd0 --- /dev/null +++ b/src/lib9/tempdir_plan9.c @@ -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 index 000000000..7b7e58b4d --- /dev/null +++ b/src/lib9/tempdir_unix.c @@ -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 index 000000000..8e9322dc8 --- /dev/null +++ b/src/lib9/tempdir_windows.c @@ -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 index 000000000..d9df319af --- /dev/null +++ b/src/lib9/win.h @@ -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*); |