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" 5394bc246a8b2fd0ef371c8f3846ac9a5a367ed9abRafael Espindola " r[abfiuRsS] - 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 "\nMODIFIERS (generic):\n" 70bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [c] - do not warn if the library had to be created\n" 71bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [v] - be verbose about actions taken\n" 72bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [V] - be *really* verbose about actions taken\n" 73bede58363c647a4e73112fdfb409e9af7051301eReid Spencer); 74bede58363c647a4e73112fdfb409e9af7051301eReid Spencer 753a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This enumeration delineates the kinds of operations on an archive 763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// that are permitted. 773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerenum ArchiveOperation { 783a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer NoOperation, ///< An operation hasn't been specified 793a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Print, ///< Print the contents of the archive 803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Delete, ///< Delete the specified members 813a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Move, ///< Move members to end or as given by {a,b,i} modifiers 823a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer QuickAppend, ///< Quickly append to end of archive 833a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ReplaceOrInsert, ///< Replace or Insert members 843a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer DisplayTable, ///< Display the table of contents 85d74ea2bbd8bb630331f35ead42d385249bd42af8Chris Lattner Extract ///< Extract files back to file system 8657bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner}; 8714baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 883a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// Modifiers to follow operation to vary behavior 893a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool AddAfter = false; ///< 'a' modifier 903a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool AddBefore = false; ///< 'b' modifier 913da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukmanbool Create = false; ///< 'c' modifier 923a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool TruncateNames = false; ///< 'f' modifier 933a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool InsertBefore = false; ///< 'i' modifier 94a99be51bf5cdac1438069d4b01766c47704961c8Gabor Greifbool DontSkipBitcode = false; ///< 'k' modifier 953a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool UseCount = false; ///< 'N' modifier 963a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool OriginalDates = false; ///< 'o' modifier 973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool FullPath = false; ///< 'P' modifier 983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool RecurseDirectories = false; ///< 'R' modifier 993a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool SymTable = true; ///< 's' & 'S' modifiers 1003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool OnlyUpdate = false; ///< 'u' modifier 1013a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool Verbose = false; ///< 'v' modifier 1023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool ReallyVerbose = false; ///< 'V' modifier 1033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// Relative Positional Argument (for insert/move). This variable holds 1053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the name of the archive member to which the 'a', 'b' or 'i' modifier 1063a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// refers. Only one of 'a', 'b' or 'i' can be specified so we only need 1073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// one variable. 1083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerstd::string RelPos; 1093a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// Select which of multiple entries in the archive with the same name should be 1113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// used (specified with -N) for the delete and extract operations. 1123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerint Count = 1; 1133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1143a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This variable holds the name of the archive file as given on the 1153a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// command line. 1163a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerstd::string ArchiveName; 1173a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1183a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This variable holds the list of member files to proecess, as given 1193a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// on the command line. 1203a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerstd::vector<std::string> Members; 1213a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This variable holds the (possibly expanded) list of path objects that 1233a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// correspond to files we will 124bede58363c647a4e73112fdfb409e9af7051301eReid Spencerstd::set<sys::Path> Paths; 1253a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1263a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// The Archive object to which all the editing operations will be sent. 1273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid SpencerArchive* TheArchive = 0; 1283a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1293a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// getRelPos - Extract the member filename from the command line for 1303a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the [relpos] argument associated with a, b, and i modifiers 1313a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid getRelPos() { 1323a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if(RestOfArgs.size() > 0) { 1333a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer RelPos = RestOfArgs[0]; 1343a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer RestOfArgs.erase(RestOfArgs.begin()); 1353a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 1363a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 1373a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Expected [relpos] for a, b, or i modifier"; 1383a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 13957bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 1403da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// getCount - Extract the [count] argument associated with the N modifier 1413a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// from the command line and check its value. 1423a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid getCount() { 1433a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if(RestOfArgs.size() > 0) { 1443a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Count = atoi(RestOfArgs[0].c_str()); 1453a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer RestOfArgs.erase(RestOfArgs.begin()); 1463a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 1473a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 1483a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Expected [count] value with N modifier"; 14957bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 1503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Non-positive counts are not allowed 1513a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Count < 1) 1523a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Invalid [count] value (not a positive integer)"; 1533a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 15457bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 1553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// getArchive - Get the archive file name from the command line 1563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid getArchive() { 1573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if(RestOfArgs.size() > 0) { 1583a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ArchiveName = RestOfArgs[0]; 1593a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer RestOfArgs.erase(RestOfArgs.begin()); 1603a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 1613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 1623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "An archive name must be specified."; 1633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 16457bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 1653a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// getMembers - Copy over remaining items in RestOfArgs to our Members vector 1663a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This is just for clarity. 1673a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid getMembers() { 1683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if(RestOfArgs.size() > 0) 1693da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman Members = std::vector<std::string>(RestOfArgs); 1703a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 17114baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1723a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// parseCommandLine - Parse the command line options as presented and return the 1733da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// operation specified. Process all modifiers and check to make sure that 1743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// constraints on modifier/operation pairs have not been violated. 1753a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid SpencerArchiveOperation parseCommandLine() { 17614baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep track of number of operations. We can only specify one 1783a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // per execution. 1793a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned NumOperations = 0; 18014baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1813a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep track of the number of positional modifiers (a,b,i). Only 1823a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // one can be specified. 1833a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned NumPositional = 0; 18414baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1853a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep track of which operation was requested 1863a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ArchiveOperation Operation = NoOperation; 18714baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1883a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for(unsigned i=0; i<Options.size(); ++i) { 1893a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer switch(Options[i]) { 1903a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'd': ++NumOperations; Operation = Delete; break; 1913a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'm': ++NumOperations; Operation = Move ; break; 1923a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'p': ++NumOperations; Operation = Print; break; 193dc32d19c1c8f976e078784da09df1095077738d7Seo Sanghyeon case 'q': ++NumOperations; Operation = QuickAppend; break; 1943da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman case 'r': ++NumOperations; Operation = ReplaceOrInsert; break; 1953a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 't': ++NumOperations; Operation = DisplayTable; break; 1963a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'x': ++NumOperations; Operation = Extract; break; 1973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'c': Create = true; break; 1983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'f': TruncateNames = true; break; 199a99be51bf5cdac1438069d4b01766c47704961c8Gabor Greif case 'k': DontSkipBitcode = true; break; 2003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'l': /* accepted but unused */ break; 2013a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'o': OriginalDates = true; break; 2023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'P': FullPath = true; break; 2033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'R': RecurseDirectories = true; break; 2043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 's': SymTable = true; break; 2053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'S': SymTable = false; break; 2063a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'u': OnlyUpdate = true; break; 2073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'v': Verbose = true; break; 2083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'V': Verbose = ReallyVerbose = true; break; 2093a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'a': 2103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getRelPos(); 2113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer AddAfter = true; 2123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer NumPositional++; 2133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 2143a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'b': 2153a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getRelPos(); 2163a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer AddBefore = true; 2173a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer NumPositional++; 2183a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 2193a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'i': 2203a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getRelPos(); 2213a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer InsertBefore = true; 2223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer NumPositional++; 2233a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 2243a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'N': 2253da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman getCount(); 2263a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer UseCount = true; 2273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 2283a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer default: 229bede58363c647a4e73112fdfb409e9af7051301eReid Spencer cl::PrintHelpMessage(); 23014baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 23114baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 23214baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 2333da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman // At this point, the next thing on the command line must be 2343a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // the archive name. 2353a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getArchive(); 23614baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 2373a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Everything on the command line at this point is a member. 2383a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getMembers(); 23914baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 2403a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Perform various checks on the operation/modifier specification 2413a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // to make sure we are dealing with a legal request. 2423a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (NumOperations == 0) 2433a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "You must specify at least one of the operations"; 2443a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (NumOperations > 1) 2453a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Only one operation may be specified"; 2463a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (NumPositional > 1) 2473a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "You may only specify one of a, b, and i modifiers"; 2483a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (AddAfter || AddBefore || InsertBefore) 2493a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Operation != Move && Operation != ReplaceOrInsert) 2503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'a', 'b' and 'i' modifiers can only be specified with " 2513a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer "the 'm' or 'r' operations"; 2523a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (RecurseDirectories && Operation != ReplaceOrInsert) 2533a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'R' modifiers is only applicabe to the 'r' operation"; 2543a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (OriginalDates && Operation != Extract) 2553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'o' modifier is only applicable to the 'x' operation"; 2563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (TruncateNames && Operation!=QuickAppend && Operation!=ReplaceOrInsert) 2573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'f' modifier is only applicable to the 'q' and 'r' operations"; 2583a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (OnlyUpdate && Operation != ReplaceOrInsert) 2593a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'u' modifier is only applicable to the 'r' operation"; 2603a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Count > 1 && Members.size() > 1) 2613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Only one member name may be specified with the 'N' modifier"; 2623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 2633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Return the parsed operation to the caller 2643a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer return Operation; 26514baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner} 26614baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 2673a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// recurseDirectories - Implements the "R" modifier. This function scans through 2683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the Paths vector (built by buildPaths, below) and replaces any directories it 2693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// finds with all the files in that directory (recursively). It uses the 2703a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// sys::Path::getDirectoryContent method to perform the actual directory scans. 271142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencerbool 27283a113b77c1b57f14175db9d401b949ed64e77adMichael J. SpencerrecurseDirectories(const sys::Path& path, 273142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer std::set<sys::Path>& result, std::string* ErrMsg) { 274142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer result.clear(); 2753a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (RecurseDirectories) { 276bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::set<sys::Path> content; 277142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (path.getDirectoryContents(content, ErrMsg)) 278142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 279142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer 2803da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (std::set<sys::Path>::iterator I = content.begin(), E = content.end(); 2813a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I) { 282142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer // Make sure it exists and is a directory 283184e67e208e2f54a3a89c262a25e45e819f58a61Reid Spencer sys::PathWithStatus PwS(*I); 284184e67e208e2f54a3a89c262a25e45e819f58a61Reid Spencer const sys::FileStatus *Status = PwS.getFileStatus(false, ErrMsg); 2858475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer if (!Status) 2868475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer return true; 2878475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer if (Status->isDir) { 2888475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer std::set<sys::Path> moreResults; 2898475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer if (recurseDirectories(*I, moreResults, ErrMsg)) 2908475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer return true; 2918475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer result.insert(moreResults.begin(), moreResults.end()); 2928475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer } else { 293142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer result.insert(*I); 294142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer } 2953a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 29614baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 297142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 2983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 29914baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 3003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// buildPaths - Convert the strings in the Members vector to sys::Path objects 3013da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// and make sure they are valid and exist exist. This check is only needed for 3023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the operations that add/replace files to the archive ('q' and 'r') 303142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencerbool buildPaths(bool checkExistence, std::string* ErrMsg) { 3043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for (unsigned i = 0; i < Members.size(); i++) { 3053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer sys::Path aPath; 306dd04df0ec33a903ee7fc747701bafde622f77d8bReid Spencer if (!aPath.set(Members[i])) 3073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw std::string("File member name invalid: ") + Members[i]; 3083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (checkExistence) { 30954453f2978c76b3aa71be7bb4e9657c8539f8648Michael J. Spencer bool Exists; 31054453f2978c76b3aa71be7bb4e9657c8539f8648Michael J. Spencer if (sys::fs::exists(aPath.str(), Exists) || !Exists) 3113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw std::string("File does not exist: ") + Members[i]; 312252ad03d7db0add504fdcc6bd67c1bc1e28bdd57Chris Lattner std::string Err; 313184e67e208e2f54a3a89c262a25e45e819f58a61Reid Spencer sys::PathWithStatus PwS(aPath); 314184e67e208e2f54a3a89c262a25e45e819f58a61Reid Spencer const sys::FileStatus *si = PwS.getFileStatus(false, &Err); 3158475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer if (!si) 316252ad03d7db0add504fdcc6bd67c1bc1e28bdd57Chris Lattner throw Err; 3178475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer if (si->isDir) { 318142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer std::set<sys::Path> dirpaths; 319142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (recurseDirectories(aPath, dirpaths, ErrMsg)) 320142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 321bede58363c647a4e73112fdfb409e9af7051301eReid Spencer Paths.insert(dirpaths.begin(),dirpaths.end()); 3223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 323bede58363c647a4e73112fdfb409e9af7051301eReid Spencer Paths.insert(aPath); 3243a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 3253a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 326bede58363c647a4e73112fdfb409e9af7051301eReid Spencer Paths.insert(aPath); 3273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 32814baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 329142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 33014baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner} 33114baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 332bede58363c647a4e73112fdfb409e9af7051301eReid Spencer// printSymbolTable - print out the archive's symbol table. 333bede58363c647a4e73112fdfb409e9af7051301eReid Spencervoid printSymbolTable() { 334424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "\nArchive Symbol Table:\n"; 335bede58363c647a4e73112fdfb409e9af7051301eReid Spencer const Archive::SymTabType& symtab = TheArchive->getSymbolTable(); 3363da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (Archive::SymTabType::const_iterator I=symtab.begin(), E=symtab.end(); 337bede58363c647a4e73112fdfb409e9af7051301eReid Spencer I != E; ++I ) { 338bede58363c647a4e73112fdfb409e9af7051301eReid Spencer unsigned offset = TheArchive->getFirstFileOffset() + I->second; 339424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << " " << format("%9u", offset) << "\t" << I->first <<"\n"; 340bede58363c647a4e73112fdfb409e9af7051301eReid Spencer } 341bede58363c647a4e73112fdfb409e9af7051301eReid Spencer} 342bede58363c647a4e73112fdfb409e9af7051301eReid Spencer 3433a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doPrint - Implements the 'p' operation. This function traverses the archive 3443a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// looking for members that match the path list. It is careful to uncompress 345a99be51bf5cdac1438069d4b01766c47704961c8Gabor Greif// things that should be and to skip bitcode files unless the 'k' modifier was 3463a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// given. 347142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencerbool doPrint(std::string* ErrMsg) { 348142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (buildPaths(false, ErrMsg)) 349142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 3503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned countDown = Count; 3513da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 3523a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I ) { 3533da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman if (Paths.empty() || 3543a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 3553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (countDown == 1) { 3563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer const char* data = reinterpret_cast<const char*>(I->getData()); 3573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 3583a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Skip things that don't make sense to print 3593da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman if (I->isLLVMSymbolTable() || I->isSVR4SymbolTable() || 360e75ca3d809ff17260efa320a949cb91ea2b3981eGabor Greif I->isBSD4SymbolTable() || (!DontSkipBitcode && I->isBitcode())) 3613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer continue; 3623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 3633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Verbose) 364424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "Printing " << I->getPath().str() << "\n"; 3653a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 36644dadffe4bd58ab32961ca5fe537e8ba69c09243Chris Lattner unsigned len = I->getSize(); 367424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs().write(data, len); 3683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 3693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer countDown--; 3703a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 3713a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 37214baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 373142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 3743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 37514baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 3763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// putMode - utility function for printing out the file mode when the 't' 3773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// operation is in verbose mode. 37883a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencervoid 379142ca8e81800ce6bcb511f3250bae23210d38ec8Reid SpencerprintMode(unsigned mode) { 3803da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman if (mode & 004) 381424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "r"; 3823a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 383424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "-"; 3843a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (mode & 002) 385424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "w"; 3863a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 387424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "-"; 3883a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (mode & 001) 389424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "x"; 3903a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 391424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "-"; 3923a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 39314baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 3943a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doDisplayTable - Implement the 't' operation. This function prints out just 3953a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the file names of each of the members. However, if verbose mode is requested 3963a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// ('v' modifier) then the file type, permission mode, user, group, size, and 3973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// modification time are also printed. 39883a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencerbool 399142ca8e81800ce6bcb511f3250bae23210d38ec8Reid SpencerdoDisplayTable(std::string* ErrMsg) { 400142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (buildPaths(false, ErrMsg)) 401142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 4023da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 4033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I ) { 4043da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman if (Paths.empty() || 4053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 4063a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Verbose) { 4073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // FIXME: Output should be this format: 4083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Zrw-r--r-- 500/ 500 525 Nov 8 17:42 2004 Makefile 409e75ca3d809ff17260efa320a949cb91ea2b3981eGabor Greif if (I->isBitcode()) 410424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "b"; 4113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 412424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << " "; 4133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned mode = I->getMode(); 414bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printMode((mode >> 6) & 007); 415bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printMode((mode >> 3) & 007); 416bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printMode(mode & 007); 417424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << " " << format("%4u", I->getUser()); 418424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << "/" << format("%4u", I->getGroup()); 419424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << " " << format("%8u", I->getSize()); 420424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << " " << format("%20s", I->getModTime().str().substr(4).c_str()); 421424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << " " << I->getPath().str() << "\n"; 4223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 423424a04ec4e291fb25782eb412d57e3a36f880c6eChris Lattner outs() << I->getPath().str() << "\n"; 4243a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 42514baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 42614baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 427bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 428bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 429142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 43014baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner} 43114baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 4323a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doExtract - Implement the 'x' operation. This function extracts files back to 43394bc246a8b2fd0ef371c8f3846ac9a5a367ed9abRafael Espindola// the file system. 43483a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencerbool 435142ca8e81800ce6bcb511f3250bae23210d38ec8Reid SpencerdoExtract(std::string* ErrMsg) { 436142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (buildPaths(false, ErrMsg)) 437142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 4383da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 4393a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I ) { 4403a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Paths.empty() || 4413a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 4423a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4433a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Make sure the intervening directories are created 4443a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (I->hasPath()) { 4453a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer sys::Path dirs(I->getPath()); 446dd04df0ec33a903ee7fc747701bafde622f77d8bReid Spencer dirs.eraseComponent(); 44783a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencer if (dirs.createDirectoryOnDisk(/*create_parents=*/true, ErrMsg)) 448e5c9cb5eb6bce502faaedea04014dab46f6540f4Reid Spencer return true; 4493a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 4503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4513a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Open up a file stream for writing 4525fb6ed4ae608c6f7ef589f1069b5dd5c7bdbd60bJeff Cohen std::ios::openmode io_mode = std::ios::out | std::ios::trunc | 4535fb6ed4ae608c6f7ef589f1069b5dd5c7bdbd60bJeff Cohen std::ios::binary; 4545fb6ed4ae608c6f7ef589f1069b5dd5c7bdbd60bJeff Cohen std::ofstream file(I->getPath().c_str(), io_mode); 4553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Get the data and its length 4573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer const char* data = reinterpret_cast<const char*>(I->getData()); 4583a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned len = I->getSize(); 4593a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 46044dadffe4bd58ab32961ca5fe537e8ba69c09243Chris Lattner // Write the data. 46144dadffe4bd58ab32961ca5fe537e8ba69c09243Chris Lattner file.write(data,len); 4623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer file.close(); 4633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4643a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // If we're supposed to retain the original modification times, etc. do so 4653a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // now. 4663a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (OriginalDates) 467252ad03d7db0add504fdcc6bd67c1bc1e28bdd57Chris Lattner I->getPath().setStatusInfoOnDisk(I->getFileStatus()); 4683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 4693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 470e5c9cb5eb6bce502faaedea04014dab46f6540f4Reid Spencer return false; 47157bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 47257bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 4733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doDelete - Implement the delete operation. This function deletes zero or more 4743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// members from the archive. Note that if the count is specified, there should 4753a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// be no more than one path in the Paths list or else this algorithm breaks. 4763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// That check is enforced in parseCommandLine (above). 47783a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencerbool 478142ca8e81800ce6bcb511f3250bae23210d38ec8Reid SpencerdoDelete(std::string* ErrMsg) { 479142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (buildPaths(false, ErrMsg)) 480142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 48183a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencer if (Paths.empty()) 482142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 4833a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned countDown = Count; 4843da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 4853a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ) { 4863a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end()) { 4873a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (countDown == 1) { 4883a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Archive::iterator J = I; 4893a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ++I; 490bede58363c647a4e73112fdfb409e9af7051301eReid Spencer TheArchive->erase(J); 4913a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else 4923a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer countDown--; 4933a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 4943a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ++I; 4953a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 4963a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 49757bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 4983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // We're done editting, reconstruct the archive. 49994bc246a8b2fd0ef371c8f3846ac9a5a367ed9abRafael Espindola if (TheArchive->writeToDisk(SymTable,TruncateNames,ErrMsg)) 500142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 501bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 502bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 503142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 50457bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 50557bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5063a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doMore - Implement the move operation. This function re-arranges just the 5073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// order of the archive members so that when the archive is written the move 5083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// of the members is accomplished. Note the use of the RelPos variable to 5093a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// determine where the items should be moved to. 51083a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencerbool 511142ca8e81800ce6bcb511f3250bae23210d38ec8Reid SpencerdoMove(std::string* ErrMsg) { 51283a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencer if (buildPaths(false, ErrMsg)) 513142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 5143a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5153a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // By default and convention the place to move members to is the end of the 5163a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // archive. 5173a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Archive::iterator moveto_spot = TheArchive->end(); 5183a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5193a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // However, if the relative positioning modifiers were used, we need to scan 5203a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // the archive to find the member in question. If we don't find it, its no 5213a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // crime, we just move to the end. 5223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (AddBefore || InsertBefore || AddAfter) { 5233da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); 5243a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I ) { 52574382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner if (RelPos == I->getPath().str()) { 5263a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (AddAfter) { 5273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer moveto_spot = I; 5283a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer moveto_spot++; 5293a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 5303a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer moveto_spot = I; 5313a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 5323a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 5333a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 5343a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 53557bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner } 53657bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5373a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep a list of the paths remaining to be moved 538bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::set<sys::Path> remaining(Paths); 5393a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5403a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Scan the archive again, this time looking for the members to move to the 5413a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // moveto_spot. 5423da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); 5433a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E && !remaining.empty(); ++I ) { 5443da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman std::set<sys::Path>::iterator found = 5453a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::find(remaining.begin(),remaining.end(),I->getPath()); 5463a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (found != remaining.end()) { 5473da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman if (I != moveto_spot) 548bede58363c647a4e73112fdfb409e9af7051301eReid Spencer TheArchive->splice(moveto_spot,*TheArchive,I); 5493a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer remaining.erase(found); 5503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 55157bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner } 55257bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5533a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // We're done editting, reconstruct the archive. 55494bc246a8b2fd0ef371c8f3846ac9a5a367ed9abRafael Espindola if (TheArchive->writeToDisk(SymTable,TruncateNames,ErrMsg)) 555142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 556bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 557bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 558142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 55957bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 56057bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doQuickAppend - Implements the 'q' operation. This function just 5623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// indiscriminantly adds the members to the archive and rebuilds it. 56383a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencerbool 564142ca8e81800ce6bcb511f3250bae23210d38ec8Reid SpencerdoQuickAppend(std::string* ErrMsg) { 5653a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Get the list of paths to append. 566142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (buildPaths(true, ErrMsg)) 567142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 56883a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencer if (Paths.empty()) 569142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 5703a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5713a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Append them quickly. 572bede58363c647a4e73112fdfb409e9af7051301eReid Spencer for (std::set<sys::Path>::iterator PI = Paths.begin(), PE = Paths.end(); 5733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer PI != PE; ++PI) { 5740ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer if (TheArchive->addFileBefore(*PI,TheArchive->end(),ErrMsg)) 5750ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer return true; 5763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 57757bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5783a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // We're done editting, reconstruct the archive. 57994bc246a8b2fd0ef371c8f3846ac9a5a367ed9abRafael Espindola if (TheArchive->writeToDisk(SymTable,TruncateNames,ErrMsg)) 580142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 581bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 582bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 583142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 58457bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 58557bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5863a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doReplaceOrInsert - Implements the 'r' operation. This function will replace 5873da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// any existing files or insert new ones into the archive. 58883a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencerbool 589142ca8e81800ce6bcb511f3250bae23210d38ec8Reid SpencerdoReplaceOrInsert(std::string* ErrMsg) { 5903a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5913a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Build the list of files to be added/replaced. 592142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (buildPaths(true, ErrMsg)) 593142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 59483a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencer if (Paths.empty()) 595142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 5963a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep track of the paths that remain to be inserted. 598bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::set<sys::Path> remaining(Paths); 5993a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Default the insertion spot to the end of the archive 6013a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Archive::iterator insert_spot = TheArchive->end(); 6023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Iterate over the archive contents 6043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 6053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E && !remaining.empty(); ++I ) { 6063a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Determine if this archive member matches one of the paths we're trying 6083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // to replace. 6090de66b5cc8766102197c565a32bc7f9436b607daReid Spencer 6100de66b5cc8766102197c565a32bc7f9436b607daReid Spencer std::set<sys::Path>::iterator found = remaining.end(); 6113da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (std::set<sys::Path>::iterator RI = remaining.begin(), 6120de66b5cc8766102197c565a32bc7f9436b607daReid Spencer RE = remaining.end(); RI != RE; ++RI ) { 61374382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner std::string compare(RI->str()); 6140de66b5cc8766102197c565a32bc7f9436b607daReid Spencer if (TruncateNames && compare.length() > 15) { 6150de66b5cc8766102197c565a32bc7f9436b607daReid Spencer const char* nm = compare.c_str(); 6160de66b5cc8766102197c565a32bc7f9436b607daReid Spencer unsigned len = compare.length(); 6170de66b5cc8766102197c565a32bc7f9436b607daReid Spencer size_t slashpos = compare.rfind('/'); 6180de66b5cc8766102197c565a32bc7f9436b607daReid Spencer if (slashpos != std::string::npos) { 6190de66b5cc8766102197c565a32bc7f9436b607daReid Spencer nm += slashpos + 1; 6200de66b5cc8766102197c565a32bc7f9436b607daReid Spencer len -= slashpos +1; 6210de66b5cc8766102197c565a32bc7f9436b607daReid Spencer } 6223da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman if (len > 15) 6230de66b5cc8766102197c565a32bc7f9436b607daReid Spencer len = 15; 6240de66b5cc8766102197c565a32bc7f9436b607daReid Spencer compare.assign(nm,len); 6250de66b5cc8766102197c565a32bc7f9436b607daReid Spencer } 62674382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner if (compare == I->getPath().str()) { 6270de66b5cc8766102197c565a32bc7f9436b607daReid Spencer found = RI; 6280de66b5cc8766102197c565a32bc7f9436b607daReid Spencer break; 6290de66b5cc8766102197c565a32bc7f9436b607daReid Spencer } 6300de66b5cc8766102197c565a32bc7f9436b607daReid Spencer } 6310de66b5cc8766102197c565a32bc7f9436b607daReid Spencer 6323a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (found != remaining.end()) { 633252ad03d7db0add504fdcc6bd67c1bc1e28bdd57Chris Lattner std::string Err; 63483a113b77c1b57f14175db9d401b949ed64e77adMichael J. Spencer sys::PathWithStatus PwS(*found); 635184e67e208e2f54a3a89c262a25e45e819f58a61Reid Spencer const sys::FileStatus *si = PwS.getFileStatus(false, &Err); 6368475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer if (!si) 6370ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer return true; 6387d8f9b6133898fcd0c51729b98bc9841ad9b55feChris Lattner if (!si->isDir) { 639bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (OnlyUpdate) { 640bede58363c647a4e73112fdfb409e9af7051301eReid Spencer // Replace the item only if it is newer. 6418475ec068c213d0bf73f7686d82491a8f12e3b32Reid Spencer if (si->modTime > I->getModTime()) 6420ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer if (I->replaceWith(*found, ErrMsg)) 6430ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer return true; 644bede58363c647a4e73112fdfb409e9af7051301eReid Spencer } else { 645bede58363c647a4e73112fdfb409e9af7051301eReid Spencer // Replace the item regardless of time stamp 6460ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer if (I->replaceWith(*found, ErrMsg)) 6470ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer return true; 648bede58363c647a4e73112fdfb409e9af7051301eReid Spencer } 6493a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 650bede58363c647a4e73112fdfb409e9af7051301eReid Spencer // We purposefully ignore directories. 6513a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 6523a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6533a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Remove it from our "to do" list 6543a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer remaining.erase(found); 6553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 65657bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 6573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Determine if this is the place where we should insert 65874382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner if ((AddBefore || InsertBefore) && RelPos == I->getPath().str()) 6593a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer insert_spot = I; 66074382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner else if (AddAfter && RelPos == I->getPath().str()) { 6613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer insert_spot = I; 6623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer insert_spot++; 66357bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner } 66457bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner } 66557bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 6663a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // If we didn't replace all the members, some will remain and need to be 6673a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // inserted at the previously computed insert-spot. 6683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (!remaining.empty()) { 6693da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman for (std::set<sys::Path>::iterator PI = remaining.begin(), 6703a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer PE = remaining.end(); PI != PE; ++PI) { 6710ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer if (TheArchive->addFileBefore(*PI,insert_spot, ErrMsg)) 6720ff2d31766209ce1a69d4d2c5d35761ef57362aaReid Spencer return true; 6733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 6743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 67557bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 6763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // We're done editting, reconstruct the archive. 67794bc246a8b2fd0ef371c8f3846ac9a5a367ed9abRafael Espindola if (TheArchive->writeToDisk(SymTable,TruncateNames,ErrMsg)) 678142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return true; 679bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 680bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 681142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return false; 68257bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 68314baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 6843a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// main - main program for llvm-ar .. see comments in the code 68514baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattnerint main(int argc, char **argv) { 686cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner // Print a stack trace if we signal out. 687cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner sys::PrintStackTraceOnErrorSignal(); 688cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner PrettyStackTraceProgram X(argc, argv); 6890d7c695c74ae6d5f68cc07378c17491915e607d3Owen Anderson LLVMContext &Context = getGlobalContext(); 690cc14d25dd99e891c586bd56aa41796abbe4ac3d8Chris Lattner llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 6913a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6923a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Have the command line options parsed and handle things 6933a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // like --help and --version. 6943a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer cl::ParseCommandLineOptions(argc, argv, 69582a13c9c4811e40d0ff858c508cb54d672ee926eDan Gohman "LLVM Archiver (llvm-ar)\n\n" 696a99be51bf5cdac1438069d4b01766c47704961c8Gabor Greif " This program archives bitcode files into single libraries\n" 6973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ); 6983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6993a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer int exitCode = 0; 7003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 7013a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Make sure we don't exit with "unhandled exception". 7023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer try { 7033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Do our own parsing of the command line because the CommandLine utility 7043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // can't handle the grouped positional parameters without a dash. 7053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ArchiveOperation Operation = parseCommandLine(); 7063a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 7073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Check the path name of the archive 7083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer sys::Path ArchivePath; 709dd04df0ec33a903ee7fc747701bafde622f77d8bReid Spencer if (!ArchivePath.set(ArchiveName)) 7103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw std::string("Archive name invalid: ") + ArchiveName; 7113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 7123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Create or open the archive object. 71354453f2978c76b3aa71be7bb4e9657c8539f8648Michael J. Spencer bool Exists; 71454453f2978c76b3aa71be7bb4e9657c8539f8648Michael J. Spencer if (llvm::sys::fs::exists(ArchivePath.str(), Exists) || !Exists) { 7153a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Produce a warning if we should and we're creating the archive 7163a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (!Create) 71774382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner errs() << argv[0] << ": creating " << ArchivePath.str() << "\n"; 71831895e73591d3c9ceae731a1274c8f56194b9616Owen Anderson TheArchive = Archive::CreateEmpty(ArchivePath, Context); 71963b8c1f6f118dfef44422283947bdc3388c0fcb4Andrew Lenharth TheArchive->writeToDisk(); 7203a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 72167c3821ea002aea0c3be9286d1779cf67fc03451Chris Lattner std::string Error; 72231895e73591d3c9ceae731a1274c8f56194b9616Owen Anderson TheArchive = Archive::OpenAndLoad(ArchivePath, Context, &Error); 723b4ed7b0f809a4023a0e9f80f4530d59d357dc5efReid Spencer if (TheArchive == 0) { 72474382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner errs() << argv[0] << ": error loading '" << ArchivePath.str() << "': " 72565f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman << Error << "!\n"; 726b4ed7b0f809a4023a0e9f80f4530d59d357dc5efReid Spencer return 1; 727b4ed7b0f809a4023a0e9f80f4530d59d357dc5efReid Spencer } 7283a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 72914baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 7303a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Make sure we're not fooling ourselves. 7313a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer assert(TheArchive && "Unable to instantiate the archive"); 7323a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 733bede58363c647a4e73112fdfb409e9af7051301eReid Spencer // Make sure we clean up the archive even on failure. 734bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::auto_ptr<Archive> AutoArchive(TheArchive); 735bede58363c647a4e73112fdfb409e9af7051301eReid Spencer 7363a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Perform the operation 737e5c9cb5eb6bce502faaedea04014dab46f6540f4Reid Spencer std::string ErrMsg; 738142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer bool haveError = false; 7393a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer switch (Operation) { 740142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer case Print: haveError = doPrint(&ErrMsg); break; 741142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer case Delete: haveError = doDelete(&ErrMsg); break; 742142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer case Move: haveError = doMove(&ErrMsg); break; 743142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer case QuickAppend: haveError = doQuickAppend(&ErrMsg); break; 744142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer case ReplaceOrInsert: haveError = doReplaceOrInsert(&ErrMsg); break; 745142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer case DisplayTable: haveError = doDisplayTable(&ErrMsg); break; 746142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer case Extract: haveError = doExtract(&ErrMsg); break; 7473a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case NoOperation: 74865f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman errs() << argv[0] << ": No operation was selected.\n"; 7493a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 7503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 751142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer if (haveError) { 75265f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman errs() << argv[0] << ": " << ErrMsg << "\n"; 753142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer return 1; 754142ca8e81800ce6bcb511f3250bae23210d38ec8Reid Spencer } 7553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } catch (const char*msg) { 7563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // These errors are usage errors, thrown only by the various checks in the 7573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // code above. 75865f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman errs() << argv[0] << ": " << msg << "\n\n"; 759bede58363c647a4e73112fdfb409e9af7051301eReid Spencer cl::PrintHelpMessage(); 7603a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer exitCode = 1; 7613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } catch (const std::string& msg) { 7623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // These errors are thrown by LLVM libraries (e.g. lib System) and represent 7633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // a more serious error so we bump the exitCode and don't print the usage. 76465f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman errs() << argv[0] << ": " << msg << "\n"; 7653a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer exitCode = 2; 7663a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } catch (...) { 7673a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // This really shouldn't happen, but just in case .... 76865f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman errs() << argv[0] << ": An unexpected unknown exception occurred.\n"; 7693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer exitCode = 3; 7703a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 7713a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 7723a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Return result code back to operating system. 7733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer return exitCode; 7743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 775