Due file sono il medesimo file? 

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... 

Non ci ho capito niente! Ricominciamo...