/** * @file * * @brief Basic NFS Filesystem Utilities for Testing the NFS * @ingroup libfs */ /* * Author: Till Straumann, , 10/2002 * * Authorship * ---------- * This software (NFS-2 client implementation for RTEMS) was created by * Till Straumann , 2002-2007, * Stanford Linear Accelerator Center, Stanford University. * * Acknowledgement of sponsorship * ------------------------------ * The NFS-2 client implementation for RTEMS was produced by * the Stanford Linear Accelerator Center, Stanford University, * under Contract DE-AC03-76SFO0515 with the Department of Energy. * * Government disclaimer of liability * ---------------------------------- * Neither the United States nor the United States Department of Energy, * nor any of their employees, makes any warranty, express or implied, or * assumes any legal liability or responsibility for the accuracy, * completeness, or usefulness of any data, apparatus, product, or process * disclosed, or represents that its use would not infringe privately owned * rights. * * Stanford disclaimer of liability * -------------------------------- * Stanford University makes no representations or warranties, express or * implied, nor assumes any liability for the use of this software. * * Stanford disclaimer of copyright * -------------------------------- * Stanford University, owner of the copyright, hereby disclaims its * copyright and all other rights in this software. Hence, anyone may * freely use it for any purpose without restriction. * * Maintenance of notices * ---------------------- * In the interest of clarity regarding the origin and status of this * SLAC software, this and all the preceding Stanford University notices * are to remain affixed to any copy or derivative of this software made * or distributed by the recipient and are to be affixed to any copy of * software made or distributed by the recipient that contains a copy or * derivative of this software. * * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 */ #if HAVE_CONFIG_H #include "config.h" #endif #ifdef __vxworks #include #endif #include #include #include #include #include #include #include #include #include /* PATH_MAX */ #include /* PRI* */ #if SIZEOF_MODE_T == 8 #define PRIomode_t PRIo64 #elif SIZEOF_MODE_T == 4 #define PRIomode_t PRIo32 #else #error "unsupport size of mode_t" #endif #if SIZEOF_OFF_T == 8 #define PRIdoff_t PRIo64 #elif SIZEOF_OFF_T == 4 #define PRIdoff_t PRIo32 #else #error "unsupported size of off_t" #endif #ifdef HAVE_CEXP #include #endif #ifndef __vxworks /* * Prototypes to avoid warnings */ int pwd(void); int ls(char *dir, char *opts); int cp(char *from, char *to, char *opts); int ln(char *to, char *name, char *opts); int rm(char *path); int cd(char *path); #endif #ifndef __vxworks int pwd(void) { char buf[PATH_MAX]; if ( !getcwd(buf,PATH_MAX)) { perror("getcwd"); return -1; } else { printf("%s\n",buf); } return 0; } static int ls_r(char *path, char *chpt, char *name, struct stat *buf) { char *t; sprintf(chpt, "/%s", name); if (lstat(path,buf)) { fprintf(stderr,"stat(%s): %s\n", path, strerror(errno)); return -1; } switch ( buf->st_mode & S_IFMT ) { case S_IFSOCK: case S_IFIFO: t = "|"; break; default: case S_IFREG: case S_IFBLK: case S_IFCHR: t = ""; break; case S_IFDIR: t = "/"; break; case S_IFLNK: t = "@"; break; } printf("%10li, %10" PRIdoff_t "b, %5i.%-5i 0%04" PRIomode_t " %s%s\n", buf->st_ino, buf->st_size, buf->st_uid, buf->st_gid, buf->st_mode & ~S_IFMT, name, t); *chpt = 0; return 0; } int ls(char *dir, char *opts) { struct dirent *de; char path[PATH_MAX+1]; char *chpt; DIR *dp = 0; int rval = -1; struct stat buf; if ( !dir ) dir = "."; strncpy(path, dir, PATH_MAX); path[PATH_MAX] = 0; chpt = path+strlen(path); if ( !(dp=opendir(dir)) ) { perror("opendir"); goto cleanup; } while ( (de = readdir(dp)) ) { ls_r(path, chpt, de->d_name, &buf); } rval = 0; cleanup: if (dp) closedir(dp); return rval; } #endif #if 0 fprintf(stderr, "usage: cp(""from"",[""to""[,""-f""]]\n"); fprintf(stderr, " ""to""==NULL -> stdout\n"); fprintf(stderr, " ""-f"" -> overwrite existing file\n"); #endif int cp(char *from, char *to, char *opts) { struct stat st; int rval = -1; int fd = -1; FILE *fst = 0; FILE *tst = 0; int flags = O_CREAT | O_WRONLY | O_TRUNC | O_EXCL; if (from) { if ((fd=open(from,O_RDONLY,0)) < 0) { fprintf(stderr, "Opening %s for reading: %s\n", from, strerror(errno)); goto cleanup; } if (fstat(fd, &st)) { fprintf(stderr, "rstat(%s): %s\n", from, strerror(errno)); goto cleanup; } if (!S_ISREG(st.st_mode)) { fprintf(stderr,"Refuse to copy a non-regular file\n"); errno = EINVAL; goto cleanup; } /* Now create a stream -- I experienced occasional weirdness * when circumventing the streams attached to fildno(stdin) * by reading/writing to the underlying fd's directly -> * for now we always go through buffered I/O... */ if ( !(fst=fdopen(fd,"r")) ) { fprintf(stderr, "Opening input stream [fdopen()] failed: %s\n", strerror(errno)); goto cleanup; } /* at this point, we have a stream and don't need 'fd' anymore */ fd = -1; } else { fst = stdin; st.st_mode = 0644; } if (opts && strchr(opts,'f')) flags &= ~ O_EXCL; if (to) { if ( (fd=open(to,flags,st.st_mode)) < 0 ) { fprintf(stderr, "Opening %s for writing: %s\n", to, strerror(errno)); goto cleanup; } if ( !(tst=fdopen(fd, "w")) ) { fprintf(stderr, "Opening output stream [fdopen()] failed: %s\n", strerror(errno)); goto cleanup; } /* at this point we have a stream and don't need 'fd' anymore */ fd = -1; } else { tst = stdout; } /* clear old errors */ clearerr(fst); clearerr(tst); /* use macro versions on register vars; stdio is already buffered, * there's nothing to be gained by reading/writing blocks into * a secondary buffer... */ { register int ch; register FILE *f = fst; register FILE *t = tst; while ( EOF != (ch = getc(f)) && EOF != putc(ch, t) ) /* nothing else */; } if ( ferror(fst) ) { fprintf(stderr,"Read error: %s\n",strerror(errno)); goto cleanup; } if ( ferror(tst) ) { fprintf(stderr,"Write error: %s\n",strerror(errno)); goto cleanup; } rval = 0; cleanup: if ( fd >= 0 ) close(fd); if ( fst ) { if ( from ) fclose(fst); else clearerr(fst); } if ( tst ) { if ( to ) fclose(tst); else { /* flush stdout */ fflush(tst); clearerr(tst); } } return rval; } int ln(char *to, char *name, char *opts) { if (!to) { fprintf(stderr,"ln: need 'to' argument\n"); return -1; } if (!name) { if ( !(name = strrchr(to,'/')) ) { fprintf(stderr, "ln: 'unable to link %s to %s\n", to,to); return -1; } name++; } if (opts && strchr(opts,'s')) { if (symlink(name,to)) { fprintf(stderr,"symlink: %s\n",strerror(errno)); return -1; } } else { if (link(name,to)) { fprintf(stderr,"hardlink: %s\n",strerror(errno)); return -1; } } return 0; } int rm(char *path) { return unlink(path); } int cd(char *path) { return chdir(path); } #ifdef HAVE_CEXP static CexpHelpTabRec _cexpHelpTabDirutils[] __attribute__((unused)) = { HELP( "copy a file: cp(""from"",[""to""[,""-f""]])\n\ from = NULL <-- stdin\n\ to = NULL --> stdout\n\ option -f: overwrite existing file\n", int, cp, (char *from, char *to, char *options) ), HELP( "list a directory: ls([""dir""])\n", int, ls, (char *dir) ), HELP( "remove a file\n", int, rm, (char *path) ), HELP( "change the working directory\n", int, cd, (char *path) ), HELP( "create a link: ln(""to"",""name"",""[-s]""\n\ -s creates a symlink\n", int, ln, (char *to, char *name, char *options) ), HELP("",,0,) }; #endif