llvm.org GIT mirror llvm / 8475ec0
For PR789: Make the sys::Path::getFileStatus function more efficient by having it return a pointer to the FileStatus structure rather than copy it. Adjust uses of the function accordingly. Also, fix some memory issues in sys::Path. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35476 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Spencer 12 years ago
16 changed file(s) with 125 addition(s) and 94 deletion(s). Raw diff Collapse all Expand all
7272 PROJ_VERSION := 1.0
7373 endif
7474 endif
75
76 LLVMMAKE := $(LLVM_SRC_ROOT)/make
7577
7678 PROJ_bindir := $(DESTDIR)$(PROJ_prefix)/bin
7779 PROJ_libdir := $(DESTDIR)$(PROJ_prefix)/lib
17591759 $(Echo) "Module : " '$(Module)'
17601760 $(Echo) "FilesToConfig: " '$(FilesToConfigPATH)'
17611761 $(Echo) "SubDirs : " '$(SubDirs)'
1762 $(Echo) "ProjLibsPaths: " '$(ProjLibsPaths)'
1763 $(Echo) "ProjLibsOptions: " '$(ProjLibsOptions)'
165165 /// @brief Construct an empty (and invalid) path.
166166 Path() : path(), status(0) {}
167167 ~Path() { delete status; }
168 Path(const Path &that) : path(that.path), status(0) {}
168169
169170 /// This constructor will accept a std::string as a path. No checking is
170171 /// done on this path to determine if it is valid. To determine validity
182183 /// @brief Assignment Operator
183184 Path &operator=(const Path &that) {
184185 path = that.path;
186 if (status)
187 delete status;
188 status = 0;
185189 return *this;
186190 }
187191
222226 /// @brief Determine if a path is syntactically valid or not.
223227 bool isValid() const;
224228
225 /// This function determines if the contents of the path name are
226 /// empty. That is, the path has a zero length. This does NOT determine if
227 /// if the file is empty. Use the getSize method for that.
229 /// This function determines if the contents of the path name are empty.
230 /// That is, the path name has a zero length. This does NOT determine if
231 /// if the file is empty. To get the length of the file itself, Use the
232 /// getFileStatus() method and then the getSize() on the returned
233 /// FileStatus object
228234 /// @returns true iff the path is empty.
229235 /// @brief Determines if the path name is empty (invalid).
230236 bool isEmpty() const { return path.empty(); }
356362
357363 /// This function returns status information about the file. The type of
358364 /// path (file or directory) is updated to reflect the actual contents
359 /// of the file system. This returns false on success, or true on error
360 /// and fills in the specified error string if specified.
365 /// of the file system.
366 /// @returns 0 on failure, with Error explaining why (if non-zero)
367 /// @returns a pointer to a FileStatus structure on success.
361368 /// @brief Get file status.
362 bool getFileStatus(
363 FileStatus &Status, ///< The resulting file status
364 bool forceUpdate = false, ///< Force an update from the file system
365 std::string *Error = 0 ///< Optional place to return an error msg.
369 const FileStatus *getFileStatus(
370 bool forceUpdate = false, ///< Force an update from the file system
371 std::string *Error = 0 ///< Optional place to return an error msg.
366372 ) const;
367373
368374 /// @}
115115 path.getMagicNumber(magic,4);
116116 signature = magic.c_str();
117117 std::string err;
118 if (path.getFileStatus(info, false, ErrMsg))
118 const sys::FileStatus *FSinfo = path.getFileStatus(false, ErrMsg);
119 if (FSinfo)
120 info = *FSinfo;
121 else
119122 return true;
120123 }
121124
162162
163163 mbr->data = 0;
164164 mbr->path = filePath;
165 if (mbr->path.getFileStatus(mbr->info, false, ErrMsg))
165 const sys::FileStatus *FSInfo = mbr->path.getFileStatus(false, ErrMsg);
166 if (FSInfo)
167 mbr->info = *FSInfo;
168 else
166169 return true;
167170
168171 unsigned flags = 0;
115115 path.getMagicNumber(magic,4);
116116 signature = magic.c_str();
117117 std::string err;
118 if (path.getFileStatus(info, false, ErrMsg))
118 const sys::FileStatus *FSinfo = path.getFileStatus(false, ErrMsg);
119 if (FSinfo)
120 info = *FSinfo;
121 else
119122 return true;
120123 }
121124
162162
163163 mbr->data = 0;
164164 mbr->path = filePath;
165 if (mbr->path.getFileStatus(mbr->info, false, ErrMsg))
165 const sys::FileStatus *FSInfo = mbr->path.getFileStatus(false, ErrMsg);
166 if (FSInfo)
167 mbr->info = *FSInfo;
168 else
166169 return true;
167170
168171 unsigned flags = 0;
193193
194194 ProgramInfo::ProgramInfo(Module *m) : M(m), ProgramTimeStamp(0,0) {
195195 assert(M && "Cannot create program information with a null module!");
196 sys::FileStatus Stat;
197 if (!sys::Path(M->getModuleIdentifier()).getFileStatus(Stat))
198 ProgramTimeStamp = Stat.getTimestamp();
196 const sys::FileStatus *Stat;
197 Stat = sys::Path(M->getModuleIdentifier()).getFileStatus();
198 if (Stat)
199 ProgramTimeStamp = Stat->getTimestamp();
199200
200201 SourceFilesIsComplete = false;
201202 SourceFunctionsIsComplete = false;
151151 const sys::Path &FileB,
152152 double AbsTol, double RelTol,
153153 std::string *Error) {
154 sys::FileStatus FileAStat, FileBStat;
155 if (FileA.getFileStatus(FileAStat, false, Error))
156 return 2;
157 if (FileB.getFileStatus(FileBStat, false, Error))
154 const sys::FileStatus *FileAStat = FileA.getFileStatus(false, Error);
155 if (!FileAStat)
156 return 2;
157 const sys::FileStatus *FileBStat = FileB.getFileStatus(false, Error);
158 if (!FileBStat)
158159 return 2;
159160
160161 // Check for zero length files because some systems croak when you try to
161162 // mmap an empty file.
162 size_t A_size = FileAStat.getSize();
163 size_t B_size = FileBStat.getSize();
163 size_t A_size = FileAStat->getSize();
164 size_t B_size = FileBStat->getSize();
164165
165166 // If they are both zero sized then they're the same
166167 if (A_size == 0 && B_size == 0)
332332 Path::canExecute() const {
333333 if (0 != access(path.c_str(), R_OK | X_OK ))
334334 return false;
335 struct stat st;
336 int r = stat(path.c_str(), &st);
337 if (r != 0 || !S_ISREG(st.st_mode))
335 if (const FileStatus *fs = getFileStatus(true, 0)) {
336 if (!S_ISREG(fs->mode))
337 return false;
338 } else
338339 return false;
339340 return true;
340341 }
361362 return path.substr(pos+1);
362363 }
363364
364 bool
365 Path::getFileStatus(FileStatus &info, bool update, std::string *ErrStr) const {
365 const FileStatus*
366 Path::getFileStatus(bool update, std::string *ErrStr) const {
366367 if (status == 0 || update) {
367368 struct stat buf;
368 if (0 != stat(path.c_str(), &buf))
369 return MakeErrMsg(ErrStr, path + ": can't get status of file");
369 if (0 != stat(path.c_str(), &buf)) {
370 MakeErrMsg(ErrStr, path + ": can't get status of file");
371 return 0;
372 }
370373 if (status == 0)
371374 status = new FileStatus;
372375 status->fileSize = buf.st_size;
378381 status->isDir = S_ISDIR(buf.st_mode);
379382 status->isFile = S_ISREG(buf.st_mode);
380383 }
381 info = *status;
382 return false;
384 return status;
383385 }
384386
385387 static bool AddPermissionBits(const Path &File, int bits) {
391393 umask(mask); // Restore the umask.
392394
393395 // Get the file's current mode.
394 FileStatus Stat;
395 if (File.getFileStatus(Stat)) return false;
396
397 // Change the file to have whichever permissions bits from 'bits'
398 // that the umask would not disable.
399 if ((chmod(File.c_str(), (Stat.getMode() | (bits & ~mask)))) == -1)
396 if (const FileStatus *fs = File.getFileStatus()) {
397 // Change the file to have whichever permissions bits from 'bits'
398 // that the umask would not disable.
399 if ((chmod(File.c_str(), (fs->getMode() | (bits & ~mask)))) == -1)
400 return false;
401 } else
400402 return false;
401403
402404 return true;
592594 bool
593595 Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const {
594596 FileStatus Status;
595 if (getFileStatus(Status, ErrStr))
597 if (const FileStatus *Status = getFileStatus(false, ErrStr)) {
598 // Note: this check catches strange situations. In all cases, LLVM should
599 // only be involved in the creation and deletion of regular files. This
600 // check ensures that what we're trying to erase is a regular file. It
601 // effectively prevents LLVM from erasing things like /dev/null, any block
602 // special file, or other things that aren't "regular" files.
603 if (Status->isFile) {
604 if (unlink(path.c_str()) != 0)
605 return MakeErrMsg(ErrStr, path + ": can't destroy file");
606 return false;
607 }
608
609 if (!Status->isDir) {
610 if (ErrStr) *ErrStr = "not a file or directory";
611 return true;
612 }
613 } else
596614 return true;
597
598 // Note: this check catches strange situations. In all cases, LLVM should only
599 // be involved in the creation and deletion of regular files. This check
600 // ensures that what we're trying to erase is a regular file. It effectively
601 // prevents LLVM from erasing things like /dev/null, any block special file,
602 // or other things that aren't "regular" files.
603 if (Status.isFile) {
604 if (unlink(path.c_str()) != 0)
605 return MakeErrMsg(ErrStr, path + ": can't destroy file");
606 return false;
607 }
608
609 if (!Status.isDir) {
610 if (ErrStr) *ErrStr = "not a file or directory";
611 return true;
612 }
615
613616 if (remove_contents) {
614617 // Recursively descend the directory to remove its contents.
615618 std::string cmd = "/bin/rm -rf " + path;
628631
629632 if (rmdir(pathname) != 0)
630633 return MakeErrMsg(ErrStr,
631 std::string(pathname) + ": can't destroy directory");
634 std::string(pathname) + ": can't erase directory");
632635 return false;
633636 }
634637
167167 // RemoveDirectoryOnSignal - The public API
168168 bool sys::RemoveDirectoryOnSignal(const sys::Path& path, std::string* ErrMsg) {
169169 // Not a directory?
170 sys::FileStatus Status;
171 if (path.getFileStatus(Status) || !Status.isDir) {
170 const sys::FileStatus *Status = path.getFileStatus(false, ErrMsg);
171 if (!Status)
172 return true;
173 if (!Status->isDir) {
172174 if (ErrMsg)
173175 *ErrMsg = path.toString() + " is not a directory";
174176 return true;
305305 return path.substr(pos+1);
306306 }
307307
308 bool
309 Path::getFileStatus(FileStatus &info, bool update, std::string *ErrStr) const {
308 const FileStatus *
309 Path::getFileStatus(bool update, std::string *ErrStr) const {
310310 if (status == 0 || update) {
311311 WIN32_FILE_ATTRIBUTE_DATA fi;
312 if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi))
313 return MakeErrMsg(ErrStr, "getStatusInfo():" + std::string(path) +
312 if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) {
313 MakeErrMsg(ErrStr, "getStatusInfo():" + std::string(path) +
314314 ": Can't get status: ");
315 return 0;
316 }
315317
316318 if (status == 0)
317319 status = new FileStatus;
336338
337339 status->isDir = fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
338340 }
339 info = *status;
340 return false;
341 return status;
341342 }
342343
343344 bool Path::makeReadableOnDisk(std::string* ErrMsg) {
368369
369370 bool
370371 Path::getDirectoryContents(std::set& result, std::string* ErrMsg) const {
371 FileStatus Status;
372 if (getFileStatus(Status, ErrMsg))
372 const FileStatus *Status = getFileStatus(false, ErrMsg);
373 if (!Status)
373374 return true;
374
375 if (!Status.isDir) {
375 if (!Status->isDir) {
376376 MakeErrMsg(ErrMsg, path + ": not a directory");
377377 return true;
378378 }
566566
567567 bool
568568 Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const {
569 FileStatus Status;
570 if (getFileStatus(Status, ErrStr))
569 const FileStatus *Status = getFileStatus(false, ErrStr);
570 if (!Status)
571571 return false;
572572
573 if (Status.isFile) {
573 if (Status->isFile) {
574574 DWORD attr = GetFileAttributes(path.c_str());
575575
576576 // If it doesn't exist, we're done.
587587 if (!DeleteFile(path.c_str()))
588588 return MakeErrMsg(ErrStr, path + ": Can't destroy file: ");
589589 return false;
590 } else if (Status.isDir) {
590 } else if (Status->isDir) {
591591 // If it doesn't exist, we're done.
592592 if (!exists())
593593 return false;
100100 // RemoveDirectoryOnSignal - The public API
101101 bool sys::RemoveDirectoryOnSignal(const sys::Path& path, std::string* ErrMsg) {
102102 // Not a directory?
103 sys::FileStatus Status;
104 if (path.getFileStatus(Status) || !Status.isDir) {
103 const sys::FileStatus *Status = path.getFileStatus(false, ErrMsg);
104 if (!Status)
105 return true;
106 if (!Status->isDir) {
105107 if (ErrMsg)
106108 *ErrMsg = path.toString() + " is not a directory";
107109 return true;
280280 for (std::set::iterator I = content.begin(), E = content.end();
281281 I != E; ++I) {
282282 // Make sure it exists and is a directory
283 sys::FileStatus Status;
284 if (I->getFileStatus(Status)) {
285 if (Status.isDir) {
286 std::set moreResults;
287 if (recurseDirectories(*I, moreResults, ErrMsg))
288 return true;
289 result.insert(moreResults.begin(), moreResults.end());
290 } else {
283 const sys::FileStatus *Status = I->getFileStatus(false, ErrMsg);
284 if (!Status)
285 return true;
286 if (Status->isDir) {
287 std::set moreResults;
288 if (recurseDirectories(*I, moreResults, ErrMsg))
289 return true;
290 result.insert(moreResults.begin(), moreResults.end());
291 } else {
291292 result.insert(*I);
292 }
293293 }
294294 }
295295 }
307307 if (checkExistence) {
308308 if (!aPath.exists())
309309 throw std::string("File does not exist: ") + Members[i];
310 sys::FileStatus si;
311310 std::string Err;
312 if (aPath.getFileStatus(si, false, &Err))
311 const sys::FileStatus *si = aPath.getFileStatus(false, &Err);
312 if (!si)
313313 throw Err;
314 if (si.isDir) {
314 if (si->isDir) {
315315 std::set dirpaths;
316316 if (recurseDirectories(aPath, dirpaths, ErrMsg))
317317 return true;
643643 }
644644
645645 if (found != remaining.end()) {
646 sys::FileStatus si;
647646 std::string Err;
648 if (found->getFileStatus(si, false, &Err))
647 const sys::FileStatus *si = found->getFileStatus(false, &Err);
648 if (!si)
649649 return true;
650 if (si.isDir) {
650 if (si->isDir) {
651651 if (OnlyUpdate) {
652652 // Replace the item only if it is newer.
653 if (si.modTime > I->getModTime())
653 if (si->modTime > I->getModTime())
654654 if (I->replaceWith(*found, ErrMsg))
655655 return true;
656656 } else {
4949
5050 // If the program has been modified, reload it!
5151 sys::Path Program(Dbg.getProgramPath());
52 sys::FileStatus Status;
5352 std::string Err;
54 if (Program.getFileStatus(Status, &Err))
53 const sys::FileStatus *Status = Program.getFileStatus(false, &Err);
54 if (!Status)
5555 throw Err;
56 if (TheProgramInfo->getProgramTimeStamp() != Status.getTimestamp()) {
56 if (TheProgramInfo->getProgramTimeStamp() != Status->getTimestamp()) {
5757 std::cout << "'" << Program << "' has changed; re-reading program.\n";
5858
5959 // Unload an existing program. This kills the program if necessary.
194194
195195 void cleanup() {
196196 if (!isSet(KEEP_TEMPS_FLAG)) {
197 sys::FileStatus Status;
198 if (!TempDir.getFileStatus(Status) && Status.isDir)
197 const sys::FileStatus *Status = TempDir.getFileStatus();
198 if (Status && Status->isDir)
199199 TempDir.eraseFromDisk(/*remove_contents=*/true);
200200 } else {
201201 std::cout << "Temporary files are in " << TempDir << "\n";