summaryrefslogtreecommitdiff
path: root/lib/Archive/ArchiveInternals.h
blob: dde83583c9a4d480616d427047303926afe9faf0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//===-- lib/Bytecode/ArchiveInternals.h -------------------------*- C++ -*-===//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Reid Spencer and is distributed under the 
// University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// Internal implementation header for LLVM Archive files.
//
//===----------------------------------------------------------------------===//

#ifndef LIB_BYTECODE_ARCHIVEINTERNALS_H
#define LIB_BYTECODE_ARCHIVEINTERNALS_H

#include "llvm/Bytecode/Archive.h"
#include "llvm/System/TimeValue.h"

#define ARFILE_MAGIC "!<arch>\n"                   ///< magic string 
#define ARFILE_MAGIC_LEN (sizeof(ARFILE_MAGIC)-1)  ///< length of magic string 
#define ARFILE_SYMTAB_NAME "/"                     ///< name of symtab entry
#define ARFILE_STRTAB_NAME "//"                    ///< name of strtab entry
#define ARFILE_PAD '\n'                            ///< inter-file align padding

namespace llvm {

  /// The ArchiveMemberHeader structure is used internally for bytecode archives. 
  /// The header precedes each file member in the archive. This structure is 
  /// defined using character arrays for direct and correct interpretation
  /// regardless of the endianess of the machine that produced it.
  /// @brief Archive File Member Header
  class ArchiveMemberHeader {
    public:
    void init() {
      memset(name,' ',16);
      memset(date,' ',12);
      memset(uid,' ',6);
      memset(gid,' ',6);
      memset(mode,' ',8);
      memset(size,' ',10);
      fmag[0] = '`';
      fmag[1] = '\n';
    }
    void setDate( int secondsSinceEpoch = 0 ) {
      if (secondsSinceEpoch == 0) {
        sys::TimeValue tv = sys::TimeValue::now();
        uint64_t secs; uint32_t nanos;
        tv.GetTimespecTime(secs,nanos);
        secondsSinceEpoch = (int) secs;
      }
      char buffer[20];
      sprintf(buffer,"%d", secondsSinceEpoch);
      memcpy(date,buffer,strlen(buffer));
    }

    void setSize(size_t sz) {
      char buffer[20];
      sprintf(buffer, "%u", (unsigned)sz);
      memcpy(size,buffer,strlen(buffer));
    }

    void setMode(int m) {
      char buffer[20];
      sprintf(buffer, "%o", m);
      memcpy(mode,buffer,strlen(buffer));
    }

    void setUid(unsigned u) {
      char buffer[20];
      sprintf(buffer, "%u", u);
      memcpy(uid,buffer,strlen(buffer));
    }

    void setGid(unsigned g) {
      char buffer[20];
      sprintf(buffer, "%u", g);
      memcpy(gid,buffer,strlen(buffer));
    }

    bool setName(const std::string& nm) {
      if (nm.length() > 0 && nm.length() <= 16) {
        memcpy(name,nm.c_str(),nm.length());
        for (int i = nm.length()+1; i < 16; i++ ) name[i] = ' ';
        return true;
      }
      return false;
    }

    private:
    char name[16];  ///< Name of the file member. The filename is terminated with '/'
                    ///< and blanks. The empty name (/ and 15 blanks) is for the 
                    ///< symbol table. The special name "//" and 15 blanks is for
                    ///< the string table, used for long file names. It must be
                    ///< first in the archive.
    char date[12];  ///< File date, decimal seconds since Epoch
    char uid[6];    ///< user id in ASCII decimal
    char gid[6];    ///< group id in ASCII decimal
    char mode[8];   ///< file mode in ASCII octal
    char size[10];  ///< file size in ASCII decimal
    char fmag[2];   ///< Always contains ARFILE_MAGIC_TERMINATOR

  };

  /// The ArchiveInternals class is used to hold the content of the archive
  /// while it is in memory. It also provides the bulk of the implementation for
  /// the llvm:Archive class's interface.
  class Archive::ArchiveInternals {
    /// @name Types
    /// @{
    public:
      typedef std::vector<std::string> StrTab;

      /// This structure holds information for one member in the archive. It is
      /// used temporarily while the contents of the archive are being
      /// determined.
      struct MemberInfo {
        MemberInfo() {}
        sys::Path path;
        std::string name;
        sys::Path::StatusInfo status;
        StrTab symbols;
        unsigned offset;
      };

    /// @}
    /// @name Methods
    /// @{
    public:
      /// @brief Add a file member to the archive.
      void addFileMember(
        const sys::Path& path,         ///< The path to the file to be added
        const std::string& name,       ///< The name for the member
        const StrTab* syms = 0         ///< The symbol table of the member
      );

      /// @brief Write the accumulated archive information to an archive file
      void writeArchive();
      void writeMember(const MemberInfo& member,std::ofstream& ARFile);
      void writeSymbolTable(std::ofstream& ARFile);
      void writeInteger(int num, std::ofstream& ARFile);

    /// @}
    /// @name  Data
    /// @{
    private:
      friend class Archive;            ///< Parent class is a friend
      sys::Path       fname;           ///< Path to the archive file
      std::vector<MemberInfo> members; ///< Info about member files
      Archive::SymTab* symtab;         ///< User's symbol table

    /// @}
  };
}

#endif

// vim: sw=2 ai