llvm.org GIT mirror llvm / 142ca8e
For PR797: Remove exception throwing from Path::getDirectoryContents and its users. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29841 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Spencer 14 years ago
5 changed file(s) with 114 addition(s) and 77 deletion(s). Raw diff Collapse all Expand all
342342
343343 /// This function builds a list of paths that are the names of the
344344 /// files and directories in a directory.
345 /// @returns false if \p this is not a directory, true otherwise
346 /// @throws std::string if the directory cannot be searched
345 /// @returns true if an error occurs, true otherwise
347346 /// @brief Build a list of directory's contents.
348 bool getDirectoryContents(std::set &paths) const;
347 bool getDirectoryContents(
348 std::set &paths, ///< The resulting list of file & directory names
349 std::string* ErrMsg ///< Optional place to return an error message.
350 ) const;
349351
350352 /// This function returns status information about the file. The type of
351353 /// path (file or directory) is updated to reflect the actual contents
414414 }
415415
416416 bool
417 Path::getDirectoryContents(std::set& result) const {
417 Path::getDirectoryContents(std::set& result, std::string* ErrMsg) const {
418418 DIR* direntries = ::opendir(path.c_str());
419 if (direntries == 0)
420 ThrowErrno(path + ": can't open directory");
419 if (direntries == 0) {
420 MakeErrMsg(ErrMsg, path + ": can't open directory");
421 return true;
422 }
421423
422424 std::string dirPath = path;
423425 if (!lastIsSlash(dirPath))
432434 if (0 != lstat(aPath.path.c_str(), &st)) {
433435 if (S_ISLNK(st.st_mode))
434436 continue; // dangling symlink -- ignore
435 ThrowErrno(aPath.path + ": can't determine file object type");
437 MakeErrMsg(ErrMsg, aPath.path + ": can't determine file object type");
438 return true;
436439 }
437440 result.insert(aPath);
438441 }
439442 }
440443
441444 closedir(direntries);
442 return true;
445 return false;
443446 }
444447
445448 bool
352352 }
353353
354354 bool
355 Path::getDirectoryContents(std::set& result) const {
356 if (!isDirectory())
357 return false;
355 Path::getDirectoryContents(std::set& result, std::string* ErrMsg) const {
356 if (!isDirectory()) {
357 MakeErrMsg(ErrMsg, path + ": not a directory");
358 return true;
359 }
358360
359361 result.clear();
360362 WIN32_FIND_DATA fd;
368370 if (h == INVALID_HANDLE_VALUE) {
369371 if (GetLastError() == ERROR_FILE_NOT_FOUND)
370372 return true; // not really an error, now is it?
371 ThrowError(path + ": Can't read directory: ");
373 MakeErrMsg(ErrMsg, path + ": Can't read directory: ");
374 return true;
372375 }
373376
374377 do {
383386 FindClose(h);
384387 if (err != ERROR_NO_MORE_FILES) {
385388 SetLastError(err);
386 ThrowError(path + ": Can't read directory: ");
387 }
388 return true;
389 MakeErrMsg(ErrMsg, path + ": Can't read directory: ");
390 return true;
391 }
392 return false;
389393 }
390394
391395 bool
156156
157157 // Grab the contents of the -L path
158158 std::set Files;
159 LPath.getDirectoryContents(Files);
159 if (LPath.getDirectoryContents(Files, 0))
160 return false;
160161
161162 // Iterate over the contents one by one to determine
162163 // if this -L path has any bytecode shared libraries
268268 // the Paths vector (built by buildPaths, below) and replaces any directories it
269269 // finds with all the files in that directory (recursively). It uses the
270270 // sys::Path::getDirectoryContent method to perform the actual directory scans.
271 std::set recurseDirectories(const sys::Path& path) {
272 std::set result;
271 bool
272 recurseDirectories(const sys::Path& path,
273 std::set& result, std::string* ErrMsg) {
274 result.clear();
273275 if (RecurseDirectories) {
274276 std::set content;
275 path.getDirectoryContents(content);
277 if (path.getDirectoryContents(content, ErrMsg))
278 return true;
279
276280 for (std::set::iterator I = content.begin(), E = content.end();
277281 I != E; ++I) {
278 // Make sure it exists and is a directory
279 sys::FileStatus Status;
280 if (!I->getFileStatus(Status)) {
281 if (Status.isDir) {
282 std::set moreResults = recurseDirectories(*I);
283 result.insert(moreResults.begin(), moreResults.end());
284 } else {
285 result.insert(*I);
286 }
287 }
288 }
289 }
290 return result;
282 // 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 {
291 result.insert(*I);
292 }
293 }
294 }
295 }
296 return false;
291297 }
292298
293299 // buildPaths - Convert the strings in the Members vector to sys::Path objects
294300 // and make sure they are valid and exist exist. This check is only needed for
295301 // the operations that add/replace files to the archive ('q' and 'r')
296 void buildPaths(bool checkExistence = true) {
302 bool buildPaths(bool checkExistence, std::string* ErrMsg) {
297303 for (unsigned i = 0; i < Members.size(); i++) {
298304 sys::Path aPath;
299305 if (!aPath.set(Members[i]))
306312 if (aPath.getFileStatus(si, &Err))
307313 throw Err;
308314 if (si.isDir) {
309 std::set dirpaths = recurseDirectories(aPath);
315 std::set dirpaths;
316 if (recurseDirectories(aPath, dirpaths, ErrMsg))
317 return true;
310318 Paths.insert(dirpaths.begin(),dirpaths.end());
311319 } else {
312320 Paths.insert(aPath);
315323 Paths.insert(aPath);
316324 }
317325 }
326 return false;
318327 }
319328
320329 // printSymbolTable - print out the archive's symbol table.
332341 // looking for members that match the path list. It is careful to uncompress
333342 // things that should be and to skip bytecode files unless the 'k' modifier was
334343 // given.
335 void doPrint() {
336 buildPaths(false);
344 bool doPrint(std::string* ErrMsg) {
345 if (buildPaths(false, ErrMsg))
346 return true;
337347 unsigned countDown = Count;
338348 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
339349 I != E; ++I ) {
364374 }
365375 }
366376 }
377 return false;
367378 }
368379
369380 // putMode - utility function for printing out the file mode when the 't'
370381 // operation is in verbose mode.
371 void printMode(unsigned mode) {
382 void
383 printMode(unsigned mode) {
372384 if (mode & 004)
373385 std::cout << "r";
374386 else
387399 // the file names of each of the members. However, if verbose mode is requested
388400 // ('v' modifier) then the file type, permission mode, user, group, size, and
389401 // modification time are also printed.
390 void doDisplayTable() {
391 buildPaths(false);
402 bool
403 doDisplayTable(std::string* ErrMsg) {
404 if (buildPaths(false, ErrMsg))
405 return true;
392406 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
393407 I != E; ++I ) {
394408 if (Paths.empty() ||
421435 }
422436 if (ReallyVerbose)
423437 printSymbolTable();
438 return false;
424439 }
425440
426441 // doExtract - Implement the 'x' operation. This function extracts files back to
427442 // the file system, making sure to uncompress any that were compressed
428 bool doExtract(std::string* ErrMsg) {
429 buildPaths(false);
443 bool
444 doExtract(std::string* ErrMsg) {
445 if (buildPaths(false, ErrMsg))
446 return true;
430447 unsigned countDown = Count;
431448 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
432449 I != E; ++I ) {
471488 // members from the archive. Note that if the count is specified, there should
472489 // be no more than one path in the Paths list or else this algorithm breaks.
473490 // That check is enforced in parseCommandLine (above).
474 void doDelete() {
475 buildPaths(false);
476 if (Paths.empty()) return;
491 bool
492 doDelete(std::string* ErrMsg) {
493 if (buildPaths(false, ErrMsg))
494 return true;
495 if (Paths.empty())
496 return false;
477497 unsigned countDown = Count;
478498 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
479499 I != E; ) {
490510 }
491511
492512 // We're done editting, reconstruct the archive.
493 std::string errmsg;
494 if (!TheArchive->writeToDisk(SymTable,TruncateNames,Compression,&errmsg))
495 throw errmsg;
513 if (!TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg))
514 return true;
496515 if (ReallyVerbose)
497516 printSymbolTable();
517 return false;
498518 }
499519
500520 // doMore - Implement the move operation. This function re-arranges just the
501521 // order of the archive members so that when the archive is written the move
502522 // of the members is accomplished. Note the use of the RelPos variable to
503523 // determine where the items should be moved to.
504 void doMove() {
505
506 buildPaths(false);
524 bool
525 doMove(std::string* ErrMsg) {
526 if (buildPaths(false, ErrMsg))
527 return true;
507528
508529 // By default and convention the place to move members to is the end of the
509530 // archive.
544565 }
545566
546567 // We're done editting, reconstruct the archive.
547 std::string errmsg;
548 if (!TheArchive->writeToDisk(SymTable,TruncateNames,Compression,&errmsg))
549 throw errmsg;
568 if (!TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg))
569 return true;
550570 if (ReallyVerbose)
551571 printSymbolTable();
572 return false;
552573 }
553574
554575 // doQuickAppend - Implements the 'q' operation. This function just
555576 // indiscriminantly adds the members to the archive and rebuilds it.
556 void doQuickAppend() {
577 bool
578 doQuickAppend(std::string* ErrMsg) {
557579 // Get the list of paths to append.
558 buildPaths(true);
559 if (Paths.empty()) return;
580 if (buildPaths(true, ErrMsg))
581 return true;
582 if (Paths.empty())
583 return false;
560584
561585 // Append them quickly.
562586 for (std::set::iterator PI = Paths.begin(), PE = Paths.end();
565589 }
566590
567591 // We're done editting, reconstruct the archive.
568 std::string errmsg;
569 if (!TheArchive->writeToDisk(SymTable,TruncateNames,Compression,&errmsg))
570 throw errmsg;
592 if (!TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg))
593 return true;
571594 if (ReallyVerbose)
572595 printSymbolTable();
596 return false;
573597 }
574598
575599 // doReplaceOrInsert - Implements the 'r' operation. This function will replace
576600 // any existing files or insert new ones into the archive.
577 void doReplaceOrInsert() {
601 bool
602 doReplaceOrInsert(std::string* ErrMsg) {
578603
579604 // Build the list of files to be added/replaced.
580 buildPaths(true);
581 if (Paths.empty()) return;
605 if (buildPaths(true, ErrMsg))
606 return true;
607 if (Paths.empty())
608 return false;
582609
583610 // Keep track of the paths that remain to be inserted.
584611 std::set remaining(Paths);
656683 }
657684
658685 // We're done editting, reconstruct the archive.
659 std::string errmsg;
660 if (!TheArchive->writeToDisk(SymTable,TruncateNames,Compression,&errmsg))
661 throw errmsg;
686 if (!TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg))
687 return true;
662688 if (ReallyVerbose)
663689 printSymbolTable();
690 return false;
664691 }
665692
666693 // main - main program for llvm-ar .. see comments in the code
713740
714741 // Perform the operation
715742 std::string ErrMsg;
743 bool haveError = false;
716744 switch (Operation) {
717 case Print: doPrint(); break;
718 case Delete: doDelete(); break;
719 case Move: doMove(); break;
720 case QuickAppend: /* FALL THROUGH */
721 case ReplaceOrInsert: doReplaceOrInsert(); break;
722 case DisplayTable: doDisplayTable(); break;
723 case Extract:
724 if (doExtract(&ErrMsg)) {
725 std::cerr << argv[0] << ": " << ErrMsg << "\n";
726 return 1;
727 }
728 break;
745 case Print: haveError = doPrint(&ErrMsg); break;
746 case Delete: haveError = doDelete(&ErrMsg); break;
747 case Move: haveError = doMove(&ErrMsg); break;
748 case QuickAppend: haveError = doQuickAppend(&ErrMsg); break;
749 case ReplaceOrInsert: haveError = doReplaceOrInsert(&ErrMsg); break;
750 case DisplayTable: haveError = doDisplayTable(&ErrMsg); break;
751 case Extract: haveError = doExtract(&ErrMsg); break;
729752 case NoOperation:
730753 std::cerr << argv[0] << ": No operation was selected.\n";
731754 break;
755 }
756 if (haveError) {
757 std::cerr << argv[0] << ": " << ErrMsg << "\n";
758 return 1;
732759 }
733760 } catch (const char*msg) {
734761 // These errors are usage errors, thrown only by the various checks in the