Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

251 lines
5.1 KiB

  1. /*
  2. This program cleans build.exe trees.
  3. */
  4. #include "windows.h"
  5. #define NUMBER_OF(x) (sizeof(x)/sizeof((x)[0]))
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <stdlib.h>
  9. // error messages
  10. const static wchar_t errorNT[] = L"This program requires Windows NT.\n";
  11. #define NumberOf(x) (sizeof(x)/sizeof((x)[0]))
  12. void Log(const char* s, const wchar_t* q)
  13. {
  14. printf(s, q);
  15. }
  16. void Log(const wchar_t* s)
  17. {
  18. printf("%ls\n", s);
  19. }
  20. void Fail(const wchar_t* s)
  21. {
  22. Log(s);
  23. exit(EXIT_FAILURE);
  24. }
  25. void LogRecurse(const wchar_t* s)
  26. {
  27. printf("Recurse %ls\n", s);
  28. }
  29. void LogDelete(const wchar_t* s)
  30. {
  31. printf("Delete %ls\n", s);
  32. }
  33. bool IsDotOrDotDot(const wchar_t* s)
  34. {
  35. return
  36. (
  37. s[0] == '.' &&
  38. (
  39. (s[1] == 0)
  40. || (s[1] == '.' && s[2] == 0)
  41. )
  42. );
  43. }
  44. void DeleteDirectory(wchar_t* directory, int length, WIN32_FIND_DATAW* wfd)
  45. {
  46. directory[length] = 0;
  47. LogRecurse(directory);
  48. directory[length] = '\\';
  49. directory[length+1] = '*';
  50. directory[length+2] = 0;
  51. HANDLE hFind = FindFirstFileW(directory, wfd);
  52. if (hFind != INVALID_HANDLE_VALUE)
  53. {
  54. __try
  55. {
  56. do
  57. {
  58. if (IsDotOrDotDot(wfd->cFileName))
  59. {
  60. continue;
  61. }
  62. DWORD dwFileAttributes = wfd->dwFileAttributes;
  63. directory[length] = '\\';
  64. wcscpy(directory + length + 1, wfd->cFileName);
  65. if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  66. {
  67. DeleteDirectory(directory, length + 1 + wcslen(wfd->cFileName), wfd);
  68. }
  69. else
  70. {
  71. if (dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY))
  72. {
  73. //if (!SetFileAttributesW(directory, dwFileAttributes & ~(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY)))
  74. {
  75. // ...
  76. }
  77. }
  78. if (DeleteFileW(directory))
  79. {
  80. LogDelete(directory);
  81. }
  82. else
  83. {
  84. // ...
  85. }
  86. }
  87. } while (FindNextFileW(hFind, wfd));
  88. }
  89. __finally
  90. {
  91. FindClose(hFind);
  92. }
  93. }
  94. directory[length] = 0;
  95. RemoveDirectoryW(directory);
  96. LogDelete(directory);
  97. }
  98. void CleanDirectory(
  99. const wchar_t* obj,
  100. wchar_t* directory,
  101. int length,
  102. WIN32_FIND_DATAW* wfd
  103. )
  104. {
  105. directory[length] = 0;
  106. LogRecurse(directory);
  107. // clean build[d,fre,chk].[log,wrn,err] builds
  108. const static wchar_t dfrechk[][4] = { L"", L"d", L"fre", L"chk" };
  109. const static wchar_t logwrnerr[][4] = { L"log", L"wrn", L"err" };
  110. for (int b = 0 ; b < NUMBER_OF(dfrechk); b++)
  111. {
  112. for (int g = 0 ; g < NUMBER_OF(logwrnerr) ; ++g)
  113. {
  114. swprintf(directory + length, L"\\build%s.%s", dfrechk[b], logwrnerr[g]);
  115. if (DeleteFileW(directory))
  116. {
  117. LogDelete(directory);
  118. }
  119. else
  120. {
  121. // ...
  122. }
  123. }
  124. }
  125. // Dangerous to clean files out of source directory, but:
  126. // FUTURE clean *.plg (VC Project Log?) files
  127. // FUTURE clean *.rsp files that sometimes appear in source dir?
  128. // FUTURE clean MSG*.bin files that sometimes appear in source dir?
  129. // FUTURE clean RC* files that sometimes appear in source dir?
  130. directory[length] = '\\';
  131. wcscpy(directory + length + 1, obj);
  132. HANDLE hFind = FindFirstFileW(directory, wfd);
  133. if (hFind != INVALID_HANDLE_VALUE)
  134. {
  135. __try
  136. {
  137. do
  138. {
  139. directory[length] = '\\';
  140. wcscpy(directory + length + 1, wfd->cFileName);
  141. DeleteDirectory(directory, length + 1 + wcslen(wfd->cFileName), wfd);
  142. }
  143. while (FindNextFileW(hFind, wfd));
  144. }
  145. __finally
  146. {
  147. FindClose(hFind);
  148. }
  149. }
  150. directory[length] = '\\';
  151. directory[length+1] = '*';
  152. directory[length+2] = 0;
  153. hFind = FindFirstFileW(directory, wfd);
  154. if (hFind != INVALID_HANDLE_VALUE)
  155. {
  156. __try
  157. {
  158. do
  159. {
  160. if (IsDotOrDotDot(wfd->cFileName))
  161. {
  162. continue;
  163. }
  164. if (!(wfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  165. {
  166. continue;
  167. }
  168. directory[length] = '\\';
  169. wcscpy(directory + length + 1, wfd->cFileName);
  170. CleanDirectory(obj, directory, length + 1 + wcslen(wfd->cFileName), wfd);
  171. } while (FindNextFileW(hFind, wfd));
  172. }
  173. __finally
  174. {
  175. FindClose(hFind);
  176. }
  177. }
  178. directory[length] = 0;
  179. }
  180. #define Lx(x) L ## x
  181. #define L(x) Lx(x)
  182. int Clean(
  183. int argc,
  184. wchar_t** argv
  185. )
  186. {
  187. Log(L"Clean version " L(__TIME__) L" " L(__DATE__));
  188. // are we running on NT?
  189. long version = GetVersion();
  190. int build = ((version >> 16) & 0x7fff);
  191. int majorVersion = (version & 0xff);
  192. bool nt = !(version & 0x80000000);
  193. if (!nt)
  194. {
  195. Fail(errorNT);
  196. }
  197. // These two buffers are shared by the whole call tree. Be careful.
  198. WIN32_FIND_DATAW wfd;
  199. wchar_t currentDirectory[1U << 15];
  200. if (argc != 2)
  201. {
  202. Log(
  203. "Usage: %ls [delete string].\n"
  204. " Typical deletion strings are obj, objd, and obj?.\n"
  205. " This will recursively delete directories matching\n"
  206. " the deletion string. It will also delete\n"
  207. " all files named build[d,fre,chk].[log,wrn,err].\n",
  208. argv[0] ? argv[0] : L"xxx.exe"
  209. );
  210. return EXIT_FAILURE;
  211. }
  212. // I prefer GetCurrentDirectory, but other programs just print '.'
  213. // if (!GetCurrentDirectoryW(NUMBER_OF(currentDirectory), currentDirectory))
  214. // {
  215. // Fail();
  216. // }
  217. currentDirectory[0] = '.';
  218. currentDirectory[1] = 0;
  219. CleanDirectory(argv[1], currentDirectory, wcslen(currentDirectory), &wfd);
  220. return EXIT_SUCCESS;
  221. }
  222. int __cdecl wmain(
  223. int argc,
  224. wchar_t** argv
  225. )
  226. {
  227. return Clean(argc, argv);
  228. }