CnC_Remastered_Collection

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

RAWFILE.CPP (55781B)


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