ape: simplify mkfile (thanks amavect)
ape cp, mv, and cc build with ?c, not pcc ape cp and mv just ignore one or two extra flags, instead of providing posix compatibility it's better to fail then do nothing remove cp.c and mv.c move cc.c to /sys/src/ape/9src so it doesn't need its own mkfile rule
This commit is contained in:
parent
61b1134df9
commit
407cf4ac6e
5 changed files with 1 additions and 450 deletions
|
@ -4,6 +4,7 @@
|
|||
TARG=\
|
||||
stty\
|
||||
tar\
|
||||
cc\
|
||||
|
||||
BIN=/$objtype/bin/ape
|
||||
</sys/src/cmd/mkmany
|
||||
|
|
|
@ -1,179 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
|
||||
#define DEFB (8*1024)
|
||||
|
||||
int failed;
|
||||
int gflag;
|
||||
int uflag;
|
||||
int xflag;
|
||||
void copy(char *from, char *to, int todir);
|
||||
int copy1(int fdf, int fdt, char *from, char *to);
|
||||
|
||||
void
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
Dir *dirb;
|
||||
int todir, i;
|
||||
|
||||
ARGBEGIN {
|
||||
case 'g':
|
||||
gflag++;
|
||||
break;
|
||||
case 'u':
|
||||
uflag++;
|
||||
gflag++;
|
||||
break;
|
||||
case 'x':
|
||||
xflag++;
|
||||
break;
|
||||
case 'p':
|
||||
break;
|
||||
default:
|
||||
goto usage;
|
||||
} ARGEND
|
||||
|
||||
todir=0;
|
||||
if(argc < 2)
|
||||
goto usage;
|
||||
dirb = dirstat(argv[argc-1]);
|
||||
if(dirb!=nil && (dirb->mode&DMDIR))
|
||||
todir=1;
|
||||
if(argc>2 && !todir){
|
||||
fprint(2, "cp: %s not a directory\n", argv[argc-1]);
|
||||
exits("bad usage");
|
||||
}
|
||||
for(i=0; i<argc-1; i++)
|
||||
copy(argv[i], argv[argc-1], todir);
|
||||
if(failed)
|
||||
exits("errors");
|
||||
exits(0);
|
||||
|
||||
usage:
|
||||
fprint(2, "usage:\tcp [-gux] fromfile tofile\n");
|
||||
fprint(2, "\tcp [-x] fromfile ... todir\n");
|
||||
exits("usage");
|
||||
}
|
||||
|
||||
int
|
||||
samefile(Dir *a, char *an, char *bn)
|
||||
{
|
||||
Dir *b;
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
b=dirstat(bn);
|
||||
if(b != nil)
|
||||
if(b->qid.type==a->qid.type)
|
||||
if(b->qid.path==a->qid.path)
|
||||
if(b->qid.vers==a->qid.vers)
|
||||
if(b->dev==a->dev)
|
||||
if(b->type==a->type){
|
||||
fprint(2, "cp: %s and %s are the same file\n", an, bn);
|
||||
ret = 1;
|
||||
}
|
||||
free(b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
copy(char *from, char *to, int todir)
|
||||
{
|
||||
Dir *dirb, dirt;
|
||||
char name[256];
|
||||
int fdf, fdt, mode;
|
||||
|
||||
if(todir){
|
||||
char *s, *elem;
|
||||
elem=s=from;
|
||||
while(*s++)
|
||||
if(s[-1]=='/')
|
||||
elem=s;
|
||||
sprint(name, "%s/%s", to, elem);
|
||||
to=name;
|
||||
}
|
||||
|
||||
if((dirb=dirstat(from))==nil){
|
||||
fprint(2,"cp: can't stat %s: %r\n", from);
|
||||
failed = 1;
|
||||
return;
|
||||
}
|
||||
mode = dirb->mode;
|
||||
if(mode&DMDIR){
|
||||
fprint(2, "cp: %s is a directory\n", from);
|
||||
free(dirb);
|
||||
failed = 1;
|
||||
return;
|
||||
}
|
||||
if(samefile(dirb, from, to)){
|
||||
free(dirb);
|
||||
failed = 1;
|
||||
return;
|
||||
}
|
||||
mode &= 0777;
|
||||
fdf=open(from, OREAD);
|
||||
if(fdf<0){
|
||||
fprint(2, "cp: can't open %s: %r\n", from);
|
||||
free(dirb);
|
||||
failed = 1;
|
||||
return;
|
||||
}
|
||||
fdt=create(to, OWRITE, mode);
|
||||
if(fdt<0){
|
||||
fprint(2, "cp: can't create %s: %r\n", to);
|
||||
close(fdf);
|
||||
free(dirb);
|
||||
failed = 1;
|
||||
return;
|
||||
}
|
||||
if(copy1(fdf, fdt, from, to)==0 && (xflag || gflag || uflag)){
|
||||
nulldir(&dirt);
|
||||
if(xflag){
|
||||
dirt.mtime = dirb->mtime;
|
||||
dirt.mode = dirb->mode;
|
||||
}
|
||||
if(uflag)
|
||||
dirt.uid = dirb->uid;
|
||||
if(gflag)
|
||||
dirt.gid = dirb->gid;
|
||||
if(dirfwstat(fdt, &dirt) < 0)
|
||||
fprint(2, "cp: warning: can't wstat %s: %r\n", to);
|
||||
}
|
||||
free(dirb);
|
||||
close(fdf);
|
||||
close(fdt);
|
||||
}
|
||||
|
||||
int
|
||||
copy1(int fdf, int fdt, char *from, char *to)
|
||||
{
|
||||
char *buf;
|
||||
long n, n1, rcount;
|
||||
int rv;
|
||||
char err[ERRMAX];
|
||||
|
||||
buf = malloc(DEFB);
|
||||
/* clear any residual error */
|
||||
err[0] = '\0';
|
||||
errstr(err, ERRMAX);
|
||||
rv = 0;
|
||||
for(rcount=0;; rcount++) {
|
||||
n = read(fdf, buf, DEFB);
|
||||
if(n <= 0)
|
||||
break;
|
||||
n1 = write(fdt, buf, n);
|
||||
if(n1 != n) {
|
||||
fprint(2, "cp: error writing %s: %r\n", to);
|
||||
failed = 1;
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(n < 0) {
|
||||
fprint(2, "cp: error reading %s: %r\n", from);
|
||||
failed = 1;
|
||||
rv = -1;
|
||||
}
|
||||
free(buf);
|
||||
return rv;
|
||||
}
|
|
@ -2,11 +2,8 @@ APE=/sys/src/ape
|
|||
<$APE/config
|
||||
|
||||
TARG=basename\
|
||||
cc\
|
||||
cp\
|
||||
dirname\
|
||||
kill\
|
||||
mv\
|
||||
uname
|
||||
|
||||
DIRS=\
|
||||
|
@ -46,24 +43,6 @@ $DIRS:V:
|
|||
mk all
|
||||
}
|
||||
|
||||
cc.$O: cc.c
|
||||
mk -f /sys/src/cmd/mkfile cc.$O
|
||||
|
||||
$O.cc: cc.$O
|
||||
mk -f /sys/src/cmd/mkfile $O.cc
|
||||
|
||||
cp.$O: cp.c
|
||||
mk -f /sys/src/cmd/mkfile cp.$O
|
||||
|
||||
$O.cp: cp.$O
|
||||
mk -f /sys/src/cmd/mkfile $O.cp
|
||||
|
||||
mv.$O: mv.c
|
||||
mk -f /sys/src/cmd/mkfile mv.$O
|
||||
|
||||
$O.mv: mv.$O
|
||||
mk -f /sys/src/cmd/mkfile $O.mv
|
||||
|
||||
$BIN/%: %.rc
|
||||
cp -x $stem.rc $BIN/$stem
|
||||
|
||||
|
|
|
@ -1,250 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
|
||||
int copy1(int fdf, int fdt, char *from, char *to);
|
||||
void hardremove(char *);
|
||||
int mv(char *from, char *todir, char *toelem);
|
||||
int mv1(char *from, Dir *dirb, char *todir, char *toelem);
|
||||
int samefile(char *, char *);
|
||||
void split(char *, char **, char **);
|
||||
|
||||
void
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i, failed;
|
||||
Dir *dirto, *dirfrom;
|
||||
char *todir, *toelem;
|
||||
|
||||
if(argc<3){
|
||||
fprint(2, "usage: mv fromfile tofile\n");
|
||||
fprint(2, " mv fromfile ... todir\n");
|
||||
exits("bad usage");
|
||||
}
|
||||
|
||||
/* Skip -f */
|
||||
if(argv[1][0] == '-' && argv[1][1] == 'f' && argv[1][2] == 0) {
|
||||
for(i=2; i<argc; i++) {
|
||||
argv[i-1] = argv[i];
|
||||
}
|
||||
argc--;
|
||||
}
|
||||
|
||||
/* prepass to canonicalise names before splitting, etc. */
|
||||
for(i=1; i < argc; i++)
|
||||
cleanname(argv[i]);
|
||||
|
||||
if((dirto = dirstat(argv[argc-1])) != nil && (dirto->mode&DMDIR)){
|
||||
dirfrom = nil;
|
||||
if(argc == 3
|
||||
&& (dirfrom = dirstat(argv[1])) != nil
|
||||
&& (dirfrom->mode & DMDIR))
|
||||
split(argv[argc-1], &todir, &toelem); /* mv dir1 dir2 */
|
||||
else{ /* mv file... dir */
|
||||
todir = argv[argc-1];
|
||||
toelem = nil; /* toelem will be fromelem */
|
||||
}
|
||||
free(dirfrom);
|
||||
}else
|
||||
split(argv[argc-1], &todir, &toelem); /* mv file1 file2 */
|
||||
free(dirto);
|
||||
if(argc>3 && toelem != nil){
|
||||
fprint(2, "mv: %s not a directory\n", argv[argc-1]);
|
||||
exits("bad usage");
|
||||
}
|
||||
|
||||
failed = 0;
|
||||
for(i=1; i < argc-1; i++)
|
||||
if(mv(argv[i], todir, toelem) < 0)
|
||||
failed++;
|
||||
if(failed)
|
||||
exits("failure");
|
||||
exits(0);
|
||||
}
|
||||
|
||||
int
|
||||
mv(char *from, char *todir, char *toelem)
|
||||
{
|
||||
int stat;
|
||||
Dir *dirb;
|
||||
|
||||
dirb = dirstat(from);
|
||||
if(dirb == nil){
|
||||
fprint(2, "mv: can't stat %s: %r\n", from);
|
||||
return -1;
|
||||
}
|
||||
stat = mv1(from, dirb, todir, toelem);
|
||||
free(dirb);
|
||||
return stat;
|
||||
}
|
||||
|
||||
int
|
||||
mv1(char *from, Dir *dirb, char *todir, char *toelem)
|
||||
{
|
||||
int fdf, fdt, i, j, stat;
|
||||
char toname[4096], fromname[4096];
|
||||
char *fromdir, *fromelem;
|
||||
Dir *dirt, null;
|
||||
|
||||
i = strlen(from);
|
||||
if(i >= sizeof(fromname)){
|
||||
fprint(2, "mv: path too big (max %d): %s\n",
|
||||
sizeof(fromname), from);
|
||||
return -1;
|
||||
}
|
||||
memmove(fromname, from, i+1);
|
||||
split(from, &fromdir, &fromelem);
|
||||
if(toelem == 0)
|
||||
toelem = fromelem;
|
||||
i = strlen(toelem);
|
||||
if(i==0){
|
||||
fprint(2, "mv: null last name element moving %s\n", fromname);
|
||||
return -1;
|
||||
}
|
||||
j = strlen(todir);
|
||||
if(i + j + 2 > sizeof toname){
|
||||
fprint(2, "mv: path too big (max %d): %s/%s\n",
|
||||
sizeof toname, todir, toelem);
|
||||
return -1;
|
||||
}
|
||||
memmove(toname, todir, j);
|
||||
toname[j] = '/';
|
||||
memmove(toname+j+1, toelem, i);
|
||||
toname[i+j+1] = 0;
|
||||
|
||||
if(samefile(fromdir, todir)){
|
||||
if(samefile(fromname, toname)){
|
||||
fprint(2, "mv: %s and %s are the same\n",
|
||||
fromname, toname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* remove target if present */
|
||||
dirt = dirstat(toname);
|
||||
if(dirt != nil) {
|
||||
hardremove(toname);
|
||||
free(dirt);
|
||||
}
|
||||
|
||||
/* try wstat */
|
||||
nulldir(&null);
|
||||
null.name = toelem;
|
||||
if(dirwstat(fromname, &null) >= 0)
|
||||
return 0;
|
||||
if(dirb->mode & DMDIR){
|
||||
fprint(2, "mv: can't rename directory %s: %r\n",
|
||||
fromname);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Renaming won't work --- must copy
|
||||
*/
|
||||
if(dirb->mode & DMDIR){
|
||||
fprint(2, "mv: %s is a directory, not copied to %s\n",
|
||||
fromname, toname);
|
||||
return -1;
|
||||
}
|
||||
fdf = open(fromname, OREAD);
|
||||
if(fdf < 0){
|
||||
fprint(2, "mv: can't open %s: %r\n", fromname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dirt = dirstat(toname);
|
||||
if(dirt != nil && (dirt->mode & DMAPPEND))
|
||||
hardremove(toname); /* because create() won't truncate file */
|
||||
free(dirt);
|
||||
|
||||
fdt = create(toname, OWRITE, dirb->mode);
|
||||
if(fdt < 0){
|
||||
fprint(2, "mv: can't create %s: %r\n", toname);
|
||||
close(fdf);
|
||||
return -1;
|
||||
}
|
||||
stat = copy1(fdf, fdt, fromname, toname);
|
||||
close(fdf);
|
||||
|
||||
if(stat >= 0){
|
||||
nulldir(&null);
|
||||
null.mtime = dirb->mtime;
|
||||
null.mode = dirb->mode;
|
||||
dirfwstat(fdt, &null); /* ignore errors; e.g. user none always fails */
|
||||
if(remove(fromname) < 0){
|
||||
fprint(2, "mv: can't remove %s: %r\n", fromname);
|
||||
stat = -1;
|
||||
}
|
||||
}
|
||||
close(fdt);
|
||||
return stat;
|
||||
}
|
||||
|
||||
int
|
||||
copy1(int fdf, int fdt, char *from, char *to)
|
||||
{
|
||||
char buf[8192];
|
||||
long n, n1;
|
||||
|
||||
while ((n = read(fdf, buf, sizeof buf)) > 0) {
|
||||
n1 = write(fdt, buf, n);
|
||||
if(n1 != n){
|
||||
fprint(2, "mv: error writing %s: %r\n", to);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(n < 0){
|
||||
fprint(2, "mv: error reading %s: %r\n", from);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
split(char *name, char **pdir, char **pelem)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = utfrrune(name, '/');
|
||||
if(s){
|
||||
*s = 0;
|
||||
*pelem = s+1;
|
||||
*pdir = name;
|
||||
}else if(strcmp(name, "..") == 0){
|
||||
*pdir = "..";
|
||||
*pelem = ".";
|
||||
}else{
|
||||
*pdir = ".";
|
||||
*pelem = name;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
samefile(char *a, char *b)
|
||||
{
|
||||
Dir *da, *db;
|
||||
int ret;
|
||||
|
||||
if(strcmp(a, b) == 0)
|
||||
return 1;
|
||||
da = dirstat(a);
|
||||
db = dirstat(b);
|
||||
ret = (da != nil && db != nil &&
|
||||
da->qid.type==db->qid.type &&
|
||||
da->qid.path==db->qid.path &&
|
||||
da->qid.vers==db->qid.vers &&
|
||||
da->dev==db->dev &&
|
||||
da->type==db->type);
|
||||
free(da);
|
||||
free(db);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
hardremove(char *a)
|
||||
{
|
||||
if(remove(a) == -1){
|
||||
fprint(2, "mv: can't remove %s: %r\n", a);
|
||||
exits("mv");
|
||||
}
|
||||
while(remove(a) != -1)
|
||||
;
|
||||
}
|
Loading…
Reference in a new issue