CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

RAWFILE.CPP (55762B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/RAWFILE.CPP 1     3/03/97 10:25a Joe_bostic $ */
     17 /***********************************************************************************************
     18  ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Westwood Library                                             *
     22  *                                                                                             *
     23  *                    File Name : RAWFILE.CPP                                                  *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : August 8, 1994                                               *
     28  *                                                                                             *
     29  *                  Last Update : August 4, 1996 [JLB]                                         *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   RawFileClass::Bias -- Bias a file with a specific starting position and length.           *
     34  *   RawFileClass::Close -- Perform a closure of the file.                                     *
     35  *   RawFileClass::Create -- Creates an empty file.                                            *
     36  *   RawFileClass::Delete -- Deletes the file object from the disk.                            *
     37  *   RawFileClass::Error -- Handles displaying a file error message.                           *
     38  *   RawFileClass::Get_Date_Time -- Gets the date and time the file was last modified.         *
     39  *   RawFileClass::Is_Available -- Checks to see if the specified file is available to open.   *
     40  *   RawFileClass::Open -- Assigns name and opens file in one operation.                       *
     41  *   RawFileClass::Open -- Opens the file object with the rights specified.                    *
     42  *   RawFileClass::RawFileClass -- Simple constructor for a file object.                       *
     43  *   RawFileClass::Raw_Seek -- Performs a seek on the unbiased file                            *
     44  *   RawFileClass::Read -- Reads the specified number of bytes into a memory buffer.           *
     45  *   RawFileClass::Seek -- Reposition the file pointer as indicated.                           *
     46  *   RawFileClass::Set_Date_Time -- Sets the date and time the file was last modified.         *
     47  *   RawFileClass::Set_Name -- Manually sets the name for a file object.                       *
     48  *   RawFileClass::Size -- Determines size of file (in bytes).                                 *
     49  *   RawFileClass::Write -- Writes the specified data to the buffer specified.                 *
     50  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     51 
     52 
     53 #include	<stdlib.h>
     54 #include	<stdio.h>
     55 #include	<string.h>
     56 #include	<direct.h>
     57 #include	<share.h>
     58 #include	<stddef.h>
     59 
     60 #include	"rawfile.h"
     61 
     62 #ifndef WIN32
     63 #include	<fcntl.h>
     64 #include	<io.h>
     65 #include	<dos.h>
     66 extern short Hard_Error_Occured;
     67 #endif
     68 
     69 
     70 /***********************************************************************************************
     71  * RawFileClass::Error -- Handles displaying a file error message.                             *
     72  *                                                                                             *
     73  *    Display an error message as indicated. If it is allowed to retry, then pressing a key    *
     74  *    will return from this function. Otherwise, it will exit the program with "exit()".       *
     75  *                                                                                             *
     76  * INPUT:   error    -- The error number (same as the DOSERR.H error numbers).                 *
     77  *                                                                                             *
     78  *          canretry -- Can this routine exit normally so that retrying can occur? If this is  *
     79  *                      false, then the program WILL exit in this routine.                     *
     80  *                                                                                             *
     81  *          filename -- Optional filename to report with this error. If no filename is         *
     82  *                      supplied, then no filename is listed in the error message.             *
     83  *                                                                                             *
     84  * OUTPUT:  none, but this routine might not return at all if the "canretry" parameter is      *
     85  *          false or the player pressed ESC.                                                   *
     86  *                                                                                             *
     87  * WARNINGS:   This routine may not return at all. It handles being in text mode as well as    *
     88  *             if in a graphic mode.                                                           *
     89  *                                                                                             *
     90  * HISTORY:                                                                                    *
     91  *   10/17/1994 JLB : Created.                                                                 *
     92  *=============================================================================================*/
     93 void RawFileClass::Error(int , int , char const * )
     94 {
     95 }
     96 
     97 
     98 /***********************************************************************************************
     99  * RawFileClass::RawFileClass -- Simple constructor for a file object.                         *
    100  *                                                                                             *
    101  *    This constructor is called when a file object is created with a supplied filename, but   *
    102  *    not opened at the same time. In this case, an assumption is made that the supplied       *
    103  *    filename is a constant string. A duplicate of the filename string is not created since   *
    104  *    it would be wasteful in that case.                                                       *
    105  *                                                                                             *
    106  * INPUT:   filename -- The filename to assign to this file object.                            *
    107  *                                                                                             *
    108  * OUTPUT:  none                                                                               *
    109  *                                                                                             *
    110  * WARNINGS:   none                                                                            *
    111  *                                                                                             *
    112  * HISTORY:                                                                                    *
    113  *   10/17/1994 JLB : Created.                                                                 *
    114  *=============================================================================================*/
    115 RawFileClass::RawFileClass(char const * filename) :
    116 	Rights(0),
    117 	BiasStart(0),
    118 	BiasLength(-1),
    119 	Handle(NULL_HANDLE),
    120 	Filename(filename),
    121 	Date(0),
    122 	Time(0),
    123 	Allocated(false)
    124 {
    125 }
    126 
    127 
    128 /***********************************************************************************************
    129  * RawFileClass::Set_Name -- Manually sets the name for a file object.                         *
    130  *                                                                                             *
    131  *    This routine will set the name for the file object to the name specified. This name is   *
    132  *    duplicated in free store. This allows the supplied name to be a temporarily constructed  *
    133  *    text string. Setting the name in this fashion doesn't affect the closed or opened state  *
    134  *    of the file.                                                                             *
    135  *                                                                                             *
    136  * INPUT:   filename -- The filename to assign to this file object.                            *
    137  *                                                                                             *
    138  * OUTPUT:  Returns with a pointer to the allocated copy of this filename. This pointer is     *
    139  *          guaranteed to remain valid for the duration of this file object or until the name  *
    140  *          is changed -- whichever is sooner.                                                 *
    141  *                                                                                             *
    142  * WARNINGS:   Because of the allocation this routine must perform, memory could become        *
    143  *             fragmented.                                                                     *
    144  *                                                                                             *
    145  * HISTORY:                                                                                    *
    146  *   10/17/1994 JLB : Created.                                                                 *
    147  *=============================================================================================*/
    148 char const * RawFileClass::Set_Name(char const * filename)
    149 {
    150 	if (Filename != NULL && Allocated) {
    151 		free((char *)Filename);
    152 		((char *&)Filename) = 0;
    153 		Allocated = false;
    154 	}
    155 
    156 	if (filename == NULL) return(NULL);
    157 
    158 	Bias(0);
    159 
    160 	((char *&)Filename) = strdup(filename);
    161 	if (Filename == NULL) {
    162 		Error(ENOMEM, false, filename);
    163 	}
    164 	Allocated = true;
    165 	return(Filename);
    166 }
    167 
    168 
    169 /***********************************************************************************************
    170  * RawFileClass::Open -- Assigns name and opens file in one operation.                         *
    171  *                                                                                             *
    172  *    This routine will assign the specified filename to the file object and open it at the    *
    173  *    same time. If the file object was already open, then it will be closed first. If the     *
    174  *    file object was previously assigned a filename, then it will be replaced with the new    *
    175  *    name. Typically, this routine is used when an anonymous file object has been crated and  *
    176  *    now it needs to be assigned a name and opened.                                           *
    177  *                                                                                             *
    178  * INPUT:   filename -- The filename to assign to this file object.                            *
    179  *                                                                                             *
    180  *          rights   -- The open file access rights to use.                                    *
    181  *                                                                                             *
    182  * OUTPUT:  bool; Was the file opened? The return value of this is moot, since the open file   *
    183  *          is designed to never return unless it succeeded.                                   *
    184  *                                                                                             *
    185  * WARNINGS:   none                                                                            *
    186  *                                                                                             *
    187  * HISTORY:                                                                                    *
    188  *   10/17/1994 JLB : Created.                                                                 *
    189  *=============================================================================================*/
    190 int RawFileClass::Open(char const * filename, int rights)
    191 {
    192 	Set_Name(filename);
    193 	return(Open(rights));
    194 }
    195 
    196 
    197 /***********************************************************************************************
    198  * RawFileClass::Open -- Opens the file object with the rights specified.                      *
    199  *                                                                                             *
    200  *    This routine is used to open the specified file object with the access rights indicated. *
    201  *    This only works if the file has already been assigned a filename. It is guaranteed, by   *
    202  *    the error handler, that this routine will always return with success.                    *
    203  *                                                                                             *
    204  * INPUT:   rights   -- The file access rights to use when opening this file. This is a        *
    205  *                      combination of READ and/or WRITE bit flags.                            *
    206  *                                                                                             *
    207  * OUTPUT:  bool; Was the file opened successfully? This will always return true by reason of  *
    208  *          the error handler.                                                                 *
    209  *                                                                                             *
    210  * WARNINGS:   none                                                                            *
    211  *                                                                                             *
    212  * HISTORY:                                                                                    *
    213  *   10/17/1994 JLB : Created.                                                                 *
    214  *=============================================================================================*/
    215 int RawFileClass::Open(int rights)
    216 {
    217 	Close();
    218 
    219 	/*
    220 	**	Verify that there is a filename associated with this file object. If not, then this is a
    221 	**	big error condition.
    222 	*/
    223 	if (Filename == NULL) {
    224 		Error(ENOENT, false);
    225 	}
    226 
    227 	/*
    228 	**	Record the access rights used for this open call. These rights will be used if the
    229 	**	file object is duplicated.
    230 	*/
    231 	Rights = rights;
    232 
    233 	/*
    234 	**	Repetitively try to open the file. Abort if a fatal error condition occurs.
    235 	*/
    236 	for (;;) {
    237 
    238 		/*
    239 		**	Try to open the file according to the access rights specified.
    240 		*/
    241 		#ifndef WIN32
    242 			Hard_Error_Occured = 0;
    243 		#endif
    244 		switch (rights) {
    245 
    246 			/*
    247 			**	If the access rights are not recognized, then report this as
    248 			**	an invalid access code.
    249 			*/
    250 			default:
    251 				errno = EINVAL;
    252 				break;
    253 
    254 			case READ:
    255 				#ifdef WIN32
    256 					Handle = CreateFile(Filename, GENERIC_READ, FILE_SHARE_READ,
    257 												NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    258 				#else
    259 					_dos_open(Filename, O_RDONLY|SH_DENYNO, &Handle);
    260 				#endif
    261 				break;
    262 
    263 			case WRITE:
    264 				#ifdef WIN32
    265 					Handle = CreateFile(Filename, GENERIC_WRITE, 0,
    266 												NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    267 				#else
    268 					_dos_creat(Filename, 0, &Handle);
    269 				#endif
    270 				break;
    271 
    272 			case READ|WRITE:
    273 				#ifdef WIN32
    274 					Handle = CreateFile(Filename, GENERIC_READ | GENERIC_WRITE, 0,
    275 												NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    276 				#else
    277 					_dos_open(Filename, O_RDWR|O_CREAT|SH_DENYWR, &Handle);
    278 				#endif
    279 				break;
    280 		}
    281 
    282 		/*
    283 		**	Biased files must be positioned past the bias start position.
    284 		*/
    285 		if (BiasStart != 0 || BiasLength != -1) {
    286 			Seek(0, SEEK_SET);
    287 		}
    288 
    289 		/*
    290 		**	If the handle indicates the file is not open, then this is an error condition.
    291 		**	For the case of the file cannot be found, then allow a retry. All other cases
    292 		**	are fatal.
    293 		*/
    294 		if (Handle == NULL_HANDLE) {
    295 
    296 #ifdef WIN32
    297 //			return(false);
    298 			Error(GetLastError(), false, Filename);
    299 //			continue;
    300 #else
    301 			/*
    302 			**	If this flag is set, then some hard error occurred. Just assume that the error
    303 			**	is probably a removed CD-ROM and allow a retry.
    304 			*/
    305 			if (Hard_Error_Occured) {
    306 				Error(Hard_Error_Occured, true, Filename);
    307 			} else {
    308 				if (errno == ENOENT) {
    309 					Error(ENOENT, true, Filename);
    310 				} else {
    311 					Error(errno, false, Filename);
    312 				}
    313 			}
    314 			continue;
    315 #endif
    316 		}
    317 		break;
    318 	}
    319 
    320 	return(true);
    321 }
    322 
    323 
    324 /***********************************************************************************************
    325  * RawFileClass::Is_Available -- Checks to see if the specified file is available to open.     *
    326  *                                                                                             *
    327  *    This routine will examine the disk system to see if the specified file can be opened     *
    328  *    or not. Use this routine before opening a file in order to make sure that is available   *
    329  *    or to perform other necessary actions.                                                   *
    330  *                                                                                             *
    331  * INPUT:   force -- Should this routine keep retrying until the file becomes available? If    *
    332  *                   in this case it doesn't become available, then the program will abort.    *
    333  *                                                                                             *
    334  * OUTPUT:  bool; Is the file available to be opened?                                          *
    335  *                                                                                             *
    336  * WARNINGS:   Depending on the parameter passed in, this routine may never return.            *
    337  *                                                                                             *
    338  * HISTORY:                                                                                    *
    339  *   10/18/1994 JLB : Created.                                                                 *
    340  *=============================================================================================*/
    341 int RawFileClass::Is_Available(int forced)
    342 {
    343 #ifndef WIN32
    344 	bool open_failed;
    345 #endif
    346 
    347 	if (Filename == NULL) return(false);
    348 
    349 	/*
    350 	**	If the file is already open, then is must have already passed the availability check.
    351 	**	Return true in this case.
    352 	*/
    353 	if (Is_Open()) return(true);
    354 
    355 	/*
    356 	**	If this is a forced check, then go through the normal open channels, since those
    357 	**	channels ensure that the file must exist.
    358 	*/
    359 	if (forced) {
    360 		RawFileClass::Open(READ);
    361 		RawFileClass::Close();
    362 		return(true);
    363 	}
    364 
    365 	/*
    366 	**	Perform a raw open of the file. If this open fails for ANY REASON, including a missing
    367 	**	CD-ROM, this routine will return a failure condition. In all but the missing file
    368 	**	condition, go through the normal error recover channels.
    369 	*/
    370 	for (;;) {
    371 
    372 #ifdef WIN32
    373 		Handle = CreateFile(Filename, GENERIC_READ, FILE_SHARE_READ,
    374 											NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    375 		if (Handle == NULL_HANDLE) {
    376 			return(false);
    377 		}
    378 		break;
    379 #else
    380 
    381 		Hard_Error_Occured = 0;
    382 		open_failed = _dos_open(Filename, O_RDONLY|SH_DENYNO, &Handle);
    383 
    384 		/*
    385 		**	If DOS reports that everything is just fine except that the file is not present,
    386 		**	then return with this fact. Any other case will fall through to the error handler
    387 		**	routine.
    388 		*/
    389 		if (open_failed && errno == ENOENT) return(false);
    390 
    391 		/*
    392 		** If we got an access error it could be because there is no cd in
    393 		** the drive.  Call the error handler but allow a continue if it
    394 		** returns.
    395 		*/
    396 		if (open_failed && errno == EACCES) {
    397 			Error(errno, true, Filename);
    398 			continue;
    399 		}
    400 
    401 		/*
    402 		**	If the file could not be found, then return with this information. If a more
    403 		**	serious error occurred, then display the error message and abort.
    404 		*/
    405 		if (Hard_Error_Occured) {
    406 			Error(Hard_Error_Occured, true, Filename);
    407 			continue;
    408 		} else {
    409 			if (open_failed) {
    410 				/*
    411 				**	An unhandled error condition is fatal. Display the error message and then
    412 				**	abort.
    413 				*/
    414 				Error(errno, false, Filename);
    415 			}
    416 		}
    417 		if (!open_failed) break;
    418 #endif
    419 	}
    420 
    421 	/*
    422 	**	Since the file could be opened, then close it and return that the file exists.
    423 	*/
    424 #ifdef WIN32
    425 	if (!CloseHandle(Handle)) {
    426 		Error(GetLastError(), false, Filename);
    427 	}
    428 #else
    429 	if (_dos_close(Handle)) {
    430 		Error(errno, false, Filename);
    431 	}
    432 #endif
    433 	Handle = NULL_HANDLE;
    434 
    435 	return(true);
    436 }
    437 
    438 
    439 /***********************************************************************************************
    440  * RawFileClass::Close -- Perform a closure of the file.                                       *
    441  *                                                                                             *
    442  *    Close the file object. In the rare case of an error, handle it as appropriate.           *
    443  *                                                                                             *
    444  * INPUT:   none                                                                               *
    445  *                                                                                             *
    446  * OUTPUT:  none                                                                               *
    447  *                                                                                             *
    448  * WARNINGS:   Some rare error conditions may cause this routine to abort the program.         *
    449  *                                                                                             *
    450  * HISTORY:                                                                                    *
    451  *   10/18/1994 JLB : Created.                                                                 *
    452  *=============================================================================================*/
    453 void RawFileClass::Close(void)
    454 {
    455 	/*
    456 	**	If the file is open, then close it. If the file is already closed, then just return. This
    457 	**	isn't considered an error condition.
    458 	*/
    459 	if (Is_Open()) {
    460 
    461 #ifdef WIN32
    462 		/*
    463 		**	Try to close the file. If there was an error (who knows what that could be), then
    464 		**	call the error routine.
    465 		*/
    466 		if (!CloseHandle(Handle)) {
    467 			Error(GetLastError(), false, Filename);
    468 		}
    469 #else
    470 		for (;;) {
    471 			/*
    472 			**	Close the file. If there was an error in the close operation -- abort.
    473 			*/
    474 			Hard_Error_Occured = 0;
    475 			if (_dos_close(Handle)) {
    476 
    477 				/*
    478 				**	By definition, this error can only be a bad file handle. This a fatal condition
    479 				**	of course, so abort with an error message.
    480 				*/
    481 				Error(errno, false, Filename);
    482 			}
    483 
    484 			/*
    485 			**	In the condition (if it is even possible) of a hard error occurring, then
    486 			**	assume it is the case of missing media. Display an error message and try
    487 			**	again if indicated.
    488 			*/
    489 			if (Hard_Error_Occured) {
    490 				Error(Hard_Error_Occured, true, Filename);
    491 				continue;
    492 			}
    493 			break;
    494 		}
    495 
    496 #endif
    497 
    498 		/*
    499 		**	At this point the file must have been closed. Mark the file as empty and return.
    500 		*/
    501 		Handle = NULL_HANDLE;
    502 	}
    503 }
    504 
    505 
    506 /***********************************************************************************************
    507  * RawFileClass::Read -- Reads the specified number of bytes into a memory buffer.             *
    508  *                                                                                             *
    509  *    This routine will read the specified number of bytes and place the data into the buffer  *
    510  *    indicated. It is legal to call this routine with a request for more bytes than are in    *
    511  *    the file. This condition can result in fewer bytes being read than requested. Determine  *
    512  *    this by examining the return value.                                                      *
    513  *                                                                                             *
    514  * INPUT:   buffer   -- Pointer to the buffer to read data into. If NULL is passed, no read    *
    515  *                      is performed.                                                          *
    516  *                                                                                             *
    517  *          size     -- The number of bytes to read. If NULL is passed, then no read is        *
    518  *                      performed.                                                             *
    519  *                                                                                             *
    520  * OUTPUT:  Returns with the number of bytes read into the buffer. If this number is less      *
    521  *          than requested, it indicates that the file has been exhausted.                     *
    522  *                                                                                             *
    523  * WARNINGS:   none                                                                            *
    524  *                                                                                             *
    525  * HISTORY:                                                                                    *
    526  *   10/18/1994 JLB : Created.                                                                 *
    527  *=============================================================================================*/
    528 long RawFileClass::Read(void * buffer, long size)
    529 {
    530 	long	bytesread = 0;			// Running count of the number of bytes read into the buffer.
    531 	int	opened = false;		// Was the file opened by this routine?
    532 
    533 	/*
    534 	**	If the file isn't opened, open it. This serves as a convenience
    535 	**	for the programmer.
    536 	*/
    537 	if (!Is_Open()) {
    538 
    539 		/*
    540 		**	The error check here is moot. Open will never return unless it succeeded.
    541 		*/
    542 		if (!Open(READ)) {
    543 			return(0);
    544 		}
    545 		opened = true;
    546 	}
    547 
    548 	/*
    549 	**	A biased file has the requested read length limited to the bias length of
    550 	**	the file.
    551 	*/
    552 	if (BiasLength != -1) {
    553 		int remainder = BiasLength - Seek(0);
    554 		size = size < remainder ? size : remainder;
    555 	}
    556 
    557 #ifdef WIN32
    558 	long total = 0;
    559 	while (size > 0) {
    560 		bytesread = 0;
    561 
    562 		SetErrorMode(SEM_FAILCRITICALERRORS);
    563 		if (!ReadFile(Handle, buffer, size, &(unsigned long&)bytesread, NULL)) {
    564 			size -= bytesread;
    565 			total += bytesread;
    566 			Error(GetLastError(), true, Filename);
    567 			SetErrorMode(0);
    568 			continue;
    569 		}
    570 		SetErrorMode(0);
    571 		size -= bytesread;
    572 		total += bytesread;
    573 		if (bytesread == 0) break;
    574 	}
    575 	bytesread = total;
    576 
    577 #else
    578 
    579 	int	readresult;
    580 
    581 	/*
    582 	**	Read the file in convenient chunk sizes. When the actual number
    583 	**	of bytes read does not match the desired, then assume that the file
    584 	**	is exhausted and bail. This loop was adjusted to take into
    585 	**	consideration the fact that "read" returns a SIGNED value whereas
    586 	**	it takes an UNSIGNED value as the byte count.
    587 	*/
    588 	while (size) {
    589 		unsigned	desired;		// Bytes desired to be read this pass.
    590 		unsigned actual;		// Actual number of bytes read.
    591 
    592 		/*
    593 		**	Break the read request into chunks no bigger than the low level DOS read
    594 		**	can handle.
    595 		*/
    596 		desired = size < 32000L ? size : 32000L;
    597 
    598 		Hard_Error_Occured = 0;
    599 		readresult = _dos_read(Handle, buffer, desired, &actual);
    600 
    601 		/*
    602 		**	If a hard error occurred, then assume that it is the case of the CD-ROM or
    603 		**	floppy media having been removed. Display the error and retry as directed.
    604 		*/
    605 		if (Hard_Error_Occured) {
    606 			Error(Hard_Error_Occured, true, Filename);
    607 			continue;			// Not technically needed, but to be consistent...
    608 		} else {
    609 
    610 			/*
    611 			**	If negative one is returned from the read operation, then this indicates
    612 			**	either a bad file number or invalid access. These are fatal conditions, so
    613 			**	display the error and then abort.
    614 			*/
    615 			if (readresult != 0) {
    616 				Error(errno, false, Filename);
    617 			} else {
    618 
    619 				/*
    620 				**	No error occurred during the read. Adjust the pointers and size counters and
    621 				**	loop again if more data is needed to be read.
    622 				*/
    623 				buffer = (char *)buffer + actual;
    624 				bytesread += actual;
    625 				size -= actual;
    626 				if (actual != desired) break;		// No more data?
    627 			}
    628 		}
    629 	}
    630 #endif	//WIN32
    631 
    632 	/*
    633 	**	Close the file if it was opened by this routine and return
    634 	**	the actual number of bytes read into the buffer.
    635 	*/
    636 	if (opened) Close();
    637 	return(bytesread);
    638 }
    639 
    640 
    641 /***********************************************************************************************
    642  * RawFileClass::Write -- Writes the specified data to the buffer specified.                   *
    643  *                                                                                             *
    644  *    This routine will write the data specified to the file.                                  *
    645  *                                                                                             *
    646  * INPUT:   buffer   -- The buffer that holds the data to write.                               *
    647  *                                                                                             *
    648  *          size     -- The number of bytes to write to the file.                              *
    649  *                                                                                             *
    650  * OUTPUT:  Returns with the number of bytes written to the file. This routine catches the     *
    651  *          case of a disk full condition, so this routine will always return with the number  *
    652  *          matching the size request.                                                         *
    653  *                                                                                             *
    654  * WARNINGS:   A fatal file condition could cause this routine to never return.                *
    655  *                                                                                             *
    656  * HISTORY:                                                                                    *
    657  *   10/18/1994 JLB : Created.                                                                 *
    658  *=============================================================================================*/
    659 long RawFileClass::Write(void const * buffer, long size)
    660 {
    661 	long	bytesread = 0;
    662 	int	opened = false;		// Was the file manually opened?
    663 
    664 	/*
    665 	**	Check to open status of the file. If the file is open, then merely write to
    666 	**	it. Otherwise, open the file for writing and then close the file when the
    667 	**	output is finished.
    668 	*/
    669 	if (!Is_Open()) {
    670 		if (!Open(WRITE)) {
    671 			return(0);
    672 		}
    673 		opened = true;
    674 	}
    675 
    676 #ifdef WIN32
    677 	if (!WriteFile(Handle, buffer, size, &(unsigned long&)bytesread, NULL)) {
    678 		Error(GetLastError(), false, Filename);
    679 	}
    680 
    681 #else
    682 
    683 	int	writeresult;
    684 	/*
    685 	**	Write the data to the file in chunks no bigger than what the low level DOS write
    686 	**	can handle.
    687 	*/
    688 	while (size) {
    689 		unsigned	desired;		// Bytes desired to be write this pass.
    690 		unsigned actual;		// Actual number of bytes written.
    691 
    692 		Hard_Error_Occured = 0;
    693 //		desired = (unsigned)MIN(size, Transfer_Block_Size());
    694 		desired = size;
    695 		writeresult = _dos_write(Handle, buffer, desired, &actual);
    696 
    697 		/*
    698 		**	If a hard error occurred, then assume it is the case of the media being
    699 		**	removed. Print the error message an retry as directed.
    700 		*/
    701 		if (Hard_Error_Occured) {
    702 			Error(Hard_Error_Occured, true, Filename);
    703 			continue;			// Not technically needed, but to be consistent...
    704 		} else {
    705 
    706 			/*
    707 			**	If negative one is returned by the DOS read, then this indicates a bad file
    708 			**	handle or invalid access. Either condition is fatal -- display error condition
    709 			**	and abort.
    710 			*/
    711 			if (writeresult != 0) {
    712 				Error(errno, false, Filename);
    713 			} else {
    714 
    715 				/*
    716 				**	A successful write occurred. Update pointers and byte counter as appropriate.
    717 				*/
    718 				buffer = (char *)buffer + actual;
    719 				bytesread += actual;
    720 				size -= actual;
    721 
    722 				/*
    723 				**	If the actual bytes written is less than requested, assume this is a case of
    724 				**	the disk being full. Consider this a fatal error condition.
    725 				*/
    726 				if (actual != desired) {
    727 					Error(ENOSPC, false, Filename);
    728 				}
    729 			}
    730 		}
    731 	}
    732 #endif	//WIN32
    733 
    734 	/*
    735 	**	Fixup the bias length if necessary.
    736 	*/
    737 	if (BiasLength != -1) {
    738 		if (Raw_Seek(0) > BiasStart+BiasLength) {
    739 			BiasLength = Raw_Seek(0) - BiasStart;
    740 		}
    741 	}
    742 
    743 	/*
    744 	**	If this routine had to open the file, then close it before returning.
    745 	*/
    746 	if (opened) {
    747 		Close();
    748 	}
    749 
    750 	/*
    751 	**	Return with the number of bytes written. This will always be the number of bytes
    752 	**	requested, since the case of the disk being full is caught by this routine.
    753 	*/
    754 	return(bytesread);
    755 }
    756 
    757 
    758 /***********************************************************************************************
    759  * RawFileClass::Seek -- Reposition the file pointer as indicated.                             *
    760  *                                                                                             *
    761  *    Use this routine to move the filepointer to the position indicated. It can move either   *
    762  *    relative to current position or absolute from the beginning or ending of the file. This  *
    763  *    routine will only return if it successfully performed the seek.                          *
    764  *                                                                                             *
    765  * INPUT:   pos   -- The position to seek to. This is interpreted as relative to the position  *
    766  *                   indicated by the "dir" parameter.                                         *
    767  *                                                                                             *
    768  *          dir   -- The relative position to relate the seek to. This can be either SEEK_SET  *
    769  *                   for the beginning of the file, SEEK_CUR for the current position, or      *
    770  *                   SEEK_END for the end of the file.                                         *
    771  *                                                                                             *
    772  * OUTPUT:  This routine returns the position that the seek ended up at.                       *
    773  *                                                                                             *
    774  * WARNINGS:   If there was a file error, then this routine might never return.                *
    775  *                                                                                             *
    776  * HISTORY:                                                                                    *
    777  *   10/18/1994 JLB : Created.                                                                 *
    778  *=============================================================================================*/
    779 long RawFileClass::Seek(long pos, int dir)
    780 {
    781 
    782 	/*
    783 	**	A file that is biased will have a seek operation modified so that the file appears to
    784 	**	exist only within the bias range. All bytes outside of this range appear to be
    785 	**	non-existant.
    786 	*/
    787 	if (BiasLength != -1) {
    788 		switch (dir) {
    789 			case SEEK_SET:
    790 				if (pos > BiasLength) {
    791 					pos = BiasLength;
    792 				}
    793 				pos += BiasStart;
    794 				break;
    795 
    796 			case SEEK_CUR:
    797 				break;
    798 
    799 			case SEEK_END:
    800 				dir = SEEK_SET;
    801 				pos += BiasStart + BiasLength;
    802 //				pos = (pos <= BiasStart+BiasLength) ? pos : BiasStart+BiasLength;
    803 //				pos = (pos >= BiasStart) ? pos : BiasStart;
    804 				break;
    805 		}
    806 
    807 		/*
    808 		**	Perform the modified raw seek into the file.
    809 		*/
    810 		long newpos = Raw_Seek(pos, dir) - BiasStart;
    811 
    812 		/*
    813 		**	Perform a final double check to make sure the file position fits with the bias range.
    814 		*/
    815 		if (newpos < 0) {
    816 			newpos = Raw_Seek(BiasStart, SEEK_SET) - BiasStart;
    817 		}
    818 		if (newpos > BiasLength) {
    819 			newpos = Raw_Seek(BiasStart+BiasLength, SEEK_SET) - BiasStart;
    820 		}
    821 		return(newpos);
    822 	}
    823 
    824 	/*
    825 	**	If the file is not biased in any fashion, then the normal seek logic will
    826 	**	work just fine.
    827 	*/
    828 	return(Raw_Seek(pos, dir));
    829 }
    830 
    831 
    832 /***********************************************************************************************
    833  * RawFileClass::Size -- Determines size of file (in bytes).                                   *
    834  *                                                                                             *
    835  *    Use this routine to determine the size of the file. The file must exist or this is an    *
    836  *    error condition.                                                                         *
    837  *                                                                                             *
    838  * INPUT:   none                                                                               *
    839  *                                                                                             *
    840  * OUTPUT:  Returns with the number of bytes in the file.                                      *
    841  *                                                                                             *
    842  * WARNINGS:   This routine handles error conditions and will not return unless the file       *
    843  *             exists and can successfully be queried for file length.                         *
    844  *                                                                                             *
    845  * HISTORY:                                                                                    *
    846  *   10/18/1994 JLB : Created.                                                                 *
    847  *=============================================================================================*/
    848 long RawFileClass::Size(void)
    849 {
    850 	long	size = 0;
    851 
    852 	/*
    853 	**	A biased file already has its length determined.
    854 	*/
    855 	if (BiasLength != -1) {
    856 		return(BiasLength);
    857 	}
    858 
    859 	/*
    860 	**	If the file is open, then proceed normally.
    861 	*/
    862 	if (Is_Open()) {
    863 
    864 #ifdef WIN32
    865 		size = GetFileSize(Handle, NULL);
    866 
    867 		/*
    868 		**	If there was in internal error, then call the error function.
    869 		*/
    870 		if (size == 0xFFFFFFFF) {
    871 			Error(GetLastError(), false, Filename);
    872 		}
    873 #else
    874 
    875 		/*
    876 		**	Repetitively try to determine the file size until a fatal error condition or success
    877 		**	is achieved.
    878 		*/
    879 		for (;;) {
    880 			Hard_Error_Occured = 0;
    881 			size = filelength(Handle);
    882 
    883 			/*
    884 			**	If a hard error occurred, then assume it is the case of removed media. Display an
    885 			**	error condition and allow retry.
    886 			*/
    887 			if (Hard_Error_Occured) {
    888 				Error(Hard_Error_Occured, true, Filename);
    889 				continue;
    890 			} else {
    891 				if (size == -1) {
    892 					Error(errno, false, Filename);
    893 				}
    894 			}
    895 			break;
    896 		}
    897 #endif
    898 
    899 	} else {
    900 
    901 		/*
    902 		**	If the file wasn't open, then open the file and call this routine again. Count on
    903 		**	the fact that the open function must succeed.
    904 		*/
    905 		if (Open()) {
    906 			size = Size();
    907 
    908 			/*
    909 			**	Since we needed to open the file we must remember to close the file when the
    910 			**	size has been determined.
    911 			*/
    912 			Close();
    913 		}
    914 	}
    915 
    916 	BiasLength = size-BiasStart;
    917 	return(BiasLength);
    918 }
    919 
    920 
    921 /***********************************************************************************************
    922  * RawFileClass::Create -- Creates an empty file.                                              *
    923  *                                                                                             *
    924  *    This routine will create an empty file from the file object. The file object's filename  *
    925  *    must already have been assigned before this routine will function.                       *
    926  *                                                                                             *
    927  * INPUT:   none                                                                               *
    928  *                                                                                             *
    929  * OUTPUT:  bool; Was the file successfully created? This routine will always return true.     *
    930  *                                                                                             *
    931  * WARNINGS:   A fatal error condition could occur with this routine. Especially if the disk   *
    932  *             is full or a read-only media was selected.                                      *
    933  *                                                                                             *
    934  * HISTORY:                                                                                    *
    935  *   10/18/1994 JLB : Created.                                                                 *
    936  *=============================================================================================*/
    937 int RawFileClass::Create(void)
    938 {
    939 	Close();
    940 	if (Open(WRITE)) {
    941 
    942 		/*
    943 		**	A biased file must be at least as long as the bias offset. Seeking to the
    944 		**	appropriate start offset has the effect of lengthening the file to the
    945 		**	correct length.
    946 		*/
    947 		if (BiasLength != -1) {
    948 			Seek(0, SEEK_SET);
    949 		}
    950 
    951 		Close();
    952 		return(true);
    953 	}
    954 	return(false);
    955 }
    956 
    957 
    958 /***********************************************************************************************
    959  * RawFileClass::Delete -- Deletes the file object from the disk.                              *
    960  *                                                                                             *
    961  *    This routine will delete the file object from the disk. If the file object doesn't       *
    962  *    exist, then this routine will return as if it had succeeded (since the effect is the     *
    963  *    same).                                                                                   *
    964  *                                                                                             *
    965  * INPUT:   none                                                                               *
    966  *                                                                                             *
    967  * OUTPUT:  bool; Was the file deleted? If the file was already missing, the this value will   *
    968  *                be false.                                                                    *
    969  *                                                                                             *
    970  * WARNINGS:   none                                                                            *
    971  *                                                                                             *
    972  * HISTORY:                                                                                    *
    973  *   10/18/1994 JLB : Created.                                                                 *
    974  *=============================================================================================*/
    975 int RawFileClass::Delete(void)
    976 {
    977 	/*
    978 	**	If the file was open, then it must be closed first.
    979 	*/
    980 	Close();
    981 
    982 	/*
    983 	**	If there is no filename associated with this object, then this indicates a fatal error
    984 	**	condition. Report this and abort.
    985 	*/
    986 	if (!Filename) {
    987 		Error(ENOENT, false);
    988 	}
    989 
    990 	/*
    991 	**	Repetitively try to delete the file if possible. Either return with success, or
    992 	**	abort the program with an error.
    993 	*/
    994 	for (;;) {
    995 
    996 		/*
    997 		**	If the file is already missing, then return with this fact. No action is necessary.
    998 		**	This can occur as this section loops if the file exists on a floppy and the floppy
    999 		**	was removed, the file deleted on another machine, and then the floppy was
   1000 		**	reinserted. Admittedly, this is a rare case, but is handled here.
   1001 		*/
   1002 		if (!Is_Available()) {
   1003 			return(false);
   1004 		}
   1005 
   1006 #ifdef WIN32
   1007 		if (!DeleteFile(Filename)) {
   1008 			Error(GetLastError(), false, Filename);
   1009 			return(false);
   1010 		}
   1011 #else
   1012 		Hard_Error_Occured = 0;
   1013 		if (remove(Filename) == -1) {
   1014 
   1015 			/*
   1016 			**	If a hard error occurred, then assume that the media has been removed. Display
   1017 			**	error message and retry as directed.
   1018 			*/
   1019 			if (Hard_Error_Occured) {
   1020 				Error(Hard_Error_Occured, true, Filename);
   1021 				continue;
   1022 			}
   1023 
   1024 			/*
   1025 			**	If at this point, DOS says the file doesn't exist, then just exit with this
   1026 			**	fact. It should have been caught earlier, but in any case, this is a legal
   1027 			**	condition.
   1028 			*/
   1029 			if (errno == ENOENT) break;
   1030 
   1031 			/*
   1032 			**	The only way it can reach this point is if DOS indicates that access is denied
   1033 			**	on the file. This occurs when trying to delete a file on a read-only media such
   1034 			**	as a CD-ROM. Report this as a fatal error and then abort.
   1035 			*/
   1036 			Error(errno, false, Filename);
   1037 		}
   1038 #endif
   1039 		break;
   1040 	}
   1041 
   1042 	/*
   1043 	**	DOS reports that the file was successfully deleted. Return with this fact.
   1044 	*/
   1045 	return(true);
   1046 }
   1047 
   1048 
   1049 /***********************************************************************************************
   1050  * RawFileClass::Get_Date_Time -- Gets the date and time the file was last modified.           *
   1051  *                                                                                             *
   1052  *    Use this routine to get the date and time of the file.                                   *
   1053  *                                                                                             *
   1054  * INPUT:   none                                                                               *
   1055  *                                                                                             *
   1056  * OUTPUT:  Returns with the file date and time as a long.                                     *
   1057  *          Use the YEAR(long), MONTH(),....                                                   *
   1058  *                                                                                             *
   1059  * WARNINGS:   none                                                                            *
   1060  *                                                                                             *
   1061  * HISTORY:                                                                                    *
   1062  *   11/14/1995 DRD : Created.                                                                 *
   1063  *   07/13/1996 JLB : Handles win32 method.                                                    *
   1064  *=============================================================================================*/
   1065 unsigned long RawFileClass::Get_Date_Time(void)
   1066 {
   1067 #ifdef WIN32
   1068 	BY_HANDLE_FILE_INFORMATION info;
   1069 
   1070 	if (GetFileInformationByHandle(Handle, &info)) {
   1071 		WORD dosdate;
   1072 		WORD dostime;
   1073 		FileTimeToDosDateTime(&info.ftLastWriteTime, &dosdate, &dostime);
   1074 		return((dosdate << 16) | dostime);
   1075 	}
   1076 	return(0);
   1077 #else
   1078 	unsigned short time;
   1079 	unsigned short date;
   1080 	unsigned long datetime = 0;
   1081 
   1082 
   1083 	//
   1084 	//	If the file is open, then proceed normally.
   1085 	//
   1086 	if ( RawFileClass::Is_Open() ) {
   1087 		if ( _dos_getftime( Handle, &date, &time ) ) {
   1088 			//
   1089 			// return 0 indicating error with no date and time
   1090 			//
   1091 			return( datetime );
   1092 		}
   1093 	} else {
   1094 
   1095 		//
   1096 		//	If the file wasn't open, then see if the file exists.
   1097 		//
   1098 		if ( RawFileClass::Is_Available() ) {
   1099 			RawFileClass::Open();
   1100 
   1101 			if ( _dos_getftime( Handle, &date, &time ) ) {
   1102 				RawFileClass::Close();
   1103 				//
   1104 				// return 0 indicating error with no date and time
   1105 				//
   1106 				return( datetime );
   1107 			}
   1108 
   1109 			RawFileClass::Close();
   1110 		} else {
   1111 			//
   1112 			// return 0 indicating error with no date and time
   1113 			//
   1114 			return( datetime );
   1115 		}
   1116 	}
   1117 
   1118 	//
   1119 	// combine the date and time as a long
   1120 	//
   1121 	datetime = (date << 16) + time;
   1122 
   1123 	return( datetime );
   1124 #endif
   1125 }
   1126 
   1127 
   1128 /***********************************************************************************************
   1129  * RawFileClass::Set_Date_Time -- Sets the date and time the file was last modified.           *
   1130  *                                                                                             *
   1131  *    Use this routine to set the date and time of the file.                                   *
   1132  *                                                                                             *
   1133  * INPUT:   the file date and time as a long                                                   *
   1134  *                                                                                             *
   1135  * OUTPUT:  successful or not if the file date and time was changed.                           *
   1136  *                                                                                             *
   1137  * WARNINGS:   none                                                                            *
   1138  *                                                                                             *
   1139  * HISTORY:                                                                                    *
   1140  *   11/14/1995 DRD : Created.                                                                 *
   1141  *   07/13/1996 JLB : Handles win 32 method                                                    *
   1142  *=============================================================================================*/
   1143 bool RawFileClass::Set_Date_Time(unsigned long datetime)
   1144 {
   1145 #ifdef WIN32
   1146 	if (RawFileClass::Is_Open()) {
   1147 		BY_HANDLE_FILE_INFORMATION info;
   1148 
   1149 		if (GetFileInformationByHandle(Handle, &info)) {
   1150 			FILETIME filetime;
   1151 			if (DosDateTimeToFileTime((WORD)(datetime >> 16), (WORD)(datetime & 0x0FFFF), &filetime)) {
   1152 				return(SetFileTime(Handle, &info.ftCreationTime, &filetime, &filetime));
   1153 			}
   1154 		}
   1155 	}
   1156 	return(false);
   1157 #else
   1158 	unsigned short time;
   1159 	unsigned short date;
   1160 
   1161 	//
   1162 	//	If the file is open, then proceed normally.
   1163 	//
   1164 	if ( RawFileClass::Is_Open() ) {
   1165 		//
   1166 		// only set the date and time if open for READ only
   1167 		//
   1168 		if ( Rights == READ ) {
   1169 			time = (unsigned short)(datetime & 0xFFFF);
   1170 			date = (unsigned short)((datetime >> 16) & 0xFFFF);
   1171 
   1172 			if ( !_dos_setftime( Handle, date, time ) ) {
   1173 				//
   1174 				// return true indicating success
   1175 				//
   1176 				return( true );
   1177 			}
   1178 		}
   1179 	} else {
   1180 
   1181 		//
   1182 		//	If the file wasn't open, then see if the file exists.
   1183 		//
   1184 		if ( RawFileClass::Is_Available() ) {
   1185 			RawFileClass::Open();
   1186 
   1187 			time = (unsigned short)(datetime & 0xFFFF);
   1188 			date = (unsigned short)((datetime >> 16) & 0xFFFF);
   1189 
   1190 			if ( !_dos_setftime( Handle, date, time ) ) {
   1191 				RawFileClass::Close();
   1192 				//
   1193 				// return true indicating success
   1194 				//
   1195 				return( true );
   1196 			}
   1197 
   1198 			RawFileClass::Close();
   1199 		}
   1200 	}
   1201 
   1202 	//
   1203 	// return false indicating error
   1204 	//
   1205 	return( false );
   1206 #endif
   1207 }
   1208 
   1209 
   1210 /***********************************************************************************************
   1211  * RawFileClass::Bias -- Bias a file with a specific starting position and length.             *
   1212  *                                                                                             *
   1213  *    This will bias a file by giving it an artificial starting position and length. By        *
   1214  *    using this routine, it is possible to 'fool' the file into ignoring a header and         *
   1215  *    trailing extra data. An example of this would be a file inside of a mixfile.             *
   1216  *                                                                                             *
   1217  * INPUT:   start    -- The starting offset that will now be considered the start of the       *
   1218  *                      file.                                                                  *
   1219  *                                                                                             *
   1220  *          length   -- The forced length of the file. For files that are opened for write,    *
   1221  *                      this serves as the artificial constraint on the file's length. For     *
   1222  *                      files opened for read, this limits the usable file size.               *
   1223  *                                                                                             *
   1224  * OUTPUT:  none                                                                               *
   1225  *                                                                                             *
   1226  * WARNINGS:   none                                                                            *
   1227  *                                                                                             *
   1228  * HISTORY:                                                                                    *
   1229  *   06/02/1996 JLB : Created.                                                                 *
   1230  *=============================================================================================*/
   1231 void RawFileClass::Bias(int start, int length)
   1232 {
   1233 	if (start == 0) {
   1234 		BiasStart = 0;
   1235 		BiasLength = -1;
   1236 		return;
   1237 	}
   1238 
   1239 	BiasLength = RawFileClass::Size();
   1240 	BiasStart += start;
   1241 	if (length != -1) {
   1242 		BiasLength = BiasLength < length ? BiasLength : length;
   1243 	}
   1244 	BiasLength = BiasLength > 0 ? BiasLength : 0;
   1245 
   1246 	/*
   1247 	**	Move the current file offset to a legal position if necessary and the
   1248 	**	file was open.
   1249 	*/
   1250 	if (Is_Open()) {
   1251 		RawFileClass::Seek(0, SEEK_SET);
   1252 	}
   1253 }
   1254 
   1255 
   1256 /***********************************************************************************************
   1257  * RawFileClass::Raw_Seek -- Performs a seek on the unbiased file                              *
   1258  *                                                                                             *
   1259  *    This will perform a seek on the file as if it were unbiased. This is in spite of any     *
   1260  *    bias setting the file may have. The ability to perform a raw seek in this fasion is      *
   1261  *    necessary to maintain the bias ability.                                                  *
   1262  *                                                                                             *
   1263  * INPUT:   pos   -- The position to seek the file relative to the "dir" parameter.            *
   1264  *                                                                                             *
   1265  *          dir   -- The origin of the seek operation.                                         *
   1266  *                                                                                             *
   1267  * OUTPUT:  Returns with the new position of the seek operation.                               *
   1268  *                                                                                             *
   1269  * WARNINGS:   none                                                                            *
   1270  *                                                                                             *
   1271  * HISTORY:                                                                                    *
   1272  *   08/04/1996 JLB : Created.                                                                 *
   1273  *=============================================================================================*/
   1274 long RawFileClass::Raw_Seek(long pos, int dir)
   1275 {
   1276 	/*
   1277 	**	If the file isn't opened, then this is a fatal error condition.
   1278 	*/
   1279 	if (!Is_Open()) {
   1280 		Error(EBADF, false, Filename);
   1281 	}
   1282 
   1283 #ifdef WIN32
   1284 	switch (dir) {
   1285 		case SEEK_SET:
   1286 			dir = FILE_BEGIN;
   1287 			break;
   1288 
   1289 		case SEEK_CUR:
   1290 			dir = FILE_CURRENT;
   1291 			break;
   1292 
   1293 		case SEEK_END:
   1294 			dir = FILE_END;
   1295 			break;
   1296 	}
   1297 
   1298 	pos = SetFilePointer(Handle, pos, NULL, dir);
   1299 
   1300 	/*
   1301 	**	If there was an error in the seek, then bail with an error condition.
   1302 	*/
   1303 	if (pos == 0xFFFFFFFF) {
   1304 		Error(GetLastError(), false, Filename);
   1305 	}
   1306 #else
   1307 
   1308 	/*
   1309 	**	Keep trying to seek until a non-retry condition occurs.
   1310 	*/
   1311 	for (;;) {
   1312 
   1313 		/*
   1314 		**	Perform the low level seek on the file.
   1315 		*/
   1316 		Hard_Error_Occured = 0;
   1317 		pos = lseek(Handle, pos, dir);
   1318 
   1319 		/*
   1320 		**	If a hard error occurred, then assume that it is the case of removed media. Display
   1321 		**	error message and retry.
   1322 		*/
   1323 		if (Hard_Error_Occured) {
   1324 			Error(Hard_Error_Occured, true, Filename);
   1325 			continue;
   1326 		} else {
   1327 
   1328 			/*
   1329 			**	A negative one indicates a fatal error with the seek operation. Display error
   1330 			**	condition and then abort.
   1331 			*/
   1332 			if (pos == -1) {
   1333 				Error(errno, false, Filename);
   1334 			}
   1335 		}
   1336 		break;
   1337 	}
   1338 #endif
   1339 
   1340 	/*
   1341 	**	Return with the new position of the file. This will range between zero and the number of
   1342 	**	bytes the file contains.
   1343 	*/
   1344 	return(pos);
   1345 }