#include #ifndef XVAGA #define XVT_INCL_NATIVE #include #endif #include #include #include #include #include #include #include #include #include #include "ba2200.h" #include "ba2201.h" struct TAFile_info : public TObject { TFilename _name; long _size; int _disk; int _last_disk; }; /////////////////////////////////////////////////////////// // Archiving mask /////////////////////////////////////////////////////////// class TArchive_mask : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TArchive_mask(); }; TArchive_mask::TArchive_mask() : TAutomask("ba2200") { #if XVT_OS == XVT_OS_WIN16 TList_field& lf = (TList_field&)field(F_FLOPPY); TToken_string codes, values; TString4 str; int k = 0; for (int d = 0; d < 26; d++) { UINT t = ::GetDriveType(d); if (t != 0) { str.format("%c:", d+'A'); codes.add(str); values.add(str); TToken_string& message = *lf.message(k++, TRUE); if (t == DRIVE_REMOVABLE) message.format("DISABLE,%d", F_PATH); else message.format("ENABLE,%d", F_PATH); } } lf.replace_items(codes, values); #endif } bool TArchive_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_PATH: if (e == fe_modify) { TFilename path = o.get(); if (path[1] == ':') { set(F_FLOPPY, path.left(2)); o.set(path.mid(2)); } } break; case F_DITTA: if (e == fe_modify || e == fe_init) { set(F_RAGSOC, (o.get() != "") ? "Tutte le ditte" : "Nessuna ditta"); } break; case F_CODDITTA: if (e == fe_modify) { if (o.empty()) set(F_RAGSOC, o.active() ? "Tutte le ditte" : "Nessuna ditta"); } break; case F_SALVA: if (e == fe_button) { const long ditta = get_long(F_CODDITTA); if (ditta > 0L && !prefix().exist(ditta)) return error_box("La ditta %ld non esiste", ditta); } default: break; } return TRUE; } /////////////////////////////////////////////////////////// // Archiving application /////////////////////////////////////////////////////////// bool TArchive_app::create() { bool ok = TRUE; TIsamfile utenti(LF_USER); utenti.open(_excllock); for (int err = utenti.first(); err == NOERR; err = utenti.next()) { const TString16 u = utenti.get("USERNAME"); if (u != user() && utenti.get_bool("CONNECTED")) { ok = error_box("L'archiviazione non puo' essere effettuata\n" "se ci sono altri utenti collegati (%s)", (const char*)u); } } utenti.close(); if (ok) ok = TSkeleton_application::create(); return ok; } KEY TArchive_app::query(int& mode, long& firm, TFilename& floppy_path, TString& desc) const { TArchive_mask m; const KEY k = m.run(); if (k != K_QUIT) { mode = 0x0; firm = 0L; if (m.get_bool(F_COM)) mode |= 0x1; if (m.get_bool(F_DITTA)) { mode |= 0x2; firm = m.get_long(F_CODDITTA); } if (m.get_bool(F_CONFIG)) mode |= 0x4; if (m.get_bool(F_770)) mode |= 0x8; if (m.get_bool(F_CESP)) mode |= 0x10; floppy_path.format("%c:%c", toupper(m.get(F_FLOPPY)[0]), SLASH); floppy_path.add(m.get(F_PATH)); desc = m.get(F_DESCR); } return k; } void TArchive_app::add_file(const TFilename& name) { TAFile_info* fi = new TAFile_info; fi->_name = name; fi->_size = fsize(name); fi->_disk = fi->_last_disk = 1; _zip_list.add(fi); } bool TArchive_app::split_file(const TFilename& archive, unsigned long max_chunk) { TFilename output(archive); output.ext("z00"); int disk = 0; unsigned long scritti = 0; FILE* i = fopen(archive, "rb"); if (i == NULL) return FALSE; FILE* o = fopen(output, "wb"); const int BUFSIZE = 1024*16; TString buf(BUFSIZE); char* buffer = buf.get_buffer(); bool ok = TRUE; while (ok) { const size_t letti = fread(buffer, 1, BUFSIZE, i); if (letti == 0) break; if (scritti >= max_chunk) { fclose(o); add_file(output); TString16 ext; ext.format("z%02d", ++disk); output.ext(ext); o = fopen(output, "wb"); scritti = 0; } ok = fwrite(buffer, letti, 1, o) > 0; scritti += letti; } fclose(i); fclose(o); add_file(output); return ok; } bool TArchive_app::zip_dir(const TFilename& name, unsigned long max_chunk) { TFilename tmp; tmp.tempdir(); tmp.add(name.name()); tmp.ext("zip"); TFilename filenames = name; filenames.add("*.*"); ofstream o("ziplist.txt"); o << filenames << endl; o.close(); TString msg; msg << "Creazione del file temporaneo " << tmp << "..."; TIndwin waitw(100,msg,FALSE,FALSE); TWait_cursor hourglass; TFilename cmd; cmd << "zip.pif " << tmp << ' ' << "ziplist.txt" << " -j"; // -j NON salvare i path TExternal_app app(cmd); int err = app.run(FALSE, FALSE, FALSE, FALSE); remove("ziplist.txt"); if (err == 0 && tmp.exist()) { if (!split_file(tmp, max_chunk)) err = 1; remove(tmp); } return err == 0; } bool TArchive_app::can_save_as(const TFilename& src, const TFilename& dst) const { if (dst.exist()) remove(dst); long s = fsize(src); return os_test_disk_free_space(dst.left(3), s); } void TArchive_app::save_zip_files(const TFilename& floppy_path, const TString& desc, unsigned long max_chunk) { // Assegna un disco di destinazione a tutti i files int disk = 1; unsigned long written = 0; for (int i = 0; i < _zip_list.items(); i++) { TAFile_info& fi = (TAFile_info&)_zip_list[i]; if (written > 0 && (written+fi._size) >= max_chunk) { disk++; written = 0; } fi._disk = disk; written += fi._size; } bool ok = TRUE; if (os_is_removable_drive(floppy_path.left(3))) { const char* msg = "Si desidera procedere con l'operazione di salvataggio?"; if (disk == 1) ok = yesno_box("Controllare che il primo disco sia nel drive %c:\n%s", floppy_path[0], msg); else ok = yesno_box("Preparare %d dischetti vuoti e controllare che il primo sia nel drive %c:\n%s", disk, floppy_path[0], msg); if (!ok) return; } const TDate oggi(TODAY); TFilename name; name = floppy_path; name.add("backup.ini"); remove(name); TConfig ini(name, "Main"); ini.set("Date", oggi.string()); ini.set("Description", desc); ini.set("Disks", disk); ini.set("Format", "zip"); TFilename last_name; long size = 0; for (i = 0; i < _zip_list.items(); i++) { const TAFile_info& fi = (const TAFile_info&)_zip_list[i]; name = fi._name.name(); name.ext(""); if (name != last_name) { ini.set("FirstDisk", fi._disk, name); last_name = name; size = 0; } ini.set("LastDisk", fi._disk); ini.set("Size", size += fi._size); } ini.set_paragraph("Main"); // Forza scrittura ultimo paragrafo int curr_disk = 1; TProgind pi(_zip_list.items(), "Salvataggio dati in corso...", FALSE, TRUE); for (i = 0; i < _zip_list.items(); i++) { pi.addstatus(1); const TAFile_info& fi = (const TAFile_info&)_zip_list[i]; if (fi._disk != curr_disk) message_box("Inserire il disco vuoto n.%d", curr_disk = fi._disk); TFilename dest; dest = floppy_path; dest.add(fi._name.name()); while(!can_save_as(fi._name, dest)) { if (!yesno_box("Sul disco %d non c'e' spazio sufficiente per il file %s" "\nSi desidera sostituire il disco e ritentare?", curr_disk, (const char*)dest)) return; } fcopy(fi._name, dest); remove(fi._name); } } void TArchive_app::backup(int mode, long firm, const TFilename& floppy_path, const TString& desc) { TPointer_array ditte; if (firm == 0) { TLocalisamfile nditte(LF_NDITTE); for (int err = nditte.first(); err == NOERR; err = nditte.next()) { const long f = nditte.get_long("CODDITTA"); ditte.add_long(f); } } else ditte.add_long(firm); const TString16 old = prefix().name(); prefix().set(NULL); // Libera tutti i lock long max_chunk = ~0; if (os_is_removable_drive(floppy_path)) { message_box("Inserire un disco vuoto nel drive %c:", floppy_path[0]); max_chunk = os_get_disk_size(floppy_path) - (1024L*64L); } _zip_list.destroy(); bool ok = TRUE; TFilename name; if (ok && (mode & 0x1)) { name = firm2dir(0); ok = zip_dir(name, max_chunk); } if (ok && (mode & 0x2)) { for (int i = 0; ok && i < ditte.items(); i++) { firm = ditte.get_long(i); if (prefix().exist(firm)) { name = firm2dir(firm); ok = zip_dir(name, max_chunk); } } } if (ok && (mode & 0x4)) { name = firm2dir(-1); // __ptprf name.add("config"); // Aggiungi configurazioni ok = zip_dir(name, max_chunk); } if (ok && (mode & 0x8)) { name = firm2dir(-1); // __ptprf name.add("m770"); // Aggiungi 770 ok = zip_dir(name, max_chunk); } if (ok && (mode & 0x10)) { name = firm2dir(-1); // __ptprf name.add("cesp"); // Aggiungi cespiti ok = zip_dir(name, max_chunk); } prefix().set(old); // Ripristina prefix if (ok) save_zip_files(floppy_path, desc, max_chunk); else error_box("Si è verificato un errore di accesso al disco:\nVerificare lo spazio disponibile"); } bool TArchive_app::read_paragraph(TConfig& ini, const char* para) { const int first = ini.get_int("FirstDisk", para); const int last = ini.get_int("LastDisk"); const bool ok = first > 0 && last >= first; if (ok) { TFilename dir; dir.tempdir(); TString16 ext; int e = 0; for (int d = first; d <= last; d++) { TAFile_info* fi = new TAFile_info; TFilename& name = fi->_name; ext.format("z%02d", e++); name = dir; name.add(para); name.ext(ext); fi->_disk = d; fi->_last_disk = last; fi->_size = ini.get_int("Size"); _zip_list.add(fi); } } return ok; } void TArchive_app::load_zip_files(const TFilename& floppy_path) { TString msg; TFilename dir; dir.tempdir(); const int files = _zip_list.items(); TProgind pi(files, "Ripristino dati in corso...", TRUE, TRUE); int curr_disk = 1; for (int i = 0; i < files; i++) { const TAFile_info& info = (const TAFile_info&)_zip_list[i]; const int& disk = info._disk; msg = "Ripristino "; msg << info._name.name() << " in corso..."; pi.set_text(msg); pi.addstatus(1); if (pi.iscancelled()) break; if (os_is_removable_drive(floppy_path.left(3))) { if (disk != curr_disk) { message_box("Inserire il disco %d del backup", disk); curr_disk = disk; } } TFilename src; src = floppy_path; src.add(info._name.name()); TFilename dst; dst = dir; dst.add(info._name.name()); dst.ext("zip"); while (!fcopy(src, dst, TRUE)) if (!yesno_box("Si desidera ritentare?")) return; if (disk == info._last_disk) { TFilename exdir; exdir = firm2dir(-1); exdir.add(dst.name()); exdir.ext(""); TString cmdline; cmdline << "unzip.pif -o " << dst << " -d " << exdir; TExternal_app app(cmdline); app.run(FALSE, FALSE, FALSE, FALSE); } } } void TArchive_app::restore(int mode, long firm, const TFilename& floppy_path) { _zip_list.destroy(); TFilename name; name = floppy_path; name.add("backup.ini"); TConfig ini(name, "Main"); ini.write_protect(); if (mode & 0x1) read_paragraph(ini, "com"); if (mode & 0x2) { if (firm > 0) { TString16 para; para.format("%05lda", firm); read_paragraph(ini, para); } else { TString_array para; ini.list_paragraphs(para); for (int i = 0; i < para.items(); i++) { const TString& n = para.row(i); if (atol(n) > 0 && n.right(1) == "a") read_paragraph(ini, n); } } } if (mode & 0x4) read_paragraph(ini, "config"); if (mode & 0x8) read_paragraph(ini, "m770"); if (mode & 0x10) read_paragraph(ini, "cesp"); const int tot = _zip_list.items(); if (tot > 0) { TString fola; fola = "Verranno ripristinati i seguenti archivi:\n"; for (int i = 0; i < tot; i++) { const TAFile_info& info = (const TAFile_info&)_zip_list[i]; if (info._disk == info._last_disk) { TFilename n = info._name.name(); n.ext(""); fola << n << ", "; } } fola.rtrim(2); fola << ".\nSi desidera continuare?"; if (yesno_box(fola)) { const TString16 old = prefix().name(); prefix().set(NULL); // Libera tutti i lock load_zip_files(floppy_path); // Scompatta i files prefix().set(old); // Ripristina prefix } } else warning_box("I dati richiesti non sono presenti sul backup"); } void TArchive_app::interactive_mode() { KEY k; int mode; long firm; TFilename floppy_path; TString80 desc; while ((k = query(mode, firm, floppy_path, desc)) != K_QUIT) { if (mode) { if (k == K_SAVE) { const bool use_zip = TRUE; if (use_zip) backup(mode, firm, floppy_path, desc); else { TArchive arc; arc.backup(mode, firm, floppy_path[0], desc); } } else { TFilename ini_name; ini_name = floppy_path; ini_name.add("backup.ini"); if (os_is_removable_drive(floppy_path.left(3))) message_box("Inserire il primo disco del backup nel drive %c", floppy_path[0]); if (ini_name.exist()) { #ifdef XVAGA restore(mode, firm, floppy_path); #else bool use_zip = FALSE; { TConfig ini(ini_name, "Main"); ini.write_protect(); use_zip = ini.get("Format").compare("zip", TRUE) == 0; } if (use_zip) restore(mode, firm, floppy_path); else { TArchive arc; arc.restore(mode, firm, floppy_path[0], FALSE); } #endif } else error_box("Impossibile trovare il file %s", (const char*)ini_name); } } else error_box("Non e' stato specificato nessun archivio"); } } void TArchive_app::batch_mode(const TString& cmd) { const int mode = ~0; const long firm = 0; const TFilename floppy_path = cmd; restore(mode, firm, floppy_path); } void TArchive_app::main_loop() { TString cmd; if (argc() > 2) { TFilename ini = argv(2); if (ini.compare("/i", 2, TRUE) == 0) // qui { ini.ltrim(2); TConfig cfg(ini, "Main"); cmd = cfg.get("Action"); if (cmd.compare("Restore ", 8, TRUE) == 0) //qui { cmd.ltrim(8); cmd.trim(); } else cmd.cut(0); } else { if (ini.exist()) cmd = ini; } } if (cmd.empty()) { TMailbox mail; TMessage* msg = mail.next_s("RESTORE"); if (msg == NULL) { mail.restart(); msg = mail.next_s("Restore"); } if (msg) cmd = msg->body(); } if (cmd.empty()) interactive_mode(); else batch_mode(cmd); } int ba2200(int argc, char* argv[]) { TArchive_app a; a.run(argc, argv, "Archiviazione"); return 0; }