implement cp and mv and improve rm
This commit is contained in:
parent
4192b13768
commit
cec53d14b1
1
LICENSE
1
LICENSE
|
@ -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"),
|
||||
|
|
10
Makefile
10
Makefile
|
@ -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
6
TODO
|
@ -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...]
|
||||
|
|
|
@ -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
22
cp.1
Normal 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
27
cp.c
Normal 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
9
fs.h
Normal 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
16
mv.1
Normal 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
39
mv.c
Normal 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
3
rm.1
|
@ -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)
|
||||
|
|
28
rm.c
28
rm.c
|
@ -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++)
|
||||
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
1
util.h
|
@ -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
59
util/cp.c
Normal 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;
|
||||
}
|
|
@ -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
15
util/fnck.c
Normal 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
17
util/rm.c
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user