166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===-- llvm-ar.cpp - LLVM archive librarian utility ----------------------===// 266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// The LLVM Compiler Infrastructure 466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// This file is distributed under the University of Illinois Open Source 666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// License. See LICENSE.TXT for details. 766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===----------------------------------------------------------------------===// 966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 1066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Builds up (relatively) standard unix archive files (.a) containing LLVM 1166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// bitcode or other files. 1266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 1366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===----------------------------------------------------------------------===// 1466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 1566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/LLVMContext.h" 1666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Module.h" 1766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Bitcode/Archive.h" 1866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/CommandLine.h" 1966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/FileSystem.h" 2066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/ManagedStatic.h" 2166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/PrettyStackTrace.h" 2266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/Format.h" 2366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/raw_ostream.h" 2466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/Signals.h" 2566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <algorithm> 2666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <memory> 2766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <fstream> 2866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanusing namespace llvm; 2966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 3066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Option for compatibility with AIX, not used but must allow it to be present. 3166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic cl::opt<bool> 3266b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanX32Option ("X32_64", cl::Hidden, 3366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::desc("Ignored option for compatibility with AIX")); 3466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 3566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// llvm-ar operation code and modifier flags. This must come first. 3666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic cl::opt<std::string> 3766b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanOptions(cl::Positional, cl::Required, cl::desc("{operation}[modifiers]...")); 3866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 3966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// llvm-ar remaining positional arguments. 4066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic cl::list<std::string> 4166b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanRestOfArgs(cl::Positional, cl::OneOrMore, 4266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::desc("[relpos] [count] <archive-file> [members]...")); 4366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 4466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// MoreHelp - Provide additional help output explaining the operations and 4566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// modifiers of llvm-ar. This object instructs the CommandLine library 4666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// to print the text of the constructor when the --help option is given. 4766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic cl::extrahelp MoreHelp( 4866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman "\nOPERATIONS:\n" 4966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " d[NsS] - delete file(s) from the archive\n" 5066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " m[abiSs] - move file(s) in the archive\n" 5166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " p[kN] - print file(s) found in the archive\n" 5266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " q[ufsS] - quick append file(s) to the archive\n" 5366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " r[abfiuzRsS] - replace or insert file(s) into the archive\n" 5466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " t - display contents of archive\n" 5566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " x[No] - extract file(s) from the archive\n" 5666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman "\nMODIFIERS (operation specific):\n" 5766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [a] - put file(s) after [relpos]\n" 5866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [b] - put file(s) before [relpos] (same as [i])\n" 5966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [f] - truncate inserted file names\n" 6066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [i] - put file(s) before [relpos] (same as [b])\n" 6166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [k] - always print bitcode files (default is to skip them)\n" 6266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [N] - use instance [count] of name\n" 6366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [o] - preserve original dates\n" 6466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [P] - use full path names when matching\n" 6566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [R] - recurse through directories when inserting\n" 6666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [s] - create an archive index (cf. ranlib)\n" 6766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [S] - do not build a symbol table\n" 6866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [u] - update only files newer than archive contents\n" 6966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [z] - compress files before inserting/extracting\n" 7066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman "\nMODIFIERS (generic):\n" 7166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [c] - do not warn if the library had to be created\n" 7266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [v] - be verbose about actions taken\n" 7366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " [V] - be *really* verbose about actions taken\n" 7466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman); 7566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 7666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// This enumeration delineates the kinds of operations on an archive 7766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// that are permitted. 7866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanenum ArchiveOperation { 7966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman NoOperation, ///< An operation hasn't been specified 8066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Print, ///< Print the contents of the archive 8166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Delete, ///< Delete the specified members 8266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Move, ///< Move members to end or as given by {a,b,i} modifiers 8366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman QuickAppend, ///< Quickly append to end of archive 8466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ReplaceOrInsert, ///< Replace or Insert members 8566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman DisplayTable, ///< Display the table of contents 8666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Extract ///< Extract files back to file system 8766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}; 8866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 8966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Modifiers to follow operation to vary behavior 9066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool AddAfter = false; ///< 'a' modifier 9166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool AddBefore = false; ///< 'b' modifier 9266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool Create = false; ///< 'c' modifier 9366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool TruncateNames = false; ///< 'f' modifier 9466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool InsertBefore = false; ///< 'i' modifier 9566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool DontSkipBitcode = false; ///< 'k' modifier 9666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool UseCount = false; ///< 'N' modifier 9766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool OriginalDates = false; ///< 'o' modifier 9866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool FullPath = false; ///< 'P' modifier 9966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool RecurseDirectories = false; ///< 'R' modifier 10066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool SymTable = true; ///< 's' & 'S' modifiers 10166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool OnlyUpdate = false; ///< 'u' modifier 10266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool Verbose = false; ///< 'v' modifier 10366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool ReallyVerbose = false; ///< 'V' modifier 10466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool Compression = false; ///< 'z' modifier 10566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 10666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Relative Positional Argument (for insert/move). This variable holds 10766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// the name of the archive member to which the 'a', 'b' or 'i' modifier 10866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// refers. Only one of 'a', 'b' or 'i' can be specified so we only need 10966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// one variable. 11066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstd::string RelPos; 11166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 11266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Select which of multiple entries in the archive with the same name should be 11366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// used (specified with -N) for the delete and extract operations. 11466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanint Count = 1; 11566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 11666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// This variable holds the name of the archive file as given on the 11766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// command line. 11866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstd::string ArchiveName; 11966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 12066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// This variable holds the list of member files to proecess, as given 12166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// on the command line. 12266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstd::vector<std::string> Members; 12366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 12466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// This variable holds the (possibly expanded) list of path objects that 12566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// correspond to files we will 12666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstd::set<sys::Path> Paths; 12766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 12866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// The Archive object to which all the editing operations will be sent. 12966b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanArchive* TheArchive = 0; 13066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 13166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// getRelPos - Extract the member filename from the command line for 13266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// the [relpos] argument associated with a, b, and i modifiers 13366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanvoid getRelPos() { 13466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if(RestOfArgs.size() > 0) { 13566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman RelPos = RestOfArgs[0]; 13666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman RestOfArgs.erase(RestOfArgs.begin()); 13766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 13866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman else 13966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw "Expected [relpos] for a, b, or i modifier"; 14066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 14166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 14266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// getCount - Extract the [count] argument associated with the N modifier 14366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// from the command line and check its value. 14466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanvoid getCount() { 14566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if(RestOfArgs.size() > 0) { 14666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Count = atoi(RestOfArgs[0].c_str()); 14766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman RestOfArgs.erase(RestOfArgs.begin()); 14866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 14966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman else 15066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw "Expected [count] value with N modifier"; 15166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 15266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Non-positive counts are not allowed 15366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Count < 1) 15466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw "Invalid [count] value (not a positive integer)"; 15566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 15666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 15766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// getArchive - Get the archive file name from the command line 15866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanvoid getArchive() { 15966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if(RestOfArgs.size() > 0) { 16066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ArchiveName = RestOfArgs[0]; 16166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman RestOfArgs.erase(RestOfArgs.begin()); 16266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 16366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman else 16466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw "An archive name must be specified."; 16566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 16666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 16766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// getMembers - Copy over remaining items in RestOfArgs to our Members vector 16866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// This is just for clarity. 16966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanvoid getMembers() { 17066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if(RestOfArgs.size() > 0) 17166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Members = std::vector<std::string>(RestOfArgs); 17266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 17366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 17466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// parseCommandLine - Parse the command line options as presented and return the 17566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// operation specified. Process all modifiers and check to make sure that 17666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// constraints on modifier/operation pairs have not been violated. 17766b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanArchiveOperation parseCommandLine() { 17866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 17966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Keep track of number of operations. We can only specify one 18066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // per execution. 18166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned NumOperations = 0; 18266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 18366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Keep track of the number of positional modifiers (a,b,i). Only 18466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // one can be specified. 18566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned NumPositional = 0; 18666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 18766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Keep track of which operation was requested 18866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ArchiveOperation Operation = NoOperation; 18966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 19066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for(unsigned i=0; i<Options.size(); ++i) { 19166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman switch(Options[i]) { 19266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'd': ++NumOperations; Operation = Delete; break; 19366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'm': ++NumOperations; Operation = Move ; break; 19466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'p': ++NumOperations; Operation = Print; break; 19566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'q': ++NumOperations; Operation = QuickAppend; break; 19666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'r': ++NumOperations; Operation = ReplaceOrInsert; break; 19766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 't': ++NumOperations; Operation = DisplayTable; break; 19866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'x': ++NumOperations; Operation = Extract; break; 19966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'c': Create = true; break; 20066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'f': TruncateNames = true; break; 20166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'k': DontSkipBitcode = true; break; 20266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'l': /* accepted but unused */ break; 20366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'o': OriginalDates = true; break; 20466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'P': FullPath = true; break; 20566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'R': RecurseDirectories = true; break; 20666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 's': SymTable = true; break; 20766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'S': SymTable = false; break; 20866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'u': OnlyUpdate = true; break; 20966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'v': Verbose = true; break; 21066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'V': Verbose = ReallyVerbose = true; break; 21166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'z': Compression = true; break; 21266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'a': 21366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman getRelPos(); 21466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman AddAfter = true; 21566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman NumPositional++; 21666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman break; 21766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'b': 21866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman getRelPos(); 21966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman AddBefore = true; 22066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman NumPositional++; 22166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman break; 22266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'i': 22366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman getRelPos(); 22466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman InsertBefore = true; 22566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman NumPositional++; 22666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman break; 22766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case 'N': 22866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman getCount(); 22966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman UseCount = true; 23066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman break; 23166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman default: 23266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::PrintHelpMessage(); 23366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 23466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 23566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 23666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // At this point, the next thing on the command line must be 23766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // the archive name. 23866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman getArchive(); 23966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 24066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Everything on the command line at this point is a member. 24166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman getMembers(); 24266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 24366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Perform various checks on the operation/modifier specification 24466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // to make sure we are dealing with a legal request. 24566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (NumOperations == 0) 24666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw "You must specify at least one of the operations"; 24766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (NumOperations > 1) 24866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw "Only one operation may be specified"; 24966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (NumPositional > 1) 25066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw "You may only specify one of a, b, and i modifiers"; 25166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (AddAfter || AddBefore || InsertBefore) 25266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Operation != Move && Operation != ReplaceOrInsert) 25366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw "The 'a', 'b' and 'i' modifiers can only be specified with " 25466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman "the 'm' or 'r' operations"; 25566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (RecurseDirectories && Operation != ReplaceOrInsert) 25666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw "The 'R' modifiers is only applicabe to the 'r' operation"; 25766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (OriginalDates && Operation != Extract) 25866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw "The 'o' modifier is only applicable to the 'x' operation"; 25966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TruncateNames && Operation!=QuickAppend && Operation!=ReplaceOrInsert) 26066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw "The 'f' modifier is only applicable to the 'q' and 'r' operations"; 26166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (OnlyUpdate && Operation != ReplaceOrInsert) 26266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw "The 'u' modifier is only applicable to the 'r' operation"; 26366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Compression && Operation!=ReplaceOrInsert && Operation!=Extract) 26466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw "The 'z' modifier is only applicable to the 'r' and 'x' operations"; 26566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Count > 1 && Members.size() > 1) 26666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw "Only one member name may be specified with the 'N' modifier"; 26766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 26866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Return the parsed operation to the caller 26966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return Operation; 27066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 27166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 27266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// recurseDirectories - Implements the "R" modifier. This function scans through 27366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// the Paths vector (built by buildPaths, below) and replaces any directories it 27466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// finds with all the files in that directory (recursively). It uses the 27566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// sys::Path::getDirectoryContent method to perform the actual directory scans. 27666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool 27766b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanrecurseDirectories(const sys::Path& path, 27866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::set<sys::Path>& result, std::string* ErrMsg) { 27966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman result.clear(); 28066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (RecurseDirectories) { 28166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::set<sys::Path> content; 28266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (path.getDirectoryContents(content, ErrMsg)) 28366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 28466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 28566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (std::set<sys::Path>::iterator I = content.begin(), E = content.end(); 28666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman I != E; ++I) { 28766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Make sure it exists and is a directory 28866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::PathWithStatus PwS(*I); 28966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const sys::FileStatus *Status = PwS.getFileStatus(false, ErrMsg); 29066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!Status) 29166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 29266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Status->isDir) { 29366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::set<sys::Path> moreResults; 29466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (recurseDirectories(*I, moreResults, ErrMsg)) 29566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 29666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman result.insert(moreResults.begin(), moreResults.end()); 29766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else { 29866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman result.insert(*I); 29966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 30066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 30166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 30266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 30366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 30466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 30566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// buildPaths - Convert the strings in the Members vector to sys::Path objects 30666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// and make sure they are valid and exist exist. This check is only needed for 30766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// the operations that add/replace files to the archive ('q' and 'r') 30866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool buildPaths(bool checkExistence, std::string* ErrMsg) { 30966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0; i < Members.size(); i++) { 31066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path aPath; 31166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!aPath.set(Members[i])) 31266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw std::string("File member name invalid: ") + Members[i]; 31366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (checkExistence) { 31466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman bool Exists; 31566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (sys::fs::exists(aPath.str(), Exists) || !Exists) 31666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw std::string("File does not exist: ") + Members[i]; 31766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string Err; 31866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::PathWithStatus PwS(aPath); 31966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const sys::FileStatus *si = PwS.getFileStatus(false, &Err); 32066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!si) 32166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw Err; 32266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (si->isDir) { 32366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::set<sys::Path> dirpaths; 32466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (recurseDirectories(aPath, dirpaths, ErrMsg)) 32566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 32666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Paths.insert(dirpaths.begin(),dirpaths.end()); 32766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else { 32866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Paths.insert(aPath); 32966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 33066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else { 33166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Paths.insert(aPath); 33266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 33366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 33466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 33566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 33666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 33766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// printSymbolTable - print out the archive's symbol table. 33866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanvoid printSymbolTable() { 33966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "\nArchive Symbol Table:\n"; 34066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const Archive::SymTabType& symtab = TheArchive->getSymbolTable(); 34166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (Archive::SymTabType::const_iterator I=symtab.begin(), E=symtab.end(); 34266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman I != E; ++I ) { 34366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned offset = TheArchive->getFirstFileOffset() + I->second; 34466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << " " << format("%9u", offset) << "\t" << I->first <<"\n"; 34566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 34666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 34766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 34866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// doPrint - Implements the 'p' operation. This function traverses the archive 34966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// looking for members that match the path list. It is careful to uncompress 35066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// things that should be and to skip bitcode files unless the 'k' modifier was 35166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// given. 35266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool doPrint(std::string* ErrMsg) { 35366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (buildPaths(false, ErrMsg)) 35466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 35566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned countDown = Count; 35666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 35766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman I != E; ++I ) { 35866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Paths.empty() || 35966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 36066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (countDown == 1) { 36166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const char* data = reinterpret_cast<const char*>(I->getData()); 36266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 36366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Skip things that don't make sense to print 36466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (I->isLLVMSymbolTable() || I->isSVR4SymbolTable() || 36566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman I->isBSD4SymbolTable() || (!DontSkipBitcode && I->isBitcode())) 36666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman continue; 36766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 36866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Verbose) 36966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "Printing " << I->getPath().str() << "\n"; 37066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 37166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned len = I->getSize(); 37266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs().write(data, len); 37366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else { 37466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman countDown--; 37566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 37666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 37766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 37866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 37966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 38066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 38166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// putMode - utility function for printing out the file mode when the 't' 38266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// operation is in verbose mode. 38366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanvoid 38466b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanprintMode(unsigned mode) { 38566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (mode & 004) 38666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "r"; 38766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman else 38866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "-"; 38966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (mode & 002) 39066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "w"; 39166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman else 39266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "-"; 39366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (mode & 001) 39466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "x"; 39566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman else 39666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "-"; 39766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 39866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 39966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// doDisplayTable - Implement the 't' operation. This function prints out just 40066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// the file names of each of the members. However, if verbose mode is requested 40166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// ('v' modifier) then the file type, permission mode, user, group, size, and 40266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// modification time are also printed. 40366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool 40466b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumandoDisplayTable(std::string* ErrMsg) { 40566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (buildPaths(false, ErrMsg)) 40666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 40766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 40866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman I != E; ++I ) { 40966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Paths.empty() || 41066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 41166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Verbose) { 41266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // FIXME: Output should be this format: 41366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Zrw-r--r-- 500/ 500 525 Nov 8 17:42 2004 Makefile 41466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (I->isBitcode()) 41566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "b"; 41666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman else if (I->isCompressed()) 41766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "Z"; 41866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman else 41966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << " "; 42066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned mode = I->getMode(); 42166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman printMode((mode >> 6) & 007); 42266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman printMode((mode >> 3) & 007); 42366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman printMode(mode & 007); 42466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << " " << format("%4u", I->getUser()); 42566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "/" << format("%4u", I->getGroup()); 42666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << " " << format("%8u", I->getSize()); 42766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << " " << format("%20s", I->getModTime().str().substr(4).c_str()); 42866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << " " << I->getPath().str() << "\n"; 42966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else { 43066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << I->getPath().str() << "\n"; 43166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 43266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 43366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 43466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (ReallyVerbose) 43566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman printSymbolTable(); 43666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 43766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 43866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 43966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// doExtract - Implement the 'x' operation. This function extracts files back to 44066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// the file system, making sure to uncompress any that were compressed 44166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool 44266b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumandoExtract(std::string* ErrMsg) { 44366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (buildPaths(false, ErrMsg)) 44466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 44566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 44666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman I != E; ++I ) { 44766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Paths.empty() || 44866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 44966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 45066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Make sure the intervening directories are created 45166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (I->hasPath()) { 45266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path dirs(I->getPath()); 45366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman dirs.eraseComponent(); 45466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (dirs.createDirectoryOnDisk(/*create_parents=*/true, ErrMsg)) 45566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 45666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 45766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 45866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Open up a file stream for writing 45966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::ios::openmode io_mode = std::ios::out | std::ios::trunc | 46066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::ios::binary; 46166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::ofstream file(I->getPath().c_str(), io_mode); 46266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 46366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Get the data and its length 46466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const char* data = reinterpret_cast<const char*>(I->getData()); 46566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned len = I->getSize(); 46666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 46766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Write the data. 46866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman file.write(data,len); 46966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman file.close(); 47066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 47166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // If we're supposed to retain the original modification times, etc. do so 47266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // now. 47366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (OriginalDates) 47466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman I->getPath().setStatusInfoOnDisk(I->getFileStatus()); 47566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 47666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 47766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 47866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 47966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 48066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// doDelete - Implement the delete operation. This function deletes zero or more 48166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// members from the archive. Note that if the count is specified, there should 48266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// be no more than one path in the Paths list or else this algorithm breaks. 48366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// That check is enforced in parseCommandLine (above). 48466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool 48566b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumandoDelete(std::string* ErrMsg) { 48666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (buildPaths(false, ErrMsg)) 48766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 48866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Paths.empty()) 48966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 49066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned countDown = Count; 49166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 49266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman I != E; ) { 49366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end()) { 49466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (countDown == 1) { 49566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Archive::iterator J = I; 49666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ++I; 49766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman TheArchive->erase(J); 49866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else 49966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman countDown--; 50066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else { 50166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ++I; 50266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 50366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 50466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 50566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // We're done editting, reconstruct the archive. 50666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 50766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 50866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (ReallyVerbose) 50966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman printSymbolTable(); 51066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 51166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 51266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 51366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// doMore - Implement the move operation. This function re-arranges just the 51466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// order of the archive members so that when the archive is written the move 51566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// of the members is accomplished. Note the use of the RelPos variable to 51666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// determine where the items should be moved to. 51766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool 51866b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumandoMove(std::string* ErrMsg) { 51966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (buildPaths(false, ErrMsg)) 52066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 52166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 52266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // By default and convention the place to move members to is the end of the 52366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // archive. 52466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Archive::iterator moveto_spot = TheArchive->end(); 52566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 52666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // However, if the relative positioning modifiers were used, we need to scan 52766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // the archive to find the member in question. If we don't find it, its no 52866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // crime, we just move to the end. 52966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (AddBefore || InsertBefore || AddAfter) { 53066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); 53166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman I != E; ++I ) { 53266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (RelPos == I->getPath().str()) { 53366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (AddAfter) { 53466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman moveto_spot = I; 53566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman moveto_spot++; 53666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else { 53766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman moveto_spot = I; 53866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 53966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman break; 54066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 54166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 54266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 54366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 54466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Keep a list of the paths remaining to be moved 54566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::set<sys::Path> remaining(Paths); 54666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 54766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Scan the archive again, this time looking for the members to move to the 54866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // moveto_spot. 54966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); 55066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman I != E && !remaining.empty(); ++I ) { 55166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::set<sys::Path>::iterator found = 55266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::find(remaining.begin(),remaining.end(),I->getPath()); 55366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (found != remaining.end()) { 55466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (I != moveto_spot) 55566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman TheArchive->splice(moveto_spot,*TheArchive,I); 55666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman remaining.erase(found); 55766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 55866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 55966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 56066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // We're done editting, reconstruct the archive. 56166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 56266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 56366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (ReallyVerbose) 56466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman printSymbolTable(); 56566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 56666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 56766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 56866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// doQuickAppend - Implements the 'q' operation. This function just 56966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// indiscriminantly adds the members to the archive and rebuilds it. 57066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool 57166b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumandoQuickAppend(std::string* ErrMsg) { 57266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Get the list of paths to append. 57366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (buildPaths(true, ErrMsg)) 57466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 57566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Paths.empty()) 57666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 57766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 57866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Append them quickly. 57966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (std::set<sys::Path>::iterator PI = Paths.begin(), PE = Paths.end(); 58066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman PI != PE; ++PI) { 58166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TheArchive->addFileBefore(*PI,TheArchive->end(),ErrMsg)) 58266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 58366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 58466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 58566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // We're done editting, reconstruct the archive. 58666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 58766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 58866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (ReallyVerbose) 58966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman printSymbolTable(); 59066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 59166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 59266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 59366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// doReplaceOrInsert - Implements the 'r' operation. This function will replace 59466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// any existing files or insert new ones into the archive. 59566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanbool 59666b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumandoReplaceOrInsert(std::string* ErrMsg) { 59766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 59866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Build the list of files to be added/replaced. 59966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (buildPaths(true, ErrMsg)) 60066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 60166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Paths.empty()) 60266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 60366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 60466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Keep track of the paths that remain to be inserted. 60566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::set<sys::Path> remaining(Paths); 60666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 60766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Default the insertion spot to the end of the archive 60866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Archive::iterator insert_spot = TheArchive->end(); 60966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 61066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Iterate over the archive contents 61166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 61266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman I != E && !remaining.empty(); ++I ) { 61366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 61466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Determine if this archive member matches one of the paths we're trying 61566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // to replace. 61666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 61766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::set<sys::Path>::iterator found = remaining.end(); 61866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (std::set<sys::Path>::iterator RI = remaining.begin(), 61966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman RE = remaining.end(); RI != RE; ++RI ) { 62066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string compare(RI->str()); 62166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TruncateNames && compare.length() > 15) { 62266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const char* nm = compare.c_str(); 62366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned len = compare.length(); 62466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman size_t slashpos = compare.rfind('/'); 62566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (slashpos != std::string::npos) { 62666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman nm += slashpos + 1; 62766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman len -= slashpos +1; 62866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 62966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (len > 15) 63066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman len = 15; 63166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman compare.assign(nm,len); 63266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 63366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (compare == I->getPath().str()) { 63466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman found = RI; 63566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman break; 63666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 63766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 63866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 63966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (found != remaining.end()) { 64066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string Err; 64166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::PathWithStatus PwS(*found); 64266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const sys::FileStatus *si = PwS.getFileStatus(false, &Err); 64366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!si) 64466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 64566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!si->isDir) { 64666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (OnlyUpdate) { 64766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Replace the item only if it is newer. 64866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (si->modTime > I->getModTime()) 64966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (I->replaceWith(*found, ErrMsg)) 65066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 65166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else { 65266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Replace the item regardless of time stamp 65366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (I->replaceWith(*found, ErrMsg)) 65466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 65566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 65666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else { 65766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // We purposefully ignore directories. 65866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 65966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 66066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Remove it from our "to do" list 66166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman remaining.erase(found); 66266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 66366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 66466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Determine if this is the place where we should insert 66566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if ((AddBefore || InsertBefore) && RelPos == I->getPath().str()) 66666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman insert_spot = I; 66766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman else if (AddAfter && RelPos == I->getPath().str()) { 66866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman insert_spot = I; 66966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman insert_spot++; 67066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 67166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 67266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 67366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // If we didn't replace all the members, some will remain and need to be 67466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // inserted at the previously computed insert-spot. 67566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!remaining.empty()) { 67666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (std::set<sys::Path>::iterator PI = remaining.begin(), 67766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman PE = remaining.end(); PI != PE; ++PI) { 67866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TheArchive->addFileBefore(*PI,insert_spot, ErrMsg)) 67966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 68066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 68166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 68266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 68366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // We're done editting, reconstruct the archive. 68466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 68566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 68666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (ReallyVerbose) 68766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman printSymbolTable(); 68866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 68966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 69066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 69166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// main - main program for llvm-ar .. see comments in the code 69266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanint main(int argc, char **argv) { 69366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Print a stack trace if we signal out. 69466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::PrintStackTraceOnErrorSignal(); 69566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman PrettyStackTraceProgram X(argc, argv); 69666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLVMContext &Context = getGlobalContext(); 69766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 69866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 69966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Have the command line options parsed and handle things 70066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // like --help and --version. 70166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::ParseCommandLineOptions(argc, argv, 70266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman "LLVM Archiver (llvm-ar)\n\n" 70366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman " This program archives bitcode files into single libraries\n" 70466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ); 70566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 70666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman int exitCode = 0; 70766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 70866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Make sure we don't exit with "unhandled exception". 70966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman try { 71066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Do our own parsing of the command line because the CommandLine utility 71166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // can't handle the grouped positional parameters without a dash. 71266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ArchiveOperation Operation = parseCommandLine(); 71366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 71466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Check the path name of the archive 71566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path ArchivePath; 71666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!ArchivePath.set(ArchiveName)) 71766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman throw std::string("Archive name invalid: ") + ArchiveName; 71866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 71966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Create or open the archive object. 72066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman bool Exists; 72166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (llvm::sys::fs::exists(ArchivePath.str(), Exists) || !Exists) { 72266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Produce a warning if we should and we're creating the archive 72366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!Create) 72466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << argv[0] << ": creating " << ArchivePath.str() << "\n"; 72566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman TheArchive = Archive::CreateEmpty(ArchivePath, Context); 72666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman TheArchive->writeToDisk(); 72766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else { 72866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string Error; 72966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman TheArchive = Archive::OpenAndLoad(ArchivePath, Context, &Error); 73066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TheArchive == 0) { 73166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << argv[0] << ": error loading '" << ArchivePath.str() << "': " 73266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman << Error << "!\n"; 73366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return 1; 73466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 73566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 73666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 73766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Make sure we're not fooling ourselves. 73866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman assert(TheArchive && "Unable to instantiate the archive"); 73966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 74066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Make sure we clean up the archive even on failure. 74166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::auto_ptr<Archive> AutoArchive(TheArchive); 74266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 74366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Perform the operation 74466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string ErrMsg; 74566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman bool haveError = false; 74666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman switch (Operation) { 74766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case Print: haveError = doPrint(&ErrMsg); break; 74866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case Delete: haveError = doDelete(&ErrMsg); break; 74966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case Move: haveError = doMove(&ErrMsg); break; 75066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case QuickAppend: haveError = doQuickAppend(&ErrMsg); break; 75166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case ReplaceOrInsert: haveError = doReplaceOrInsert(&ErrMsg); break; 75266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case DisplayTable: haveError = doDisplayTable(&ErrMsg); break; 75366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case Extract: haveError = doExtract(&ErrMsg); break; 75466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case NoOperation: 75566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << argv[0] << ": No operation was selected.\n"; 75666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman break; 75766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 75866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (haveError) { 75966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << argv[0] << ": " << ErrMsg << "\n"; 76066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return 1; 76166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 76266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } catch (const char*msg) { 76366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // These errors are usage errors, thrown only by the various checks in the 76466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // code above. 76566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << argv[0] << ": " << msg << "\n\n"; 76666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::PrintHelpMessage(); 76766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman exitCode = 1; 76866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } catch (const std::string& msg) { 76966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // These errors are thrown by LLVM libraries (e.g. lib System) and represent 77066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // a more serious error so we bump the exitCode and don't print the usage. 77166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << argv[0] << ": " << msg << "\n"; 77266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman exitCode = 2; 77366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } catch (...) { 77466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // This really shouldn't happen, but just in case .... 77566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << argv[0] << ": An unexpected unknown exception occurred.\n"; 77666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman exitCode = 3; 77766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 77866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 77966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Return result code back to operating system. 78066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return exitCode; 78166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 782