gfile.cpp

Go to the documentation of this file.
00001 // gfile.cpp -- Version 0.8
00002 
00003 #include <stdlib.h> // For: rand/mkstemp
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 // OS-SPECIFIC
00012 #include <time.h>
00013 #include <signal.h>
00014 #ifdef gDOS_SPEC
00015 #include <windows.h>
00016 #endif //gDOS_SPEC
00017 // *end* OS-SPECIFIC
00018 
00019 // Static members
00020 gFileControl gFileControl::myself;
00021 bool gFileControl::isTerminated=false;
00022 
00023 // Global vars
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" },  // see ifdef
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  //Suppressed because of forked behaviour:
00089  //     if ( tempL!=nil ) fprintf(stderr,"@FILE: unreleased.\n");
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  // strerror() primitive would do as well...
00169  sErrorRef = strerror( aErrorNo );
00170  // Deprecated: return (char*)sys_errlist[aErrorNo]
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  // Returns 0 if ok (initialized)
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  // Returns non-zero (typically 1) if the signal is to be 'signaled'/handled by glib
00237  t_int16 iter, sigId;
00238  for (iter=0; ; iter++) {
00239      sigId = global_signal_traps[iter].sigId;
00240      if ( sigId<0 ) return 0;  // Not found, therefore it's not signaled
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; // never reaches here
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; // never reaches here
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; // never reaches here
00287 }
00288 
00289 void gFileControl::SignalHandler (int signalId)
00290 {
00291  if ( isTerminated ) {
00292      // Because of thread support
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  // This old statement was deprecated:  if ( doEnd ) OnEventTerminate( gglobal_EventTerminate )
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  // Not using PATH_MAX, but supporting an arbitrarily long string
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  //printf("DBG: NanoSleep (%u sec, %u nanoSeconds)\n",(unsigned)uSec,(unsigned)nSec);
00376  return nanosleep( &tReq, &tRem );
00377 #else
00378  // Highly artificial Win32 solution (!!)
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  //// sleep( aSec ) ::: primitive seconds, occupying too much processor
00393  /*
00394  clock_t current, end, seconds = (clock_t)aSec;
00395  current = clock();
00396  end = current + CLOCKS_PER_SEC * seconds;
00397  while (current < end) {
00398         current = clock();
00399  }
00400  return 0;
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; // micro-seconds
00413         mSec *= 1000; // nano-seconds
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  // signal( signal_id, SIG_DFL )  is used to force default signal behaviour
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); //especialy useful for sockets!
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  // signal(SIGCLD, SIG_IGN)  <== used with forked-base progs.
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          // Below more relaxed names allowed...
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          // Allow almost all ISO8859-1 characters...
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 // gFile - Generic file handling
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  // Reads one chunk of data of 'bufSize' bytes
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  //size_t fread (void *ptr, size_t size, size_t nmemb, FILE *stream)
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  // Try to read 'bufSize' bytes into 'buf'.
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  // Tries to read one chunk of data of 'bufSize' bytes; if read less than
00673  // that, still returns true but returns 'nBytes' that were effectively read.
00674  ;
00675  // From:
00676  //   #include <unistd.h>
00677  //   ssize_t read(int fd, void *buf, size_t count);
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  // Returns 0 on success
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  // Returns true on success;
00832  // isOk is true if buffer is big enough for the line
00833  // that is being read.
00834  static unsigned readLineLen;
00835 
00836  lastOpError = 0;
00837 
00838  // Clean just the first position of buffer,
00839  // since it is a text-file read-out.
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  // At least one character is present when 'fgets' succeeds.
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  // This contructor is designed to be used with
00883  //    <unistd.h>
00884  //    ssize_t write(int fd, const void *buf, size_t count)
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  // Note str gets overwritten by mkstemp
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      // Limitation: file was re-opened...
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  }//end CASE
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 

Generated on Sat Aug 18 02:40:53 2007 for xpfweb_v2x lib by  doxygen 1.4.2