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 muntar version 1.0.
- *
- */
-
- /* the original muntar program was then altered to become part of suntar:
- */
-
- /*******************************************************************************\
-
- tar reading 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 muntar, but most of the latter were modified more or less
- heavily by us
- */
-
- #define USA_CURRVREFN
-
-
-
- #include "PB_sync.h"
- #include "antiglue.h"
- #include "windows.h"
- #include "suntar.h"
-
- /*#include <FileMgr.h>
- #include <OSUtil.h>
- #include <HFS.h>*/
- #include <string.h>
- /* #include <errors.h> */
-
- #define ASM
-
- #define tarsz(n) (((n)+511L) & -512L)
- #define macbinsz(n) (((n)+127L) & -128L)
-
- char *strrchr();
-
-
- struct binh_type macbinh;
- tarh_type tarh;
- unsigned char disk_buffer [512];
-
- OSType filecreator,filetype;
- unsigned char listonly=0;
-
- /* alcune routines sue un po' riscritte (ho il sospetto esistano in libreria o nella ROM,
- ma non so con che nomi e che parametri, tanto vale riscriversele
- */
-
-
- StringPtr c2pstr(p)
- register char p[];
- {
- register int i,len=strlen(p);
- for(i=len;i>0;i--)
- p[i]=p[i-1];
- p[0]=len;
- return (StringPtr) p;
- }
-
- char * p2cstr(p)
- register unsigned char p[];
- {
- register int i,len=p[0];
- for(i=0;i<len;i++)
- p[i]=p[i+1];
- p[len]='\0';
- return p;
- }
-
- /* main() l'ho tolto di torno...
- {
- printf(
- "This is freeware. If you paid money for this program, you got ripped off.\n");
- return;
- }
- */
-
- int binary=true; /* se convertire LF-CR o no */
- #define UNIXTIME 2082844800L /* Jan 1, 1970 00:00:00 */
-
- #ifndef ASM
- /* simple implementation */
- void mcopy(dest, src, len)
- register char*dest,*src;
- register unsigned short len;
- {
- while ((short)--len>=0) *dest++ = *src++;
- }
- #endif
-
-
- /******************** start of routines by Speranza ***********************/
-
- #ifdef ASM
- void mcopy(char * dest,char * src,unsigned short len )
-
- /* optimazed implementation, remembering that the 68000 is a 32 bit machine
- and may move 4 bytes at a time, at least if they are placed at an even address
- (since the compiler places at even addresses the start of all data structures,
- that means almost always)
- By Gabriele Speranza, 17 Nov 1991
- */
-
- {
- extern SysEnvRec gMac;
- /* #define EXPLOIT_020 */
- asm {
- move.l dest,a0
- move.l src,a1
- move.w len,d1
- /*
- #ifndef EXPLOIT_020 / * suntar uses mcopy only for small * /
- / * copies, and those which are not aligned are rarely big, * /
- / * probably it's not worth of it, that symbol is NOT defined * /
- if(len>=10 && !((((long)dest)^((long)src))&1) ){
- / * if the transfer is long enough and the pointers have the same parity * /
- #else
- if(len>=10 && ( gMac.processor>=env68020 || !((((long)dest)^((long)src))&1) ) ){
- / * the 68020 and later CPUs do not require same parity * /
- #endif
- */
- cmp.w #10,d1
- blt.s @inloop
- move.l a0,d0
- #ifdef EXPLOIT_020
- cmp.w #env68020,gMac.processor
- bge @ok_to_movelong
- #endif
- move.l a1,d2
- eor.l d0,d2
- lsr.l #1,d2
- bcs.s @inloop
- ok_to_movelong:
-
- /* if(((long)dest)&1){
- *dest++ = *src++; / * both odd=>move one byte to get both even * /
- len--;
- }
- */
- lsr.l #1,d0
- bcc.s @l1
- move.b (a1)+,(a0)+
- subq.w #1,d1
- addq.l #1,d0 /* se il LSB era 1, aggiungere 1 provoca carry sul bit 1
- -- bit 0 was shifted out, and was 1: adding 1 to bit 0 will cause
- a carry to bit 1, but bit 1 was shifted to bit 0...*/
- /* if(((long)dest)&2){
- / * now I have two even addresses, and that's good. But a destination
- at an address multiple of 4 better exploits a 32 bit bus.
- Obviously, the same is for the source, but in 50% of cases aligning one
- aligns the other too, and the cache works better when reading, hence a
- misalignment on reading is less bad then on writing.
- Really, I've an LC where the bus is 16 bit wide, and the cache is used
- only for instructions, so this trick is not fully exploited on my machine! * /
- *((short*)dest)++ = *((short*)src)++;
- len -= 2;
- }
- */
- l1: lsr.l #1,d0
- bcc.s @l2
- move.w (a1)+,(a0)+
- subq.w #2,d1
- /*
- for(temp=len/4;temp;temp--)
- *((long*)dest)++ = *((long*)src)++;
- len %=4;
- */
- l2: move.w d1,d0
- lsr.w #2,d0
- subq.w #1,d0
- loop1:move.l (a1)+,(a0)+
- dbra d0,@loop1
- and.w #3,d1 /* up to 3 further bytes may have to be moved ... */
- /*
- } / * end if: now move byte-wise anything is remaining,
- that is all the job if couldn't move long-wise * /
- while (len-- >0) *dest++ = *src++;
- */
- bra.s @inloop
- loop2: move.b (a1)+,(a0)+
- inloop: dbra d1,@loop2
- }
- }
- #endif
-
- #define dp printf
-
-
- Boolean chiedi_su_questo(int,sector_t,char*);
- OsErr verifica_nome(int,sector_t *);
- short isMacBin2(unsigned char*);
- void make_badname(char*,char*);
- Boolean too_long(char *);
- Boolean is_gif_file(long);
- short gestisci_nome_doppio(char *,char*,FileParam *);
- static void skip_macbinII(int);
- void cancella_file_aperto(short);
-
- jmp_buf main_loop;
- long file_date;
- unsigned char mac_file_name[120]; /* deve poter contenere un path completo...*/
- int openfile_vrefnum;
- long openfile_dirID;
-
- int more_in_bytes; /* I don't remember the number of bytes currently in the
- buffer, but more_in_bytes = 512-number of bytes = free space */
- sector_t sect_n;
- ParamBlockRec pb; /* Å diventata una variabile globale per poter chiudere il file in
- caso di errore; proprio per questo perÿ ha senso che anche il nome
- del file, puntato da un campo del record, sia globale */
- #define ioDirID ioFlNum
- int floppy_n;
- Boolean bar_archive;
- static Boolean notTrueMacBinary,MacBinaryII;
- static unsigned short mbIIsec_head_len;
- Boolean all_listonly;
- Boolean devo_chiudere_out=false;
- /* gruppetto di variabili usate per la verifica di un header 'M' del GNU tar, ma
- anche per altri scopi, sia in lettura sia in scrittura */
- Boolean ultimo_header_valido;
- Boolean ultimo_disco_espulso; /* il disco contenente quell'ultimo header Å stato
- espulso ? */
- Boolean hasVheader;
- char ultimo_header[184]; /* usata anche per altri scopi, viene SEMPRE aggiornata
- coi primi 184 bytes dell'ultimo header, tar o bar, che
- si Å letto o scritto
- -- I always copy here the first 184 bytes of any
- tar or bar file header which is being read (here) or
- written (in tar.c)
- */
- long last_offset; /* solo per GNU tar */
- sector_t next_header_for_AIX; /* only for tar archives, useful only for AIX:
- -1 if next header is on same disk, otherwise number
- of sector in next disk */
- sector_t avail_sectors_for_file; /* = sectors_on_floppy - sect_n successivo di quando ho
- caricato ultimo_header
- -- = sectors_on_floppy - the sector following the header
- */
-
-
- /* titoli italiani dei bottoni dei dialoghi modali
- -- italian titles of the buttons */
- char *titoli[]={"\pSô","\pNo","\pTermina"};
- static char *t1[]= {"\pContinua qui","\pContinua altrove","\pNon salvare"};
- char s_spazi[]=" ";
-
- /****************************/
-
- /* do some buffering towards the hard disk. If I write in relatively small
- pieces (e.g. 5Kbytes) the Mac freezes for a few seconds from time to time,
- (maybe flushing the disk buffers?) yielding big total times. With 10K
- everything works regularly and about two times faster (three times faster than
- suntar 1.2.2, thanks to some other improvements).
- */
-
- static char*hd_buffer;
- static short bytes_in_hd_buffer;
-
- unsigned int hd_buffer_size;
-
- void init_hd_buffering()
- {
- ResrvMem ((Size)hd_buffer_size);
- hd_buffer=NewPtr((Size) hd_buffer_size);
- check_allocated(hd_buffer);
- }
-
- #define reinit_hd_buffering() bytes_in_hd_buffer=0
-
- OSErr flush_hd_buffer(void);
- static OSErr flush_hd_buffer()
- {
- OSErr err;
- if(!bytes_in_hd_buffer) return noErr;
-
- pb.ioParam.ioPosMode = fsAtMark;
- pb.ioParam.ioPosOffset = 0;
- pb.ioParam.ioBuffer = hd_buffer;
- pb.ioParam.ioReqCount=bytes_in_hd_buffer;
- bytes_in_hd_buffer=0;
- if( (err=PBWriteSync(&pb)) || pb.ioParam.ioResult) return pb.ioParam.ioResult;
-
- if(pb.ioParam.ioReqCount != pb.ioParam.ioActCount) return ioErr;
- return noErr;
- }
-
- OSErr write_hd(char*,short);
- static OSErr write_hd(buffer,size)
- char*buffer;
- short size;
- {
- OSErr i;
- if(bytes_in_hd_buffer>hd_buffer_size-size)
- if((i=flush_hd_buffer())) return i;
- mcopy(hd_buffer+bytes_in_hd_buffer,buffer,size);
- if((bytes_in_hd_buffer+=size)==hd_buffer_size)
- return flush_hd_buffer();
- return noErr;
- }
-
- /******************************/
-
- short readblock(buf,nbytes)
- /* this routines translates from the sector-based view of the device driver
- to the "byte stream" view used by most of the program, by buffering reads
- and controlling disk swaps
- Never call it asking for more than 512 bytes, the "buffer fill" operation is
- performed at most once.
- */
- register char*buf;
- int nbytes;
- {
- int i;
-
- /*printf("readblock(%d)\n",nbytes);*/
- if(more_in_bytes<nbytes){
- if(more_in_bytes){
- nbytes-=more_in_bytes;
- mcopy(buf,&disk_buffer[512-more_in_bytes],more_in_bytes);
- buf+=more_in_bytes;
- }
- if(bar_archive)
- bar_check_floppy_swap(0);
- else
- tar_check_floppy_swap(0);
- leggi_settore(sect_n,&disk_buffer);
- /*printf("leggo settore %ld,err=%d\n",(long)sect_n,err_code);*/
- if((i=check_error_and_events())<0) return err_code;
- if(i>0){ /* "missing disk" was converted to a pause event, now the disk
- should be in, but I must repeat the operation */
- leggi_settore(sect_n,&disk_buffer);
- if(check_error()) return err_code;
- }
- more_in_bytes=512;
- sect_n++;
- settori_passati++;
- }
- mcopy(buf,&disk_buffer[512-more_in_bytes],nbytes);
- more_in_bytes-=nbytes;
- return 0;
- }
-
- void unget_block()
- {
- /* viene chiamata per l'unget dei primi bytes di un file, quindi
- -- used to unget the first bytes of a file: they are still in the buffer, hence:
- */
- more_in_bytes=512;
- }
-
- void unget_char()
- {
- more_in_bytes++;
- }
-
- /*
- attenzione che anche nei moduli dehqx e unpit uso i buffer e more_in_bytes !
- -- caution: modifying the above functions, take a look at hqx_end_of_file &
- get_hqx_byte & fast_get_hqx_byte in dehqx.c, and fast_get_pit_byte in unpit.c,
- which are partially copied from the above and use the same data structures
- */
-
-
- void end_of_file()
- {
- /* Å chiamata per saltare sopra gli ultimi bytes prima dell' header del file
- seguente, quindi non c'Å che passare al settore successivo
- -- it skips the last bytes of the current sector: next read will read
- an header which is aligned at the start of a sector
- */
- more_in_bytes=0;
- }
-
- void skip_file(fsize)
- /* it increments the sector number: the disk swap routines are designed to
- handled case when the requested sector is not the first sector in next disk */
- long fsize;
- {
- if(fsize<=512)return; /* il primo settore Å giê stato letto */
- sect_n+= (fsize-1) >>9;
- }
-
-
- /*************************/
-
- void stampa_buffer(sect_n,buffer)
- /* utilissima nel debugging
- -- it was written for debugging, then it became a permanent part of the program
- executing the View sector command
- */
- sector_t sect_n;
- unsigned char *buffer;
- {short i,j=0,x;
- disable_autoflush();
- for(i=0;i<512;i++){
- if((x=buffer[i])<16)
- printf("0%x",x);
- else if(x>=' '&&x<127)
- printf(" %c",x);
- else
- printf("%x",x);
- if(j==24){
- put_char('\n');
- j=0;
- }
- else{
- put_char(' ');
- j++;
- }
- }
- printf(" end of sector %ld\n",(long)sect_n);
- enable_autoflush();
- }
-
- /***************************/
-
- short isASCII(fsize,nLF)
- /* decide if the file is ASCII examining the first sector of its data
- (which was already read by chkmacbin, or is read and ungetted here)
- returns:
- 1 it's ASCII
- 0 it's not ASCII
- -1 the percentage of ASCII bytes is high enough to deserve a 'TEXT' type,
- maybe that file was created on a Mac which gives a meaning to many
- not ASCII chars (e.g. ⌐), but it's too low to choose to modify the
- data by automatically converting any LF to CR...
- */
- long fsize;
- int*nLF;
- {
- register int i,n_non_ASCII;
- int nbytes;
- register char c;
-
- nbytes= fsize>512? 512 : fsize;
- if(nbytes==0) return 0; /* troppo corto per
- decidere, e se Å 0 non ha senso dargli l'icona di testo... */
- if(more_in_bytes==0){
- if(readblock(nLF,1)) raise_error(); /* fill the disk_buffer...*/
- unget_block();
- }
- *nLF=0;
- n_non_ASCII=0;
- for(i=nbytes-1;i>=0;i--){
- c=disk_buffer[i];
- if(c>=' ' && c <= 126)
- ; /* ASCII */
- else if(c==CR || c== '\t' || c=='\f')
- ;
- else if(c==LF)
- (*nLF)++;
- else{
- if(++n_non_ASCII>(14+(512>>5))) break;
- }
- }
- if( !n_non_ASCII && (nbytes>=80 || smallFilesAreASCII) ) return 1;
- return n_non_ASCII > 14+(nbytes>>5) ? 0 : -1;
- }
-
- Boolean print_if_string(format,buffer,size)
- char*format,*buffer;
- {
- /* for error reporting: something coming from a sector containing errors is printed
- only if it looks like a string (only ASCII characters, a terminating '\0', no '\n'... */
- int i=0;
- size--;
- while(i<size && buffer[i]>=' ' && buffer[i]<127 )
- i++;
- if(i==0 || buffer[i]) return false; /* empty string or end of string not reached */
- printf(format,buffer);
- return true;
- }
-
- /***************************/
-
- void my_untar() /* intermediate-level handler of the Extract and List commands */
- {
- int fine,i;
- long lunghezza_file();
-
- more_in_bytes=0;
- bar_archive=0;
- all_listonly=listonly;
-
- tar_check_floppy_swap(1); /* ci sono delle inizializzazioni
- -- obviously I don't swap disks before beginning, but it
- initializes some variables and checks sector 0
- */
- do{
-
- leggi_settore(sect_n,&disk_buffer);
- if(err_code==eofErr)
- fine=true;
- else{
- if((i=check_error_and_events())<0) raise_error();
- if(i>0){
- leggi_settore(sect_n,&disk_buffer);
- if(check_error()) raise_error();
- }
- fine=check_all_zero(disk_buffer);
- }
- if(!fine){
- /*printf("n_settori=%ld\n",((untar_number(&disk_buffer[124],false)+511)/512) );*/
-
- untar();
- tar_check_floppy_swap(-1);
- }
- }
- while(!fine);
- if(sect_n==0){
- one_empty_line();
- printf(in_Italia?"Archivio vuoto\n":"No files in the archive\n");
- }
- else{
- if(expert_mode)
- print_sector_n(sect_n);
- else
- printf("\n");
- printf(in_Italia?"Fine archivio\n":"End of archive\n");
- }
- }
- /************** gestione del formato bar *************/
- /* bar format handling */
-
- void my_unbar()
- {
- int fine,i;
-
- bar_archive=1;
- all_listonly=listonly;
- more_in_bytes=0;
-
- bar_check_floppy_swap(1);
-
- do{
- leggi_settore(sect_n,&disk_buffer);
- if(err_code==eofErr)
- fine=true;
- else{
- if((i=check_error_and_events())<0) raise_error();
- if(i>0){
- leggi_settore(sect_n,&disk_buffer);
- if(check_error()) raise_error();
- }
- fine=check_all_zero(disk_buffer);
- }
-
- if(!fine){
- unbar();
- bar_check_floppy_swap(-1);
- }
- }
- while(!fine);
- if(expert_mode)
- print_sector_n(sect_n);
- else
- printf("\n");
- printf(in_Italia?"Fine archivio\n":"End of archive\n");
- }
-
-
- short unbar_checksum(buffer,do_error,exp_check)
- register unsigned char *buffer;
- long *exp_check;
- {
- register int i;
- register long chksum;
- long hchksum;
-
- hchksum = untar_number(((barh_type*)buffer)->chksum,do_error);
- if(hchksum==-1) return -2; /* testata non bar */
- chksum= ' ' * 8; /* nel calcolo del checksum, il campo checksum era sostituito
- da spazi */
- for (i=0; i < 48; ++i)
- chksum += (unsigned char)buffer[i];
- for (i+=8; i < sizeof(tarh); ++i)
- chksum += (unsigned char)buffer[i];
-
- *exp_check=chksum;
-
- if (chksum == hchksum) return 0; /* tutto OK */
-
- /* il fatto e' questo: quando bar calcola il checksum del settore zero, il campo
- size contiene '0','\0'. Perÿ, per un orribile bug, i 10 bytes successivi non vengono
- affatto azzerati ma contengono ancora la parte finale del campo size del disco
- precedente, e se il nuovo valore di size, che viene scritto DOPO aver calcolato il
- checksum, Å abbastanza lungo succede che parte dei bytes usati per il calcolo del
- checksum vengono irrimediabilmente sovrascritti, e non ho pi¥ modo di calcolarlo
- correttamente.
- Ma d'altra parte a me fa molto comodo poter controllare il checksum, quindi mi rassegno
- al fatto che un errore puÿ esserci, ma controllo che questo errore sia compatibile con
- questo comportamento errato, senza perÿ strafare, in fondo altre versioni di bar
- potrebbero aver corretto il bug: cioÅ, controllo che il checksum letto sia giustificabile
- con un numero di cifre ottali <= del numero di caratteri sovrascritti dal nuovo valore
- di size, e ipotizzo anche che la correzione del bug consista nel calcolare il checksum
- quando sarebbe logico, dopo aver riscritto size.
-
- -- The checksum computation of the volume header is one of the most
- horrible aspects of bar (file headers are OK, fortunately). For some
- unknown reason, bar saves the volume header in a reserved place, so
- the next volume header is built without reinitializing all fields:
- 1) the volume_num is updated
- 2) the size field is replaced by "0" (a '0' followed by a '\0'):
- since that field is 12 bytes long, 10 bytes of the old value are not
- altered by that operation
- 3) the checksum is computed and stored
- 4) the new value of size is now stored in the size field (strangely, since
- file header checksums are always computed after filling all other fields):
- since it's in octal and is multiple of 512, either it's 0 or it's at least
- 4 bytes long, so it overwrites part of the non-fixed data used to compute
- the checksum
- Hence, the size field is not protected by the checksum (not a tragedy, the
- whole file data is not protected by any checksum...) and the cheksum is computed
- using some data which is no more stored on the current disk. In fact, bar
- simply ignores the volume checksum, but it could check it by obliging you to
- always insert all disks of the archive in the correct order (on the first disk the
- "old size" is 0, on other disks it's the previous size field partially overwritten
- by "0").
- But suntar allows you to insert disks in any order, starting extraction from
- any disk. Furthermore, it automatically distinguishes between a tar and bar
- archive, and the checksum of sector 0 looks like the better way to
- guide the choice.
- Hence, this function returns:
- 0 OK, the checksum is valid for a file header (the write commands of suntar
- computes checksums of volume headers as if they were file headers, by
- updating the size field before computing the checksum)
- 1 the checksum is bad as a file header, but the error could be due to some
- binary zeros and some unknown octal digits overwritten by what is currently
- in the size field: that is, it could be a valid checksum for a volume header
- -1 the checksum is invalid anyway
- -2 the checksum field did not contain an octal string
-
- */
-
- {
- register int s;
- s=0;
- for(i=0;((barh_type*)buffer)->size[i]!=0; ++i){
- s+= (unsigned char)((barh_type*)buffer)->size[i];
- }
- chksum -= s;
- }
-
- if( hchksum<chksum || hchksum > chksum + (i+1)*'7' ) /* i contiene ancora la
- dimensione della stringa size, il +1 per il \0 in fondo */
- return -1; /* bad checksum */
- /* there are still some values which are forbidden: e.g. there is a hole between
- "7\0"=55 and "00"=96, however "7777777\0" is > "00000000" hence the last hole
- occurs when there are 7 bytes */
- if(i+1 > 7) return 1;
- i= ((int)(hchksum-chksum))/'0'; /* that's the number of octal digits, supposing
- that all other chars are binary zeros */
- if(i>=8) i=7; /* "77777777"/'0' yields 8, but without doubts it contains 7 digits */
- if( (int)(hchksum-chksum) <= i*'7')
- return 1; /* l'errore Å giustificabile con i caratteri sporcati dal bug di bar */
- return -1;
-
- }
-
-
-
- unsigned char guess_bar_linkflag()
- /* il campo prima del linkflag che in teoria dovrebbe essere vuoto in pratica Å pieno
- e a volte sborda sul linkflag: a prima vista sembra che il linkflag sia scritto dopo,
- era comunque sempre '0' per i file, ma '6' per una directory, invece del '5' che
- mi aspetterei secondo la codifica tar (un'altra volta era '5', ma quando il campo
- precedente non sborda Å '\0'). Per di pi¥, gli hard link (ma non quelli simbolici) hanno
- il campo size != 0 ( e il linkflag corretto, '1'), anche se poi non segue nessun byte.
- Meglio continuare a fare a meno del linkflag nel capire che razza di entry Å...
-
- -- second horrible feature of bar: the rdev field should always be binary zeros
- for conventional files and directories, hence it should not be of interest
- to a program running on the Macintosh. On the contrary, it contains data, and
- I don't know what that data means. The horrible thing is that when that number
- was negative, it's written anyway as a 32 bit unsigned octal number, and that
- occupies 12 bytes, overflowing the rdev field and overwriting the linkflag
- field: it happens often, about one time out of two (and files in the same
- subdirectories tend to either have all the problem or not have it at all).
- So, the linkflag field can't be relied upon, and it should have been the most
- important field of the header, the first thing to look at!
- If the original bar succeed to survive to such a disaster, there must be a way:
- here is what we succeeded to guess by a lot of testing:
- 1) folders may be distinguished since their name ends in '/': that was easy
- 2) links can be distinguished since the linkname field is full: however,
- unlike tar and unlike what the documentation of bar says, the linkname field
- really starts at the first byte after the '\0' which terminates the string
- in the name field. The simple solution of suntar 1.0, consider that as a
- file entry, works for symbolic links (obviously creating an empty file during
- extraction) but does not work for hard links, whose size field is not 0
- even if the archive contains 0 bytes of their contents
- 3) anything else is considered to be a normal file
- If there will be any problem in this approach, the fault is not ours: the
- fault is of that fellow who after doing such a blatant bug, did not correct
- it and allowed it to remain in a program which was used for years and is now
- at the version number 4.51, if I remember well. Obviously, if we could have a
- look at the source of the original bar we would be surer of what we are doing,
- but that would not make the thing less horrible.
- */
- {
- short l;
- l=strlen(((barh_type*)disk_buffer)->name);
- if( ((barh_type*)disk_buffer)->name[l-1] == '/')
- return '5';
- else if( ((barh_type*)disk_buffer)->name[l+1] ) /* perchÄ il link name non sta
- affatto nel campo omonimo...
- -- remember that the linkname is not placed in the linkname field */
- return '1';
- else
- return '0';
- }
-
-
- void unbar()
- {
- unsigned char linkflag;
- long exp_check;
-
- if(expert_mode) print_sector_n(sect_n);
- sect_n++;
- more_in_bytes=0;
- if( unbar_checksum(&disk_buffer,1,&exp_check) != 0 ){
- tarh.name[99]='\0'; /* non si sa mai che cosa ci sia...*/
- printf("Bad header checksum ");
- if(expert_mode){
- if( print_if_string("(got %s expected ",((barh_type*)disk_buffer)->chksum,8))
- printf("%lo) ",exp_check);
- }
- if(!ignore_errors) raise_error();
- put_char('\n'); printf(s_spazi);
- }
- strcpy(tarh.name,((barh_type*)disk_buffer)->name);
- copia_ultimo_header(disk_buffer,sect_n);
-
- file_date= untar_number( &disk_buffer[36],false);
-
- linkflag=guess_bar_linkflag();
-
- if (linkflag=='5')
- untar_directory();
- else if(linkflag=='1')
- printf("Link %s -> %s%s\n", tarh.name,
- &((barh_type*)disk_buffer)->name[strlen(((barh_type*)disk_buffer)->name)+1],
- listonly?"":in_Italia?" (ignorato)":" (ignored)");
- else
- untar_file(untar_number(((barh_type*)disk_buffer)->size,1));
- }
-
- void copia_ultimo_header(p,sector_n)
- /* copies the first 184 bytes of the header where it must be copied, and
- sets some related variables */
-
- char*p; /* puntatore al buffer contenente un header di file o directory */
- sector_t sector_n; /* numero del settore che segue quello in cui l'header Å stato scritto */
- {
- mcopy(ultimo_header,p,sizeof(ultimo_header));
- ultimo_header_valido=true;
- ultimo_disco_espulso=false;
- avail_sectors_for_file= sectors_on_floppy - sector_n;
- /* last_offset non Å gestito qui, tocca al chiamante occuparsene
- -- last_offset is not assigned here, but it must be assigned by the caller
- */
- }
-
- /*************************/
-
- void bar_check_floppy_swap(situation)
- short situation;
- /* handle floppy swap for bar archives */
- {
- int i,this_floppy,accept_any_disk;
- sector_t previous_sect;
-
- if(situation>0){ /* 1 => il primo settore dell'archivio; 0=>un altro settore richiesto da readblock
- (entro un file); -1 => un altro settore richiesto per leggere un header
- -- situation =1 => the first sector in the archive; 0 => another
- sector read through readblock; -1 => a sector which should contain
- a file header */
- floppy_n=1;
- sect_n=1;
- if(fase==hack_listing){
- this_floppy=bar_check_settore0(§_n,true);
- if(this_floppy<0) raise_error();
- if(sect_n>0)printf("%ld sectors from a previous file",sect_n);
- sect_n++;
- if(sect_n>=sectors_on_floppy){
- printf(" (Partly on next disk)\n"); /* a very long file may be splitted
- in three or more disks... */
- longjmp(main_loop,-1); /* during Expert list, the disk is not
- ejected...*/
- }
- else
- printf("\n");
- return;
- }
- /* e prosegui, per il controllo del settore 0
- -- continue, to check sector 0 */
- }
- else if(sect_n<sectors_on_floppy || !drive_number)
- /* the most common case: the requested sector is in the disk which is already
- in the drive */
- return;
- else{
- floppy_n++;
- sect_n -= sectors_on_floppy-1; /* -1 per via dell'header...; in modalitê normale
- si ottiene sempre 1, in listonly no !
- -- minus 1 because of the header; during extraction,
- sect_n will be == sectors_on_floppy, during a List
- it will not
- */
- if(fase==hack_listing){
- if(sect_n>1) printf("(%ld sectors on next disk)\n",(long)sect_n-1);
- printf("\nEnd of disk\n");
- longjmp(main_loop,-1);
- }
- }
-
- accept_any_disk= listonly || situation!=0; /* cioÅ, non sono in mezzo ad un salvataggio...
- if I'm in the middle of a file saving, to get next disk is more important */
-
- for(;;){
- if(situation<=0){ /* il primo disco Å giê dentro, gli altri bisogna sostituirli a
- ciÿ che Å dentro...
- -- the first disk is already in the drive, further disks must
- be inserted
- */
- if(file_aperto) raise_error(); /* dovrÿ metterci un messaggio di errore,
- ma non ne ho voglia di farlo ora; idem per GNU... */
- diskEject();
- do{
- if(fase==hack_reading) /* succede solo per untar e unbar at sector */
- i=inserzione_assicurata(in_Italia?"\pInserisci il prossimo disco":
- "\pInsert next disk",accept_any_disk);
- else{
- char buffer[40];
- strcpy(buffer,in_Italia?"Inserisci il disco numero ":"Insert disk number ");
- my_itoa((long)floppy_n,&buffer[strlen(buffer)]);
- i=inserzione_assicurata(c2pstr(buffer),accept_any_disk);
- }
- }
- while(i!=0);
- }
- else
- situation=-2; /* non posso lasciare 1 se resto entro il ciclo
- -- it can't remain 1 inside the loop
- */
-
- /* ora guardo se il disco ricevuto Å quello che mi aspetto
- -- check whether the inserted disk is the expected disk
- */
-
- this_floppy= bar_check_settore0(&previous_sect,true);
-
- if(this_floppy==floppy_n ||
- fase==hack_reading && previous_sect+avail_sectors_for_file==
- ((untar_number(((barh_type*)ultimo_header)->size,-1)+511)/512) ){
- /* Å stato inserito il disco voluto: nel caso di unbar at sector non posso
- fare affidamento sul numero di floppy, ma almeno le dimensioni le controllo */
-
- printf(in_Italia?"Disco numero %d":"Disk number %d",this_floppy);
- print_if_string(in_Italia?" dell\'archivio %s":" of the archive %s",
- ((barh_type*)disk_buffer)->name,100);
- printf("\n");
-
- if(sect_n<sectors_on_floppy) return;
- /* puÿ capitare durante il list di un file che risulta suddiviso in pi¥
- di 2 dischi, allora chiede anche quelli intermedi ma al solo scopo di
- sapere quanti settori ci sono
- -- I may be here only during List of a file which is so long to be splitted
- among at least three disks: suntar asks all the disks, but the intermediate
- ones are ejected soon after reading how many sectors they contain (it's not
- forbidden to use disks of different sizes for a single archive)
- */
- if(sect_n>=sectors_on_floppy)
- printf(in_Italia?"Disco occupato completamente da parte di un file precedente\n":
- "The whole disk is occupied by part of a previous file\n",
- ((tarh_type*)ultimo_header)->name);
- floppy_n++;
- sect_n -= sectors_on_floppy-1;
- avail_sectors_for_file += sectors_on_floppy-1;
- situation = -1;
-
- }
- else if(this_floppy<0){
- if(situation==-2)
- raise_error(); /* l'utente puÿ ridare il comando senza rimetterci nulla
- -- the user may repeat the command and return here in this same situation */
- else
- ; /* non Å un disco bar, non c'Å che riprovare...
- not a bar disk: remain in the loop, so it will be ejected and a new one
- will be asked for
- */
- }
- else{
- /* it's not the right disk, but it's a bar disk */
- printf(in_Italia?"Questo Å il floppy numero %d\n":"Disk number %d\n",this_floppy);
- if(!accept_any_disk){
- beep_in_foreground();
- if(fase!=hack_reading)
- printf(in_Italia?"Errore, io voglio il floppy %d, non il %d\n":
- "Error, requested disk is number %d, not %d\n",floppy_n,this_floppy);
- else
- printf("Wrong disk !\n");
- }
- else{
- char pt[6];
- my_itoa((long)floppy_n,&pt[1]);
- pt[0]=strlen(pt+1);
- ParamText(in_Italia?"\pLeggo questo disco invece del ":
- "\pMust I use this disk rather than disk ",pt,"\p ?",PNS);
- if( chiedi_su_questo(this_floppy,previous_sect,NULL) ){
- floppy_n=this_floppy;
- sect_n = previous_sect;
- ultimo_header_valido=false;
- sect_n++; /* per tener conto anche del settore 0 */
- return;
- }
- }
- }
- }
- }
-
- short inserzione_assicurata(mesg,accept_any_disk)
- /* as aspetta_inserzione but it never returns without a new disk inserted,
- it rather calls raise_error: if a file is being saved, it asks for confirmation,
- since an error closes all open files and hence truncates them */
- char*mesg;
- Boolean accept_any_disk;
- {
- /* come aspetta inserzione ma non ritorna al chiamante, usando longjmp, se il disco
- non viene affatto inserito ed Å accettabile che non lo sia */
- int i;
- do{
- i=aspetta_inserzione(mesg);
- if(i!=0){
- if(!accept_any_disk){
- ParamText(in_Italia?"\pVa bene lasciare il file incompleto ?":
- "\pDo you want to let this file uncompleted ?",PNS,PNS,PNS);
- if(my_modal_dialog(130,titoli,2)==1)
- raise_error();
- else
- return i;
- }
- else
- raise_error();
- }
- if(di.is_not_initialized) diskEject();
- }
- while(di.is_not_initialized);
- return 0;
- }
-
-
- short bar_check_settore0(previous_sect,verbose)
- /* examine if sector 0 is a valid bar volume header */
- sector_t *previous_sect;
- Boolean verbose;
- {
- int disk_n;
- long offset,exp_check;
-
- leggi_settore(0,disk_buffer);
- if(check_error()) return err_code;
-
- offset=untar_number(((barh_type*)disk_buffer)->size,-1);
-
- if(my_atoi(((barh_type*)disk_buffer)->volume_num,&disk_n) ) disk_n = -1;
-
- if(((barh_type*)disk_buffer)->bar_magic[0]!= 'V' ||
- ((barh_type*)disk_buffer)->bar_magic[1] != 0 || disk_n==-1 || offset==-1){
- if(verbose){
- beep_in_foreground();
- printf(in_Italia?"Questo non Å un disco in formato bar\n":"Not a bar disk !\n");
- }
- return -1;
- }
- *previous_sect=(offset+511)/512; /* Å un multiplo di 512, ma non fidarsi Å meglio */
- /* se fosse previous_sect = 0 (se l'ultimo settore di un disco Å un header...) allora
- permettere di estrarre anche questo file !!*/
-
- if( unbar_checksum(disk_buffer,0,&exp_check) <0 ){
- if(verbose){
- printf("Bad disk header checksum");
- if(expert_mode){
- if( print_if_string(" (got %s expected ",((barh_type*)disk_buffer)->chksum,8))
- printf("%lo)",exp_check);
- }
- printf("\n");
- if( ! ignore_errors){
- raise_error();
- return -1;
- }
- }
- else
- return -1;
- }
- return disk_n;
- }
-
- static Boolean chiedi_su_questo(this_floppy,previous_sect,name)
- /* presents the modal dialog "must I continue on this disk ?" */
- sector_t previous_sect;
- char*name;
- {
- enum {dOK=1,dNo,dHalt};
- switch(my_modal_dialog(129,titoli,3)){
- case dOK:
- if(this_floppy>1&§_n>0){
- printf(in_Italia?"Presenti %ld settori di completamento di "
- :"%ld sectors from ",(long)previous_sect);
- if(name==NULL)
- printf(in_Italia?"un file precedente\n":"a previous file\n");
- else
- printf("%s\n",name);
- }
- return 1;
- case dNo:
- return 0;
- case dHalt:
- raise_error();
- }
- }
-
- /*******************************/
-
- void tar_check_floppy_swap(situation)
- /* check disk swap for GNU tar or AIX tar archives.
- Many comments are identical to those in bar_check_floppy_swap, hence they were not
- translated */
- {
- /* in questa routine, floppy_n puo' valere solo 1 o 2, non vado a contare i floppy.
- Perÿ, se capita che un disco che non sia il primo abbia di nuovo un header di file
- al settore 0, devo rimetterlo ad 1 perchÄ non avrÿ l'header di continuazione
- -- floppy_n may have only two values: 1 for disks without an 'M' continuation
- header (such as the first disk) and 2 for a disk which has one (as most of the
- following disks)
- */
-
- int i,this_floppy,accept_any_disk;
- sector_t previous_sect;
- static char s1[]="Disco occupato completamente da parte di %s\n",
- s2[]="The whole disk is occupied by a part of %s\n";
-
- if(situation>0){ /* 1 => il primo settore dell'archivio;
- 0 => un altro settore richiesto da readblock (entro un file);
- -1 => un altro settore richiesto per leggere un header;
- -2 => il parametro di ingresso era 1 ma ho dovuto espellere
- il disco perchÄ non buono */
- floppy_n=1;
- previousFormat=tar_unknown;
- ultimo_header_valido=false;
- sect_n=0;
- if(fase==hack_listing){
- if(next_header_for_AIX!=-1){
- sect_n=next_header_for_AIX; /* hacking() has already checked that's a good
- starting sector */
- return;
- }
- accept_any_disk= true;
- this_floppy=tar_check_settore0(true);
- if(this_floppy<0)
- raise_error();
- if(this_floppy==2){
- sect_n= (untar_number(((tarh_type*)disk_buffer)->size,false)+511)>>9;
- if(sect_n>0)printf("%ld sectors from %s", /* se il file Å lunghissimo non
- Å vero, non sono tutti qui ! Lo scrivo sotto */
- (long)sect_n,((tarh_type*)disk_buffer)->name);
- sect_n++;
- }
- if(hasVheader) sect_n++;
- if(sect_n>=sectors_on_floppy){
- printf(" (Partly on next disk)\n");
- longjmp(main_loop,-1);
- }
- printf("\n");
- return;
- }
- accept_any_disk= true;
- }
- else if(sect_n<sectors_on_floppy || !drive_number)
- return;
- else{
- accept_any_disk= listonly || situation!=0;
- floppy_n=2;
- sect_n -= sectors_on_floppy; /* in modalitê normale si ottiene sempre 0, in listonly no !*/
- if(situation==-1 && sect_n==0){ /* in questo caso l'header di continuazione non c'Å
- -- if the last sectors of a file happens to be written in the last
- sector of a disk, the following disk has not a continuation header, hence
- it looks like the first disk of another archive */
- floppy_n=1;
- /*sect_n--; no, chiedo comunque il 0, sta poi alla gestione dell'inserzione
- prossimo disco saltare eventuali header */
- }
- if(fase==hack_listing){
- if(sect_n>0) printf("(%ld sectors on next disk)\n",(long)sect_n);
- printf("\nEnd of disk\n");
- longjmp(main_loop,-1);
- }
- }
-
- for(;;){
- if(situation<=0){ /* il primo disco Å giê dentro, gli altri bisogna sostituirli a
- ciÿ che Å dentro... */
- if(file_aperto) raise_error();
- diskEject();
- if(tar_version==tar_unknown &&previousFormat==tar_unknown){
- ParamText(in_Italia?
- "\pQuesto Å un archivio multidisco ?":
- "\pIs this a multivolume archive ?",PNS,PNS,PNS);
- assegna_tar_version();
- }
- if(tar_version==tar_singlevol && previousFormat==tar_unknown)
- error_message(in_Italia?"Errore: raggiunta la fine del disco\n":
- "Error: end of disk was reached\n");
-
- do{
- i=inserzione_assicurata(situation==-2 ? (
- in_Italia?"\pInserisci il disco in formato tar":
- "\pInsert the disk in tar format") :
- (in_Italia?"\pInserisci il prossimo disco tar":
- "\pInsert next tar disk"), accept_any_disk);
- }
- while(i!=0);
- }
- else
- situation=-2; /* non posso lasciare 1 se resto entro il ciclo */
-
- if(situation!=-2 && (previousFormat==tar_AIX ||
- previousFormat==tar_unknown && tar_version==tar_AIX) ){
- /* an AIX disk has no header, hence I can't be sure that it's the right
- disk, I must rely on the current setting of the option */
- previousFormat=tar_AIX;
- this_floppy=2;
- previous_sect=0;
- if(sect_n >= sectors_on_floppy){ /* la solito, puÿ succedere per un List */
- sect_n -= sectors_on_floppy;
- printf(in_Italia? s1:s2,((tarh_type*)ultimo_header)->name);
- continue; /* the disk must be ejected, continuing on next one */
- }
- /* if(qualche controllo che sia veramente AIX.....) */
- return;
- }
-
- this_floppy= tar_check_settore0(true);
- previous_sect=0;
-
- if(floppy_n==2 && this_floppy==2 &&
- verifica_nome(hasVheader,&previous_sect)!=noErr ) this_floppy=3; /* any value
- which can't be equal to floppy_n */
- if(this_floppy==floppy_n){ /* Å stato inserito il disco voluto */
-
- if(hasVheader) sect_n++; /* devo incrementare sect_n per saltare l'header di
- volume, ed Å pi¥ flessibile non farlo in tar_check_settore0,
- non posso farlo se il disco non viene accettato e l'ultima
- decisione su questo la prendo qui
- -- I could not do that in tar_check_settore0, since it can't
- know whether the disk is the right one or not */
- if(floppy_n==2) sect_n++; /* salto anche l'header extra... */
- avail_sectors_for_file = sectors_on_floppy;
- if(hasVheader) avail_sectors_for_file--; /* perchÄ quei settori non sono */
- if(this_floppy>=2) avail_sectors_for_file--; /*usati per il file */
- if(sect_n<sectors_on_floppy)
- return;
-
- /* puÿ capitare durante il list di un file che risulta suddiviso in pi¥
- di 2 dischi, allora chiede anche quelli intermedi ma al solo scopo di
- sapere quanti settori ci sono */
- printf(in_Italia? s1:s2,((tarh_type*)ultimo_header)->name);
- sect_n -= sectors_on_floppy; /* gli incrementi a sect_n per gli header extra
- sono giê stati effettuati OK */
- floppy_n=2;
- if(situation==-1 && sect_n==1)
- floppy_n=1;
- /* e proseguo, esattamente come se ci fosse stato un errore e fosse stato
- inserito il disco sbagliato, solo che i dati di controllo sono stati
- aggiornati a pretendere il disco successivo */
- }
- else if(this_floppy<0){
- /* printf(in_Italia ? "Il disco non Å in formato tar nÄ bar\n" :
- "Disk format is neither tar nor bar\n"); no, qualcosa viene scritto da
- bar_check_settore_zero (magari tramite check_error o untar_number) */
- if(situation==-2){
- raise_error(); /* l'utente puÿ ridare il comando senza rimetterci nulla */
- }
- else
- printf(in_Italia?"Riprova !\n":"Try again !\n"); /* disco non tar, non c'Å che riprovare... */
- }
- else{
- if(!accept_any_disk){
- beep_in_foreground();
- printf(in_Italia?"Errore, non Å il floppy successivo!\n":
- "Error, it\'s not next disk!\n");
- }
- else{
- if(this_floppy==1)
- previous_sect=0;
- else
- previous_sect= (untar_number(((tarh_type*)disk_buffer)->size,false)+511)>>9;
- if(situation==-2)
- ParamText(in_Italia?"\pInizio da questo disco ?":
- "\pMust I start from this disk ?",PNS,PNS,PNS);
- else
- ParamText(in_Italia?"\pContinuo su questo disco ?":
- "\pMust I continue on this disk ?",PNS,PNS,PNS);
- if( chiedi_su_questo(this_floppy,previous_sect,((tarh_type*)disk_buffer)->name) ){
- if(this_floppy==1){
- ultimo_header_valido=false; /* tanto gestisco subito il primo buono */
- avail_sectors_for_file=sectors_on_floppy-sect_n;
- }
- else{
- long last_size;
- copia_ultimo_header(disk_buffer,hasVheader?2:1);
- last_offset=untar_number(((tarh_type*)disk_buffer)->offset,-1);
- last_size=untar_number(((tarh_type*)ultimo_header)->size,false);
- ((tarh_type*)ultimo_header)->linkflag='\0';
- numstr (((tarh_type*)ultimo_header)->size,last_size+last_offset,12);
- }
- if(this_floppy==3) this_floppy=2;
- floppy_n=this_floppy;
- sect_n = previous_sect;
- if(hasVheader) sect_n++;
- if(this_floppy>=2) sect_n++;
- if(sect_n<sectors_on_floppy){
- if(this_floppy!=1) printf(in_Italia ? "Parte finale del file %s\n":
- "Last part of file %s\n",((tarh_type*)ultimo_header)->name);
- return;
- }
- sect_n-=sectors_on_floppy;
- if(this_floppy!=1) printf(in_Italia ? s1: s2, ((tarh_type*)ultimo_header)->name);
- }
- }
- }
- }
- }
-
- short tar_check_settore0(verbose)
- /* examine the first sector of a tar disk: either it's all zeros, or a normal
- file header, or a continuation file header. If it's a 'V' volume header, then
- check sector 1 too
- */
- Boolean verbose;
- {
- int i;
-
- hasVheader=0;
- leggi_settore(0,disk_buffer);
- if(check_error()) return err_code;
-
- if(check_all_zero(disk_buffer)) return 1; /* un archivio tar vuoto... */
- if( (i=untar_checksum(disk_buffer,-1,verbose)) < 0){
- if(i==-2||!verbose|| !ignore_errors) return -1;
- }
-
- hasVheader = ((tarh_type*)disk_buffer)->linkflag=='V';
- if(hasVheader){
- previousFormat=tar_GNU;
- disk_buffer[99]=0;
- if(verbose) printf(in_Italia?"Il nome del disco Å %s\n":
- "The disk name is %s\n",disk_buffer); /* stampa l'informazione contenuta nell'header !
- -- that's the string the user specified in the V option, plus the volume number */
- leggi_settore(1,disk_buffer);
- if(check_error()) return err_code;
- if(check_all_zero(disk_buffer)) return 1;
- if( (i=untar_checksum(disk_buffer,-1,verbose&&!ignore_errors)) < 0){
- if( (i==-2 || !ignore_errors) && verbose ) return -1;
- /* verbose is false if and only if I were called by identify format,
- which only wants to know if this is a tar archive, not if its sector 1
- is corrupted */
- }
- }
-
- if(((tarh_type*)disk_buffer)->linkflag=='M'){
- previousFormat=tar_GNU;
- return 2;
- }
- else
- return 1;
- }
-
- static OsErr verifica_nome(volume_header,previous_sect)
- /* verify a continuation header against the normal header which was in the previous disk */
- sector_t *previous_sect;
- {
- long last_size,sizeleft,expected_offset;
-
- if(!ultimo_header_valido){
- *previous_sect=0;
- return noErr; /* non ho visto il disco precedente, perchÄ
- sono alla prima inserzione */
- }
- sizeleft=untar_number(((tarh_type*)disk_buffer)->size,false);
- last_size=untar_number(((tarh_type*)ultimo_header)->size,false);
- *previous_sect=(sizeleft+511)>>9;
- if( strcmp(ultimo_header,disk_buffer) ) return -1; /* il nome non coincide */
-
- expected_offset=last_offset+((long)avail_sectors_for_file<<9);
- last_offset=untar_number(((tarh_type*)disk_buffer)->offset,false);
- /*printf("<%ld %ld,%ld,%ld,%ld>",(long)avail_sectors_for_file,expected_offset,last_offset,last_size,sizeleft);*/
-
- if(expected_offset!=last_offset || last_size-last_offset!=sizeleft) return -1;
-
- if(volume_header)
- (*previous_sect)++;
-
- return noErr;
- }
-
-
- void close_or_del_out_file()
- {
- if(devo_chiudere_out){
- if(del_incompl){
- reinit_hd_buffering();
- cancella_file_aperto(pb.ioParam.ioRefNum);
- }
- else{
- flush_hd_buffer();
- PBCloseSync(&pb);
- }
- devo_chiudere_out=false;
- }
- }
-
- /******************************************************************/
-
- int filter_conf(EventRecord*);
- static int filter_conf(theEvent)
- EventRecord*theEvent;
- {
- /* the standard filter for semimodal makes CR equivalent to button 1,
- this filter makes esc equivalent to button 2 */
- #define ESC 27
- if(theEvent->what==keyDown&&(char)theEvent->message==ESC)
- return 2;
- return 0;
- }
-
-
- void check_confirmation()
- /* handles the confirm saves dialog */
- {
- /* il nome del file DEVE stare in tarh.name, formato C
- -- the file name MUST be a C string in tarh.name
- */
- static Point wPos={-1,-1};
- static char *t_ita[]= {"\pSalva","\pNon salvare","\pSalva tutto","\pSalta tutto"};
- char buffer[120];
-
- if(!confirm_saves||all_listonly||fase==hack_reading||
- fase==hack_listing||fase==selected_reading || file_aperto>ff_tarbar )
- return;
- else{
- int item;
- enum {cdSave=1,cdSkip,cdSaveAll,cdSkipAll};
-
- strcpy(buffer,"File\312"); /* spazio non interrompibile
- -- non-breakable space: if the file name is long,
- breaking between lines here is not a wise thing */
- strcat(buffer,tarh.name);
-
- item=semimodalDialog(136,&wPos,filter_conf,t_ita,4,c2pstr(buffer),NULL,NULL,teJustLeft,true);
-
- listonly= item==cdSkip || item==cdSkipAll;
- if(item==cdSaveAll || item==cdSkipAll)
- set_skip_all(1);
- }
- }
-
- void check_conf_dir(dname)
- char*dname;
- {
- /* in confirm saves directories are extracted only if they already existed.
- OK, that seems the opposite of any logical thing, but when extracting, for example,
- dir/file if dir does not exist it's created. Hence, if I wish to extract files
- which go to that directory it will be created anyway, but I should warn the user
- before placing them in a directory which already existed (that could cause a
- chaotic mix of files). The simplest way to do that warning is calling create_directory...
- */
- if(!confirm_saves||all_listonly||fase==hack_reading||
- fase==hack_listing||fase==selected_reading)
- return;
- {
- CInfoPBRec cinfo;
- int i;
- cinfo.dirInfo.ioNamePtr= c2pstr(dname);
- #ifdef USA_CURRVREFN
- cinfo.dirInfo.ioVRefNum=curr_vrefnum;
- #else
- cinfo.dirInfo.ioVRefNum=0;
- #endif
- cinfo.dirInfo.ioFDirIndex=0;
- cinfo.dirInfo.ioDrDirID=0;
- listonly= PBGetCatInfoSync(&cinfo)!=noErr;
- p2cstr(dname);
- }
- }
-
- /********************************/
- void my_itoa(val,buffer)
- register long val;
- char *buffer;
- {
- char buf[14];
- Boolean nega;
- register char *p=&buf[13];
- if(nega= (val<0) )
- val= -val;
- *p='\0';
- do{
- *--p ='0'+(int)(val%10);
- val /= 10;
- }
- while(val>0);
- if(nega) *--p='-';
- strcpy(buffer,p);
- }
-
- static short isMacBin2(buf)
- /* checks whether the MacBinary header is a MacBinary II header;
- returns 0 for non-MacBinary II
- 1 for Macbinary II
- -1 for an unknown (future) release of MacBinary II that suntar can't decode,
- -2 for CRC error
- */
- register unsigned char *buf;
- {
- extern short current_crc;
- register int i;
- /* can't declare a pointer to binh_type since it's misaligned by one byte */
- if(buf[122]<129 || buf[123]<129) return 0;
- if(buf[123]>129) return -1;
- current_crc=0;
- for(i=0;i<124;i++)
- CalcCRC(buf[i]);
- CalcCRC(0);
- CalcCRC(0);
- if( current_crc != *(short*)&buf[124]) return -2;
- return 1;
- }
-
- void clear_unused_fields()
- {
- /* leggere documentazione su MacBinary II, ma non azzero busy perchÄ
- nel System 7 ha cambiato significato
- -- the file macbinary2-standard.txt, reporting the decisions of the people
- who met to set the standard, explains:
- >All Finder flags and information would be uploaded, however, a downloading
- >program should clear the Finder flag bits of
- > 0 - Set if file/folder is on the desktop (Finder 5.0 and later)
- > 1 - bFOwnAppl (used internally)
- > 8 - Inited (seen by Finder)
- > 9 - Changed (used internally by Finder)
- > 10 - Busy (copied from File System busy bit)
-
- >Also, fdLocation and fdFldr should be zeroed
-
- Bit Meaning (from Technical Note 40)
- 0 Set if file/folder is on the desktop (Finder 5.0 and later)
- 1 bFOwnAppl (used internally)
- 2 reserved, currently unused
- 3 reserved, currently unused
- 4 bFNever (never SwitchLaunch) (not implemented)
- 5 bFAlways (always SwitchLaunch)
- 6 Set if application is shared and is opened read-only (128K ROM only)
- 7 Set if file should be cached (not implemented)
- 8 Inited (seen by Finder)
- 9 Changed (used internally by Finder)
- 10 Busy (copied from File System busy bit)
- 11 NoCopy (not used in 5.0 and later, formerly called BOZO)
- 12 System (set if file is a system file)
- 13 HasBundle
- 14 Invisible
- 15 File Locked
-
- However, in System 7 bit 10 means "hasCustomIcon" and it's better to preserve it.
- It's unfortunate that the MacBinary standard did not include a field for "version
- of Finder which created it", now that different versions of the Finder use the same bits
- for different purposes: luckily, if that file does have a custom icon its resource
- fork contains a 'ICN#' resource with ID -16455.
- And bit 15 should not be cleared according to the standard, but in System 7 it means
- "is an alias" and it's correct to clear it when transferring an old file to
- system 7, if the file does not contain an 'alis' resource.
- As a result, I MUST examine the resource fork of the file if either bit 10 or 15
- are set.
- Bit 11 is now "is stationery pad": it's better to preserve it anyway, since the old
- meaning is obsolete since Finder 5.0, there is no particular contents to check for
- and the user may change it by a Get Info
- Bit 12 was "is System file" and is now "Name locked": since it would be useless
- to download an old system file to a machine with System 7, under System 7 it's
- better to preserve it, but under system 6 ?
- */
-
- macbinh.finfo.fdFlags &= ~0x303;
- *(long*)&macbinh.finfo.fdLocation=0;
- macbinh.finfo.fdFldr=0;
-
- if(macbinh.finfo.fdFlags & 0x8400){
- if(macbinh.rflen==0 ||
- !(macbinh.finfo.fdFlags & 0x400)&&(macbinh.dflen>0||macbinh.rflen>4096) )
- /* an alias file has no data fork and is not very big */
- macbinh.finfo.fdFlags &= ~0x8400;
- else{
- unsigned char name[64];
- int refnum,oldvRefNum,oldres;
- SetResLoad(false); /* it should save the old status to restore
- it, but it should never be false... */
- if(GetVol (&name,&oldvRefNum)!=noErr) oldvRefNum=0;
-
- SetVol(NULL,pb.fileParam.ioVRefNum);
- oldres=CurResFile();
- refnum= OpenResFile(pb.fileParam.ioNamePtr);
- if(refnum==-1)
- macbinh.finfo.fdFlags &= ~0x8400; /* clear both flags */
- else{
- if(macbinh.finfo.fdFlags & 0x8000){ /* alias bit */
- if(! Count1Resources ('alis') )
- macbinh.finfo.fdFlags &= ~0x8000;
- else if(!gHasResolveAlias){
- ParamText(in_Italia?
- "\pQuesto file Å un alias, solo il System 7 puÿ utilizzarlo":
- "\pThis file is an alias, only System 7 knows how to use it",PNS,PNS,PNS);
- my_alert();
- }
- }
- if(macbinh.finfo.fdFlags & 0x400){ /* "has custom icon" bit */
- Handle h = Get1Resource('ICN#',-16455);
- if(h!=NULL)
- ReleaseResource(h);
- else
- macbinh.finfo.fdFlags &= ~0x400;
- }
- CloseResFile(refnum);
- }
- if(oldvRefNum) SetVol (&name,oldvRefNum);
- UseResFile(oldres);
- SetResLoad(true);
- }
- }
- }
-
-
- static void make_badname(fname,name)
- /* creates a new name for a file which caused a bad name error (some
- versions of UNIX have a max name length which is greater than that of the HFS,
- and it happens to see public domain Mac files with a very long name which
- would not be legal on a Macintosh)
- */
- char*fname,*name;
- {
- static int bad_names=0;
- static char BadNameFolder[]=":bad names folder:";
- register char *p1,*p;
- register int i;
-
- strcpy(fname,BadNameFolder);
- my_itoa((long)++bad_names,&fname[sizeof(BadNameFolder)-1]);
-
- p1= name;
- p=&p1[(unsigned char)*p1]; /* last character of original name */
- p1=p1+1;
- while(*p==':' && p>p1) p--; /* typically, at the end of a Mac name there may be */
- i = *p!=':'; /* 0-1 */
- while(p>p1 && p[-1]!=':' && i<=24){
- p--; i++;
- }
- p1=fname + strlen(fname);
- if(i){
- *p1++ =' ';
- *p1++ ='-';
- while(i-- >0){
- if(*p>=' ' && *p< 127) *p1++ = *p;
- p++;
- }
- }
- *p1='\0';
-
- printf(in_Italia?"%p: nome non valido, cambiato in %s\n":
- "%p: bad name, renamed to %s\n",name,fname);
- }
-
- static Boolean too_long(fname)
- register char *fname;
- {
- register int i=0;
- while(*fname!='\0'){
- if(*fname==':')
- i=0;
- else
- if(++i>31) return true;
- fname++;
- }
- return false;
- }
-
- static Boolean is_gif_file(fsize)
- long fsize;
- {
- /* checks whether the file begins with 'GIF'
- (really, the signature is GIF87a or GIF89a, but when there will be a GIF9xa
- it will be better to recognize it too)
- (This "privilege" is because gif files are very popular, and since they are
- a non-Mac format usually they are downloaded as data only so they have no
- type and creator)
- */
- static char h[]={'G','I','F'};
- if (fsize>100 && !strncmp(h,disk_buffer,(size_t)3) &&
- disk_buffer[3]>='0' && disk_buffer[3]<='9' &&
- disk_buffer[4]>='0' && disk_buffer[4]<='9' &&
- disk_buffer[5]>='a' && disk_buffer[5]<='z') return true;
- return false;
- /* since a gif file has an internal signature, it's better to rely on it
- than to look at the name...
- int l;
- l=strlen(tarh.name);
- return (l >4 && !ci_strcmp(&tarh.name[l-4],".gif" );
- */
- }
-
- void print_type_creator(t,c)
- OSType t,c;
- {
- /* sorry, my printf doesn't accept %.4s */
- printf(in_Italia?"tipo=\'":"type=\'");
- print_chars(&t,4);
- printf(in_Italia?"\' creatore=\'":"\' creator=\'");
- print_chars(&c,4);
- printf("\'");
- }
-
- void print_one_date(cdate,message)
- long cdate;
- char*message;
- {
- char p[20];
- printf("%s",message);
- IUDateString(cdate,abbrevDate,p);
- printf("%p ",p);
- IUTimeString(cdate,true,p);
- printf("%p",p);
- }
-
-
-
- void cancella_file_aperto(ioRefNum)
- short ioRefNum;
- {
- OSErr i;
- get_openfile_location(ioRefNum);
- PBCloseSync(&pb);
- pb.fileParam.ioNamePtr=mac_file_name;
- pb.fileParam.ioVRefNum=openfile_vrefnum;
- pb.fileParam.ioDirID=openfile_dirID;
- i=PBHDeleteSync(&pb);
- /*printf("delete=%d\n",i);*/
- }
-
- short crea_e_controlla(tempattrib)
- /* crea un file ma fa anche qualche controllo...;
- ritorna come create_file
- -- creates a file and does some checking; returns as create_file
- */
- Boolean tempattrib;
- {
- char copia[100];
- short i;
-
- mcopy(copia,tarh.name,100);
- for(;;){
- if( create_file(tarh.name,fsWrPerm,tempattrib)) return 1; /* Cancel... */
-
- i=controlla_spazio(macbinh.dflen,macbinh.rflen);
- if(i==1) return 1;
- if(i==2){
- /* restore the name, in case it was changed (e.g. if the file existed...) */
- mcopy(tarh.name,copia,100);
- /* and retry... */
- }
- else{
- if(macbinh.finfo.fdFlags&0x4000){ /* bit "invisible" */
- ParamText(in_Italia?"\pFile invisibile: lo rendo visibile ?":
- "\pInvisible file: make it visible ?",PNS,PNS,PNS);
- if(my_modal_dialog(130,titoli,2)==1)
- macbinh.finfo.fdFlags &= ~0x4000;
- }
- return 0;
- }
- }
- }
-
-
- short controlla_spazio(dlen,rlen)
- long dlen,rlen;
- /* checks that the destination volume has enough free space;
- returns 0 if OK, 1 if not enough space and the user canceled
- the operation, 2 if not enough space and the user selected another
- volume for continuing
- */
- {
- long l;
- int vrefnum;
- Boolean prima_volta=true;
- short i;
-
- for(;;){
- if(pb.fileParam.ioVRefNum)
- vrefnum=pb.fileParam.ioVRefNum;
- else{
- volumeParam param;
- char buffer[50];
- param.ioNamePtr=buffer; /* or NULL, but what happens if some system bug
- (or a bad INIT) does not check for NULLs ? */
- if(PBGetVolSync (¶m) !=noErr) return;
- vrefnum=param.ioVRefNum;
- }
- if(GetVInfo (0,NULL,&vrefnum,&l)!=noErr)
- return 0; /* the error could be not fatal, it's better to hope that
- anything is OK, this routine is only a check to prevent
- some errors but suntar still works without checking for
- space... */
- /*printf("l=%ld\n",l);*/
- if( ((dlen+511)&~511L) + ((rlen+511)&~511L) <= l )
- return 0; /* space is enough */
- else{
- if(!prima_volta){
- ParamText(in_Italia?"\pSpazio ancora insufficiente,\rproseguo comunque ?":
- "\pSpace is still insufficient,\rcontinue anyway ?",PNS,PNS,PNS);
- if(my_modal_dialog(130,titoli,2)==1)
- return 0;
- /* else continue */
- }
- do{
- i=semimodalDialog(141,NULL,NULL,t1,3,
- in_Italia?"\pSpazio su disco insufficiente: puoi voler cancellare\r\
- qualcosa prima di cliccare su un bottone\roppure puoi abortire il comando":
- "\pInsufficient space on destination volume: you\r\
- might wish to delete something before clicking a\r\
- button or you may abort the current command",
- NULL,NULL,teJustCenter,true);
- if(i==2){
- /* continue elsewhere */
- select_directory();
- cancella_file_aperto(pb.ioParam.ioRefNum);
- if(reply.good) return 2;
- }
- else if(i==3)
- return 1;
- else{
- /* continue here: maybe the user deleted some files */
- prima_volta=false;
- }
- }
- while(i==2); /* if I'm here, it was cancelled */
- }
- }
- }
-
- #if V_122
- /* old versions used till suntar 1.2.2 */
-
- void conferma_invisibili()
- {
- if(macbinh.finfo.fdFlags&0x4000){ /* bit "invisible" */
- ParamText(in_Italia?"\pFile invisibile: lo rendo visibile ?":
- "\pInvisible file: make it visible ?",PNS,PNS,PNS);
- if(my_modal_dialog(130,titoli,2)==1)
- macbinh.finfo.fdFlags &= ~0x4000;
- }
- }
-
- void controlla_spazio(dlen,rlen)
- long dlen,rlen;
- /* checks that the destination volume has enough free space */
- {
- long l;
- int vrefnum;
- if(pb.fileParam.ioVRefNum)
- vrefnum=pb.fileParam.ioVRefNum;
- else{
- volumeParam param;
- char buffer[50];
- param.ioNamePtr=buffer; /* or NULL, but what happens if some system bug
- (or a bad INIT) does not check for NULLs ? */
- if(PBGetVolSync (¶m) !=noErr) return;
- vrefnum=param.ioVRefNum;
- }
- if(GetVInfo (0,NULL,&vrefnum,&l)==noErr){
- /*printf("l=%ld\n",l);*/
- if( ((dlen+511)&~(long)0x1FF) + ((rlen+511)&~(long)0x1FF) > l){
- beep_in_foreground();
- error_message(in_Italia?"Spazio su disco insufficiente\n":
- "Insufficient space on destination volume\n");
- }
- }
- }
- #endif
-
-
-
- static short gestisci_nome_doppio(fname,name,fpb)
- /* handle a duplicate name error */
- char *fname,*name;
- register FileParam *fpb;
- {
- int err,i,l=strlen(fname);
- WDPBRec param;
-
- settori_passati=0;
- beep_in_foreground();
- /*if(fase==hack_reading){
- error_message("File already existing !\n");
- }
- */
- /* ci sono due modi di procurarsi le informazioni da mettere nelle due variabili
- che dicono dove lo standard file deve posizionarsi inizialmente:
- 1) come nel programma Apple, creare una WD con PBOpenWD e poi fare PBGetWDInfo
- 2) non creare alcuna WD, ma allora bisogna usare PBGetCatInfo per avere il DirID
- e PBGetWDInfo (sulla WD preesistente...) per avere il vRefNum del volume
- (cioÅ, della root)
- per ora seguo il metodo 1, che funziona, ma quando avrÿ tempo preferirei passare al 2
- -- I must oblige SFPutFile to show the folder where the file had to go, and that's
- done by setting two low memory variables. But I must get the information in the
- right format, and the simplest way to do that requires the creation of a working
- directory (the other way looks even easier, but currently it does not work, at least
- not always)
- */
-
- for(i=l-1;i>=0 && fname[i]!=':';i--)
- ;
- #if 1
- /* ora i Å -1 o punta ad un ':' */
- if(i<=0){ /* un : in testa non conta... */
- err=GetVol (name,¶m.ioVRefNum);
- /* name[0]=0; */
- }
- else{
- mcopy(&name[1],fname,i+1); /* cosô tronco al : (che resta compreso)...*/
- name[0]=i+1;
-
-
- #ifdef USA_CURRVREFN
- param.ioVRefNum=curr_vrefnum;
- #else
- param.ioVRefNum=0;
- #endif
- }
- param.ioNamePtr=(unsigned char*)name;
- param.ioWDProcID=signature;
- param.ioWDDirID=0;
- err=PBOpenWDSync(¶m); /* ho bisogno di una WD perchÄ doForceDirectory
- Å fatta a quel modo... */
- doForceDirectory(¶m);
- register_WD(param.ioVRefNum);
-
- #else
- /* that's the second way: in this form it's worse, but, damn it, why should I be
- obliged to do two calls to get both the dirID and the root vRefNum ? */
-
- /* se mi decido per questo, togliere doForceDirectory da StdFile.c ! */
- /*printf("giusti = %d %ld \n",-SFSaveDisk,CurDirStore);*/
- {CInfoPBRec cinfo;
-
- printf("fname=%s, name=%p\n",fname,name);
-
- cinfo.dirInfo.ioNamePtr= (unsigned char*)name;
- cinfo.dirInfo.ioVRefNum=curr_vrefnum;
- cinfo.dirInfo.ioFDirIndex=0;
- cinfo.dirInfo.ioDrDirID=0;
- PBGetCatInfoSync(&cinfo); /* get the dirID */
-
- /*printf("result= %d attr=%x\n",cinfo.dirInfo.ioResult,cinfo.dirInfo.ioFlAttrib);
- printf("cose che vedo =%d %ld %d\n",cinfo.dirInfo.ioVRefNum,cinfo.dirInfo.ioDrDirID,
- cinfo.dirInfo.ioFRefNum);*/
- /*cinfo.dirInfo.ioDrDirID contiene il DirId giusto, ma il vRefNum giusto
- non sta in nessun campo !*/
- param.ioNamePtr = NULL;
- param.ioVRefNum = 0;
- param.ioWDIndex = 0;
- param.ioWDProcID = 0;
-
- PBGetWDInfoSync(¶m); /* get the vrefnum */
- /* ioVRefNum Å quello che voglio, ma ovviamente non avendogli dato il path da lô
- non posso avere alcun DirID, e anche a dare il path sembra che non si ottenga */
- /*printf("stavolta ho %d %ld\n",param.ioVRefNum, param.ioWDDirID);*/
-
- CurDirStore = cinfo.dirInfo.ioDrParID or cinfo.dirInfo.ioDrDirID ???????;
- SFSaveDisk = -param.ioVRefNum;
- }
- #endif
- /*printf("settato %d %ld\n",SFSaveDisk,CurDirStore);*/
-
- c2pstr(&fname[i+1]);
-
- while( SFPut_con_pausa(&fname[i+1])){
- handle_pause();
- accept_abort_command();
- }
- if(!reply.good) return 1;
-
- fpb->ioNamePtr = reply.fName;
- fpb->ioVRefNum = reply.vRefNum;
- fpb->ioFVersNum = 0;
- err=PBCreateSync(fpb) ;
- pStrcpy(fname,reply.fName); /* devo salvarlo prima se no lo perdo */
- if(err==dupFNErr){
- if(open_overwrite(reply.fName,reply.vRefNum,&(fpb->ioFRefNum))==noErr) /* ok il
- codice che dice che esiste, siamo dopo un SFPutFile, ma bisogna
- troncare il file... */
- FSClose(fpb->ioFRefNum);
- }
-
- else if(err!=noErr)
- pbsyserr(fpb);
-
- p2cstr(fname);
- fpb->ioVRefNum = reply.vRefNum;
- fpb->ioFVersNum = 0;
- fpb->ioFDirIndex = 0;
- return 0;
- }
-
- static void skip_macbinII(size)
- int size;
- {
- while(size>0){
- if(readblock(&tarh,128)) raise_error();
- size-=128;
- }
- }
-
-
- void get_openfile_location(ioRefNum)
- int ioRefNum;
- {
- /* get the current name and location of the file, so that it may be
- reopened even if the user has moved or renamed it */
-
- FCBPBRec param;
-
- fillmem(¶m,0,sizeof(param));
- param.ioVRefNum=0;
- param.ioRefNum=ioRefNum;
- param.ioFCBIndx=0;
-
- param.ioNamePtr=mac_file_name;
- if((err_code=PBGetFCBInfoSync(¶m))==noErr){
- openfile_vrefnum=param.ioFCBVRefNum;
- openfile_dirID=param.ioFCBParID;
- /*pStrcpy(mac_file_name,param.ioNamePtr);*/
- }
- else
- openfile_dirID=0;
- /*
- printf("err=%d(%d) ioV=%d ioR=%d volRN=%d dirID=%ld name=%lx:%p\n",
- err_code,param.ioResult,param.ioVRefNum,param.ioRefNum,param.ioFCBVRefNum,param.ioFCBParID,
- param.ioNamePtr,param.ioNamePtr);
- */
-
- }
-
- /************* end of routines by Speranza **************************/
-
- /************* Routines obtained by modifying ones by Zacharias **********
- (that is, modifying their interface and purpose and not only their code)
- **********************************************************************/
-
-
- /********************* hqx *******************************/
-
- void untar_hqx (fsize)
- long fsize;
- {
- register char *cp;
- jmp_buf savebuf;
- int i;
-
- hqx_length=fsize;
- mcopy(&savebuf,&main_loop,sizeof(jmp_buf));
- if((i=setjmp(main_loop))<0 ){
- mcopy(&main_loop,&savebuf,sizeof(jmp_buf));
- if(i==-2) /* raise_hqx_error... */
- return;
- raise_error();
- }
-
- if( hqx_header() ){ /* con risultati in macbinh
- -- results in macbinh */
- mcopy(&main_loop,&savebuf,sizeof(jmp_buf));
- return;
- }
-
- for(cp = tarh.name+strlen(tarh.name); cp != tarh.name && cp[-1] != ':'; --cp);
- mcopy(cp, macbinh.name, macbinh.nlen);
- cp[macbinh.nlen] = '\0';
-
- disable_autoflush();
- if(expert_mode&&file_aperto<=ff_tarbar) printf(s_spazi); /*per allinearsi col [sector xxxx] stampato
- presumibilmente alla riga prima
- -- to align with the [sector xxxx] printed in the previous line */
- printf(in_Italia ? "Contenente" : "Containing");
- printf(" %p (", &macbinh.nlen);
- printf("data %ld+res %ld bytes)", macbinh.dflen, macbinh.rflen);
- if(fase==hack_listing){
- printf(" ");
- print_type_creator(macbinh.finfo.fdType,macbinh.finfo.fdCreator);
- }
- printf("\n");
- enable_autoflush();
-
- filecreator=filetype='????';
-
- #ifdef V_122
- if (!listonly && ! create_file(tarh.name,fsWrPerm,true)) {
- controlla_spazio(macbinh.dflen,macbinh.rflen);
- conferma_invisibili();
- #if 0 /* Think C Marker.... */
- }
- #endif
- #else
-
- if(!listonly && ! crea_e_controlla(true) ){
- #endif
- write_hqx_fork(512,macbinh.dflen);
-
- pb.ioParam.ioVersNum = 0;
- pb.ioParam.ioPermssn = fsWrPerm;
- pb.ioParam.ioMisc = 0;
- if((pb.fileParam.ioDirID=openfile_dirID)!=0){
- pb.ioParam.ioVRefNum=openfile_vrefnum;
- pb.ioParam.ioNamePtr=mac_file_name;
- }
- if( PBHOpenRFSync(&pb)) pbsyserr(&pb);
-
- devo_chiudere_out=true;
-
- write_hqx_fork(512,macbinh.rflen);
-
- set_binhex();
- if(hqx_length > 16) /* tanto per dare un valore...
- -- well, due to multiple buffering of data that variable
- does NOT hold the number of remaining chars, at least if
- those chars are before the final ':' (the buffering does
- not go past that ':'); on the other hand I don't check for
- the presence of that ':', and I've read that
- "Some old programs produced an extra exclamation mark (!)
- immediately before the final colon", hence I don't want to
- check that no extra chars are present.
- */
- printf(in_Italia ? "%ld caratteri dopo i dati Binhex sono stati ignorati\n" :
- "%ld characters follow BinHex data: ignored\n", hqx_length);
- }
- hqx_end_of_file();
- mcopy(&main_loop,&savebuf,sizeof(jmp_buf));
- }
-
- void write_hqx_fork(chunk_size,size)
- short chunk_size;
- long size;
- {
- short bytes_to_read;
-
- reinit_hd_buffering();
- current_crc=0;
- while (size) {
- bytes_to_read= chunk_size;
- if(bytes_to_read>size) bytes_to_read=size;
- read_hqx(&tarh,bytes_to_read);
- size -= bytes_to_read;
- if(write_hd((char*) &tarh, bytes_to_read) ) pbsyserr(&pb);
- }
- if(flush_hd_buffer()) pbsyserr(&pb);
- get_openfile_location(pb.ioParam.ioRefNum);
- PBCloseSync(&pb);
- devo_chiudere_out=false;
- check_CRC();
- }
-
- void write_pit_fork(chunk_size,size)
- short chunk_size;
- long size;
- {
- int bytes_to_read;
-
- reinit_hd_buffering();
-
- while (size) {
- bytes_to_read= chunk_size;
- if(bytes_to_read>size) bytes_to_read=size;
- get_pit_bytes(&tarh,bytes_to_read);
-
- size -= bytes_to_read;
- if(write_hd((char*) &tarh, bytes_to_read)) pbsyserr(&pb);
- }
- if(flush_hd_buffer()) pbsyserr(&pb);
- get_openfile_location(pb.ioParam.ioRefNum);
- PBCloseSync(&pb);
- devo_chiudere_out=false;
- }
-
-
- void set_binhex ()
- /* set the file informations from the BinHex header, almost identical to setmacbin */
- {
- FileParam fpb;
- fpb.ioFVersNum = 0;
- fpb.ioFDirIndex = 0;
-
- if((fpb.ioDirID=openfile_dirID)!=0){
- fpb.ioVRefNum=openfile_vrefnum;
- fpb.ioNamePtr=mac_file_name;
- }
- else{
- fpb.ioVRefNum=pb.fileParam.ioVRefNum;
- fpb.ioNamePtr=pb.fileParam.ioNamePtr;
- }
-
- if (PBHGetFInfoSync(&fpb)) pbsyserr(&fpb);
-
- clear_unused_fields();
- mcopy(&fpb.ioFlFndrInfo, &macbinh.finfo, 10); /* type,creator e flags ma non il resto*/
- if(file_aperto==ff_binhex){
- fpb.ioFlCrDat=macbinh.cdate;
- fpb.ioFlMdDat=macbinh.mdate;
- }
- else if(file_date!=-1)
- fpb.ioFlCrDat = fpb.ioFlMdDat = file_date + UNIXTIME;
- fpb.ioDirID=openfile_dirID; /* PBHSetFInfo writes the FlNum return value in that field ! */
- if (PBHSetFInfoSync(&fpb)) pbsyserr(&fpb);
- }
-
-
- short untar_checksum(buffer,do_error,verbose)
- register unsigned char *buffer;
- Boolean verbose;
- {
- register int i;
- register long chksum;
- long hchksum;
- #define tar_chksum_offset 148 /* (tarh.checksum-(char*)&tarh) */
- hchksum = untar_number(((tarh_type*)buffer)->chksum,do_error);
- if(hchksum==-1){
- if(verbose) printf("Empty header checksum\n");
- return -2; /* testata non tar */
- }
- chksum= ' ' * 8; /* nel calcolo del checksum, il campo checksum era sostituito
- da spazi */
- for (i=0; i < tar_chksum_offset; ++i)
- chksum += (unsigned char)*buffer++;
- for (i+=8,buffer+=8; i < sizeof(tarh); ++i)
- chksum += (unsigned char)*buffer++;
-
- if (chksum == hchksum) return 0; /* tutto OK */
- if(verbose){
- printf("Bad header checksum ");
- if(expert_mode){
- if(((tarh_type*)disk_buffer)->linkflag!='V')
- if(print_if_string("(got %s expected ",((tarh_type*)disk_buffer)->chksum,8))
- printf("%lo)",chksum);
- }
- printf("\n");
- }
- return -1;
- }
-
-
- short chkmacbin (fsize,relax_test)
- /* tests whether the file is MacBinary */
- long fsize;
- int relax_test;
- {
- char buf[128];
-
-
- if (fsize == 0) return 0;
- if (readblock(buf,128)) /* devo leggerlo comunque, per uniformitê */
- raise_error();
- if (fsize < 128){
- unget_block();
- return 0;
- }
- mcopy(&macbinh, &buf[1], sizeof(macbinh));
-
- /* in the MacBinary format, the data and resource forks should occupy an
- integer number of 128 bytes blocks (the size of XMODEM blocks): however,
- some programs save space by not extending the two forks, hence I must
- accept both standard ad "compact" formats
- */
-
- if (buf[0] == 0 && macbinh.zero == 0 && macbinh.nlen < 64 && macbinh.nlen > 0 )
- if(macbinh.dflen >= 0 && macbinh.rflen >= 0 ){
- short i=isMacBin2(buf);
- long expected_length_compact=macbinh.dflen +macbinh.rflen + 128L;
- long expected_length_standard=macbinsz(macbinh.dflen) + macbinsz(macbinh.rflen) + 128L;
- if( (MacBinaryII=i>0)){
- /* The MacBinary || standard defines fields for the sizes of extra header info
- and of comment:
- > Offset 099-Word, length of Get Info comment to be sent after the resource
- > fork (if implemented).
- > *Offset 120-Word, Length of a secondary header. If this is non-zero,
- > Skip this many bytes (rounded up to the next multiple of 128)
- > This is for future expansion only, when sending files with
- > MacBinary, this word should be zero.
- we've never seen files using those fields, nor versions of MacbinaryII
- bigger than 129, but it would not be honest to declare that suntar is
- MacBinaryII compatible without supporting them
- */
- mcopy(&mbIIsec_head_len,&macbinh.headlen,2);
- mbIIsec_head_len = macbinsz(mbIIsec_head_len);
- expected_length_standard += macbinh.gilen + mbIIsec_head_len;
- /* I believe that a MBII file can't be "compact", and surely it can't
- be compact and have comment info or secondary header */
- }
- if(relax_test ||
- (fsize==expected_length_compact||fsize==expected_length_standard) &&
- i>=0 ){
- notTrueMacBinary = fsize<expected_length_standard;
- if(relax_test==ff_c_macbin&&fsize<expected_length_standard)
- notTrueMacBinary=true;
-
- if( MacBinaryII )
- macbinh.finfo.fdFlags = macbinh.finfo.fdFlags&0xFF00 |
- (unsigned char) macbinh.extra_fflags;
- /* else
- macbinh.finfo.fdFlags = macbinh.finfo.fdFlags&0xFF00; NO:
- The first MacBinary standard did not store bits 7-0, stating that
- the byte following bits 15-8 should be zeroed. But mtar did not zero it, and maybe
- it's the same for other programs (but NOT for BinHex5.0), anyway suntar does not check
- for them to be zero, and in a MacBinary (not MacBinary II) files which has a nonzero
- value in that byte it believes that it's containing the correct values of bits 0-7.
- */
- return 1;
- }
- }
- unget_block();
- return 0;
- }
-
- void setdata ()
- /* set modification date = creation date */
- {
- FileParam fpb;
- fpb.ioFVersNum = 0;
- fpb.ioFDirIndex = 0;
-
- if((fpb.ioDirID=openfile_dirID)!=0){
- fpb.ioVRefNum=openfile_vrefnum;
- fpb.ioNamePtr=mac_file_name;
- }
- else{
- fpb.ioVRefNum=pb.fileParam.ioVRefNum;
- fpb.ioNamePtr=pb.fileParam.ioNamePtr;
- }
- if (PBHGetFInfoSync(&fpb)==noErr){ /* not to be able to set the date is NOT a big error */
- fpb.ioFlMdDat = fpb.ioFlCrDat;
- fpb.ioDirID=openfile_dirID;
- PBHSetFInfoSync(&fpb);
- }
- }
-
- /******* end of routines by Gail Zacharias, rewritten by Speranza ********/
-
- /***************** start of routines by Gail Zacharias **********/
-
-
- void untar ()
- {
-
- long exp_check;
- short i;
- if(expert_mode) print_sector_n(sect_n);
- sect_n++;
- more_in_bytes=0; /* forse non necessario, ma prudente */
-
- mcopy(&tarh,&disk_buffer,sizeof(tarh));
- if ( (i=untar_checksum(&disk_buffer[0],1,true)) != 0 ){
- if(i==-2 || !ignore_errors) raise_error();
- if(i==-1) printf(s_spazi);
- }
- copia_ultimo_header(disk_buffer,sect_n); /* sect_n Å giê stato incrementato */
- last_offset=0; /* l'offset Å 0 perchÄ non Å un header 'M' */
-
- file_date= untar_number(&tarh.mtime,false);
-
- switch (tarh.linkflag) {
- case '\0': case '0': case '7':
- is_file:
- if (tarh.name[strlen(tarh.name)-1] == '/')
- untar_directory();
- else
- untar_file(untar_number(tarh.size,1));
- break;
- case '1': case '2':
- untar_link();
- break;
- case '5':
- untar_directory();
- break;
- case 'M':
- if(untar_number(&tarh.offset,-1)==0) goto is_file; /* the file header
- was in the last sector of previous disk, hence this continuation
- header is followed by the whole contents of the file, so it may
- be extracted starting from here: all informations are available... */
- /* else continue */
- case 'V':
- printf("Bad use of GNU extensions\n");
- raise_error();
- break;
- default:
- printf("Unknown header type (octal %o)\n", tarh.linkflag);
- raise_error();
- }
- }
-
-
- void untar_file (fsize)
- long fsize;
- {
- int nLF;
- short isText;
- short isBinHex;
- Boolean is_gif=false;
- long cdate=untar_number(bar_archive?((barh_type*)disk_buffer)->mtime:
- ((tarh_type*)disk_buffer)->mtime,-1);
-
- disable_autoflush();
- if(listonly!=2) printf("File %s", tarh.name); /* 2 means Get File Info, which has
- already printed the file name and size */
- if(!bar_archive){
- next_header_for_AIX = sect_n + ((fsize+511)>>9);
- if(next_header_for_AIX<sectors_on_floppy)
- next_header_for_AIX=-1;
- else
- next_header_for_AIX-=sectors_on_floppy;
- }
- if(sect_n==sectors_on_floppy){
- if(fase==hack_listing){
- printf(" (%ld bytes, on next disk)\n",fsize);
- /* for expert list of AIX archives, I must let sect_n point to next
- file header... */
- enable_autoflush();
- longjmp(main_loop,-1);
- }
- else
- start_of_line(); /* ci saranno i messaggi di cambio disco...
- --some messages are arriving... */
- enable_autoflush();
- }
- if ( file_aperto==ff_macbin || file_aperto<=ff_tarbar && chkmacbin(fsize,0)){
- /*printf(" ");
- if(fase==hack_listing)*/
- if(listonly!=2) printf(" (%ld bytes) ",fsize);
- if(notTrueMacBinary) printf("compact ");
- printf("MacBinary");
- if(MacBinaryII) printf(" II");
- printf("\n");
- if(expert_mode&&file_aperto<=ff_tarbar) printf(s_spazi);
- printf(in_Italia ? "Contenente":"Containing");
- printf(" %p (", &macbinh.nlen);
- printf("data %ld+res %ld bytes)", macbinh.dflen, macbinh.rflen);
- if(fase==hack_listing){
- printf("\n%s",s_spazi);
- print_type_creator(macbinh.finfo.fdType,macbinh.finfo.fdCreator);
- if(cdate!=-1) print_one_date(cdate+UNIXTIME,in_Italia?" creato ":" created "); /* di solito in expert mode non
- bado alla lingua, ma poi stampo una stringa del toolbox che lo fa...*/
- }
- printf("\n");
- enable_autoflush();
-
- check_confirmation(); /* se ora andassi in non_convertire, nessun problema... */
- unix_to_mac(tarh.name);
-
- untar_macbin(fsize);
- }
- else{
- if(listonly!=2) printf(" (%ld bytes)",fsize); /* queste scritte devono stare prima della
- check_confirmation, ma del resto i test sulle conversioni vanno dopo
- e questo complica un po' le cose */
- if(file_aperto<=ff_tarbar)
- isBinHex= fsize>=20 && is_hqx_name();
- else
- isBinHex=file_aperto==ff_binhex;
- if(isBinHex){
- printf(in_Italia?" testo BinHex":" BinHex text");
- binary=0; /* per il caso poi non vada convertito */
- }
- else{
- if(file_aperto<=ff_tarbar){
- isText=isASCII(fsize,&nLF); /* grazie a chkmacbin, disk_buffer Å pieno... */
- binary= ! (isText>0 && nLF>0);
- }
- else{
- isText= file_aperto==ff_ASCII; /* I'm not here in that case, but
- who knows what may happen in the future... */
- binary=false;
- }
-
- if (isText>0 && !binary)
- printf(in_Italia?" testo ASCII con LF":" ASCII text using LF");
- else if(isText>0)
- printf(in_Italia?" testo ASCII":" ASCII text");
- else if((is_gif=is_gif_file(fsize)))
- printf(" CompuServe GIF");
- }
- if(fase==hack_listing)
- if(cdate!=-1) print_one_date(cdate+UNIXTIME,in_Italia?" creato ":" created ");
-
- printf("\n");
- enable_autoflush();
-
- check_confirmation(); /* durante il quale posso anche cambiare preferences */
- unix_to_mac(tarh.name);
-
- if( !(disable_binhex&1) && isBinHex==1 &&
- !(non_convertire&&file_aperto<=ff_tarbar && !listonly) ){
- untar_hqx(fsize);
- }
- else{
- if(is_gif ){
- filecreator= gif_creator;
- filetype='GIFf';
- }
- else{
- filecreator= (isText>0||isBinHex) ? text_creator : '????';
- filetype= (isText||isBinHex) ? 'TEXT' : '????';
- }
- untar_data(fsize);
- }
- }
- }
-
-
- void untar_data (fsize)
- long fsize;
- {
-
- #ifdef V_122
- if (!listonly && ! create_file(tarh.name,fsWrPerm,false)) {
- controlla_spazio(fsize,0L);
- #if 0 /* Think C Marker.... */
- }
- #endif
- #else
- macbinh.dflen=fsize; /* crea_e_controlla expects some data here... */
- macbinh.rflen=0;
- macbinh.finfo.fdFlags=0;
- if(!listonly && ! crea_e_controlla(false) ){
- #endif
- pb.ioParam.ioReqCount = sizeof(tarh);
- notTrueMacBinary=true; /* writefork tests it... in practice its value is
- irrelevant, since extra bytes in the last sector are skipped anyway */
- writefork(512, fsize, binary || non_convertire&&file_aperto<=ff_tarbar);
- if(save_modi_date) setdata();
- }
- else
- skip_file(fsize);
- }
-
- void untar_macbin (fsize)
- long fsize;
- {
- register char *cp;
-
- for(cp = tarh.name+strlen(tarh.name); cp != tarh.name && cp[-1] != ':'; --cp);
- mcopy(cp, macbinh.name, macbinh.nlen);
- cp[macbinh.nlen] = '\0';
- if(non_convertire&&file_aperto<=ff_tarbar){
- unget_block(); /* i 128 bytes di intestazione... */
- filetype='TEXT';
- filecreator='BnHq'; /* il creator di BinHex 5.0 */
- untar_data(fsize);
- return;
- }
-
- filecreator=filetype='????'; /* temporaneamente, ma in caso di errore resta cosô */
-
- #ifdef V_122
- if (!listonly && ! create_file(tarh.name,fsWrPerm,true)) {
- controlla_spazio(macbinh.dflen,macbinh.rflen);
- conferma_invisibili();
- #if 0 /* Think C Marker.... */
- }
- #endif
- #else
-
- if(!listonly && ! crea_e_controlla(true) ){
- #endif
- if(MacBinaryII) skip_macbinII(mbIIsec_head_len); /* secondary header... */
- writefork(128,macbinh.dflen, 1);
- pb.ioParam.ioVersNum = 0;
- pb.ioParam.ioPermssn = fsWrPerm;
- pb.ioParam.ioMisc = 0;
- if((pb.fileParam.ioDirID=openfile_dirID)!=0){
- pb.ioParam.ioVRefNum=openfile_vrefnum;
- pb.ioParam.ioNamePtr=mac_file_name;
- }
- if( PBHOpenRFSync(&pb)) pbsyserr(&pb);
- devo_chiudere_out=true;
- pb.ioParam.ioReqCount = 128;
- writefork(128,macbinh.rflen, 1);
- if(MacBinaryII) skip_macbinII(macbinh.gilen); /* comment */
- setmacbin();
-
- end_of_file();
- }
- else
- skip_file(fsize);
- }
-
- void writefork(chunk_size, size, binp)
- short chunk_size;
- long size;
- Boolean binp;
- {
- short bytes_to_read;
-
- reinit_hd_buffering();
-
- while (size) {
- bytes_to_read= chunk_size;
- if(notTrueMacBinary && bytes_to_read>size) bytes_to_read=size;
- if (readblock(&tarh, bytes_to_read))
- raise_error();
- if(bytes_to_read>size) bytes_to_read=size; /* in true MacBinary, I may read
- from the archive more bytes than I write to the file */
- size -= bytes_to_read;
- if (!binp){
- register int i;
- register char*p=tarh.name;
- for (i=bytes_to_read; --i >= 0 ; p++)
- if (*p == LF) *p = CR;
- }
-
- if(write_hd((char*) &tarh, bytes_to_read)) pbsyserr(&pb);
- }
- if(flush_hd_buffer()) pbsyserr(&pb);
-
- get_openfile_location(pb.ioParam.ioRefNum);
-
- PBCloseSync(&pb);
- devo_chiudere_out=false;
- }
-
- void setmacbin ()
- /* set the file informations from the MacBinary header */
- {
- FileParam fpb;
- fpb.ioFVersNum = 0;
- fpb.ioFDirIndex = 0;
-
- if((fpb.ioDirID=openfile_dirID)!=0){
- fpb.ioVRefNum=openfile_vrefnum;
- fpb.ioNamePtr=mac_file_name;
- }
- else{
- fpb.ioVRefNum=pb.fileParam.ioVRefNum;
- fpb.ioNamePtr=pb.fileParam.ioNamePtr;
- }
-
- if (PBHGetFInfoSync(&fpb)) pbsyserr(&fpb);
- clear_unused_fields();
- mcopy(&fpb.ioFlFndrInfo, &macbinh.finfo, 10);
- fpb.ioFlCrDat = macbinh.cdate;
- fpb.ioFlMdDat = macbinh.mdate;
-
- fpb.ioDirID=openfile_dirID;
- if (PBHSetFInfoSync(&fpb)) pbsyserr(&fpb);
- }
-
- void untar_directory ()
- {
- int len = strlen(tarh.name);
-
- if (len && tarh.name[len-1] != '/') {
- tarh.name[len] = '/';
- tarh.name[len+1] = '\0';
- }
- if(!bar_archive){
- if(sect_n<sectors_on_floppy)
- next_header_for_AIX=-1;
- else
- next_header_for_AIX=sect_n-sectors_on_floppy;
- }
- printf("Directory %s\n", tarh.name);
- unix_to_mac(tarh.name);
- if (!tarh.name[1] ) return;
- check_conf_dir(tarh.name);
- if(!listonly) create_directory(tarh.name);
- }
-
-
-
- /* fname may contain a filename after the last ':', it will be ignored */
- void create_directory (fname)
- char *fname;
- {
- FileParam fpb;
- char name[128], *cp, *bp;
- OSErr i;
-
- cp = fname + strlen(fname);
- for (bp = fname; *bp == ':'; ++bp);
-
- fpb.ioNamePtr = (StringPtr) name;
- do {
- while (cp[-1] != ':') --cp;
- if (cp == bp){ printf("%s - Bad directory name\n", fname); raise_error(); }
- strncpy(name+1, fname, name[0] = --cp - fname);
- retry:
-
- #ifdef USA_CURRVREFN
- fpb.ioVRefNum = curr_vrefnum;
- #else
- fpb.ioVRefNum = 0;
- #endif
-
- fpb.ioDirID = 0;
- } while ((i=PBDirCreateSync(&fpb)) == dirNFErr || i==fnfErr);
- if(fpb.ioResult == dupFNErr){
- beep_in_foreground();
- if(fase==hack_reading){
- printf("Folder already existing\n");
- fpb.ioResult=noErr;
- }
- else{
- char buffer[100];
- short item;
- do{
- strcpy(buffer,tarh.name);
- c2pstr(buffer);
- item = semimodalDialog(137,NULL,NULL,t1,2,
- in_Italia?"\pLa cartella\312":"\pThe folder\312",buffer,in_Italia?
- "\p\resiste giê: prima di cliccare su un bottone puoi\rvoler cambiar nome o spostare quella preesistente":
- "\p\ralready exists: before clicking a button, you might\rwish to rename, move or delete the old one",
- teJustLeft,true);
- if(item!=1){
- select_directory();
- if(reply.good) goto retry;
- }
- }
- while(item!=1);
- fpb.ioResult=noErr; /* e continua senza preoccuparti */
- }
- }
- if (fpb.ioResult)pbsyserr(&fpb);
- while (1) {
- while (*++cp != ':') if (!*cp) return;
- strncpy(name+1, fname, name[0] = cp - fname);
-
- #ifdef USA_CURRVREFN
- fpb.ioVRefNum = curr_vrefnum;
- #else
- fpb.ioVRefNum = 0;
- #endif
-
- fpb.ioDirID = 0;
- if (PBDirCreateSync(&fpb)) pbsyserr(&fpb);
- }
- }
-
- short create_file (fname,perm,tempattrib)
- char *fname;
- int perm;
- Boolean tempattrib;
- /* ritorna 1 se, causa nome doppio o bad name, il salvataggio Å stato annullato
- -- returns 1 if, due to a duplicate name, the user clicked on Cancel
- */
- {
- /*
- this routine was heavily modified by us (Speranza).
- OK, it's incoherent that for duplicate names a dialog appears
- while bad names are renamed without asking to the user...
- */
- FileParam fpb;
- char name[128];
- extern SysEnvRec gMac;
- Boolean opened_OK=false;
-
- fillmem(&fpb,0,sizeof(fpb));
- fpb.ioNamePtr = c2pstr(strcpy(name, fname));
-
- while(!opened_OK){
-
- #ifdef USA_CURRVREFN
- fpb.ioVRefNum = curr_vrefnum;
- #else
- fpb.ioVRefNum = 0;
- #endif
-
- fpb.ioFVersNum = 0;
- if(!PBCreateSync(&fpb)) {
- #ifdef USA_CURRVREFN
- fpb.ioVRefNum = curr_vrefnum;
- #else
- fpb.ioVRefNum = 0;
- #endif
-
- fpb.ioFVersNum = 0;
- fpb.ioFDirIndex = 0;
- opened_OK=true;
- }
- else{
- /*printf("creo %p con %d\n",name,fpb.ioResult);*/
- /* The new network software from Apple has a bug: with System 7.0 and 7.01,
- when the "File Sharing Extension" is active (on our Mac LC which is not
- connected to a network), PBCreate returns paramErr (error in parameter block)
- when it should return bdNamErr (bad name) and fnfErr (file not found) when
- it should return dirNFErr (folder not found).
- Since fnfErr was not expected, we handle it as a dirNFErr. However, thinking
- that any paramErr is a misnamed bdNamErr would be dangerous, hence we check that
- the name contains a subname which is longer than 31 characters (since unix_to_mac
- translates any non-ASCII char and checks the placing of ':', there should
- be no other possible cause for a bad name) before translating the err code.
- */
- if(fpb.ioResult==paramErr && too_long(fname) ) fpb.ioResult=bdNamErr;
- if(fpb.ioResult == dupFNErr){
- if( gestisci_nome_doppio(fname,name,&fpb) ) return 1; /* annullato...*/
- opened_OK=true;
- }
- else if(fpb.ioResult== bdNamErr){
- /* check_foreground(); no, ma... non lo so */
- SysBeep(5);
- make_badname(fname,name); /* o anche qui proporre di cambiare nome !*/
- fpb.ioNamePtr = c2pstr(strcpy(name, fname));
- }
- else if (fpb.ioResult == dirNFErr || fpb.ioResult==fnfErr){ /* System 7
- sometimes returns fnfErr when the folder does not exist */
- create_directory(fname);
- fpb.ioNamePtr = c2pstr(strcpy(name, fname));
- }
- else{
- pbsyserr(&fpb);
- }
- }
- }
-
- fpb.ioNamePtr = c2pstr(strcpy(name, fname));
- if (PBGetFInfoSync(&fpb)) pbsyserr(&fpb);
- fpb.ioNamePtr = c2pstr(strcpy(name, fname));
- fpb.ioFlFndrInfo.fdType = filetype;
- fpb.ioFlFndrInfo.fdCreator = filecreator;
- if(file_aperto==ff_binhex)
- fpb.ioFlCrDat =macbinh.cdate; /* non posso assegnare ora anche la data
- di modifica, perchÄ sto per modificare il file: in macbinary e binhex
- lo faccio dopo, per il .info pazienza... Poi, Å bene avere un'indicazione
- che il salvataggio di un file non Å stato completato (l'icona appare solo
- alla fine...)
- --there is no reason to set the modification date now, since I'm
- going to modify the file ! That date is modified after closing the
- file, but not for the .info file. Also type and creator are set only
- when closing the file, so that the icon appears only when the file is
- completed and may be opened by the application.
- */
- else if(file_date!=-1 )
- fpb.ioFlCrDat = file_date + UNIXTIME;
-
- if (PBSetFInfoSync(&fpb)) pbsyserr(&fpb);
-
- pStrcpy(mac_file_name,fpb.ioNamePtr);
- pb.ioParam.ioVRefNum = fpb.ioVRefNum;
- pb.ioParam.ioNamePtr = mac_file_name;
- pb.ioParam.ioVersNum = 0;
- pb.ioParam.ioPermssn = perm;
- pb.ioParam.ioMisc = 0;
- pb.ioParam.ioRefNum = 0;
- if (PBOpenSync(&pb)) pbsyserr(&pb);
- devo_chiudere_out=true;
- return 0;
- }
-
-
- void untar_link ()
- {
- /*unix_to_mac(tarh.name);
- unix_to_mac(tarh.linkname);*/
- printf("Link %s -> %s%s\n", tarh.name, tarh.linkname,
- listonly?"":in_Italia?" (ignorato)":" (ignored)");
- if(!bar_archive){
- if(sect_n<sectors_on_floppy)
- next_header_for_AIX=-1;
- else
- next_header_for_AIX=sect_n-sectors_on_floppy;
- }
- }
-
- /* Convert Unix pathname to a mac pathname. Do not allow absolute
- names - "/foo/bar/baz" is treated as if it were "foo/bar/baz".
- */
- void unix_to_mac (name)
- char *name;
- {
- char buf[102];
- register unsigned char *cp = name, *bp = buf, *op,c;
- *bp++ = ':';
- op = bp;
- while (1) {
- if (cp[0] == '/') ++cp;
- else if (cp[0] == '.' && cp[1] == '/') cp += 2;
- else if (cp[0] == '.' && cp[1] == '.' && cp[2] == '/') {
- if (op == bp) *bp++ = ':', op = bp;
- else for (--op; op != bp && op[-1] != ':'; --op);
- cp += 3;
- }
- else {
- while (c=*cp, c!=0 && c != '/'){
- if(c== ':')
- c= '/';
- else if(c=='_' && !pres_underscore)
- c=' ';
- else if(c<' '||c>126) c=0xC9; /* '╔' */
- *op++ = c;
- cp++;
- }
- if (!*cp++) break;
- *op++ = ':';
- }
- }
- *op = '\0';
- strcpy(name, buf);
- }
-
- #if 0
- /* Name is the user-specified name, file is the actual tarred file */
- void match_file (name, file)
- char *name, *file;
- {
- char *cp;
- if (!strdiff(name, file)) return 1;
- if ((cp = strrchr(file, ':')) && !strdiff(cp+1, name)) return 1;
- if (name[strlen(name)-1] == ':' && strdiff(name, file) >= 0) return 1;
- return 0;
- }
-
- /* return 0 if the same, 1 if s1 is a substring of s2, -1 otherwise */
- strdiff (s1, s2)
- char *s1, *s2;
- {
- while (*s1) {
- if (*s1 != *s2) {
- char c1 = *s1;
- if ('A' <= c1 && c1 <= 'Z') c1 |= 0x20;
- if ('a' > c1 || c1 > 'z' || c1 != (*s2 | 0x20)) return -1;
- }
- ++s1, ++s2;
- }
- return (*s2 ? 1 : 0);
- }
- #endif
-
- long untar_number (cp,doerror)
- char *cp;
- {
- int neg = 0;
- long num = 0;
- while (*cp == ' ') cp++;
- if (*cp == '-') neg++, cp++;
- if('0' <= *cp && *cp <= '7'){
- while ('0' <= *cp && *cp <= '7') num = (num<<3) + (*cp++ - '0');
- if (neg) num = -num;
- }
- else
- cp="A"; /* per fargli dare errore
- -- in order to force the error */
- if(*cp!='\0'&&*cp!=' '){
- if(doerror>=0)
- printf(in_Italia?"Testata non in formato %car !\n":
- "Error: not a %car header !\n",bar_archive ? 'b' : 't');
- if(doerror>0)
- raise_error();
- else
- return -1L;
- }
- return num;
- }
-
- void pbsyserr (fpb)
- ioParam *fpb;
- {
- int err = fpb->ioResult;
- char *name = (char*) fpb->ioNamePtr;
- p2cstr(name);
- start_of_line();
- if (err == fnfErr) printf("%s - File not found\n", name);
- else if (err == nsvErr) printf("%s - No such volume\n", name);
- else if (err == tmfoErr) printf("%s - Too many files open\n", name);
- else if (err == permErr) printf("%s - Permissions error\n", name);
- else if (err == dupFNErr) printf("%s - Duplicate filename\n", name);
- else if (err == eofErr) printf("%s - Premature end of file\n", name);
- else if (err == dskFulErr) printf("%s - Disk full\n", name);
- else printf("%s - Error #%d\n", name, err);
- raise_error();
- }
-