md5sum ajoute «\» à la somme de contrôle

22

Pourquoi md5sum ajoute-t-il "\" devant la somme de contrôle lors de la recherche de la somme de contrôle d'un fichier avec "\" dans le nom?

$ md5sum /tmp/test\\test
\d41d8cd98f00b204e9800998ecf8427e  /tmp/test\\test

La même chose est notée pour tous les autres utilitaires.

jsaji
la source
Juste pour référence, les autres *sumutilitaires (de la même famille que md5sum, e, g, sha1sumetc.) dans GNU coreutils font de même.
Kusalananda
Je ne vois pas ce comportement, quelle est la version de l'utilitaire:md5sum --version
Kiwy
@Kusalananda Cela peut être spécifique à la version coreutils; sur CentOS 7 cksumne fonctionne pas; par exemple% cksum test\\test 3915528286 4 test\test
Stephen Harris
@StephenHarris C'est probablement parce qu'il cksums'agit d'un utilitaire POSIX et de ses spécifications. ne le permet pas.
Kusalananda

Réponses:

33

Ceci est documenté , pour Coreutils md5sum:

Si le fichier contient une barre oblique inverse ou une nouvelle ligne, la ligne est démarrée avec une barre oblique inverse et chaque caractère problématique du nom de fichier est échappé par une barre oblique inverse, rendant la sortie sans ambiguïté même en présence de noms de fichiers arbitraires.

(le fichier est le nom du fichier, pas le contenu du fichier).

b2sum, sha1sumEt les différents outils SHA-2 se comportent de la même manière que md5sum. sumet cksumne le faites pas; sumest uniquement fourni pour la compatibilité descendante (et ses ancêtres ne produisent pas de sortie entre guillemets), et cksumest spécifié par POSIX et n'autorise pas ce type de sortie.

Ce comportement a été introduit en novembre 2015 et publié dans la version 8.25 (janvier 2016), avec l' NEWSentrée suivante :

md5sumgarantit désormais une seule ligne par fichier pour le statut sur la sortie standard, en utilisant un «\» au début de la ligne et en remplaçant les nouvelles lignes par «\ n». Cela affecte aussi sha1sum, sha224sum, sha256sum, sha384sumet sha512sum.

La barre oblique inverse au début de la ligne sert d'indicateur: les échappements dans les noms de fichiers ne sont traités que si la ligne commence par une barre oblique inverse. (Unescaping ne peut pas être le comportement par défaut: il casserait les sommes générées avec les anciennes versions de Coreutils contenant \\ou \ndans les noms de fichiers stockés.)

Stephen Kitt
la source
30
C'est dommage que quelque chose de complètement intuitif comme celui-ci ne soit pas documenté dans les manpages. (Et oui, je suis conscient que GNU veut que tout le monde lise infoplutôt leurs pages très compliquées .)
roaima
3
@msouth la barre oblique inverse au début de la ligne sert d'indicateur indiquant que les barres obliques inverses dans le nom de fichier sont des échappements; sinon vous ne sauriez pas s'il faut traiter \netc. comme des littéraux ou des échappements.
Stephen Kitt
3
@msouth si c'est au début du nom de fichier, vous n'avez aucun moyen de savoir si c'est le drapeau, ou un nom de fichier commençant véritablement par une barre oblique inverse
Stephen Kitt
1
@StephenKitt Je ne pense pas que le premier \ soit là pour la désambiguïsation. Il n'y a aucune ambiguïté si la sortie est documentée comme s'échappant toujours des barres obliques inverses et des retours à la ligne. Il est là pour que le déséchappement ne soit pas nécessaire s'il n'est pas nécessaire. Vous pouvez bien sûr débattre si cela en vaut la peine (personnellement, je pense que ce n'est pas le cas mais je ne suis pas un coreutilscontributeur).
TypeIA
1
L'expression de la documentation "chaque caractère problématique dans le nom de fichier est échappé avec une barre oblique inverse" est incorrecte; remplacer une nouvelle ligne par \nn'est pas la même chose qu'échapper une nouvelle ligne avec une barre oblique inverse!
ruakh
17

La réponse de Stephen Kitt couvre le quoi et j'essaierai de comprendre pourquoi ce changement a été mis en œuvre. Tout d'abord, quelqu'un a observé qu'un nom de fichier contenant des sauts de ligne 1 pouvait entraîner une sortie ambiguë . Par exemple, considérez cette sortie:

d41d8cd98f00b204e9800998ecf8427e  foo
25af89c92254a806b2e93fffd8ac1814  bar

Est-ce à dire qu'il y avait deux fichiers fooet / barou un seul fichier dont le nom est "foo\n25af89c92254a806b2e93fffd8ac1814 bar"? Certes, cette dernière possibilité est hautement improbable, mais elle est possible. Pour résoudre l'ambiguïté, les développeurs ont choisi d'échapper aux nouvelles lignes avec une barre oblique inverse ( \). La sortie devient alors reconnaissable. Cependant, il y a encore une ambiguïté:

764efa883dda1e11db47671c4a3bbd9e  foo\nbar

Le nom de ce fichier contient-il une nouvelle ligne ou une barre oblique inverse suivie d'un n? Pour résoudre ce problème, nous devons également échapper aux barres obliques inverses, afin que ce dernier cas devienne:

764efa883dda1e11db47671c4a3bbd9e  foo\\nbar

Enfin, ils ont choisi de faire précéder chaque ligne de sortie qui contient ces échappements d'un \\afin de permettre à un analyseur de détecter facilement si l'échappement a été effectué. Vraisemblablement, cela a été fait pour permettre aux analyseurs de gérer la sortie à la fois des versions d'échappement md5sumet des versions non d'échappement (non GNU). Le drapeau signifie également qu'il n'est pas nécessaire de procéder à un échappement «coûteux» lorsqu'il n'est pas nécessaire. Vous pouvez voir un exemple de cette analyse en action en md5sum.csoi (ligne 382 dans la version liée).


1 Par saut de ligne, j'entends le caractère \nqui est parfois aussi spécifiquement appelé saut de ligne ou LF ; voir md5sum.c.

TypeIA
la source
1
Bien sûr, le comportement sensé serait d' interdire complètement chaque fichier contenant une nouvelle ligne. Refusez simplement de les traiter.
pipe
1
@pipe c'est un comportement insensé . POSIX autorise de tels noms de fichiers, et les utilitaires refusant intentionnellement de travailler avec des fichiers légitimes sont mauvais et doivent être tués par le feu.
Ruslan
2
@Ruslan Il s'agit de protester contre POSIX pour avoir autorisé de tels noms antisociaux . Autoriser de tels caractères a probablement causé une grande quantité de problèmes de sécurité et de ballonnement de code juste pour gérer de tels cas spéciaux.
pipe
@pipe alors que LF dans un nom de fichier est en effet antisocial, les autres choses mentionnées dans votre lien sont beaucoup plus discutables - comme les espaces, les lettres non latines, etc.
Ruslan
Sur-ingénierie classique par les ingénieurs. Leçon (encore une fois): ne permettez pas aux ingénieurs de conduire les exigences. Ils trouveront le cas le plus obscur et le plus compliqué et le porteront au cas dominant et confondront tout le monde.