diff options
Diffstat (limited to 'libc/tests/ft.c')
-rw-r--r-- | libc/tests/ft.c | 1209 |
1 files changed, 0 insertions, 1209 deletions
diff --git a/libc/tests/ft.c b/libc/tests/ft.c deleted file mode 100644 index 1bdc737..0000000 --- a/libc/tests/ft.c +++ /dev/null @@ -1,1209 +0,0 @@ -/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk> - * This program is distributed under the GNU General Public License. - */ - -/* - * File Tool, This program is a collection of basic file tools - * it includes cat, cp, ln, mkdir, mknod, chmod, chown, mv, rm - * - * Links may be used to call it under any of these names. - */ -#include <stdio.h> -#ifdef __STDC__ -#include <unistd.h> -#include <stdlib.h> -#endif -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <string.h> -#include <dirent.h> -#include <sys/param.h> -#include <utime.h> -#include <pwd.h> -#include <grp.h> - -#ifdef S_IFSOCK -#include <sys/socket.h> -#endif -#ifndef S_IFLNK -#define lstat stat -#endif - -/* Ansi prototypes */ -#ifdef __STTDC__ -#define PR(x) x -#else -#define PR(x) () -#endif - -void main PR((int argc, char ** argv)); -int select_command PR((char * argv)); -void do_prep PR((void)); -void do_post PR((void)); -void execute PR((char * dname, char * fname)); -int exec_for_subdir PR((char * dname)); -void exec_for_item PR((int when, char * fname)); -void parse_perms PR((char * prefix, char * ustring)); -int edit_mode PR((int mode, char * mode_str)); -int cmd_ft PR((char * fname)); -int cmd_mkfifo PR((char * fname)); -int cmd_mksock PR((char * fname)); -int cmd_rm PR((char * fname)); -void build_dest PR((char * dest, char * name, char * newpath)); -int strisdigit PR((char * str)); -int cmd_mv PR((char * fname)); -int cmd_ln PR((char * fname)); -int cmd_cp PR((char * fname)); -int copy_modes PR((char * file)); -int copy_file PR((char * source, char * dest)); -void Usage PR((void)); -int cmd_mkdir PR((char * dirname)); -int cmd_mknod PR((void)); -int warning PR((int enumber, char * estr, char * eobj)); -int error PR((int enumber, char * estr, char * eobj)); - -#define DO_BDIR 0x0010 /* Do Dir before contents */ -#define DO_ADIR 0x0020 /* Do Dir after contents */ -#define DO_MCOPY 0x0040 /* Preserve modes flag forced */ -#define OK_DIR 0x0080 /* Directorys OK even if no flg_recurse */ -#define IGN_LNK 0x0100 /* Not interested in symlinks */ -#define NO_SOURCE 0x0200 /* Named files created */ -#define OK_NO_SOURCE 0x0400 /* Don't need the source */ - -#define CMD_FT (0+OK_DIR+DO_BDIR) -#define CMD_CAT (1+IGN_LNK) -#define CMD_CHGRP (2+OK_DIR+IGN_LNK+DO_ADIR) -#define CMD_CHMOD (3+OK_DIR+IGN_LNK+DO_ADIR) -#define CMD_CHOWN (4+OK_DIR+IGN_LNK+DO_ADIR) -#define CMD_CP (5+IGN_LNK) -#define CMD_EXTAR (6+DO_MCOPY+DO_BDIR) -#define CMD_INSTALL (7+DO_MCOPY) -#define CMD_LN (8+IGN_LNK+DO_BDIR) -#define CMD_MKDIR (9+NO_SOURCE) -#define CMD_MKFIFO (10+NO_SOURCE) -#define CMD_MKSOCK (11+NO_SOURCE) -#define CMD_MKNOD (12+NO_SOURCE) -#define CMD_MV (13+DO_MCOPY+OK_DIR+DO_BDIR) -#define CMD_RM (14+DO_ADIR) - -struct { - char * name; - int cmd; - int argpat; - char * opts; -} command_list[] = -{ - { "ft", CMD_FT, 0, "-Rv" }, - { "cat", CMD_CAT, 0, "uR" }, - { "chgrp", CMD_CHGRP, 1, "vfR" }, - { "chmod", CMD_CHMOD, 1, "vfR" }, - { "chown", CMD_CHOWN, 1, "vfR" }, - { "cp", CMD_CP, -1, "vifRrpsda" }, - { "extar", CMD_EXTAR, 1, "" }, - { "install", CMD_INSTALL, -1, "cdso:g:m:" }, - { "ln", CMD_LN, -1, "vifs" }, - { "mkdir", CMD_MKDIR, 0, "m:" }, - { "mkfifo", CMD_MKFIFO, 0, "m:" }, -#ifdef S_IFSOCK - { "mksock", CMD_MKSOCK, 0, "m:" }, -#endif - { "mknod", CMD_MKNOD, 4, "m:" }, - { "mv", CMD_MV, -1, "vif" }, - { "rm", CMD_RM, 0, "vifr" }, - { 0 } -}; - -int cmd_arg = 0; -int cmd_tok = CMD_FT; -char * cmd_opt = "-"; -char * cmd_string = 0; /* the first (or last) arg where special */ -char * prog_name = ""; - -char ** flist = 0; -int fcount = 0; -int add_base=0; -char * or_name = 0; -int or_offset = 0; - -int flg_recurse = 0; -int flg_verbose = 1; -int flg_preserve= 0; -int flg_mkpdir = 0; -int flg_noderef = 0; -int flg_symlink = 0; -int flg_exestrip= 0; - -int flg_r, flg_force; -char *str_o, *str_g, *str_m; - -/* Things to set on the new file */ -int set_user = -1; -int set_group = -1; -int set_mode = -1; -time_t set_time = -1; -char mode_str[32] = ""; -int u_mask = 0; /* 07777 altered by umask() */ - -struct stat cur_file_stat; -struct stat dest_item; -struct stat access_stat; - -int done_something = 0; - -void -main(argc, argv) -int argc; char ** argv; -{ - int ar; - (void) select_command(argv[0]); - - for(ar=1; - argv[ar] && argv[ar][0] == '-' && argv[ar][1]; - ar++) - { - char * p = argv[ar]+1; - /* For symbolic changes of the form -rwx */ - if( cmd_tok == CMD_CHMOD && strchr("rwx", *p) != 0 ) break; - while(*p) - { - char * ap=0, *av=0; - char ch; - /* Is it a valid opt for this cmd */ - if(*p == ':' || (ap=strchr(cmd_opt, *p)) == 0) Usage(); - - /* Got an argument ? */ - if(ap[1] == ':') - { - if(!argv[ar+1]) Usage(); - av = argv[++ar]; - } - - if( (ch = *p) == '-' ) - { - if( (ch=select_command(p)) < 0 ) Usage(); - } - switch(ch) - { - case '\0': break; - case 'r': - case 'R': flg_recurse++; break; - case 'v': flg_verbose++; break; - case 'p': if(cmd_tok == CMD_MKDIR) flg_mkpdir++; - else flg_preserve++; - break; - case 'd': if(cmd_tok == CMD_INSTALL) - { flg_mkpdir++; cmd_arg=0; } /* Special mkdir */ - else flg_noderef++; /* cmd_copy */ - break; - - case 'f': flg_force++; flg_verbose=0; break; - case 'o': str_o = av; break; - case 'g': str_g = av; break; - case 'm': str_m = av; break; - - case 's': flg_symlink++; - if( cmd_tok == CMD_LN) cmd_tok |= OK_DIR+OK_NO_SOURCE; - break; - case 'a': flg_recurse++; flg_preserve++; flg_noderef++; - break; - } - if(*p == '-') break; - p++; - } - } - - switch(cmd_arg) - { - case 1: - if( ar >= argc ) Usage(); - cmd_string = argv[ar++]; - fcount = argc-ar; - flist = argv+ar; - break; - case 0: - fcount = argc-ar; - flist = argv+ar; - break; - case -1: - if( ar >= argc ) Usage(); - cmd_string = argv[argc-1]; - fcount = argc-ar-1; - flist = argv+ar; - break; - default: - if( ar != argc-cmd_arg ) Usage(); - fcount = argc-ar; - flist = argv+ar; - break; - } - - do_prep(); - - for(ar=0; ar<fcount; ar++) - { - done_something=1; - or_name = flist[ar]; or_offset = strlen(or_name)+1; - execute(flist[ar], (char*)0); - } - - do_post(); - - if( !done_something ) - { - if( cmd_tok == CMD_CAT ) - execute("-", (char*)0); - else - Usage(); - } - exit(0); -} - -int select_command(argv) -char * argv; -{ - int ar; - char *p, *s; - prog_name = argv; - for(ar=0; command_list[ar].name; ar++) - { - p = strrchr(argv, '-'); if(p) p++; else p=argv; - s = strrchr(p, '/'); if(s) s++; else s=p; - if( strcmp(s, command_list[ar].name) == 0 ) - { - cmd_arg = command_list[ar].argpat; - cmd_tok = command_list[ar].cmd; - cmd_opt = command_list[ar].opts; - return 0; - } - } - return -1; -} - -void do_prep() -{ - char * prefix = "::"; - - u_mask = umask(077); - umask(u_mask); - u_mask = (07777&(~u_mask)); - - if(cmd_tok&DO_MCOPY) flg_preserve++; - if(str_m) parse_perms(prefix, str_m); - - switch(cmd_tok) - { - /* mknod is very different */ - case CMD_MKNOD: cmd_mknod(); exit(0); break; - - case CMD_CP: - if(strcmp(cmd_string, "-") == 0) - { - cmd_tok = CMD_CAT; - cmd_arg = 0; - break; - } - if(flg_symlink) - { - cmd_tok = CMD_LN+OK_DIR+OK_NO_SOURCE; - flg_preserve = 0; - } - break; - - case CMD_CHOWN: prefix++; - case CMD_CHGRP: prefix++; - case CMD_CHMOD: - parse_perms(prefix, cmd_string); - set_time = 0; - break; - case CMD_INSTALL: - flg_exestrip = flg_symlink; - flg_symlink = 0; - if(str_o) parse_perms(prefix+2, str_o); - if(str_g) parse_perms(prefix+1, str_g); - if(flg_mkpdir) cmd_tok = CMD_MKDIR; - else - { - cmd_tok = CMD_CP; - flg_preserve = 1; - } - break; - } - -#ifndef S_IFLNK - if(flg_symlink) - { - error(0, "No support for symlinks available:", cmd_string); - exit(1); - } -#endif - - /* Are we transfering many to one ? Then it must be a directory */ - if(cmd_arg == -1) - { - if( stat(cmd_string, &dest_item) == -1) - { - if( fcount > 1 ) - { - if( cmd_mkdir(cmd_string) < 0 ) - exit(1); - stat(cmd_string, &dest_item); - add_base = 1; - } - } - else - { - if( !S_ISDIR(dest_item.st_mode) ) - { - if( fcount > 1 ) - { - error(0, "Destination must be a directory:", cmd_string); - exit(1); - } - } - else add_base = 1; - } - } -} - -void do_post() -{ - /* Oh! It seems there's nothing to do, ah well. */ -} - -void execute(dname, fname) -char * dname; char * fname; -{ - char * buf; - if( strcmp(dname, "-") == 0 ) - { - exec_for_item(0, dname); - return; - } - if( fname ) - { - buf = alloca(strlen(dname) + strlen(fname) + 4); - if( buf == 0 ) - { - error(errno, "Can't allocate memory for path beyond ", dname); - return ; - } - strcpy(buf, dname); - if(strcmp(dname, "/")) strcat(buf, "/"); - strcat(buf, fname); - } - else buf = dname; - - if( lstat(buf, &cur_file_stat) == -1 ) - { - if( cmd_tok&(NO_SOURCE|OK_NO_SOURCE) ) - exec_for_item(0, buf); - else - warning(errno, "", buf); - return; - } - if( !flg_force && ( cmd_tok&NO_SOURCE )) - { - error(EEXIST, "", buf); - return; - } - - if( S_ISDIR(cur_file_stat.st_mode)) - { - if( (cmd_tok&OK_DIR) || flg_recurse ) - (void) exec_for_subdir(buf); - else - error(EISDIR, "", buf); - return; - } - -#ifdef S_IFLNK - if( S_ISLNK(cur_file_stat.st_mode)) - { - /* Links are special */ - if( cmd_tok&IGN_LNK ) - { - if( stat(buf, &cur_file_stat) == -1 ) - { - warning(errno, "", buf); - return; - } - } - } -#endif - exec_for_item(0, buf); -} - -int exec_for_subdir(dname) -char * dname; -{ - DIR * dfd; - struct dirent * ent; - int old_mode = -1; - - if( cmd_tok&DO_BDIR ) exec_for_item(-1, dname); - - if( flg_recurse ) - { - dfd = opendir(dname); - if( dfd == 0 && errno == EACCES && flg_force ) - { - old_mode = (cur_file_stat.st_mode & 07777); - if( chmod(dname, (0700|old_mode)) ) - return error(errno, "", dname); - - dfd = opendir(dname); - } - if( dfd == 0 ) return error(errno, "", dname); - - while((ent=readdir(dfd))) - { - if( strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0 ) - continue; - - alloca(0); /* Free up if using fake version */ - execute(dname, ent->d_name); - } - closedir(dfd); - if( old_mode != -1 ) - chmod(dname, old_mode); - } - - if( cmd_tok&DO_ADIR ) - { - lstat(dname, &cur_file_stat); - exec_for_item(1, dname); - } - return 0; -} - -void exec_for_item(when, fname) -int when; char * fname; -{ - int rv = -1; - switch(cmd_tok) - { - case CMD_FT: rv = cmd_ft(fname); break; - - case CMD_CAT: rv = copy_file(fname, "-"); break; - - case CMD_CHGRP: /* And fall */ - case CMD_CHMOD: /* And fall */ - case CMD_CHOWN: rv = copy_modes(fname); break; - - case CMD_CP: rv = cmd_cp(fname); break; - case CMD_MV: rv = cmd_mv(fname); break; - case CMD_RM: rv = cmd_rm(fname); break; - - case CMD_EXTAR: error(EINVAL, "", "No code."); exit(1); - - case CMD_LN+OK_DIR+OK_NO_SOURCE: - case CMD_LN: rv = cmd_ln(fname); break; - - case CMD_INSTALL: error(EINVAL, "", ""); exit(1); - - case CMD_MKDIR: rv = cmd_mkdir(fname); break; - case CMD_MKFIFO: rv = cmd_mkfifo(fname); break; -#ifdef S_IFSOCK - case CMD_MKSOCK: rv = cmd_mksock(fname); break; -#endif - case CMD_MKNOD: break; - } -} - -void parse_perms(prefix, ustring) -char * prefix; char * ustring; -{ - char * userstr; - char * groupstr; - char * modestr; - char * cp; - struct passwd * pwd = 0; - struct group * grp; - - userstr = alloca(strlen(prefix) + strlen(ustring) + 2); - strcpy(userstr, prefix); - strcat(userstr, ustring); - - /* Select User */ - cp = strchr(userstr, ':'); - if(!cp) cp = strchr(userstr, '.'); - if(cp) *cp = '\0'; - - /* If there's a user */ - if( *userstr != 0 ) - { - pwd = getpwnam(userstr); - if(pwd == NULL) - { - if(!strisdigit(userstr) ) - { - error(EINVAL, "Unknown user ", userstr); - exit(1); - } - set_user = atoi(userstr); - } - else set_user = pwd->pw_uid; - endpwent(); - } - if(cp) - { - groupstr = cp+1; - cp = strchr(groupstr, ':'); - if(!cp) cp = strchr(groupstr, '.'); - if(cp) *cp = '\0'; - if( *groupstr != '\0' ) - { - grp = getgrnam(groupstr); - if(grp == NULL) - { - if(!strisdigit(groupstr) ) - { - error(EINVAL, "Unknown group ", groupstr); - exit(1); - } - set_group = atoi(groupstr); - } - else set_group = grp->gr_gid; - endgrent(); - } - else if( pwd ) - set_group = pwd->pw_gid; - } - if(cp) - { - modestr = cp+1; - if(strisdigit(modestr)) - set_mode = strtol(modestr, NULL, 8); - else - { - strncpy(mode_str, modestr, sizeof(mode_str)-1); - /* This is the time that the mode change will fail on syn error */ - (void) edit_mode(u_mask, mode_str); - } - } - - if( set_user < 0 && set_group < 0 && set_mode < 0 && *mode_str == 0) - { - error(EINVAL, "", "Permission string has no changes"); - exit(1); - } -} - -int edit_mode(mode, mode_str) -int mode; char * mode_str; -{ - char * str=mode_str; -static mtab[] = {0, 0111, 0222, 0333, 0444, 0555, 0666, 0777 }; - - int done_change = 0; - int isdir = S_ISDIR(mode); - int change_op = 0; - int change_mask = u_mask; - int v=0, s=0, nm=0; - - for(; *mode_str; mode_str++) - { - switch(*mode_str) - { - case ',': change_op = 0; - change_mask=u_mask; continue; - case '=': change_op = 1; if(0) { - case '+': change_op = 2; } if(0) { - case '-': change_op = 3; } - v=0; nm=0; - if(strchr(",=+-", mode_str[1]) == 0 ) continue; - break; - case 'a': if(change_op) goto ch_error; - nm |= 07777; if(0) { - case 'u': nm |= 04700; s= 6; } if(0) { - case 'g': nm |= 02070; s= 3; } if(0) { - case 'o': nm |= 01007; s= 0; } - if(change_op==0) { change_mask=nm; continue; } - v |= mtab[(mode>>s)&7]; - break; - case 'r': v |= 0444; break; - case 'w': v |= 0222; break; - case 'x': v |= 0111; break; - case 's': v |=06000; break; - case 't': v |=01000; break; - case 'X': v |= mtab[isdir]; break; - default: goto ch_error; - } - switch(change_op) - { - case 0: goto ch_error; - case 1: mode= ((mode&(~change_mask)) | (v&change_mask)); - break; - case 2: mode= ( mode | (v&change_mask)); - break; - case 3: mode= ( mode & ~(v&change_mask)); - break; - } - done_change=1; - } - if(!done_change) - { -ch_error: - error(EINVAL, "Invalid mode string ", str); - exit(1); - } - return mode; -} - -int -cmd_ft(fname) -char * fname; -{ -static char oldpath[2048] = "~"; -static int last_uid=-1, last_gid=-1, last_mode=-1; - struct passwd * pptr; - struct group * gptr; - - if( flg_verbose>1 ) - { - char *p = 0; - if( fname[1] ) p = strrchr(fname, '/'); - if( p ) - { - *p = '\0'; - if( strcmp(fname, oldpath) != 0 ) - { - strcpy(oldpath, fname); - printf("%s/\n", oldpath); - } - *p = '/'; - } - else if( *oldpath ) - *oldpath = '\0'; - if(p) printf("%s", p+1); - else printf("%s", fname); - -#ifdef S_IFLNK - if( S_ISLNK(cur_file_stat.st_mode)) - { - char linkbuf[1024]; - int v; - *linkbuf='\0'; - v = readlink(fname, linkbuf, sizeof(linkbuf)); - if(v>0) linkbuf[v] = '\0'; - printf("\t+%s", linkbuf); - } - else -#endif - if( cur_file_stat.st_mode != last_mode - || cur_file_stat.st_uid != last_uid - || cur_file_stat.st_gid != last_gid) - { - printf("\t"); - if( cur_file_stat.st_uid != last_uid ) - { - pptr = getpwuid(cur_file_stat.st_uid); - if( pptr ) - printf("%s", pptr->pw_name); - else - printf("%d", cur_file_stat.st_uid); - } - printf(":"); - if( cur_file_stat.st_gid != last_gid ) - { - gptr = getgrgid(cur_file_stat.st_gid); - if( gptr ) - printf("%s", gptr->gr_name); - else - printf("%d", cur_file_stat.st_gid); - } - if( (cur_file_stat.st_mode&07777) != (last_mode&07777) ) - printf(":%03o", cur_file_stat.st_mode & 07777); - - switch(cur_file_stat.st_mode & S_IFMT) - { - case S_IFDIR: printf("\td"); break; - case S_IFIFO: printf("\tp"); break; -#ifdef S_IFSOCK - case S_IFSOCK: printf("\ts"); break; -#endif - case S_IFBLK: printf("\tb,%d,%d", cur_file_stat.st_rdev>>8, - cur_file_stat.st_rdev&0xFF); - break; - case S_IFCHR: printf("\tc,%d,%d", cur_file_stat.st_rdev>>8, - cur_file_stat.st_rdev&0xFF); - break; - } - last_mode = ((cur_file_stat.st_mode&07777)|S_IFREG); - if( (cur_file_stat.st_mode&07000) ) last_mode = -1; - last_uid = cur_file_stat.st_uid; - last_gid = cur_file_stat.st_gid; - } - printf("\n"); - } - else printf("%s\n", fname); - - return 0; -} - -int -cmd_mkfifo(fname) -char * fname; -{ - int rv; - int mode=0666; - if( set_mode >= 0 ) mode=set_mode; - rv = mknod(fname, S_IFIFO|mode, 0); - if(rv<0) - warning(errno, "Cannot create fifo ", fname); - return rv; -} - -#ifdef S_IFSOCK -int -cmd_mksock(fname) -char * fname; -{ - int rv, fd, len; - struct sockaddr *adr; - - len = strlen(fname)+1 + sizeof(*adr) - sizeof(adr->sa_data); - if( len < sizeof(*adr) ) len = sizeof(*adr); - - adr = alloca(len+2); - adr->sa_family = AF_UNIX; - strcpy(adr->sa_data, fname); - - rv = fd = socket(AF_UNIX, SOCK_STREAM, 0); - if( fd>=0 ) rv = bind(fd, adr, len); - if( fd>=0 ) close(fd); - if(set_mode >= 0 && chmod(fname, set_mode&07777) < 0 ) - warning(errno, "Chmod ", fname); - - if(rv<0) - warning(errno, "Cannot create socket ", fname); - return rv; -} -#endif - -int -cmd_rm(fname) -char * fname; -{ - struct stat dirstat; - int rv; - char * buf, * p; - - if( S_ISDIR(cur_file_stat.st_mode) ) - if( !flg_recurse ) return error(EISDIR, "", fname); - - if( S_ISDIR(cur_file_stat.st_mode) ) - { - if( rmdir(fname) >= 0 ) return 0; - } - else - { - if( unlink(fname) >= 0 ) return 0; - } - - if( !flg_force ) - return error(errno, "", fname); - - /* Try VERY hard */ - buf = alloca(strlen(fname)+4); - strcpy(buf, fname); - p = strrchr(buf, '/'); - if( p ) strcpy(p+1, "."); else strcpy(buf, "."); - - if( stat(buf, &dirstat) < 0 ) return -1; - if( chmod(buf, dirstat.st_mode|0700) < 0 ) return -1; - - if( S_ISDIR(cur_file_stat.st_mode) ) - rv = rmdir(fname); - else - rv = unlink(fname); - - chmod(buf, dirstat.st_mode); - - return rv; -} - -void -build_dest(dest, name, newpath) -char * dest; char * name; char * newpath; -{ - char * p; - strcpy(dest, newpath); - if( add_base ) - { - strcat(dest, "/"); - p = strrchr(or_name, '/'); - if(p==0) strcat(dest, or_name); - else strcat(dest, p+1); - } - if(strlen(name) <= or_offset) return; - strcat(dest, name+or_offset); -} - -int -strisdigit(str) -char * str; -{ - if( str==0 || *str == 0 ) return 0; - - for(;*str; str++) - if(*str>'9'|| *str<'0') return 0; - return 1; -} - -int -cmd_mv(fname) -char * fname; -{ - char * destfile; - destfile = alloca(strlen(fname)+strlen(cmd_string)+4); - - build_dest(destfile, fname, cmd_string); - - if( !flg_force && lstat(destfile, &access_stat) == 0 ) - return error(EEXIST, "", destfile); - - if( rename(fname, destfile) == 0 ) return 0; - - if( errno != EXDEV ) - return error(errno, "", fname); - - if( S_ISDIR(cur_file_stat.st_mode) ) - return error(EISDIR, "Can't rename across devices ", fname); - - if( copy_file(fname, destfile) != 0 ) return -1; - copy_modes(destfile); - return unlink(fname); -} - -int -cmd_ln(fname) -char * fname; -{ - char * destfile; - destfile = alloca(strlen(fname)+strlen(cmd_string)+4); - - build_dest(destfile, fname, cmd_string); - - if( lstat(destfile, &access_stat) != -1 ) - { - if( !flg_force ) return error(EEXIST, "", destfile); - cmd_rm(destfile); - } - -#ifdef S_IFLNK - if( flg_symlink ) - { - if( symlink(fname, destfile) == 0 ) return 0; - } - else - { -#endif - if( link(fname, destfile) == 0 ) return 0; -#ifdef S_IFLNK - } -#endif - - return error(errno, "", destfile); -} - -int -cmd_cp(fname) -char * fname; -{ - struct stat dest_stat; - char * destfile; - int no_dest = 0; - - destfile = alloca(strlen(fname)+strlen(cmd_string)+4); - - build_dest(destfile, fname, cmd_string); - - if( stat(destfile, &dest_stat) >= 0 ) - { - if( dest_stat.st_ino == cur_file_stat.st_ino - && dest_stat.st_dev == cur_file_stat.st_dev ) - { - warning(EPERM, "Can't copy file to itself ", fname); - return -1; - } - } - else no_dest = 1; - - if( S_ISDIR(cur_file_stat.st_mode) ) - { - if( !no_dest ) - { - if( S_ISDIR(dest_stat.st_mode) ) return 0; - if( unlink(destfile) < 0 ) - return error(errno, "Can't delete ", destfile); - } - return cmd_mkdir(destfile); - } - else if( S_ISDIR(dest_stat.st_mode) ) - return error(EPERM, "Can't copy non-directory to directory ", destfile); - else if( S_ISREG(cur_file_stat.st_mode) ) - { - /* Copy_ok - do we want to force a real file */; - if( flg_force && !no_dest && !S_ISREG(dest_stat.st_mode) ) - cmd_rm(destfile); - } - else if( flg_recurse ) /* Don't copy other things while recursing */ - { - return error(EPERM, "Can't copy ", fname); - } - - if( copy_file(fname, destfile) != 0 ) return -1; - if( flg_preserve ) copy_modes(destfile); - return 0; -} - -int -copy_modes(file) -char * file; -{ - int user, group, mode; - /* chown turns off set[ug]id bits for non-root, - so do the chmod last. */ - - /* Try to copy the old file's modtime and access time. */ - if(set_time) - { - struct utimbuf tv; - - tv.actime = cur_file_stat.st_atime; - tv.modtime = cur_file_stat.st_mtime; - if( set_time != -1 ) - tv.modtime = set_time; - if (utime (file, &tv) && !flg_force) - return error (errno, "", file); - } - - /* Try to preserve ownership. For non-root it might fail, but that's ok. - But root probably wants to know, e.g. if NFS disallows it. */ - user = cur_file_stat.st_uid; if(set_user>=0) user = set_user; - group = cur_file_stat.st_gid; if(set_group>=0) group = set_group; - - if (chown (file, user, group) - && (errno != EPERM || geteuid() == 0 || (flg_preserve==0 && flg_force==0))) - error (errno, "Can't change perms for ", file); - - mode = cur_file_stat.st_mode; - if(set_mode>=0) mode=set_mode; - else if(*mode_str) - mode = edit_mode(mode, mode_str); - - if (chmod (file, mode & 07777)) - return error (errno, "", file); - - return 0; -} - -/* This copies from something to a file or stdout */ -/* If the source has zero blocks (possibly holes) the destination - * is built with holes (assuming it's a normal file) */ - -int -copy_file(source, dest) -char * source; char * dest; -{ - char * buf; - int sfd, dfd; - struct stat st; - int blksz = BUFSIZ; - int cc; - char * ptr; - int hole_flag = 0; - int retv = 0; - int no_seek; - int mmode = 0666; - - if(flg_verbose>1) printf("%s -> %s\n", source, dest); - if( strcmp(source, "-") == 0 ) - sfd = 0; - else - { - sfd = open(source, O_RDONLY); - if(sfd<0) return error(errno, "", source); - mmode = (cur_file_stat.st_mode&0777); - } - - if( strcmp(dest, "-") == 0 ) - dfd = 1; - else - { - dfd = open(dest, O_WRONLY|O_TRUNC|O_CREAT, mmode); - if(dfd<0) - { - close(sfd); - return error(errno, "Cannot create ", source); - } - } - - if( fstat(dfd, &st) ) - { - retv = error(errno, "", dest); - no_seek = 1; - } - else - { -#ifndef __BCC__ - blksz = st.st_blksize; -#endif - no_seek = !S_ISREG(st.st_mode); - } - buf = alloca(blksz + sizeof(int)); - if( buf == 0 ) return error(0, "Out of memory", ""); - - for(;;) - { - cc = read(sfd, buf, blksz); - if(cc<0) - { - retv = error(errno, "", source); - goto exit_now; - } - if(cc==0) break; - buf[cc] = 1; - for(ptr=buf; *ptr==0 ; ptr++) ; - if((hole_flag = (ptr == buf+cc))) - { /* Make a hole */ - if( lseek(dfd, (off_t) cc, SEEK_CUR) < 0 ) - { - retv = error(errno, "", dest); - goto exit_now; - } - } - else - { - if( cc != write(dfd, buf, cc)) - { - retv = error(errno, "", dest); - goto exit_now; - } - } - } - if( hole_flag ) - { - if( lseek(dfd, (off_t) -1, SEEK_CUR) < 0 - || write(dfd, "", 1) != 1 ) - { - retv = error(errno, "", dest); - goto exit_now; - } - } - -exit_now: - if(sfd>2) close(sfd); - if(dfd>2) close(dfd); - return retv; -} - -void -Usage() -{ - int i; - - printf("FileTool Usage: %s%s", prog_name[0]=='-'?"ft -":"", prog_name); - if( cmd_tok == CMD_FT ) - { - printf(" --[com_name] [-options] [files]\n"); - printf("\nAvailable commands are:\n"); - } - - for(i=1; command_list[i].name; i++) - { - if( cmd_tok == CMD_FT ) - printf(" %s --%s", prog_name, command_list[i].name); - else if( cmd_tok != command_list[i].cmd ) - continue; - - if( *command_list[i].opts ) - printf(" [-%s]", command_list[i].opts); - switch(command_list[i].argpat) - { - case 1: printf(" <info> [files]"); break; - case -1: printf(" [files] [dest]"); break; - case 0: printf(" [files]"); break; - default: printf(" path [bcu] major minor"); break; - } - printf("\n"); - } - - exit(99); -} - -int -cmd_mkdir(dirname) -char * dirname; -{ - int retv; - int mode = 0777; - if( set_mode >= 0 ) mode = set_mode; - - retv = mkdir(dirname, mode); - if(retv<0) - { - if(flg_mkpdir && errno == ENOENT) - { - /* Create parents */ - } - } - if( retv>=0 && cmd_tok == CMD_MKDIR ) - { - if( set_user > 0 || set_group > 0 ) - { - if( chown(dirname, set_user, set_group) < 0) - warning(errno, "Cannot change directory owner ", dirname); - else if( chmod (dirname, mode & 07777) ) - warning(errno, "", dirname); - } - } - - if(retv<0) error(errno, "Cannot create directory ", dirname); - return retv; -} - -int -cmd_mknod() -{ - int device; - int rv = -1; - int mode=0666; - if( set_mode >= 0 ) mode=set_mode; - - device = (atoi(flist[2])<<8) + atoi(flist[3]); - - if(flist[1][0] == 'b') - rv = mknod(flist[0], S_IFBLK|mode, device); - else if(flist[1][0] == 'c' || flist[1][0] == 'u') - rv = mknod(flist[0], S_IFCHR|mode, device); - else Usage(); - - if(rv<0) - { - error(errno, "", flist[0]); - exit(1); - } - return rv; -} - -int -warning(enumber, estr, eobj) -int enumber; char * estr; char * eobj; -{ - if(flg_verbose) - return error(enumber, estr, eobj); - return 0; -} - -int -error(enumber, estr, eobj) -int enumber; char * estr; char * eobj; -{ - fprintf(stderr, "%s%s: ", prog_name[0]=='-'?"ft":"", prog_name); - fprintf(stderr, "%s%s: %s\n", estr, eobj, strerror(enumber)); - return -1; -} |