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 pancake <pancake@youterm.com>
© 2011 Random832 <random832@fastmail.us>
© 2012 William Haddon <william@haddonthethird.net>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View File

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

6
TODO
View File

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

View File

@ -10,7 +10,7 @@ MANPREFIX = $(PREFIX)/share/man
LD = $(CC)
CPPFLAGS = -D_POSIX_C_SOURCE=200112L
CFLAGS = -Os -ansi -Wall -pedantic $(CPPFLAGS)
LDFLAGS = -static #-s
LDFLAGS =
#CC = tcc
#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.
.TP
.B \-r
remove directories recursively.
remove directories recursively. If this flag is not specified, directories are
not removed.
.SH SEE ALSO
.IR remove (3)

30
rm.c
View File

@ -3,39 +3,33 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include "fs.h"
#include "util.h"
static void rm(const char *);
static bool fflag = false;
static bool rflag = false;
int
main(int argc, char *argv[])
{
char c;
struct stat st;
while((c = getopt(argc, argv, "fr")) != -1)
switch(c) {
case 'f':
fflag = true;
rm_fflag = true;
break;
case 'r':
rflag = true;
rm_rflag = true;
break;
default:
exit(EXIT_FAILURE);
}
for(; optind < argc; optind++)
rm(argv[optind]);
for(; optind < argc; 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;
}
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 enprintf(int, const char *, ...);
long estrtol(const char *, int);
void fnck(const char *, const char *, int (*)(const char *, const char *));
void putword(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 "../util.h"
static void fnck(const char *, const char *, int (*)(const char *, const char *));
void
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);
}
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);
}