Le fichier exécutable Unix est remplacé par Document lors du transfert via les sockets

Je suis sur Mac OSX. J’ai écrit deux programmes pour transférer un “fichier exécutable Unix” d’un endroit à un autre (programme serveur vers programme client). Voici le code:

Code côté serveur:

fileDescriptor = open(reqMsg.filename, O_RDONLY); if (fileDescriptor > 0) while ((msgLength = read(fileDescriptor, content, MESSAGESIZE)) > 0) send(data.remoteSocketDes, content, msgLength, 0); 

Code côté client:

 fileDescriptor = open(data.filename, O_CREAT|O_WRONLY); if (fileDescriptor > 0) while ((msgLength = recv(localSocketDes, content, MESSAGESIZE, 0)) > 0) write(fileDescriptor, content, msgLength); 

La taille et le contenu du fichier sont exactement les mêmes mais le type de fichier est passé de “Fichier exécutable Unix” à “Document”. Finalement, je ne peux pas l’exécuter depuis l’endroit où il a été copié.

Remarque: le code fonctionne correctement pour les fichiers “.txt”.

Sous Unix (et les variantes telles que OS X), le facteur déterminant à savoir si vous pouvez exécuter une commande à partir de l’invite du shell est de savoir si le fichier que vous essayez d’exécuter possède le bit d’ execute (et vous êtes autorisé à l’exécuter).

Pour gérer cela depuis l’invite de commande, utilisez simplement chmod +x {file} , mais si vous savez que le fichier entrant est un exécutable (peut-être en testant d’abord l’expéditeur et en envoyant les informations dans le préambule), vous pouvez coder votre programme de réception pour définir le bit d’exécution si nécessaire en utilisant chmod() :

 chmod( data.filename, permission) 

Où vous calculez la permission en exécutant les bits d’exécution avec le umask par défaut, comme ceci:

 mode_t mask = umask (0); umask (mask); mode_t permission = mask | S_IXUSR | S_IXGRP | S_IXOTH; 

Notez que cela définira les permissions en écriture pour le monde, le groupe et le propriétaire, ce qui peut ne pas être souhaitable. Notez également que vous DEVEZ appeler umask la deuxième fois, car le premier appel est destructif.

La propriété “executable” d’un fichier est fonction de ses permissions, pas de son contenu. La simple copie de son contenu dans un autre fichier ne préservera pas cette propriété.

Si vous souhaitez conserver cela, vous devrez sérialiser les permissions du fichier d’origine (que vous pouvez obtenir en utilisant stat() sur le fichier), les envoyer au client et les appliquer au nouveau fichier (en utilisant chmod() , ou en passant les permissions à open() ).

Si la préservation de métadonnées de fichiers telles que celle-ci est importante, vous pouvez également envisager de préserver les durées de création et de modification ainsi que les atsortingbuts étendus du fichier.