Copie du descripteur de fichier avec son propre fichier de décalage

comment créer un nouveau descripteur de fichier à partir d'un descripteur de fichier existant de telle sorte que le nouveau descripteur ne partage pas la même structure/entrée de fichier interne dans la table de fichier? En particulier, les attributs tels que l'offset de fichier (et de préférence les permissions, le partage et les modes) ne devraient pas être partagés entre les descripteurs de fichier nouveaux et anciens.

sous Windows et Linux,dup() dupliquer le fichier descripteur, mais les deux descripteurs toujours la même structure de fichiers la table des fichiers du processus. Toute recherche sur descripteur d'ajuster la position pour les autres descripteurs.

Remarque:

j'ai depuis reçu des réponses pour Windows et Linux et j'ai ajusté la question un peu trop souvent, ce qui a rendu difficile pour les gens de répondre. Je vais ajuster mes votes et accepter la réponse la plus propre qui couvre les deux fenêtres et Linux. Mes excuses à tous, je suis encore nouveau dans le paradigme SO. Merci pour l' excellentes réponses!

15
demandé sur Matt Joiner 2009-10-21 07:28:37

3 réponses

Donc en gros, ce que vous voulez vraiment est un descripteur de fichier, et fondamentalement ouvrir le fichier de même encore, pour obtenir une part, le partage, la mode, etc. Et vous voulez le faire sur Windows (où le "descripteur de fichier" est essentiellement un objet étranger, pas quelque chose utilisé directement par l'OS ou la bibliothèque du run-time.

assez Étonnamment, il y a une façon de le faire, au moins avec MS VC++. Toutes les étapes sauf deux n'utilisent que le Win32 Le portage D'API vers d'autres compilateurs/bibliothèques devrait être assez raisonnable (je pense que la plupart des versions de fourniture de ces deux fonctions). Ceux-ci sont pour convertir un descripteur de fichier de type Unix en un gestionnaire de fichier Win32 natif, et pour convertir un gestionnaire de fichier Win32 natif en un descripteur de fichier de type Unix.

  1. Convertir le fichier descripteur de fichier natif de la poignée avec _get_osfhandle()
  2. Obtenez un nom pour le fichier avec GetFileInformationByHandleEx (FILE_NAME_INFO)1
  3. utilisez CreateFile pour ouvrir une nouvelle poignée à ce fichier
  4. créer un descripteur de fichier pour ce handle avec _open_osfhandle()

Et voilà, nous avons un nouveau descripteur de fichier faisant référence au même fichier, mais avec ses propres autorisations, la position, etc.

Vers la fin de votre question, vous faire sonner comme vous voulez aussi les "autorisations", mais qui ne semble pas faites n'importe quel vrai sens -- les permissions attachent au dossier lui-même, pas à la façon dont le dossier est ouvert, donc l'ouverture ou la réouverture du dossier n'a aucun effet sur les permissions du dossier. Si vous voulez vraiment le savoir, vous pouvez l'obtenir avec GetFileInformationByHandle, mais sachez que les permissions de fichiers dans Windows sont assez différentes des permissions de fichiers (traditionnelles) dans Unix. Unix a les permissions de propriétaire/groupe/monde sur tous les fichiers, et la plupart des systèmes ont aussi ACLs (bien qu'il y ait plus de variation dans la façon dont ils travaillent). Windows n'a pas du tout de permissions (par exemple, les fichiers sur FAT ou FAT32) ou utilise des ACLs (par exemple, les fichiers sur NTFS), mais rien qui soit vraiment équivalent aux permissions propriétaire/groupe/world traditionnelles auxquelles la plupart des gens sont habitués sur Unix.

vous utilisez peut-être" permissions " pour indiquer si le fichier était ouvert à la lecture, à l'écriture ou aux deux. Se qui est considérablement plus laid que les précédentes. Le problème est que la plupart de c'est dans la bibliothèque, pas de Win32, donc il n'y a probablement aucun moyen de le faire qui sera encore près de portable entre les compilateurs. Avec MS VC++ 9.0 SP1 (non garanti pour autre compilateur), vous pouvez faire ceci:

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

Depuis ce qui a impliqué la spéléologie, j'ai écrit un test rapide pour vérifier qu'il pourrait réellement fonctionner:

#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

Et les résultats semblent indiquer une réussite:

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

vous pouvez ensuite tester que le drapeau retourné contre _IOREAD, _IOWRT, et _IORW, qui sont définis dans stdio.H. En dépit de mes mises en garde précédentes, je dois probablement souligner que je soupçonne (bien que je ne peux certainement pas garantir) que cette partie de la Bibliothèque est assez stable, de sorte que les chances réelles de changements majeurs sont probablement assez minimes.

Dans l'autre sens, cependant, il n'y a fondamentalement aucune chance tout que ça marchera avec n'importe quelle autre bibliothèque. (mais n'est certainement pas garanti) de travailler avec les autres compilateurs qui utilisent la bibliothèque MS, tels que Intel, MinGW ou Comeau utilisant MS VC++ comme back-end. De ceux-là, je dirais que le plus susceptible de travailler serait Comeau, et le moins susceptible MinGW (mais ce n'est qu'une supposition; il y a de bonnes chances que cela ne fonctionnera pas avec l'un d'eux).

  1. nécessite le redistribuable Win32 fileID API Library
12
répondu Jerry Coffin 2009-10-27 05:16:50

donc, je recommande de lire sur ce sujet un peu plus. dup() et les fonctions connexes servent à créer une valeur dupliquée dans la table de descripteur de fichier pointant vers la même entrée dans la table de fichier ouverte. C'est but pour avoir le même décalage. Si vous appelez open(), vous allez créer une nouvelle entrée la table open file.

cela n'a aucun sens de créer un duplicata d'un descripteur de fichier et ce nouveau descripteur de fichier a un décalage différent dans la table open file (cela semble contredire ce que signifie le mot "dupliquer").

Je ne suis pas sûr de ce que votre question est réellement. Je veux dire, ce n'est pas la même chose comme un doublon. Vous avez pu lire:

/proc/self/fd/[descriptor]

et obtenir la chaîne de caractères qui a été utilisé pour ouvrir le fichier descripteur; garder à l'esprit ceci peut fournir des pièges à éviter, certains que vous avez effectivement constaté dans votre observation de l'appel open() encore une fois.

Peut-être que vous pouvez expliquer un peu plus et je peux essayer de mettre à jour aider.

2
répondu BobbyShaftoe 2009-10-21 03:59:42

pourquoi ne pas simplement ouvrir le fichier une deuxième fois avec open() ou CreateFile() sous windows? Cela vous donne à tous la liberté de différents droits d'accès et de compensation séparée.

ceci a bien sûr l'inconvénient que vous ne pouvez pas ouvrir le fichier exclusivement, mais il résout votre problème très simplement.

0
répondu RED SOFT ADAIR 2009-10-29 10:24:31