Chinaunix首页 | 论坛 | 博客
  • 博客访问: 773471
  • 博文数量: 143
  • 博客积分: 2077
  • 博客等级: 大尉
  • 技术积分: 2393
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-28 12:57
文章存档

2016年(2)

2015年(3)

2014年(3)

2013年(41)

2012年(94)

分类: LINUX

2013-04-28 18:52:21

/** mv1.c
 ** ------------------------------------------------------------
	This version of mv accepts a directory name as the 
	second argument.  In that case the source item is
	moved into that directory.  
	sol04.16.c.

 ** ------------------------------------------------------------
 **
 *  A version of mv that accepts a directory name as second argument
 *
 *     usage: mv src dest
 *     if dest names a directory, then rename src to dest/src
 *     Note: if src has a leading path, then only use last component
 *     Also: if dest is on a different file system then copy the file
 */

#include        
#include	
#include        
#include	
#include	
#include	


void oops(char *, char *);

int
main(int ac, char *av[])
{
        if ( ac != 3 ){
                fprintf( stderr, "usage: %s source destination\n", *av);
                exit(1);
        }
	return do_mv(av[1], av[2]);
}

/*
 * Renames a file from src to dest
 *
 * If dest is a directory, then do_mv() moves to an item
 * in dest with the name taken from the filename for src
 */
int
do_mv(char *src, char *dest)
{
	char	*destfilename;
	char	*make_destfilename(char*,char*);
	int	rv;

	destfilename = make_destfilename(src, dest);
	rv = rename(src,destfilename);
	/*
	 * If target is different file system, try copy and remove
	 */
	if ( rv == -1 && errno == EXDEV )
		rv = copy_and_unlink(src,destfilename);
	if ( rv == -1 ){
		fprintf(stderr,"mv: cannot mv %s -> %s: ", src, dest);
		perror("");
	}
	return rv;

}

void oops(char *s1, char *s2)
{
        fprintf(stderr,"Error: %s ", s1);
        perror(s2);
        exit(1);
}

/*
 * if dest is a directory, then combine src and dest
 * (see header to this program)
 */

char *
make_destfilename(char *src, char *dest)
{
	struct stat info;
	char   *srcfilename;
	char   *rv;

	if ( stat(dest, &info) == -1 )	/* is a new filename */
		return dest;

	if ( ! S_ISDIR(info.st_mode) )	/* pre is a dir or old filename ,if a dir,ok to copy to other types	*/
		return dest;

	/* find last component of source name */
	if ( (srcfilename = strrchr(src, '/')) != NULL )
		srcfilename++;
	else
		srcfilename = src;

	/* use that to construct target name */
	rv = malloc(strlen(srcfilename) + strlen(dest) + 2);
	if ( rv == NULL )
		oops("Out of memory","");
	sprintf(rv, "%s/%s", dest, srcfilename);

	return rv;
}

/*
 * copy_and_unlink(old,new)
 *   purpose: copy a file and unlink the original
 *    reason: links cannot be moved to different file systems
 *    action: makes a copy using standard i/o lib
 *   returns: 0 for OK or -1 for file errors
 *   details: tedious.  If unlink fails, then unlink target
 *     NEEDS: needs to copy permission bits to new file
 */

copy_and_unlink(char *old, char *new)
{
	FILE	*fpin, *fpout;
	int	c;
	int	rv = 0;

	/** open files **/
	if ( (fpin = fopen(old,"r")) == NULL )
		return -1;
	if ( (fpout = fopen(new, "w")) == NULL ){
		fclose(fpin);
		return -1;
	}

	/** do copy **/
	while( rv == 0 && (c = getc(fpin)) != EOF )
		if ( putc(c, fpout) == EOF )
			rv = -1;

	/** close files: if error, abandon project **/
	if ( fclose(fpin) == EOF || fclose(fpout) == EOF ){
		rv = -1;
		unlink(new);
	}
	/** otherwise try to unlink original **/
	else if ( unlink(old) == -1 ){
		rv = -1;
		unlink(new);
	}

	/** whew! **/
	return rv;
}
阅读(1792) | 评论(0) | 转发(0) |
0

上一篇:mkdir -p dirname

下一篇:ls -li 源码

给主人留下些什么吧!~~