llvm.org GIT mirror llvm / 252ad03
Change Path::getStatusInfo to return a boolean and error string on an error instead of throwing an exception. This reduces the amount of code that is exposed to exceptions (e.g. FileUtilities), though it is clearly only one step along the way. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29395 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 13 years ago
11 changed file(s) with 118 addition(s) and 110 deletion(s). Raw diff Collapse all Expand all
3939 /// of the Archive class instead.
4040 /// @brief This class represents a single archive member.
4141 class ArchiveMember {
42
4342 /// @name Types
4443 /// @{
4544 public:
7473 /// have any applicability on non-Unix systems but is a required component
7574 /// of the "ar" file format.
7675 /// @brief Get the user associated with this archive member.
77 unsigned getUser() const { return info.user; }
76 unsigned getUser() const { return info.getUser(); }
7877
7978 /// The "group" is the owning group of the file per Unix security. This
8079 /// may not have any applicability on non-Unix systems but is a required
8180 /// component of the "ar" file format.
8281 /// @brief Get the group associated with this archive member.
83 unsigned getGroup() const { return info.group; }
82 unsigned getGroup() const { return info.getGroup(); }
8483
8584 /// The "mode" specifies the access permissions for the file per Unix
8685 /// security. This may not have any applicabiity on non-Unix systems but is
8786 /// a required component of the "ar" file format.
8887 /// @brief Get the permission mode associated with this archive member.
89 unsigned getMode() const { return info.mode; }
88 unsigned getMode() const { return info.getMode(); }
9089
9190 /// This method returns the time at which the archive member was last
9291 /// modified when it was not in the archive.
9392 /// @brief Get the time of last modification of the archive member.
94 sys::TimeValue getModTime() const { return info.modTime; }
93 sys::TimeValue getModTime() const { return info.getTimestamp(); }
9594
9695 /// @returns the size of the archive member in bytes.
9796 /// @brief Get the size of the archive member.
98 unsigned getSize() const { return info.fileSize; }
97 unsigned getSize() const { return info.getSize(); }
9998
10099 /// This method returns the total size of the archive member as it
101100 /// appears on disk. This includes the file content, the header, the
161160 /// systems.
162161 /// @returns the status info for the archive member
163162 /// @brief Obtain the status info for the archive member
164 const sys::Path::StatusInfo& getStatusInfo() const { return info; }
163 const sys::FileStatus &getFileStatus() const { return info; }
165164
166165 /// This method causes the archive member to be replaced with the contents
167166 /// of the file specified by \p File. The contents of \p this will be
168167 /// updated to reflect the new data from \p File. The \p File must exist and
169168 /// be readable on entry to this method.
170169 /// @brief Replace contents of archive member with a new file.
171 void replaceWith(const sys::Path& aFile);
170 void replaceWith(const sys::Path &aFile);
172171
173172 /// @}
174173 /// @name ilist methods - do not use
189188 ArchiveMember* prev; ///< Pointer to previous archive member
190189 Archive* parent; ///< Pointer to parent archive
191190 sys::Path path; ///< Path of file containing the member
192 sys::Path::StatusInfo info; ///< Status info (size,mode,date)
191 sys::FileStatus info; ///< Status info (size,mode,date)
193192 unsigned flags; ///< Flags about the archive member
194193 const void* data; ///< Data for the member
195194
204203 private:
205204 /// Used internally by the Archive class to construct an ArchiveMember.
206205 /// The contents of the ArchiveMember are filled out by the Archive class.
207 ArchiveMember( Archive* PAR );
206 ArchiveMember(Archive *PAR);
208207
209208 // So Archive can construct an ArchiveMember
210209 friend class llvm::Archive;
2222
2323 namespace llvm {
2424 namespace sys {
25
26 /// This structure provides basic file system information about a file. It
27 /// is patterned after the stat(2) Unix operating system call but made
28 /// platform independent and eliminates many of the unix-specific fields.
29 /// However, to support llvm-ar, the mode, user, and group fields are
30 /// retained. These pertain to unix security and may not have a meaningful
31 /// value on non-Unix platforms. However, the fileSize and modTime fields
32 /// should always be applicable on all platforms. The structure is
33 /// filled in by the Path::getFileStatus method.
34 /// @brief File status structure
35 class FileStatus {
36 public:
37 uint64_t fileSize; ///< Size of the file in bytes
38 TimeValue modTime; ///< Time of file's modification
39 uint32_t mode; ///< Mode of the file, if applicable
40 uint32_t user; ///< User ID of owner, if applicable
41 uint32_t group; ///< Group ID of owner, if applicable
42 bool isDir : 1; ///< True if this is a directory.
43 bool isFile : 1; ///< True if this is a file.
44
45 FileStatus() : fileSize(0), modTime(0,0), mode(0777), user(999),
46 group(999), isDir(false) { }
47
48 TimeValue getTimestamp() const { return modTime; }
49 size_t getSize() const { return fileSize; }
50 uint32_t getMode() const { return mode; }
51 uint32_t getUser() const { return user; }
52 uint32_t getGroup() const { return group; }
53 };
2554
2655 /// This class provides an abstraction for the path to a file or directory
2756 /// in the operating system's filesystem and provides various basic operations
5281 /// @since 1.4
5382 /// @brief An abstraction for operating system paths.
5483 class Path {
55 /// @name Types
56 /// @{
57 public:
58 /// This structure provides basic file system information about a file. It
59 /// is patterned after the stat(2) Unix operating system call but made
60 /// platform independent and eliminates many of the unix-specific fields.
61 /// However, to support llvm-ar, the mode, user, and group fields are
62 /// retained. These pertain to unix security and may not have a meaningful
63 /// value on non-Unix platforms. However, the fileSize and modTime fields
64 /// should always be applicabe on all platforms. The structure is
65 /// filled in by the getStatusInfo method.
66 /// @brief File status structure
67 struct StatusInfo {
68 StatusInfo() : fileSize(0), modTime(0,0), mode(0777), user(999),
69 group(999), isDir(false) { }
70 uint64_t fileSize; ///< Size of the file in bytes
71 TimeValue modTime; ///< Time of file's modification
72 uint32_t mode; ///< Mode of the file, if applicable
73 uint32_t user; ///< User ID of owner, if applicable
74 uint32_t group; ///< Group ID of owner, if applicable
75 bool isDir; ///< True if this is a directory.
76 };
77
78 /// @}
7984 /// @name Constructors
8085 /// @{
8186 public:
174179 /// Makes a copy of \p that to \p this.
175180 /// @returns \p this
176181 /// @brief Assignment Operator
177 Path & operator = ( const Path & that ) {
182 Path &operator=(const Path &that) {
178183 path = that.path;
179184 return *this;
180185 }
182187 /// Compares \p this Path with \p that Path for equality.
183188 /// @returns true if \p this and \p that refer to the same thing.
184189 /// @brief Equality Operator
185 bool operator == (const Path& that) const {
186 return 0 == path.compare(that.path) ;
190 bool operator==(const Path &that) const {
191 return 0 == path.compare(that.path);
187192 }
188193
189194 /// Compares \p this Path with \p that Path for inequality.
190195 /// @returns true if \p this and \p that refer to different things.
191196 /// @brief Inequality Operator
192 bool operator !=( const Path & that ) const {
193 return 0 != path.compare( that.path );
197 bool operator!=(const Path &that) const {
198 return 0 != path.compare(that.path);
194199 }
195200
196201 /// Determines if \p this Path is less than \p that Path. This is required
199204 /// the std::string::compare method.
200205 /// @returns true if \p this path is lexicographically less than \p that.
201206 /// @brief Less Than Operator
202 bool operator< (const Path& that) const {
203 return 0 > path.compare( that.path );
207 bool operator<(const Path& that) const {
208 return 0 > path.compare(that.path);
204209 }
205210
206211 /// @}
227232 /// std::string. This allows the underlying path string to be manipulated.
228233 /// @returns std::string containing the path name.
229234 /// @brief Returns the path as a std::string.
230 const std::string& toString() const { return path; }
235 const std::string &toString() const { return path; }
231236
232237 /// This function returns the last component of the path name. The last
233238 /// component is the file or directory name occuring after the last
247252 /// Obtain a 'C' string for the path name.
248253 /// @returns a 'C' string containing the path name.
249254 /// @brief Returns the path as a C string.
250 const char* const c_str() const { return path.c_str(); }
255 const char *const c_str() const { return path.c_str(); }
251256
252257 /// @}
253258 /// @name Disk Accessors
361366 /// @returns false if \p this is not a directory, true otherwise
362367 /// @throws std::string if the directory cannot be searched
363368 /// @brief Build a list of directory's contents.
364 bool getDirectoryContents(std::set& paths) const;
369 bool getDirectoryContents(std::set &paths) const;
365370
366371 /// This function returns status information about the file. The type of
367372 /// path (file or directory) is updated to reflect the actual contents
368 /// of the file system. If the file does not exist, false is returned.
369 /// For other (hard I/O) errors, a std::string is thrown indicating the
370 /// problem.
371 /// @throws std::string if an error occurs.
373 /// of the file system. This returns false on success, or true on error
374 /// and fills in the specified error string if specified.
372375 /// @brief Get file status.
373 void getStatusInfo(StatusInfo& info) const;
374
375 /// This function returns the last modified time stamp for the file
376 /// referenced by this path. The Path may reference a file or a directory.
377 /// If the file does not exist, a ZeroTime timestamp is returned.
378 /// @returns last modified timestamp of the file/directory or ZeroTime
379 /// @brief Get file timestamp.
380 inline TimeValue getTimestamp() const {
381 StatusInfo info; getStatusInfo(info); return info.modTime;
382 }
383
384 /// This function returns the size of the file referenced by this path.
385 /// @brief Get file size.
386 inline size_t getSize() const {
387 StatusInfo info; getStatusInfo(info); return info.fileSize;
388 }
376 bool getFileStatus(FileStatus &Status, std::string *Error = 0) const;
389377
390378 /// @}
391379 /// @name Path Mutators
474462 /// @throws std::string if an error occurs.
475463 /// @returns true
476464 /// @brief Set the status information.
477 bool setStatusInfoOnDisk(const StatusInfo& si) const;
465 bool setStatusInfoOnDisk(const FileStatus &SI) const;
478466
479467 /// This method attempts to create a directory in the file system with the
480468 /// same name as the Path object. The \p create_parents parameter controls
537525 /// refers to something that is neither a file nor a directory.
538526 /// @throws std::string if there is an error.
539527 /// @brief Removes the file or directory from the filesystem.
540 bool eraseFromDisk( bool destroy_contents = false ) const;
528 bool eraseFromDisk(bool destroy_contents = false) const;
541529
542530 /// @}
543531 /// @name Data
103103 flags &= ~HasLongFilenameFlag;
104104
105105 // Get the signature and status info
106 const char* signature = (const char*) data;
106107 std::string magic;
107 const char* signature = (const char*) data;
108108 if (!signature) {
109109 path.getMagicNumber(magic,4);
110110 signature = magic.c_str();
111 path.getStatusInfo(info);
111 std::string err;
112 if (path.getFileStatus(info, &err))
113 throw err;
112114 }
113115
114116 // Determine what kind of file it is
158158
159159 mbr->data = 0;
160160 mbr->path = filePath;
161 mbr->path.getStatusInfo(mbr->info);
161 std::string err;
162 if (mbr->path.getFileStatus(mbr->info, &err))
163 throw err;
162164
163165 unsigned flags = 0;
164166 bool hasSlash = filePath.toString().find('/') != std::string::npos;
103103 flags &= ~HasLongFilenameFlag;
104104
105105 // Get the signature and status info
106 const char* signature = (const char*) data;
106107 std::string magic;
107 const char* signature = (const char*) data;
108108 if (!signature) {
109109 path.getMagicNumber(magic,4);
110110 signature = magic.c_str();
111 path.getStatusInfo(info);
111 std::string err;
112 if (path.getFileStatus(info, &err))
113 throw err;
112114 }
113115
114116 // Determine what kind of file it is
158158
159159 mbr->data = 0;
160160 mbr->path = filePath;
161 mbr->path.getStatusInfo(mbr->info);
161 std::string err;
162 if (mbr->path.getFileStatus(mbr->info, &err))
163 throw err;
162164
163165 unsigned flags = 0;
164166 bool hasSlash = filePath.toString().find('/') != std::string::npos;
195195
196196 ProgramInfo::ProgramInfo(Module *m) : M(m), ProgramTimeStamp(0,0) {
197197 assert(M && "Cannot create program information with a null module!");
198 sys::Path modulePath(M->getModuleIdentifier());
199 ProgramTimeStamp = modulePath.getTimestamp();
198 sys::FileStatus Stat;
199 if (!sys::Path(M->getModuleIdentifier()).getFileStatus(Stat))
200 ProgramTimeStamp = Stat.getTimestamp();
200201
201202 SourceFilesIsComplete = false;
202203 SourceFunctionsIsComplete = false;
145145 const sys::Path &FileB,
146146 double AbsTol, double RelTol,
147147 std::string *Error) {
148 sys::FileStatus FileAStat, FileBStat;
149 if (FileA.getFileStatus(FileAStat, Error) ||
150 FileB.getFileStatus(FileBStat, Error))
151 return 2;
152 // Check for zero length files because some systems croak when you try to
153 // mmap an empty file.
154 size_t A_size = FileAStat.getSize();
155 size_t B_size = FileBStat.getSize();
156
157 // If they are both zero sized then they're the same
158 if (A_size == 0 && B_size == 0)
159 return 0;
160 // If only one of them is zero sized then they can't be the same
161 if ((A_size == 0 || B_size == 0))
162 return 1;
163
148164 try {
149 // Check for zero length files because some systems croak when you try to
150 // mmap an empty file.
151 size_t A_size = FileA.getSize();
152 size_t B_size = FileB.getSize();
153
154 // If they are both zero sized then they're the same
155 if (A_size == 0 && B_size == 0)
156 return 0;
157 // If only one of them is zero sized then they can't be the same
158 if ((A_size == 0 || B_size == 0))
159 return 1;
160
161165 // Now its safe to mmap the files into memory becasue both files
162166 // have a non-zero size.
163167 sys::MappedFile F1(FileA);
385385 return path.substr(pos+1);
386386 }
387387
388 void
389 Path::getStatusInfo(StatusInfo& info) const {
388 bool
389 Path::getFileStatus(FileStatus &info, std::string *ErrStr) const {
390390 struct stat buf;
391 if (0 != stat(path.c_str(), &buf)) {
392 ThrowErrno(path + ": can't determine type of path object: ");
393 }
391 if (0 != stat(path.c_str(), &buf))
392 return GetErrno(path + ": can't determine type of path object: ", ErrStr);
394393 info.fileSize = buf.st_size;
395394 info.modTime.fromEpochTime(buf.st_mtime);
396395 info.mode = buf.st_mode;
397396 info.user = buf.st_uid;
398397 info.group = buf.st_gid;
399 info.isDir = S_ISDIR(buf.st_mode);
400 }
401
402 static bool AddPermissionBits(const std::string& Filename, int bits) {
398 info.isDir = S_ISDIR(buf.st_mode);
399 info.isFile = S_ISREG(buf.st_mode);
400 return false;
401 }
402
403 static bool AddPermissionBits(const Path &File, int bits) {
403404 // Get the umask value from the operating system. We want to use it
404405 // when changing the file's permissions. Since calling umask() sets
405406 // the umask and returns its old value, we must call it a second
408409 umask(mask); // Restore the umask.
409410
410411 // Get the file's current mode.
411 struct stat st;
412 if ((stat(Filename.c_str(), &st)) == -1)
413 return false;
412 FileStatus Stat;
413 if (File.getFileStatus(Stat)) return false;
414414
415415 // Change the file to have whichever permissions bits from 'bits'
416416 // that the umask would not disable.
417 if ((chmod(Filename.c_str(), (st.st_mode | (bits & ~mask)))) == -1)
417 if ((chmod(File.c_str(), (Stat.getMode() | (bits & ~mask)))) == -1)
418418 return false;
419419
420420 return true;
421421 }
422422
423423 void Path::makeReadableOnDisk() {
424 if (!AddPermissionBits(path,0444))
424 if (!AddPermissionBits(*this, 0444))
425425 ThrowErrno(path + ": can't make file readable");
426426 }
427427
428428 void Path::makeWriteableOnDisk() {
429 if (!AddPermissionBits(path,0222))
429 if (!AddPermissionBits(*this, 0222))
430430 ThrowErrno(path + ": can't make file writable");
431431 }
432432
433433 void Path::makeExecutableOnDisk() {
434 if (!AddPermissionBits(path,0111))
434 if (!AddPermissionBits(*this, 0111))
435435 ThrowErrno(path + ": can't make file executable");
436436 }
437437
641641 }
642642
643643 bool
644 Path::setStatusInfoOnDisk(const StatusInfo& si) const {
644 Path::setStatusInfoOnDisk(const FileStatus &si) const {
645645 struct utimbuf utb;
646646 utb.actime = si.modTime.toPosixTime();
647647 utb.modtime = utb.actime;
298298 if (checkExistence) {
299299 if (!aPath.exists())
300300 throw std::string("File does not exist: ") + Members[i];
301 sys::Path::StatusInfo si;
302 aPath.getStatusInfo(si);
301 sys::FileStatus si;
302 std::string Err;
303 if (aPath.getFileStatus(si, &Err))
304 throw Err;
303305 if (si.isDir) {
304306 std::set dirpaths = recurseDirectories(aPath);
305307 Paths.insert(dirpaths.begin(),dirpaths.end());
455457 // If we're supposed to retain the original modification times, etc. do so
456458 // now.
457459 if (OriginalDates)
458 I->getPath().setStatusInfoOnDisk(I->getStatusInfo());
460 I->getPath().setStatusInfoOnDisk(I->getFileStatus());
459461 }
460462 }
461463 }
609611 }
610612
611613 if (found != remaining.end()) {
612 sys::Path::StatusInfo si;
613 found->getStatusInfo(si);
614 sys::FileStatus si;
615 std::string Err;
616 if (found->getFileStatus(si, &Err))
617 throw Err;
614618 if (si.isDir) {
615619 if (OnlyUpdate) {
616620 // Replace the item only if it is newer.
4848 eliminateRunInfo();
4949
5050 // If the program has been modified, reload it!
51 sys::Path Program (Dbg.getProgramPath());
52 if (TheProgramInfo->getProgramTimeStamp() != Program.getTimestamp()) {
51 sys::Path Program(Dbg.getProgramPath());
52 sys::FileStatus Status;
53 std::string Err;
54 if (Program.getFileStatus(Status, &Err))
55 throw Err;
56 if (TheProgramInfo->getProgramTimeStamp() != Status.getTimestamp()) {
5357 std::cout << "'" << Program << "' has changed; re-reading program.\n";
5458
5559 // Unload an existing program. This kills the program if necessary.