565 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			565 lines
		
	
	
		
			16 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
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Funzione per richiedere all'utente il dischetto e per controllare la
 | |
| //        corretta sequenza dei dischetti da inserire
 | |
| //
 | |
| // @rdesc Ritorna il puntatore al file presente (o meno) sul dischetto
 | |
| FILE* TArchive::ask_disk(
 | |
|       TFilename& name,      // @parm Nome del file da creare/cercare su disco
 | |
|       int disk,             // @parm Numero progressivo del set
 | |
|       char floppy,          // @parm Drive sul quale effettuare l'operazione (A, B, C, ...)
 | |
|       bool lettura) const   // @parm Indica il modo di apertura del file:
 | |
|                             //
 | |
|                             // @flag TRUE | Apre il file in lettura
 | |
|                             // @flag FALSE | Apre il file in scrittura
 | |
| {     
 | |
|   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();  
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Costruisce la lista delle directory da scompattare
 | |
| //
 | |
| // @rdesc Ritorna il numero di direttori da ripristinare
 | |
| int TArchive::build_restore_list(
 | |
|     long firm,                // @parm Ditta di cui effettuare il salvataggio
 | |
|     char floppy,              // @parm Floppy su cui effettuare il backup
 | |
|     TString_array& fl) const  // @parm Nomi dei direttori da ripristinare
 | |
| {   
 | |
|   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();    
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Spezza il file in modo da farlo stare sul dischetto
 | |
| //
 | |
| // @rdesc Ritorna se e' riuscito a spezzare il file
 | |
| bool TArchive::fsplit(
 | |
|      const char* filename,    // @parm Nome del file da spezare
 | |
|      char floppy,             // @parm Floppy su cui scaricare il file
 | |
|      const char* desc) const  // @parm Descrizione dell'archivio
 | |
| {               
 | |
|   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;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Ricostruisce il file spezzato
 | |
| //
 | |
| // @rdesc Ritorna se e' riuscito a ricostruire il file
 | |
| bool TArchive::fbuild(
 | |
|      const char* filename, // @parm Nome del file da ricostrutire
 | |
|      char floppy) const    // @parm Floppy da cui recupare i pezzi del file
 | |
| {               
 | |
|   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;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Effettua il backup della ditta o della directory
 | |
| //
 | |
| // @rdesc Ritorna il risultato dell'operazione
 | |
| bool TArchive::backup(
 | |
|      const char* dir,  // @parm Directory di cui effettuare il backup
 | |
|      char floppy,      // @parm Floppy su cui effettuare il backup
 | |
|      const char* desc, // @parm Descrizione da assegnare al backup
 | |
|      bool pr_set)      // @parm Se TRUE setta il prefix come vuoto (default TRUE)
 | |
|                        // @parm long | firm | Ditta di cui effettuare il backup
 | |
|                        
 | |
| // @syntax bool backup(const char* dir, char floppy, const char* desc, bool pr_set);
 | |
| // @syntax bool backup(long firm, char floppy, const char* desc, bool pr_set);
 | |
| 
 | |
| // @comm Il parametro <p pr_set> e' utilizzato per evitare errori di riaperture di files.
 | |
| 
 | |
| {                                      
 | |
|   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;  
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Effettua il restore della ditta o dell directory
 | |
| //
 | |
| // @rdesc Ritorna il risultato dell'operazione
 | |
| bool TArchive::restore(
 | |
|      const char* dir,   // @parm Directory di cui effettuare il restore
 | |
|      char floppy,       // @parm Floppy da cui leggere i dati
 | |
|      bool tmp,          // @parm Directory temporanea da utilizzare
 | |
|      bool pr_set)       // @parm Se TRUE setta il prefix come vuoto (default TRUE)
 | |
|      
 | |
| // @syntax bool restore(const char* dir, char floppy, bool temp, bool pr_set);
 | |
| // @syntax bool restore(long firm, char floppy, bool temp, bool pr_set);
 | |
| 
 | |
| // @comm Il parametro <p pr_set> e' utilizzato per evitare errori di riaperture di files.
 | |
| 
 | |
| {                 
 | |
|   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, 6), _arc(arc)
 | |
| { 
 | |
|   RCT rct; 
 | |
|   xvt_rect_set(&rct, CHARX, CHARY, 58*CHARX, 5*CHARY/2);
 | |
|   WINDOW wtxt = xvt_ctl_create(WC_EDIT, &rct, "", win(), CTL_FLAG_DISABLED, (long)this, 101);
 | |
|   xvt_rect_set(&rct, 28*CHARX, 3*CHARY, 33*CHARX, 9*CHARY/2);
 | |
|   WINDOW wnum = xvt_ctl_create(WC_EDIT, &rct, "", win(), CTL_FLAG_DISABLED, (long)this, 102);
 | |
|   
 | |
|   add_button(DLG_USER, 0, "Cancel", -11, -1, 10, 2, "", BMP_CANCEL); 
 | |
|   set_handler(DLG_USER, cancel_handler);
 | |
| 
 | |
| #if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
 | |
|   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;
 | |
| }
 | |
| 
 | |
| 
 |