diff options
| author | Klaatu <[email protected]> | 2015-05-17 15:33:21 +1200 |
|---|---|---|
| committer | Klaatu <[email protected]> | 2015-05-17 15:33:21 +1200 |
| commit | b0de699679e8f1e39af847ed172d1ba605b4370c (patch) | |
| tree | 01dac00471d61f727394e508c613b29cff0ceae5 /install-bin.c | |
bulk upload of source
Diffstat (limited to 'install-bin.c')
| -rw-r--r-- | install-bin.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/install-bin.c b/install-bin.c new file mode 100644 index 0000000..fc18b07 --- /dev/null +++ b/install-bin.c @@ -0,0 +1,129 @@ +#include <unistd.h> +#include <fcntl.h> +#include <alloca.h> +#include <stdio.h> +#include <sys/stat.h> +#include "ninitfeatures.h" +#include "error_table.h" +#include "uid.h" + +#define U "unable to " + +static char *e() { return error_string(table, errno); } +static void nomem() { die(111,"out of memory"); } +static void ex(char *s0, char *s1) { die(111,U,s0,": ",s1,": ",e()); } + +static void doit(char *to, char *line) { + char *x, **arg, *target, *tmp; + char *type, *mid, *name, *alias; + unsigned long uid, gid, mode; + int in, out, len; + static char *uid_global, *gid_global, *mode_global, *mid_global, V; + + len=splitmem(0,line,':'); if (len <7) return; + arg=alloca((len+1) * sizeof(char*)); if (arg==0) nomem(); + splitmem(arg,line,':'); + + type = arg[0]; + x=arg[1]; if (!*x==0 && uid_global) x=uid_global; + if (*x) uid=atoulong(x); else uid = -1; + + x=arg[2]; if (!*x==0 && gid_global) x=gid_global; + if (*x) gid=atoulong(x); else gid = -1; + + x=arg[3]; if (!*x && mode_global) x=mode_global; scan_8ulong(x,&mode); + mid = arg[4]; if (!*mid && mid_global) mid=mid_global; + name= arg[5]; + x=arg[6]; alias = (*x) ? x : name; + + len = str_len(to) + str_len(mid) + str_len(name); + x=alloca(2*len + 32); if (x==0) nomem(); + target = x; + x += str_copy(x,to); + x += str_copy(x,mid); + x += str_copy(x,name); + while (target[0]=='/' && target[1]=='/') target++; + tmp = (*type=='x') ? x+2 : 0; + + switch(*type) { + case 'p': + if (SYS_mknod(target,S_IFIFO|0600,0) == -1) + if (errno != EEXIST) ex("mknod",target); + if (V) msg("pipe:\t", target); + break; + + case 'd': + if (mkdir(target,0700) == -1) + if (errno != EEXIST) ex("mkdir",target); + if (V) msg("mkdir:\t", target); + break; + + case 'c': + case 'x': + if ((in=open(alias, O_RDONLY)) <0) ex("open",alias); + + if (*type == 'c') out = open(target, O_WRONLY|O_CREAT|O_TRUNC, 0600); + else out = open_tmpfd(target, tmp, 0600); + if (out <0) ex("open",target); + + x=alloca(8192); if (x==0) nomem(); + for (;;) { + len=read(in,x,8192); + if (len==0) break; + else if (len==-1) ex("read",alias); + else if (len != write(out,x,len)) { die(111,U,"write",target); } + } + + close(in); + if (fsync(out)) ex("fsync",target); + if (close(out)) ex("close",target); + if (tmp && rename(tmp,target)) + { die(111,U,"rename: ", tmp, " -> ", target, ": ", e()); } + if (V) msg(alias, "\t-> ", target); + break; + + case 'g': + x=arg[1]; uid_global = (*x) ? x : 0; + x=arg[2]; gid_global = (*x) ? x : 0; + x=arg[3]; mode_global = (*x) ? x : 0; + x=arg[4]; mid_global = (*x) ? x : 0; + return; + + case 'v': + if (arg[1][0]) V=1; + else V=0; + + default: + return; + } + if (SYS_chown(target,uid,gid) <0) ex("chown",target); + if (chmod(target,mode) <0) ex("chmod",target); +} + +int main(int argc, char **argv) { + char *to, **arg, *s=0; + if (argc<2) { die(100,"usage: install-bin Dir < File\n " + "install-bin Dir c:::755:mid:file:: x:::755:mid:name:source: ...\n" + "File contains lines:\ntype:uid:gid:mode:middle:target:source:\n" + "type is one of the letters: vpdcxg\n" + "type g sets global uid:gid:mode:middle\n"); } + + to = argv[1]; + errmsg_iam("install-bin"); + umask(077); + + if (argc == 2) { + int len; + if (GLOBAL_READ(0,s, len,100000)) ex("read","stdin"); + close(0); + s[len]=0; + + len = splitmem(0,s,'\n'); + arg = alloca((len+1) * sizeof(char*)); if (arg==0) nomem(); + splitmem(arg,s,'\n'); + } else + arg = argv+2; + + for (; (s=*arg); ++arg) doit(to, s); + return 0; +} |
