campo-sirio/ba/ba1100.cpp
guy 97cf100315 Patch level : 10.0 200
Files correlati     : ba1.exe
Ricompilazione Demo : [ ]
Commento            :
0001036: installazione cd patch 180
Installando ex novo ed indicando una società esistente di dati su una cartella diversa viene segnalato l'errore ba1.exe in fase di conversione archivi, richiamando da manutenzione archivi la conversione vengono generati gli errori allegati. Nell'area ftp di Aga, cartella Ilaria allego l'area dati SIDA per il test.


git-svn-id: svn://10.65.10.50/trunk@17973 c028cbd2-c16b-5b4b-a496-9718f37d4682
2008-12-23 09:11:50 +00:00

1639 lines
42 KiB
C++
Executable File
Raw Blame History

#include "ba1.h"
#include "ba1100.h"
#include "ba1103.h"
#include <applicat.h>
#include <dongle.h>
#include <printer.h>
#include <progind.h>
#include <reprint.h>
#include <reputils.h>
#include <utility.h>
#include <urldefid.h>
#include <user.h>
#ifdef WIN32
#include <io.h>
#include <share.h>
#include <sys/stat.h>
#else
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#endif
#define History_file "conv.his"
#define Dir_file "dir.gen"
#define Trc_file "trc.gen"
class TManutenzione_app : public TSkeleton_application
{
TDir_sheet* _browse;
TArray _dirs;
TArray _recs;
TMask* _mask;
long _firm;
long _level;
long _history_firm;
TRec_sheet* _rec;
TLog_report* _log;
bool _print_log;
bool _superprassi;
protected:
virtual void main_loop();
virtual bool create () ;
virtual bool destroy();
void insert_riga(long, TToken_string&);
void edit_riga(long, TToken_string&);
void edit_riga(const TString&);
void delete_riga(long);
virtual bool extended_firm() const { return true; }
bool recover(TSystemisamfile& f, int err);
void update();
void update_dir();
void convert_dir();
virtual void print();
virtual void do_print(TPrinter & p, TRec_sheet & r);
const char* dumpfilename(const FileDes& dep) const;
void load_des();
void open_history();
void put_history(const char* firm);
void close_history();
void dump_trc(const char * dir, const bool des_too, const long modules);
void repair_file(int i);
void save_file(const char * file);
void open_log();
void write_log(const char* line, const int severity = 0);
void close_log();
bool moveable_file(int file) const;
public:
TManutenzione_app();
};
HIDDEN bool browse_file_handler(TMask_field& f, KEY k)
{
if (k == K_F9)
{
FILE_SPEC fs; memset(&fs, 0, sizeof(FILE_SPEC));
TFilename fname = f.get(); fname.ext("dbf");
xvt_fsys_convert_str_to_fspec(fname, &fs);
xvt_fsys_get_default_dir(&fs.dir);
xvt_fsys_save_dir();
if (xvt_dm_post_file_open(&fs, TR("Selezione file")) == FL_OK)
{
TFilename n;
xvt_fsys_convert_dir_to_str(&fs.dir, n.get_buffer(n.size()), n.size());
n.add(fs.name);
f.set(n);
}
xvt_fsys_restore_dir();
f.set_focus();
}
return true;
}
TManutenzione_app::TManutenzione_app() : _browse(NULL), _mask(NULL), _firm(0), _level(0), _rec(NULL), _log(NULL)
{
if (!fexist(Dir_file)) // controlla l'esistenza dei direttori standard (dir.gen e trc.gen)
{ // vengono creati se non esistono
FileDes fd; memset(&fd, 0, sizeof(fd));
strncpy(fd.SysName, "$dir.gen", sizeof(fd.SysName));
strncpy(fd.Des, "Directory", sizeof(fd.Des));
strncpy(fd.FCalc, "0", sizeof(fd.FCalc));
strncpy(fd.GenPrompt,"", sizeof(fd.GenPrompt));
fd.LenR =160;
fd.EOD = fd.EOX = 1L;
fd.Flags = 0;
#ifdef WIN32
int handle = sopen(Dir_file, O_RDWR|O_BINARY|O_CREAT,SH_DENYNO,S_IREAD|S_IWRITE);
#else
int handle = open(Dir_file, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO);
#endif
if (handle != -1)
{
if (write( handle, &fd, sizeof(FileDes)) == -1)
fatal_box("Impossibile scrivere il file dir.gen per dati standard: errore %d",errno);
close(handle);
}
else
fatal_box("Impossibile creare il file dir.gen per dati standard: errore %d",errno);
}
if (!fexist(Trc_file))
{
TTrec r;
RecDes& rd = r.rec();
#ifdef WIN32
int handle = sopen(Trc_file, O_RDWR|O_BINARY|O_CREAT,SH_DENYNO,S_IREAD|S_IWRITE);
#else
int handle = open(Trc_file, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO);
#endif
if (handle != -1)
{
if (write( handle, (void*)&rd, sizeof(RecDes)) == -1)
fatal_box("Impossibile scrivere il file trc.gen per dati standard: errore %d",errno);
close(handle);
}
else
fatal_box("Impossibile creare il file trc.gen per dati standard: errore %d",errno);
}
}
void TManutenzione_app::do_print(TPrinter & p, TRec_sheet & r)
{
const char* table[] = {"", TR("Alfanumerico"), TR("Intero"), TR("Intero Lungo"),
TR("Reale"), TR("Data"), TR("Intero"), TR("Carattere"),
TR("Booleano"), TR("Intero Zerofilled"), TR("Intero Lungo Zerofilled"),TR("Memo")};
TPrintrow row;
TToken_string s;
TParagraph_string d("", 25);
TConfig * descr = NULL;
const TTrec& rec = r.rec();
const TDir& dir = r.dir();
const char * descfname = r.descfname();
TString4 tab(r.tab());
const bool istab = tab.not_empty();
tab.upper();
if (fexist(descfname))
descr = new TConfig(descfname, DESCPAR);
const bool hasdescr = descr != NULL;
row.reset();
if (istab)
row.put(format(FR("Lista tabella %s "), (const char *) tab), 2);
else
row.put(format(FR("Lista tracciato %s (%s)"), dir.des(), dir.name()), 2);
row.put(TR("Pag. @#"), 69);
p.setheaderline(2, row);
row.reset();
row.put(HR("Nome"), 7);
row.put(HR("Tipo"), 18);
row.put(HR("Lun."), 38);
row.put(HR("Dec."), 44);
row.put(HR("Pos."), 48);
row.put(HR("Descrizione"), 53);
p.setheaderline(4, row);
TString riga(78); riga.fill('-');
row.put(riga, 1);
p.setheaderline(5, row);
int i;
for (i = 0; i < rec.fields(); i ++)
{
row.reset();
s = rec.fielddef(i);
TString16 name = s.get();
row.put(format("%3d", i + 1), 2);
row.put(name, 7);
row.put(table[s.get_int()], 18);
row.put(format("%4d", s.get_int()), 38);
row.put(format("%4d", s.get_int()), 43);
row.put(format("%4d", rec.rec().Fd[i].RecOff), 48);
const char *wd = NULL;
d = "";
if (hasdescr)
d = descr->get(name);
if (!istab || d.not_empty())
{
if (hasdescr)
{
wd = d.get();
if (wd != NULL)
row.put(wd, 53);
}
p.print(row);
wd = d.get();
while(wd != NULL)
{
row.reset();
row.put(wd, 53);
p.print(row);
wd = d.get();
}
}
}
row.reset();
p.print(row);
row.put(HR("Espressione chiave"), 7);
row.put(HR("Duplicabile"), 68);
p.setheaderline(4, row);
if (p.rows_left() < 5)
p.formfeed();
else
{
p.print(row);
row.put(riga, 1);
p.print(row);
}
for (i = 0; i < rec.keys(); i ++)
{
row.reset();
s = rec.keydef(i);
row.put(format("%3d", i + 1), 2);
row.put(s.get(), 7);
row.put(*s.get() == 'X' ? TR("Si") : TR("No"), 68);
p.print(row);
}
p.formfeed();
if (hasdescr)
delete descr;
}
void TManutenzione_app::print()
{
TPrinter& p = printer();
p.open();
p.headerlen(6);
p.footerlen(4);
if (_rec == NULL)
{
TDir d; d.get(LF_DIR);
int items = (int)d.eod();
if (items > 0)
{
TProgind pi(items, TR("Stampa tracciati record archivi"), true, true);
for (int i = LF_USER; pi.setstatus(i) && i <= items; i++)
{
d.get(i);
if (d.len() > 0)
{
TRec_sheet r(i, "");
do_print(p, r);
}
}
}
TString_array list;
items = list_files("recdesc/d???.des", list);
if (items > 0)
{
TProgind pi(items, TR("Stampa descrizione tabelle"), true, true);
TString16 tab;
for (int i = 0; pi.setstatus(i) && i < items; i++)
{
tab = list.row(i).right(7);
tab.cut(3);
if (isalpha(tab[0]))
{
TRec_sheet r(4, tab);
do_print(p, r);
}
}
}
}
else
do_print(p, *_rec);
p.close();
}
bool TManutenzione_app::create() // initvar e arrmask
{
_firm = get_firm();
TString sw(argc()>2 ? argv(2) : "");
// Posso fare le operazione avanzate solo se sono ammistratore
// e NON mi trovo su di una installazione di tipo client
_superprassi = user() == ::dongle().administrator();
if (_superprassi)
{
TConfig campo_ini(CONFIG_INSTALL, "Main");
const int type = campo_ini.get_int("Type");
if (type == 1 || type == 2)
_superprassi = true;
else
_superprassi = campo_ini.get_bool("TestDatabase");
}
if (argc() > 2 && sw == "-C")
{
update();
return false;
}
else
{
if (sw == "-D")
{
const int c = argc();
bool des_too = true; // Anche le descrizioni
long modules = -1; // Tutti i moduli
if (c < 4)
{
error_box("Usage: BA1 -0 -D <directory> [0|1] [<module number>]");
return false;
}
TFilename dir(argv(3));
if (!fexist(dir))
{
error_box(FR("Non esiste il direttorio %s"), (const char*)dir);
return false;
}
if (c == 5)
des_too = atoi(argv(4)) ? true : false;
if (c == 6)
modules = atol(argv(5));
prefix().set("");
load_des();
dump_trc(dir,des_too,modules);
return false;
}
#ifndef _DEMO_
else
if (!set_firm())
return false;
#endif
load_des();
_mask = new TMask("ba1100a");
_browse = new TDir_sheet(TR("Manutenzione file di sistema"), _superprassi);
if (_superprassi)
{
_mask->enable(-1); // Abilita campi privilegiati del gruppo 1
}
}
enable_menu_item(M_FILE_PRINT);
return TSkeleton_application::create();
}
bool TManutenzione_app::destroy() // releasev e arrmask
{
if (_firm) set_firm(_firm);
if (_browse != NULL) delete _browse;
if (_mask != NULL) delete _mask;
return TApplication::destroy() ;
}
void TManutenzione_app::open_log()
{
_print_log = false;
if (_log == NULL)
{
TString s; s << TR("Conversione") << ' ' << TDate(TODAY);
_log = new TLog_report(s);
}
}
void TManutenzione_app::write_log(const char* line, const int severity)
{
if (_log != NULL)
{
_log->log(severity, line);
if (severity > 0)
_print_log = true;
}
}
void TManutenzione_app::close_log()
{
if (_log != NULL)
{
if (_print_log)
{
TReport_book book;
book.add(*_log);
book.preview();
}
delete _log;
_log = NULL;
}
}
void TManutenzione_app::save_file(const char * file)
{
TFilename n(file);
const TFilename source_path(n.path());
TFilename dest_path(source_path);
n.ext("*");
TString_array files_to_copy;
list_files(n, files_to_copy);
dest_path << "sav";
if (!dest_path.exist())
make_dir(dest_path);
FOR_EACH_ARRAY_ROW_BACK(files_to_copy, row, fname)
{
TFilename source_file(*fname);
TFilename dest_file(dest_path); dest_file << '/' << (const char *) source_file.name();
fcopy((const char *) source_file, dest_file);
}
}
void TManutenzione_app::insert_riga (long riga_sel, TToken_string& riga)
{
const int logicnum = int(riga_sel) + 1;
const int num_files = (int)_browse->items();
_mask->disable(DLG_PACK);
_mask->disable(DLG_RECORD);
_mask->disable(DLG_LOAD);
_mask->disable(DLG_DUMP);
_mask->show(F_TAB, logicnum >= LF_TABGEN && logicnum <= LF_TAB);
_mask->hide(FLD_EXTEND);
_mask->hide(FLD_EOX);
_mask->set (FLD_NUM, riga.get(0));
_mask->reset (F_TAB);
if (_mask->run() == K_ENTER)
{
/* shift di uno in avanti degli elementi del direttorio partendo dall'ultimo */
for (int i=num_files; i>=logicnum; i--)
{
_browse->dir().get (i, _nolock, _nordir, _sysdirop);
_browse->dir().put (i + 1, _nordir, _sysdirop);
_browse->rec().get (i);
_browse->rec().put (i + 1);
}
_browse->dir().set(_mask->get(FLD_NOME), _mask->get_long(FLD_EOD),
_mask->get_long(FLD_FLAG), _mask->get (FLD_DESC),
_mask->get (FLD_FORMULA));
_browse->dir().put(logicnum, _nordir, _sysdirop);
_browse->rec().zero();
_browse->rec().put(logicnum);
_browse->dir().get(LF_DIR);
_browse->dir().set_eod(_browse->dir().eod()+1);
_browse->set_items(_browse->dir().eod());
_browse->dir().put(LF_DIR);
}
}
void TManutenzione_app::open_history()
{
FILE *fp = fopen(History_file,"r");
if (fp != NULL)
{
char line[16];
fgets(line,16,fp);
int l = strlen(line);
line[l > 0 ? l -1 : 0 ] = '\0';
if (l==0) _history_firm = -1;
else
_history_firm = atol(line);
}
else
{
fp = fopen(History_file,"w");
_history_firm = -1;
}
fclose (fp);
}
void TManutenzione_app::put_history(const char* firm)
{
FILE * fp = fopen(History_file,"w");
fprintf(fp,"%s\n",firm);
fclose (fp);
}
void TManutenzione_app::close_history()
{
// Se la conversione non ha rilevato errori rimuove il file di history.
remove(History_file);
}
void TManutenzione_app::dump_trc(const char * dir, const bool des_too, const long modules)
{
TDir d;
d.get(LF_DIR);
const int items = (int) d.eod();
const long flags = d.flags(); // livello archivi
TFilename fn(dir);
fn << "/level.dir";
{
ofstream of(fn);
of << flags << '\n';
}
TString s(TR("Scarico dei tracciati standard in "));
s << dir;
TProgind p(items ? items : 1, s, false, true);
p.setstatus(1);
for (int i=2;i<=items;i++) //Salta il primo (dir.gen)
{
p.addstatus(1);
TTrec& rc = (TTrec&)_recs[i];
TDir& dr = (TDir&)_dirs[i];
const long file_mod = (long)abs((int)dr.flags());
if (modules != -1 && file_mod != modules) continue; // se non fa parte del modulo lo salta
TFilename descfname;
descfname.format("%s/d%d.des", DESCDIR, i);
if (!fexist(descfname)) // crea la descrizione se non esiste
{
FILE * fd = fopen(descfname, "w");
if (fd != NULL)
fclose(fd);
}
TConfig conf_des(descfname,DESCPAR);
if (des_too) rc.set_des(&conf_des);
fn = dir;
fn << "/f";fn << i;
fn.ext("trr");
ofstream out(fn);
out << rc;
fn.ext("dir");
ofstream out_dir(fn);
out_dir << dr;
}
}
const char* TManutenzione_app::dumpfilename(const FileDes& dep) const
{
TFilename n; n.tempdir();
n.add(dep.SysName);
n.strip("$%");
n.ext("txt");
n.lower();
TString & tmp = get_tmp_string();
tmp = n;
return tmp;
}
void TManutenzione_app::edit_riga (const TString& name)
{
const TFilename n(name);
TExternisamfile* f = new TExternisamfile(n);
_mask->set (FLD_NUM, "");
_mask->set (FLD_NOME, n);
_mask->set (FLD_EOD, f->items());
_mask->set (FLD_EOX, f->items());
_mask->set (F_LEN, f->curr().len());
_mask->set (FLD_DESC, f->description());
_mask->set (FLD_FORMULA, "");
_mask->set (FLD_FLAG, "");
_mask->reset (FLD_EXTEND);
_mask->reset (F_TAB);
_mask->disable(-1);
_mask->enable(DLG_RECORD, _superprassi);
KEY tasto = _mask->run();
switch (tasto)
{
case K_F4:
{
TEdit_file ef;
ef.browse_file(f, n);
break;
}
case K_F6:
_rec = new TRec_sheet(f);
_rec->edit();
delete _rec;
_rec = NULL;
delete f; // La delete di TExternisamfile va fatta solo qui perche' in K_F4 viene fatta dalla TRelation interna
break;
default:
break;
}
}
void TManutenzione_app::edit_riga (long riga_sel, TToken_string& riga)
{
KEY tasto;
FileDes dep;
TDir d;
const int logicnum = int(riga_sel) + 1;
_mask->enable(DLG_PACK, _superprassi);
_mask->enable(DLG_RECORD, _superprassi);
_mask->enable(DLG_LOAD, _superprassi);
_mask->enable(DLG_DUMP);
_mask->show(F_TAB, logicnum >= LF_TABGEN && logicnum <= LF_TAB);
_mask->set (FLD_NUM, riga.get(0));
_mask->set (FLD_NOME, riga.get());
_mask->set (FLD_EOD, riga.get());
_mask->set (FLD_EOX, riga.get());
_mask->set (F_LEN, riga.get());
_mask->set (FLD_DESC, riga.get());
_mask->set (FLD_FORMULA, riga.get());
_mask->set (FLD_FLAG, riga.get());
_mask->reset (FLD_EXTEND);
_mask->reset (F_TAB);
const TRecnotype oldeox = _mask->get_long(FLD_EOX);
const bool com = prefix().is_com() || !*prefix().name();
const char* name = _mask->get(FLD_NOME);
const bool enable_extend = (com ? *name != '$' : *name == '$') &&
(riga_sel > 0) &&
(_mask->get_int(F_LEN) > 0 || oldeox > 0);
_mask->show(FLD_EXTEND, enable_extend);
_mask->show(FLD_EOX, enable_extend);
tasto = _mask->run();
switch (tasto)
{
case K_F4:
if (logicnum > 1)
{
const TFilename filename(_mask->get(FLD_NOME));
const TString& tabella = _mask->get(F_TAB);
TEdit_file ef;
ef.browse_file(logicnum, filename, tabella);
}
break;
case K_F5:
case K_F6:
case K_F8:
if (!_superprassi)
{
error_box(FR("Funzione non ammessa per l'utente %s"), (const char*)user());
break;
}
case K_F7:
case K_ENTER:
{
strcpy (dep.SysName,_mask->get(FLD_NOME));
dep.EOD = atol(_mask->get (FLD_EOD));
dep.Flags = atol(_mask->get (FLD_FLAG));
strcpy (dep.Des,_mask->get (FLD_DESC));
strcpy (dep.FCalc,_mask->get (FLD_FORMULA));
const TRecnotype eox = _mask->get_bool(FLD_EXTEND) ? _mask->get_long(FLD_EOX) : oldeox;
TDir& dir = _browse->dir();
dir.get(logicnum, _lock, _nordir, _sysdirop);
dir.set(dep.SysName, dep.EOD, dep.Flags, dep.Des, dep.FCalc);
dir.put(logicnum, _nordir, _sysdirop);
{
TSystemisamfile f(logicnum);
if (eox != oldeox)
{
d.get(logicnum);
TFilename f_name(d.name());
f_name.ext("dbf");
if (!f_name.exist())
f.build(eox);
_browse->dir().get(logicnum, _nolock, _nordir, _sysdirop);
}
if (tasto == K_F5 && logicnum >= LF_USER)
{
f.packfile();
f.packindex();
// le 4 righe seguenti servono per allineare i valori di EOD ed EOX dopo una compattazione forzata
dir.get(logicnum, _lock, _nordir, _sysdirop);
dir.set(dep.SysName, dep.EOD, dep.Flags, dep.Des, dep.FCalc);
dir.set_eox(_browse->dir().eod());
dir.put(logicnum, _nordir, _sysdirop);
}
else
if (tasto == K_F6)
{
_rec = new TRec_sheet(logicnum, _mask->get(F_TAB));
_rec->edit();
delete _rec;
_rec = NULL;
}
else
if (tasto == K_F7)
{
TMask m("ba1100b");
TFilename nout(dumpfilename(dep));
m.set(FLD_OUTFILE, nout);
if (m.run() == K_ENTER)
{
nout = m.get(FLD_OUTFILE);
if (nout.not_empty())
{
const char fs = *esc(m.get(FLD_FS));
const char fd = *esc(m.get(FLD_FD));
const char rs = *esc(m.get(FLD_RS));
const bool withdel = m.get_bool(FLD_WITHDEL);
const int keyno = m.get_int(FLD_KEYNO);
const TString4 tabella(_mask->get(F_TAB));
if (tabella.not_empty())
{
TToken_string filter;
filter.add("COD"); filter.add(tabella);
f.dump(nout, keyno, fs, fd, rs, true, withdel, filter);
}
else
f.dump(nout, keyno, fs, fd, rs, true, withdel);
}
}
}
else
if (tasto == K_F8)
{
TMask m("ba1100c");
TFilename ninp(dumpfilename(dep));
m.set(FLD_INFILE, ninp);
if (m.run() == K_ENTER)
{
const char fs = *esc(m.get(FLD_FS));
const char fd = *esc(m.get(FLD_FD));
const char rs = *esc(m.get(FLD_RS));
const bool indexed = !m.get_bool(FLD_WITHKEY);
ninp = m.get(FLD_INFILE);
f.load(ninp, fs, fd, rs, true, false, indexed);
}
}
}
}
break;
default:
break;
}
}
void TManutenzione_app::delete_riga (long riga_sel)
{
const int logicnum = int(riga_sel) + 1;
const int num_files = (int)_browse->items();
TTrec r;
/* shift di uno in avanti degli elementi del direttorio partendo dall'ultimo */
for (int i = logicnum + 1; i <= num_files; i++)
{
_browse->dir().get (i, _nolock, _nordir, _sysdirop);
_browse->dir().put (i - 1, _nordir, _sysdirop);
_browse->rec().get (i);
_browse->rec().put (i - 1);
}
_browse->dir().get(LF_DIR);
r.zero();
r.put(_browse->dir().eod());
_browse->dir().set_eod(_browse->dir().eod()-1);
_browse->set_items(_browse->dir().eod());
_browse->dir().put(LF_DIR);
_browse->force_update();
}
bool TManutenzione_app::recover(TSystemisamfile& f, int err)
{
if (err == -60 || err == -64 || err == _ispatherr || (err > -600 && err <= -300))
{
err = f.packindex(false, false);
}
return err == NOERR;
}
void TManutenzione_app::repair_file(int i)
{
TString s(_MAX_PATH + 50); // Messaggio di log
TDir d(i);
const char* n = d.filename();
if (d.eod() == 0)
{
save_file(n);
TToken_string names; get_table_names(i, names, 0xF);
FOR_EACH_TOKEN(names, name)
xvt_fsys_remove_file(name);
s.format(FR("File n. %d - %s : eliminato file errato"), i, n);
write_log(s, 2);
}
else
{
d.get(i, _lock, _nordir, _sysdirop);
save_file(n);
TExternisamfile ef(n);
const RecDes& rd = ef.curr().rec_des();
TTrec rec; rec.get(i);
const int oldreclen = rec.len();
rec.rec() = rd;
rec.put(i);
const int reclen = rec.len();
d.set_len(reclen);
d.put(i, _nordir, _sysdirop);
s.format(FR("File n. %d - %s : corretto tracciato da %d a %d bytes"), i, n, oldreclen, reclen);
write_log(s, 1);
}
}
bool TManutenzione_app::moveable_file(int file) const
{
return file == LF_PCON || file == LF_CLIFO || file == LF_CAUSALI ||
file == LF_RCAUSALI || file == LF_CFVEN || file == LF_INDSP;
}
void TManutenzione_app::update_dir()
{
// Particolare significato dei flags oltre i 10000:
// trattasi di files PRASSI, (ad esempio i cespiti) che da noi non vengono toccati,
// in modo da evitare colpe inutili. Noi aggiorniamo solo i tracciati su dir e trc,
// ma il file fisico manco lo tocchiamo!!
if (prefix().get_codditta() <= _history_firm)
return;
const TString pref(prefix().name());
const bool is_com = prefix().is_com();
const int last_new_item = _dirs.last(); //quale <20> il numero dell'ultimo file nuovo?
TDir d(LF_DIR); // equivale a d.get(LF_DIR, _nolock, _nordir, _sysdirop);
const int last_curr_item = (int)d.eod(); //quale <20> il numero dell'ultimo file attualmente presente
const int update_items = (last_new_item < last_curr_item) ? last_new_item : last_curr_item;
safely_close_closeable_isamfiles(); // Serve a premettere la chiamata ad fsize() in sicurezza
TString prompt(128);
if (is_com)
prompt << TR("Aggiornamento dati comuni");
else
prompt << TR("Aggiornamento ditta") << ' ' << atol(pref) << '.';
TProgind p(update_items ? update_items : 1, prompt, false, true);
int i;
for (i = LF_USER; i <= update_items; i++)
{
if (!p.setstatus(i))
break;
const TDir & ds = (const TDir &) _dirs[i];
const bool is_firm = ds.is_firm();
const bool to_create = (is_com ? ds.is_com() : ds.is_firm());
TFilename fd(ds.filename());
bool towrite = false;
const long flags = ds.flags();
d.get(i, _nolock, _nordir, _sysdirop);
const bool old_is_firm = d.is_firm();
TFilename fs = d.filename();
/* Roba incomprensibile e quindi inutile
d.get(i);
if (strrchr(d.name(),'.') != NULL) // No extension please!
{
d.get(i, _nolock, _nordir, _sysdirop);
TFilename ext(d.name());
ext.ext("");
d.set_name(ext);
d.put(i, _nordir, _sysdirop);
}
*/
if (!fs.exist())
{
if (d.eox() > 0L)
{
d.get(i, _nolock, _nordir, _sysdirop);
d.set_eod(0);
d.set_eox(0);
d.put(i, _nordir, _sysdirop);
}
}
else
{
if (is_com)
{
if (old_is_firm && !moveable_file(i) && d.eod() == 0L)
{
const char* n = d.filename();
save_file(n);
TToken_string names; get_table_names(i, names, 0xF);
FOR_EACH_TOKEN(names, name)
xvt_fsys_remove_file(name);
TString msg(_MAX_PATH);
msg.format(FR("File n. %d - %s : eliminato file non utilizzato"), i, (const char *)d.filename());
write_log(msg, 1);
}
}
if (i > LF_USER && is_firm == old_is_firm)
{
const long size = fsize(fs);
if (flags < 10000L && size > 0L && d.len() > 0)
{
TSystemisamfile b(i);
int err = b.is_valid(true);
if ((err == _istrcerr || err == _ispatherr) && (d.eod() == 0) && (size < 4096))
{
bool kill = true;
//controllo solo all'aga
if (is_power_station())
kill = yesno_box(FR("Il tracciato record del file %d e' incoerente:\nSi desidera eliminare il file vuoto %s?"), i, (const char*)fs);
if (kill)
{
TToken_string names; get_table_names(i, names, 0xF);
FOR_EACH_TOKEN(names, name)
xvt_fsys_remove_file(name);
err = NOERR;
// se si decide di eliminare il file con tracciato del cazzo deve tenerne traccia nel log (nel caso di utonti..
//..<2E> sempre cos<6F>, perch<63> kill <20> sempre true)
TString msg;
msg.format(TR("Eliminato il file %d avente tracciato record incoerente"), i);
write_log(msg, 2);
}
} //if((err==_istrcerr...
if (err != NOERR && flags < 10000L)
{
if (err == _istrcerr || err == _isbadtrc)
{
repair_file(i);
err = NOERR;
}
if (err != NOERR && flags < 10000L)
{
if (!recover(b, err))
{
TString msg(_MAX_PATH);
msg.format(TR("Impossibile compattare il file %d - %s : errore n.ro %d"), i, (const char *)d.filename(), err);
write_log(msg, 2);
}
}
} //if(err!=NOERR && flags<10000L..
}
else
{
if (flags < 10000L && to_create)
{
TToken_string names;
get_table_names(i, names, 0xF);
FOR_EACH_TOKEN(names, name)
xvt_fsys_remove_file(name);
d.get(i, _nolock, _nordir, _sysdirop);
d.reset_eox();
d.put(i, _nordir, _sysdirop);
}
}
}
}
d.get(i, _nolock, _nordir, _sysdirop);
bool cmn_file = false;
bool valid_file = moveable_file(i);
if (!is_com && valid_file && d.is_com())
cmn_file = true; // Salta in questo caso:
// sto aggiornando le ditte,
// il file in questione e' uno di quelli che possono essere comuni
// il file e' in comune
// Serve per evitare che durante l'aggiornamento i file
// PCON, CLIFO, CAUS ed RCAUS vengano spostati da COM alla
// prima ditta
if (to_create && !cmn_file)
{
if (flags < 10000L && flags > -1L && fs.exist() && (fd != fs))
{
bool ok = true;
TFilename path(fd.path());
bool found = false;
for (int j = i + 1; !found && j <= update_items; j++)
{
const TDir & dn = (const TDir &) _dirs[j];
TFilename fn(dn.filename());
if (fs == fn)
{
TTrec wrs(i), wrd(j);
wrd = wrs; wrd.set_num(j); // Copia e rinumera
wrd.put(j);
wrs.zero();
wrs.put(i);
TDir wds(i), wdd(j);
wdd.set(wds.name(), wds.eod(), wds.flags(), wds.des(), wds.expr());
wdd.set_eox(wds.eox());
wdd.set_len(wrd.len());
wdd.put(j, _nordir, _sysdirop);
prefix().destroy_info(j);
wds.set(ds.name(), 0L, 0L, ds.des(), ds.expr());
wds.set_eox(0L);
wds.set_len(0);
wds.put(i, _nordir, _sysdirop);
prefix().destroy_info(i);
found = true;
}
}
if (found)
continue;
path.rtrim(1);
if (path.full() && !path.exist())
ok = make_dir(path);
if (ok && fcopy(fs, fd))
{
TToken_string ts(10),td(10);
td.cut(0);
get_table_names(i,ts,0x2); // Get index names of current file in current dir
for (int j=1; j<= ts.items() && ok; j++)
{
const TFilename fsi(ts.get());
TFilename fdi(fd); // Nuovo nome. (Con l'estensione)
fdi.ext("");
if (j > 1) // Means that more indexes are in TToken_string ts
{
const TFixed_string xx(fdi.name());
if (xx.len() < 8)
fdi << ('0' + j);
else
fdi[8] = ('0' + j);
}
fdi.ext(fsi.ext());
td.add(fdi);
if (!fcopy(fsi, fdi))
ok = false;
}
if (ok)
{
remove(fs); // Rimuove i files sorgenti. Crea un eventuale .cgp
fd.ext("cgp");
FILE *o=NULL;
if (ts.items() > 1)
{
fs.ext("cgp");
remove(fs);
o=fopen(fd,"w");
}
ts.restart();
td.restart();
for (int j=1; j<=ts.items(); j++)
{
remove(ts.get());
if (ts.items() > 1) // Means that fd.cgp must be created
{
TFilename ff=td.get();
ff.ext("");
ff.rtrim(1);
fprintf(o,"%s\n",ff.name());
}
}
if (o!=NULL)
fclose(o);
}
else
{
remove(fd); // Remove all destinations written
td.restart();
for (int j=1; j<=td.items(); j++)
remove(td.get());
}
}
else
ok = false;
if (ok)
{
d.set(ds.name(), d.eox(), 0L, ds.des(), d.expr());
towrite = true;
}
}
if (!fexist(fs) && !valid_file) // Controlla eventali nomi di files non validi (ed es. %.dbf ecc.)
{
d.set(ds.name(), d.eox(), 0L, ds.des(), d.expr());
towrite = true;
}
}
else
{
towrite = TFixed_string(ds.des()) != d.des();
if (towrite)
{
if (!valid_file)
d.set(ds.name(), d.eox(), d.eod(), ds.des(), d.expr());
else
strcpy((char *) d.des(), ds.des());
}
}
if (is_com && valid_file && d.name()[0] == '$')
{
TString name(d.name());
name[0] = '%';
d.set_name(name);
towrite = true;
}
if (towrite)
d.put(i, _nordir, _sysdirop);
} //for(i=LF_USER; i<=update_items; i++)
//se il numero totale di files nuovi <20> inferiore a quello dei files gi<67> presenti c'<27> qualcosa che probabilmente..
//..non va (aggiornamento da un cd vecchio ad esempio); comunque ha finito il suo lavoro qui, perch<63> quello che..
//..segue riguarda solo i files nuovi
if (last_curr_item >= last_new_item)
return;
//aggiornatore degli EOX EOD ecc. dei files nuovi
for (i = last_curr_item + 1; i <= last_new_item; i++)
{
TDir d1((const TDir&)_dirs[i]);
d1.set_len(0);
d1.reset_eox();
d1.set_flags(0);
d1.put(i, _nordir, _sysdirop); //scrive su dir.gen il nuovo file aggiunto (mettendo numero,eox,eod,flags)
}
//allinea i valori di eox ed eod (eox non pu<70> mai essere < eod!)
d.get(LF_DIR, _nolock, _nordir, _sysdirop);
d.set_eod(last_new_item);
d.put(LF_DIR, _nordir, _sysdirop);
}
void TManutenzione_app::convert_dir()
{
if (prefix().get_codditta() <= _history_firm)
return;
const TString pref(prefix().name());
const bool is_com = prefix().is_com();
const int last_new_item = _dirs.last();
TDir d(LF_DIR);
const int last_curr_item = (int)d.eod();
const int update_items = (last_new_item < last_curr_item) ? last_new_item : last_curr_item;
TString s;
if (is_com)
s = TR("Aggiornamento archivi comuni.\n");
else
{
s = TR("Aggiornamento archivi della ditta ");
s << atol (pref) << ".\n";
}
TProgind p(update_items ? update_items : 1, s, is_power_station());
for (int i = LF_USER; i <= update_items; i++)
{
if (!p.addstatus(1))
break;
const TTrec& rs = (const TTrec&)_recs[i]; // Nuovo tracciato record
const TDir& ds = (const TDir&)_dirs[i];
const long flags = ds.flags();
if (ds.len() > 0)
{
if (flags >= 0L && flags < 10000L)
{
d.get(i, _nolock, _nordir, _sysdirop);
TString msg = s; msg << d.filename();
p.set_text(msg);
const int module = abs((int)ds.flags());
TSystemisamfile f(i);
int err = f.is_valid(true);
switch (err)
{
case -64:
case -60:
err = NOERR; // verif.
break;
default:
break;
}
if (i > LF_USER && err != NOERR && ((is_com && d.is_com()) || (!is_com && d.is_firm())))
{
if (err == _istrcerr || err == _isbadtrc)
{
repair_file(i);
err = NOERR;
}
if (err != NOERR)
{
//si decide di proseguire anche se il file non pu<70> essere aperto ne tiene traccia nel log (nel caso di utonti..
//..<2E> sempre cos<6F>, perch<63> go_on <20> sempre true)
msg.format(TR("Il file %d non pu<70> essere aperto. Errore %d"), i, err);
write_log(msg, 2);
continue;
}
} //if (i > 2 && err != NOERR &&...
bool to_create = (is_com ? d.is_com() : d.is_firm());
// I files LF_PCON, LF_CAUS, LF_RCAUS, LF_CLIFO, LF_CFVEN, LF_INDSPED
// vanno creati comunque nel direttorio COM, vuoti, (se non esistono gia').
if (is_com && !to_create && moveable_file(i))
to_create = true;
if (to_create && has_module(module, CHK_DONGLE))
{
const TDir df(i);
const TFilename fname(df.filename());
//crea il nuovo file in base al tracciato record nuovo!
if (!fname.exist() && ds.len() > 0)
{
set_autoload_new_files(false);
f.build(0L,rs);
set_autoload_new_files(true);
// Anche se il file non esisteva, prosegue, perche' possono esserci conversioni
// specificate in FCONV.INI
}
}
f.update(rs, false);
if (f.status() == 8) // cio' significa che e' accaduto quasi l'irreparabile...
{
{
TLocalisamfile u(LF_USER);
u.zero(); u.put(USR_USERNAME, ::dongle().administrator());
if (u.read() == NOERR)
{
u.zero(USR_AUTSTR);
u.rewrite();
}
}
stop_run();
} //if(f.status()...
} //if (flags >= 0L && < 10000L...
else // altrimenti se i flags sono oltre i fatidici 10000...
{
TTrec r(rs);
d.get(i, _nolock, _nordir, _sysdirop);
d.set_len(r.len());
d.put(i, _nordir, _sysdirop);
r.put(i);
} //else di if(flags>=...
} //if (ds.len() > 0... (la dimensione del tracciato e' > 0)
else // altrimenti se la dimensione del tracciato e' zero...
{
TTrec r(rs);
r.zero();
d.get(i, _nolock, _nordir, _sysdirop);
d.set_len(r.len());
d.put(i, _nordir, _sysdirop);
r.put(i);
} //else di if(ds.len()>0...
} //for (int i = 2; i <= update_items...
d.get(LF_DIR, _nolock, _nordir, _sysdirop);
d.set_flags(_level);
d.put(LF_DIR, _nordir, _sysdirop);
put_history(pref);
}
void TManutenzione_app::load_des()
{
TWait_cursor waiter;
const TString pref(prefix().name());
_dirs.destroy();
_recs.destroy();
_level = prefix().filelevel();
TDir d(LF_DIR);
int items = (int)d.eod();
long flags = d.flags();
const bool standard = pref.empty();
if (standard) // carica eventuali nuove descrizioni ed il nuovo livello archivi
{
// Cerca in RECDESC i files f[nnn].dir
TString ws;
TFilename fn;
TDir td,new_dir;
TTrec tr;
int ln = items,last_newln = items;
tr.zero();
fn << DESCDIR << "/level.dir";
if (fexist(fn))
{
ifstream infile(fn);
long fl;
infile >> fl;
if (fl > flags) flags = fl;
}
// scandisce *.dir in RECDESC
// eventuali "buchi" oltre al numero attuale di items vengono rimpiazzati
// con tracciati vuoti.
fn.format("%s/f*.dir",DESCDIR);
TString_array list;
const int totfiles = list_files(fn, list);
for (int n = 0; n < totfiles; n++)
{
fn = list.row(n);
if (fn.exist())
{
ifstream infile(fn);
infile >> td;
}
ln = td.num();
const bool is_new = ln > last_newln; // memorizza l'ultimo record scritto come nuovo
if (is_new) // aggiunge i files che mancano
{
for (int i = last_newln+1; i<ln; i++)
{
ws.format("$f%d",i);
new_dir.set(ws,0L,-1L, TR("File non presente"),"");
new_dir.put(i,_nordir,_sysdirop);
tr.put(i);
}
last_newln = ln;
}
td.put(ln,_nordir,_sysdirop);
if (is_new)
tr.put(ln);
}
d.set_eod(last_newln);
d.set_eox(last_newln);
d.set_flags(_level = flags);
prefix().set_stdlevel(flags);
d.put(LF_DIR,_nordir,_sysdirop);
}
items = (int) d.eod();
TString80 s;
if (standard)
s = TR("Caricamento descrizioni archivi standard");
else
{
if (prefix().is_com()) s << TR("Caricamento descrizioni archivi comuni");
else s << TR("Caricamento descrizioni archivi della ditta ") << atol (pref);
}
TProgind p(items ? items : 1, s, false, true);
p.setstatus(1);
for (int i = LF_USER; i <= items; i++)
{
p.addstatus(1);
d.get(i, _nolock, _nordir, _sysdirop);
TTrec r(i);
if (standard)
{
TFilename desc_file;
desc_file << DESCDIR << "/f" << i;
desc_file.ext("trr");
if (fexist(desc_file))
{
{
ifstream in(desc_file);
TFilename descfname;
descfname.format("%s/d%d.des", DESCDIR, i);
if (!fexist(descfname))
{
FILE* fd = fopen(descfname, "w");
if (fd != NULL)
fclose(fd);
}
TConfig descr(descfname, DESCPAR);
r.set_des(&descr);
in >> r;
r.put(i);
d.set_len(r.len());
d.put(i, _nordir, _sysdirop);
r.set_des();
}
}
}
_dirs.add(d, i);
_recs.add(r, i);
}
}
void TManutenzione_app::update()
{
TIsamfile utenti(LF_USER);
utenti.open(_excllock);
#ifndef DBG
bool ok = false;
while (!ok)
{
TToken_string utonti(64, ',');
for (int err = utenti.first(); err == NOERR; err = utenti.next())
{
const TString& u = utenti.get(USR_USERNAME);
if (u != ::dongle().administrator() && utenti.get_bool(USR_CONNECTED))
utonti.add(u);
}
ok = utonti.empty();
if (!ok)
{
TToken_string message(80, '\n');
message = TR("Conversione archivi impossibile mentre ci sono utenti collegati!");
message.add(TR("Qualora uno degli utenti elencati non fosse effettivamente connesso, "));
message.add(TR("effettuare una sua connessione e disconnessione immediata per sbloccarlo"));
message.add(utonti);
error_box(message);
break;
}
}
#else
bool ok = true;
#endif
// Scrive CONVERTING solo dopo aver testato che non ci sia nessuno connesso
if (ok)
{
utenti.zero();
utenti.put(USR_USERNAME, dongle().administrator());
ok = utenti.read() == NOERR;
if (ok)
{
utenti.put(USR_AUTSTR, "CONVERTING");
ok = utenti.rewrite() == NOERR;
}
}
utenti.close();
if (!ok)
return;
open_history();
long firm = get_firm();
TString pref;
if (firm == 0) pref = prefix().name();
do_events();
prefix().set("");
load_des();
prefix().set_codditta(0L);
open_log();
write_log(TR("Conversione Dati comuni"));
write_log("");
TPointer_array ditte; // Evita di aprire LF_NDITTE
const int nditte = prefix().firms(ditte);
TProgind p(nditte+1, TR("Conversione archivi ditte."), is_power_station());
p.addstatus(1);
update_dir();
convert_dir();
for (int i = 0; i < nditte; i++)
{
if (!p.addstatus(1))
break;
const long codditta = ditte.get_long(i);
TString mxs; mxs << TR("Conversione Ditta") << ' ' << codditta;
p.set_text(mxs);
if (codditta > _history_firm && prefix().exist(codditta) && set_firm(codditta))
{
write_log("");
write_log(mxs);
write_log("");
update_dir();
convert_dir();
}
}
//chiude il log di conversione
close_log();
if (firm > 0) set_firm(firm);
else prefix().set(pref);
load_des();
ok = false;
while (!ok)
{
utenti.open(_excllock);
ok = utenti.ok();
do_events();
}
// Azzera la scritta converting
utenti.put(USR_USERNAME, ::dongle().administrator());
if (utenti.read() == NOERR)
{
utenti.zero(USR_AUTSTR);
utenti.rewrite();
}
utenti.close();
close_history();
send_campo_xml(); // Spedisce situazione via ftp
}
void TManutenzione_app::main_loop()
{
TToken_string riga;
long riga_selezionata;
bool done = false;
_browse->rebuild();
while (!done)
{
disable_menu_item(M_FILE_NEW);
KEY key = _browse->run();
if (key != K_ENTER && key != K_QUIT && key != K_ESC &&
!_superprassi)
{
error_box(FR("Operazione non permessa all'utente %s"), (const char*)user());
key = 0;
}
// Si assicura di chiudere tutto prima di conversioni o altro
prefix().close_closeable_isamfiles();
switch (key)
{
case K_F1:
dispatch_e_menu(M_HELP_CONTENTS);
break;
case K_F2:
dispatch_e_menu(M_FILE_ABOUT);
break;
case K_F3:
dispatch_e_menu(M_FILE_PRINT);
break;
case K_F6:
riga_selezionata = _browse->selected();
riga = _browse->row();
insert_riga (riga_selezionata, riga);
break;
case K_ENTER:
riga_selezionata = _browse->selected();
riga = _browse->row();
edit_riga (riga_selezionata, riga);
break;
case K_DEL:
riga_selezionata = _browse->selected();
delete_riga(riga_selezionata);
break;
case K_QUIT:
case K_ESC:
done = true; close_history();
break;
case K_F7:
update();
break;
case K_F8:
_browse->add();
riga_selezionata = _browse->items() - 1;
riga = _browse->row(riga_selezionata);
edit_riga (riga_selezionata, riga);
break;
case K_F5: // Other file
{
TMask other("ba1100g");
other.set_handler(101, browse_file_handler);
if (other.run() == K_ENTER)
edit_riga(other.get(101));
}
break;
default:
break;
}
enable_menu_item(M_FILE_NEW);
}
}
int ba1100(int argc, char** argv)
{
TManutenzione_app a;
a.run(argc, argv, TR("Gestione files"));
return 0;
}