Reapply commit 112702 which was speculatively reverted by echristo.
[oota-llvm.git] / lib / System / Unix / Path.inc
1 //===- llvm/System/Unix/Path.cpp - Unix Path Implementation -----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the Unix specific portion of the Path class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 //===----------------------------------------------------------------------===//
15 //=== WARNING: Implementation here must contain only generic UNIX code that
16 //===          is guaranteed to work on *all* UNIX variants.
17 //===----------------------------------------------------------------------===//
18
19 #include "Unix.h"
20 #if HAVE_SYS_STAT_H
21 #include <sys/stat.h>
22 #endif
23 #if HAVE_FCNTL_H
24 #include <fcntl.h>
25 #endif
26 #ifdef HAVE_SYS_MMAN_H
27 #include <sys/mman.h>
28 #endif
29 #ifdef HAVE_SYS_STAT_H
30 #include <sys/stat.h>
31 #endif
32 #if HAVE_UTIME_H
33 #include <utime.h>
34 #endif
35 #if HAVE_TIME_H
36 #include <time.h>
37 #endif
38 #if HAVE_DIRENT_H
39 # include <dirent.h>
40 # define NAMLEN(dirent) strlen((dirent)->d_name)
41 #else
42 # define dirent direct
43 # define NAMLEN(dirent) (dirent)->d_namlen
44 # if HAVE_SYS_NDIR_H
45 #  include <sys/ndir.h>
46 # endif
47 # if HAVE_SYS_DIR_H
48 #  include <sys/dir.h>
49 # endif
50 # if HAVE_NDIR_H
51 #  include <ndir.h>
52 # endif
53 #endif
54
55 #if HAVE_DLFCN_H
56 #include <dlfcn.h>
57 #endif
58
59 #ifdef __APPLE__
60 #include <mach-o/dyld.h>
61 #endif
62
63 // Put in a hack for Cygwin which falsely reports that the mkdtemp function
64 // is available when it is not.
65 #ifdef __CYGWIN__
66 # undef HAVE_MKDTEMP
67 #endif
68
69 namespace {
70 inline bool lastIsSlash(const std::string& path) {
71   return !path.empty() && path[path.length() - 1] == '/';
72 }
73
74 }
75
76 namespace llvm {
77 using namespace sys;
78
79 const char sys::PathSeparator = ':';
80
81 Path::Path(StringRef p)
82   : path(p) {}
83
84 Path::Path(const char *StrStart, unsigned StrLen)
85   : path(StrStart, StrLen) {}
86
87 Path&
88 Path::operator=(StringRef that) {
89   path.assign(that.data(), that.size());
90   return *this;
91 }
92
93 bool
94 Path::isValid() const {
95   // Check some obvious things
96   if (path.empty())
97     return false;
98   return path.length() < MAXPATHLEN;
99 }
100
101 bool
102 Path::isAbsolute(const char *NameStart, unsigned NameLen) {
103   assert(NameStart);
104   if (NameLen == 0)
105     return false;
106   return NameStart[0] == '/';
107 }
108
109 bool
110 Path::isAbsolute() const {
111   if (path.empty())
112     return false;
113   return path[0] == '/';
114 }
115
116 void Path::makeAbsolute() {
117   if (isAbsolute())
118     return;
119
120   Path CWD = Path::GetCurrentDirectory();
121   assert(CWD.isAbsolute() && "GetCurrentDirectory returned relative path!");
122
123   CWD.appendComponent(path);
124
125   path = CWD.str();
126 }
127
128 Path
129 Path::GetRootDirectory() {
130   Path result;
131   result.set("/");
132   return result;
133 }
134
135 Path
136 Path::GetTemporaryDirectory(std::string *ErrMsg) {
137 #if defined(HAVE_MKDTEMP)
138   // The best way is with mkdtemp but that's not available on many systems,
139   // Linux and FreeBSD have it. Others probably won't.
140   char pathname[MAXPATHLEN];
141   strcpy(pathname,"/tmp/llvm_XXXXXX");
142   if (0 == mkdtemp(pathname)) {
143     MakeErrMsg(ErrMsg,
144       std::string(pathname) + ": can't create temporary directory");
145     return Path();
146   }
147   Path result;
148   result.set(pathname);
149   assert(result.isValid() && "mkdtemp didn't create a valid pathname!");
150   return result;
151 #elif defined(HAVE_MKSTEMP)
152   // If no mkdtemp is available, mkstemp can be used to create a temporary file
153   // which is then removed and created as a directory. We prefer this over
154   // mktemp because of mktemp's inherent security and threading risks. We still
155   // have a slight race condition from the time the temporary file is created to
156   // the time it is re-created as a directoy.
157   char pathname[MAXPATHLEN];
158   strcpy(pathname, "/tmp/llvm_XXXXXX");
159   int fd = 0;
160   if (-1 == (fd = mkstemp(pathname))) {
161     MakeErrMsg(ErrMsg,
162       std::string(pathname) + ": can't create temporary directory");
163     return Path();
164   }
165   ::close(fd);
166   ::unlink(pathname); // start race condition, ignore errors
167   if (-1 == ::mkdir(pathname, S_IRWXU)) { // end race condition
168     MakeErrMsg(ErrMsg,
169       std::string(pathname) + ": can't create temporary directory");
170     return Path();
171   }
172   Path result;
173   result.set(pathname);
174   assert(result.isValid() && "mkstemp didn't create a valid pathname!");
175   return result;
176 #elif defined(HAVE_MKTEMP)
177   // If a system doesn't have mkdtemp(3) or mkstemp(3) but it does have
178   // mktemp(3) then we'll assume that system (e.g. AIX) has a reasonable
179   // implementation of mktemp(3) and doesn't follow BSD 4.3's lead of replacing
180   // the XXXXXX with the pid of the process and a letter. That leads to only
181   // twenty six temporary files that can be generated.
182   char pathname[MAXPATHLEN];
183   strcpy(pathname, "/tmp/llvm_XXXXXX");
184   char *TmpName = ::mktemp(pathname);
185   if (TmpName == 0) {
186     MakeErrMsg(ErrMsg,
187       std::string(TmpName) + ": can't create unique directory name");
188     return Path();
189   }
190   if (-1 == ::mkdir(TmpName, S_IRWXU)) {
191     MakeErrMsg(ErrMsg,
192         std::string(TmpName) + ": can't create temporary directory");
193     return Path();
194   }
195   Path result;
196   result.set(TmpName);
197   assert(result.isValid() && "mktemp didn't create a valid pathname!");
198   return result;
199 #else
200   // This is the worst case implementation. tempnam(3) leaks memory unless its
201   // on an SVID2 (or later) system. On BSD 4.3 it leaks. tmpnam(3) has thread
202   // issues. The mktemp(3) function doesn't have enough variability in the
203   // temporary name generated. So, we provide our own implementation that
204   // increments an integer from a random number seeded by the current time. This
205   // should be sufficiently unique that we don't have many collisions between
206   // processes. Generally LLVM processes don't run very long and don't use very
207   // many temporary files so this shouldn't be a big issue for LLVM.
208   static time_t num = ::time(0);
209   char pathname[MAXPATHLEN];
210   do {
211     num++;
212     sprintf(pathname, "/tmp/llvm_%010u", unsigned(num));
213   } while ( 0 == access(pathname, F_OK ) );
214   if (-1 == ::mkdir(pathname, S_IRWXU)) {
215     MakeErrMsg(ErrMsg,
216       std::string(pathname) + ": can't create temporary directory");
217     return Path();
218   }
219   Path result;
220   result.set(pathname);
221   assert(result.isValid() && "mkstemp didn't create a valid pathname!");
222   return result;
223 #endif
224 }
225
226 void
227 Path::GetSystemLibraryPaths(std::vector<sys::Path>& Paths) {
228 #ifdef LTDL_SHLIBPATH_VAR
229   char* env_var = getenv(LTDL_SHLIBPATH_VAR);
230   if (env_var != 0) {
231     getPathList(env_var,Paths);
232   }
233 #endif
234   // FIXME: Should this look at LD_LIBRARY_PATH too?
235   Paths.push_back(sys::Path("/usr/local/lib/"));
236   Paths.push_back(sys::Path("/usr/X11R6/lib/"));
237   Paths.push_back(sys::Path("/usr/lib/"));
238   Paths.push_back(sys::Path("/lib/"));
239 }
240
241 void
242 Path::GetBitcodeLibraryPaths(std::vector<sys::Path>& Paths) {
243   char * env_var = getenv("LLVM_LIB_SEARCH_PATH");
244   if (env_var != 0) {
245     getPathList(env_var,Paths);
246   }
247 #ifdef LLVM_LIBDIR
248   {
249     Path tmpPath;
250     if (tmpPath.set(LLVM_LIBDIR))
251       if (tmpPath.canRead())
252         Paths.push_back(tmpPath);
253   }
254 #endif
255   GetSystemLibraryPaths(Paths);
256 }
257
258 Path
259 Path::GetLLVMDefaultConfigDir() {
260   return Path("/etc/llvm/");
261 }
262
263 Path
264 Path::GetUserHomeDirectory() {
265   const char* home = getenv("HOME");
266   if (home) {
267     Path result;
268     if (result.set(home))
269       return result;
270   }
271   return GetRootDirectory();
272 }
273
274 Path
275 Path::GetCurrentDirectory() {
276   char pathname[MAXPATHLEN];
277   if (!getcwd(pathname,MAXPATHLEN)) {
278     assert (false && "Could not query current working directory.");
279     return Path();
280   }
281
282   return Path(pathname);
283 }
284
285 #if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__minix)
286 static int
287 test_dir(char buf[PATH_MAX], char ret[PATH_MAX],
288     const char *dir, const char *bin)
289 {
290   struct stat sb;
291
292   snprintf(buf, PATH_MAX, "%s/%s", dir, bin);
293   if (realpath(buf, ret) == NULL)
294     return (1);
295   if (stat(buf, &sb) != 0)
296     return (1);
297
298   return (0);
299 }
300
301 static char *
302 getprogpath(char ret[PATH_MAX], const char *bin)
303 {
304   char *pv, *s, *t, buf[PATH_MAX];
305
306   /* First approach: absolute path. */
307   if (bin[0] == '/') {
308     if (test_dir(buf, ret, "/", bin) == 0)
309       return (ret);
310     return (NULL);
311   }
312
313   /* Second approach: relative path. */
314   if (strchr(bin, '/') != NULL) {
315     if (getcwd(buf, PATH_MAX) == NULL)
316       return (NULL);
317     if (test_dir(buf, ret, buf, bin) == 0)
318       return (ret);
319     return (NULL);
320   }
321
322   /* Third approach: $PATH */
323   if ((pv = getenv("PATH")) == NULL)
324     return (NULL);
325   s = pv = strdup(pv);
326   if (pv == NULL)
327     return (NULL);
328   while ((t = strsep(&s, ":")) != NULL) {
329     if (test_dir(buf, ret, t, bin) == 0) {
330       free(pv);
331       return (ret);
332     }
333   }
334   free(pv);
335   return (NULL);
336 }
337 #endif // __FreeBSD__ || __NetBSD__
338
339 /// GetMainExecutable - Return the path to the main executable, given the
340 /// value of argv[0] from program startup.
341 Path Path::GetMainExecutable(const char *argv0, void *MainAddr) {
342 #if defined(__APPLE__)
343   // On OS X the executable path is saved to the stack by dyld. Reading it
344   // from there is much faster than calling dladdr, especially for large
345   // binaries with symbols.
346   char exe_path[MAXPATHLEN];
347   uint32_t size = sizeof(exe_path);
348   if (_NSGetExecutablePath(exe_path, &size) == 0) {
349     char link_path[MAXPATHLEN];
350     if (realpath(exe_path, link_path))
351       return Path(std::string(link_path));
352   }
353 #elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__minix)
354   char exe_path[PATH_MAX];
355
356   if (getprogpath(exe_path, argv0) != NULL)
357     return Path(std::string(exe_path));
358 #elif defined(__linux__) || defined(__CYGWIN__)
359   char exe_path[MAXPATHLEN];
360   ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path));
361   if (len >= 0)
362     return Path(std::string(exe_path, len));
363 #elif defined(HAVE_DLFCN_H)
364   // Use dladdr to get executable path if available.
365   Dl_info DLInfo;
366   int err = dladdr(MainAddr, &DLInfo);
367   if (err == 0)
368     return Path();
369
370   // If the filename is a symlink, we need to resolve and return the location of
371   // the actual executable.
372   char link_path[MAXPATHLEN];
373   if (realpath(DLInfo.dli_fname, link_path))
374     return Path(std::string(link_path));
375 #endif
376   return Path();
377 }
378
379
380 StringRef Path::getDirname() const {
381   return getDirnameCharSep(path, "/");
382 }
383
384 StringRef
385 Path::getBasename() const {
386   // Find the last slash
387   std::string::size_type slash = path.rfind('/');
388   if (slash == std::string::npos)
389     slash = 0;
390   else
391     slash++;
392
393   std::string::size_type dot = path.rfind('.');
394   if (dot == std::string::npos || dot < slash)
395     return StringRef(path).substr(slash);
396   else
397     return StringRef(path).substr(slash, dot - slash);
398 }
399
400 StringRef
401 Path::getSuffix() const {
402   // Find the last slash
403   std::string::size_type slash = path.rfind('/');
404   if (slash == std::string::npos)
405     slash = 0;
406   else
407     slash++;
408
409   std::string::size_type dot = path.rfind('.');
410   if (dot == std::string::npos || dot < slash)
411     return StringRef();
412   else
413     return StringRef(path).substr(dot + 1);
414 }
415
416 bool Path::getMagicNumber(std::string &Magic, unsigned len) const {
417   assert(len < 1024 && "Request for magic string too long");
418   char Buf[1025];
419   int fd = ::open(path.c_str(), O_RDONLY);
420   if (fd < 0)
421     return false;
422   ssize_t bytes_read = ::read(fd, Buf, len);
423   ::close(fd);
424   if (ssize_t(len) != bytes_read)
425     return false;
426   Magic.assign(Buf, len);
427   return true;
428 }
429
430 bool
431 Path::exists() const {
432   return 0 == access(path.c_str(), F_OK );
433 }
434
435 bool
436 Path::isDirectory() const {
437   struct stat buf;
438   if (0 != stat(path.c_str(), &buf))
439     return false;
440   return buf.st_mode & S_IFDIR ? true : false;
441 }
442
443 bool
444 Path::canRead() const {
445   return 0 == access(path.c_str(), R_OK);
446 }
447
448 bool
449 Path::canWrite() const {
450   return 0 == access(path.c_str(), W_OK);
451 }
452
453 bool
454 Path::isRegularFile() const {
455   // Get the status so we can determine if it's a file or directory
456   struct stat buf;
457
458   if (0 != stat(path.c_str(), &buf))
459     return false;
460
461   if (S_ISREG(buf.st_mode))
462     return true;
463
464   return false;
465 }
466
467 bool
468 Path::canExecute() const {
469   if (0 != access(path.c_str(), R_OK | X_OK ))
470     return false;
471   struct stat buf;
472   if (0 != stat(path.c_str(), &buf))
473     return false;
474   if (!S_ISREG(buf.st_mode))
475     return false;
476   return true;
477 }
478
479 StringRef
480 Path::getLast() const {
481   // Find the last slash
482   size_t pos = path.rfind('/');
483
484   // Handle the corner cases
485   if (pos == std::string::npos)
486     return path;
487
488   // If the last character is a slash
489   if (pos == path.length()-1) {
490     // Find the second to last slash
491     size_t pos2 = path.rfind('/', pos-1);
492     if (pos2 == std::string::npos)
493       return StringRef(path).substr(0,pos);
494     else
495       return StringRef(path).substr(pos2+1,pos-pos2-1);
496   }
497   // Return everything after the last slash
498   return StringRef(path).substr(pos+1);
499 }
500
501 const FileStatus *
502 PathWithStatus::getFileStatus(bool update, std::string *ErrStr) const {
503   if (!fsIsValid || update) {
504     struct stat buf;
505     if (0 != stat(path.c_str(), &buf)) {
506       MakeErrMsg(ErrStr, path + ": can't get status of file");
507       return 0;
508     }
509     status.fileSize = buf.st_size;
510     status.modTime.fromEpochTime(buf.st_mtime);
511     status.mode = buf.st_mode;
512     status.user = buf.st_uid;
513     status.group = buf.st_gid;
514     status.uniqueID = uint64_t(buf.st_ino);
515     status.isDir  = S_ISDIR(buf.st_mode);
516     status.isFile = S_ISREG(buf.st_mode);
517     fsIsValid = true;
518   }
519   return &status;
520 }
521
522 static bool AddPermissionBits(const Path &File, int bits) {
523   // Get the umask value from the operating system.  We want to use it
524   // when changing the file's permissions. Since calling umask() sets
525   // the umask and returns its old value, we must call it a second
526   // time to reset it to the user's preference.
527   int mask = umask(0777); // The arg. to umask is arbitrary.
528   umask(mask);            // Restore the umask.
529
530   // Get the file's current mode.
531   struct stat buf;
532   if (0 != stat(File.c_str(), &buf))
533     return false;
534   // Change the file to have whichever permissions bits from 'bits'
535   // that the umask would not disable.
536   if ((chmod(File.c_str(), (buf.st_mode | (bits & ~mask)))) == -1)
537       return false;
538   return true;
539 }
540
541 bool Path::makeReadableOnDisk(std::string* ErrMsg) {
542   if (!AddPermissionBits(*this, 0444))
543     return MakeErrMsg(ErrMsg, path + ": can't make file readable");
544   return false;
545 }
546
547 bool Path::makeWriteableOnDisk(std::string* ErrMsg) {
548   if (!AddPermissionBits(*this, 0222))
549     return MakeErrMsg(ErrMsg, path + ": can't make file writable");
550   return false;
551 }
552
553 bool Path::makeExecutableOnDisk(std::string* ErrMsg) {
554   if (!AddPermissionBits(*this, 0111))
555     return MakeErrMsg(ErrMsg, path + ": can't make file executable");
556   return false;
557 }
558
559 bool
560 Path::getDirectoryContents(std::set<Path>& result, std::string* ErrMsg) const {
561   DIR* direntries = ::opendir(path.c_str());
562   if (direntries == 0)
563     return MakeErrMsg(ErrMsg, path + ": can't open directory");
564
565   std::string dirPath = path;
566   if (!lastIsSlash(dirPath))
567     dirPath += '/';
568
569   result.clear();
570   struct dirent* de = ::readdir(direntries);
571   for ( ; de != 0; de = ::readdir(direntries)) {
572     if (de->d_name[0] != '.') {
573       Path aPath(dirPath + (const char*)de->d_name);
574       struct stat st;
575       if (0 != lstat(aPath.path.c_str(), &st)) {
576         if (S_ISLNK(st.st_mode))
577           continue; // dangling symlink -- ignore
578         return MakeErrMsg(ErrMsg,
579                           aPath.path +  ": can't determine file object type");
580       }
581       result.insert(aPath);
582     }
583   }
584
585   closedir(direntries);
586   return false;
587 }
588
589 bool
590 Path::set(StringRef a_path) {
591   if (a_path.empty())
592     return false;
593   std::string save(path);
594   path = a_path;
595   if (!isValid()) {
596     path = save;
597     return false;
598   }
599   return true;
600 }
601
602 bool
603 Path::appendComponent(StringRef name) {
604   if (name.empty())
605     return false;
606   std::string save(path);
607   if (!lastIsSlash(path))
608     path += '/';
609   path += name;
610   if (!isValid()) {
611     path = save;
612     return false;
613   }
614   return true;
615 }
616
617 bool
618 Path::eraseComponent() {
619   size_t slashpos = path.rfind('/',path.size());
620   if (slashpos == 0 || slashpos == std::string::npos) {
621     path.erase();
622     return true;
623   }
624   if (slashpos == path.size() - 1)
625     slashpos = path.rfind('/',slashpos-1);
626   if (slashpos == std::string::npos) {
627     path.erase();
628     return true;
629   }
630   path.erase(slashpos);
631   return true;
632 }
633
634 bool
635 Path::appendSuffix(StringRef suffix) {
636   std::string save(path);
637   path.append(".");
638   path.append(suffix);
639   if (!isValid()) {
640     path = save;
641     return false;
642   }
643   return true;
644 }
645
646 bool
647 Path::eraseSuffix() {
648   std::string save = path;
649   size_t dotpos = path.rfind('.',path.size());
650   size_t slashpos = path.rfind('/',path.size());
651   if (dotpos != std::string::npos) {
652     if (slashpos == std::string::npos || dotpos > slashpos+1) {
653       path.erase(dotpos, path.size()-dotpos);
654       return true;
655     }
656   }
657   if (!isValid())
658     path = save;
659   return false;
660 }
661
662 static bool createDirectoryHelper(char* beg, char* end, bool create_parents) {
663
664   if (access(beg, R_OK | W_OK) == 0)
665     return false;
666
667   if (create_parents) {
668
669     char* c = end;
670
671     for (; c != beg; --c)
672       if (*c == '/') {
673
674         // Recurse to handling the parent directory.
675         *c = '\0';
676         bool x = createDirectoryHelper(beg, c, create_parents);
677         *c = '/';
678
679         // Return if we encountered an error.
680         if (x)
681           return true;
682
683         break;
684       }
685   }
686
687   return mkdir(beg, S_IRWXU | S_IRWXG) != 0;
688 }
689
690 bool
691 Path::createDirectoryOnDisk( bool create_parents, std::string* ErrMsg ) {
692   // Get a writeable copy of the path name
693   char pathname[MAXPATHLEN];
694   path.copy(pathname,MAXPATHLEN);
695
696   // Null-terminate the last component
697   size_t lastchar = path.length() - 1 ;
698
699   if (pathname[lastchar] != '/')
700     ++lastchar;
701
702   pathname[lastchar] = 0;
703
704   if (createDirectoryHelper(pathname, pathname+lastchar, create_parents))
705     return MakeErrMsg(ErrMsg,
706                       std::string(pathname) + ": can't create directory");
707
708   return false;
709 }
710
711 bool
712 Path::createFileOnDisk(std::string* ErrMsg) {
713   // Create the file
714   int fd = ::creat(path.c_str(), S_IRUSR | S_IWUSR);
715   if (fd < 0)
716     return MakeErrMsg(ErrMsg, path + ": can't create file");
717   ::close(fd);
718   return false;
719 }
720
721 bool
722 Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) {
723   // Make this into a unique file name
724   if (makeUnique( reuse_current, ErrMsg ))
725     return true;
726
727   // create the file
728   int fd = ::open(path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0666);
729   if (fd < 0)
730     return MakeErrMsg(ErrMsg, path + ": can't create temporary file");
731   ::close(fd);
732   return false;
733 }
734
735 bool
736 Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const {
737   // Get the status so we can determine if it's a file or directory.
738   struct stat buf;
739   if (0 != stat(path.c_str(), &buf)) {
740     MakeErrMsg(ErrStr, path + ": can't get status of file");
741     return true;
742   }
743
744   // Note: this check catches strange situations. In all cases, LLVM should
745   // only be involved in the creation and deletion of regular files.  This
746   // check ensures that what we're trying to erase is a regular file. It
747   // effectively prevents LLVM from erasing things like /dev/null, any block
748   // special file, or other things that aren't "regular" files.
749   if (S_ISREG(buf.st_mode)) {
750     if (unlink(path.c_str()) != 0)
751       return MakeErrMsg(ErrStr, path + ": can't destroy file");
752     return false;
753   }
754
755   if (!S_ISDIR(buf.st_mode)) {
756     if (ErrStr) *ErrStr = "not a file or directory";
757     return true;
758   }
759
760   if (remove_contents) {
761     // Recursively descend the directory to remove its contents.
762     std::string cmd = "/bin/rm -rf " + path;
763     if (system(cmd.c_str()) != 0) {
764       MakeErrMsg(ErrStr, path + ": failed to recursively remove directory.");
765       return true;
766     }
767     return false;
768   }
769
770   // Otherwise, try to just remove the one directory.
771   char pathname[MAXPATHLEN];
772   path.copy(pathname, MAXPATHLEN);
773   size_t lastchar = path.length() - 1;
774   if (pathname[lastchar] == '/')
775     pathname[lastchar] = 0;
776   else
777     pathname[lastchar+1] = 0;
778
779   if (rmdir(pathname) != 0)
780     return MakeErrMsg(ErrStr,
781       std::string(pathname) + ": can't erase directory");
782   return false;
783 }
784
785 bool
786 Path::renamePathOnDisk(const Path& newName, std::string* ErrMsg) {
787   if (0 != ::rename(path.c_str(), newName.c_str()))
788     return MakeErrMsg(ErrMsg, std::string("can't rename '") + path + "' as '" +
789                newName.str() + "'");
790   return false;
791 }
792
793 bool
794 Path::setStatusInfoOnDisk(const FileStatus &si, std::string *ErrStr) const {
795   struct utimbuf utb;
796   utb.actime = si.modTime.toPosixTime();
797   utb.modtime = utb.actime;
798   if (0 != ::utime(path.c_str(),&utb))
799     return MakeErrMsg(ErrStr, path + ": can't set file modification time");
800   if (0 != ::chmod(path.c_str(),si.mode))
801     return MakeErrMsg(ErrStr, path + ": can't set mode");
802   return false;
803 }
804
805 bool
806 sys::CopyFile(const sys::Path &Dest, const sys::Path &Src, std::string* ErrMsg){
807   int inFile = -1;
808   int outFile = -1;
809   inFile = ::open(Src.c_str(), O_RDONLY);
810   if (inFile == -1)
811     return MakeErrMsg(ErrMsg, Src.str() +
812       ": can't open source file to copy");
813
814   outFile = ::open(Dest.c_str(), O_WRONLY|O_CREAT, 0666);
815   if (outFile == -1) {
816     ::close(inFile);
817     return MakeErrMsg(ErrMsg, Dest.str() +
818       ": can't create destination file for copy");
819   }
820
821   char Buffer[16*1024];
822   while (ssize_t Amt = ::read(inFile, Buffer, 16*1024)) {
823     if (Amt == -1) {
824       if (errno != EINTR && errno != EAGAIN) {
825         ::close(inFile);
826         ::close(outFile);
827         return MakeErrMsg(ErrMsg, Src.str()+": can't read source file");
828       }
829     } else {
830       char *BufPtr = Buffer;
831       while (Amt) {
832         ssize_t AmtWritten = ::write(outFile, BufPtr, Amt);
833         if (AmtWritten == -1) {
834           if (errno != EINTR && errno != EAGAIN) {
835             ::close(inFile);
836             ::close(outFile);
837             return MakeErrMsg(ErrMsg, Dest.str() +
838               ": can't write destination file");
839           }
840         } else {
841           Amt -= AmtWritten;
842           BufPtr += AmtWritten;
843         }
844       }
845     }
846   }
847   ::close(inFile);
848   ::close(outFile);
849   return false;
850 }
851
852 bool
853 Path::makeUnique(bool reuse_current, std::string* ErrMsg) {
854   if (reuse_current && !exists())
855     return false; // File doesn't exist already, just use it!
856
857   // Append an XXXXXX pattern to the end of the file for use with mkstemp,
858   // mktemp or our own implementation.
859   // This uses std::vector instead of SmallVector to avoid a dependence on
860   // libSupport. And performance isn't critical here.
861   std::vector<char> Buf;
862   Buf.resize(path.size()+8);
863   char *FNBuffer = &Buf[0];
864     path.copy(FNBuffer,path.size());
865   if (isDirectory())
866     strcpy(FNBuffer+path.size(), "/XXXXXX");
867   else
868     strcpy(FNBuffer+path.size(), "-XXXXXX");
869
870 #if defined(HAVE_MKSTEMP)
871   int TempFD;
872   if ((TempFD = mkstemp(FNBuffer)) == -1)
873     return MakeErrMsg(ErrMsg, path + ": can't make unique filename");
874
875   // We don't need to hold the temp file descriptor... we will trust that no one
876   // will overwrite/delete the file before we can open it again.
877   close(TempFD);
878
879   // Save the name
880   path = FNBuffer;
881 #elif defined(HAVE_MKTEMP)
882   // If we don't have mkstemp, use the old and obsolete mktemp function.
883   if (mktemp(FNBuffer) == 0)
884     return MakeErrMsg(ErrMsg, path + ": can't make unique filename");
885
886   // Save the name
887   path = FNBuffer;
888 #else
889   // Okay, looks like we have to do it all by our lonesome.
890   static unsigned FCounter = 0;
891   // Try to initialize with unique value.
892   if (FCounter == 0) FCounter = ((unsigned)getpid() & 0xFFFF) << 8;
893   char* pos = strstr(FNBuffer, "XXXXXX");
894   do {
895     if (++FCounter > 0xFFFFFF) {
896       return MakeErrMsg(ErrMsg,
897         path + ": can't make unique filename: too many files");
898     }
899     sprintf(pos, "%06X", FCounter);
900     path = FNBuffer;
901   } while (exists());
902   // POSSIBLE SECURITY BUG: An attacker can easily guess the name and exploit
903   // LLVM.
904 #endif
905   return false;
906 }
907
908 const char *Path::MapInFilePages(int FD, uint64_t FileSize) {
909   int Flags = MAP_PRIVATE;
910 #ifdef MAP_FILE
911   Flags |= MAP_FILE;
912 #endif
913   void *BasePtr = ::mmap(0, FileSize, PROT_READ, Flags, FD, 0);
914   if (BasePtr == MAP_FAILED)
915     return 0;
916   return (const char*)BasePtr;
917 }
918
919 void Path::UnMapFilePages(const char *BasePtr, uint64_t FileSize) {
920   ::munmap((void*)BasePtr, FileSize);
921 }
922
923 } // end llvm namespace