home *** CD-ROM | disk | FTP | other *** search
- /* Copyright 1988, Gail Zacharias. All rights reserved.
- * Permission is hereby granted to copy, reproduce, redistribute or
- * otherwise use this software provided there is no monetary profit
- * gained specifically from its use or reproduction, it is not sold
- * rented, traded or otherwise marketed, and this copyright notice
- * and the software version number is included prominently in any copy
- * made.
- * This was mtar version 1.0.
- *
- */
-
- /* the original mtar program was then altered to become part of suntar:
- */
-
- /*******************************************************************************\
-
- tar writing module
-
- part of suntar, ⌐1991-92 Sauro & Gabriele Speranza
-
- This program is public domain, feel free to use it or part of it for anything
-
- \*******************************************************************************/
-
-
- /*
- comments in the text explain which routines were added for suntar by us and
- which ones are from mtar, but most of the latter were modified more or less
- heavily by us
- */
-
- #include "system7.h"
- #include "PB_sync.h"
- #include "antiglue.h"
-
- #include <string.h>
- /*#include <FileMgr.h>
- #include <OSUtil.h>
- #include <HFS.h>*/
-
- #include "suntar.h"
-
- #include "windows.h"
-
-
- void fillmem(dest, ch, len)
- register char*dest;
- register char ch;
- register int len;
- {
- while (--len>=0) *dest++ = ch;
- }
-
-
- #define tarsz(n) (((n)+511L) & -512L)
- #define macbinsz(n) (((n)+127L) & -128L)
-
- static HFileInfo statb;
-
- static Boolean binary = false,
- dataonly = false;
-
- #define dirmode 0777
- #define filemode 0666
-
- char *uname,
- *gname;
-
- /* Unfortunately, the Mac keeps only local time, so this will be off by
- the time zone... */
- #define UNIXTIME 2082844800L /* Jan 1, 1970 00:00:00 */
-
- /*
- main (argc, argv)
- char **argv;
- {
- fprintf(stderr,
- "This is freeware. If you paid money for this program, you got ripped off.\n");
- }
- */
- /*********************** start of routines by Speranza **************************/
-
- /* dovrÿ riorganizzare un po' le cose: ha senso che, come in untar, ci siano due
- modi di chiamare le routine di output: uno per quelli che sanno che esistono i settori
- (scrittura header) e uno per quelli che preferiscono vedere un flusso continuo di bytes:
- ovviamente ci vuole una routine per riallinearsi al settore dopo una serie di
- chiamate del secondo gruppo, ma questa esiste giê, svuota_buffer
- -- Beware: the disk handling routines are organized with an external interface
- which looks like a continuous stream of bytes (they trasparently handle volume
- headers and disk swapping) but in several places the caller must know about
- the internal behaviour, about sector and disk numbers (e.g., it must know in
- which sector of which disk a file header was written). That makes things a
- little tricky, less comprehensible than the untar module where the low level
- routines are less clever
- */
-
- #define ALIAS_BIT 0x8000
-
- static sector_t last_header, /* il settore contenente l'ultimo header di file
- -- the sector containing the last file header */
- last_sector; /* il settore vuoto che sarê scritto alla prossima occasione;
- nota che in questo modulo Å gestito in modo un po' "sotterraneo":
- eccetto che per cose strane (header speciali, che non riguardano
- le normali routines) scrivi_settori viene sempre chiamata col
- tramite di write_next_sector (che si occupa di gestire un eventuale
- cambio disco: bisogna chiedergli comunque un settore a partire da 0,
- sa lei che a causa degli header di disco poi non Å detto si vada
- al 0, ed Å impossibile per bar), ma last_sector va incrementata
- subito dopo tale chiamata, col che appunto Å sempre il prossimo
- settore. Attenzione che write_block butta fuori quando ha il buffer
- pieno (cioÅ non lo lascia con 512 bytes, lo svuota subito)
- -- next sector to be written: after a call to write_next_sector
- which fills a sector, it was already incremented so it points
- to the next sector (or beyond the end of disk)
- */
- static short more_space; /* number of free bytes in buffer, that is 512 - number of
- bytes currently in the buffer */
- static int path_len=0; /* nell'archivio scrivo solo l'ultima parte del pathname
- completo che invece uso per aprire i files
- -- The full path name is used to open files, but the stored name
- in the archive is only the last part of it, the partial path
- from the folder which was selected by the user.
- */
- int inputFile;
- /*static IOParam pb;*/
- extern ParamBlockRec pb;
- /* Å diventata una variabile globale per poter chiudere il file in
- caso di errore; per la veritê non Å necessario, basta un singolo
- campo, il RefNum... */
- unsigned char previousFormat; /* solo per tar, quelli bar sono sempre multivolume
- -- for tar format only, bar archives are always allowed to become multivolume */
- Boolean inf_is_open=false;
- static Boolean write_in_corso=0; /* remembers that I was writing, hence what is in
- the disk is not correctly terminated by a null header */
- static Boolean devo_chiudere_in=false;
-
- static Boolean questo_e_un_header; /* set just before writing an header sector */
- extern int floppy_n;
- extern unsigned char mac_file_name[];
- extern int openfile_vrefnum;
- extern long openfile_dirID;
-
- static char bar_date[12];
- long my_uid,my_gid;
-
- void chiedi_altro_disco(void);
- void set_bar_date(void);
- Boolean surely_not_mac(char*);
- void alias_error(short);
-
-
- static void chiedi_altro_disco() /* ask for another disk */
- {
- int i;
- diskEject();
-
- for(;;){
- i=aspetta_inserzione(in_Italia?"\pInserisci un altro disco su cui scrivere":
- "\pInsert another disk to be written");
- if(i!=0) raise_error(); /* un annulla...
- -- the user clicked the Cancel button
- */
- if(is_wrprot()){
- printf_protetto();
- }
- else if(di.is_not_initialized)
- disk_format(false);
- else{
- warning_400_800();
- return;
- }
- }
- }
-
-
- void reset_sector_count()
- {
- /* viene chiamata quando si dê un comando di create o append, quindi Å il posto
- buono per inserire qualunque inizializzazione
- -- called for the Create and Append commands, it's the right place for initializing
- some variables
- */
- last_header=last_sector=0;
- previousFormat= tar_unknown;
- floppy_n=0;
- set_bar_date(); /* deve essere comune per tutto l'archivio
- -- the same value must be used for all volumes in the archive */
- }
-
- void write_next_sector(void);
- static void write_next_sector()
- {
-
- if(last_sector>=sectors_on_floppy){
- if(!bar_archive && previousFormat<=tar_singlevol&&tar_version<=tar_singlevol){
- start_of_line();
- printf("Disk full, write aborted !\n"); /* non dovrebbe capitare mai, */
- tronca_archivio(); /* visto che controllo prima, ma nel caso...
- -- that should never happen, that's checked at every header,
- but if that check should contain a bug, don't crash
- */
- raise_error();
- }
- last_sector=0; /* deve essere =0 perchÄ scrivo sempre tutti
- i settori (non per niente questa routine si chiama cosô...) */
- chiedi_altro_disco();
- }
- if(last_sector==0){
- floppy_n++;
- warning_first_write(0);
- if(bar_archive){
- write_bar_volume_header();
- }
- else{
- if(floppy_n!=1 && !questo_e_un_header &&
- (previousFormat==tar_GNU || tar_version==tar_GNU&&previousFormat!=tar_AIX) ){
- /* scrivi un header di continuazione file
- -- write a 'M' header for a file splitted between disks */
- write_tar_volume_header();
- }
- }
- }
- scrivi_settore(last_sector,disk_buffer);
- check_wr_err();
- questo_e_un_header=false;
- settori_passati++;
- }
-
- void warning_400_800()
- {
- if( (sectors_on_floppy==800 || sectors_on_floppy==1600) && !accetta_GCR){
- unsigned char b[2];
- b[0]=1;
- b[1]= sectors_on_floppy==800 ? '4' : '8';
- if(in_Italia )
- ParamText("\pUn disco da ",b,"\p00K non puÿ essere\rletto su un sistema UNIX",PNS);
- else
- ParamText("\pA ",b,"\p00K disk can\'t be read\ron an UNIX machine",PNS);
- my_alert();
- }
- }
-
-
- void printf_protetto()
- {
- start_of_line();
- printf(in_Italia?"Disco protetto da scrittura !\n":"Write protected disk !\n");
- diskEject();
- }
-
- static Boolean surely_not_mac(buffer)
- char buffer[512];
- {
- if(di.disk_code!=noErr) return true;
- leggi_settore(2,buffer);
- return err_code!=0;
- }
-
- short warning_first_write(n)
- /* n=0 if called by a command in the write menu (don't return without a writable disk),
- 1 for initialize */
- {
- /* called before the first write to a disk which is still containing
- what it was containing when it was inserted: it's the last chance to
- avoid a data loss
- returns:
- -1: (only if n=1) the user canceled the operation but the disk wasn't ejected yet
- 0: the user approved the operation
- 1: it's not a Mac disk (no dialog)
- 2: it's an empty Mac disk (no dialog)
- */
-
- static char *loc_titoli[]={"\pEspelli","\pOk"};
- char buffer[512];
-
- for(;;){
- Boolean guarda_files;
-
- while(surely_not_mac(buffer)){
- short inPlace;
- testa_stato(&inPlace,0);
- if(!n&&di.is_not_initialized){
- disk_format(false);
- if(drive_number){
- if(testa_stato(&inPlace,1) || !inPlace)
- diskEject();
- else if(is_wrprot())
- printf_protetto();
- else
- return 1;
- }
- chiedi_altro_disco();
- }
- else
- return 1;
- }
- /*printf("n files=%d\n",*(int*)&buffer[12]);
- printf("n dirs=%d\n",*(int*)&buffer[82]);
- printf("n files tot=%ld\n",*(long*)&buffer[84]);
- printf("n dirs tot=%ld\n",*(long*)&buffer[88]);
- */
- /* if it's a Macintosh disk (same test used by is_mac_disk in suntar.c) see if
- it contains more than one file (the first one is the desktop) or more than zero folders
- */
-
- if( (*(int*) buffer== 0xD2D7 || *(int*) buffer== 0x4244) ){ /* MFS o HFS */
- guarda_files=true;
- if( *(int*) buffer== 0x4244 && ((*(int*)&buffer[10])&0x200)){
- /* see TN 287: System 7 sets that flag if one or more bad sectors were
- found and marked as unusable */
- ParamText(in_Italia?"\pQuesto disco contiene dei settori marcati difettosi":
- "\pIn this disk some sectors are marked bad",PNS,PNS,PNS);
- if( my_modal_dialog(133,loc_titoli,2) ==1){
- if(n) return -1;
- guarda_files=false;
- }
- }
- if(guarda_files){
- if(*(unsigned char*)&buffer[36]<=27 && /* length of volume name */
- (*(int*)&buffer[12]>1 || /* files in root directory, e il primo Å il Desktop */
- (*(int*) buffer== 0x4244 &&*(int*)&buffer[82]>0)) ){ /* folders in root directory */
- ParamText(in_Italia?
- "\pQuesto disco contiene files in formato Macintosh, verranno sovrascritti":
- "\pThis disk contains some Macintosh files, their data will be overwritten",
- PNS,PNS,PNS);
- if( my_modal_dialog(133,loc_titoli,2) ==2){
- if(!n)de_Mac_ize(buffer);
- return 0;
- }
- if(n) return -1;
- }
- else{
- if(!n) de_Mac_ize(buffer);
- return 2;
- }
- }
- chiedi_altro_disco();
- }
- else
- return 1;
- }
- }
-
- void de_Mac_ize(buffer)
- char buffer[512];
- /* the Finder keeps a copy of sector 2 in the sector before the last one, and
- PBMountVol (called by GetNextEvent) when sees a disk with an invalid sector 2
- (what happens for any tar disk with more than 1024 bytes of data on it)
- but a valid sector 2878 (or 1598 or whatever) tells it's a Mac disk. (At first,
- we believed that the cause were tags, but a technical note explained that tags
- are no more required by the file system, hence they do not exist in drive where
- the hardware doesn't provide them, and the MFM format doesn't have tags).
- So it's better to deMac-ize disks when creating an archive. I prefer NOT to do
- that when sector 2 was overwritten by the UNIX tar, which obviously does not know
- about the Mac and the Finder, in that case in order to de-Macize I should write
- to the disk even if the user asked only to read, not a good thing
- */
- {
- leggi_settore(sectors_on_floppy-2,buffer);
- if(err_code) return;
- if(*(int*) buffer== 0xD2D7 || *(int*) buffer== 0x4244 )
- buffer[0]++; /* it's better to preserve everything, only change the
- code */
- write_sectors(sectors_on_floppy-2,buffer,1); /* non-buffered write */
- di.disk_code=noMacDskErr;
- }
-
- void write_tar_volume_header()
- /* writes the 'M' continuation header on GNU tar volumes following the first one */
-
- {
- tarh_type buffer;
- long old_size,delta_size;
- int i;
-
- /* get the needed data, which were saved when writing the last normal header */
- mcopy(&buffer,ultimo_header,sizeof(ultimo_header));
- fillmem(&buffer.name[sizeof(ultimo_header)],0,512-sizeof(ultimo_header));
- old_size=untar_number(buffer.size,-1);
- fillmem(buffer.size, '\0', 12);
-
- delta_size = (long)avail_sectors_for_file<<9;
- last_offset += delta_size;
-
- if(old_size<=delta_size) return; /* il file terminava proprio
- nell'ultimo settore del disco precedente
- -- the file happened to end in the last sector of the previous disk,
- hence this disk must not contain an 'M' continuation header
- */
-
- numstr(&buffer.size, old_size-delta_size, 12);
- numstr(&buffer.offset, last_offset, 12);
- buffer.linkflag = 'M';
- fill_checksum(&buffer);
-
- /* update the saved informations */
- copia_ultimo_header(&buffer,(sector_t)1);
-
- /* last_offset l'ho giê calcolato */
- ultimo_disco_espulso=true; /* forse... bisogna vedere come ritrovo l'header da
- azzerare in tronca_archivio !!!
- -- unused variable, but in the future it should serve to help clearing
- the last_header in case of error
- */
-
- scrivi_settore(0,&buffer);
- check_wr_err();
- last_sector=1;
- }
-
- static void set_bar_date()
- /* read the current date an time and store it in the format of the date field
- for bar archives */
- {
- DateTimeRec cdate;
- register char*p = bar_date;
- register int i;
-
- GetTime (&cdate);
- cdate.year %= 100; /* solo le ultime due cifre dell'anno... */
- for(i=0;i<5;i++){
- *p++ = '0'+ ((int*)&cdate.year)[i] /10;
- *p++ = '0'+ ((int*)&cdate.year)[i] %10;
- }
- *p='\0';
- }
-
- void write_bar_volume_header()
- {
- /* when there were doubts about what should be written (see untar.c)
- I preferred to write clean information rather than to follow the
- silly rules of the original bar: there seems to be no compatibility
- problem, since bar ignores the contents of the fields which it
- writes in a silly way
- */
- barh_type buffer;
- register long oldsize;
- int i;
-
- fillmem(&buffer,0,512);
- my_itoa(my_uid,&buffer.uid);
- my_itoa(my_gid,&buffer.gid);
- buffer.bar_magic[0]='V';
- buffer.bar_magic[1]='\0';
- my_itoa((long)floppy_n,&buffer.volume_num);
- buffer.compressed='0';
- mcopy(&buffer.cdate,bar_date,12);
-
- if(floppy_n==1)
- oldsize = 0L;
- else{
- oldsize = untar_number(((barh_type*)ultimo_header)->size,-1);
- oldsize = (oldsize+511)>>9; /* numero di settori necessari */
- oldsize -= avail_sectors_for_file; /* meno quelli giê usati
- -- size = number of needed sectors at the time of the last header
- minus number of available sectors on previous disk
- */
- avail_sectors_for_file += sectors_on_floppy-1;
- }
-
- numstr(buffer.size, oldsize<<9, 12);
- bar_checksum(&buffer);
-
- scrivi_settore(0,&buffer);
- check_wr_err();
- last_sector=1;
- }
-
- short bar_header(fname, fsize, barh)
- char *fname;
- long fsize;
- register barh_type *barh;
- {
- fillmem(barh, 0, 512);
- mac_to_unix(barh->name, fname+path_len);
- if(!strcmp("./",barh->name) || !barh->name[0] ) return -1; /* succede nel system 7.0 se
- come folder da salvare seleziono un volume
- -- I get that string in System 7, a whole volume such as "HD40"
- becomes "./", but it's better not to save any entry for "HD40" !
- */
-
- if (statb.ioFlAttrib & ioDirMask)
- if (barh->name[strlen(barh->name)-1] != '/')
- barh->name[strlen(barh->name)] = '/';
- numstr(barh->mode, (long)((statb.ioFlAttrib & ioDirMask) ? dirmode : filemode), 8);
- numstr(barh->uid, my_uid, 8);
- numstr(barh->gid, my_gid, 8);
- numstr(barh->size, fsize, 12);
- numstr(barh->mtime, (long) statb.ioFlMdDat - UNIXTIME, 12);
- barh->linkflag = ((statb.ioFlAttrib & ioDirMask) ? '\0' : '0'); /* it's not clear
- what I should write here, see the discussion un untar.c */
- bar_checksum(barh);
- questo_e_un_header=true;
- writeblock(barh, 512);
- last_header=last_sector-1; /* ho bisogno di last_sector NON ancora incrementato
- al settore successivo, ma incrementato degli eventuali header extra !
- -- last_sector was already incremented, and I can't get the value before
- calling write_block since it may add a volume header */
- copia_ultimo_header(barh,last_sector); /* last_sector incrementato */
- return 0;
- }
-
- void bar_checksum(buf)
- char *buf;
- {
- register int i;
- register long chk= ' '*8;
- for(i=0;i<48;++i)
- chk += (unsigned char) buf[i];
- for (i+=8; i < 512; ++i)
- chk += (unsigned char) buf[i];
- numstr(((barh_type*)buf)->chksum,chk,8);
- }
-
- void writeblock(p,len)
- register char*p;
- int len;
- {
- if(len>=more_space){
- mcopy(&disk_buffer[512-more_space],p,more_space);
- p+=more_space;
- len-=more_space;
- write_next_sector();
- last_sector++;
- more_space=512;
- check_events();
- if(!len) return;
- }
- mcopy(&disk_buffer[512-more_space],p,len);
- more_space-=len;
- }
-
- unsigned char get_linkflag(length)
- long *length;
- {
- unsigned char linkflag;
- *length=untar_number( bar_archive ? ((barh_type*)disk_buffer)->size :
- ((tarh_type*)disk_buffer)->size,true);
- if(bar_archive){
- linkflag=guess_bar_linkflag();
- if(linkflag=='1'||linkflag=='5') *length=0;
- }
- else{
- /* for directories, the size field may be used to store some informations,
- hence I can't rely on it being 0 */
- linkflag=((tarh_type*)disk_buffer)->linkflag;
- if(linkflag=='5' || ((tarh_type*)disk_buffer)->name[
- strlen(((tarh_type*)disk_buffer)->name)-1] == '/'){
- linkflag='5';
- *length=0;
- }
- }
- return linkflag;
- }
-
-
- void cerca_fine() /* find the end of the archive: used for Append */
- {
- long length;
- enum formats fmt;
- Boolean message_given=false;
-
- previousFormat=tar_unknown;
- listonly=1; /* don't use buffering */
- fmt=identify_format();
- if(fmt==tar_format){
- bar_archive=false;
- if( hasVheader || ((tarh_type*)disk_buffer)->linkflag=='M' ) {
- previousFormat=tar_GNU; /* se Å giê
- multivolume, vuol dire che il GNU tar Å disponibile...
- -- if it's already GNU multivolume, later I must not bother the
- user asking if I may create a multivolume archive, and I must
- use the GNU format even if the current setting of tar_version
- is AIX */
- if(hasVheader) last_header=1;
- }
- floppy_n=1;
- }
- else if(fmt==bar_format){
- bar_archive=true;
- floppy_n=untar_number( ((barh_type*)disk_buffer)->volume_num,true);
- mcopy(bar_date,((barh_type*)disk_buffer)->cdate,12);
- last_header= (untar_number( ((barh_type*)disk_buffer)->size,true)+1023)>>9;
- }
- else
- raise_error();
-
- for(;;){
- static char sita[]=" (dovresti assegnare l\'opzione \"tar version\")\n",
- sing[]=" (you should set the \"tar version\" option)\n",
- snew[]="\n";
- register unsigned char linkflag;
- while(last_header>=sectors_on_floppy){
- if(fmt==bar_format||previousFormat==tar_GNU||previousFormat!=tar_AIX&&tar_version==tar_GNU){
- Boolean opt_ok= fmt==bar_format||tar_version==tar_GNU;
- if(in_Italia)
- printf("La fine dell\'archivio non Å in questo disco%s",opt_ok||message_given ? snew : sita);
- else
- printf("The end of archive is not in this disk%s\n",opt_ok||message_given ? snew : sing);
- message_given=true;
- raise_error();
- }
- else{ /* potrebbe essere AIX...
- -- it could be AIX, but maybe the user has not set the option
- and in that case suntar suggests him to do that */
- int i;
- Boolean was_AIX;
- last_header-=sectors_on_floppy;
- do{
- diskEject();
- i=aspetta_inserzione(in_Italia?
- "\pInserisci il prossimo disco tar":"\pInsert next tar disk");
- if(i) raise_error();
- }
- while(di.is_not_initialized);
- was_AIX=previousFormat==tar_AIX;
- i = tar_check_settore0(false);
- if(i==-1){ /* bad header, but it's the normal case for AIX disks
- following the first one */
- if(previousFormat<=tar_singlevol&&tar_version!=tar_AIX){
- start_of_line();
- if(in_Italia)
- printf("Probabile formato AIX%s",message_given?snew:sita);
- else
- printf("Probable AIX format%s",message_given?snew:sing);
- message_given=true;
- }
- previousFormat=tar_AIX;
- }
- else if(previousFormat==tar_GNU){ /* it was not so when entering in
- this while, but check_settore_0 may assign it */
- if(was_AIX) error_message("Not a AIX tar disk !\n");
- if(in_Italia)
- printf("Formato GNU tar%s",message_given?snew:sita);
- else
- printf("GNU tar format%s",message_given?snew:sing);
- message_given=true;
- last_header= hasVheader ? 1 : 0;
- }
- }
- }
- check_events();
- leggi_settore(last_header,disk_buffer);
- if(check_error()) raise_error();
-
- last_sector=last_header;
- if(check_all_zero(disk_buffer)){
- if(last_header==0||(bar_archive||hasVheader)&&last_header==1)
- printf(in_Italia?"Disco vuoto\n":"No files on disk\n");
- return;
- }
- linkflag= get_linkflag(&length);
- if(linkflag!='1'&&linkflag!='2'&&linkflag!='V'&&linkflag!='M')
- print_info(bar_archive ? ((barh_type*)disk_buffer)->name :
- ((tarh_type*)disk_buffer)->name,length);
- last_header += (length+1023)/512;
- }
- }
-
- void svuota_buffer()
- /* empty the buffer, used at the end of a file, next data
- will be a file header which must be aligned at the start of a sector;
- really, it's useful only for MacBinary files, since tardata internally
- groups the data in 512 bytes chunks
- */
- {
- if(more_space!=512){
- /* succede solo per MacBinary, visto che tardata scrive comunque in blocchi di 512 */
- fillmem(&disk_buffer[512-more_space],0,more_space); /* azzera quello che resta:
- il tar per UNIX non lo fa, ma non Å bello lasciare della robaccia...
- -- clear the empty part of the buffer before writing it out: the
- UNIX tar doesn't do that, but it's not professional to write
- garbage data (well, the Macintosh too does that, the 128 bytes
- of reserved data in the resource fork are garbage: but, think
- what would happen if that garbage happens to be a part of your
- personal mail, or reserved informations... The reserved bytes in
- the suntar application often happen to contain a chunk of its source
- code, which was saved before compiling and is still in the disk
- buffer)
- */
- write_next_sector();
- last_sector++;
- }
- more_space=512;
- }
-
- void azzera_settore() /* clear a sector, that is write an end of archive header */
- {
- svuota_buffer();
- fillmem(disk_buffer, 0, 512);
- questo_e_un_header=true;
- write_next_sector();
- /* niente last_sector++, per ovvie ragioni
- -- don't increment last_sector, another write must overwrite this sector
- */
- last_header=last_sector;
- }
-
- void tronca_archivio()
- /* truncate an archive, by clearing the last header: used when,
- due to an error, what follows that header can't be completed */
- {
- last_sector=last_header;
- /* multivolume, se il disco Å stato espulso deve richiederlo !!
- o forse non lo faccio qui, ma nella gestione setjmp, questa qui Å chiamata anche
- in caso di quit
- o forse dare un messaggio, in fondo capita raramente...
- -- in multivolume archives, the sector to be cleared may be on another disk,
- which was ejected. The correct behaviour should be to ask the user to insert
- back that disk, carefully check that it's the right disk and clear the sector,
- or, if the user refuses to insert it back, print which sector (and file)
- must be cleared. By now, in that case I do nothing
- */
- /*printf("<%ld>",(long)last_sector);*/
- /* I may avoid to flush things which are AFTER the last header: not only that
- saves time, but if the operation was interrupted because that's the wrong
- disk it could save good data */
- invalid_after(last_sector);
-
- read_sectors(last_sector,disk_buffer,1); /* don't use the value stored in the buffers! */
- if(err_code==0){
- /* compare it with the stored content of the last sector: it would be
- terrible to clear a sector in a disk which happens to be in that drive
- but is not the tar/bar disk I was writing !
- */
- if(compare_mem(ultimo_header,disk_buffer,sizeof(ultimo_header))){
- fillmem(disk_buffer, 0, 512);
- scrivi_settore(last_sector,disk_buffer); /* senza verifica di errore */
- flush_buffers();
- }
- else
- invalid_buffers();
- }
- else
- invalid_buffers();
- more_space=512;
- }
-
- Boolean compare_mem(p,q,s)
- register char*p,*q;
- register int s;
- {
- while(s){
- if(*p++ != *q++) return false;
- s--;
- }
- return true;
- }
-
- void print_ready()
- {
- long sz=sectors_on_floppy-last_header-1;
- printf("%ld",sz/2);
- if(sz&1)printf(in_Italia?",5":".5");
- printf(in_Italia?" Kbytes disponibili\n":" Kbytes available\n");
- }
-
- /********************************/
-
- void check_and_eject()
- /* eseguita in caso di QUIT ma anche in caso di errore
- -- executed in case of error or Quit
- */
- {
- if(write_in_corso){
- tronca_archivio();
- write_in_corso=false;
- }
- else{
- if(dirty_buffers()) invalid_buffers();
- }
- diskEject();
- }
-
- /************************/
- void check_wr_err()
- {
- if(err_code){
- start_of_line();
- if(err_code==-65)
- printf(in_Italia?"Errore, disco assente\n":"Error, missing disk\n");
- else
- printf("Disk write error %d\n",err_code);
- if(!ignore_errors && write_in_corso){
- tronca_archivio();
- raise_error();
- }
- }
- }
- /*********************************/
-
- void my_tar(file_mode) /* handles a command from the Write menu */
- {
- int charsRead;
-
- int n_types;
- SFTypeList myTypes;
- extern unsigned char*nomeFormato;
-
- if(file_mode==wmASCII){
- n_types=1;
- myTypes[0]='TEXT';
- binary=false;
- dataonly=true;
- nomeFormato="\p (ASCII)";
- }
- else if(file_mode==wmWriteTar){
- if(bar_archive)
- n_types=-1;
- else
- n_types=2;
- myTypes[0]='TARF';
- myTypes[1]='TEXT'; /* quelli estratti con MacCompress se provengono da UNIX
- (niente resource fork) sono TEXT KAHL
- -- .tar.Z files extracted with MacCompress are TEXT-KAHL,
- .tar files created by tar 3.0 are TARF TAR , those created
- by suntar may be TARF (copy to mac file) or TEXT (save sectors)
- */
- }
- else{ /* wmDataFork o wmWriteMacBin */
- n_types=-1;
- binary=true;
- dataonly= file_mode==wmDataFork;
- nomeFormato=file_mode==wmWriteMacBin?"\p(MacBinary)":"\p(Data fork)";
- }
-
- more_space=512;
- if(file_mode!=wmWriteTar){
- Str255 name;
- int i=get_file_or_folder(name,n_types,&myTypes);
- if(i<0) return; /* cancel...*/
- if(i==0){ /* folder: il nome Å il path completo, ma non voglio
- salvarlo tutto nell'archivio
- -- folder: discover the size difference between the full
- pathname and the partial pathname
- No more useful since now I use a partial file name anyway,
- but to keep these instructions causes no problems */
- path_len=name[0]-1; /*il -1 Å necessario, in fondo c'Å un :
- -- the -1 is needed since the last character is a ':'
- */
- while(path_len>0 && name[path_len]!=':') path_len--;
- if(--path_len<0)path_len=0; /*non dovrebbe mai capitare
- -- that should never happen, but behaving well in cases
- that should be impossible may save a programmer from
- some nasty bugs */
- }
- else /* file semplice, il nome Å relativo al volume
- -- single file, I've filename + vRefNum as returned by SFGetFile
- */
- path_len=0;
- name[name[0]+1]=0;
- fase=writing_disk;
- write_in_corso=1;
- tar_file_or_folder(&name[1]);
- azzera_settore();
- flush_buffers();
- write_in_corso=0;
- }
- else{ /* file tar, non c'Å da creare header o altro...
- -- write tar file: handle it directly here...
- */
- sector_t more_sectors=0;
- long length;
-
- my_SF_Get(n_types,myTypes);
- if(!reply.good)return;
- path_len=0;
-
- if(apri_file("rb",&inputFile))
- return;
- inf_is_open=true;
- fase=writing_disk;
- write_in_corso=1;
- if(bar_archive){
- /* read (and skip) the volume header, with some checks */
- charsRead = mac_fread(disk_buffer, 512, inputFile);
- if(((barh_type*)disk_buffer)->bar_magic[0]!= 'V' ||
- ((barh_type*)disk_buffer)->bar_magic[1] != 0)
- error_message(in_Italia?"Questo non Å un file in formato bar\n":
- "Not a bar file !\n");
- if(floppy_n==0 && last_sector==0) mcopy(bar_date,((barh_type*)disk_buffer)->cdate,12);
- }
- do{
- charsRead = mac_fread(disk_buffer, 512, inputFile);
- if(charsRead>=0 && charsRead<512)
- fillmem(&disk_buffer[charsRead], 0, 512-charsRead); /* non indispensabile,
- ma Å brutto che lo spazio extra
- nell'ultimo settore del file resti garbage.
- -- see before, clear the buffer to avoid writing
- garbage at the end of the last sector
- */
- /* meglio non controllare errore, i file di tar2 sono cattivi e invece va poi
- tutto bene...*/
- if(more_sectors==0){
- last_header=last_sector;
- if(check_all_zero(disk_buffer))
- more_sectors=-1; /* infinity... */
- else{
- /* it was an header: do the standard work for headers, extract the size
- field and continue */
- questo_e_un_header=true;
- copia_ultimo_header(disk_buffer,last_sector+1);
- last_offset=0;
- (void)get_linkflag(&length);
- if(length<0){
- check_and_eject();
- raise_error();
- }
- else{
- more_sectors=(length+511)/512;
- print_info(bar_archive?((barh_type*)disk_buffer)->name:disk_buffer,length);
- if(!bar_archive) controlla_che_ci_stia(more_sectors);
- }
- }
- }
- else
- more_sectors--;
- check_events();
- write_next_sector();
- last_sector++;
- }
- while(charsRead>0);
- flush_buffers();
- write_in_corso=0;
-
- FSClose(inputFile);
- inf_is_open=false;
- last_sector=last_header;
- }
- }
-
-
- void close_input_files()
- { /* da chiamare in caso che una longjmp esca dalla routine precedente */
- if(inf_is_open){
- FSClose(inputFile);
- inf_is_open=false;
- file_aperto=false; /* lo stesso inputFile viene usato per due scopi diversi,
- in ogni caso dopo di adesso il valore buono Å false...
- -- the inputFile variable is used in two different places
- for different purposes, hence two variables to be cleared
- */
- }
- if(devo_chiudere_in){
- (void) PBCloseSync(&pb);
- devo_chiudere_in=false;
- }
- }
-
- void FillMacBin2Fields() /* transforms a MacBinary header into a MacBinary II header */
- {
- extern short current_crc;
- register int i;
-
- /* can't declare a pointer to binh_type since it's misaligned by one byte */
- tarh.name[101]=tarh.name[74]; /* because I didn't clear that byte, as the
- MacBinary standard says, but left there the finder flags which
- MacBinary II says must be stored elsewhere */
- tarh.name[74]=0; /* but now it's better to follow the standard */
- tarh.name[122]=tarh.name[123]=129;
- current_crc=0;
- for(i=0;i<124;i++)
- CalcCRC(tarh.name[i]);
- CalcCRC(0);
- CalcCRC(0);
- *(short*)&tarh.name[124]=current_crc;
- }
-
- void assegna_tar_version()
- {
- extern char *titoli[];
-
- if(dirty_buffers()) flush_buffers();
- tar_version=my_modal_dialog(140,NULL,0);
-
- ParamText(in_Italia?
- "\pDevo assegnare l\'opzione \"tar version\" permanentemente ?":
- "\pSet the option \"tar version\" permanently ?",PNS,PNS,PNS);
- if(my_modal_dialog(130,titoli,2)==1)
- save_options();
- }
-
-
- void controlla_che_ci_stia(n_sectors)
- sector_t n_sectors;
- /* check that there is enough space in the disk for next file: if not,
- a multivolume archive could be generated, but the standard tar does not
- accept multivolume archives
- */
- {
- if(previousFormat<=tar_singlevol &&tar_version<=tar_singlevol &&
- last_header+n_sectors+1>=sectors_on_floppy){ /* l'header va nel
- settore last_header, seguono n_sectors settori di dati fino a last_header +
- n_sectors e il settore last_header+n_sectors+1 deve contenere gli zeri di
- indicazione fine archivio */
- if(previousFormat==tar_unknown&&tar_version==tar_unknown){
- if(dirty_buffers()) flush_buffers();
- ParamText(in_Italia?
- "\pSpazio insufficiente, creo un archivio multidisco ?":
- "\pNot enough space, OK to create a multivolume archive ?",PNS,PNS,PNS);
- assegna_tar_version();
- }
-
- if(tar_version==tar_singlevol){
- printf(in_Italia?"Errore, spazio insufficiente\n":"Error, not enough space\n");
- /*tronca_archivio(); /* bisogna riazzerare l'ultimo header per avere un disco consistente */
- raise_error(); /* che chiama check_and_eject che chiama tronca_archivio, per cui
- quella chiamata sopra non serve */
- }
- }
- }
-
- /*********** end of routines by Speranza ****************/
-
- /****** start of routines by Gail Zacharias *****************/
-
-
- void tar_file_or_folder (file_name)
- char *file_name;
- {
-
- statf(file_name);
- if (statb.ioFlAttrib & ioDirMask) {
- statb.ioVRefNum = getvrefnum(file_name);
- tardir(file_name);
- }
- else{
- char *cp = file_name+strlen(file_name);
- while (cp != file_name && cp[-1] != ':') --cp;
- if ((macbinh.nlen = strlen(cp)) >= 64) nametoolong(file_name);
- strcpy(macbinh.name, cp);
- tarfile(file_name);
- }
- }
-
- void tardir (dname)
- char *dname;
- {
- int isvolume;
- Str255 name;
- long dirid = statb.ioDirID;
- int index = 0;
- int dlen = strlen(dname);
-
- isvolume = bar_archive ? bar_header(dname, 0L, &tarh) : tarheader(dname, 0L);
- if(!isvolume){
- if(expert_mode) print_sector_n(last_sector-1); /* -1 perchÄ Å giê stato
- incrementato; potrei spostare la printf sopra, ma allora non saprei se Å
- un volume... */
- printf(in_Italia?"Cartella %s\n":"Folder %s\n",
- bar_archive?((barh_type*)&tarh)->name:tarh.name);
- }
-
- if(strchr(dname, ':'))
- strcpy(name, dname);
- else{
- name[0] = ':';
- strcpy(&name[1], dname);
- dlen++;
- }
- if (name[dlen-1] != ':') name[dlen++] = ':';
- while (1) {
- statb.ioFDirIndex = ++index;
- statb.ioDirID = dirid;
- statb.ioNamePtr = &macbinh.nlen;
- if (PBGetCatInfoSync(&statb) || statb.ioResult) {
- if (statb.ioResult != fnfErr ) pbsyserr(&statb);
- return;
- }
- strncpy(&name[dlen], macbinh.name, macbinh.nlen);
- name[dlen+macbinh.nlen] = '\0';
- if (macbinh.nlen >= 64 ) nametoolong(name);
- if (statb.ioFlAttrib & ioDirMask)
- tardir(name);
- else
- tarfile(name);
- }
- }
-
- static void alias_error(err)
- {
- if(err!=noErr){
- beep_in_foreground();
- error_message_1("Error %d in resolving alias\n",err);
- }
- }
-
- void tarfile (fname)
- /* heavily modified by Speranza, in order to handle aliases */
- char *fname;
- {
- char name[150];
- short vrefnum=0;
- int old_pl=path_len;
- extern char s_spazi[];
-
- strcpy(name,fname);
- if (statb.ioFRefNum) {
- printf("Warning: file %s was already open\n", name);
- devo_chiudere_in=false;
- }
-
- if( resolve_aliases && (statb.ioFlFndrInfo.fdFlags & ALIAS_BIT) ){
- if(! gHasResolveAlias){
- if(dirty_buffers()) flush_buffers();
- ParamText(in_Italia?"\pPer risolvere gli alias ci vuole il System 7":
- "\pAliases can\'t be resolved without System 7",PNS,PNS,PNS);
- my_alert();
- }
- else{
- FSSpec mySpec;
- WDPBRec param;
- char is_folder,is_aliased;
- int io;
-
- io=FSMakeFSSpec(0,0L,c2pstr(name),&mySpec);
- alias_error(io);
- p2cstr(name);
-
- io=ResolveAliasFile(&mySpec,true,&is_folder,&is_aliased);
- if(io!=noErr){
- printf(in_Italia?"Alias %p: non trovato l\'originale\n":
- "Alias %p: original not found\n",mySpec.name);
- return;
- }
- /* ora, il metodo regolamentare sarebbe fare
- io=FSpOpenDF(&mySpec,fsRdPerm,&pb.ioRefNum); (data fork)
- io=FSpOpenRF(&mySpec,fsRdPerm,&pb.ioRefNum); (resource fork)
- ma tutto il programma Å impostato sui vecchi formati: quale Å il nuovo
- equivalente di PBGetCatInfo ? Ovvero, come la si deve chiamare se si hanno
- solo le informazioni vecchio stile ? Per ora preferisco tradurre la specifica nuova
- in una vecchia, forse il modo che uso non Å il migliore ma per ora l'importante
- Å che funzioni
- -- at this point, I have a FSSpec, while all the routines by Zacharias expect
- the old couple vRefNum-filename
- A conversion to the new style would be more elegant, a conversion to the old
- style is more compatible and easier to implement, hence that's what I did
- */
- if(is_folder){
- #ifdef V_122
- PathNameFromDirID(mySpec.parID, mySpec.vRefNum, name);
- path_len=name[0]-1; /* ci sarebbe da discutere che path name
- mettere nell'archivio, quello dell'alias o quello dell'
- originale ? Cosô non ci metto nessun pathname, gli alias di
- folder appaiono al livello esterno
- -- which path must be written in the archive ? to remove
- the problem, aliases are written with the last name only:
- that's not the best solution, but it's simple to implement
- */
- pStrcat(name,mySpec.name);
- pStrcat(name,"\p:");
- p2cstr(name);
- tar_file_or_folder (name);
- #else
- short oldref;
- path_len=0;
- pStrcpy(name,"\p:");
- pStrcat(name,mySpec.name);
- pStrcat(name,"\p:");
- p2cstr(name);
- oldref=curr_vrefnum;
-
- param.ioVRefNum=mySpec.vRefNum;
- /*printf("FSSpec=%d %ld %p\n",mySpec.vRefNum,mySpec.parID,mySpec.name);*/
- param.ioNamePtr=NULL;
- param.ioWDProcID=signature;
- param.ioWDDirID=mySpec.parID;
- io=PBOpenWDSync(¶m);
- alias_error(io);
- curr_vrefnum=param.ioVRefNum;
- SetVol(NULL,curr_vrefnum);
- register_WD(param.ioVRefNum);
-
- /*printf("intero=%s pezzo=%s\n",name,name+path_len);*/
- tar_file_or_folder (name);
- SetVol(NULL,curr_vrefnum=oldref);
- #endif
- path_len=old_pl;
- return;
- }
- /* ora mi creo una WD sul file origine: poi non la chiudo per lo stesso motivo
- che in Untar (gestione duplicate file name)
- -- PBGetCatInfo may be called without a working directory ID (by using PBHGetCatInfo),
- but tardata and other routines expect a vrefnum, hence I create a working directory. */
- param.ioVRefNum=mySpec.vRefNum;
- param.ioNamePtr=NULL;
- param.ioWDProcID=signature;
- param.ioWDDirID=mySpec.parID;
- io=PBOpenWDSync(¶m);
- alias_error(io);
-
- vrefnum=param.ioVRefNum; /* ad uso delle varie open...*/
- register_WD(param.ioVRefNum);
-
- /* fill the informations which statf should have returned */
- statb.ioNamePtr = mySpec.name;
- statb.ioFVersNum = 0;
- statb.ioVRefNum = param.ioVRefNum;
- statb.ioFDirIndex = 0;
- statb.ioDirID = 0;
- if (PBGetCatInfoSync(&statb) ) pbsyserr(&statb);
-
- statb.ioNamePtr = NULL;
- p2cstr(mySpec.name);
- strcpy(name,mySpec.name);
- path_len=0;
- }
- }
-
-
- if (dataonly){
- if(binary || (statb.ioFlFndrInfo.fdType == 'TEXT'&&!(statb.ioFlFndrInfo.fdFlags&ALIAS_BIT)))
- tardata(name,vrefnum);
- else /* Write ASCII on non-text files */
- switch(non_text_ASCII){
- case 0: /* not saved */
- if(expert_mode) printf(s_spazi);
- printf("File %s (%s)\n",name+path_len,in_Italia?"non salvato":"not saved");
- break;
- case 1: /* data */
- binary=1;
- tardata(name,vrefnum);
- binary=0;
- break;
- case 2: /* ASCII */
- tardata(name,vrefnum);
- break;
- case 3: /* macbinary */
- tarmacbin(name,vrefnum);
- break;
- }
- }
- else
- tarmacbin(name,vrefnum);
- path_len=old_pl;
- svuota_buffer(); /* per approssimare per eccesso a multipli di 512 bytes... */
- }
-
-
- void tardata (fname,vrefnum)
- char *fname;
- {
- if(bar_archive)
- bar_header(fname, statb.ioFlLgLen, &tarh);
- else
- tarheader(fname, statb.ioFlLgLen);
- if(expert_mode) print_sector_n(last_sector-1);
-
- printf("File %s (%ld bytes)",bar_archive?((barh_type*)&tarh)->name:tarh.name,
- statb.ioFlLgLen);
- if(!binary) printf(" ASCII\n"); else printf("\n");
-
- pb.ioParam.ioVRefNum = vrefnum;
- pb.ioParam.ioVersNum = 0;
- pb.ioParam.ioPermssn = fsRdPerm;
- pb.ioParam.ioMisc = 0;
- pb.ioParam.ioNamePtr = c2pstr(fname);
- if (PBOpenSync(&pb)) pbsyserr(&pb);
-
- devo_chiudere_in=true;
- tar_writefork(statb.ioFlLgLen, 0);
- p2cstr(fname);
- }
-
- void tarmacbin(fname,vrefnum)
- char *fname;
- {
- long fsize = macbinsz(statb.ioFlLgLen)+macbinsz(statb.ioFlRLgLen)+128L;
- if(bar_archive)
- bar_header(fname, fsize, &tarh);
- else
- tarheader(fname, fsize);
- if(expert_mode) print_sector_n(last_sector-1);
-
- printf("MacBinary %s (data %ld+res %ld bytes)\n",
- bar_archive ? ((barh_type*)&tarh)->name : tarh.name,
- statb.ioFlLgLen, statb.ioFlRLgLen);
- macbinheader();
- pb.ioParam.ioVRefNum = vrefnum;
- pb.ioParam.ioVersNum = 0;
- pb.ioParam.ioPermssn = fsRdPerm;
- pb.ioParam.ioMisc = 0;
- pb.ioParam.ioNamePtr = c2pstr(fname);
- if (PBOpenSync(&pb)) pbsyserr(&pb);
- devo_chiudere_in=true;
- tar_writefork(statb.ioFlLgLen, 1);
- pb.ioParam.ioVRefNum = vrefnum;
- pb.ioParam.ioVersNum = 0;
- pb.ioParam.ioPermssn = fsRdPerm;
- pb.ioParam.ioMisc = 0;
-
- #define ioDirID ioFlNum
- if((pb.fileParam.ioDirID=openfile_dirID)!=0){
- pb.ioParam.ioVRefNum=openfile_vrefnum;
- pb.ioParam.ioNamePtr=mac_file_name;
- }
- #undef ioDirID /* must not conflict with statb.ioDirID */
-
- if (PBHOpenRFSync(&pb)) pbsyserr(&pb);
- devo_chiudere_in=true;
- tar_writefork(statb.ioFlRLgLen, 2);
- /* if (fsize & 511L) writeblock(&tarh, 512 - (fsize & 511L));
- NO, ci deve pensare svuota_buffer */
- p2cstr(fname);
- }
-
- void macbinheader()
- {
-
- fillmem(&macbinh.name[macbinh.nlen], 0, 64+63-macbinh.nlen);
- /* anche i campi che seguono vanno azzerati... */
- mcopy(&macbinh.finfo, &statb.ioFlFndrInfo, sizeof(FInfo));
- macbinh.protected = 0;
- macbinh.zero = 0;
- macbinh.dflen = statb.ioFlLgLen;
- macbinh.rflen = statb.ioFlRLgLen;
- macbinh.cdate = statb.ioFlCrDat;
- macbinh.mdate = statb.ioFlMdDat;
- tarh.name[0]=0;
- mcopy(&tarh.name[1], &macbinh, sizeof(macbinh));
- FillMacBin2Fields();
- writeblock(&tarh, 128);
- }
-
- void tar_writefork (fsize, macbinp)
- long fsize;
- {
- unsigned int n_non_ASCII=0;
- int blocksz = (macbinp ? 128 : 512);
- pb.ioParam.ioPosMode = fsAtMark;
- pb.ioParam.ioBuffer = (Ptr) &tarh;
- pb.ioParam.ioReqCount = blocksz;
- while (fsize) {
- if (fsize < pb.ioParam.ioReqCount)
- pb.ioParam.ioReqCount = fsize;
- fsize -= pb.ioParam.ioReqCount;
- if (PBReadSync(&pb) || pb.ioParam.ioActCount != pb.ioParam.ioReqCount) {
- int err = pb.ioParam.ioResult;
- (void) PBCloseSync(&pb);
- devo_chiudere_in=false;
- pb.ioParam.ioResult = err;
- pbsyserr(&pb);
- }
- if (!macbinp && !binary) {
- register char *cp = pb.ioParam.ioBuffer;
- register int i = pb.ioParam.ioActCount;
- while (i) {
- if (*cp == CR) *cp = LF;
- else if( (unsigned char) *cp >= 128 )
- n_non_ASCII++;
- --i, ++cp;
- }
- }
- if(pb.ioParam.ioActCount<blocksz)
- fillmem(&pb.ioParam.ioBuffer[pb.ioParam.ioReqCount],0,blocksz-(int)pb.ioParam.ioActCount); /* il tar
- per UNIX non lo fa, ma Å talmente sporco non farlo */
- writeblock(pb.ioParam.ioBuffer, blocksz);
- }
- if(macbinp==1)
- get_openfile_location(pb.ioParam.ioRefNum);
-
- if (PBCloseSync(&pb)) pbsyserr(&pb);
- devo_chiudere_in=false;
- if(n_non_ASCII != 0) printf(in_Italia?"Scritti %u caratteri non ASCII\n":
- "%u non-ASCII characters were written\n",n_non_ASCII);
- }
-
- short tarheader (fname, fsize)
- char *fname;
- long fsize;
- {
- long n_sectors=(fsize+511)/512;
-
- fillmem(&tarh, 0, 512);
- mac_to_unix(tarh.name, fname+path_len);
- if(!strcmp("./",tarh.name) || !tarh.name[0] ) return -1;
- if (statb.ioFlAttrib & ioDirMask)
- if (tarh.name[strlen(tarh.name)-1] != '/')
- tarh.name[strlen(tarh.name)] = '/';
- numstr(&tarh.mode, (long)((statb.ioFlAttrib & ioDirMask) ? dirmode : filemode), 8);
- numstr(&tarh.uid, my_uid, 8);
- numstr(&tarh.gid, my_gid, 8);
- numstr(&tarh.size, fsize, 12);
- numstr(&tarh.mtime, (long) statb.ioFlMdDat - UNIXTIME, 12);
- tarh.linkflag = ((statb.ioFlAttrib & ioDirMask) ? '5' : '0');
- fill_checksum(&tarh);
- last_offset=0;
- questo_e_un_header=true;
- writeblock(&tarh, 512);
- last_header=last_sector-1; /* mi serve il valore pre-incremento, ma eventuali
- header di volume devono essere contati... */
-
- /* remember what you are going to write: it's useful for the 'M' continuation
- header, and also for checks before clearing this same sector later if
- I can't successfully save on disk the whole file
- */
- copia_ultimo_header(&tarh,last_sector); /* valore post-incremento */
- controlla_che_ci_stia((int)n_sectors);
- return 0;
- }
-
- void fill_checksum(t)
- register tarh_type *t;
- {
- register long chksum = 0;
- register int i;
- fillmem(t->chksum, ' ', 8);
- if(uname[0]||gname[0]){
- strcpy(t->magic, "ustar ");
- strcpy(t->uname, uname);
- strcpy(t->gname, gname);
- }
- for(i=0; i<512; ++i) chksum += (unsigned char)t->name[i];
- numstr(t->chksum, chksum, 8);
- }
-
- /* Don't allow absolute names. "HD:foo:bar" becomes "./foo/bar" */
- void mac_to_unix(uname, mname)
- char *uname, *mname;
- {
- register char *dp = uname, *cp;
- register unsigned char c;
- register int namelen;
- if (cp = strchr(mname, ':')) {
- #ifdef DOT_SLASH_NAME
- *dp++ = '.', *dp++ = '/';
- #endif
- ++cp;
- }
- else
- cp = mname;
-
- for(;;) {
- while (*cp == ':') *dp++ = '.', *dp++ = '.', *dp++ = '/', ++cp;
- namelen=0;
- while (*cp && *cp != ':'){
- /* modified by Speranza to handle in some way non-ASCII codes 128 and upper,
- and characters which the UNIX shell uses.
- Really we're not so expert of UNIX to know the better thing to do with
- every character under every shell and/or file utility: the rule which
- is often given is "use only letters, digits, underscore and dot" but
- a few other characters are usually good */
- c=*cp++;
-
- if(c>=127){
- static char s1[]="Çàèܺ«╛╬╧¬";
- static char s2[]="⌐»┐╦╠═╪";
- char *p;
- if((p=strchr(s1,c))){ /* special characters with a two-character transliteration */
- if(!trunc_14 || namelen<14)
- *dp++="AOaosAaOot"[p-s1];
- namelen++;
- c= "eeeeseeeem"[p-s1];
- }
- else if(c>=128 && c<160) /* remove accents, tilde etc. */
- c= "AACENOUaaaaaaceeeeiiiinooooouuuu"[c-128];
- else if((p=strchr(s2,c)))
- c= "cOoAAOy"[p-s2];
- else if( (c==208 || c==209) && namelen!=0)
- c='-';
- else if(c==202&&!suppress_shell_chars) /* non-breakable space */
- c=' ';
- else
- c='\0';
- }
- else if(suppress_shell_chars){
- /* many characters have a special meaning to the UNIX shell, but some
- only when used as first character of an identifier */
- if(c==' ')
- c='_';
- else if(strchr(";|^*?\'\\`\"!$@<>&()[],",c) )
- c= '\0';
- else if(namelen==0 && strchr("~%-.#",c) )
- c= '\0';
- }
- if (c<' '){
- #define REPLACER '+'
- if(namelen!=0 && (*(dp-1)==REPLACER||*(dp-1)=='_' ) )
- ; /* suppress it ! */
- else
- if(!trunc_14 || namelen<14) *dp++ = REPLACER;
- }
- else{
- if(c=='/') c=':';
- if(!trunc_14 || namelen<14) *dp++ = c;
- }
- namelen++;
- }
- if (!*cp++) break;
- *dp++ = '/';
- }
- if (strlen(uname) >= 100) nametoolong(mname);
- }
-
- void numstr (p, num, count)
- register char *p;
- register long num;
- register int count;
- {
- /* come fatto da Zacharias lasciava un sacco di '0' in testa, l'unico modo
- per non farlo Å scrivere in un buffer e poi copiare
- -- I (G. Speranza) don't like how Zacharias did it, he wrote directly to
- the destination filling extra space at the beginning with '0's ! It's
- also a risk for compatibility, since the UNIX tar and bar don't write
- things in that way.
- */
- char buffer[14];
- buffer[--count] = '\0';
- if (count != 11) buffer[--count] = ' ';
- if(count!=0){
- do{
- buffer[--count] = '0' + ((int)num & 7);
- num >>= 3;
- }
- while (count && num);
- }
- strcpy(p,&buffer[count]);
- }
-
- void statf (fname)
- char *fname;
- {
- char name[256];
- statb.ioNamePtr = c2pstr(strcpy(name, fname));
- statb.ioFVersNum = 0;
- statb.ioVRefNum = curr_vrefnum;
- statb.ioFDirIndex = 0;
- statb.ioDirID = 0;
- if (PBGetCatInfoSync(&statb) || statb.ioResult) pbsyserr(&statb);
- statb.ioNamePtr = NULL;
- }
-
- short getvrefnum (fname)
- char *fname;
- {
- /* ho il sospetto che non serva pi¥, se serve solo a sapere il vrefnum attuale...
- no, a volte curr_vrefnum Å 0, forse serve, e comunque sono poche istruzioni
- */
- HVolumeParam hpb;
- char name[256];
- hpb.ioNamePtr = c2pstr(strcpy(name, fname));
- hpb.ioVRefNum = 0;
- hpb.ioVolIndex = 0;
- if (PBHGetVInfoSync(&hpb) || hpb.ioResult) pbsyserr(&hpb);
- return hpb.ioVRefNum;
- }
-
- void nametoolong (name)
- char *name;
- {
- printf("\"%s\" - name too long\n", name);
- raise_error();
- }
-