實現文件複製命令

 

一、實驗目的
學習使用linux和windows下有關目錄讀寫和文件讀寫的API函數。
二、實驗內容
完成一個目錄複製命令mycp,包括目錄下的文件和子目錄。
說明:
Linux: creat,read,write等系統調用
Windows: CreateFile(), ReadFile(), WriteFile(), CloseHandle()函數。
三、實驗環境
Ubuntu10.10和Windows7
四、程序設計與實現
主要算法是打開源目錄,遍歷源目錄中的每一項,如果是文件,就在目標目錄的相應位置創建文件,然後複製文件內容,如果是文件夾,在目標位置建立文件夾,然後遞歸進入該文件夾繼續操作。這裏要注意的是在建立文件夾和文件的時候,要同時把源文件的權限複製到目標文件上去。
主要使用了一下API函數:
windows下:
HANDLE CreateFile(
  LPCTSTR lpFileName, //指向文件名的指針
  DWORD dwDesiredAccess, //訪問模式(寫/讀)
  DWORD dwShareMode, //共享模式
  LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全屬性的指針
  DWORD dwCreationDisposition, //如何創建
  DWORD dwFlagsAndAttributes, //文件屬性
  HANDLE hTemplateFile //用於複製文件句柄
  );
BOOL WriteFile(
  HANDLE hFile, // 文件句柄
  LPCVOID lpBuffer, // 數據緩存區指針
  DWORD nNumberOfBytesToWrite, // 你要寫的字節數
  LPDWORD lpNumberOfBytesWritten, // 用於保存實際寫入字節數的存儲區域的指針
  LPOVERLAPPED lpOverlapped // OVERLAPPED結構體指針
  );
BOOL ReadFile(
  HANDLE hFile, //文件的句柄
  LPVOID lpBuffer, //用於保存讀入數據的一個緩衝區
  DWORD nNumberOfBytesToRead, //要讀入的字符數
  LPDWORD lpNumberOfBytesRead, //指向實際讀取字節數的指針
  LPOVERLAPPED lpOverlapped //如文件打開時指定了FILE_FLAG_OVERLAPPED,那麼必須,用這個參數引用一個特殊的結構。該結構定義了一次異步讀取操作。否則,應將這個參數設爲NULL
  );
BOOL CloseHandle(
  HANDLE hObject //代表一個已打開對象handle
  );
linux下:
int creat(const char * pathname, mode_tmode);//_tmode爲文件的狀態碼
int read(int handle, void *buf, int nbyte);//nbyte爲最大讀取字節數,返回值爲實際讀取字節數
int write(int handel, void *buf, int nbyte); //nbyte爲最大寫入字節數,返回值爲實際寫入字節數

windows版本:

 

  1. #include <windows.h>
  2. #include <windowsx.h>
  3. #include <tchar.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #define chDIMOF(Array) (sizeof(Array)/sizeof(Array[0]))
  8. static BOOL IsChildDir(WIN32_FIND_DATA * lpFindData)
  9. {
  10. return ((lpFindData->dwFileAttributes&
  11. FILE_ATTRIBUTE_DIRECTORY)!=0)&&
  12. (lstrcmp(lpFindData->cFileName,__TEXT("."))!=0)&&
  13. (lstrcmp(lpFindData->cFileName,__TEXT(".."))!=0);
  14. }
  15. static BOOL FindNextChildDir(HANDLE hFindFile,WIN32_FIND_DATA *lpFindData)
  16. {
  17. BOOL fFound=FALSE;
  18. do
  19. {
  20. fFound=FindNextFile(hFindFile,lpFindData);
  21. }while (fFound&&!IsChildDir(lpFindData));
  22. return fFound;
  23. }
  24. static HANDLE FindFirstChildDir(LPTSTR szPath,WIN32_FIND_DATA * lpFindData)
  25. {
  26. BOOL fFound;
  27. HANDLE hFindFile=FindFirstFile(szPath,lpFindData);
  28. if (hFindFile!=INVALID_HANDLE_VALUE)
  29. {
  30. fFound=IsChildDir(lpFindData);
  31. if (!fFound)
  32. {
  33. fFound=FindNextChildDir(hFindFile,lpFindData);
  34. }
  35. if (!fFound)
  36. {
  37. FindClose(hFindFile);
  38. hFindFile=INVALID_HANDLE_VALUE;
  39. }
  40. }
  41. return hFindFile;
  42. }
  43. typedef struct
  44. {
  45. int nDepth;
  46. BOOL fRecurse;
  47. TCHAR szBuf[1000];
  48. int nIndent;
  49. BOOL fOk;
  50. BOOL fIsDir;
  51. WIN32_FIND_DATA FindData;
  52. }DIRWALKDATA,*LPDIRWALKDATA;
  53. static void DirWalkRecurse(LPDIRWALKDATA pDW,LPTSTR pszRootPath,LPTSTR pszdestPath)
  54. {
  55. HANDLE hFind;
  56. LPTSTR temp;
  57. LPTSTR ttemp;
  58. temp=(LPTSTR)malloc(100*sizeof(LPTSTR));
  59. ttemp=(LPTSTR)malloc(100*sizeof(LPTSTR));
  60. pDW->nDepth++;
  61. pDW->nIndent=3*pDW->nDepth;
  62. _stprintf(pDW->szBuf,__TEXT("%*s"),pDW->nIndent,__TEXT(""));
  63. GetCurrentDirectory(chDIMOF(pDW->szBuf)-pDW->nIndent,&pDW->szBuf[pDW->nIndent]);
  64. //printf("%s\n",pDW->szBuf);
  65. hFind=FindFirstFile(__TEXT("*.*"),&pDW->FindData);
  66. pDW->fOk=(hFind!=INVALID_HANDLE_VALUE);
  67. while(pDW->fOk)
  68. {
  69. pDW->fIsDir=pDW->FindData.dwFileAttributes&
  70. FILE_ATTRIBUTE_DIRECTORY;
  71. if (!pDW->fIsDir||
  72. (!pDW->fRecurse&&IsChildDir(&pDW->FindData)))
  73. {
  74. _stprintf(pDW->szBuf,
  75. pDW->fIsDir?__TEXT("%*s[%s]"):__TEXT("%*s%s"),
  76. pDW->nIndent,__TEXT(""),
  77. pDW->FindData.cFileName);
  78. //printf("%s\n",pDW->szBuf);
  79. lstrcpy(temp,pszRootPath);
  80. lstrcat(temp,"\\");
  81. lstrcat(temp,pDW->FindData.cFileName);
  82. lstrcpy(ttemp,pszdestPath);
  83. lstrcat(ttemp,"\\");
  84. lstrcat(ttemp,pDW->FindData.cFileName);
  85. HANDLE hfile=CreateFile(
  86. ttemp,
  87. GENERIC_READ|GENERIC_WRITE,
  88. 0,
  89. NULL,
  90. OPEN_ALWAYS,
  91. pDW->FindData.dwFileAttributes,
  92. NULL);
  93. HANDLE dfile=CreateFile(
  94. temp,
  95. GENERIC_READ|GENERIC_WRITE,
  96. 0,
  97. NULL,
  98. OPEN_EXISTING,
  99. pDW->FindData.dwFileAttributes,
  100. NULL);
  101. DWORD filesize=GetFileSize(dfile,NULL);
  102. char* buffer=new char[filesize+1];
  103. DWORD readsize;
  104. ReadFile(dfile,buffer,filesize,&readsize,NULL);
  105. WriteFile(hfile,buffer,filesize,&readsize,NULL);
  106. buffer[filesize]=0;
  107. CloseHandle(hfile);
  108. CloseHandle(dfile);
  109. }
  110. else if(pDW->fIsDir&&IsChildDir(&pDW->FindData))
  111. {
  112. SECURITY_ATTRIBUTES attribute;
  113. attribute.nLength = sizeof(attribute);
  114. attribute.lpSecurityDescriptor = NULL;
  115. attribute.bInheritHandle = FALSE;
  116. SetCurrentDirectory(pszdestPath);
  117. CreateDirectory(
  118. pDW->FindData.cFileName,
  119. &attribute
  120. );
  121. SetCurrentDirectory(pszRootPath);
  122. }
  123. pDW->fOk=FindNextFile(hFind,&pDW->FindData);
  124. }
  125. if (hFind != INVALID_HANDLE_VALUE)
  126. {
  127. FindClose(hFind);
  128. }
  129. if (pDW->fRecurse)
  130. {
  131. hFind=FindFirstChildDir(__TEXT("*.*"),&pDW->FindData);
  132. pDW->fOk=(hFind!=INVALID_HANDLE_VALUE);
  133. while(pDW->fOk)
  134. {
  135. if (SetCurrentDirectory(pDW->FindData.cFileName))
  136. {
  137. lstrcpy(temp,pszRootPath);
  138. lstrcat(temp,"\\");
  139. lstrcat(temp,pDW->FindData.cFileName);
  140. lstrcpy(ttemp,pszdestPath);
  141. lstrcat(ttemp,"\\");
  142. lstrcat(ttemp,pDW->FindData.cFileName);
  143. DirWalkRecurse(pDW,temp,ttemp);
  144. SetCurrentDirectory(__TEXT(".."));
  145. }
  146. pDW->fOk=FindNextChildDir(hFind,&pDW->FindData);
  147. }
  148. if (hFind!=INVALID_HANDLE_VALUE)
  149. {
  150. FindClose(hFind);
  151. }
  152. }
  153. pDW->nDepth--;
  154. }
  155. void DirWalk(LPTSTR pszRootPath,LPTSTR pszdestPath,BOOL fResourse)
  156. {
  157. TCHAR szCurrDir[_MAX_DIR];
  158. DIRWALKDATA DW;
  159. GetCurrentDirectory(chDIMOF(szCurrDir),szCurrDir);
  160. SetCurrentDirectory(pszRootPath);
  161. DW.nDepth=-1;
  162. DW.fRecurse=fResourse;
  163. DirWalkRecurse(&DW,pszRootPath,pszdestPath);
  164. SetCurrentDirectory(szCurrDir);
  165. }
  166. int main(int argc,char *argv[])
  167. {
  168. char tmp[100],ttmp[100];
  169. int i;
  170. if (argc!=3)
  171. {
  172. printf("Argument Error\n");
  173. exit(0);
  174. }
  175. strcpy(tmp,argv[1]);
  176. if (strlen(tmp)!=1&&tmp[strlen(tmp)-1] == '\\')
  177. {
  178. tmp[strlen(tmp)-1]=0;
  179. }
  180. for ( i = strlen(tmp); i >= 0; i--)
  181. {
  182. if ( tmp[i] == '\\')
  183. {
  184. break;
  185. }
  186. }
  187. //printf("%s\n",&tmp[i+1]);
  188. strcpy(ttmp,argv[2]);
  189. if (strcmp(&tmp[i+1],"")&&strcmp(&tmp[i+1],"..")&&strcmp(&tmp[i+1],"."))
  190. {
  191. if (ttmp[strlen(ttmp)-1] != '\\')
  192. {
  193. strcat(ttmp,"/");
  194. }
  195. strcat(ttmp,&tmp[i+1]);
  196. //printf("cp %s %s\n",tmp,ttmp);
  197. SECURITY_ATTRIBUTES attribute;
  198. attribute.nLength = sizeof(attribute);
  199. attribute.lpSecurityDescriptor = NULL;
  200. attribute.bInheritHandle = FALSE;
  201. SetCurrentDirectory(argv[2]);
  202. CreateDirectory(
  203. &tmp[i+1],
  204. &attribute
  205. );
  206. }
  207. DirWalk((char *)argv[1],(char *)ttmp,TRUE);
  208. return 0;
  209. }

linux版本:

 

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <dirent.h>
  5. #include <sys/stat.h>
  6. #include <dirent.h>
  7. #include <fcntl.h>
  8. #define N 4096
  9. int cp(char dir[],char tdir[],int k)
  10. {
  11. int i,j,n;
  12. int fd,tfd;
  13. DIR *dp;
  14. char buf[N];
  15. char tmp[N],ttmp[N],ch[N];
  16. struct dirent *dirp[N],*dirptmp;
  17. struct stat st[N];
  18. if ( (dp = opendir(dir)) == NULL)
  19. {
  20. printf("cp: cannot access %s: No such file or directory\n",dir);
  21. return 1;
  22. }
  23. i=0;
  24. n=0;
  25. while ( (dirp[i] = readdir(dp)) != NULL)
  26. {
  27. if (dirp[i]->d_name[0]=='.')
  28. {
  29. continue;
  30. }
  31. strcpy(tmp,dir);
  32. if (tmp[strlen(tmp)-1] != '/')
  33. {
  34. strcat(tmp,"/");
  35. }
  36. strcat(tmp,dirp[i]->d_name);
  37. //printf("%s\n",tmp);
  38. if (lstat(tmp,&st[i]) < 0)
  39. {
  40. printf("Cannot open the directory\n");
  41. break;
  42. }
  43. i++;
  44. n++;
  45. }
  46. for ( i = 0; i < n; i++)
  47. {
  48. //printf("%d\n",i);
  49. memset(tmp,0,sizeof(tmp));
  50. memset(ttmp,0,sizeof(ttmp));
  51. //printf("%s\n",dirp[i]->d_name);
  52. if (S_ISDIR(st[i].st_mode))
  53. {
  54. strcpy(tmp,dir);
  55. if (tmp[strlen(tmp)-1] != '/')
  56. {
  57. strcat(tmp,"/");
  58. }
  59. strcat(tmp,dirp[i]->d_name);
  60. strcpy(ttmp,tdir);
  61. if (ttmp[strlen(ttmp)-1] != '/')
  62. {
  63. strcat(ttmp,"/");
  64. }
  65. strcat(ttmp,dirp[i]->d_name);
  66. //printf("cp %s %s\n",tmp,ttmp);
  67. if (mkdir(ttmp,st[i].st_mode) != 0)
  68. {
  69. //printf("The directory %s is exist.\n",ttmp);
  70. //continue;
  71. }
  72. cp(tmp,ttmp,k+1);
  73. //printf("%s\n",tmp);
  74. }
  75. else if(S_ISLNK(st[i].st_mode))
  76. {
  77. continue;
  78. }
  79. else
  80. {
  81. strcpy(tmp,dir);
  82. if (tmp[strlen(tmp)-1] != '/')
  83. {
  84. strcat(tmp,"/");
  85. }
  86. strcat(tmp,dirp[i]->d_name);
  87. fd=open(tmp,O_RDONLY);
  88. if (fd == -1)
  89. {
  90. printf("open file error\n");
  91. continue;
  92. }
  93. strcpy(ttmp,tdir);
  94. strcat(ttmp,"/");
  95. strcat(ttmp,dirp[i]->d_name);
  96. tfd=creat(ttmp,0644);
  97. if (tfd == -1)
  98. {
  99. printf("open file error\n");
  100. continue;
  101. }
  102. //printf("file %s %s\n",tmp,ttmp);
  103. while((j=read(fd,buf,512))>0)
  104. {
  105. write(tfd,buf,j);
  106. }
  107. close(fd);
  108. close(tfd);
  109. }
  110. }
  111. closedir(dp);
  112. return 0;
  113. }
  114. int main(int argc, char *argv[])
  115. {
  116. int i;
  117. char tmp[N],ttmp[N];
  118. struct stat st[N];
  119. if (argc < 2)
  120. {
  121. printf("Argument error\n");
  122. return 0;
  123. }
  124. else if (argc == 2)
  125. {
  126. printf("Argument error\n");
  127. return 0;
  128. }
  129. else if (argc == 3)
  130. {
  131. strcpy(tmp,argv[1]);
  132. if (strlen(tmp)!=1&&tmp[strlen(tmp)-1] == '/')
  133. {
  134. tmp[strlen(tmp)-1]=0;
  135. }
  136. for ( i = strlen(tmp); i >= 0; i--)
  137. {
  138. if ( tmp[i] == '/')
  139. {
  140. break;
  141. }
  142. }
  143. //printf("%s\n",&tmp[i+1]);
  144. strcpy(ttmp,argv[2]);
  145. if (strcmp(&tmp[i+1],"")&&strcmp(&tmp[i+1],"..")&&strcmp(&tmp[i+1],"."))
  146. {
  147. if (ttmp[strlen(ttmp)-1] != '/')
  148. {
  149. strcat(ttmp,"/");
  150. }
  151. strcat(ttmp,&tmp[i+1]);
  152. //printf("cp %s %s\n",tmp,ttmp);
  153. if (lstat(tmp,&st[i]) < 0)
  154. {
  155. printf("Cannot open the directory\n");
  156. exit(0);
  157. }
  158. mkdir(ttmp,st[i].st_mode);
  159. }
  160. //printf("cp %s %s\n",argv[1],ttmp);
  161. cp(argv[1],ttmp,0);//參數應爲絕對路徑
  162. }
  163. else
  164. {
  165. printf("Argument error\n");
  166. return 0;
  167. }
  168. return 0;
  169. }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章