Upgrading to today's standards (is just barely started anyway)

This commit is contained in:
Pierre Pronchery 2005-06-14 04:36:09 +00:00
parent f0e05efa18
commit 1530c909f4

View File

@ -10,13 +10,24 @@
#include <string.h>
#include <errno.h>
#define sys_error(msg) { fprintf(stderr, "%s", "cp: "); perror(msg); return 2; }
/* types */
typedef int Prefs;
#define PREFS_f 0x01
#define PREFS_i 0x02
#define PREFS_H 0x04
#define PREFS_L 0x08
#define PREFS_p 0x10
#define PREFS_P 0x20
#define PREFS_r 0x40
#define PREFS_R 0x80
/* cp */
static int _cp_single(char * src, char * dst);
static int _cp_multiple(int argc, char * argv[]);
static int _cp(int argc, char * argv[])
static int _cp_error(char * message, int ret);
static int _cp_single(Prefs * prefs, char * src, char * dst);
static int _cp_multiple(Prefs * prefs, int argc, char * argv[]);
static int _cp(Prefs * prefs, int argc, char * argv[])
{
/* FIXME
* - cp_multiple already checks if last arg is a dir
@ -26,36 +37,48 @@ static int _cp(int argc, char * argv[])
struct stat st;
if(argc > 2)
return _cp_multiple(argc, argv);
return _cp_multiple(prefs, argc, argv);
if(stat(argv[1], &st) == -1 && errno != ENOENT)
sys_error(argv[1]);
_cp_error(argv[1], 0);
if(S_ISDIR(st.st_mode))
return _cp_multiple(argc, argv);
return _cp_single(argv[0], argv[1]);
return _cp_multiple(prefs, argc, argv);
return _cp_single(prefs, argv[0], argv[1]);
}
static int _cp_single(char * src, char * dst)
static int _cp_error(char * message, int ret)
{
fprintf(stderr, "%s", "cp: ");
perror(message);
return ret;
}
static int _cp_single(Prefs * prefs, char * src, char * dst)
{
FILE * fsrc;
FILE * fdst;
char buf[BUFSIZ];
size_t size;
char * err = src;
int fd;
struct stat st;
if(stat(src, &st) == -1)
sys_error(src);
if((fsrc = fopen(src, "r")) == NULL)
return _cp_error(src, 1);
if((fd = fileno(fsrc)) == -1 || fstat(fd, &st) != 0)
{
fclose(fsrc);
return _cp_error(src, 0);
}
if(S_ISDIR(st.st_mode))
{
fprintf(stderr, "%s%s%s", "cp: ", src, ": omitting directory\n");
fprintf(stderr, "%s%s%s", "cp: ", src,
": Omitting directory\n");
return 2;
}
if((fsrc = fopen(src, "r")) == NULL)
sys_error(src);
if((fdst = fopen(dst, "w")) == NULL)
{
fclose(fsrc);
sys_error(dst);
_cp_error(dst, 0);
}
while((size = fread(buf, sizeof(char), BUFSIZ, fsrc)) > 0)
if(fwrite(buf, sizeof(char), size, fdst) != BUFSIZ)
@ -67,13 +90,13 @@ static int _cp_single(char * src, char * dst)
if(!feof(fsrc))
{
fclose(fsrc);
sys_error(err);
_cp_error(err, 0);
}
fclose(fsrc);
return 0;
}
static int _cp_multiple(int argc, char * argv[])
static int _cp_multiple(Prefs * prefs, int argc, char * argv[])
{
char * dst = NULL;
char * p;
@ -85,11 +108,11 @@ static int _cp_multiple(int argc, char * argv[])
if((p = realloc(dst, len * sizeof(char))) == NULL)
{
free(dst);
sys_error("malloc");
_cp_error("malloc", 0);
}
dst = p;
sprintf(dst, "%s/%s", argv[argc-1], argv[i]);
_cp_single(argv[i], dst);
_cp_single(prefs, argv[i], dst);
}
free(dst);
return 2;
@ -101,7 +124,12 @@ static int _usage(void)
fprintf(stderr, "%s", "Usage: cp [-fip] source_file target_file\n\
cp [-fip] source_file ... target\n\
cp -R [-H | -L | -P][-fip] source_file ... target\n\
cp -r [-H | -L | -P][-fip] source_file ... target\n");
cp -r [-H | -L | -P][-fip] source_file ... target\n\
-f attempt to remove destination file before a copy if necessary\n\
-i prompt before a copy to an existing file\n\
-p duplicate characteristics of the source files\n\
-R copy file hierarchies\n\
-r copy file hierarchies\n");
return 1;
}
@ -109,17 +137,45 @@ static int _usage(void)
/* main */
int main(int argc, char * argv[])
{
Prefs prefs;
int o;
memset(&prefs, 0, sizeof(Prefs));
while((o = getopt(argc, argv, "")) != -1)
{
switch(o)
{
case 'f':
prefs -= prefs & PREFS_i;
prefs |= PREFS_f;
break;
case 'i':
prefs -= prefs & PREFS_f;
prefs |= PREFS_i;
break;
case 'H':
prefs -= prefs & PREFS_L;
prefs |= PREFS_H;
break;
case 'L':
prefs -= prefs & PREFS_H;
prefs |= PREFS_L;
break;
case 'P':
break;
case 'p':
break;
case 'R':
prefs -= prefs & PREFS_R;
break;
case 'r':
prefs -= prefs & PREFS_r;
break;
case '?':
return _usage();
}
}
if(optind + 1 >= argc)
return _usage();
return _cp(argc - optind, &argv[optind]);
return _cp(&prefs, argc - optind, &argv[optind]);
}