campo-sirio/include/archives.cpp
guy 55a36762ef archives.cpp Tolto include windows.h
checks.cpp      Tolto include windows.h
colors.cpp      Tolto include windows.h
controls.cpp    Aggiunto cambiamento del font runtime dei TText_control
execp.cpp       Tolto include windows.h
form.cpp        Tolto include windows.h
mask.cpp        Corretta formattazione di due righe
maskfld.cpp     Aggiunto messaggio CHECK
msksheet.cpp    Tolto include windows.h
relapp.cpp      Tolto include windows.h
strings.pp      Corretto CHECK della TFixed_string::format()
viswin.cpp      Tolto include windows.h
window.cpp      Tolto include windows.h
xvtility.cpp    Corretto calcolo altezza righe delle maschere


git-svn-id: svn://10.65.10.50/trunk@4085 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-01-17 11:07:43 +00:00

566 lines
16 KiB
C++
Executable File

#include <direct.h>
#include <al.h>
#define XVT_INCL_NATIVE
#define STRICT
#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;
}