diff options
Diffstat (limited to 'src/lib9')
-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 | 110 | ||||
-rw-r--r-- | src/lib9/win.h | 8 |
7 files changed, 388 insertions, 0 deletions
diff --git a/src/lib9/run_plan9.c b/src/lib9/run_plan9.c new file mode 100644 index 000000000..2b043cc2c --- /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: + exec(argv[0], argv); + fprint(2, "exec %s: %r", argv[0]); + exits("exec"); + } + + 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..092d00d16 --- /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 fd, 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, i; + 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..1a530059a --- /dev/null +++ b/src/lib9/tempdir_windows.c @@ -0,0 +1,110 @@ +// 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 rr; + WinRune *r; + + n = utflen(p); + r = malloc((n+1)*sizeof r[0]); + for(i=0; i<n; i++) { + p += chartorune(&rr, p); + r[i] = rr; + } + r[n] = '\0'; + 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*); |