unix/FileSystem.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 /* REXX AIX Support aixfile.c */
40 /* */
41 /* AIX specific file related routines. */
42 /* */
43 /******************************************************************************/
44 #ifdef HAVE_CONFIG_H
45 # include "config.h"
46 #endif
47 
48 #include "RexxCore.h"
49 #include "StringClass.hpp"
50 #include "BufferClass.hpp"
51 #include "ProtectedObject.hpp"
52 #include "Interpreter.hpp"
53 #include "SystemInterpreter.hpp"
54 #include "InterpreterInstance.hpp"
55 #include "SysFileSystem.hpp"
56 #include <string.h>
57 #include <stdio.h>
58 #include <stddef.h>
59 #include <sys/stat.h>
60 #include <limits.h>
61 
62 #if defined( HAVE_SYS_FILIO_H )
63 # include <sys/filio.h>
64 #endif
65 
66 #include <sys/ioctl.h>
67 #include <sys/types.h>
68 #include <unistd.h>
69 
70 #ifdef HAVE_STROPTS_H
71 # include <stropts.h>
72 #endif
73 
74 /**
75  * Resolve a program for intial loading or a subroutine call.
76  *
77  * @param _name The target name. This can be fully qualified, or a simple name
78  * without an extension.
79  * @param _parentDir The directory of the file of our calling program. The first place
80  * we'll look is in the same directory as the program.
81  * @param _parentExtension
82  * The extension our calling program has. If there is an extension,
83  * we'll use that version first before trying any of the default
84  * extensions.
85  *
86  * @return A string version of the file name, if found. Returns OREF_NULL if
87  * the program cannot be found.
88  */
90 {
91  char resolvedName[PATH_MAX + 3]; // finally resolved name
92 
93  const char *name = _name->getStringData();
94  const char *parentDir = _parentDir == OREF_NULL ? NULL : _parentDir->getStringData();
95  const char *parentExtension = _parentExtension == OREF_NULL ? NULL : _parentExtension->getStringData();
96  const char *pathExtension = instance->searchPath == OREF_NULL ? NULL : instance->searchPath->getStringData();
97 
98  SysSearchPath searchPath(parentDir, pathExtension);
99 
100  // if the file already has an extension, this dramatically reduces the number
101  // of searches we need to make.
102  if (SysFileSystem::hasExtension(name))
103  {
104  if (SysFileSystem::searchName(name, searchPath.path, NULL, resolvedName))
105  {
106  return new_string(resolvedName);
107  }
108  return OREF_NULL;
109  }
110 
111  // if we have a parent extension provided, use that in preference to any default searches
112  if (parentExtension != NULL)
113  {
114  if (SysFileSystem::searchName(name, searchPath.path, parentExtension, resolvedName))
115  {
116  return new_string(resolvedName);
117  }
118 
119  }
120 
121  // ok, now time to try each of the individual extensions along the way.
122  for (size_t i = instance->searchExtensions->firstIndex(); i != LIST_END; i = instance->searchExtensions->nextIndex(i))
123  {
125 
126  if (SysFileSystem::searchName(name, searchPath.path, ext->getStringData(), resolvedName))
127  {
128  return new_string(resolvedName);
129  }
130  }
131 
132  // The file may purposefully have no extension.
133  if (SysFileSystem::searchName(name, searchPath.path, NULL, resolvedName))
134  {
135  return new_string(resolvedName);
136  }
137 
138  return OREF_NULL;
139 }
140 
141 
142 void SystemInterpreter::loadImage(char **imageBuffer, size_t *imageSize)
143 /*******************************************************************/
144 /* Function : Load the image into storage */
145 /*******************************************************************/
146 {
147  char fullname[PATH_MAX + 2]; // finally resolved name
148  // try first in the current directory
149  FILE *image = fopen(BASEIMAGE, "rb");
150  // if not found, then try a path search
151  if (image == NULL)
152  {
153  // The file may purposefully have no extension.
154  if (!SysFileSystem::primitiveSearchName(BASEIMAGE, getenv("PATH"), NULL, fullname))
155  {
156  #ifdef ORX_CATDIR
157  strcpy(fullname, ORX_CATDIR"/rexx.img");
158  #else
159  Interpreter::logicError("no startup image"); /* open failure */
160  #endif
161  }
162  image = fopen(fullname, "rb");/* try to open the file */
163  if ( image == NULL )
164  {
165  Interpreter::logicError("unable to open image file");
166  }
167  }
168 
169  /* Read in the size of the image */
170  if (!fread(imageSize, 1, sizeof(size_t), image))
171  {
172  Interpreter::logicError("could not check the size of the image");
173  }
174  /* Create new segment for image */
175  *imageBuffer = (char *)memoryObject.allocateImageBuffer(*imageSize);
176  /* Create an object the size of the */
177  /* image. We will be overwriting the */
178  /* object header. */
179  /* read in the image, store the */
180  /* the size read */
181  if (!(*imageSize = fread(*imageBuffer, 1, *imageSize, image)))
182  {
183  Interpreter::logicError("could not read in the image");
184  }
185  fclose(image); /* and close the file */
186 }
187 
188 
190 /*******************************************************************/
191 /* Function: Read a program into a buffer */
192 /*******************************************************************/
193 {
194  FILE *handle; /* open file access handle */
195  size_t buffersize; /* size of read buffer */
196  size_t readSize; // actual bytes read
197  {
198  handle = fopen(file_name, "rb"); /* open as a binary file */
199  if (handle == NULL)
200  { /* open error? */
201  return OREF_NULL; /* return nothing */
202  }
203 
204  fseek(handle, 0, SEEK_END); /* seek to the file end */
205  buffersize = ftell(handle); /* get the file size */
206  fseek(handle, 0, SEEK_SET); /* seek back to the file beginning */
207  }
208  RexxBuffer *buffer = new_buffer(buffersize); /* get a buffer object */
209  ProtectedObject p(buffer);
210  {
211  UnsafeBlock releaser;
212 
213  readSize = fread(buffer->getData(), 1, buffersize, handle);
214  fclose(handle); /* close the file */
215  }
216  if (readSize < buffersize) // read error?
217  {
218  return OREF_NULL; /* return nothing */
219  }
220  return buffer; /* return the program buffer */
221 }
222 
224  RexxString * name) /* stream information block */
225 /*******************************************************************/
226 /* Function: Qualify a stream name for this system */
227 /*******************************************************************/
228 {
229  char nameBuffer[SysFileSystem::MaximumFileNameBuffer];
230 
231  /* clear out the block */
232  memset(nameBuffer, 0, sizeof(nameBuffer));
233  SysFileSystem::qualifyStreamName(name->getStringData(), nameBuffer, sizeof(nameBuffer)); /* expand the full name */
234  /* get the qualified file name */
235  return new_string(nameBuffer);
236 }
237 
238 
239 
240 
RexxBuffer * new_buffer(size_t s)
#define LIST_END
Definition: ListClass.hpp:60
#define OREF_NULL
Definition: RexxCore.h:61
RexxMemory memoryObject
Definition: RexxMemory.cpp:86
RexxString * new_string(const char *s, stringsize_t l)
static void logicError(const char *desc, const char *info1=NULL, size_t info2=0)
virtual char * getData()
size_t firstIndex()
Definition: ListClass.hpp:84
size_t nextIndex(size_t i)
Definition: ListClass.cpp:804
RexxObject * getValue(size_t i)
Definition: ListClass.cpp:276
char * allocateImageBuffer(size_t size)
const char * getStringData()
static bool primitiveSearchName(const char *name, const char *path, const char *extension, char *resolvedName)
static bool searchName(const char *name, const char *path, const char *extension, char *resolvedName)
static void qualifyStreamName(const char *unqualifiedName, char *qualifiedName, size_t bufferSize)
static bool hasExtension(const char *name)
RexxString * resolveProgramName(RexxString *_name, RexxString *_parentDir, RexxString *_parentExtension)
static RexxString * qualifyFileSystemName(RexxString *name)
static RexxBuffer * readProgram(const char *file_name)
static void loadImage(char **imageBuffer, size_t *imageSize)
#define BASEIMAGE