implement cp and mv and improve rm

This commit is contained in:
William Haddon 2012-01-30 22:41:33 +00:00
parent 4192b13768
commit cec53d14b1
16 changed files with 229 additions and 42 deletions

View File

@ -7,6 +7,7 @@ MIT/X Consortium License
© 2011 Hiltjo Posthuma <hiltjo@codemadness.org> © 2011 Hiltjo Posthuma <hiltjo@codemadness.org>
© 2011 pancake <pancake@youterm.com> © 2011 pancake <pancake@youterm.com>
© 2011 Random832 <random832@fastmail.us> © 2011 Random832 <random832@fastmail.us>
© 2012 William Haddon <william@haddonthethird.net>
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),

View File

@ -1,17 +1,20 @@
include config.mk include config.mk
HDR = text.h util.h HDR = fs.h text.h util.h
LIB = \ LIB = \
util/afgets.o \ util/afgets.o \
util/agetcwd.o \ util/agetcwd.o \
util/apathmax.o \ util/apathmax.o \
util/concat.o \ util/concat.o \
util/cp.o \
util/enmasse.o \ util/enmasse.o \
util/eprintf.o \ util/eprintf.o \
util/enprintf.o \ util/enprintf.o \
util/estrtol.o \ util/estrtol.o \
util/fnck.o \
util/putword.o \ util/putword.o \
util/recurse.o \ util/recurse.o \
util/rm.o \
util/venprintf.o util/venprintf.o
SRC = \ SRC = \
@ -21,6 +24,7 @@ SRC = \
chown.c \ chown.c \
cksum.c \ cksum.c \
cmp.c \ cmp.c \
cp.c \
date.c \ date.c \
dirname.c \ dirname.c \
echo.c \ echo.c \
@ -33,6 +37,7 @@ SRC = \
ls.c \ ls.c \
mkdir.c \ mkdir.c \
mkfifo.c \ mkfifo.c \
mv.c \
nl.c \ nl.c \
nohup.c \ nohup.c \
pwd.c \ pwd.c \
@ -56,7 +61,8 @@ all: $(BIN)
$(OBJ): util.h config.mk $(OBJ): util.h config.mk
$(BIN): util.a $(BIN): util.a
cat.o grep.o tail.o: text.h cat.o cp.o mv.o grep.o tail.o: text.h
cp.o mv.o rm.o: fs.h
.o: .o:
@echo LD $@ @echo LD $@

6
TODO
View File

@ -1,17 +1,11 @@
comm [-123] file1 file2 comm [-123] file1 file2
cp [-r] file [name]
cp [-r] [file...] [directory]
cut [-bcfs] [-d delim] list [file...] cut [-bcfs] [-d delim] list [file...]
diff [-ru] file1 file2 diff [-ru] file1 file2
id [-gnru] [user] id [-gnru] [user]
mv file [name]
mv [file...] directory
paste [-s] [-d list] [file...] paste [-s] [-d list] [file...]
printf format [argument...] printf format [argument...]

View File

@ -10,7 +10,7 @@ MANPREFIX = $(PREFIX)/share/man
LD = $(CC) LD = $(CC)
CPPFLAGS = -D_POSIX_C_SOURCE=200112L CPPFLAGS = -D_POSIX_C_SOURCE=200112L
CFLAGS = -Os -ansi -Wall -pedantic $(CPPFLAGS) CFLAGS = -Os -ansi -Wall -pedantic $(CPPFLAGS)
LDFLAGS = -static #-s LDFLAGS =
#CC = tcc #CC = tcc
#LD = $(CC) #LD = $(CC)

22
cp.1 Normal file
View File

@ -0,0 +1,22 @@
.TH CP 1 sbase\-VERSION
.SH NAME
cp \- copy files and directories
.SH SYNOPSIS
.B cp
.RB [ \-r ]
.I file
.RI [ name ]
.P
.B cp
.RB [ \-r ]
.RI [ file ...]
.RI [ directory ]
.SH DESCRIPTION
.B cp
copies a given file, naming it the given name. If multiple files are listed
they will be copied into the given directory.
.SH OPTIONS
.TP
.B \-r
copies directories recursively. If this flag is not specified, directories are
not copied.

27
cp.c Normal file
View File

@ -0,0 +1,27 @@
/* See LICENSE file for copyright and license details. */
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include "fs.h"
#include "util.h"
int
main(int argc, char *argv[])
{
struct stat st;
char c;
while((c = getopt(argc, argv, "r")) != -1)
switch(c) {
case 'r':
cp_rflag = true;
break;
default:
exit(EXIT_FAILURE);
}
if(argc > 3 && !cp_rflag && !(stat(argv[argc-1], &st) == 0 && S_ISDIR(st.st_mode)))
eprintf("%s: not a directory\n", argv[argc-1]);
enmasse(argc - optind, &argv[optind], cp);
return EXIT_SUCCESS;
}

9
fs.h Normal file
View File

@ -0,0 +1,9 @@
/* See LICENSE file for copyright and license details. */
#include <stdbool.h>
extern bool cp_rflag;
extern bool rm_fflag;
extern bool rm_rflag;
int cp(const char *, const char *);
void rm(const char *);

16
mv.1 Normal file
View File

@ -0,0 +1,16 @@
.TH MV 1 sbase\-VERSION
.SH NAME
mv \- move files and directories
.SH SYNOPSIS
.B mv
.I file
.RI [ name ]
.P
.B mv
.RI [ file ...]
.RI [ directory ]
.SH DESCRIPTION
.B mv
moves or renames a given file or directory, naming it the given name. If
multiple files and directories are listed they will be moved into the given
directory.

39
mv.c Normal file
View File

@ -0,0 +1,39 @@
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include "fs.h"
#include "util.h"
int mv(const char *, const char *);
int
main(int argc, char *argv[])
{
struct stat st;
if(getopt(argc, argv, "") != -1)
exit(EXIT_FAILURE);
if(argc > 3 && !(stat(argv[argc-1], &st) == 0 && S_ISDIR(st.st_mode)))
eprintf("%s: not a directory\n", argv[argc-1]);
enmasse(argc - optind, &argv[optind], mv);
return EXIT_SUCCESS;
}
int
mv (const char *s1, const char *s2)
{
if (rename(s1, s2) == 0)
return 0;
if (errno == EXDEV)
{
cp_rflag = true;
rm_rflag = true;
cp(s1, s2);
rm(s1);
return 0;
}
return -1;
}

3
rm.1
View File

@ -14,6 +14,7 @@ removes the given files and directories.
ignore files that cannot be removed. ignore files that cannot be removed.
.TP .TP
.B \-r .B \-r
remove directories recursively. remove directories recursively. If this flag is not specified, directories are
not removed.
.SH SEE ALSO .SH SEE ALSO
.IR remove (3) .IR remove (3)

30
rm.c
View File

@ -3,39 +3,33 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h>
#include "fs.h"
#include "util.h" #include "util.h"
static void rm(const char *);
static bool fflag = false;
static bool rflag = false;
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
char c; char c;
struct stat st;
while((c = getopt(argc, argv, "fr")) != -1) while((c = getopt(argc, argv, "fr")) != -1)
switch(c) { switch(c) {
case 'f': case 'f':
fflag = true; rm_fflag = true;
break; break;
case 'r': case 'r':
rflag = true; rm_rflag = true;
break; break;
default: default:
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
for(; optind < argc; optind++) for(; optind < argc; optind++) {
rm(argv[optind]); if(!rm_rflag && stat(argv[optind], &st) == 0 &&
S_ISDIR(st.st_mode))
fprintf(stderr, "%s: is a directory\n", argv[optind]);
else
rm(argv[optind]);
}
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
void
rm(const char *path)
{
if(rflag)
recurse(path, rm);
if(remove(path) == -1 && !fflag)
eprintf("remove %s:", path);
}

1
util.h
View File

@ -8,5 +8,6 @@ void enmasse(int, char **, int (*)(const char *, const char *));
void eprintf(const char *, ...); void eprintf(const char *, ...);
void enprintf(int, const char *, ...); void enprintf(int, const char *, ...);
long estrtol(const char *, int); long estrtol(const char *, int);
void fnck(const char *, const char *, int (*)(const char *, const char *));
void putword(const char *); void putword(const char *);
void recurse(const char *, void (*)(const char *)); void recurse(const char *, void (*)(const char *));

59
util/cp.c Normal file
View File

@ -0,0 +1,59 @@
/* See LICENSE file for copyright and license details. */
#include <dirent.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include "../fs.h"
#include "../text.h"
#include "../util.h"
bool cp_rflag = false;
int
cp(const char *s1, const char *s2)
{
FILE *f1, *f2;
char *ns1, *ns2;
long size1, size2;
struct dirent *d;
struct stat st;
DIR *dp;
if (stat(s1, &st) == 0 && S_ISDIR(st.st_mode)) {
if (!cp_rflag) {
eprintf("%s: is a directory\n", s1);
}
else {
if(!(dp = opendir(s1)))
eprintf("opendir %s:", s1);
if (mkdir(s2, st.st_mode) == -1 && errno != EEXIST)
eprintf("mkdir %s:", s2);
apathmax(&ns1, &size1);
apathmax(&ns2, &size2);
while((d = readdir(dp)))
if(strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) {
if(snprintf(ns1, size1, "%s/%s", s1, d->d_name) > size1)
eprintf("%s/%s: filename too long\n", s1, d->d_name);
if(snprintf(ns2, size2, "%s/%s", s2, d->d_name) > size2)
eprintf("%s/%s: filename too long\n", s2, d->d_name);
fnck(ns1, ns2, cp);
}
closedir(dp);
free(ns1);
free(ns2);
}
return 0;
}
if(!(f1 = fopen(s1, "r")))
eprintf("fopen %s:", s1);
if(!(f2 = fopen(s2, "w")))
eprintf("fopen %s:", s2);
concat(f1, s1, f2, s2);
fclose(f2);
fclose(f1);
return 0;
}

View File

@ -7,8 +7,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#include "../util.h" #include "../util.h"
static void fnck(const char *, const char *, int (*)(const char *, const char *));
void void
enmasse(int argc, char **argv, int (*fn)(const char *, const char *)) enmasse(int argc, char **argv, int (*fn)(const char *, const char *))
{ {
@ -32,15 +30,3 @@ enmasse(int argc, char **argv, int (*fn)(const char *, const char *))
} }
free(buf); free(buf);
} }
void
fnck(const char *a, const char *b, int (*fn)(const char *, const char *))
{
struct stat sta, stb;
if(stat(a, &sta) == 0 && stat(b, &stb) == 0
&& sta.st_dev == stb.st_dev && sta.st_ino == stb.st_ino)
eprintf("%s -> %s: same file\n", a, b);
if(fn(a, b) == -1)
eprintf("%s -> %s:", a, b);
}

15
util/fnck.c Normal file
View File

@ -0,0 +1,15 @@
/* See LICENSE file for copyright and license details. */
#include <sys/stat.h>
#include "../util.h"
void
fnck(const char *a, const char *b, int (*fn)(const char *, const char *))
{
struct stat sta, stb;
if(stat(a, &sta) == 0 && stat(b, &stb) == 0
&& sta.st_dev == stb.st_dev && sta.st_ino == stb.st_ino)
eprintf("%s -> %s: same file\n", a, b);
if(fn(a, b) == -1)
eprintf("%s -> %s:", a, b);
}

17
util/rm.c Normal file
View File

@ -0,0 +1,17 @@
/* See LICENSE file for copyright and license details. */
#include <stdbool.h>
#include <stdio.h>
#include "../fs.h"
#include "../util.h"
bool rm_fflag = false;
bool rm_rflag = false;
void
rm(const char *path)
{
if(rm_rflag)
recurse(path, rm);
if(remove(path) == -1 && !rm_fflag)
eprintf("remove %s:", path);
}