#define STRICT #include #include #include #include #include #include #include #include #include #include #include #include "ba2200.h" /////////////////////////////////////////////////////////// // TProgress_win declaration /////////////////////////////////////////////////////////// class TArchive; 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 /////////////////////////////////////////////////////////// class TArchive : public TObject { enum { BUFSIZE = 4096 }; ALArchive* _arc; protected: KEY query() const; FILE* ask_disk(TFilename& name, int disk, char floppy, bool lettura) const; long fsize(FILE* f) const; bool fsplit(const char* filename, char floppy, const char* desc = "") const; bool fbuild(const char* filename, char floppy) const; public: bool backup(const char* dir, char floppy, const char* desc); bool backup(long firm, char floppy, const char* desc); bool restore(const char* dir, char floppy, bool temp); bool restore(long firm, char floppy, bool temp); void stop_job(); }; FILE* TArchive::ask_disk(TFilename& name, int disk, char floppy, bool lettura) const { message_box("Inserire il disco %d nel drive %c:", disk, floppy); name.ext(format("%03d", disk)); 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 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; } 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); const long tot = fsize(i); 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 word letti = fread((char*)(const char*)buffer, 1, BUFSIZE, i); if (o != NULL) ok = letti ? (fwrite((char*)(const char*)buffer, letti, 1, o) == 1) : TRUE; else ok = FALSE; if (!ok) { if (o != NULL) 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 TString16 d(c.get("Date")); if (d.not_empty()) { ok = yesno_box("Il disco %d contiene gia' un backup del direttorio %s del %s" "\nSi desidera continuare ugualmente?", disk, (const char*)parag, (const char*)d); if (!ok) break; } } else { FILE* i = fopen(ini, "w"); // Crea il file backup.ini fclose(i); } 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 ? (fwrite((char*)(const char*)buffer, letti, 1, o) == 1) : TRUE; if (!ok) error_box("Impossibile scrivere i dati sul dischetto"); } } w.addstatus(letti); if (letti < BUFSIZE) break; if (ok) ok = !w.iscancelled(); } 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); long totale = 0L; // Bytes letti long max = 1440000L; // Bytes da leggere TFilename name; // Nome del file su dischetto name << floppy << ":/" << work.name(); TString256 msg("Rispristino da "); msg << name; TProgind w(max, msg, TRUE, TRUE, 32); int disk = 0; TString buffer(BUFSIZE); bool ok = TRUE; while (ok) { word letti = 0; if (i != NULL) { letti = fread((char*)(const char*)buffer, 1, BUFSIZE, i); ok = letti > 0; } else ok = FALSE; if (!ok) { 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) { letti = fread((char*)(const char*)buffer, 1, BUFSIZE, i); ok = letti > 0; } } } if (ok) { 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 (letti < BUFSIZE || totale == max) break; } fclose(o); if (i != NULL) fclose(i); return ok; } bool TArchive::backup(const char* dir, char floppy, const char* desc) { const TString16 old(prefhndl->name()); prefhndl->set(NULL); save_dir(); chdir(dir); const TFilename d(dir); const TString16 name(d.name()); TFilename work; work.tempdir(); work << '/' << name << ".gal"; _arc = new ALArchive(work); TProgress_win w("Archiviazione", this); ALEntryList list(w.monitor()); _arc->AddWildCardFiles( list, "*.*" ); w.open_modal(); _arc->Create( list ); bool ok = _arc->mStatus == AL_SUCCESS; if (!ok) error_box("Compressione degli archivi errata o incompleta:\n%s", _arc->mStatus.GetStatusString()); w.close_modal(); delete _arc; _arc = NULL; if (ok) ok = fsplit(work, floppy, desc); remove(work); restore_dir(); prefhndl->set(old); return ok; } bool TArchive::backup(long firm, char floppy, const char* desc) { const TFilename dir(firm2dir(firm)); return backup(dir, floppy, desc); } bool TArchive::restore(const char* dir, char floppy, bool tmp) { 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; const TString16 old(prefhndl->name()); prefhndl->set(NULL); save_dir(); bool ok = chdir(work) == 0; if (!ok) { prefhndl->set(old); return error_box("Impossibile accedere a %s", (const char*)work); } 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); } restore_dir(); prefhndl->set(old); return ok; } bool TArchive::restore(long firm, char floppy, bool temp) { const TFilename dir(firm2dir(firm)); return restore(dir, floppy, temp); } 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) { 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_CANCEL, 0, "", -11, 3, 10, 2); set_handler(DLG_CANCEL, cancel_handler); #if XVT_OS == XVT_OS_WIN HWND txt = (HWND)get_value(wtxt, ATTR_NATIVE_WINDOW); HWND num = (HWND)get_value(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; } /////////////////////////////////////////////////////////// // Archiving application /////////////////////////////////////////////////////////// class TArchive_app : public TApplication { TArchive _arc; protected: virtual bool create(); virtual bool menu(MENU_TAG); KEY query(long& firm, char& floppy, TString& desc, bool& tmp) const; public: void stop_job(); TArchive_app() {} virtual ~TArchive_app() {} }; bool TArchive_app::create() { TApplication::create(); dispatch_e_menu(BAR_ITEM(1)); return TRUE; } KEY TArchive_app::query(long& firm, char& floppy, TString& desc, bool& temp) const { TMask m("ba2200"); const KEY k = m.run(); if (k != K_QUIT) { firm = m.get_long(F_CODDITTA); floppy = m.get(F_FLOPPY)[0]; desc = m.get(F_DESCR); temp = m.get_bool(F_TEMP); } return k; } bool TArchive_app::menu(MENU_TAG) { KEY k; long firm; char floppy; TString80 desc; bool temp; while ((k = query(firm, floppy, desc, temp)) != K_QUIT) { if (k == K_SAVE) _arc.backup(firm, floppy, desc); else _arc.restore(firm, floppy, temp); } return FALSE; } int ba2200(int argc, char* argv[]) { TArchive_app a; a.run(argc, argv, "Archiviazione"); return 0; }