00001
00002
00003 #include <stdlib.h>
00004 #include <errno.h>
00005 #include <string.h>
00006 #include "gmain.h"
00007 #include "gfile.h"
00008 #include "gfilestat.h"
00009 #include "glist.h"
00010
00011
00012 #include <time.h>
00013 #include <signal.h>
00014 #ifdef gDOS_SPEC
00015 #include <windows.h>
00016 #endif //gDOS_SPEC
00017
00018
00019
00020 gFileControl gFileControl::myself;
00021 bool gFileControl::isTerminated=false;
00022
00023
00024 sSignalTrap global_signal_traps[]={
00025 { GX_SIGHUP, 1, "HUP" },
00026 { GX_SIGINT, 1, "INT" },
00027 { GX_SIGQUIT, 0, "QUIT" },
00028 { GX_SIGTRAP, 0, "TRAP" },
00029 { GX_SIGKILL, 0, "KILL" },
00030 { GX_SIGPIPE, 1, "PIPE" },
00031 { GX_SIGALRM, 0, "ALRM" },
00032 { GX_SIGTERM, 1, "TERM" },
00033 { GX_SIGCHLD, 0, "CHLD" },
00034 { GX_SIGUSR1, 1, "USR1" },
00035 { GX_SIGUSR2, 0, "USR2" },
00036 { -1, -1 }
00037 };
00038
00039
00040 void MySignalHandler (int signalId)
00041 {
00042 gFileControl::Self().SignalHandler( signalId );
00043 }
00044
00045 gFileOut::gFileOut (FILE* aFile, bool isModeDOS)
00046 : f( aFile )
00047 {
00048 SetModeDOS( isModeDOS );
00049 }
00050
00051 gFileOut::~gFileOut ()
00052 {
00053 if ( f!=nil && f!=stdout && f!=stdin && f!=stderr )
00054 fclose( f );
00055 }
00056
00057 void gFileOut::SetModeDOS (bool isDOS)
00058 {
00059 sNL.SetEmpty();
00060 if ( isDOS ) sNL.Add( '\r' );
00061 sNL.Add( '\n' );
00062 }
00063
00064 gFileControl::gFileControl ()
00065 : lastOpError( 0 ),
00066 charOnFileRelax( FILENM_STRICT_LVL4 ),
00067 userId( 0 ),
00068 fReport( stderr ),
00069 exitCodeOnSignal( 1 ),
00070 isInit( false )
00071 {
00072 tmpPath[0] = tmpPrefix[0] = 0;
00073 CtrlGetTempPath( (char*)tmpPath );
00074 strcpy(tmpPrefix,"tmp_");
00075 #ifdef gGX_USR_SUPPORT
00076 userId = getuid();
00077 #else
00078 userId = 0;
00079 #endif
00080 char* strEnv = getenv("USER");
00081 sUName = strEnv==NULL ? (char*)"%" : strEnv;
00082 strcpy( tmpSuffix, ".tmp" );
00083 tempL = new gList;
00084 }
00085
00086 gFileControl::~gFileControl ()
00087 {
00088
00089
00090 }
00091
00092 bool gFileControl::IsOkStrict (t_uchar c, bool isStrict)
00093 {
00094 bool isOk = IsOkChar( c );
00095 if ( isStrict ) return isOk;
00096 if ( charOnFileRelax>=FILENM_STRICT_LVL8 )
00097 return isOk || c=='\\' || c=='/';
00098 return isOk || c==gSLASHCHR;
00099 }
00100
00101 bool gFileControl::IsOkPathname (char* s)
00102 {
00103 unsigned i, len;
00104 t_uchar c;
00105
00106 ASSERTION(s!=nil,"s!=nil");
00107 len = strlen( s );
00108 if ( len==0 ) return false;
00109 if ( s[0]<=' ' || s[len-1]<=' ' ) return false;
00110 for (i=0; i<len; i++) {
00111 c = (t_uchar)s[i];
00112 if ( c==gSLASHCHR ) continue;
00113 if ( IsOkChar( c )==false ) return false;
00114 }
00115 return true;
00116 }
00117
00118 int gFileControl::CtrlGetTempPath (char* resPathStr)
00119 {
00120 strcpy(resPathStr,gSLASHSTR);
00121 strcat(resPathStr,"tmp");
00122 #ifdef gDOS_SPEC
00123 char* envStr = getenv("TEMP");
00124 if ( envStr!=NULL && envStr[0]!=0 )
00125 strcpy(resPathStr,envStr);
00126 else {
00127 envStr = getenv("TMP");
00128 if ( envStr!=NULL && envStr[0]!=0 ) strcpy(resPathStr,envStr);
00129 }
00130 #endif //gDOS_SPEC
00131 return 0;
00132 }
00133
00134 t_uint32 gFileControl::CtrlGetPid ()
00135 {
00136 #if defined(linux) || defined(gDOS_LIB_CRT_DLL)
00137 pid_t pid = getpid();
00138 return (t_uint32)pid;
00139 #else
00140 return 0;
00141 #endif //linux...
00142 }
00143
00144 t_uint32 gFileControl::GetCurrentEpoch ()
00145 {
00146 time_t aT;
00147 time_t aTInvalid = ((time_t)-1);
00148
00149 aT = time(NULL);
00150 if ( aT==aTInvalid ) {
00151 lastOpError = errno;
00152 return 0;
00153 }
00154 return (t_uint32)aT;
00155 }
00156
00157 gString& gFileControl::GetUniqueName (char* s)
00158 {
00159 t_uint32 aStamp, aRand;
00160 thisGetUniqueName( s, aStamp, aRand, sName );
00161 return sName;
00162 }
00163
00164 char* gFileControl::ErrorStr (int aErrorNo)
00165 {
00166 sErrorRef.SetEmpty();
00167 if ( aErrorNo<=0 ) return NULL;
00168
00169 sErrorRef = strerror( aErrorNo );
00170
00171 return sErrorRef.Str();
00172 }
00173
00174 int gFileControl::RemoveTemp (bool doReport)
00175 {
00176 unsigned nTemp;
00177 return RemoveTemp( nTemp, doReport );
00178 }
00179
00180 int gFileControl::RemoveTemp (unsigned& nTemp, bool doReport)
00181 {
00182 unsigned i;
00183 int tempErr;
00184
00185 ASSERTION(tempL!=nil,"tempL!=nil");
00186 nTemp = tempL->N();
00187 for (i=1; i<=nTemp; i++) {
00188 char* str = tempL->Str(i);
00189 if ( (tempErr = remove( str ))!=0 ) {
00190 lastOpError = tempErr;
00191 }
00192 if ( doReport )
00193 fprintf(fReport,"Cleaning: %s file: %s\n",
00194 tempErr==0?"Deleted":"Unable to delete",
00195 str);
00196 }
00197 delete tempL;
00198 tempL = new gList;
00199 return lastOpError;
00200 }
00201
00202 int gFileControl::Release (bool doReport)
00203 {
00204 if ( tempL==nil ) return -1;
00205 RemoveTemp( doReport );
00206 delete tempL;
00207 tempL = nil;
00208 return lastOpError;
00209 }
00210
00211 bool gFileControl::AddTempFile (gString& s)
00212 {
00213 ASSERTION(tempL!=nil,"tempL!=nil");
00214 if ( s.IsEmpty() ) return false;
00215 tempL->Add( s );
00216 return true;
00217 }
00218
00219 int gFileControl::Init ()
00220 {
00221
00222 return thisInit();
00223 }
00224
00225 int gFileControl::End (bool doReportObjs)
00226 {
00227 gStorageControl::Self().assertedNr = 1;
00228 int deltaObjs = gStorageControl::Self().NumObjs();
00229 DBGPRINT("@DBG: gNObjs: %d\n",deltaObjs);
00230 if ( deltaObjs!=0 && doReportObjs==true ) fprintf(stderr,"@deltaObjs: %d\n",deltaObjs);
00231 return Release( true );
00232 }
00233
00234 t_int16 gFileControl::IsSignaled (t_int16 iSignalId)
00235 {
00236
00237 t_int16 iter, sigId;
00238 for (iter=0; ; iter++) {
00239 sigId = global_signal_traps[iter].sigId;
00240 if ( sigId<0 ) return 0;
00241 if ( sigId==iSignalId ) {
00242 DBGPRINT_MIN("DBG: IsSignaled(%d), named '%s'? %d\n",
00243 iSignalId,
00244 global_signal_traps[iter].shortName,
00245 global_signal_traps[iter].handled);
00246 return global_signal_traps[iter].handled;
00247 }
00248 }
00249 return -1;
00250 }
00251
00252 t_int16 gFileControl::SetSignaled (t_int16 iSignalId, t_int16 handled)
00253 {
00254 t_int16 iter, sigId;
00255 for (iter=0; ; iter++) {
00256 sigId = global_signal_traps[iter].sigId;
00257 if ( sigId<0 ) return 0;
00258 if ( sigId==iSignalId ) {
00259 DBGPRINT_MIN("DBG: IsSignaled(%d), named '%s'? %d, now: %d\n",
00260 iSignalId,
00261 global_signal_traps[iter].shortName,
00262 global_signal_traps[iter].handled,
00263 handled);
00264 return global_signal_traps[iter].handled = handled;
00265 }
00266 }
00267 return -1;
00268 }
00269
00270 t_int16 gFileControl::SetSignaledByStr (char* shortStr, t_int16 handled)
00271 {
00272 t_int16 iter, sigId;
00273 for (iter=0; ; iter++) {
00274 sigId = global_signal_traps[iter].sigId;
00275 if ( sigId<0 ) return 0;
00276 gString shortName( global_signal_traps[iter].shortName );
00277 if ( shortName.Match( shortStr ) ) {
00278 DBGPRINT_MIN("DBG: IsSignaled(%d), named '%s'? %d, now: %d\n",
00279 sigId,
00280 global_signal_traps[iter].shortName,
00281 global_signal_traps[iter].handled,
00282 handled);
00283 return global_signal_traps[iter].handled = handled;
00284 }
00285 }
00286 return -1;
00287 }
00288
00289 void gFileControl::SignalHandler (int signalId)
00290 {
00291 if ( isTerminated ) {
00292
00293 Release( false );
00294 exit( exitCodeOnSignal );
00295 }
00296 isTerminated = true;
00297
00298 #ifdef gGX_SIG_SUPPORT
00299 switch ( signalId ) {
00300 case SIGHUP:
00301 isTerminated = false;
00302 gglobal_EventTerminate( SIGHUP );
00303 return;
00304 case SIGINT:
00305 fprintf(fReport,"Aborted with Ctrl-C.\n");
00306 break;
00307 case SIGSEGV:
00308 fprintf(fReport,"Aborted with SIGSEGV.\n");
00309 exit( 1 );
00310 case SIGPIPE:
00311 isTerminated = false;
00312 gglobal_EventTerminate( SIGPIPE );
00313 return;
00314 case SIGTERM:
00315 fprintf(fReport,"Terminated!\n");
00316 break;
00317 default:
00318 isTerminated = false;
00319 fprintf(fReport,"Handled signal: %d\n",signalId);
00320 break;
00321 }
00322 #endif //gGX_SIG_SUPPORT
00323
00324
00325 if ( gglobal_EventTerminate( signalId )==-1 ) return;
00326
00327 Release( true );
00328 exit( exitCodeOnSignal );
00329 }
00330
00331 int gFileControl::OnEventTerminate (int (*DoSomething)(int))
00332 {
00333 return DoSomething( 0 );
00334 }
00335
00336 bool gFileControl::Write (int fHandle, t_uchar* uBuf, unsigned nBytes)
00337 {
00338 ssize_t bytesWritten;
00339 if ( fHandle==-1 ) return false;
00340 bytesWritten = write( fHandle, uBuf, (size_t)nBytes );
00341 if ( bytesWritten!=(ssize_t)nBytes ) {
00342 lastOpError = errno;
00343 return false;
00344 }
00345 lastOpError = 0;
00346 return true;
00347 }
00348
00349 void gFileControl::GetCwd (gString& s)
00350 {
00351 unsigned aSize;
00352 char* str;
00353 s.Reset();
00354
00355 for (aSize=5000; ; aSize*=2) {
00356 gUCharBuffer aBuf( aSize+2 );
00357 str = getcwd( aBuf.Str(), aSize );
00358 if ( str!=NULL ) {
00359 s.Set( aBuf.Str() );
00360 return;
00361 }
00362 lastOpError = errno;
00363 s.Reset();
00364 if ( lastOpError!=ERANGE ) return;
00365 }
00366 }
00367
00368 int gFileControl::NanoSleep (t_uint32 uSec, t_uint32 nSec)
00369 {
00370 ASSERTION(nSec<=999999999UL,"NanoSleep(1)");
00371 #ifdef linux
00372 struct timespec tReq, tRem;
00373 tReq.tv_sec = (time_t)uSec;
00374 tReq.tv_nsec = (long)nSec;
00375
00376 return nanosleep( &tReq, &tRem );
00377 #else
00378
00379 static long lInt;
00380 DBGPRINT("@Win32: Faking nanosleep(%lu,%lu)\n",(unsigned long)uSec,(unsigned long)nSec);
00381 printf("@Win32: Faking nanosleep(%lu,%lu)\n",(unsigned long)uSec,(unsigned long)nSec);
00382 for (lInt=0; lInt>=0 && lInt<(long)uSec; ) lInt = lInt + (long)((float)1.0);
00383 return 0;
00384 #endif //linux
00385 }
00386
00387 int gFileControl::SecSleep (t_uint32 aSec)
00388 {
00389 DBGPRINT("<SEC_SLEEP:%u sec>\n",aSec);
00390 return MiliSecSleep( aSec * 1000 );
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 }
00403
00404 int gFileControl::MiliSecSleep (t_uint32 mSec)
00405 {
00406 DBGPRINT_MIN("PACE(%u)\n",(unsigned)mSec);
00407 #ifdef linux
00408 static t_uint32 aSec;
00409 if ( mSec>=1000 ) {
00410 aSec = mSec / 1000;
00411 mSec %= 1000;
00412 mSec *= 1000;
00413 mSec *= 1000;
00414 return NanoSleep( aSec, mSec );
00415 }
00416 return NanoSleep( 0, mSec*1000*1000 );
00417 #else
00418 Sleep( mSec );
00419 #endif
00420 return 0;
00421 }
00422
00423 int gFileControl::thisInit ()
00424 {
00425 if ( isInit ) return 1;
00426 isInit = true;
00427
00428 thisInitCharOnFile( true );
00429
00430
00431 #ifdef gGX_SIG_SUPPORT
00432 if ( IsSignaled( GX_SIGHUP ) ) signal(SIGHUP, MySignalHandler);
00433 if ( IsSignaled( GX_SIGINT ) ) signal(SIGINT, MySignalHandler);
00434 if ( IsSignaled( GX_SIGQUIT ) ) signal(SIGQUIT, MySignalHandler);
00435 if ( IsSignaled( GX_SIGALRM ) ) signal(SIGALRM, MySignalHandler);
00436 if ( IsSignaled( GX_SIGUSR1 ) ) signal(SIGUSR1, MySignalHandler);
00437 if ( IsSignaled( GX_SIGUSR2 ) ) signal(SIGUSR2, MySignalHandler);
00438 signal(SIGSEGV, MySignalHandler);
00439 if ( IsSignaled( GX_SIGPIPE ) ) signal(SIGPIPE, MySignalHandler);
00440 if ( IsSignaled( GX_SIGTERM ) ) signal(SIGTERM, MySignalHandler);
00441 #ifdef gSIGNAL_HANDLE_KILL
00442 signal(SIGKILL, MySignalHandler);
00443 #endif //gSIGNAL_HANDLE_KILL
00444 #endif //gGX_SIG_SUPPORT
00445
00446
00447
00448 return 0;
00449 }
00450
00451 void gFileControl::InitCharOnFile (t_uchar* s)
00452 {
00453 short v;
00454 thisInitCharOnFile( false );
00455 while ( s!=NULL && (v = (short)(*(s++)))!=0 ) {
00456 isCharOnFile[v] = 1;
00457 }
00458 }
00459
00460 int gFileControl::thisInitCharOnFile (bool doDefault)
00461 {
00462 short i;
00463 for (i=0; i<256; i++) isCharOnFile[i] = 0;
00464 if ( doDefault ) {
00465 InitCharOnFile( (t_uchar*)"\
00466 abcdefghijklmnopqrstuvwxyz\
00467 ABCDEFGHIJKLMNOPQRSTUVWXYZ\
00468 0123456789\
00469 !@#$%&()={}'`´\
00470 ~^-_.:,;" );
00471 switch ( charOnFileRelax ) {
00472 case FILENM_STRICT_LVL1:
00473 isCharOnFile[(int)'#'] = 0;
00474 isCharOnFile[(int)'@'] = 0;
00475 isCharOnFile[(int)'~'] = 0;
00476 isCharOnFile[(int)'^'] = 0;
00477 isCharOnFile[(int)':'] = 0;
00478 isCharOnFile[(int)','] = 0;
00479 case FILENM_STRICT_LVL2:
00480 isCharOnFile[(int)'"'] = 0;
00481 isCharOnFile[(int)'\''] = 0;
00482 isCharOnFile[(int)'´'] = 0;
00483 isCharOnFile[(int)'`'] = 0;
00484 isCharOnFile[(int)'!'] = 0;
00485 isCharOnFile[(int)'='] = 0;
00486 case FILENM_STRICT_LVL3:
00487 isCharOnFile[(int)'$'] = 0;
00488 isCharOnFile[(int)'&'] = 0;
00489 isCharOnFile[(int)'('] = isCharOnFile[(int)')'] = 0;
00490 isCharOnFile[(int)'{'] = isCharOnFile[(int)'}'] = 0;
00491 case FILENM_STRICT_LVL4:
00492
00493 case FILENM_STRICT_LVL5:
00494 isCharOnFile[(int)' '] = 1;
00495 isCharOnFile[(int)'['] = isCharOnFile[(int)']'] = 1;
00496 break;
00497 case FILENM_STRICT_LVL9:
00498 case FILENM_STRICT_LVL8:
00499 case FILENM_STRICT_LVL7:
00500
00501 for (i=128; i<255; i++) isCharOnFile[i] = 2;
00502 default:
00503 break;
00504 }
00505 return 0;
00506 }
00507 return 1;
00508 }
00509
00510 int gFileControl::thisGetUniqueName (char* s,
00511 t_uint32& aStamp,
00512 t_uint32& aRand,
00513 gString& sRes)
00514 {
00515 static t_uint32 aCnt;
00516 gString sTemp( (char*)tmpPath ), sEpoch( 50, '\0' );
00517 sTemp.Add( gSLASHCHR );
00518 sTemp.Add( tmpPrefix );
00519 if ( s!=nil ) sTemp.Add( s );
00520 aStamp = GetCurrentEpoch();
00521 aRand = ++aCnt;
00522 sprintf( sEpoch.Str(), "%04x-%04x_%03X-%lu%s",
00523 (unsigned)userId,
00524 (unsigned)CtrlGetPid(),
00525 (unsigned)(aRand%0xFFF),
00526 (unsigned long)aStamp,
00527 tmpSuffix );
00528 sTemp.AddString( sEpoch );
00529 sName = sTemp;
00530 return 0;
00531 }
00532
00533
00534
00535 gFile::gFile (eFileKind aFKind, char* fName, bool doOpenToRead, bool isTmpFile)
00536 : lastOpError( 0 ),
00537 f( NULL ),
00538 fKind( aFKind ),
00539 dKind( e_fDevOther ),
00540 fMode( doOpenToRead ? FL_FILE_TO_READ : 0 )
00541 {
00542 lastErrorMsg[0] = 0;
00543 if ( fName==NULL || fName[0]==0 ) {
00544 if ( isTmpFile==false ) OpenDevice( doOpenToRead ? e_fStdin : e_fStdout );
00545 }
00546 else {
00547 if ( doOpenToRead==true ) {
00548 f = fopen(fName,fKind==e_Text?"rt":"rb");
00549 if ( f==nil ) lastOpError = errno;
00550 }
00551 }
00552 }
00553
00554 gFile::~gFile ()
00555 {
00556 Close();
00557 }
00558
00559 bool gFile::ReadData (void* buf, t_uint16 bufSize)
00560 {
00561 t_uint16 nBytes;
00562 return ReadBuffer( buf, bufSize, nBytes );
00563 }
00564
00565 bool gFile::ReadBuffer (void* buf, t_uint16 bufSize, t_uint16& nBytes)
00566 {
00567 ;
00568
00569 ;
00570 size_t nReadItems;
00571
00572 ASSERTION(buf!=NULL,"buf!=NULL");
00573 nBytes = 0;
00574 lastOpError = -1;
00575 if ( f==nil ) return false;
00576
00577 nReadItems = fread(buf,bufSize,1,f);
00578 if ( nReadItems==0 ) {
00579 lastOpError = errno;
00580 return false;
00581 }
00582 nBytes = (t_uint16)bufSize;
00583 lastOpError = 0;
00584 return true;
00585 }
00586
00587 bool gFile::Read (void* buf, t_uint16 bufSize, t_uint16& nBytes)
00588 {
00589 ;
00590
00591 ;
00592 ASSERTION(buf!=NULL,"buf!=NULL");
00593 if ( f==nil ) return false;
00594 return thisRead(fileno(f),buf,bufSize,nBytes);
00595 }
00596
00597 char* gFile::LastErrorStr ()
00598 {
00599 lastErrorMsg[0] = 0;
00600 if ( lastOpError==0 ) return lastErrorMsg;
00601 strcpy( lastErrorMsg, "Unknown internal error" );
00602 if ( lastOpError<0 ) return lastErrorMsg;
00603 strcpy( lastErrorMsg, ErrorStr( lastOpError ) );
00604 return lastErrorMsg;
00605 }
00606
00607 char* gFile::ErrorStr (int aErrorNo)
00608 {
00609 return gFileControl::Self().ErrorStr( aErrorNo );
00610 }
00611
00612 bool gFile::OpenDevice (eDeviceKind aDKind)
00613 {
00614 Close();
00615 switch ( aDKind ) {
00616 case e_fDevOther:
00617 return false;
00618 case e_fStdin:
00619 fMode = FL_FILE_TO_READ;
00620 f = stdin;
00621 break;
00622 case e_fStdout:
00623 case e_fStderr:
00624 fMode = FL_FILE_TO_WRITE;
00625 f = aDKind==e_fStdout ? stdout : stderr;
00626 break;
00627 default:
00628 ASSERTION_FALSE("OpenDevice(1)");
00629 break;
00630 }
00631 dKind = aDKind;
00632 return true;
00633 }
00634
00635 bool gFile::OpenToRead (char* fName)
00636 {
00637 lastErrorMsg[0] = 0;
00638 lastOpError = 0;
00639 if ( IsOpened() ) return false;
00640
00641 fMode = FL_FILE_TO_READ;
00642 if ( fName!=NULL && fName[0]!=0 ) {
00643 f = fopen(fName,fKind==e_Text?"rt":"rb");
00644 if ( f==nil ) lastOpError = errno;
00645 }
00646 return lastOpError==0;
00647 }
00648
00649 bool gFile::Overwrite (char* fName)
00650 {
00651 Close();
00652 fMode = FL_FILE_TO_WRITE;
00653 if ( fName==nil || fName[0]==0 ) return false;
00654 dKind = e_fDevOther;
00655 f = fopen(fName,fKind==e_Text?"wt":"wb");
00656 if ( f==nil ) lastOpError = errno;
00657 return f!=NULL;
00658 }
00659
00660 bool gFile::Close ()
00661 {
00662 bool wasOpened = f!=NULL;
00663 lastOpError = 0;
00664 if ( f!=NULL && dKind==e_fDevOther ) fclose(f);
00665 f = NULL;
00666 return wasOpened;
00667 }
00668
00669 bool gFile::thisRead (int fd, void* buf, t_uint16 bufSize, t_uint16& nBytes)
00670 {
00671 ;
00672
00673
00674 ;
00675
00676
00677
00678 ssize_t readResult;
00679
00680 lastOpError = -1;
00681 if ( fd==-1 ) return false;
00682 lastOpError = 0;
00683 readResult = read(fd,buf,bufSize);
00684 nBytes = 0;
00685 if ( readResult<0 ) {
00686 lastOpError = errno;
00687 return false;
00688 }
00689 nBytes = (t_uint16)readResult;
00690 return true;
00691 }
00692
00693 gFileStream::gFileStream (char* fName, bool doOpenToRead)
00694 : gFile( gFile::e_Text, fName, doOpenToRead ),
00695 isOpOk( true ),
00696 isFileChanged( false ),
00697 isBufferOk( true ),
00698 seekPos( 0 ),
00699 seekEnd( 0 ),
00700 bufferSize( DEF_FIL_BUFSIZE ),
00701 buffer( NULL )
00702 {
00703 int fd=-1;
00704 isOpOk = f!=NULL && (fd = fileno(f))!=-1;
00705 if ( isOpOk ) isOpOk = thisGetStreamSize(fd)>=0;
00706 thisAllocateBuffer( bufferSize );
00707 }
00708
00709 gFileStream::gFileStream (gFile::eFileKind aFKind, char* fName, bool doOpenToRead, bool isTmpFile)
00710 : gFile( aFKind, fName, doOpenToRead, isTmpFile ),
00711 isOpOk( true ),
00712 isFileChanged( false ),
00713 isBufferOk( true ),
00714 seekPos( 0 ),
00715 seekEnd( 0 ),
00716 bufferSize( DEF_FIL_BUFSIZE ),
00717 buffer( NULL )
00718 {
00719 int fd=-1;
00720 isOpOk = f!=NULL && (fd = fileno(f))!=-1;
00721 if ( isOpOk ) isOpOk = thisGetStreamSize(fd)>=0;
00722 thisAllocateBuffer( bufferSize );
00723 }
00724
00725 gFileStream::~gFileStream ()
00726 {
00727 delete[] buffer;
00728 buffer = NULL;
00729 }
00730
00731 char* gFileStream::Buffer ()
00732 {
00733 ASSERTION(buffer!=NULL,"buffer!=nil");
00734 return (char*)buffer;
00735 }
00736
00737 t_uchar* gFileStream::UBuffer ()
00738 {
00739 ASSERTION(buffer!=NULL,"buffer!=nil");
00740 return buffer;
00741 }
00742
00743 bool gFileStream::Overwrite (char* fName)
00744 {
00745 isOpOk = gFile::Overwrite( fName );
00746 if ( isOpOk==false ) return false;
00747 isFileChanged = true;
00748 isBufferOk = true;
00749 seekPos = seekEnd = 0;
00750 return true;
00751 }
00752
00753 bool gFileStream::ReadBuffer (void* buf, t_uint16 bufSize, t_uint16& nBytes)
00754 {
00755 t_uint16 anBytes=0;
00756 isOpOk = gFile::ReadBuffer(buf,bufSize,anBytes);
00757 seekPos += anBytes;
00758 return isOpOk;
00759 }
00760
00761 bool gFileStream::Read (void* buf, t_uint16 bufSize, t_uint16& nBytes)
00762 {
00763 if ( f==nil ) return false;
00764 isOpOk = gFile::Read(buf,bufSize,nBytes);
00765 seekPos += nBytes;
00766 return isOpOk;
00767 }
00768
00769 bool gFileStream::Rewind ()
00770 {
00771 int error;
00772 if ( IsOpened()==false || IsDevice()==true ) return false;
00773 error = fseek( f, 0L, SEEK_SET );
00774 lastOpError = errno;
00775 if ( error!=0 ) return false;
00776 seekPos = 0;
00777 return true;
00778 }
00779
00780 int gFileStream::thisAllocateBuffer (t_uint16 aBufferSize)
00781 {
00782
00783 ASSERTION(aBufferSize>0,"aBufferSize>0");
00784 if ( buffer!=NULL ) delete[] buffer;
00785 buffer = new t_uchar[aBufferSize];
00786 DBGPRINT("DBG: gFileStream buffer allocated: %u\n",aBufferSize);
00787 ASSERTION(buffer!=nil,"buffer!=nil");
00788 return buffer==nil;
00789 }
00790
00791 int gFileStream::thisGetStreamSize (int fd)
00792 {
00793 off_t seekResult;
00794
00795 if ( fd==-1 ) return -1;
00796 seekResult = lseek(fd,(off_t)0,SEEK_END);
00797 lastOpError = errno;
00798 if ( seekResult==(off_t)-1 ) return -1;
00799 if ( seekEnd!=seekResult ) isFileChanged = true;
00800 seekEnd = seekResult;
00801 seekResult = lseek(fd,0,SEEK_SET);
00802 lastOpError = errno;
00803 seekPos = 0;
00804 return isFileChanged==true;
00805 }
00806
00807 gFileText::gFileText (char* fName, bool doOpenToRead)
00808 : gFileStream( gFile::e_Text, fName, doOpenToRead)
00809 {
00810 }
00811
00812 gFileText::~gFileText ()
00813 {
00814 }
00815
00816 bool gFileText::ReadLine ()
00817 {
00818 bool isOk;
00819 bool hasNewLine;
00820 return ReadLine( isOk, hasNewLine );
00821 }
00822
00823 bool gFileText::ReadLine (bool& isOk)
00824 {
00825 bool hasNewLine;
00826 return ReadLine( isOk, hasNewLine );
00827 }
00828
00829 bool gFileText::ReadLine (bool& isOk, bool& hasNewLine)
00830 {
00831
00832
00833
00834 static unsigned readLineLen;
00835
00836 lastOpError = 0;
00837
00838
00839
00840 buffer[0] = 0;
00841 isOk = IsOpened();
00842 if ( isOk==false ) {
00843 lastOpError = -1;
00844 return false;
00845 }
00846
00847 #ifdef DEBUG_IO
00848 printf("DBG: readLineLen:%d, bufferSize=%d, seekPos=%d, isBufferOk?%d\n",readLineLen,bufferSize,(int)seekPos,(int)isBufferOk);
00849 #endif
00850
00851 isOk = false;
00852 if ( fgets((char*)buffer,bufferSize,f)==NULL ) return false;
00853
00854 readLineLen = (unsigned)strlen( (char*)buffer );
00855 seekPos += (off_t)readLineLen;
00856 isBufferOk = readLineLen+1 < bufferSize;
00857
00858
00859 #ifdef DEBUG_IO
00860 printf("DBG: readLineLen:%d, bufferSize=%d, seekPos=%d, isBufferOk?%d\n",readLineLen,bufferSize,(int)seekPos,(int)isBufferOk);
00861 #endif
00862
00863 if ( readLineLen==0 ) return false;
00864 readLineLen--;
00865 hasNewLine = buffer[readLineLen]=='\n';
00866 if ( hasNewLine ) {
00867 buffer[readLineLen] = 0;
00868 if ( readLineLen>0 && buffer[--readLineLen]=='\r' )
00869 buffer[readLineLen] = 0;
00870 }
00871
00872 return true;
00873 }
00874
00875 gFileTemp::gFileTemp (char* strTemplate, gFile::eFileKind aFKind)
00876 : gFileStream( aFKind, nil, false, true ),
00877 fHandle( -1 ),
00878 tempMethod( e_NameStd ),
00879 isHandledFStream( false )
00880 {
00881 ;
00882
00883
00884
00885 ;
00886 char* str;
00887 unsigned pos;
00888
00889 gString sTemplate( strTemplate );
00890 gString sName( gFileControl::Self().tmpPath );
00891
00892 pos = sTemplate.Find("XXXXXX");
00893 if ( pos>0 && pos+6-1==sTemplate.Length() ) {
00894 str = sTemplate.Str();
00895 }
00896 else {
00897 sName.Add( gSLASHCHR );
00898 sName.Add( gFileControl::Self().tmpPrefix );
00899 sName.Add( "XXXXXX" );
00900 str = sName.Str();
00901 }
00902
00903 #if defined(linux) || defined(gDOS_LIB_XIO)
00904 fHandle = mkstemp( str );
00905
00906 thisOverwrite( str );
00907 #else
00908 char* pTemplate = mktemp( str );
00909 ASSERTION(pTemplate!=nil,"pTemplate!=nil");
00910 str = pTemplate;
00911 f = fopen( str, "wb" );
00912 ASSERTION(f!=nil,"f!=nil");
00913 sTempName = str;
00914 if ( (isHandledFStream = f!=nil)==true ) fHandle = fileno( f );
00915 DBGPRINT("DBG: TEMP PATH: <%s>, fHandle=%d\n",str,fHandle);
00916 #endif //linux...
00917 }
00918
00919 gFileTemp::gFileTemp (gFile::eFileKind aFKind)
00920 : gFileStream( aFKind, nil, false, true ),
00921 fHandle( -1 ),
00922 tempMethod( e_NamePre ),
00923 isHandledFStream( false )
00924 {
00925 gString sName(
00926 gFileControl::Self().GetUniqueName( gFileControl::Self().CtrlGetUserName().Str() )
00927 );
00928 if ( thisOverwrite( sName.Str() )==0 ) {
00929 fHandle = fileno( f );
00930 }
00931 }
00932
00933 gFileTemp::~gFileTemp ()
00934 {
00935 char* strNameTemp;
00936 if ( gFileControl::Self().tempL!=nil && IsOpened()==true ) {
00937 switch ( tempMethod ) {
00938 case e_NameStd:
00939 case e_NamePre:
00940 if ( sTempName.IsEmpty()==false ) {
00941 if ( isHandledFStream ) Close();
00942 strNameTemp = sTempName.Str();
00943 lastOpError = remove( strNameTemp )!=0;
00944 if ( lastOpError!=0 ) fprintf(stderr,"Unable to delete: %s\n",strNameTemp);
00945 gFileControl::Self().tempL->DeleteString( sTempName );
00946 }
00947 break;
00948 default:
00949 ASSERTION_FALSE("gFileTemp::~gFileTemp");
00950 break;
00951 }
00952 }
00953 }
00954
00955 bool gFileTemp::IsOpened ()
00956 {
00957 switch ( tempMethod ) {
00958 case e_NameStd:
00959 return fHandle!=-1;
00960 case e_NamePre:
00961 return gFileStream::IsOpened();
00962 default:
00963 return false;
00964 }
00965 }
00966
00967 bool gFileTemp::Rewind ()
00968 {
00969 off_t seekResult;
00970
00971 DBGPRINT("DBG: :::gFileTemp::Rewind(<%s>,method=%d,fHandle=%d)\n",sTempName.Str(),tempMethod,fHandle);
00972
00973 switch ( tempMethod ) {
00974
00975 case e_NameStd:
00976 if ( fHandle==-1 ) return false;
00977 #ifdef gDOS_SPEC
00978
00979 ASSERTION(f!=nil,"f!=nil");
00980 fclose( f );
00981 fHandle = -1;
00982 f = fopen( sTempName.Str(), "rb" );
00983 seekResult = f==nil ? -1 : 0;
00984 isHandledFStream = f!=nil;
00985 if ( isHandledFStream ) fHandle = fileno( f );
00986 #else
00987 seekResult = lseek( fHandle, 0L, SEEK_SET );
00988 #endif //gDOS_SPEC
00989 return seekResult!=(off_t)-1;
00990
00991 case e_NamePre:
00992 ASSERTION(fHandle!=-1,"Rewind(2)");
00993 if ( IsOpened()==false ) return false;
00994 ASSERTION(f!=nil,"Rewind(2)");
00995 fclose( f );
00996 DBGPRINT("DBG: reopening '%s'\n",sTempName.Str());
00997 f = fopen(sTempName.Str(),"rb");
00998 fHandle = -1;
00999 if ( f==nil ) return false;
01000 fHandle = fileno( f );
01001 break;
01002 default:
01003 ASSERTION_FALSE("Rewind(5)");
01004 break;
01005 }
01006
01007 return true;
01008 }
01009
01010 int gFileTemp::thisOverwrite (char* fName)
01011 {
01012 ASSERTION(fName!=nil,"fName!=nil");
01013 switch ( tempMethod ) {
01014 case e_NameStd:
01015 ASSERTION(fHandle!=-1,"fHandle!=-1");
01016 break;
01017 case e_NamePre:
01018 if ( Overwrite( fName )==false ) return -1;
01019 break;
01020 default:
01021 ASSERTION_FALSE("thisOverwrite");
01022 }
01023 sTempName = fName;
01024 gFileControl::Self().AddTempFile( sTempName );
01025 return lastOpError;
01026 }
01027
01028