1
0
mirror of https://github.com/golang/go synced 2024-11-25 09:17:57 -07:00

lib9: add mktempdir, removeall, runprog

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/7523043
This commit is contained in:
Russ Cox 2013-03-06 15:48:28 -05:00
parent c76379954f
commit 7610a0552f
9 changed files with 396 additions and 0 deletions

View 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*);

View 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;

38
src/lib9/run_plan9.c Normal file
View File

@ -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;
}

43
src/lib9/run_unix.c Normal file
View File

@ -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;
}

83
src/lib9/run_windows.c Normal file
View File

@ -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;
}

54
src/lib9/tempdir_plan9.c Normal file
View File

@ -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);
}

52
src/lib9/tempdir_unix.c Normal file
View File

@ -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);
}

112
src/lib9/tempdir_windows.c Normal file
View File

@ -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);
}

8
src/lib9/win.h Normal file
View File

@ -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*);