一、复制的三种情况:
-
将文件复制成另外一个文件;
int copy_file2file( char *cpSrcPath,char *cpDstPath ) { int iFdSrc = 0; int iFdDst = 0; int iRdNum = 0; int iWrNum = 0; char caLine[ LINELEN ]; /* open thhe source file */ if( ( iFdSrc = open( cpSrcPath, O_RDONLY ) ) < 0 { /* fail to open the source file */ return -1; } /* open the dest file */ if( ( iFdDst = open( cpDstPath, O_WRONLY | O_CREAT | O_TRUNC, S_IWUSR |S_IRUSR ) ) < 0 ) { return -1; } /* read the file until the EOF or some error */ while( ( iRdNum = read( iFdSrc, caLine, sizeof( caLine ) ) ) > 0 ) { if( ( iWrNum = write( iFdDst, caLine,iRdNum ) ) != iRdNum ) { /* write error */ close_fd( 2, iFdSrc, iFdDst ); /* delete the dest file */ unlink( cpDstPath ); return -1; } } /* read error */ if( iRdNum != 0 ) { close_fd( 2, iFdSrc, iFdDst ); /* delete the dest file */ unlink( cpDstPath ); return -1; } close_fd( iFdSrc, iFdDst ); return 0; }
-
将文件复制到另外一个文件夹里;
int copy_file2dir( char *cpSrcPath, char *cpDstPath ) { char caTmpDstPath[ NAMELEN ]; char caTmpBaseName[ NAMELEN ]; get_path_basename( cpSrcPath, caTmpBaseName ); combine_path( cpDstPath, caTmpBaseName, caTmpDstPath ); return copy_file2file( cpSrcPath, caTmpDstPath ); }
-
将文件夹复制到另外一个文件夹里;
int copy_dir2dir( char *cpSrcPath, char *cpDstPath ) { char caTmpSrcPath[ NAMELEN ]; char caTmpDstPath[ NAMELEN ]; char caTmpBaseName[ NAMELEN ]; DIR *fpDir = NULL; struct dirent *dirpCurr = NULL; int iTmpErrno; if( ( fpDir = opendir( cpSrcPath ) ) == NULL ) { return -1; } iTmpErrno = errno; get_path_basename( cpSrcPath, caTmpBaseName ); combine_path( cpDstPath, caTmpBaseName, caTmpDstPath ); if( mkdir( caTmpDstPath, S_IRWXU ) != 0 ) { return -1; } while( ( dirpCurr = readdir( fpDir ) ) != NULL ) { if( ( strcmp( dirpCurr->d_name, "." ) == 0 ) || ( strcmp( dirpCurr->d_name, ".." ) == 0 ) ) continue; combine_path( cpSrcPath, dirpCurr->d_name, caTmpSrcPath ); if( file_type( caTmpSrcPath ) == EN_DIR ) copy_dir2dir( caTmpSrcPath, caTmpDstPath ); else copy_file2dir( caTmpSrcPath, caTmpDstPath ); } if( errno != iTmpErrno ) { /* some error */ return -1; } closedir( fpDir ); return 0; }
二、Makefile
# when update the src/cp.c file # first time to compile, there is some errors # but second time, it's OK, to find the resond ROOT=../.. include $(ROOT)/Make.defines VPATH:=src include obj PRGS:=mycp .PHONY=all all: $(PRGS) $(PRGS): mycp.c cp.o $(CC) $(CFLAGS) -I./include -o $@ $^ $(CLIBS) cp.o: cp.c $(CC) $(CFLAGS) -I./include -c $< $(MV) $@ obj/ .PHONY=clean clean: $(RM) $(TMPFILE) $(PRGS)
Make.defines和实现more时候的文件是基本是一样的,除了将Make.defines的CFLAGS里定义了一个宏-D_XOPEN_SOURCE=500,因为在判断文件类型的时候使用了S_ISSOCK(m)这个宏在一些版本里没有,所以定义了它。但是这个Makefile有个问题是每次修改了cp.c这个文件或重新生成的时候,第一编译会出错,提示找不到cp.o;第二次编译才能成功。
可能的原因分析:
当cp.c更新或重新生成的时候,make要生成最后的mycp目标文件,会检查依赖文件mycp.c和cp.o。
因为VPATH=include src obj,所以mycp.c会在src下找到,也就是编译时候的src/mycp.c,这没有问题;cp.o的问题应该是下面两种情况
当没有找到cp.o,make会根据定义的cp.o生成规则在当前目录生成cp.o,编译的时候会使用cp.o而不是obj/cp.o,但是我在生成cp.o之后马上将cp.o移动到了obj目录,而make并不知道,所以报找不到cp.o文件;
当找到obj/cp.o,但是发现其依赖文件src/cp.c已经更新,这时make放弃之前找到的obj/cp.o文件,转而采用根据规则重新生成的cp.o文件,这样就和上面的那种情况一样了。
针对Makefile之前的情况,我将移动cp.o的动作放到生成最终目标文件之后,所有添加了一个宏IF_MV,在执行完生成操作之后,如果在当前目录发现cp.o就将其移到obj目录ROOT=../.. include $(ROOT)/Make.defines VPATH:=src include obj PRGS:=mycp OBJ=cp.o define IF_MV @if[ -e "$(OBJ)" ]; \ then \ $(MV) $(OBJ) obj; \ fi endef .PHONY=all all: $(PRGS) $(PRGS): mycp.c cp.o $(CC) $(CFLAGS) -I./include -o $@ $^ $(CLIBS) $(IF_MV) cp.o: cp.c $(CC) $(CFLAGS) -I./include -c $< .PHONY=clean clean: $(RM) $(TMPFILE) $(PRGS)
三、源代码