TArchive::backup() e TArchive::restore(). git-svn-id: svn://10.65.10.50/trunk@1856 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			499 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			499 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#define STRICT
 | 
						|
#include <windows.h>
 | 
						|
#include <direct.h>
 | 
						|
 | 
						|
#include <al.h>         
 | 
						|
#include <archives.h>
 | 
						|
#include <config.h>
 | 
						|
#include <isam.h>
 | 
						|
#include <mask.h>
 | 
						|
#include <prefix.h>
 | 
						|
#include <progind.h>
 | 
						|
#include <urldefid.h>
 | 
						|
#include <utility.h>
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TProgress_win declaration
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
 | 
						|
class TProgress_win : public TMask
 | 
						|
{                  
 | 
						|
  ALWindowsMessage* _monitor;         
 | 
						|
  TArchive* _arc;
 | 
						|
  
 | 
						|
protected:
 | 
						|
  static bool cancel_handler(TMask_field&, KEY k); 
 | 
						|
  
 | 
						|
public:
 | 
						|
  ALWindowsMessage* monitor() const { return _monitor; }
 | 
						|
  
 | 
						|
  TProgress_win(const char* title, TArchive* = NULL);
 | 
						|
  ~TProgress_win();
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TArchive
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
 | 
						|
FILE* TArchive::ask_disk(TFilename& name, int disk, char floppy, bool lettura) const
 | 
						|
{     
 | 
						|
  TFilename prev(name);
 | 
						|
  prev.ext(format("%03d", disk-1));       // File precedente
 | 
						|
  bool first = TRUE;
 | 
						|
  do
 | 
						|
  {                 
 | 
						|
    if (first)
 | 
						|
    {
 | 
						|
      message_box("Inserire il disco %d nel drive %c:", disk, floppy);
 | 
						|
      first = FALSE;
 | 
						|
    }  
 | 
						|
    else
 | 
						|
    {
 | 
						|
      const bool ok = yesno_box("Inserire il disco %d nel drive %c\n"
 | 
						|
                                "Estrarre il disco %d e continuare?", disk, floppy, disk-1);
 | 
						|
      if (!ok) return NULL;                          
 | 
						|
    }
 | 
						|
  } while (fexist(prev));                 // Non facciamo i furbetti!
 | 
						|
 | 
						|
  name.ext(format("%03d", disk));         // File attuale
 | 
						|
  
 | 
						|
  FILE* f = NULL;                                                           
 | 
						|
  bool retry = TRUE;
 | 
						|
  while (retry)
 | 
						|
  {               
 | 
						|
    f = fopen(name, lettura ? "rb" : "wb");
 | 
						|
    if (f == NULL) 
 | 
						|
      retry = yesno_box("Il file %s non e' accessibile: riprovare?", (const char*)name);
 | 
						|
    else
 | 
						|
    {
 | 
						|
      setvbuf(f, NULL, _IOFBF, BUFSIZE);
 | 
						|
      retry = FALSE; 
 | 
						|
    }  
 | 
						|
  }  
 | 
						|
 | 
						|
  return f;
 | 
						|
} 
 | 
						|
 | 
						|
long TArchive::fsize(FILE* f) const
 | 
						|
{     
 | 
						|
  CHECK(f, "Can't measure NULL file");
 | 
						|
  fseek(f, 0, SEEK_END);
 | 
						|
  const long s = ftell(f);
 | 
						|
  fseek(f, 0, SEEK_SET);
 | 
						|
  return s;
 | 
						|
} 
 | 
						|
 | 
						|
int TArchive::build_backup_list(long firm, TString_array& fl) const
 | 
						|
{
 | 
						|
  fl.destroy();
 | 
						|
  if (firm < 0L)
 | 
						|
  {                     
 | 
						|
    fl.add(firm2dir(0L));
 | 
						|
    TLocalisamfile ditte(LF_NDITTE);
 | 
						|
    for (int err = ditte.first(); err == NOERR; err = ditte.next())
 | 
						|
    {
 | 
						|
      const char* dir = firm2dir(ditte.get_long("CODDITTA"));
 | 
						|
      if (fexist(dir))
 | 
						|
        fl.add(dir);
 | 
						|
    }  
 | 
						|
    
 | 
						|
    TFilename name(firm2dir(-1));     // __ptprf
 | 
						|
    name.add("config");               // Aggiungi configurazioni
 | 
						|
    if (fexist(name))
 | 
						|
      fl.add(name);                                                
 | 
						|
  }
 | 
						|
  else
 | 
						|
    fl.add(firm2dir(firm));
 | 
						|
  
 | 
						|
  return fl.items();  
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Costruisce la lista delle directory da scompattare
 | 
						|
int TArchive::build_restore_list(long firm, char floppy, TString_array& fl) const
 | 
						|
{   
 | 
						|
  if (firm < 0)                                       // Crea lista automaticamente
 | 
						|
  {      
 | 
						|
    TFilename name("a:/backup.ini"); name[0] = floppy;
 | 
						|
    TConfig ini(name);
 | 
						|
    const int max = ini.list_paragraphs(fl);          // Lista degli archivi
 | 
						|
    for (int i = max-1; i >= 0; i--)
 | 
						|
    {
 | 
						|
      const int disk = ini.get_int("Disk", fl.row(i));
 | 
						|
      if (disk == 1) 
 | 
						|
      {
 | 
						|
        firm = atol(fl.row(i));
 | 
						|
        fl.add(firm2dir(firm), i);                    // Aggiungi gli archivi che iniziano qui
 | 
						|
      }
 | 
						|
      else fl.destroy(i, TRUE);                       // Elimina gli archivi che non iniziano qui
 | 
						|
    } 
 | 
						|
    
 | 
						|
    name = firm2dir(-1);                              // __ptprf
 | 
						|
    name.add("config");                               // Aggiungi configurazioni
 | 
						|
    fl.add(name);                                                
 | 
						|
  }
 | 
						|
  else  
 | 
						|
  {
 | 
						|
    fl.destroy();
 | 
						|
    fl.add(firm2dir(firm));                           // Inserisci solo una ditta (o COM)
 | 
						|
  }
 | 
						|
  
 | 
						|
  return fl.items();    
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool TArchive::fsplit(const char* filename, char floppy, const char* desc) const
 | 
						|
{               
 | 
						|
  const TFilename from(filename);          // File da splittare
 | 
						|
 | 
						|
  FILE* i = fopen(from, "rb"), *o = NULL;
 | 
						|
  if (i == NULL) return error_box("Impossibile aprire il file '%s'", from);
 | 
						|
  setvbuf(i, NULL, _IOFBF, BUFSIZE);
 | 
						|
  
 | 
						|
  const long tot = fsize(i);  
 | 
						|
  long       scritti=0;
 | 
						|
  
 | 
						|
  TFilename work;
 | 
						|
  work << floppy << ":/" << from.name();    // File su dischetto
 | 
						|
 | 
						|
  TString256 msg("Archiviazione di "); msg << work << " (" << (tot/1024) << "K)";
 | 
						|
  TProgind w(tot, msg, TRUE, TRUE, 40);
 | 
						|
  
 | 
						|
  int disk = 0;        
 | 
						|
  TString buffer(BUFSIZE);
 | 
						|
  
 | 
						|
  bool ok = TRUE;
 | 
						|
  while (ok)
 | 
						|
  {
 | 
						|
    const size_t letti = fread((char*)(const char*)buffer, 1, BUFSIZE, i);
 | 
						|
    
 | 
						|
    if (o != NULL)
 | 
						|
      ok = (letti > 0) ? (fwrite((char*)(const char*)buffer, letti, 1, o) == 1) : TRUE;
 | 
						|
    else
 | 
						|
      ok = FALSE;  
 | 
						|
    
 | 
						|
    if (!ok) 
 | 
						|
    { 
 | 
						|
      
 | 
						|
      if (o != NULL)
 | 
						|
      {
 | 
						|
        chsize(fileno(o),scritti);  // Must truncate output file or some information will be rewritten on next disk!
 | 
						|
        scritti = 0;                // Reset count bytes written to disk.
 | 
						|
        fclose(o);
 | 
						|
      }
 | 
						|
      o = ask_disk(work, ++disk, floppy, FALSE);
 | 
						|
      ok = o != NULL;                                               
 | 
						|
      if (ok) 
 | 
						|
      { 
 | 
						|
        TFilename parag(work.name()); parag.ext("");
 | 
						|
        TFilename ini("a:/backup.ini"); ini[0] = floppy;
 | 
						|
        
 | 
						|
        if (fexist(ini)) 
 | 
						|
        {
 | 
						|
          TConfig c(ini, parag);
 | 
						|
          const int d = c.get_int("Disk");
 | 
						|
          if (d == disk)
 | 
						|
          {
 | 
						|
            ok = yesno_box("Il disco %d contiene gia' un backup del direttorio %s del %s"
 | 
						|
                           "\nSi desidera continuare?", 
 | 
						|
                           disk, (const char*)parag, (const char*)c.get("Date"));
 | 
						|
          }    
 | 
						|
        }  
 | 
						|
        else
 | 
						|
        {
 | 
						|
          FILE* i = fopen(ini, "w");    // Crea il file backup.ini per evitare messaggi
 | 
						|
          fclose(i);
 | 
						|
        }
 | 
						|
        if (!ok) break;
 | 
						|
        
 | 
						|
        TConfig c(ini, parag);
 | 
						|
        const char* oggi = TDate(TODAY).string();
 | 
						|
        c.set("Size", tot , NULL, TRUE); 
 | 
						|
        c.set("Disk", disk, NULL, TRUE);
 | 
						|
        c.set("Description", desc, NULL, TRUE);
 | 
						|
        c.set("Date", oggi, NULL, TRUE);
 | 
						|
        
 | 
						|
        ok = (letti > 0) ? (fwrite((char*)(const char*)buffer, letti, 1, o) == 1) : TRUE;
 | 
						|
        if (!ok) error_box("Impossibile scrivere i dati sul dischetto");
 | 
						|
        else 
 | 
						|
          scritti +=letti;
 | 
						|
      }  
 | 
						|
    }
 | 
						|
    else
 | 
						|
      scritti += letti;
 | 
						|
    w.addstatus(letti);
 | 
						|
    if (ok) 
 | 
						|
      ok = !w.iscancelled();
 | 
						|
    if (letti < BUFSIZE) 
 | 
						|
      break;
 | 
						|
  }    
 | 
						|
 | 
						|
  fclose(i);
 | 
						|
  if (o != NULL) fclose(o);
 | 
						|
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool TArchive::fbuild(const char* filename, char floppy) const
 | 
						|
{               
 | 
						|
  const TFilename work(filename);
 | 
						|
 | 
						|
  FILE* o = fopen(work, "wb"), *i = NULL;
 | 
						|
  if (o == NULL) 
 | 
						|
    return error_box("Impossibile creare il file '%s'", (const char*)work);
 | 
						|
  setvbuf(o, NULL, _IOFBF, BUFSIZE);
 | 
						|
 | 
						|
  long totale = 0L;                        // Bytes letti
 | 
						|
  long max = 1440000L;                     // Bytes da leggere
 | 
						|
  TFilename name;                          // Nome del file su dischetto
 | 
						|
  name << floppy << ":/" << work.name();
 | 
						|
 | 
						|
  TString256 msg("Ripristino da "); msg << name;
 | 
						|
  TProgind w(max, msg, TRUE, TRUE, 32);
 | 
						|
  
 | 
						|
  int disk = 0;        
 | 
						|
  TString buffer(BUFSIZE);
 | 
						|
  
 | 
						|
  bool ok = TRUE;
 | 
						|
  while (ok)
 | 
						|
  {       
 | 
						|
    size_t letti = 0;
 | 
						|
    if (i != NULL)
 | 
						|
    {
 | 
						|
      letti = fread((char*)(const char*)buffer, 1, BUFSIZE, i);
 | 
						|
      ok = letti > 0;
 | 
						|
    }  
 | 
						|
    else
 | 
						|
      ok = FALSE;  
 | 
						|
    
 | 
						|
    if (!ok)       // Richiedi nuovo disco
 | 
						|
    {
 | 
						|
      if (i != NULL) fclose(i);
 | 
						|
      i = ask_disk(name, ++disk, floppy, TRUE);
 | 
						|
      ok = i != NULL;                                               
 | 
						|
      if (ok) 
 | 
						|
      {            
 | 
						|
        if (disk == 1)
 | 
						|
        {                                            
 | 
						|
          TFilename ini("a:/backup.ini"); ini[0] = floppy;
 | 
						|
          if (fexist(ini)) 
 | 
						|
          {
 | 
						|
            TFilename parag(name.name()); parag.ext("");
 | 
						|
            TConfig c(ini, parag);
 | 
						|
            max = c.get_long("Size");
 | 
						|
          }
 | 
						|
          else ok = yesno_box("Manca il file %s: continuare ugualmente?", (const char*)ini);
 | 
						|
        }                                    
 | 
						|
        w.setmax(max);
 | 
						|
        
 | 
						|
        if (ok)   // Leggi primo blocco di bytes
 | 
						|
        {
 | 
						|
          letti = fread((char*)(const char*)buffer, 1, BUFSIZE, i);
 | 
						|
          ok = letti > 0;
 | 
						|
        }  
 | 
						|
      }  
 | 
						|
    }
 | 
						|
    
 | 
						|
    if (ok)       // La lettura e stata fatta bene
 | 
						|
    {
 | 
						|
      ok = fwrite((char*)(const char*)buffer, 1, letti, o) == letti;
 | 
						|
      if (ok) 
 | 
						|
      {
 | 
						|
        w.addstatus(letti);   
 | 
						|
        totale += letti;
 | 
						|
        ok = !w.iscancelled();
 | 
						|
      }
 | 
						|
      else error_box("Impossibile scrivere i dati sul file %s", (const char*)work);
 | 
						|
    }         
 | 
						|
    
 | 
						|
    if (!ok || totale == max)      // Esci in caso di errore o se hai finito
 | 
						|
      break;
 | 
						|
  }    
 | 
						|
 | 
						|
  fclose(o);
 | 
						|
  if (i != NULL) fclose(i);
 | 
						|
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TArchive::backup(const char* dir, char floppy, const char* desc, bool pr_set)
 | 
						|
{                                      
 | 
						|
  const TString16 old(prefix().name());
 | 
						|
  if (pr_set)
 | 
						|
    prefix().set(NULL);
 | 
						|
  
 | 
						|
  xvt_fsys_save_dir();
 | 
						|
  chdir(dir);
 | 
						|
  
 | 
						|
  const TFilename d(dir);
 | 
						|
  const TString16 name(d.name());
 | 
						|
  TFilename work; work.tempdir(); work.add(name); work.ext("gal");
 | 
						|
 | 
						|
  _arc = new ALArchive(work);
 | 
						|
  
 | 
						|
  TString256 title("Archiviazione di "); title << name;
 | 
						|
  TProgress_win w(title, this);
 | 
						|
  ALEntryList list(w.monitor());
 | 
						|
  _arc->AddWildCardFiles(list, "*.*");
 | 
						|
  
 | 
						|
  w.open_modal();
 | 
						|
  _arc->Create( list );
 | 
						|
  w.close_modal();
 | 
						|
  
 | 
						|
  bool ok = _arc->mStatus == AL_SUCCESS;
 | 
						|
  if (ok)
 | 
						|
    ok = fsplit(work, floppy, desc);
 | 
						|
  else  
 | 
						|
    error_box("Compressione degli archivi errata o incompleta:\n%s", 
 | 
						|
              _arc->mStatus.GetStatusDetail());
 | 
						|
 | 
						|
  delete _arc; _arc = NULL;
 | 
						|
  
 | 
						|
  remove(work);
 | 
						|
  xvt_fsys_restore_dir();
 | 
						|
  if (pr_set)
 | 
						|
    prefix().set(old);
 | 
						|
  
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TArchive::backup(long firm, char floppy, const char* desc, bool pr_set)
 | 
						|
{                     
 | 
						|
  TString_array fl;
 | 
						|
  const int num_ditte = build_backup_list(firm, fl);
 | 
						|
  
 | 
						|
  bool ok = TRUE;
 | 
						|
  for (int f = 0; f < num_ditte; f++)
 | 
						|
  {                                  
 | 
						|
    ok = backup(fl.row(f), floppy, desc, pr_set);
 | 
						|
    if (!ok) break;
 | 
						|
  }
 | 
						|
  
 | 
						|
  return ok;  
 | 
						|
}
 | 
						|
 | 
						|
bool TArchive::restore(const char* dir, char floppy, bool tmp, bool pr_set)
 | 
						|
{                 
 | 
						|
  TFilename work;
 | 
						|
  if (tmp) 
 | 
						|
    work.tempdir();
 | 
						|
  else 
 | 
						|
    work = dir;
 | 
						|
  
 | 
						|
  TFilename output(dir); 
 | 
						|
  output = output.name(); output.ext("gal");
 | 
						|
 | 
						|
  if (!yesno_box("Attenzione l'archivio sul disco %c: verra' ripristinato\n"
 | 
						|
                 "nel direttorio %s. Continuare?", floppy, (const char*)work))
 | 
						|
    return FALSE;             
 | 
						|
  
 | 
						|
  xvt_fsys_save_dir();
 | 
						|
  bool ok = chdir(work) == 0;
 | 
						|
  if (!ok) 
 | 
						|
  {
 | 
						|
    ok = yesno_box("Non esiste il direttorio %s: si desidera crearlo?", (const char*)work);
 | 
						|
    if (ok) 
 | 
						|
    {
 | 
						|
      make_dir(work);
 | 
						|
      ok = chdir(work) == 0;
 | 
						|
    }  
 | 
						|
    if (!ok)
 | 
						|
      return error_box("Impossibile accedere a %s", (const char*)work);
 | 
						|
  }  
 | 
						|
 | 
						|
  const TString16 old(prefix().name());
 | 
						|
  if(pr_set)
 | 
						|
    prefix().set(NULL);
 | 
						|
  
 | 
						|
  ok = fbuild(output, floppy);
 | 
						|
 | 
						|
  if (ok)
 | 
						|
  {
 | 
						|
    _arc = new ALArchive(output);
 | 
						|
 | 
						|
    TProgress_win w("Ripristino", this);
 | 
						|
    ALEntryList list(w.monitor());
 | 
						|
    _arc->ReadDirectory(list);
 | 
						|
    
 | 
						|
    w.open_modal();
 | 
						|
    _arc->Extract( list );
 | 
						|
    
 | 
						|
    ok = _arc->mStatus == AL_SUCCESS;
 | 
						|
    if (!ok) error_box("Ripristino degli archivi errato o incompleto:\n%s", 
 | 
						|
                       _arc->mStatus.GetStatusString());
 | 
						|
    w.close_modal();    
 | 
						|
    delete _arc; _arc = NULL;
 | 
						|
    
 | 
						|
    remove(output);
 | 
						|
  }
 | 
						|
  
 | 
						|
  xvt_fsys_restore_dir();
 | 
						|
  if(pr_set)
 | 
						|
    prefix().set(old);
 | 
						|
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TArchive::restore(long firm, char floppy, bool temp, bool pr_set)
 | 
						|
{
 | 
						|
  TString_array fl;
 | 
						|
  const int num_ditte = build_restore_list(firm, floppy, fl);
 | 
						|
  
 | 
						|
  bool ok = TRUE;
 | 
						|
  for (int f = 0; f < num_ditte; f++)
 | 
						|
  {                                  
 | 
						|
    ok = restore(fl.row(f), floppy, temp, pr_set);
 | 
						|
    if (!ok) break;
 | 
						|
  }
 | 
						|
  
 | 
						|
  return ok;  
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void TArchive::stop_job()
 | 
						|
{
 | 
						|
  if (_arc != NULL)
 | 
						|
    _arc->GetStorageObject()->mStatus.SetError(AL_USER_ABORT, "Interrotto dall'utente");
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TProgress_win implementation
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
TProgress_win::TProgress_win(const char* title, TArchive* arc)
 | 
						|
: TMask(title, 1, 60, 5), _arc(arc)
 | 
						|
{ 
 | 
						|
  WINDOW wtxt = add_string(101, 0, "", -11, 1, 56, "D"); 
 | 
						|
  WINDOW wnum = add_number(102, 0, "", -11, 2, 4, "D"); 
 | 
						|
  WINDOW wcan = add_button(DLG_USER, 0, "#102Cancel", -11, 3, 10, 2); 
 | 
						|
  set_handler(DLG_USER, cancel_handler);
 | 
						|
 | 
						|
#if XVT_OS == XVT_OS_WIN
 | 
						|
  HWND txt = (HWND)xvt_vobj_get_attr(wtxt, ATTR_NATIVE_WINDOW);
 | 
						|
  HWND num = (HWND)xvt_vobj_get_attr(wnum, ATTR_NATIVE_WINDOW);
 | 
						|
  _monitor = new ALWindowsMessage(AL_MONITOR_OBJECTS, txt, AL_SEND_RATIO, num);
 | 
						|
#endif                      
 | 
						|
}                   
 | 
						|
 | 
						|
TProgress_win::~TProgress_win()
 | 
						|
{  
 | 
						|
  if (_monitor) delete _monitor;
 | 
						|
}                     
 | 
						|
 | 
						|
bool TProgress_win::cancel_handler(TMask_field& f, KEY k)
 | 
						|
{
 | 
						|
  if (k == K_SPACE) 
 | 
						|
  {
 | 
						|
    TProgress_win& m = (TProgress_win&)f.mask();
 | 
						|
    if (m._arc != NULL)
 | 
						|
      m._arc->stop_job();
 | 
						|
  }  
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 |