La domanda è formulata in modo fuorviante. Il problema che intendiamo
affrontare è, in realtà, come capire se due pathname, apparentemente
differenti, si riferiscono al medesimo file: la questione non è
banale, in quanto occorre tenere nella dovuta considerazione i default
assunti di volta in volta dal DOS. Vediamo un semplice esempio: "\PROGS\BIN\DOCS\LEGGIMI.TXT"
e "C:LEGGIMI.TXT" sono il medesimo file? La risposta
è SI, se il drive e la directory di default sono, rispettivamente,
"C:" e "\PROGS\BIN\DOCS"; NO altrimenti.
Una prima soluzione del problema consiste nell'utilizzo delle opportune
chiamate al DOS per conoscere i defaults attuali: ad esempio, i servizi
19h e 47h dell'int 21h consentono di conoscere drive e, rispettivamente,
directory di default.
Una seconda possibilità è affidarsi al sistema operativo
per ricavare dalle stringhe di partenza i due pathname completi, ad esempio
mediante il servizio 60h dell'int 21h (disponibile a partire dalla versione
3.0 del DOS), non documentata ufficialmente, ma della quale riportiamo,
per completezza, la descrizione:
INT 21H, SERV. 60H: RISOLVE UN PATH IN PATHNAME COMPLETO
Input
AH
60h
DS:SI
indirizzo della stringa contenente il pathname da risolvere
ES:DI
indirizzo del buffer (80 byte) per il pathname completo
Output
Carry
1 = errore
AX = codice dell'errore
02h = stringa non valida
03h = drive non valido
0 = altrimenti
AL = 00h
AH = '\' se il path in input si riferisce ad un file
o a una subdirectory della root; ultima lettera del path in input se esso
si riferisce alla directory di default; 00h altrimenti
Note
Il buffer puntato da ES:DI è riempito con
il pathname completo (D:\PATH\FILE.EXT); il pathname in input
è valido anche se inesistente e può contenere '.'
e "..". Tutte le lettere sono convertite in maiuscole.
Le '/' sono convertite in '\'.
Entrambi i metodi descritti rivelano un approccio di tipo "umano"
al problema; dal momento che il DOS gestisce i file mediante la File Allocation
Table e che un cluster di un disco non può appartenere
contemporaneamente a due file[1], possiamo individuare un metodo più
diretto: due pathname referenziano il medesimo file se il DOS, mediante
la propria routine FINDFIRST di scansione della directory (int
21h, servizio 4Eh), evidenzia per entrambi medesimo drive e medesimo cluster
iniziale.
La routine che presentiamo si basa sulla funzione di libreria findfirst(),
la quale utilizza una struct ffblk (definita in DIR.H)
per memorizzare quanto restituito dalla FINDFIRST del DOS: isfsame()
può pertanto essere definita una funzione di alto livello.
/********************
BARNINGA_Z! - 1990
ISFSAME.C - isfsame()
int cdecl isfsame(char *fname1,char *fname2);
char *fname1, *fname2; puntatori ai due pathnames
Restituisce: !0 se i due pathnames sono il medesimo
0 altrimenti
COMPILABILE CON TURBO C++ 1.0
tcc -O -d -c -mx isfsame.c
dove -mx puo' essere -mt -ms -mc -mm -ml -mh
********************/
#include <dir.h>
#include <dos.h> /* richiesto solo per FA_LABEL e FA_DIREC */
#define RESFIELD_LEN 21
int cdecl isfsame(char *fname1,char *fname2)
{
register int i = 0;
struct ffblk ff1, ff2;
if(!findfirst(fname1,&ff1,~(FA_LABEL | FA_DIREC)))
if(!findfirst(fname2,&ff2,~(FA_LABEL | FA_DIREC)))
for(; i < RESFIELD_LEN; i++)
if(ff1.ff_reserved[i] != ff2.ff_reserved[i])
break;
return(i == RESFIELD_LEN);
}
La findfirst() è invocata due volte, una per ogni pathname:
in entrambi i casi, l'attributo di ricerca (il terzo parametro) determina
l'esclusione delle etichette di volume e delle
directory[2]; i due pathname si riferiscono al medesimo file se i campi
ff_reserved delle due strutture sono identici.
E' necessario precisare che il contenuto del campo ff_reserved
non è ufficialmente documentato: tuttavia in esso si trovano le
informazioni necessarie al nostro scopo (drive e cluster iniziale del file)
ed altre che vengono utilizzate nelle eventuali chiamate alla findnext(),
la quale, a sua volta, si fonda sull'int 21h, funzione 4Fh (la FINDNEXT
del DOS). La posizione di tali informazioni all'interno del campo è
differente, a seconda della versione del DOS; tuttavia, la isfsame()
sopravvive sulla constatazione che, se i due pathname si riferiscono al
medesimo file, l'algoritmo si risolve nel chiamare due volte la findfirst()
per quel file, e ciò, ovviamente, sotto la stessa versione di DOS.
OK, andiamo avanti a leggere il libro...