197f752f6d501f507b5ed433a28f8e6f09cbe5170Chris Lattner//===-- llvm-ar.cpp - LLVM archive librarian utility ----------------------===// 23da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// 37c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell// The LLVM Compiler Infrastructure 47c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell// 521c62da287237d39d0d95004881ea4baae3be6daChris Lattner// This file is distributed under the University of Illinois Open Source 621c62da287237d39d0d95004881ea4baae3be6daChris Lattner// License. See LICENSE.TXT for details. 73da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// 87c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell//===----------------------------------------------------------------------===// 914baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner// 103da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// Builds up (relatively) standard unix archive files (.a) containing LLVM 11a99be51bf5cdac1438069d4b01766c47704961c8Gabor Greif// bitcode or other files. 1214baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner// 1314baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner//===----------------------------------------------------------------------===// 144fa9fd3035780e7733f4b4510d1f98c70f65bfd7Brian Gaeke 158b477ed579794ba6d76915d56b3f448a7dd20120Owen Anderson#include "llvm/LLVMContext.h" 1614baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner#include "llvm/Module.h" 1744dadffe4bd58ab32961ca5fe537e8ba69c09243Chris Lattner#include "llvm/Bitcode/Archive.h" 18551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/CommandLine.h" 1954453f2978c76b3aa71be7bb4e9657c8539f8648Michael J. Spencer#include "llvm/Support/FileSystem.h" 20c30598bc3ad792eb8cc75b188eb872a28c62ab71Chris Lattner#include "llvm/Support/ManagedStatic.h" 21cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner#include "llvm/Support/PrettyStackTrace.h" 22424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner#include "llvm/Support/Format.h" 2365f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman#include "llvm/Support/raw_ostream.h" 241f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Signals.h" 253a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer#include <algorithm> 266927b067bc43427a7db159ba9a603046a4a9c02cDuraid Madina#include <memory> 278da76367c5d6beadd520d35aef77e6d47996ea19Chris Lattner#include <fstream> 283a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerusing namespace llvm; 2957bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 3082f209e42136f1bbed3afc782c78f8ff59409e71Dan Gohman// Option for compatibility with AIX, not used but must allow it to be present. 313da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukmanstatic cl::opt<bool> 323da94aec4d429b2ba0f65fa040c33650cade196bMisha BrukmanX32Option ("X32_64", cl::Hidden, 33bede58363c647a4e73112fdfb409e9af7051301eReid Spencer cl::desc("Ignored option for compatibility with AIX")); 343a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 35bede58363c647a4e73112fdfb409e9af7051301eReid Spencer// llvm-ar operation code and modifier flags. This must come first. 363da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukmanstatic cl::opt<std::string> 373a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid SpencerOptions(cl::Positional, cl::Required, cl::desc("{operation}[modifiers]...")); 383a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 39bede58363c647a4e73112fdfb409e9af7051301eReid Spencer// llvm-ar remaining positional arguments. 403da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukmanstatic cl::list<std::string> 413da94aec4d429b2ba0f65fa040c33650cade196bMisha BrukmanRestOfArgs(cl::Positional, cl::OneOrMore, 423a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer cl::desc("[relpos] [count] <archive-file> [members]...")); 433a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 44bede58363c647a4e73112fdfb409e9af7051301eReid Spencer// MoreHelp - Provide additional help output explaining the operations and 45bede58363c647a4e73112fdfb409e9af7051301eReid Spencer// modifiers of llvm-ar. This object instructs the CommandLine library 46bede58363c647a4e73112fdfb409e9af7051301eReid Spencer// to print the text of the constructor when the --help option is given. 47bede58363c647a4e73112fdfb409e9af7051301eReid Spencerstatic cl::extrahelp MoreHelp( 483da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman "\nOPERATIONS:\n" 49bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " d[NsS] - delete file(s) from the archive\n" 50bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " m[abiSs] - move file(s) in the archive\n" 51bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " p[kN] - print file(s) found in the archive\n" 52bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " q[ufsS] - quick append file(s) to the archive\n" 53bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " r[abfiuzRsS] - replace or insert file(s) into the archive\n" 54bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " t - display contents of archive\n" 55bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " x[No] - extract file(s) from the archive\n" 56bede58363c647a4e73112fdfb409e9af7051301eReid Spencer "\nMODIFIERS (operation specific):\n" 57bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [a] - put file(s) after [relpos]\n" 58bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [b] - put file(s) before [relpos] (same as [i])\n" 59bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [f] - truncate inserted file names\n" 60bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [i] - put file(s) before [relpos] (same as [b])\n" 61a99be51bf5cdac1438069d4b01766c47704961c8Gabor Greif " [k] - always print bitcode files (default is to skip them)\n" 62bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [N] - use instance [count] of name\n" 63bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [o] - preserve original dates\n" 64bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [P] - use full path names when matching\n" 65bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [R] - recurse through directories when inserting\n" 66bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [s] - create an archive index (cf. ranlib)\n" 67bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [S] - do not build a symbol table\n" 68bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [u] - update only files newer than archive contents\n" 69bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [z] - compress files before inserting/extracting\n" 70bede58363c647a4e73112fdfb409e9af7051301eReid Spencer "\nMODIFIERS (generic):\n" 71bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [c] - do not warn if the library had to be created\n" 72bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [v] - be verbose about actions taken\n" 73bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [V] - be *really* verbose about actions taken\n" 74bede58363c647a4e73112fdfb409e9af7051301eReid Spencer); 75bede58363c647a4e73112fdfb409e9af7051301eReid Spencer 763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This enumeration delineates the kinds of operations on an archive 773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// that are permitted. 783a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerenum ArchiveOperation { 793a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer NoOperation, ///< An operation hasn't been specified 803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Print, ///< Print the contents of the archive 813a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Delete, ///< Delete the specified members 823a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Move, ///< Move members to end or as given by {a,b,i} modifiers 833a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer QuickAppend, ///< Quickly append to end of archive 843a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ReplaceOrInsert, ///< Replace or Insert members 853a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer DisplayTable, ///< Display the table of contents 86d74ea2bbd8bb630331f35ead42d385249bd42af8Chris Lattner Extract ///< Extract files back to file system 8757bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner}; 8814baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 893a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// Modifiers to follow operation to vary behavior 903a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool AddAfter = false; ///< 'a' modifier 913a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool AddBefore = false; ///< 'b' modifier 923da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukmanbool Create = false; ///< 'c' modifier 933a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool TruncateNames = false; ///< 'f' modifier 943a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool InsertBefore = false; ///< 'i' modifier 95a99be51bf5cdac1438069d4b01766c47704961c8Gabor Greifbool DontSkipBitcode = false; ///< 'k' modifier 963a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool UseCount = false; ///< 'N' modifier 973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool OriginalDates = false; ///< 'o' modifier 983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool FullPath = false; ///< 'P' modifier 993a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool RecurseDirectories = false; ///< 'R' modifier 1003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool SymTable = true; ///< 's' & 'S' modifiers 1013a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool OnlyUpdate = false; ///< 'u' modifier 1023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool Verbose = false; ///< 'v' modifier 1033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool ReallyVerbose = false; ///< 'V' modifier 1043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool Compression = false; ///< 'z' modifier 1053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1063a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// Relative Positional Argument (for insert/move). This variable holds 1073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the name of the archive member to which the 'a', 'b' or 'i' modifier 1083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// refers. Only one of 'a', 'b' or 'i' can be specified so we only need 1093a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// one variable. 1103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerstd::string RelPos; 1113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// Select which of multiple entries in the archive with the same name should be 1133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// used (specified with -N) for the delete and extract operations. 1143a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerint Count = 1; 1153a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1163a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This variable holds the name of the archive file as given on the 1173a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// command line. 1183a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerstd::string ArchiveName; 1193a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1203a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This variable holds the list of member files to proecess, as given 1213a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// on the command line. 1223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerstd::vector<std::string> Members; 1233a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1243a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This variable holds the (possibly expanded) list of path objects that 1253a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// correspond to files we will 126bede58363c647a4e73112fdfb409e9af7051301eReid Spencerstd::set<sys::Path> Paths; 1273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1283a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// The Archive object to which all the editing operations will be sent. 1293a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid SpencerArchive* TheArchive = 0; 1303a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1313a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// getRelPos - Extract the member filename from the command line for 1323a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the [relpos] argument associated with a, b, and i modifiers 1333a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid getRelPos() { 1343a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if(RestOfArgs.size() > 0) { 1353a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer RelPos = RestOfArgs[0]; 1363a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer RestOfArgs.erase(RestOfArgs.begin()); 1373a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 1383a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 1393a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Expected [relpos] for a, b, or i modifier"; 1403a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 14157bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 1423da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// getCount - Extract the [count] argument associated with the N modifier 1433a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// from the command line and check its value. 1443a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid getCount() { 1453a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if(RestOfArgs.size() > 0) { 1463a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Count = atoi(RestOfArgs[0].c_str()); 1473a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer RestOfArgs.erase(RestOfArgs.begin()); 1483a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 1493a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 1503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Expected [count] value with N modifier"; 15157bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 1523a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Non-positive counts are not allowed 1533a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Count < 1) 1543a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Invalid [count] value (not a positive integer)"; 1553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 15657bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 1573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// getArchive - Get the archive file name from the command line 1583a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid getArchive() { 1593a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if(RestOfArgs.size() > 0) { 1603a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ArchiveName = RestOfArgs[0]; 1613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer RestOfArgs.erase(RestOfArgs.begin()); 1623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 1633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 1643a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "An archive name must be specified."; 1653a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 16657bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 1673a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// getMembers - Copy over remaining items in RestOfArgs to our Members vector 1683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This is just for clarity. 1693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid getMembers() { 1703a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if(RestOfArgs.size() > 0) 1713da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman Members = std::vector<std::string>(RestOfArgs); 1723a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 17314baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// parseCommandLine - Parse the command line options as presented and return the 1753da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// operation specified. Process all modifiers and check to make sure that 1763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// constraints on modifier/operation pairs have not been violated. 1773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid SpencerArchiveOperation parseCommandLine() { 17814baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1793a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep track of number of operations. We can only specify one 1803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // per execution. 1813a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned NumOperations = 0; 18214baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1833a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep track of the number of positional modifiers (a,b,i). Only 1843a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // one can be specified. 1853a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned NumPositional = 0; 18614baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1873a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep track of which operation was requested 1883a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ArchiveOperation Operation = NoOperation; 18914baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1903a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for(unsigned i=0; i<Options.size(); ++i) { 1913a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer switch(Options[i]) { 1923a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'd': ++NumOperations; Operation = Delete; break; 1933a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'm': ++NumOperations; Operation = Move ; break; 1943a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'p': ++NumOperations; Operation = Print; break; 195dc32d19c1c8f976e078784da09df1095077738d7Seo Sanghyeon case 'q': ++NumOperations; Operation = QuickAppend; break; 1963da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman case 'r': ++NumOperations; Operation = ReplaceOrInsert; break; 1973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 't': ++NumOperations; Operation = DisplayTable; break; 1983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'x': ++NumOperations; Operation = Extract; break; 1993a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'c': Create = true; break; 2003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'f': TruncateNames = true; break; 201a99be51bf5cdac1438069d4b01766c47704961c8Gabor Greif case 'k': DontSkipBitcode = true; break; 2023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'l': /* accepted but unused */ break; 2033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'o': OriginalDates = true; break; 2043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'P': FullPath = true; break; 2053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'R': RecurseDirectories = true; break; 2063a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 's': SymTable = true; break; 2073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'S': SymTable = false; break; 2083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'u': OnlyUpdate = true; break; 2093a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'v': Verbose = true; break; 2103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'V': Verbose = ReallyVerbose = true; break; 2113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'z': Compression = true; break; 2123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'a': 2133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getRelPos(); 2143a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer AddAfter = true; 2153a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer NumPositional++; 2163a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 2173a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'b': 2183a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getRelPos(); 2193a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer AddBefore = true; 2203a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer NumPositional++; 2213a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 2223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'i': 2233a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getRelPos(); 2243a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer InsertBefore = true; 2253a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer NumPositional++; 2263a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 2273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'N': 2283da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman getCount(); 2293a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer UseCount = true; 2303a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 2313a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer default: 232bede58363c647a4e73112fdfb409e9af7051301eReid Spencer cl::PrintHelpMessage(); 23314baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 23414baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 23514baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 2363da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman // At this point, the next thing on the command line must be 2373a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // the archive name. 2383a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getArchive(); 23914baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 2403a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Everything on the command line at this point is a member. 2413a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getMembers(); 24214baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 2433a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Perform various checks on the operation/modifier specification 2443a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // to make sure we are dealing with a legal request. 2453a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (NumOperations == 0) 2463a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "You must specify at least one of the operations"; 2473a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (NumOperations > 1) 2483a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Only one operation may be specified"; 2493a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (NumPositional > 1) 2503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "You may only specify one of a, b, and i modifiers"; 2513a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (AddAfter || AddBefore || InsertBefore) 2523a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Operation != Move && Operation != ReplaceOrInsert) 2533a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'a', 'b' and 'i' modifiers can only be specified with " 2543a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer "the 'm' or 'r' operations"; 2553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (RecurseDirectories && Operation != ReplaceOrInsert) 2563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'R' modifiers is only applicabe to the 'r' operation"; 2573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (OriginalDates && Operation != Extract) 2583a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'o' modifier is only applicable to the 'x' operation"; 2593a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (TruncateNames && Operation!=QuickAppend && Operation!=ReplaceOrInsert) 2603a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'f' modifier is only applicable to the 'q' and 'r' operations"; 2613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (OnlyUpdate && Operation != ReplaceOrInsert) 2623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'u' modifier is only applicable to the 'r' operation"; 2633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Compression && Operation!=ReplaceOrInsert && Operation!=Extract) 2643a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'z' modifier is only applicable to the 'r' and 'x' operations"; 2653a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Count > 1 && Members.size() > 1) 2663a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Only one member name may be specified with the 'N' modifier"; 2673a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 2683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Return the parsed operation to the caller 2693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer return Operation; 27014baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner} 27114baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 2723a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// recurseDirectories - Implements the "R" modifier. This function scans through 2733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the Paths vector (built by buildPaths, below) and replaces any directories it 2743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// finds with all the files in that directory (recursively). It uses the 2753a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// sys::Path::getDirectoryContent method to perform the actual directory scans. 276142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencerbool 27783a113b77c1b57f14175db9d401b949ed64e77adMichael J. SpencerrecurseDirectories(const sys::Path& path, 278142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer std::set<sys::Path>& result, std::string* ErrMsg) { 279142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer result.clear(); 2803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (RecurseDirectories) { 281bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::set<sys::Path> content; 282142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (path.getDirectoryContents(content, ErrMsg)) 283142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 284142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer 2853da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (std::set<sys::Path>::iterator I = content.begin(), E = content.end(); 2863a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I) { 287142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer // Make sure it exists and is a directory 288184e67e208e2f54a3a89c262a25e45e819f58a61Reid Spencer sys::PathWithStatus PwS(*I); 289184e67e208e2f54a3a89c262a25e45e819f58a61Reid Spencer const sys::FileStatus *Status = PwS.getFileStatus(false, ErrMsg); 2908475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer if (!Status) 2918475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer return true; 2928475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer if (Status->isDir) { 2938475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer std::set<sys::Path> moreResults; 2948475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer if (recurseDirectories(*I, moreResults, ErrMsg)) 2958475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer return true; 2968475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer result.insert(moreResults.begin(), moreResults.end()); 2978475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer } else { 298142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer result.insert(*I); 299142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer } 3003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 30114baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 302142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 3033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 30414baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 3053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// buildPaths - Convert the strings in the Members vector to sys::Path objects 3063da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// and make sure they are valid and exist exist. This check is only needed for 3073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the operations that add/replace files to the archive ('q' and 'r') 308142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencerbool buildPaths(bool checkExistence, std::string* ErrMsg) { 3093a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for (unsigned i = 0; i < Members.size(); i++) { 3103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer sys::Path aPath; 311dd04df0ec33a903ee7fc747701bafde622f77d8bReid Spencer if (!aPath.set(Members[i])) 3123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw std::string("File member name invalid: ") + Members[i]; 3133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (checkExistence) { 31454453f2978c76b3aa71be7bb4e9657c8539f8648Michael J. Spencer bool Exists; 31554453f2978c76b3aa71be7bb4e9657c8539f8648Michael J. Spencer if (sys::fs::exists(aPath.str(), Exists) || !Exists) 3163a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw std::string("File does not exist: ") + Members[i]; 317252ad03d7db0add504fdcc6bd67c1bc1e28bdd57Chris Lattner std::string Err; 318184e67e208e2f54a3a89c262a25e45e819f58a61Reid Spencer sys::PathWithStatus PwS(aPath); 319184e67e208e2f54a3a89c262a25e45e819f58a61Reid Spencer const sys::FileStatus *si = PwS.getFileStatus(false, &Err); 3208475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer if (!si) 321252ad03d7db0add504fdcc6bd67c1bc1e28bdd57Chris Lattner throw Err; 3228475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer if (si->isDir) { 323142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer std::set<sys::Path> dirpaths; 324142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (recurseDirectories(aPath, dirpaths, ErrMsg)) 325142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 326bede58363c647a4e73112fdfb409e9af7051301eReid Spencer Paths.insert(dirpaths.begin(),dirpaths.end()); 3273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 328bede58363c647a4e73112fdfb409e9af7051301eReid Spencer Paths.insert(aPath); 3293a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 3303a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 331bede58363c647a4e73112fdfb409e9af7051301eReid Spencer Paths.insert(aPath); 3323a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 33314baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 334142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 33514baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner} 33614baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 337bede58363c647a4e73112fdfb409e9af7051301eReid Spencer// printSymbolTable - print out the archive's symbol table. 338bede58363c647a4e73112fdfb409e9af7051301eReid Spencervoid printSymbolTable() { 339424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "\nArchive Symbol Table:\n"; 340bede58363c647a4e73112fdfb409e9af7051301eReid Spencer const Archive::SymTabType& symtab = TheArchive->getSymbolTable(); 3413da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (Archive::SymTabType::const_iterator I=symtab.begin(), E=symtab.end(); 342bede58363c647a4e73112fdfb409e9af7051301eReid Spencer I != E; ++I ) { 343bede58363c647a4e73112fdfb409e9af7051301eReid Spencer unsigned offset = TheArchive->getFirstFileOffset() + I->second; 344424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << " " << format("%9u", offset) << "\t" << I->first <<"\n"; 345bede58363c647a4e73112fdfb409e9af7051301eReid Spencer } 346bede58363c647a4e73112fdfb409e9af7051301eReid Spencer} 347bede58363c647a4e73112fdfb409e9af7051301eReid Spencer 3483a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doPrint - Implements the 'p' operation. This function traverses the archive 3493a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// looking for members that match the path list. It is careful to uncompress 350a99be51bf5cdac1438069d4b01766c47704961c8Gabor Greif// things that should be and to skip bitcode files unless the 'k' modifier was 3513a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// given. 352142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencerbool doPrint(std::string* ErrMsg) { 353142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (buildPaths(false, ErrMsg)) 354142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 3553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned countDown = Count; 3563da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 3573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I ) { 3583da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman if (Paths.empty() || 3593a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 3603a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (countDown == 1) { 3613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer const char* data = reinterpret_cast<const char*>(I->getData()); 3623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 3633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Skip things that don't make sense to print 3643da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman if (I->isLLVMSymbolTable() || I->isSVR4SymbolTable() || 365e75ca3d809ff17260efa320a949cb91ea2b3981eGabor Greif I->isBSD4SymbolTable() || (!DontSkipBitcode && I->isBitcode())) 3663a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer continue; 3673a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 3683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Verbose) 369424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "Printing " << I->getPath().str() << "\n"; 3703a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 37144dadffe4bd58ab32961ca5fe537e8ba69c09243Chris Lattner unsigned len = I->getSize(); 372424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs().write(data, len); 3733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 3743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer countDown--; 3753a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 3763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 37714baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 378142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 3793a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 38014baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 3813a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// putMode - utility function for printing out the file mode when the 't' 3823a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// operation is in verbose mode. 38383a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencervoid 384142ca8e81800ce6bcb511f3250bae23210d38ec8Reid SpencerprintMode(unsigned mode) { 3853da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman if (mode & 004) 386424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "r"; 3873a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 388424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "-"; 3893a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (mode & 002) 390424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "w"; 3913a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 392424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "-"; 3933a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (mode & 001) 394424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "x"; 3953a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 396424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "-"; 3973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 39814baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 3993a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doDisplayTable - Implement the 't' operation. This function prints out just 4003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the file names of each of the members. However, if verbose mode is requested 4013a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// ('v' modifier) then the file type, permission mode, user, group, size, and 4023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// modification time are also printed. 40383a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencerbool 404142ca8e81800ce6bcb511f3250bae23210d38ec8Reid SpencerdoDisplayTable(std::string* ErrMsg) { 405142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (buildPaths(false, ErrMsg)) 406142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 4073da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 4083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I ) { 4093da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman if (Paths.empty() || 4103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 4113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Verbose) { 4123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // FIXME: Output should be this format: 4133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Zrw-r--r-- 500/ 500 525 Nov 8 17:42 2004 Makefile 414e75ca3d809ff17260efa320a949cb91ea2b3981eGabor Greif if (I->isBitcode()) 415424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "b"; 4163a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else if (I->isCompressed()) 417424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "Z"; 4183a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 419424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << " "; 4203a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned mode = I->getMode(); 421bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printMode((mode >> 6) & 007); 422bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printMode((mode >> 3) & 007); 423bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printMode(mode & 007); 424424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << " " << format("%4u", I->getUser()); 425424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "/" << format("%4u", I->getGroup()); 426424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << " " << format("%8u", I->getSize()); 427424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << " " << format("%20s", I->getModTime().str().substr(4).c_str()); 428424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << " " << I->getPath().str() << "\n"; 4293a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 430424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << I->getPath().str() << "\n"; 4313a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 43214baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 43314baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 434bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 435bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 436142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 43714baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner} 43814baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 4393a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doExtract - Implement the 'x' operation. This function extracts files back to 440e5c9cb5eb6bce502faaedea04014dab46f6540f4Reid Spencer// the file system, making sure to uncompress any that were compressed 44183a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencerbool 442142ca8e81800ce6bcb511f3250bae23210d38ec8Reid SpencerdoExtract(std::string* ErrMsg) { 443142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (buildPaths(false, ErrMsg)) 444142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 4453da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 4463a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I ) { 4473a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Paths.empty() || 4483a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 4493a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Make sure the intervening directories are created 4513a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (I->hasPath()) { 4523a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer sys::Path dirs(I->getPath()); 453dd04df0ec33a903ee7fc747701bafde622f77d8bReid Spencer dirs.eraseComponent(); 45483a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencer if (dirs.createDirectoryOnDisk(/*create_parents=*/true, ErrMsg)) 455e5c9cb5eb6bce502faaedea04014dab46f6540f4Reid Spencer return true; 4563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 4573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4583a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Open up a file stream for writing 4595fb6ed4ae608c6f7ef589f1069b5dd5c7bdbd60bJeff Cohen std::ios::openmode io_mode = std::ios::out | std::ios::trunc | 4605fb6ed4ae608c6f7ef589f1069b5dd5c7bdbd60bJeff Cohen std::ios::binary; 4615fb6ed4ae608c6f7ef589f1069b5dd5c7bdbd60bJeff Cohen std::ofstream file(I->getPath().c_str(), io_mode); 4623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Get the data and its length 4643a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer const char* data = reinterpret_cast<const char*>(I->getData()); 4653a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned len = I->getSize(); 4663a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 46744dadffe4bd58ab32961ca5fe537e8ba69c09243Chris Lattner // Write the data. 46844dadffe4bd58ab32961ca5fe537e8ba69c09243Chris Lattner file.write(data,len); 4693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer file.close(); 4703a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4713a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // If we're supposed to retain the original modification times, etc. do so 4723a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // now. 4733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (OriginalDates) 474252ad03d7db0add504fdcc6bd67c1bc1e28bdd57Chris Lattner I->getPath().setStatusInfoOnDisk(I->getFileStatus()); 4753a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 4763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 477e5c9cb5eb6bce502faaedea04014dab46f6540f4Reid Spencer return false; 47857bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 47957bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 4803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doDelete - Implement the delete operation. This function deletes zero or more 4813a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// members from the archive. Note that if the count is specified, there should 4823a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// be no more than one path in the Paths list or else this algorithm breaks. 4833a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// That check is enforced in parseCommandLine (above). 48483a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencerbool 485142ca8e81800ce6bcb511f3250bae23210d38ec8Reid SpencerdoDelete(std::string* ErrMsg) { 486142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (buildPaths(false, ErrMsg)) 487142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 48883a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencer if (Paths.empty()) 489142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 4903a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned countDown = Count; 4913da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 4923a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ) { 4933a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end()) { 4943a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (countDown == 1) { 4953a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Archive::iterator J = I; 4963a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ++I; 497bede58363c647a4e73112fdfb409e9af7051301eReid Spencer TheArchive->erase(J); 4983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else 4993a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer countDown--; 5003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 5013a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ++I; 5023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 5033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 50457bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // We're done editting, reconstruct the archive. 50609069b3bf57df0103f3be3c7cb6e61680c857ca1Reid Spencer if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 507142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 508bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 509bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 510142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 51157bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 51257bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doMore - Implement the move operation. This function re-arranges just the 5143a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// order of the archive members so that when the archive is written the move 5153a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// of the members is accomplished. Note the use of the RelPos variable to 5163a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// determine where the items should be moved to. 51783a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencerbool 518142ca8e81800ce6bcb511f3250bae23210d38ec8Reid SpencerdoMove(std::string* ErrMsg) { 51983a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencer if (buildPaths(false, ErrMsg)) 520142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 5213a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // By default and convention the place to move members to is the end of the 5233a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // archive. 5243a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Archive::iterator moveto_spot = TheArchive->end(); 5253a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5263a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // However, if the relative positioning modifiers were used, we need to scan 5273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // the archive to find the member in question. If we don't find it, its no 5283a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // crime, we just move to the end. 5293a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (AddBefore || InsertBefore || AddAfter) { 5303da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); 5313a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I ) { 53274382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner if (RelPos == I->getPath().str()) { 5333a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (AddAfter) { 5343a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer moveto_spot = I; 5353a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer moveto_spot++; 5363a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 5373a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer moveto_spot = I; 5383a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 5393a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 5403a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 5413a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 54257bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner } 54357bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5443a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep a list of the paths remaining to be moved 545bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::set<sys::Path> remaining(Paths); 5463a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5473a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Scan the archive again, this time looking for the members to move to the 5483a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // moveto_spot. 5493da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); 5503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E && !remaining.empty(); ++I ) { 5513da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman std::set<sys::Path>::iterator found = 5523a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::find(remaining.begin(),remaining.end(),I->getPath()); 5533a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (found != remaining.end()) { 5543da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman if (I != moveto_spot) 555bede58363c647a4e73112fdfb409e9af7051301eReid Spencer TheArchive->splice(moveto_spot,*TheArchive,I); 5563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer remaining.erase(found); 5573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 55857bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner } 55957bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5603a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // We're done editting, reconstruct the archive. 56109069b3bf57df0103f3be3c7cb6e61680c857ca1Reid Spencer if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 562142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 563bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 564bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 565142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 56657bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 56757bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doQuickAppend - Implements the 'q' operation. This function just 5693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// indiscriminantly adds the members to the archive and rebuilds it. 57083a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencerbool 571142ca8e81800ce6bcb511f3250bae23210d38ec8Reid SpencerdoQuickAppend(std::string* ErrMsg) { 5723a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Get the list of paths to append. 573142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (buildPaths(true, ErrMsg)) 574142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 57583a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencer if (Paths.empty()) 576142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 5773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5783a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Append them quickly. 579bede58363c647a4e73112fdfb409e9af7051301eReid Spencer for (std::set<sys::Path>::iterator PI = Paths.begin(), PE = Paths.end(); 5803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer PI != PE; ++PI) { 5810ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer if (TheArchive->addFileBefore(*PI,TheArchive->end(),ErrMsg)) 5820ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer return true; 5833a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 58457bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5853a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // We're done editting, reconstruct the archive. 58609069b3bf57df0103f3be3c7cb6e61680c857ca1Reid Spencer if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 587142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 588bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 589bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 590142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 59157bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 59257bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5933a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doReplaceOrInsert - Implements the 'r' operation. This function will replace 5943da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// any existing files or insert new ones into the archive. 59583a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencerbool 596142ca8e81800ce6bcb511f3250bae23210d38ec8Reid SpencerdoReplaceOrInsert(std::string* ErrMsg) { 5973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Build the list of files to be added/replaced. 599142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (buildPaths(true, ErrMsg)) 600142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 60183a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencer if (Paths.empty()) 602142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 6033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep track of the paths that remain to be inserted. 605bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::set<sys::Path> remaining(Paths); 6063a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Default the insertion spot to the end of the archive 6083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Archive::iterator insert_spot = TheArchive->end(); 6093a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Iterate over the archive contents 6113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 6123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E && !remaining.empty(); ++I ) { 6133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6143a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Determine if this archive member matches one of the paths we're trying 6153a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // to replace. 6160de66b5cc8766102197c565a32bc7f9436b607daReid Spencer 6170de66b5cc8766102197c565a32bc7f9436b607daReid Spencer std::set<sys::Path>::iterator found = remaining.end(); 6183da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (std::set<sys::Path>::iterator RI = remaining.begin(), 6190de66b5cc8766102197c565a32bc7f9436b607daReid Spencer RE = remaining.end(); RI != RE; ++RI ) { 62074382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner std::string compare(RI->str()); 6210de66b5cc8766102197c565a32bc7f9436b607daReid Spencer if (TruncateNames && compare.length() > 15) { 6220de66b5cc8766102197c565a32bc7f9436b607daReid Spencer const char* nm = compare.c_str(); 6230de66b5cc8766102197c565a32bc7f9436b607daReid Spencer unsigned len = compare.length(); 6240de66b5cc8766102197c565a32bc7f9436b607daReid Spencer size_t slashpos = compare.rfind('/'); 6250de66b5cc8766102197c565a32bc7f9436b607daReid Spencer if (slashpos != std::string::npos) { 6260de66b5cc8766102197c565a32bc7f9436b607daReid Spencer nm += slashpos + 1; 6270de66b5cc8766102197c565a32bc7f9436b607daReid Spencer len -= slashpos +1; 6280de66b5cc8766102197c565a32bc7f9436b607daReid Spencer } 6293da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman if (len > 15) 6300de66b5cc8766102197c565a32bc7f9436b607daReid Spencer len = 15; 6310de66b5cc8766102197c565a32bc7f9436b607daReid Spencer compare.assign(nm,len); 6320de66b5cc8766102197c565a32bc7f9436b607daReid Spencer } 63374382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner if (compare == I->getPath().str()) { 6340de66b5cc8766102197c565a32bc7f9436b607daReid Spencer found = RI; 6350de66b5cc8766102197c565a32bc7f9436b607daReid Spencer break; 6360de66b5cc8766102197c565a32bc7f9436b607daReid Spencer } 6370de66b5cc8766102197c565a32bc7f9436b607daReid Spencer } 6380de66b5cc8766102197c565a32bc7f9436b607daReid Spencer 6393a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (found != remaining.end()) { 640252ad03d7db0add504fdcc6bd67c1bc1e28bdd57Chris Lattner std::string Err; 64183a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencer sys::PathWithStatus PwS(*found); 642184e67e208e2f54a3a89c262a25e45e819f58a61Reid Spencer const sys::FileStatus *si = PwS.getFileStatus(false, &Err); 6438475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer if (!si) 6440ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer return true; 6457d8f9b6133898fcd0c51729b98bc9841ad9b55feChris Lattner if (!si->isDir) { 646bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (OnlyUpdate) { 647bede58363c647a4e73112fdfb409e9af7051301eReid Spencer // Replace the item only if it is newer. 6488475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer if (si->modTime > I->getModTime()) 6490ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer if (I->replaceWith(*found, ErrMsg)) 6500ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer return true; 651bede58363c647a4e73112fdfb409e9af7051301eReid Spencer } else { 652bede58363c647a4e73112fdfb409e9af7051301eReid Spencer // Replace the item regardless of time stamp 6530ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer if (I->replaceWith(*found, ErrMsg)) 6540ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer return true; 655bede58363c647a4e73112fdfb409e9af7051301eReid Spencer } 6563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 657bede58363c647a4e73112fdfb409e9af7051301eReid Spencer // We purposefully ignore directories. 6583a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 6593a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6603a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Remove it from our "to do" list 6613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer remaining.erase(found); 6623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 66357bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 6643a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Determine if this is the place where we should insert 66574382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner if ((AddBefore || InsertBefore) && RelPos == I->getPath().str()) 6663a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer insert_spot = I; 66774382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner else if (AddAfter && RelPos == I->getPath().str()) { 6683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer insert_spot = I; 6693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer insert_spot++; 67057bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner } 67157bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner } 67257bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 6733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // If we didn't replace all the members, some will remain and need to be 6743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // inserted at the previously computed insert-spot. 6753a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (!remaining.empty()) { 6763da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (std::set<sys::Path>::iterator PI = remaining.begin(), 6773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer PE = remaining.end(); PI != PE; ++PI) { 6780ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer if (TheArchive->addFileBefore(*PI,insert_spot, ErrMsg)) 6790ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer return true; 6803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 6813a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 68257bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 6833a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // We're done editting, reconstruct the archive. 68409069b3bf57df0103f3be3c7cb6e61680c857ca1Reid Spencer if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 685142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 686bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 687bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 688142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 68957bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 69014baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 6913a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// main - main program for llvm-ar .. see comments in the code 69214baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattnerint main(int argc, char **argv) { 693cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner // Print a stack trace if we signal out. 694cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner sys::PrintStackTraceOnErrorSignal(); 695cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner PrettyStackTraceProgram X(argc, argv); 6960d7c695c74ae6d5f68cc07378c17491915e607d3Owen Anderson LLVMContext &Context = getGlobalContext(); 697cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 6983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6993a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Have the command line options parsed and handle things 7003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // like --help and --version. 7013a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer cl::ParseCommandLineOptions(argc, argv, 70282a13c9c4811e40d0ff858c508cb54d672ee926eDan Gohman "LLVM Archiver (llvm-ar)\n\n" 703a99be51bf5cdac1438069d4b01766c47704961c8Gabor Greif " This program archives bitcode files into single libraries\n" 7043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ); 7053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 7063a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer int exitCode = 0; 7073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 7083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Make sure we don't exit with "unhandled exception". 7093a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer try { 7103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Do our own parsing of the command line because the CommandLine utility 7113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // can't handle the grouped positional parameters without a dash. 7123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ArchiveOperation Operation = parseCommandLine(); 7133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 7143a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Check the path name of the archive 7153a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer sys::Path ArchivePath; 716dd04df0ec33a903ee7fc747701bafde622f77d8bReid Spencer if (!ArchivePath.set(ArchiveName)) 7173a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw std::string("Archive name invalid: ") + ArchiveName; 7183a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 7193a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Create or open the archive object. 72054453f2978c76b3aa71be7bb4e9657c8539f8648Michael J. Spencer bool Exists; 72154453f2978c76b3aa71be7bb4e9657c8539f8648Michael J. Spencer if (llvm::sys::fs::exists(ArchivePath.str(), Exists) || !Exists) { 7223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Produce a warning if we should and we're creating the archive 7233a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (!Create) 72474382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner errs() << argv[0] << ": creating " << ArchivePath.str() << "\n"; 72531895e73591d3c9ceae731a1274c8f56194b9616Owen Anderson TheArchive = Archive::CreateEmpty(ArchivePath, Context); 72663b8c1f6f118dfef44422283947bdc3388c0fcb4Andrew Lenharth TheArchive->writeToDisk(); 7273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 72867c3821ea002aea0c3be9286d1779cf67fc03451Chris Lattner std::string Error; 72931895e73591d3c9ceae731a1274c8f56194b9616Owen Anderson TheArchive = Archive::OpenAndLoad(ArchivePath, Context, &Error); 730b4ed7b0f809a4023a0e9f80f4530d59d357dc5efReid Spencer if (TheArchive == 0) { 73174382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner errs() << argv[0] << ": error loading '" << ArchivePath.str() << "': " 73265f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman << Error << "!\n"; 733b4ed7b0f809a4023a0e9f80f4530d59d357dc5efReid Spencer return 1; 734b4ed7b0f809a4023a0e9f80f4530d59d357dc5efReid Spencer } 7353a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 73614baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 7373a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Make sure we're not fooling ourselves. 7383a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer assert(TheArchive && "Unable to instantiate the archive"); 7393a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 740bede58363c647a4e73112fdfb409e9af7051301eReid Spencer // Make sure we clean up the archive even on failure. 741bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::auto_ptr<Archive> AutoArchive(TheArchive); 742bede58363c647a4e73112fdfb409e9af7051301eReid Spencer 7433a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Perform the operation 744e5c9cb5eb6bce502faaedea04014dab46f6540f4Reid Spencer std::string ErrMsg; 745142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer bool haveError = false; 7463a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer switch (Operation) { 747142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer case Print: haveError = doPrint(&ErrMsg); break; 748142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer case Delete: haveError = doDelete(&ErrMsg); break; 749142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer case Move: haveError = doMove(&ErrMsg); break; 750142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer case QuickAppend: haveError = doQuickAppend(&ErrMsg); break; 751142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer case ReplaceOrInsert: haveError = doReplaceOrInsert(&ErrMsg); break; 752142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer case DisplayTable: haveError = doDisplayTable(&ErrMsg); break; 753142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer case Extract: haveError = doExtract(&ErrMsg); break; 7543a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case NoOperation: 75565f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman errs() << argv[0] << ": No operation was selected.\n"; 7563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 7573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 758142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (haveError) { 75965f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman errs() << argv[0] << ": " << ErrMsg << "\n"; 760142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return 1; 761142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer } 7623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } catch (const char*msg) { 7633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // These errors are usage errors, thrown only by the various checks in the 7643a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // code above. 76565f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman errs() << argv[0] << ": " << msg << "\n\n"; 766bede58363c647a4e73112fdfb409e9af7051301eReid Spencer cl::PrintHelpMessage(); 7673a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer exitCode = 1; 7683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } catch (const std::string& msg) { 7693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // These errors are thrown by LLVM libraries (e.g. lib System) and represent 7703a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // a more serious error so we bump the exitCode and don't print the usage. 77165f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman errs() << argv[0] << ": " << msg << "\n"; 7723a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer exitCode = 2; 7733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } catch (...) { 7743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // This really shouldn't happen, but just in case .... 77565f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman errs() << argv[0] << ": An unexpected unknown exception occurred.\n"; 7763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer exitCode = 3; 7773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 7783a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 7793a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Return result code back to operating system. 7803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer return exitCode; 7813a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 782