summaryrefslogblamecommitdiffstats
path: root/cpukit/libfs/src/nfsclient/src/dirutils.c
blob: e392b9a3fef3cc44cc0de77ebdfc2d7f9d7a5a5e (plain) (tree)
1
2
3
4
5
6
7
8
9
10





                                                            
 
  

                                                                




                                                                       
  




                                                                          
  







                                                                           
  



                                                                         
  



                                                                      

                                                     







                                                                        
  
                                                                        
   
 



                   










                     
                                  
 

















                                  




                     











                                         





































                                                                        
                                                                              


































































































































































































                                                                                        
                                       


























































                                                                         
/**
 * @file
 *
 * @brief Basic NFS Filesystem Utilities for Testing the NFS
 * @ingroup libfs
 */

/*
 * Author: Till Straumann, <strauman@slac.stanford.edu>, 10/2002
 *
 * Authorship
 * ----------
 * This software (NFS-2 client implementation for RTEMS) was created by
 *     Till Straumann <strauman@slac.stanford.edu>, 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 <vxWorks.h>
#endif
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include <limits.h> /* PATH_MAX */

#include <inttypes.h> /* 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 <cexpHelp.h>
#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