blob: cb4594194a848682368bd2cdd5c32eb00f2fa4e4 [file] [log] [blame]
Reid Spencerb016a372004-09-15 05:49:50 +00001//===- llvm/System/Linux/Path.cpp - Linux Path Implementation ---*- C++ -*-===//
2//
Reid Spencercbad7012004-09-11 04:59:30 +00003// The LLVM Compiler Infrastructure
4//
Reid Spencerb016a372004-09-15 05:49:50 +00005// This file was developed by Reid Spencer and is distributed under the
Reid Spencercbad7012004-09-11 04:59:30 +00006// University of Illinois Open Source License. See LICENSE.TXT for details.
Reid Spencerb016a372004-09-15 05:49:50 +00007//
8// Modified by Henrik Bach to comply with at least MinGW.
Reid Spencerd0c9e0e2004-09-18 19:29:16 +00009// Ported to Win32 by Jeff Cohen.
Reid Spencerb016a372004-09-15 05:49:50 +000010//
Reid Spencercbad7012004-09-11 04:59:30 +000011//===----------------------------------------------------------------------===//
12//
13// This file provides the Win32 specific implementation of the Path class.
14//
15//===----------------------------------------------------------------------===//
16
17//===----------------------------------------------------------------------===//
Reid Spencerb016a372004-09-15 05:49:50 +000018//=== WARNING: Implementation here must contain only generic Win32 code that
19//=== is guaranteed to work on *all* Win32 variants.
Reid Spencercbad7012004-09-11 04:59:30 +000020//===----------------------------------------------------------------------===//
21
Reid Spencerd0c9e0e2004-09-18 19:29:16 +000022#include "Win32.h"
Reid Spencerd0c9e0e2004-09-18 19:29:16 +000023#include <fstream>
24#include <malloc.h>
Reid Spencercbad7012004-09-11 04:59:30 +000025
Reid Spencer6a0ec6f2004-09-29 00:01:17 +000026static void FlipBackSlashes(std::string& s) {
27 for (size_t i = 0; i < s.size(); i++)
28 if (s[i] == '\\')
29 s[i] = '/';
30}
31
Reid Spencercbad7012004-09-11 04:59:30 +000032namespace llvm {
Reid Spencerb016a372004-09-15 05:49:50 +000033namespace sys {
Reid Spencercbad7012004-09-11 04:59:30 +000034
Reid Spencerb016a372004-09-15 05:49:50 +000035bool
Reid Spencer07adb282004-11-05 22:15:36 +000036Path::isValid() const {
Reid Spencerb016a372004-09-15 05:49:50 +000037 if (path.empty())
38 return false;
Reid Spencerd0c9e0e2004-09-18 19:29:16 +000039
Reid Spencer6a0ec6f2004-09-29 00:01:17 +000040 // If there is a colon, it must be the second character, preceded by a letter
41 // and followed by something.
42 size_t len = path.size();
43 size_t pos = path.rfind(':',len);
44 if (pos != std::string::npos) {
45 if (pos != 1 || !isalpha(path[0]) || len < 3)
46 return false;
47 }
Reid Spencerd0c9e0e2004-09-18 19:29:16 +000048
Reid Spencer6a0ec6f2004-09-29 00:01:17 +000049 // Check for illegal characters.
50 if (path.find_first_of("\\<>\"|\001\002\003\004\005\006\007\010\011\012"
51 "\013\014\015\016\017\020\021\022\023\024\025\026"
52 "\027\030\031\032\033\034\035\036\037")
53 != std::string::npos)
54 return false;
55
56 // A file or directory name may not end in a period.
57 if (path[len-1] == '.')
58 return false;
59 if (len >= 2 && path[len-2] == '.' && path[len-1] == '/')
60 return false;
61
62 // A file or directory name may not end in a space.
63 if (path[len-1] == ' ')
64 return false;
65 if (len >= 2 && path[len-2] == ' ' && path[len-1] == '/')
66 return false;
67
68 return true;
Reid Spencercbad7012004-09-11 04:59:30 +000069}
70
Reid Spencerd0c9e0e2004-09-18 19:29:16 +000071static Path *TempDirectory = NULL;
72
Reid Spencerb016a372004-09-15 05:49:50 +000073Path
74Path::GetTemporaryDirectory() {
Reid Spencerd0c9e0e2004-09-18 19:29:16 +000075 if (TempDirectory)
76 return *TempDirectory;
77
78 char pathname[MAX_PATH];
79 if (!GetTempPath(MAX_PATH, pathname))
Reid Spencer6a0ec6f2004-09-29 00:01:17 +000080 throw std::string("Can't determine temporary directory");
Reid Spencerd0c9e0e2004-09-18 19:29:16 +000081
Reid Spencerb016a372004-09-15 05:49:50 +000082 Path result;
Reid Spencer07adb282004-11-05 22:15:36 +000083 result.setDirectory(pathname);
Reid Spencerd0c9e0e2004-09-18 19:29:16 +000084
85 // Append a subdirectory passed on our process id so multiple LLVMs don't
86 // step on each other's toes.
87 sprintf(pathname, "LLVM_%u", GetCurrentProcessId());
Reid Spencer07adb282004-11-05 22:15:36 +000088 result.appendDirectory(pathname);
Reid Spencerd0c9e0e2004-09-18 19:29:16 +000089
90 // If there's a directory left over from a previous LLVM execution that
91 // happened to have the same process id, get rid of it.
Reid Spencer07adb282004-11-05 22:15:36 +000092 result.destroyDirectory(true);
Reid Spencerd0c9e0e2004-09-18 19:29:16 +000093
94 // And finally (re-)create the empty directory.
Reid Spencer07adb282004-11-05 22:15:36 +000095 result.createDirectory(false);
Reid Spencerd0c9e0e2004-09-18 19:29:16 +000096 TempDirectory = new Path(result);
97 return *TempDirectory;
Reid Spencerb016a372004-09-15 05:49:50 +000098}
99
100Path::Path(std::string unverified_path)
101 : path(unverified_path)
102{
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000103 FlipBackSlashes(path);
Reid Spencerb016a372004-09-15 05:49:50 +0000104 if (unverified_path.empty())
105 return;
Reid Spencer07adb282004-11-05 22:15:36 +0000106 if (this->isValid())
Reid Spencerb016a372004-09-15 05:49:50 +0000107 return;
108 // oops, not valid.
109 path.clear();
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000110 throw std::string(unverified_path + ": path is not valid");
Reid Spencerb016a372004-09-15 05:49:50 +0000111}
112
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000113// FIXME: the following set of functions don't map to Windows very well.
Reid Spencerb016a372004-09-15 05:49:50 +0000114Path
115Path::GetRootDirectory() {
116 Path result;
Reid Spencer07adb282004-11-05 22:15:36 +0000117 result.setDirectory("/");
Reid Spencerb016a372004-09-15 05:49:50 +0000118 return result;
119}
120
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000121std::string
122Path::GetDLLSuffix() {
123 return "dll";
124}
125
Reid Spencer6c4b7bd2004-12-13 03:03:42 +0000126static void getPathList(const char*path, std::vector<sys::Path>& Paths) {
127 const char* at = path;
128 const char* delim = strchr(at, ';');
129 Path tmpPath;
130 while( delim != 0 ) {
131 std::string tmp(at, size_t(delim-at));
132 if (tmpPath.setDirectory(tmp))
133 if (tmpPath.readable())
134 Paths.push_back(tmpPath);
135 at = delim + 1;
136 delim = strchr(at, ';');
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000137 }
Reid Spencer6c4b7bd2004-12-13 03:03:42 +0000138 if (*at != 0)
139 if (tmpPath.setDirectory(std::string(at)))
140 if (tmpPath.readable())
141 Paths.push_back(tmpPath);
142
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000143}
144
Reid Spencer6c4b7bd2004-12-13 03:03:42 +0000145void
146Path::GetSystemLibraryPaths(std::vector<sys::Path>& Paths) {
147#ifdef LTDL_SHLIBPATH_VAR
148 char* env_var = getenv(LTDL_SHLIBPATH_VAR);
149 if (env_var != 0) {
150 getPathList(env_var,Paths);
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000151 }
Reid Spencer6c4b7bd2004-12-13 03:03:42 +0000152#endif
153 // FIXME: Should this look at LD_LIBRARY_PATH too?
154 Paths.push_back(sys::Path("C:\\WINDOWS\\SYSTEM32\\"));
155 Paths.push_back(sys::Path("C:\\WINDOWS\\"));
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000156}
157
Reid Spencer6c4b7bd2004-12-13 03:03:42 +0000158void
159Path::GetBytecodeLibraryPaths(std::vector<sys::Path>& Paths) {
160 char * env_var = getenv("LLVM_LIB_SEARCH_PATH");
161 if (env_var != 0) {
162 getPathList(env_var,Paths);
163 }
164#ifdef LLVMGCCDIR
165 {
166 Path tmpPath(std::string(LLVMGCCDIR) + "bytecode-libs/");
167 if (tmpPath.readable())
168 Paths.push_back(tmpPath);
169 }
170#endif
171#ifdef LLVM_LIBDIR
172 {
173 Path tmpPath;
174 if (tmpPath.setDirectory(LLVM_LIBDIR))
175 if (tmpPath.readable())
176 Paths.push_back(tmpPath);
177 }
178#endif
179 GetSystemLibraryPaths(Paths);
Reid Spencerb016a372004-09-15 05:49:50 +0000180}
181
182Path
183Path::GetLLVMDefaultConfigDir() {
184 return Path("/etc/llvm/");
185}
186
187Path
188Path::GetLLVMConfigDir() {
Reid Spencerb016a372004-09-15 05:49:50 +0000189 return GetLLVMDefaultConfigDir();
190}
191
192Path
193Path::GetUserHomeDirectory() {
194 const char* home = getenv("HOME");
195 if (home) {
196 Path result;
Reid Spencer07adb282004-11-05 22:15:36 +0000197 if (result.setDirectory(home))
Reid Spencerb016a372004-09-15 05:49:50 +0000198 return result;
199 }
200 return GetRootDirectory();
201}
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000202// FIXME: the above set of functions don't map to Windows very well.
203
204bool
Reid Spencer07adb282004-11-05 22:15:36 +0000205Path::isFile() const {
206 return (isValid() && path[path.length()-1] != '/');
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000207}
208
209bool
Reid Spencer07adb282004-11-05 22:15:36 +0000210Path::isDirectory() const {
211 return (isValid() && path[path.length()-1] == '/');
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000212}
213
214std::string
Reid Spencer07adb282004-11-05 22:15:36 +0000215Path::getBasename() const {
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000216 // Find the last slash
217 size_t slash = path.rfind('/');
218 if (slash == std::string::npos)
219 slash = 0;
220 else
221 slash++;
222
223 return path.substr(slash, path.rfind('.'));
224}
225
Reid Spencer07adb282004-11-05 22:15:36 +0000226bool Path::hasMagicNumber(const std::string &Magic) const {
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000227 size_t len = Magic.size();
228 char *buf = reinterpret_cast<char *>(_alloca(len+1));
229 std::ifstream f(path.c_str());
230 f.read(buf, len);
231 buf[len] = '\0';
232 return Magic == buf;
233}
234
235bool
Reid Spencer07adb282004-11-05 22:15:36 +0000236Path::isBytecodeFile() const {
Reid Spencer4b826812004-11-09 20:27:23 +0000237 char buffer[ 4];
238 buffer[0] = 0;
239 std::ifstream f(path.c_str());
240 f.read(buffer, 4);
241 if (f.bad())
242 ThrowErrno("can't read file signature");
243 return 0 == memcmp(buffer,"llvc",4) || 0 == memcmp(buffer,"llvm",4);
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000244}
245
246bool
Reid Spencer07adb282004-11-05 22:15:36 +0000247Path::isArchive() const {
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000248 if (readable()) {
Reid Spencer07adb282004-11-05 22:15:36 +0000249 return hasMagicNumber("!<arch>\012");
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000250 }
251 return false;
252}
Reid Spencerb016a372004-09-15 05:49:50 +0000253
254bool
255Path::exists() const {
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000256 DWORD attr = GetFileAttributes(path.c_str());
257 return attr != INVALID_FILE_ATTRIBUTES;
Reid Spencerb016a372004-09-15 05:49:50 +0000258}
259
260bool
261Path::readable() const {
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000262 // FIXME: take security attributes into account.
263 DWORD attr = GetFileAttributes(path.c_str());
264 return attr != INVALID_FILE_ATTRIBUTES;
Reid Spencerb016a372004-09-15 05:49:50 +0000265}
266
267bool
268Path::writable() const {
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000269 // FIXME: take security attributes into account.
270 DWORD attr = GetFileAttributes(path.c_str());
271 return (attr != INVALID_FILE_ATTRIBUTES) && !(attr & FILE_ATTRIBUTE_READONLY);
Reid Spencerb016a372004-09-15 05:49:50 +0000272}
273
274bool
275Path::executable() const {
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000276 // FIXME: take security attributes into account.
277 DWORD attr = GetFileAttributes(path.c_str());
278 return attr != INVALID_FILE_ATTRIBUTES;
Reid Spencerb016a372004-09-15 05:49:50 +0000279}
280
281std::string
282Path::getLast() const {
283 // Find the last slash
284 size_t pos = path.rfind('/');
285
286 // Handle the corner cases
287 if (pos == std::string::npos)
288 return path;
289
290 // If the last character is a slash
291 if (pos == path.length()-1) {
292 // Find the second to last slash
293 size_t pos2 = path.rfind('/', pos-1);
294 if (pos2 == std::string::npos)
295 return path.substr(0,pos);
296 else
297 return path.substr(pos2+1,pos-pos2-1);
298 }
299 // Return everything after the last slash
300 return path.substr(pos+1);
301}
302
303bool
Reid Spencer07adb282004-11-05 22:15:36 +0000304Path::setDirectory(const std::string& a_path) {
Reid Spencerb016a372004-09-15 05:49:50 +0000305 if (a_path.size() == 0)
306 return false;
307 Path save(*this);
308 path = a_path;
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000309 FlipBackSlashes(path);
Reid Spencerb016a372004-09-15 05:49:50 +0000310 size_t last = a_path.size() -1;
311 if (last != 0 && a_path[last] != '/')
312 path += '/';
Reid Spencer07adb282004-11-05 22:15:36 +0000313 if (!isValid()) {
Reid Spencerb016a372004-09-15 05:49:50 +0000314 path = save.path;
315 return false;
316 }
317 return true;
318}
319
320bool
Reid Spencer07adb282004-11-05 22:15:36 +0000321Path::setFile(const std::string& a_path) {
Reid Spencerb016a372004-09-15 05:49:50 +0000322 if (a_path.size() == 0)
323 return false;
324 Path save(*this);
325 path = a_path;
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000326 FlipBackSlashes(path);
Reid Spencerb016a372004-09-15 05:49:50 +0000327 size_t last = a_path.size() - 1;
328 while (last > 0 && a_path[last] == '/')
329 last--;
330 path.erase(last+1);
Reid Spencer07adb282004-11-05 22:15:36 +0000331 if (!isValid()) {
Reid Spencerb016a372004-09-15 05:49:50 +0000332 path = save.path;
333 return false;
334 }
335 return true;
336}
337
338bool
Reid Spencer07adb282004-11-05 22:15:36 +0000339Path::appendDirectory(const std::string& dir) {
340 if (isFile())
Reid Spencerb016a372004-09-15 05:49:50 +0000341 return false;
342 Path save(*this);
343 path += dir;
344 path += "/";
Reid Spencer07adb282004-11-05 22:15:36 +0000345 if (!isValid()) {
Reid Spencerb016a372004-09-15 05:49:50 +0000346 path = save.path;
347 return false;
348 }
349 return true;
350}
351
352bool
Reid Spencer07adb282004-11-05 22:15:36 +0000353Path::elideDirectory() {
354 if (isFile())
Reid Spencerb016a372004-09-15 05:49:50 +0000355 return false;
356 size_t slashpos = path.rfind('/',path.size());
357 if (slashpos == 0 || slashpos == std::string::npos)
358 return false;
359 if (slashpos == path.size() - 1)
360 slashpos = path.rfind('/',slashpos-1);
361 if (slashpos == std::string::npos)
362 return false;
363 path.erase(slashpos);
364 return true;
365}
366
367bool
Reid Spencer07adb282004-11-05 22:15:36 +0000368Path::appendFile(const std::string& file) {
369 if (!isDirectory())
Reid Spencerb016a372004-09-15 05:49:50 +0000370 return false;
371 Path save(*this);
372 path += file;
Reid Spencer07adb282004-11-05 22:15:36 +0000373 if (!isValid()) {
Reid Spencerb016a372004-09-15 05:49:50 +0000374 path = save.path;
375 return false;
376 }
377 return true;
378}
379
380bool
Reid Spencer07adb282004-11-05 22:15:36 +0000381Path::elideFile() {
382 if (isDirectory())
Reid Spencerb016a372004-09-15 05:49:50 +0000383 return false;
384 size_t slashpos = path.rfind('/',path.size());
385 if (slashpos == std::string::npos)
386 return false;
387 path.erase(slashpos+1);
388 return true;
389}
390
391bool
Reid Spencer07adb282004-11-05 22:15:36 +0000392Path::appendSuffix(const std::string& suffix) {
393 if (isDirectory())
Reid Spencerb016a372004-09-15 05:49:50 +0000394 return false;
395 Path save(*this);
396 path.append(".");
397 path.append(suffix);
Reid Spencer07adb282004-11-05 22:15:36 +0000398 if (!isValid()) {
Reid Spencerb016a372004-09-15 05:49:50 +0000399 path = save.path;
400 return false;
401 }
402 return true;
403}
404
405bool
Reid Spencer07adb282004-11-05 22:15:36 +0000406Path::elideSuffix() {
407 if (isDirectory()) return false;
Reid Spencerb016a372004-09-15 05:49:50 +0000408 size_t dotpos = path.rfind('.',path.size());
409 size_t slashpos = path.rfind('/',path.size());
410 if (slashpos != std::string::npos && dotpos != std::string::npos &&
411 dotpos > slashpos) {
412 path.erase(dotpos, path.size()-dotpos);
413 return true;
414 }
415 return false;
416}
417
418
419bool
Reid Spencer07adb282004-11-05 22:15:36 +0000420Path::createDirectory( bool create_parents) {
Reid Spencerb016a372004-09-15 05:49:50 +0000421 // Make sure we're dealing with a directory
Reid Spencer07adb282004-11-05 22:15:36 +0000422 if (!isDirectory()) return false;
Reid Spencerb016a372004-09-15 05:49:50 +0000423
424 // Get a writeable copy of the path name
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000425 char *pathname = reinterpret_cast<char *>(_alloca(path.length()+1));
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000426 path.copy(pathname,path.length());
427 pathname[path.length()] = 0;
Reid Spencerb016a372004-09-15 05:49:50 +0000428
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000429 // Determine starting point for initial / search.
430 char *next = pathname;
431 if (pathname[0] == '/' && pathname[1] == '/') {
432 // Skip host name.
433 next = strchr(pathname+2, '/');
434 if (next == NULL)
435 throw std::string(pathname) + ": badly formed remote directory";
436 // Skip share name.
437 next = strchr(next+1, '/');
438 if (next == NULL)
439 throw std::string(pathname) + ": badly formed remote directory";
440 next++;
441 if (*next == 0)
442 throw std::string(pathname) + ": badly formed remote directory";
443 } else {
444 if (pathname[1] == ':')
445 next += 2; // skip drive letter
446 if (*next == '/')
447 next++; // skip root directory
448 }
Reid Spencerb016a372004-09-15 05:49:50 +0000449
450 // If we're supposed to create intermediate directories
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000451 if (create_parents) {
Reid Spencerb016a372004-09-15 05:49:50 +0000452 // Loop through the directory components until we're done
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000453 while (*next) {
454 next = strchr(next, '/');
Reid Spencerb016a372004-09-15 05:49:50 +0000455 *next = 0;
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000456 if (!CreateDirectory(pathname, NULL))
457 ThrowError(std::string(pathname) + ": Can't create directory: ");
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000458 *next++ = '/';
Reid Spencerb016a372004-09-15 05:49:50 +0000459 }
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000460 } else {
461 // Drop trailing slash.
462 pathname[path.size()-1] = 0;
463 if (!CreateDirectory(pathname, NULL)) {
464 ThrowError(std::string(pathname) + ": Can't create directory: ");
465 }
Reid Spencerb016a372004-09-15 05:49:50 +0000466 }
467 return true;
468}
469
470bool
Reid Spencer07adb282004-11-05 22:15:36 +0000471Path::createFile() {
Reid Spencerb016a372004-09-15 05:49:50 +0000472 // Make sure we're dealing with a file
Reid Spencer07adb282004-11-05 22:15:36 +0000473 if (!isFile()) return false;
Reid Spencerb016a372004-09-15 05:49:50 +0000474
475 // Create the file
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000476 HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW,
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000477 FILE_ATTRIBUTE_NORMAL, NULL);
478 if (h == INVALID_HANDLE_VALUE)
479 ThrowError(std::string(path.c_str()) + ": Can't create file: ");
Reid Spencerb016a372004-09-15 05:49:50 +0000480
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000481 CloseHandle(h);
Reid Spencerb016a372004-09-15 05:49:50 +0000482 return true;
483}
484
485bool
Reid Spencer07adb282004-11-05 22:15:36 +0000486Path::destroyDirectory(bool remove_contents) {
Reid Spencerb016a372004-09-15 05:49:50 +0000487 // Make sure we're dealing with a directory
Reid Spencer07adb282004-11-05 22:15:36 +0000488 if (!isDirectory()) return false;
Reid Spencerb016a372004-09-15 05:49:50 +0000489
490 // If it doesn't exist, we're done.
491 if (!exists()) return true;
492
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000493 char *pathname = reinterpret_cast<char *>(_alloca(path.length()+1));
494 path.copy(pathname,path.length()+1);
495 int lastchar = path.length() - 1 ;
496 if (pathname[lastchar] == '/')
497 pathname[lastchar] = 0;
498
Reid Spencerb016a372004-09-15 05:49:50 +0000499 if (remove_contents) {
500 // Recursively descend the directory to remove its content
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000501 // FIXME: The correct way of doing this on Windows isn't pretty...
502 // but this may work if unix-like utils are present.
503 std::string cmd("rm -rf ");
Reid Spencerb016a372004-09-15 05:49:50 +0000504 cmd += path;
505 system(cmd.c_str());
506 } else {
507 // Otherwise, try to just remove the one directory
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000508 if (!RemoveDirectory(pathname))
509 ThrowError(std::string(pathname) + ": Can't destroy directory: ");
Reid Spencerb016a372004-09-15 05:49:50 +0000510 }
511 return true;
512}
513
514bool
Reid Spencer07adb282004-11-05 22:15:36 +0000515Path::destroyFile() {
516 if (!isFile()) return false;
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000517
518 DWORD attr = GetFileAttributes(path.c_str());
519
520 // If it doesn't exist, we're done.
521 if (attr == INVALID_FILE_ATTRIBUTES)
522 return true;
523
524 // Read-only files cannot be deleted on Windows. Must remove the read-only
525 // attribute first.
526 if (attr & FILE_ATTRIBUTE_READONLY) {
527 if (!SetFileAttributes(path.c_str(), attr & ~FILE_ATTRIBUTE_READONLY))
528 ThrowError(std::string(path.c_str()) + ": Can't destroy file: ");
529 }
530
531 if (!DeleteFile(path.c_str()))
532 ThrowError(std::string(path.c_str()) + ": Can't destroy file: ");
Reid Spencerb016a372004-09-15 05:49:50 +0000533 return true;
534}
535
536}
Reid Spencercbad7012004-09-11 04:59:30 +0000537}
538
539// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab
Reid Spencerb016a372004-09-15 05:49:50 +0000540