blob: 944aea101fbe745af527153c8fbd5ce4801f4ec4 [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 Spencerd0c9e0e2004-09-18 19:29:16 +0000126static inline bool IsLibrary(Path& path, const std::string& basename) {
Reid Spencer07adb282004-11-05 22:15:36 +0000127 if (path.appendFile(std::string("lib") + basename)) {
128 if (path.appendSuffix(Path::GetDLLSuffix()) && path.readable())
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000129 return true;
Reid Spencer07adb282004-11-05 22:15:36 +0000130 else if (path.elideSuffix() && path.appendSuffix("a") && path.readable())
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000131 return true;
Reid Spencer07adb282004-11-05 22:15:36 +0000132 else if (path.elideSuffix() && path.appendSuffix("o") && path.readable())
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000133 return true;
Reid Spencer07adb282004-11-05 22:15:36 +0000134 else if (path.elideSuffix() && path.appendSuffix("bc") && path.readable())
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000135 return true;
Reid Spencer07adb282004-11-05 22:15:36 +0000136 } else if (path.elideFile() && path.appendFile(basename)) {
137 if (path.appendSuffix(Path::GetDLLSuffix()) && path.readable())
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000138 return true;
Reid Spencer07adb282004-11-05 22:15:36 +0000139 else if (path.elideSuffix() && path.appendSuffix("a") && path.readable())
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000140 return true;
Reid Spencer07adb282004-11-05 22:15:36 +0000141 else if (path.elideSuffix() && path.appendSuffix("o") && path.readable())
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000142 return true;
Reid Spencer07adb282004-11-05 22:15:36 +0000143 else if (path.elideSuffix() && path.appendSuffix("bc") && path.readable())
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000144 return true;
145 }
146 path.clear();
147 return false;
148}
149
150Path
151Path::GetLibraryPath(const std::string& basename,
152 const std::vector<std::string>& LibPaths) {
153 Path result;
154
155 // Try the paths provided
156 for (std::vector<std::string>::const_iterator I = LibPaths.begin(),
157 E = LibPaths.end(); I != E; ++I ) {
Reid Spencer07adb282004-11-05 22:15:36 +0000158 if (result.setDirectory(*I) && IsLibrary(result,basename))
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000159 return result;
160 }
161
162 // Try the LLVM lib directory in the LLVM install area
Reid Spencer07adb282004-11-05 22:15:36 +0000163 //if (result.setDirectory(LLVM_LIBDIR) && IsLibrary(result,basename))
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000164 // return result;
165
166 // Try /usr/lib
Reid Spencer07adb282004-11-05 22:15:36 +0000167 if (result.setDirectory("/usr/lib/") && IsLibrary(result,basename))
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000168 return result;
169
170 // Try /lib
Reid Spencer07adb282004-11-05 22:15:36 +0000171 if (result.setDirectory("/lib/") && IsLibrary(result,basename))
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000172 return result;
173
174 // Can't find it, give up and return invalid path.
175 result.clear();
176 return result;
177}
178
Reid Spencerb016a372004-09-15 05:49:50 +0000179Path
180Path::GetSystemLibraryPath1() {
181 return Path("/lib/");
182}
183
184Path
185Path::GetSystemLibraryPath2() {
186 return Path("/usr/lib/");
187}
188
189Path
190Path::GetLLVMDefaultConfigDir() {
191 return Path("/etc/llvm/");
192}
193
194Path
195Path::GetLLVMConfigDir() {
Reid Spencerb016a372004-09-15 05:49:50 +0000196 return GetLLVMDefaultConfigDir();
197}
198
199Path
200Path::GetUserHomeDirectory() {
201 const char* home = getenv("HOME");
202 if (home) {
203 Path result;
Reid Spencer07adb282004-11-05 22:15:36 +0000204 if (result.setDirectory(home))
Reid Spencerb016a372004-09-15 05:49:50 +0000205 return result;
206 }
207 return GetRootDirectory();
208}
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000209// FIXME: the above set of functions don't map to Windows very well.
210
211bool
Reid Spencer07adb282004-11-05 22:15:36 +0000212Path::isFile() const {
213 return (isValid() && path[path.length()-1] != '/');
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000214}
215
216bool
Reid Spencer07adb282004-11-05 22:15:36 +0000217Path::isDirectory() const {
218 return (isValid() && path[path.length()-1] == '/');
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000219}
220
221std::string
Reid Spencer07adb282004-11-05 22:15:36 +0000222Path::getBasename() const {
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000223 // Find the last slash
224 size_t slash = path.rfind('/');
225 if (slash == std::string::npos)
226 slash = 0;
227 else
228 slash++;
229
230 return path.substr(slash, path.rfind('.'));
231}
232
Reid Spencer07adb282004-11-05 22:15:36 +0000233bool Path::hasMagicNumber(const std::string &Magic) const {
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000234 size_t len = Magic.size();
235 char *buf = reinterpret_cast<char *>(_alloca(len+1));
236 std::ifstream f(path.c_str());
237 f.read(buf, len);
238 buf[len] = '\0';
239 return Magic == buf;
240}
241
242bool
Reid Spencer07adb282004-11-05 22:15:36 +0000243Path::isBytecodeFile() const {
Reid Spencer4b826812004-11-09 20:27:23 +0000244 char buffer[ 4];
245 buffer[0] = 0;
246 std::ifstream f(path.c_str());
247 f.read(buffer, 4);
248 if (f.bad())
249 ThrowErrno("can't read file signature");
250 return 0 == memcmp(buffer,"llvc",4) || 0 == memcmp(buffer,"llvm",4);
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000251}
252
253bool
Reid Spencer07adb282004-11-05 22:15:36 +0000254Path::isArchive() const {
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000255 if (readable()) {
Reid Spencer07adb282004-11-05 22:15:36 +0000256 return hasMagicNumber("!<arch>\012");
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000257 }
258 return false;
259}
Reid Spencerb016a372004-09-15 05:49:50 +0000260
261bool
262Path::exists() const {
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000263 DWORD attr = GetFileAttributes(path.c_str());
264 return attr != INVALID_FILE_ATTRIBUTES;
Reid Spencerb016a372004-09-15 05:49:50 +0000265}
266
267bool
268Path::readable() 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;
Reid Spencerb016a372004-09-15 05:49:50 +0000272}
273
274bool
275Path::writable() 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) && !(attr & FILE_ATTRIBUTE_READONLY);
Reid Spencerb016a372004-09-15 05:49:50 +0000279}
280
281bool
282Path::executable() const {
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000283 // FIXME: take security attributes into account.
284 DWORD attr = GetFileAttributes(path.c_str());
285 return attr != INVALID_FILE_ATTRIBUTES;
Reid Spencerb016a372004-09-15 05:49:50 +0000286}
287
288std::string
289Path::getLast() const {
290 // Find the last slash
291 size_t pos = path.rfind('/');
292
293 // Handle the corner cases
294 if (pos == std::string::npos)
295 return path;
296
297 // If the last character is a slash
298 if (pos == path.length()-1) {
299 // Find the second to last slash
300 size_t pos2 = path.rfind('/', pos-1);
301 if (pos2 == std::string::npos)
302 return path.substr(0,pos);
303 else
304 return path.substr(pos2+1,pos-pos2-1);
305 }
306 // Return everything after the last slash
307 return path.substr(pos+1);
308}
309
310bool
Reid Spencer07adb282004-11-05 22:15:36 +0000311Path::setDirectory(const std::string& a_path) {
Reid Spencerb016a372004-09-15 05:49:50 +0000312 if (a_path.size() == 0)
313 return false;
314 Path save(*this);
315 path = a_path;
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000316 FlipBackSlashes(path);
Reid Spencerb016a372004-09-15 05:49:50 +0000317 size_t last = a_path.size() -1;
318 if (last != 0 && a_path[last] != '/')
319 path += '/';
Reid Spencer07adb282004-11-05 22:15:36 +0000320 if (!isValid()) {
Reid Spencerb016a372004-09-15 05:49:50 +0000321 path = save.path;
322 return false;
323 }
324 return true;
325}
326
327bool
Reid Spencer07adb282004-11-05 22:15:36 +0000328Path::setFile(const std::string& a_path) {
Reid Spencerb016a372004-09-15 05:49:50 +0000329 if (a_path.size() == 0)
330 return false;
331 Path save(*this);
332 path = a_path;
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000333 FlipBackSlashes(path);
Reid Spencerb016a372004-09-15 05:49:50 +0000334 size_t last = a_path.size() - 1;
335 while (last > 0 && a_path[last] == '/')
336 last--;
337 path.erase(last+1);
Reid Spencer07adb282004-11-05 22:15:36 +0000338 if (!isValid()) {
Reid Spencerb016a372004-09-15 05:49:50 +0000339 path = save.path;
340 return false;
341 }
342 return true;
343}
344
345bool
Reid Spencer07adb282004-11-05 22:15:36 +0000346Path::appendDirectory(const std::string& dir) {
347 if (isFile())
Reid Spencerb016a372004-09-15 05:49:50 +0000348 return false;
349 Path save(*this);
350 path += dir;
351 path += "/";
Reid Spencer07adb282004-11-05 22:15:36 +0000352 if (!isValid()) {
Reid Spencerb016a372004-09-15 05:49:50 +0000353 path = save.path;
354 return false;
355 }
356 return true;
357}
358
359bool
Reid Spencer07adb282004-11-05 22:15:36 +0000360Path::elideDirectory() {
361 if (isFile())
Reid Spencerb016a372004-09-15 05:49:50 +0000362 return false;
363 size_t slashpos = path.rfind('/',path.size());
364 if (slashpos == 0 || slashpos == std::string::npos)
365 return false;
366 if (slashpos == path.size() - 1)
367 slashpos = path.rfind('/',slashpos-1);
368 if (slashpos == std::string::npos)
369 return false;
370 path.erase(slashpos);
371 return true;
372}
373
374bool
Reid Spencer07adb282004-11-05 22:15:36 +0000375Path::appendFile(const std::string& file) {
376 if (!isDirectory())
Reid Spencerb016a372004-09-15 05:49:50 +0000377 return false;
378 Path save(*this);
379 path += file;
Reid Spencer07adb282004-11-05 22:15:36 +0000380 if (!isValid()) {
Reid Spencerb016a372004-09-15 05:49:50 +0000381 path = save.path;
382 return false;
383 }
384 return true;
385}
386
387bool
Reid Spencer07adb282004-11-05 22:15:36 +0000388Path::elideFile() {
389 if (isDirectory())
Reid Spencerb016a372004-09-15 05:49:50 +0000390 return false;
391 size_t slashpos = path.rfind('/',path.size());
392 if (slashpos == std::string::npos)
393 return false;
394 path.erase(slashpos+1);
395 return true;
396}
397
398bool
Reid Spencer07adb282004-11-05 22:15:36 +0000399Path::appendSuffix(const std::string& suffix) {
400 if (isDirectory())
Reid Spencerb016a372004-09-15 05:49:50 +0000401 return false;
402 Path save(*this);
403 path.append(".");
404 path.append(suffix);
Reid Spencer07adb282004-11-05 22:15:36 +0000405 if (!isValid()) {
Reid Spencerb016a372004-09-15 05:49:50 +0000406 path = save.path;
407 return false;
408 }
409 return true;
410}
411
412bool
Reid Spencer07adb282004-11-05 22:15:36 +0000413Path::elideSuffix() {
414 if (isDirectory()) return false;
Reid Spencerb016a372004-09-15 05:49:50 +0000415 size_t dotpos = path.rfind('.',path.size());
416 size_t slashpos = path.rfind('/',path.size());
417 if (slashpos != std::string::npos && dotpos != std::string::npos &&
418 dotpos > slashpos) {
419 path.erase(dotpos, path.size()-dotpos);
420 return true;
421 }
422 return false;
423}
424
425
426bool
Reid Spencer07adb282004-11-05 22:15:36 +0000427Path::createDirectory( bool create_parents) {
Reid Spencerb016a372004-09-15 05:49:50 +0000428 // Make sure we're dealing with a directory
Reid Spencer07adb282004-11-05 22:15:36 +0000429 if (!isDirectory()) return false;
Reid Spencerb016a372004-09-15 05:49:50 +0000430
431 // Get a writeable copy of the path name
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000432 char *pathname = reinterpret_cast<char *>(_alloca(path.length()+1));
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000433 path.copy(pathname,path.length());
434 pathname[path.length()] = 0;
Reid Spencerb016a372004-09-15 05:49:50 +0000435
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000436 // Determine starting point for initial / search.
437 char *next = pathname;
438 if (pathname[0] == '/' && pathname[1] == '/') {
439 // Skip host name.
440 next = strchr(pathname+2, '/');
441 if (next == NULL)
442 throw std::string(pathname) + ": badly formed remote directory";
443 // Skip share name.
444 next = strchr(next+1, '/');
445 if (next == NULL)
446 throw std::string(pathname) + ": badly formed remote directory";
447 next++;
448 if (*next == 0)
449 throw std::string(pathname) + ": badly formed remote directory";
450 } else {
451 if (pathname[1] == ':')
452 next += 2; // skip drive letter
453 if (*next == '/')
454 next++; // skip root directory
455 }
Reid Spencerb016a372004-09-15 05:49:50 +0000456
457 // If we're supposed to create intermediate directories
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000458 if (create_parents) {
Reid Spencerb016a372004-09-15 05:49:50 +0000459 // Loop through the directory components until we're done
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000460 while (*next) {
461 next = strchr(next, '/');
Reid Spencerb016a372004-09-15 05:49:50 +0000462 *next = 0;
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000463 if (!CreateDirectory(pathname, NULL))
464 ThrowError(std::string(pathname) + ": Can't create directory: ");
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000465 *next++ = '/';
Reid Spencerb016a372004-09-15 05:49:50 +0000466 }
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000467 } else {
468 // Drop trailing slash.
469 pathname[path.size()-1] = 0;
470 if (!CreateDirectory(pathname, NULL)) {
471 ThrowError(std::string(pathname) + ": Can't create directory: ");
472 }
Reid Spencerb016a372004-09-15 05:49:50 +0000473 }
474 return true;
475}
476
477bool
Reid Spencer07adb282004-11-05 22:15:36 +0000478Path::createFile() {
Reid Spencerb016a372004-09-15 05:49:50 +0000479 // Make sure we're dealing with a file
Reid Spencer07adb282004-11-05 22:15:36 +0000480 if (!isFile()) return false;
Reid Spencerb016a372004-09-15 05:49:50 +0000481
482 // Create the file
Reid Spencer6a0ec6f2004-09-29 00:01:17 +0000483 HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW,
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000484 FILE_ATTRIBUTE_NORMAL, NULL);
485 if (h == INVALID_HANDLE_VALUE)
486 ThrowError(std::string(path.c_str()) + ": Can't create file: ");
Reid Spencerb016a372004-09-15 05:49:50 +0000487
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000488 CloseHandle(h);
Reid Spencerb016a372004-09-15 05:49:50 +0000489 return true;
490}
491
492bool
Reid Spencer07adb282004-11-05 22:15:36 +0000493Path::destroyDirectory(bool remove_contents) {
Reid Spencerb016a372004-09-15 05:49:50 +0000494 // Make sure we're dealing with a directory
Reid Spencer07adb282004-11-05 22:15:36 +0000495 if (!isDirectory()) return false;
Reid Spencerb016a372004-09-15 05:49:50 +0000496
497 // If it doesn't exist, we're done.
498 if (!exists()) return true;
499
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000500 char *pathname = reinterpret_cast<char *>(_alloca(path.length()+1));
501 path.copy(pathname,path.length()+1);
502 int lastchar = path.length() - 1 ;
503 if (pathname[lastchar] == '/')
504 pathname[lastchar] = 0;
505
Reid Spencerb016a372004-09-15 05:49:50 +0000506 if (remove_contents) {
507 // Recursively descend the directory to remove its content
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000508 // FIXME: The correct way of doing this on Windows isn't pretty...
509 // but this may work if unix-like utils are present.
510 std::string cmd("rm -rf ");
Reid Spencerb016a372004-09-15 05:49:50 +0000511 cmd += path;
512 system(cmd.c_str());
513 } else {
514 // Otherwise, try to just remove the one directory
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000515 if (!RemoveDirectory(pathname))
516 ThrowError(std::string(pathname) + ": Can't destroy directory: ");
Reid Spencerb016a372004-09-15 05:49:50 +0000517 }
518 return true;
519}
520
521bool
Reid Spencer07adb282004-11-05 22:15:36 +0000522Path::destroyFile() {
523 if (!isFile()) return false;
Reid Spencerd0c9e0e2004-09-18 19:29:16 +0000524
525 DWORD attr = GetFileAttributes(path.c_str());
526
527 // If it doesn't exist, we're done.
528 if (attr == INVALID_FILE_ATTRIBUTES)
529 return true;
530
531 // Read-only files cannot be deleted on Windows. Must remove the read-only
532 // attribute first.
533 if (attr & FILE_ATTRIBUTE_READONLY) {
534 if (!SetFileAttributes(path.c_str(), attr & ~FILE_ATTRIBUTE_READONLY))
535 ThrowError(std::string(path.c_str()) + ": Can't destroy file: ");
536 }
537
538 if (!DeleteFile(path.c_str()))
539 ThrowError(std::string(path.c_str()) + ": Can't destroy file: ");
Reid Spencerb016a372004-09-15 05:49:50 +0000540 return true;
541}
542
543}
Reid Spencercbad7012004-09-11 04:59:30 +0000544}
545
546// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab
Reid Spencerb016a372004-09-15 05:49:50 +0000547