ProgramMetaData.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.oorexx.org/license.html */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 
39 
40 #include "RexxCore.h"
41 #include "ProgramMetaData.hpp"
42 #include "BufferClass.hpp"
43 #include "Interpreter.hpp"
44 #include <stdio.h>
45 #include <fcntl.h>
46 
47 
48 const char * compiledHeader = "/**/@REXX";
49 
50 
51 /**
52  * Allocate a combined metadata object with the flattened
53  * program data after it.
54  *
55  * @param size The size of the object
56  * @param buff The appended buffer.
57  *
58  * @return The storage allocated for the new instance.
59  */
60 void *ProgramMetaData::operator new (size_t size, RexxBuffer *buff)
61 {
62  // allocate a new buffer for this
63  return SystemInterpreter::allocateResultMemory(buff->getDataLength() + size - sizeof(char[4]));
64 }
65 
66 
67 /**
68  * Initialize the meta data directly from a buffer.
69  *
70  * @param image The image buffer.
71  */
73 {
74  // add the leading header
75  strcpy(fileTag, compiledHeader);
76  // fill in the version specifics and the hardward architecture type
79  // this is the number of bits in a word
82 
83  RexxString *versionNumber = Interpreter::getVersionNumber();
84  strncpy(rexxVersion, versionNumber->getStringData(), sizeof(rexxVersion));
85 
86  // copy in the image information
87  imageSize = size_v(image->getDataLength());
88  memcpy(imageData, image->getData(), imageSize);
89 }
90 
91 
92 /**
93  * Initialize program metadata for a specific size image.
94  *
95  * @param size The size of the program data.
96  */
98 {
99  // add the leading header
100  strcpy(fileTag, compiledHeader);
101  // fill in the version specifics and the hardward architecture type
104  // this is the number of bits in a word
107 
108  RexxString *versionNumber = Interpreter::getVersionNumber();
109  strncpy(rexxVersion, versionNumber->getStringData(), sizeof(rexxVersion));
110 
111  // copy in the image information
112  imageSize = size;
113 }
114 
115 
116 /**
117  * Initialized a default metadata descriptor.
118  */
120 {
121  // this is for the purposes of reading in...force everything to zero.
122  magicNumber = 0;
123  imageVersion = 0;
124  // this is the number of bits in a word
125  wordSize = 0;
126  bigEndian = 0;
127  imageSize = 0;
128 }
129 
130 
131 /**
132  * Get the final size of a copied buffer
133  *
134  * @return The data image size.
135  */
137 {
138  return imageSize + sizeof(*this) - sizeof(imageData);
139 }
140 
141 
142 /**
143  * Get the final size of a copied buffer
144  *
145  * @return The data image size.
146  */
148 {
149  return (char *)&imageData - (char *)this;
150 }
151 
152 
153 /**
154  * Extract the following data as a RexxBuffer object.
155  *
156  * @return The extracted buffer object.
157  */
159 {
160  return new_buffer(imageData, imageSize);
161 }
162 
163 
164 /**
165  * Return a pointer to the inline image data.
166  *
167  * @return The pointer to the image data following the metadata header.
168  */
170 {
171  return imageData;
172 }
173 
174 
175 /**
176  * Validate that this saved program image is valid for this
177  * interpreter.
178  *
179  * @param badVersion Indicates whether this is a version
180  * failure.
181  *
182  * @return true if this is good data, false otherwise.
183  */
184 bool ProgramMetaData::validate(bool &badVersion)
185 {
186  badVersion = false;
187  // we always add the compiled program tag to the front
188  if (strcmp(fileTag, compiledHeader) != 0)
189  {
190  return false;
191  }
192  // check all of the version specifics
195  {
196  // this is a version failure, mark it as such
197  badVersion = true;
198  return false;
199  }
200  // good to go.
201  return true;
202 }
203 
204 
205 /**
206  * Write the metadata to a file.
207  *
208  * @param handle The handle of the output file.
209  * @param program The program buffer data (also written out).
210  */
211 void ProgramMetaData::write(FILE *handle, RexxBuffer *program)
212 {
213  fwrite(this, 1, getHeaderSize(), handle);
214  /* and finally the flattened method */
215  fwrite(program->getData(), 1, size_v(program->getDataLength()), handle);
216 }
217 
218 
219 /**
220  * Read the program meta data and the image data from a file, with
221  * image validation.
222  *
223  * @param handle The input file handle.
224  *
225  * @return A RexxBuffer instance containing the program data, or OREF_NULL
226  * if the file is not a valid image.
227  */
228 RexxBuffer *ProgramMetaData::read(RexxString *fileName, FILE *handle)
229 {
230  bool badVersion = false;
231  size_t readSize;
232 
233  // now read the control info
234  readSize = fread((char *)this, 1, getHeaderSize(), handle);
235  // validate all of the meta information
236  if (!validate(badVersion))
237  {
238  // if this failed because of the version signature, we need to raise an error now.
239  if (badVersion)
240  {
241  fclose(handle); /* close the file */
243  }
244 
245  // if it didn't validate, it might be because we have a unix-style "hash bang" line at the
246  // beginning of the file. The first read in bit has a "#!", then we need to read
247  // beyond the first linend and try again.
248  if (fileTag[0] == '#' && fileTag[1] == '!')
249  {
250  // back to the start (ok, just past the hash bang)
251  fseek(handle, 2, SEEK_SET);
252 
253  while (true)
254  {
255  if (fread(fileTag, 1, 1, handle) <= 0)
256  {
257  fclose(handle);
258  return OREF_NULL;
259  }
260  // if we hit a newline, this is our stopping point.
261  // NB: this works with both \n and \r\n sequences.
262  if (fileTag[0] == '\n')
263  {
264  break;
265  }
266  // ok, try to read the control information one more time.
267  // if this doesn't work, no point in being pushy about it.
268  readSize = fread((char *)this, 1, getHeaderSize(), handle);
269  // validate all of the meta information
270  if (!validate(badVersion))
271  {
272  fclose(handle); /* close the file */
273  // if because of a bad version sig, we can close now
274  if (badVersion)
275  {
277  }
278  return OREF_NULL;
279  }
280  }
281  }
282  }
283  RexxBuffer *buffer = new_buffer(imageSize);
284  readSize = fread(buffer->getData(), 1, imageSize, handle);
285  return buffer;
286 }
void reportException(wholenumber_t error)
RexxBuffer * new_buffer(sizeB_t s)
const char * compiledHeader
#define OREF_NULL
Definition: RexxCore.h:60
#define Error_Program_unreadable_version
static RexxString * getVersionNumber()
Definition: Version.cpp:52
static bool isBigEndian()
static int getWordSize()
void write(FILE *handle, RexxBuffer *program)
unsigned short wordSize
unsigned short bigEndian
unsigned short magicNumber
RexxBuffer * read(RexxString *name, FILE *handle)
RexxBuffer * extractBufferData()
bool validate(bool &)
unsigned short imageVersion
sizeB_t getDataLength()
Definition: BufferClass.hpp:53
virtual char * getData()
const char * getStringData()
static void * allocateResultMemory(sizeB_t)
#define size_v(X)
Definition: rexx.h:237