windows/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 Kernel */
40 /* */
41 /* Windows specific file related routines. */
42 /* */
43 /******************************************************************************/
44 
45 #include "RexxCore.h"
46 #include "StringClass.hpp"
47 #include "BufferClass.hpp"
48 #include "ActivityManager.hpp"
49 #include "ProtectedObject.hpp"
50 #include "Interpreter.hpp"
51 #include "SystemInterpreter.hpp"
52 #include "InterpreterInstance.hpp"
53 #include "SysFileSystem.hpp"
54 #include <string.h>
55 #include <io.h>
56 #include <fcntl.h>
57 #include <conio.h>
58 #define MAX_STDOUT_LENGTH 32767 /* max. amount of data to push to STDOUT @THU007A */ /* @HOL007M */
59 
60 
61 /**
62  * Resolve a program for intial loading or a subroutine call.
63  *
64  * @param _name The target name. This can be fully qualified, or a simple name
65  * without an extension.
66  * @param _parentDir The directory of the file of our calling program. The first place
67  * we'll look is in the same directory as the program.
68  * @param _parentExtension
69  * The extension our calling program has. If there is an extension,
70  * we'll use that version first before trying any of the default
71  * extensions.
72  *
73  * @return A string version of the file name, if found. Returns OREF_NULL if
74  * the program cannot be found.
75  */
77 {
78  char resolvedName[MAX_PATH + 2]; // finally resolved name
79 
80  const char *name = _name->getStringData();
81  const char *parentDir = _parentDir == OREF_NULL ? NULL : _parentDir->getStringData();
82  const char *parentExtension = _parentExtension == OREF_NULL ? NULL : _parentExtension->getStringData();
83  const char *pathExtension = instance->searchPath == OREF_NULL ? NULL : instance->searchPath->getStringData();
84 
85  SysSearchPath searchPath(parentDir, pathExtension);
86 
87 
88  // if the file already has an extension, this dramatically reduces the number
89  // of searches we need to make.
91  {
92  if (SysFileSystem::searchName(name, searchPath.path, NULL, resolvedName))
93  {
94  return new_string(resolvedName);
95  }
96  return OREF_NULL;
97  }
98 
99  // if we have a parent extension provided, use that in preference to any default searches
100  if (parentExtension != NULL)
101  {
102  if (SysFileSystem::searchName(name, searchPath.path, parentExtension, resolvedName))
103  {
104  return new_string(resolvedName);
105  }
106 
107  }
108 
109  // ok, now time to try each of the individual extensions along the way.
110  for (size_t i = instance->searchExtensions->firstIndex(); i != LIST_END; i = instance->searchExtensions->nextIndex(i))
111  {
113 
114  if (SysFileSystem::searchName(name, searchPath.path, ext->getStringData(), resolvedName))
115  {
116  return new_string(resolvedName);
117  }
118  }
119 
120  // The file may purposefully have no extension.
121  if (SysFileSystem::searchName(name, searchPath.path, NULL, resolvedName))
122  {
123  return new_string(resolvedName);
124  }
125 
126  return OREF_NULL;
127 }
128 
129 /**
130  * Load the base image into storage.
131  *
132  * @param imageBuffer returned start of the image
133  * @param imageSize returned size of the image
134  *
135  * @remarks We pass null to primitiveSearchName(), which has the effect of the
136  * Windows API SearchPath() being called with null for the path. When
137  * SearchPath is called with null for the path, and there is no path
138  * informtion in the file name, the first directory searched is the
139  * directory in which the application (rexx.exe) image is located.
140  *
141  * Since, on Windows, the base image (rexx.img) is always located in
142  * the same directory as rexx.exe, this results in the image being
143  * found faster. For development, it prevents the wrong base image
144  * being picked up during a compile.
145  *
146  * If the image is not found in the application image's directory, the
147  * regular executable search, which searches the path, is performed.
148  */
149 void SystemInterpreter::loadImage(char **imageBuffer, size_t *imageSize )
150 {
151  char fullname[MAX_PATH + 1]; // finally resolved name
152 
153  if (!SysFileSystem::primitiveSearchName(BASEIMAGE, NULL, NULL, fullname))
154  {
155  Interpreter::logicError("no startup image"); /* can't find it */
156  }
157 
158  /* try to open the file */
159  HANDLE fileHandle = CreateFile(fullname, GENERIC_READ, FILE_SHARE_READ,
160  NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL);
161 
162  if (fileHandle == INVALID_HANDLE_VALUE)
163  {
164  Interpreter::logicError("no startup image"); /* can't find it */
165  }
166  DWORD bytesRead; /* number of bytes read */
167  /* Read in the size of the image */
168  ReadFile(fileHandle, imageSize, sizeof(size_t), &bytesRead, NULL);
169  *imageBuffer = memoryObject.allocateImageBuffer(*imageSize);
170  /* read in the image */
171  ReadFile(fileHandle, *imageBuffer, (DWORD)*imageSize, &bytesRead, NULL);
172  // set this to the actual size read.
173  *imageSize = bytesRead;
174  CloseHandle(fileHandle); /* and close the file */
175 }
176 
177 
179  const char *file_name) /* program file name */
180 /*******************************************************************/
181 /* Function: Read a program into a buffer */
182 /*******************************************************************/
183 {
184  HANDLE fileHandle; /* open file access handle */
185  size_t buffersize; /* size of read buffer */
186  RexxBuffer * buffer; /* buffer object to read file into */
187  BY_HANDLE_FILE_INFORMATION status; /* file status information */
188  DWORD bytesRead; /* number of bytes read */
189 
190  {
191  UnsafeBlock releaser;
192  /* try to open the file */
193  fileHandle = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ,
194  NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL);
195  if (fileHandle == INVALID_HANDLE_VALUE)
196  {
197  return OREF_NULL; /* return nothing */
198  }
199  /* retrieve the file size */
200  GetFileInformationByHandle(fileHandle, &status);
201  }
202  buffersize = status.nFileSizeLow; /* get the file size */
203  buffer = new_buffer(buffersize); /* get a buffer object */
204  ProtectedObject p(buffer);
205  {
206  UnsafeBlock releaser;
207 
208  /* read in a buffer of data */
209  if (ReadFile(fileHandle, buffer->getData(), (DWORD)buffersize, &bytesRead, NULL) == 0) {
210  return OREF_NULL; /* return nothing */
211  }
212  CloseHandle(fileHandle); /* close the file now */
213  return buffer; /* return the program buffer */
214  }
215 }
216 
217 
219  RexxString * name) /* stream information block */
220 /*******************************************************************/
221 /* Function: Qualify a stream name for this system */
222 /*******************************************************************/
223 {
224  char nameBuffer[SysFileSystem::MaximumFileNameBuffer];
225 
226  /* clear out the block */
227  memset(nameBuffer, 0, sizeof(nameBuffer));
228  SysFileSystem::qualifyStreamName((char *)name->getStringData(), nameBuffer, sizeof(nameBuffer)); /* expand the full name */
229  /* uppercase this */
230  strupr(nameBuffer);
231  /* get the qualified file name */
232  return new_string(nameBuffer);
233 }
234 
235 
236 
237 
238 
RexxBuffer * new_buffer(sizeB_t s)
#define LIST_END
Definition: ListClass.hpp:60
#define OREF_NULL
Definition: RexxCore.h:60
RexxMemory memoryObject
Definition: RexxMemory.cpp:85
RexxString * new_string(const char *s, stringsizeB_t bl, sizeC_t cl=-1)
static void logicError(const char *desc)
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
void strupr(char *string)