#include #include #include #include #include #include #include #include #include "ba2200.h" #include "ba2201.h" #include #include #include #include "mask.h" struct TAFile_info : public TObject { TFilename _name; long _size; int _disk; int _last_disk; }; bool is_real_floppy(const TFilename& path) { return (path[0] == 'A' || path[0] == 'B') && xvt_fsys_is_removable_drive(path); } /////////////////////////////////////////////////////////// // Archiving mask /////////////////////////////////////////////////////////// class TArchive_mask : public TAutomask { private: int _selected=-1; // -1: nessuna selezione altrimenti si sala la riga selezionata protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); virtual bool on_key(KEY key); public: TArchive_mask(); void load_sheet(); void fill_field(); const TString& get_selected() const; }; TArchive_mask::TArchive_mask() : TAutomask("ba2200") { TList_field& lf = lfield(F_FLOPPY); TToken_string codes, values; TString4 str; int k = 0; for (int d = 0; d < 26; d++) { str.format("%c:", 'A'+d); const bool isrem = xvt_fsys_is_removable_drive(str) != 0; const bool isfix = !isrem && xvt_fsys_is_fixed_drive(str); const bool isnet = !isrem && !isfix && xvt_fsys_is_network_drive(str); if (isrem || isfix || isnet) { codes.add(str); values.add(str); TToken_string& message = *lf.message(k++, TRUE); if (isrem && is_real_floppy(str)) message.format("CLEAR,%d", F_PATH); else message.format("ENABLE,%d", F_PATH); } } enable(F_RIPR, false); enable(F_DELETE, false); lf.replace_items(codes, values); fill_field(); load_sheet(); } void TArchive_mask::fill_field() { TFilename bkp_path = ini_get_string(CONFIG_STUDIO, "ba", "BkpPath"); if (bkp_path.full()) { TList_field& lf = lfield(F_FLOPPY); if (bkp_path[1] == ':') { lf.set(bkp_path.left(2)); TString b = get(F_FLOPPY); set(F_PATH, bkp_path.mid(2)); TFilename path = get(F_FLOPPY); path << SLASH; path.add(get(F_PATH)); } if (!bkp_path.exist()) error_box(FR("Percorso non valido: %s"), (const char*)bkp_path); else { enable(F_PATH, false); enable(F_FLOPPY, false); } } } bool TArchive_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { short a = o.dlg(); TSheet_field& sf = sfield(F_BKPTABLE); switch (o.dlg()) { case F_PATH: if (e == fe_button) { TFilename path = get(F_FLOPPY); path << SLASH; path.add(o.get()); DIRECTORY dir; xvt_fsys_convert_str_to_dir(path, &dir); if (xvt_dm_post_dir_sel(&dir) == FL_OK) { xvt_fsys_convert_dir_to_str(&dir, path.get_buffer(), path.size()); o.set(path); e = fe_modify; } } if (e == fe_modify) { TFilename path = o.get(); if (path[1] == ':') { set(F_FLOPPY, path.left(2)); TString a = get(F_FLOPPY); o.set(path.mid(2)); } path = get(F_FLOPPY); path << SLASH; path.add(o.get()); if (!path.exist()) return error_box(FR("Percorso non valido: %s"), (const char*)path); else { ini_set_string(CONFIG_STUDIO, "ba", "BkpPath", path); load_sheet(); } } break; case F_DITTA: if (e == fe_modify || e == fe_init) { set(F_RAGSOC, !o.empty() ? TR("Tutte le ditte") : TR("Nessuna ditta")); } break; case F_CODDITTA: if (e == fe_modify) { if (o.empty()) set(F_RAGSOC, o.active() ? TR("Tutte le ditte") : TR("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(FR("La ditta %ld non esiste"), ditta); } break; case F_RELOAD: if (e == fe_button) { load_sheet(); } break; case F_DELETE: if (e == fe_button) { TFilename path = get(F_FLOPPY); path << SLASH; path.add(get(F_PATH))<count; enable(F_RIPR, false); enable(F_DELETE, false); _selected = -1; sf.force_update(); } const TString& TArchive_mask::get_selected() const { TSheet_field& sf = sfield(F_BKPTABLE); const TString& name = sf.get_str_row_cell(sf.selected(), S_NOME); return name; } /////////////////////////////////////////////////////////// // 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 TString& u = utenti.get(USR_USERNAME); if (u != user() && utenti.get_bool(USR_CONNECTED)) #ifdef DBG ok = yesno_box("L'archiviazione non puo' essere effettuata\nse ci sono altri utenti collegati (%s)", (const char*)u); #else ok = error_box(FR("L'archiviazione non puo' essere effettuata\nse ci sono altri utenti collegati (%s)"), (const char*)u); #endif } utenti.close(); if (ok) { ok = TSkeleton_application::create(); } return ok; } KEY TArchive_app::query(int& mode, long& firm, TFilename& floppy_path, TString& desc, TString& pkgname) 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_CUSTOM)) mode |= 0x10; floppy_path.format("%c:%c", toupper(m.get(F_FLOPPY)[0]), SLASH); const TString& bkp_path = ini_get_string(CONFIG_STUDIO, "ba", "BkpPath"); floppy_path.add(m.get(F_PATH)); desc = m.get(F_DESCR); if (k == K_SAVE) pkgname = m.get(F_NOMEPKG); else if (k == K_INS) pkgname = m.get(F_SELECTED); } 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) { bool ok = true; TFilename output(archive); output.ext("z00"); if (max_chunk > 0 && max_chunk < LONG_MAX) // Devo davvero suddividere archive? { int disk = 0; unsigned long scritti = 0; FILE* i = NULL; fopen_s(&i, archive, "rb"); if (i == NULL) return FALSE; FILE* o = NULL; fopen_s(&o, output, "wb"); const int BUFSIZE = 1024*16; TString buf(BUFSIZE); char* buffer = buf.get_buffer(); 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); TString4 ext; ext.format("z%02d", ++disk); output.ext(ext); fopen_s(&o, output, "wb"); scritti = 0; } ok = fwrite(buffer, letti, 1, o) > 0; scritti += letti; } fclose(i); fclose(o); archive.fremove(); } else { if (output.exist()) output.fremove(); ok = ::rename(archive, output) == 0; // Basta rinominarlo } if (ok) add_file(output); return ok; } bool TArchive_app::zip_dir(const TFilename& name, unsigned long max_chunk, const TString dir_name) { TFilename tmp; tmp.tempdir(); tmp.add(dir_name); if (!tmp.exist()) xvt_fsys_mkdir(tmp); tmp.add(name.name()); tmp.ext("zip"); bool ok = false; if (name.full()) { TFilename filenames = name; filenames.add("*.*"); TString msg; msg << TR("Creazione del file temporaneo ") << tmp << "..."; TIndwin waitw(100, msg, false, false); ok = aga_zip(filenames, tmp); } if (ok && tmp.exist()) ok = split_file(tmp, max_chunk); return ok; } bool TArchive_app::prepare_package(const TString pkg_name, unsigned long max_chunk, const TFilename& floppy_path, const TString& desc) { TFilename pkg_tmp; TFilename bak_dir; pkg_tmp.tempdir(); bak_dir.tempdir(); pkg_tmp.add(pkg_name); if (!pkg_tmp.exist()) { error_box("Errore imprevisto! Pacchetto non trovato"); } else { bak_dir.add(pkg_name); bak_dir.add("bakup"); if(!bak_dir.exist()) xvt_fsys_mkdir(bak_dir); //pkg_tmp.ext("zip"); } // Assegna un disco di destinazione a tutti i files int disk = 1; unsigned long written = 0; int i; for (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; } const TFilename& from = fi._name; const TString& fname = from.name(); TFilename to = bak_dir; to.add(fname); fmove(fi._name, to); fi._disk = disk; written += fi._size; } bool ok = true; TFilename bak_zip = pkg_tmp; bak_zip.add("backup.zip"); if (ok) { const TDate oggi(TODAY); TFilename inifile = pkg_tmp; inifile.add("backup.ini"); //TFilename name; name = floppy_path; name.add("backup.ini"); inifile.fremove(); TConfig ini(inifile, "Main"); ini.set("Date", oggi.string()); ini.set("Description", desc); ini.set("User", user()); 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]; inifile = fi._name.name(); inifile.ext(""); if (inifile != last_name) { ini.set("FirstDisk", fi._disk, inifile); last_name = inifile; 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; } if (pkg_name.full()) { TFilename all_files = bak_dir; all_files.add("*.*"); TString msg; msg << TR("Creazione del file temporaneo ") << pkg_tmp << "..."; TIndwin waitw(100, msg, false, false); ok &= aga_zip(all_files, bak_zip); } if (ok && bak_zip.exist()) { ok &= split_file(bak_zip, max_chunk); remove_files(bak_dir, true); xvt_fsys_rmdir(bak_dir); } int curr_disk = 1; if (!can_save_as(pkg_tmp, floppy_path)) { if (!yesno_box(FR("Sul disco %d non c'e' spazio sufficiente per il file %s\nSi desidera sostituire il disco e ritentare?"), curr_disk, (const char*)floppy_path)) return false; } TFilename destination = floppy_path; destination.add(pkg_name); TFilename mask = pkg_tmp; mask.add("*.*"); SLIST files = xvt_fsys_list_files("", mask, false); if (!destination.exist()) ok &= xvt_fsys_mkdir(destination); ok &= xvt_fsys_files_move(pkg_tmp, files, destination) == files->count; ok &= xvt_fsys_rmdir(pkg_tmp); return ok; } bool TArchive_app::can_save_as(const TFilename& src, const TFilename& dst) const { if (dst.exist()) remove(dst); long s = fsize(src); return xvt_fsys_test_disk_free_space(dst.left(3), s) != 0; } bool TArchive_app::save_zip_files(const TFilename& floppy_path, const TString& desc, unsigned long max_chunk, const TString dir_name) { // Assegna un disco di destinazione a tutti i files int disk = 1; unsigned long written = 0; int i; for (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; const bool is_floppy = is_real_floppy(floppy_path); if (is_floppy) { const char* msg = TR("Si desidera procedere con l'operazione di salvataggio?"); if (disk == 1) ok = yesno_box(FR("Controllare che il primo disco sia nel drive %c:\n%s"), floppy_path[0], msg); else ok = yesno_box(FR("Preparare %d dischetti vuoti e controllare che il primo sia nel drive %c:\n%s"), disk, floppy_path[0], msg); } else { if (!xvt_fsys_mkdir(floppy_path)) ok = error_box(FR("Impossibile creare la cartella %s"), (const char*)floppy_path); } if (ok) { const TDate oggi(TODAY); TFilename name; name = floppy_path; name.add("backup.ini"); name.fremove(); 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(), TR("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(FR("Inserire il disco vuoto n.%d"), curr_disk = fi._disk); TFilename dest; dest = floppy_path; dest.add(dir_name); if (!dest.exist()) xvt_fsys_mkdir(dest); dest.add(fi._name.name()); while(!can_save_as(fi._name, dest)) { if (!yesno_box(FR("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 false; } fcopy(fi._name, dest); fi._name.fremove(); } } return ok; } void TArchive_app::backup(int mode, long firm, const TFilename& floppy_path, const TString& desc, const TString& pkgname) { TPointer_array ditte; if (firm == 0) prefix().firms(ditte); else ditte.add_long(firm); const TString16 old = prefix().name(); prefix().set(NULL); // Libera tutti i lock long max_chunk = LONG_MAX; const TDate today(TODAY); TString dir_name = pkgname; dir_name << today.date2ansi(); if (is_real_floppy(floppy_path)) { message_box(FR("Inserire un disco vuoto nel drive %c:"), floppy_path[0]); max_chunk = xvt_fsys_get_disk_size(floppy_path, 'B') - (1024L*64L); } _zip_list.destroy(); bool ok = true; TFilename name; if (ok && (mode & 0x1)) { name = firm2dir(0); ok &= zip_dir(name, max_chunk, dir_name); } 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, dir_name); } } } if (ok && (mode & 0x4)) { name = firm2dir(-1); // __ptprf name.add("config"); // Aggiungi configurazioni ok &= zip_dir(name, max_chunk, dir_name); } if (ok && (mode & 0x8)) { name = firm2dir(-1); // __ptprf name.add("m770"); // Aggiungi 770 if (name.exist()) ok &= zip_dir(name, max_chunk, dir_name); } if (ok && (mode & 0x10)) { name = firm2dir(-1); // __ptprf name.add("custom"); // Aggiungi personalizzazioni if (name.exist()) ok &= zip_dir(name, max_chunk, dir_name); } prefix().set(old); // Ripristina prefix if (ok) { ok &= prepare_package(dir_name, max_chunk, floppy_path, desc); } else error_box(TR("Si è verificato un errore di accesso al disco:\nVerificare lo spazio disponibile")); if (ok) message_box(TR("Backup avvenuto con successo!")); else warning_box(TR("Errore nella procedura di backup! Contattare l'assistenza")); } bool TArchive_app::read_paragraph(TConfig& ini, const char* para, const TString& pkgname) { 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(); dir.add(pkgname); 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("backup"); 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& pkgpath, const TFilename& tmppkg) { TString msg; TFilename dir; dir.tempdir(); const int files = _zip_list.items(); TProgind pi(files, TR("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 = TR("Ripristino "); msg << info._name.name() << TR("..."); pi.set_text(msg); pi.addstatus(1); if (pi.iscancelled()) break; if (is_real_floppy(pkgpath.path())) { if (disk != curr_disk) { message_box(FR("Inserire il disco %d del backup"), disk); curr_disk = disk; } } TFilename studio = prefix().get_studio(); TFilename src; src = tmppkg; src.add(info._name.name()); TFilename dst; dst = studio; dst.add(info._name.name()); dst.ext("zip"); while (!fcopy(src, dst, i > 0)) if (!yesno_box(TR("Si desidera ritentare?"))) return; if (disk == info._last_disk) { TFilename exdir; exdir = firm2dir(-1); exdir.add(dst.name()); exdir.ext(""); aga_unzip(dst, exdir); } } } void TArchive_app::restore(int mode, long firm, const TFilename& pkgpath) { _zip_list.destroy(); const TString& pkgname = pkgpath.name(); TFilename tmp_path; tmp_path.tempdir(); tmp_path.add(pkgname); TFilename ini_path; ini_path = pkgpath; ini_path.add("backup.ini"); TFilename z00_path; z00_path = pkgpath; z00_path.add("backup.z00"); if (!ini_path.exist()) TR("Errore! Il pacchetto è sprovvisto del file .ini e non può essere ripristinato"); if (!z00_path.exist()) TR("Errore! Il pacchetto è corrotto e non può essere ripristinato"); TConfig ini(ini_path, "Main"); ini.write_protect(); if (mode & 0x1) read_paragraph(ini, "com", pkgname); if (mode & 0x2) { if (firm > 0) { TString8 para; para.format("%05lda", firm); read_paragraph(ini, para, pkgname); } 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, pkgname); } } } if (mode & 0x4) read_paragraph(ini, "config", pkgname); if (mode & 0x8) read_paragraph(ini, "m770", pkgname); if (mode & 0x10) read_paragraph(ini, "custom", pkgname); const int tot = _zip_list.items(); if (tot > 0) { TString fola; fola = TR("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 << TR(".\nSi desidera continuare?"); if (yesno_box(fola)) { const TString16 old = prefix().name(); prefix().set(NULL); // Libera tutti i lock aga_unzip(z00_path, tmp_path); // scompatta il file backup.z00 load_zip_files(pkgpath, tmp_path); // Scompatta i files TFilename mask = tmp_path; mask.add("*.*"); // Elimina i file temporanei remove_files(mask, true); xvt_fsys_rmdir(tmp_path); prefix().set(old); // Ripristina prefix } } else warning_box(TR("I dati richiesti non sono presenti sul backup")); } void TArchive_app::interactive_mode() { KEY k; int mode; long firm; TFilename floppy_path; TString80 desc; TString pkgname; while ((k = query(mode, firm, floppy_path, desc, pkgname)) != K_QUIT) { if (mode) { if (k == K_SAVE) { if (pkgname.empty()) error_box(FR("Inserire un Nome Pacchetto valido!")); else backup(mode, firm, floppy_path, desc, pkgname); } else { TFilename pkgpath = floppy_path; pkgpath.add(pkgname); TFilename ini_name = pkgpath; ini_name.add("backup.ini"); if (is_real_floppy(floppy_path)) message_box(FR("Inserire il primo disco del backup nel drive %c"), floppy_path[0]); if (ini_name.exist()) { bool yn = yesno_box(FR("Attenzione! I dati attualmente presenti negli archivi verranno sovrascritti.\nAssicurarsi di aver fatto un backup prima di continuare.\nProcedere?")); if(yn) restore(mode, firm, pkgpath); } else error_box(FR("Impossibile trovare il file %s"), (const char*)ini_name); } } else error_box(TR("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, TR("Archiviazione")); return 0; }