Implement Path::MapInFilePages/UnMapFilePages on unix, which
[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 "llvm/Config/alloca.h"
20 #include "Unix.h"
21 #if HAVE_SYS_STAT_H
22 #include <sys/stat.h>
23 #endif
24 #if HAVE_FCNTL_H
25 #include <fcntl.h>
26 #endif
27 #if HAVE_UTIME_H
28 #include <utime.h>
29 #endif
30 #if HAVE_TIME_H
31 #include <time.h>
32 #endif
33 #if HAVE_DIRENT_H
34 # include <dirent.h>
35 # define NAMLEN(dirent) strlen((dirent)->d_name)
36 #else
37 # define dirent direct
38 # define NAMLEN(dirent) (dirent)->d_namlen
39 # if HAVE_SYS_NDIR_H
40 #  include <sys/ndir.h>
41 # endif
42 # if HAVE_SYS_DIR_H
43 #  include <sys/dir.h>
44 # endif
45 # if HAVE_NDIR_H
46 #  include <ndir.h>
47 # endif
48 #endif
49
50 #if HAVE_DLFCN_H
51 #include <dlfcn.h>
52 #endif
53
54 // Put in a hack for Cygwin which falsely reports that the mkdtemp function
55 // is available when it is not.
56 #ifdef __CYGWIN__
57 # undef HAVE_MKDTEMP
58 #endif
59
60 namespace {
61 inline bool lastIsSlash(const std::string& path) {
62   return !path.empty() && path[path.length() - 1] == '/';
63 }
64
65 }
66
67 namespace llvm {
68 using namespace sys;
69
70 extern const char sys::PathSeparator = ':';
71
72 bool 
73 Path::isValid() const {
74   // Check some obvious things
75   if (path.empty()) 
76     return false;
77   else if (path.length() >= MAXPATHLEN)
78     return false;
79
80   // Check that the characters are ascii chars
81   size_t len = path.length();
82   unsigned i = 0;
83   while (i < len && isascii(path[i])) 
84     ++i;
85   return i >= len; 
86 }
87
88 bool 
89 Path::isAbsolute() const {
90   if (path.empty())
91     return false;
92   return path[0] == '/';
93
94 Path
95 Path::GetRootDirectory() {
96   Path result;
97   result.set("/");
98   return result;
99 }
100
101 Path
102 Path::GetTemporaryDirectory(std::string* ErrMsg ) {
103 #if defined(HAVE_MKDTEMP)
104   // The best way is with mkdtemp but that's not available on many systems, 
105   // Linux and FreeBSD have it. Others probably won't.
106   char pathname[MAXPATHLEN];
107   strcpy(pathname,"/tmp/llvm_XXXXXX");
108   if (0 == mkdtemp(pathname)) {
109     MakeErrMsg(ErrMsg, 
110       std::string(pathname) + ": can't create temporary directory");
111     return Path();
112   }
113   Path result;
114   result.set(pathname);
115   assert(result.isValid() && "mkdtemp didn't create a valid pathname!");
116   return result;
117 #elif defined(HAVE_MKSTEMP)
118   // If no mkdtemp is available, mkstemp can be used to create a temporary file
119   // which is then removed and created as a directory. We prefer this over
120   // mktemp because of mktemp's inherent security and threading risks. We still
121   // have a slight race condition from the time the temporary file is created to
122   // the time it is re-created as a directoy. 
123   char pathname[MAXPATHLEN];
124   strcpy(pathname, "/tmp/llvm_XXXXXX");
125   int fd = 0;
126   if (-1 == (fd = mkstemp(pathname))) {
127     MakeErrMsg(ErrMsg, 
128       std::string(pathname) + ": can't create temporary directory");
129     return Path();
130   }
131   ::close(fd);
132   ::unlink(pathname); // start race condition, ignore errors
133   if (-1 == ::mkdir(pathname, S_IRWXU)) { // end race condition
134     MakeErrMsg(ErrMsg, 
135       std::string(pathname) + ": can't create temporary directory");
136     return Path();
137   }
138   Path result;
139   result.set(pathname);
140   assert(result.isValid() && "mkstemp didn't create a valid pathname!");
141   return result;
142 #elif defined(HAVE_MKTEMP)
143   // If a system doesn't have mkdtemp(3) or mkstemp(3) but it does have
144   // mktemp(3) then we'll assume that system (e.g. AIX) has a reasonable
145   // implementation of mktemp(3) and doesn't follow BSD 4.3's lead of replacing
146   // the XXXXXX with the pid of the process and a letter. That leads to only
147   // twenty six temporary files that can be generated.
148   char pathname[MAXPATHLEN];
149   strcpy(pathname, "/tmp/llvm_XXXXXX");
150   char *TmpName = ::mktemp(pathname);
151   if (TmpName == 0) {
152     MakeErrMsg(ErrMsg, 
153       std::string(TmpName) + ": can't create unique directory name");
154     return Path();
155   }
156   if (-1 == ::mkdir(TmpName, S_IRWXU)) {
157     MakeErrMsg(ErrMsg, 
158         std::string(TmpName) + ": can't create temporary directory");
159     return Path();
160   }
161   Path result;
162   result.set(TmpName);
163   assert(result.isValid() && "mktemp didn't create a valid pathname!");
164   return result;
165 #else
166   // This is the worst case implementation. tempnam(3) leaks memory unless its
167   // on an SVID2 (or later) system. On BSD 4.3 it leaks. tmpnam(3) has thread
168   // issues. The mktemp(3) function doesn't have enough variability in the
169   // temporary name generated. So, we provide our own implementation that 
170   // increments an integer from a random number seeded by the current time. This
171   // should be sufficiently unique that we don't have many collisions between
172   // processes. Generally LLVM processes don't run very long and don't use very
173   // many temporary files so this shouldn't be a big issue for LLVM.
174   static time_t num = ::time(0);
175   char pathname[MAXPATHLEN];
176   do {
177     num++;
178     sprintf(pathname, "/tmp/llvm_%010u", unsigned(num));
179   } while ( 0 == access(pathname, F_OK ) );
180   if (-1 == ::mkdir(pathname, S_IRWXU)) {
181     MakeErrMsg(ErrMsg, 
182       std::string(pathname) + ": can't create temporary directory");
183     return Path();
184   }
185   Path result;
186   result.set(pathname);
187   assert(result.isValid() && "mkstemp didn't create a valid pathname!");
188   return result;
189 #endif
190 }
191
192 void 
193 Path::GetSystemLibraryPaths(std::vector<sys::Path>& Paths) {
194 #ifdef LTDL_SHLIBPATH_VAR
195   char* env_var = getenv(LTDL_SHLIBPATH_VAR);
196   if (env_var != 0) {
197     getPathList(env_var,Paths);
198   }
199 #endif
200   // FIXME: Should this look at LD_LIBRARY_PATH too?
201   Paths.push_back(sys::Path("/usr/local/lib/"));
202   Paths.push_back(sys::Path("/usr/X11R6/lib/"));
203   Paths.push_back(sys::Path("/usr/lib/"));
204   Paths.push_back(sys::Path("/lib/"));
205 }
206
207 void
208 Path::GetBitcodeLibraryPaths(std::vector<sys::Path>& Paths) {
209   char * env_var = getenv("LLVM_LIB_SEARCH_PATH");
210   if (env_var != 0) {
211     getPathList(env_var,Paths);
212   }
213 #ifdef LLVM_LIBDIR
214   {
215     Path tmpPath;
216     if (tmpPath.set(LLVM_LIBDIR))
217       if (tmpPath.canRead())
218         Paths.push_back(tmpPath);
219   }
220 #endif
221   GetSystemLibraryPaths(Paths);
222 }
223
224 Path 
225 Path::GetLLVMDefaultConfigDir() {
226   return Path("/etc/llvm/");
227 }
228
229 Path
230 Path::GetUserHomeDirectory() {
231   const char* home = getenv("HOME");
232   if (home) {
233     Path result;
234     if (result.set(home))
235       return result;
236   }
237   return GetRootDirectory();
238 }
239
240 Path
241 Path::GetCurrentDirectory() {
242   char pathname[MAXPATHLEN];
243   if (!getcwd(pathname,MAXPATHLEN)) {
244     assert (false && "Could not query current working directory.");
245     return Path("");
246   }
247   
248   return Path(pathname);
249 }
250
251 /// GetMainExecutable - Return the path to the main executable, given the
252 /// value of argv[0] from program startup.
253 Path Path::GetMainExecutable(const char *argv0, void *MainAddr) {
254 #if defined(__CYGWIN__)
255   char exe_link[64];
256   snprintf(exe_link, sizeof(exe_link), "/proc/%d/exe", getpid());
257   char exe_path[MAXPATHLEN];
258   ssize_t len = readlink(exe_link, exe_path, sizeof(exe_path));
259   if (len > 0 && len < MAXPATHLEN - 1) {
260     exe_path[len] = '\0';
261     return Path(std::string(exe_path));
262   }
263 #elif defined(HAVE_DLFCN_H)
264   // Use dladdr to get executable path if available.
265   Dl_info DLInfo;
266   int err = dladdr(MainAddr, &DLInfo);
267   if (err != 0)
268     return Path(std::string(DLInfo.dli_fname));
269 #endif
270   return Path();
271 }
272
273
274 std::string
275 Path::getBasename() const {
276   // Find the last slash
277   size_t slash = path.rfind('/');
278   if (slash == std::string::npos)
279     slash = 0;
280   else
281     slash++;
282
283   size_t dot = path.rfind('.');
284   if (dot == std::string::npos || dot < slash)
285     return path.substr(slash);
286   else
287     return path.substr(slash, dot - slash);
288 }
289
290 bool Path::getMagicNumber(std::string& Magic, unsigned len) const {
291   assert(len < 1024 && "Request for magic string too long");
292   char* buf = (char*) alloca(1 + len);
293   int fd = ::open(path.c_str(), O_RDONLY);
294   if (fd < 0)
295     return false;
296   ssize_t bytes_read = ::read(fd, buf, len);
297   ::close(fd);
298   if (ssize_t(len) != bytes_read) {
299     Magic.clear();
300     return false;
301   }
302   Magic.assign(buf,len);
303   return true;
304 }
305
306 bool
307 Path::exists() const {
308   return 0 == access(path.c_str(), F_OK );
309 }
310
311 bool
312 Path::isDirectory() const {
313   struct stat buf;
314   if (0 != stat(path.c_str(), &buf))
315     return false;
316   return buf.st_mode & S_IFDIR ? true : false;
317 }
318
319 bool
320 Path::canRead() const {
321   return 0 == access(path.c_str(), F_OK | R_OK );
322 }
323
324 bool
325 Path::canWrite() const {
326   return 0 == access(path.c_str(), F_OK | W_OK );
327 }
328
329 bool
330 Path::canExecute() const {
331   if (0 != access(path.c_str(), R_OK | X_OK ))
332     return false;
333   struct stat buf;
334   if (0 != stat(path.c_str(), &buf))
335     return false;
336   if (!S_ISREG(buf.st_mode))
337     return false;
338   return true;
339 }
340
341 std::string 
342 Path::getLast() const {
343   // Find the last slash
344   size_t pos = path.rfind('/');
345
346   // Handle the corner cases
347   if (pos == std::string::npos)
348     return path;
349
350   // If the last character is a slash
351   if (pos == path.length()-1) {
352     // Find the second to last slash
353     size_t pos2 = path.rfind('/', pos-1);
354     if (pos2 == std::string::npos)
355       return path.substr(0,pos);
356     else
357       return path.substr(pos2+1,pos-pos2-1);
358   }
359   // Return everything after the last slash
360   return path.substr(pos+1);
361 }
362
363 const FileStatus *
364 PathWithStatus::getFileStatus(bool update, std::string *ErrStr) const {
365   if (!fsIsValid || update) {
366     struct stat buf;
367     if (0 != stat(path.c_str(), &buf)) {
368       MakeErrMsg(ErrStr, path + ": can't get status of file");
369       return 0;
370     }
371     status.fileSize = buf.st_size;
372     status.modTime.fromEpochTime(buf.st_mtime);
373     status.mode = buf.st_mode;
374     status.user = buf.st_uid;
375     status.group = buf.st_gid;
376     status.uniqueID = uint64_t(buf.st_ino);
377     status.isDir  = S_ISDIR(buf.st_mode);
378     status.isFile = S_ISREG(buf.st_mode);
379     fsIsValid = true;
380   }
381   return &status;
382 }
383
384 static bool AddPermissionBits(const Path &File, int bits) {
385   // Get the umask value from the operating system.  We want to use it
386   // when changing the file's permissions. Since calling umask() sets
387   // the umask and returns its old value, we must call it a second
388   // time to reset it to the user's preference.
389   int mask = umask(0777); // The arg. to umask is arbitrary.
390   umask(mask);            // Restore the umask.
391
392   // Get the file's current mode.
393   struct stat buf;
394   if (0 != stat(File.toString().c_str(), &buf)) 
395     return false;
396   // Change the file to have whichever permissions bits from 'bits'
397   // that the umask would not disable.
398   if ((chmod(File.c_str(), (buf.st_mode | (bits & ~mask)))) == -1)
399       return false;
400   return true;
401 }
402
403 bool Path::makeReadableOnDisk(std::string* ErrMsg) {
404   if (!AddPermissionBits(*this, 0444)) 
405     return MakeErrMsg(ErrMsg, path + ": can't make file readable");
406   return false;
407 }
408
409 bool Path::makeWriteableOnDisk(std::string* ErrMsg) {
410   if (!AddPermissionBits(*this, 0222))
411     return MakeErrMsg(ErrMsg, path + ": can't make file writable");
412   return false;
413 }
414
415 bool Path::makeExecutableOnDisk(std::string* ErrMsg) {
416   if (!AddPermissionBits(*this, 0111))
417     return MakeErrMsg(ErrMsg, path + ": can't make file executable");
418   return false;
419 }
420
421 bool
422 Path::getDirectoryContents(std::set<Path>& result, std::string* ErrMsg) const {
423   DIR* direntries = ::opendir(path.c_str());
424   if (direntries == 0)
425     return MakeErrMsg(ErrMsg, path + ": can't open directory");
426
427   std::string dirPath = path;
428   if (!lastIsSlash(dirPath))
429     dirPath += '/';
430
431   result.clear();
432   struct dirent* de = ::readdir(direntries);
433   for ( ; de != 0; de = ::readdir(direntries)) {
434     if (de->d_name[0] != '.') {
435       Path aPath(dirPath + (const char*)de->d_name);
436       struct stat st;
437       if (0 != lstat(aPath.path.c_str(), &st)) {
438         if (S_ISLNK(st.st_mode))
439           continue; // dangling symlink -- ignore
440         return MakeErrMsg(ErrMsg, 
441                           aPath.path +  ": can't determine file object type");
442       }
443       result.insert(aPath);
444     }
445   }
446   
447   closedir(direntries);
448   return false;
449 }
450
451 bool
452 Path::set(const std::string& a_path) {
453   if (a_path.empty())
454     return false;
455   std::string save(path);
456   path = a_path;
457   if (!isValid()) {
458     path = save;
459     return false;
460   }
461   return true;
462 }
463
464 bool
465 Path::appendComponent(const std::string& name) {
466   if (name.empty())
467     return false;
468   std::string save(path);
469   if (!lastIsSlash(path))
470     path += '/';
471   path += name;
472   if (!isValid()) {
473     path = save;
474     return false;
475   }
476   return true;
477 }
478
479 bool
480 Path::eraseComponent() {
481   size_t slashpos = path.rfind('/',path.size());
482   if (slashpos == 0 || slashpos == std::string::npos) {
483     path.erase();
484     return true;
485   }
486   if (slashpos == path.size() - 1)
487     slashpos = path.rfind('/',slashpos-1);
488   if (slashpos == std::string::npos) {
489     path.erase();
490     return true;
491   }
492   path.erase(slashpos);
493   return true;
494 }
495
496 bool
497 Path::appendSuffix(const std::string& suffix) {
498   std::string save(path);
499   path.append(".");
500   path.append(suffix);
501   if (!isValid()) {
502     path = save;
503     return false;
504   }
505   return true;
506 }
507
508 bool
509 Path::eraseSuffix() {
510   std::string save = path;
511   size_t dotpos = path.rfind('.',path.size());
512   size_t slashpos = path.rfind('/',path.size());
513   if (dotpos != std::string::npos) {
514     if (slashpos == std::string::npos || dotpos > slashpos+1) {
515       path.erase(dotpos, path.size()-dotpos);
516       return true;
517     }
518   }
519   if (!isValid())
520     path = save;
521   return false;
522 }
523
524 bool
525 Path::createDirectoryOnDisk( bool create_parents, std::string* ErrMsg ) {
526   // Get a writeable copy of the path name
527   char pathname[MAXPATHLEN];
528   path.copy(pathname,MAXPATHLEN);
529
530   // Null-terminate the last component
531   int lastchar = path.length() - 1 ; 
532   if (pathname[lastchar] == '/') 
533     pathname[lastchar] = 0;
534   else 
535     pathname[lastchar+1] = 0;
536
537   // If we're supposed to create intermediate directories
538   if ( create_parents ) {
539     // Find the end of the initial name component
540     char * next = strchr(pathname,'/');
541     if ( pathname[0] == '/') 
542       next = strchr(&pathname[1],'/');
543
544     // Loop through the directory components until we're done 
545     while ( next != 0 ) {
546       *next = 0;
547       if (0 != access(pathname, F_OK | R_OK | W_OK))
548         if (0 != mkdir(pathname, S_IRWXU | S_IRWXG)) {
549           return MakeErrMsg(ErrMsg, 
550                             std::string(pathname) + ": can't create directory");
551         }
552       char* save = next;
553       next = strchr(next+1,'/');
554       *save = '/';
555     }
556   } 
557
558   if (0 != access(pathname, F_OK | R_OK))
559     if (0 != mkdir(pathname, S_IRWXU | S_IRWXG)) {
560       return MakeErrMsg(ErrMsg, 
561                         std::string(pathname) + ": can't create directory");
562     }
563   return false;
564 }
565
566 bool
567 Path::createFileOnDisk(std::string* ErrMsg) {
568   // Create the file
569   int fd = ::creat(path.c_str(), S_IRUSR | S_IWUSR);
570   if (fd < 0)
571     return MakeErrMsg(ErrMsg, path + ": can't create file");
572   ::close(fd);
573   return false;
574 }
575
576 bool
577 Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) {
578   // Make this into a unique file name
579   if (makeUnique( reuse_current, ErrMsg ))
580     return true;
581
582   // create the file
583   int fd = ::open(path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0666);
584   if (fd < 0) 
585     return MakeErrMsg(ErrMsg, path + ": can't create temporary file");
586   ::close(fd);
587   return false;
588 }
589
590 bool
591 Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const {
592   // Get the status so we can determin if its a file or directory
593   struct stat buf;
594   if (0 != stat(path.c_str(), &buf)) {
595     MakeErrMsg(ErrStr, path + ": can't get status of file");
596     return true;
597   }
598
599   // Note: this check catches strange situations. In all cases, LLVM should 
600   // only be involved in the creation and deletion of regular files.  This 
601   // check ensures that what we're trying to erase is a regular file. It 
602   // effectively prevents LLVM from erasing things like /dev/null, any block 
603   // special file, or other things that aren't "regular" files. 
604   if (S_ISREG(buf.st_mode)) {
605     if (unlink(path.c_str()) != 0)
606       return MakeErrMsg(ErrStr, path + ": can't destroy file");
607     return false;
608   }
609   
610   if (!S_ISDIR(buf.st_mode)) {
611     if (ErrStr) *ErrStr = "not a file or directory";
612     return true;
613   }
614
615   if (remove_contents) {
616     // Recursively descend the directory to remove its contents.
617     std::string cmd = "/bin/rm -rf " + path;
618     system(cmd.c_str());
619     return false;
620   }
621
622   // Otherwise, try to just remove the one directory.
623   char pathname[MAXPATHLEN];
624   path.copy(pathname, MAXPATHLEN);
625   int lastchar = path.length() - 1 ; 
626   if (pathname[lastchar] == '/') 
627     pathname[lastchar] = 0;
628   else
629     pathname[lastchar+1] = 0;
630     
631   if (rmdir(pathname) != 0)
632     return MakeErrMsg(ErrStr, 
633       std::string(pathname) + ": can't erase directory");
634   return false;
635 }
636
637 bool
638 Path::renamePathOnDisk(const Path& newName, std::string* ErrMsg) {
639   if (0 != ::rename(path.c_str(), newName.c_str()))
640     return MakeErrMsg(ErrMsg, std::string("can't rename '") + path + "' as '" + 
641                newName.toString() + "' ");
642   return false;
643 }
644
645 bool 
646 Path::setStatusInfoOnDisk(const FileStatus &si, std::string *ErrStr) const {
647   struct utimbuf utb;
648   utb.actime = si.modTime.toPosixTime();
649   utb.modtime = utb.actime;
650   if (0 != ::utime(path.c_str(),&utb))
651     return MakeErrMsg(ErrStr, path + ": can't set file modification time");
652   if (0 != ::chmod(path.c_str(),si.mode))
653     return MakeErrMsg(ErrStr, path + ": can't set mode");
654   return false;
655 }
656
657 bool 
658 sys::CopyFile(const sys::Path &Dest, const sys::Path &Src, std::string* ErrMsg){
659   int inFile = -1;
660   int outFile = -1;
661   inFile = ::open(Src.c_str(), O_RDONLY);
662   if (inFile == -1)
663     return MakeErrMsg(ErrMsg, Src.toString() + 
664       ": can't open source file to copy");
665
666   outFile = ::open(Dest.c_str(), O_WRONLY|O_CREAT, 0666);
667   if (outFile == -1) {
668     ::close(inFile);
669     return MakeErrMsg(ErrMsg, Dest.toString() +
670       ": can't create destination file for copy");
671   }
672
673   char Buffer[16*1024];
674   while (ssize_t Amt = ::read(inFile, Buffer, 16*1024)) {
675     if (Amt == -1) {
676       if (errno != EINTR && errno != EAGAIN) {
677         ::close(inFile);
678         ::close(outFile);
679         return MakeErrMsg(ErrMsg, Src.toString()+": can't read source file: ");
680       }
681     } else {
682       char *BufPtr = Buffer;
683       while (Amt) {
684         ssize_t AmtWritten = ::write(outFile, BufPtr, Amt);
685         if (AmtWritten == -1) {
686           if (errno != EINTR && errno != EAGAIN) {
687             ::close(inFile);
688             ::close(outFile);
689             return MakeErrMsg(ErrMsg, Dest.toString() + 
690               ": can't write destination file: ");
691           }
692         } else {
693           Amt -= AmtWritten;
694           BufPtr += AmtWritten;
695         }
696       }
697     }
698   }
699   ::close(inFile);
700   ::close(outFile);
701   return false;
702 }
703
704 bool 
705 Path::makeUnique(bool reuse_current, std::string* ErrMsg) {
706   if (reuse_current && !exists())
707     return false; // File doesn't exist already, just use it!
708
709   // Append an XXXXXX pattern to the end of the file for use with mkstemp, 
710   // mktemp or our own implementation.
711   char *FNBuffer = (char*) alloca(path.size()+8);
712   path.copy(FNBuffer,path.size());
713   strcpy(FNBuffer+path.size(), "-XXXXXX");
714
715 #if defined(HAVE_MKSTEMP)
716   int TempFD;
717   if ((TempFD = mkstemp(FNBuffer)) == -1)
718     return MakeErrMsg(ErrMsg, path + ": can't make unique filename");
719
720   // We don't need to hold the temp file descriptor... we will trust that no one
721   // will overwrite/delete the file before we can open it again.
722   close(TempFD);
723
724   // Save the name
725   path = FNBuffer;
726 #elif defined(HAVE_MKTEMP)
727   // If we don't have mkstemp, use the old and obsolete mktemp function.
728   if (mktemp(FNBuffer) == 0)
729     return MakeErrMsg(ErrMsg, path + ": can't make unique filename");
730
731   // Save the name
732   path = FNBuffer;
733 #else
734   // Okay, looks like we have to do it all by our lonesome.
735   static unsigned FCounter = 0;
736   unsigned offset = path.size() + 1;
737   while ( FCounter < 999999 && exists()) {
738     sprintf(FNBuffer+offset,"%06u",++FCounter);
739     path = FNBuffer;
740   }
741   if (FCounter > 999999)
742     return MakeErrMsg(ErrMsg, 
743       path + ": can't make unique filename: too many files");
744 #endif
745   return false;
746 }
747
748 const char *Path::MapInFilePages(int FD, uint64_t FileSize) {
749   int Flags = MAP_PRIVATE;
750 #ifdef MAP_FILE
751   Flags |= MAP_FILE;
752 #endif
753   void *BasePtr = ::mmap(0, FileSize, PROT_READ, Flags, FD, 0);
754   if (BasePtr == MAP_FAILED)
755     return 0;
756   return BasePtr;
757 }
758
759 void Path::UnMapFilePages(const char *BasePtr, uint64_t FileSize) {
760   ::munmap(BasePtr, FileSize);
761 }
762
763 } // end llvm namespace
764