Domanda

Come si può creare un nuovo descrittore di file da un descrittore di file esistente in modo tale che il nuovo descrittore non condivida la stessa struttura/voce di file interna nella tabella dei file?Nello specifico gli attributi come l'offset del file (e preferibilmente i permessi, la condivisione e le modalità) non dovrebbero essere condivisi tra i descrittori di file nuovi e vecchi.

Sia sotto Windows che sotto Linux, dup() duplicherà il descrittore di file, ma entrambi i descrittori puntano comunque alla stessa struttura di file nella tabella dei file del processo.Qualsiasi ricerca su uno dei descrittori modificherà la posizione anche per gli altri descrittori.

Nota

Da allora ho ricevuto risposte sia per Windows che per Linux e ho modificato la domanda un po' troppo spesso, il che ha reso difficile per le persone rispondere.Adeguerò i miei voti e accetterò la risposta più chiara che copre entrambi i sistemi Windows E Linux.Mi scuso con tutti, sono ancora nuovo nel paradigma SO.Grazie per le ottime risposte!

È stato utile?

Soluzione

Quindi, in pratica, ciò che vuoi veramente è ricevere un descrittore di file e sostanzialmente aprire di nuovo lo stesso file, per ottenere una posizione, condivisione, modalità separata, ecc.E vuoi farlo su Windows (dove il "descrittore di file" è fondamentalmente un oggetto estraneo, non qualcosa utilizzato direttamente dal sistema operativo O la libreria runtime.

Abbastanza sorprendentemente, ecco È un modo per farlo, almeno con MS VC++.Tutti i passaggi tranne due utilizzano solo l'API Win32, quindi il porting su altri compilatori/librerie dovrebbe essere abbastanza ragionevole (penso che la maggior parte fornisca versioni di queste due funzioni).Quelli servono per convertire un descrittore di file in stile Unix in un handle di file Win32 nativo e convertire un handle di file Win32 nativo in un descrittore di file in stile Unix.

  1. Converti il ​​descrittore di file nell'handle di file nativo con _get_osfhandle()
  2. Ottieni un nome per il file con GetFileInformationByHandleEx(FILE_NAME_INFO)1
  3. Utilizza CreateFile per aprire un nuovo handle per quel file
  4. Crea un descrittore di file per quell'handle con _open_osfhandle()

Et voilà, abbiamo un nuovo descrittore di file che fa riferimento allo stesso file, ma con i propri permessi, posizione, ecc.

Verso la fine della tua domanda, fai sembrare che tu voglia anche i "permessi", ma questo non sembra avere alcun senso: i permessi si collegano al file stesso, non al modo in cui il file viene aperto, quindi l'apertura o la riapertura del file non ha alcun effetto sulle autorizzazioni del file.Se vuoi davvero saperlo, puoi ottenerlo con GetFileInformationByHandle, ma tieni presente che i permessi dei file in Windows sono un po' diversi dai permessi dei file (tradizionali) in Unix.Unix ha permessi di proprietario/gruppo/mondo su tutti i file e la maggior parte dei sistemi ha anche ACL (sebbene ci siano più variazioni nel modo in cui funzionano).Windows non ha alcun permesso (ad esempio, file su FAT o FAT32) oppure utilizza ACL (ad esempio, file su NTFS), ma nulla che sia realmente equivalente ai tradizionali permessi proprietario/gruppo/mondo a cui la maggior parte delle persone è abituata su Unix.

Forse stai utilizzando "autorizzazioni" per indicare se il file era aperto in lettura, scrittura o entrambi.Ottenere questo è considerevolmente più brutto di qualsiasi altro dei precedenti.Il problema è che la maggior parte di esso è nella libreria, non in Win32, quindi probabilmente non c'è modo di farlo che sia anche vicino alla portabilità tra compilatori.Con MS VC++ 9.0 SP1 (non garantito per Qualunque altro compilatore) puoi fare questo:

#include <stdio.h>

int get_perms(int fd) {
    int i;
 FILE * base = __iob_func();

    for (i=0; i<_IOB_ENTRIES; i++) 
        if (base[i]._file == fd)
            return base[i]._flag;     // we've found our file
    return 0; // file wasn't found.
}

Dato che questo comportava un po' di speleologia, ho scritto un rapido test per verificare che potesse effettivamente funzionare:

#ifdef TEST
#include <io.h>

void show_perms(int perms, char const *caption) { 
 printf("File opened for %s\n", caption);
 printf("Read permission = %d\n", (perms & _IOREAD)!=0);
 printf("Write permission = %d\n", (perms & _IOWRT)!=0);
}

int main(int argc, char **argv) { 
 FILE *file1, *file2;
 int perms1, perms2;

 file1=fopen(argv[1], "w");
 perms1 = get_perms(_fileno(file1));
 fclose(file1);

 file2=fopen(argv[1], "r");
 perms2 = get_perms(_fileno(file2));
 fclose(file2);

 show_perms(perms1, "writing");
 show_perms(perms2, "reading");
 return 0;
}
#endif

E i risultati sembrano indicare il successo:

File opened for writing
Read permission = 0
Write permission = 1
File opened for reading
Read permission = 1
Write permission = 0

È quindi possibile testare il flag restituito rispetto a _IOREAD, _IOWRT e _IORW, definiti in stdio.h.Nonostante i miei precedenti avvertimenti, dovrei probabilmente sottolineare che sospetto (anche se certamente non posso garantire) che questa parte della libreria sia abbastanza stabile, quindi le possibilità reali di cambiamenti importanti sono probabilmente abbastanza minime.

Nella direzione opposta, tuttavia, non c’è praticamente alcuna possibilità affatto che funzionerà con qualsiasi altra libreria.Esso Potevo (ma certamente non è garantito che funzioni) con gli altri compilatori che utilizzano la libreria MS, come Intel, MinGW o Comeau utilizzando MS VC++ come back-end.Di questi, direi che il più probabile che funzioni sarebbe Comeau, e il meno probabile MinGW (ma è solo una supposizione;ci sono buone probabilità che non funzioni con nessuno di essi).

  1. Richiede il ridistribuibile Libreria API Win32 FileID

Altri suggerimenti

Quindi, ti consiglio di leggere un po 'di più su questo.IL dup() e le funzioni correlate servono a creare un valore duplicato nella tabella dei descrittori di file che punta alla stessa voce nella tabella dei file aperti.Questo è destinato avere lo stesso offset.Se chiami open(), creerai una nuova voce nella tabella dei file aperti.

Non ha alcun senso creare un duplicato di un descrittore di file e che il nuovo descrittore di file abbia un offset diverso nella tabella dei file aperti (questo sembra contraddire il significato della parola "duplicato").

Non sono sicuro di quale sia effettivamente la tua domanda.Voglio dire, non è la stessa cosa di un duplicato.Potresti leggere:

/proc/self/fd/[descriptor]

e ottieni la stringa utilizzata per aprire quel descrittore di file;tieni presente che ciò potrebbe comportare alcune insidie, alcune delle quali hai effettivamente notato nella tua osservazione della chiamata open() Ancora.

Forse puoi spiegare un po' di più e posso provare ad aggiornare per aiutare.

Perché non apri semplicemente il file una seconda volta con open() o CreateFile() su Windows?Ciò offre a tutti la libertà di diritti di accesso diversi e offset separati.

Questo ovviamente ha lo svantaggio che non puoi aprire il file in modo esclusivo, ma risolve il tuo problema in modo molto semplice.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top