Pour gérer les noms de fichiers arbitraires (y compris ceux contenant des caractères de nouvelle ligne), l' astuce habituelle consiste à rechercher des fichiers à l'intérieur .//.
au lieu de .
. Étant donné que //
cela ne peut normalement pas se produire lors de la traversée de l'arborescence des répertoires, vous êtes sûr qu'un //
signale le début d'un nouveau nom de fichier dans la sortie find
(ou ici lsattr -R
).
lsattr -R .//. | awk '
function process() {
i = index(record, " ")
if (i && index(substr(record,1,i), "i"))
print substr(record, i+4)
}
{
if (/\/\//) {
process()
record=$0
} else {
record = record "\n" $0
}
}
END{process()}'
Notez que la sortie sera toujours séparée par des sauts de ligne. Si vous devez le post-traiter, vous devrez l'adapter. Par exemple, vous pouvez ajouter un -v ORS='\0'
pour pouvoir le transmettre aux GNU xargs -r0
.
Notez également que lsattr -R
(au moins 1.42.13) ne peut pas signaler les indicateurs de fichiers dont le chemin est plus grand que PATH_MAX (généralement 4096), donc quelqu'un pourrait masquer un tel fichier immuable en déplaçant son répertoire parent (ou l'un des composants de chemin qui mènent à , sauf lui-même car il est immuable) dans un répertoire très profond.
Une solution de contournement consisterait à utiliser find
avec -execdir
:
find . -execdir sh -c '
a=$(lsattr -d "$1") &&
case ${a%% *} in
(*i*) ;;
(*) false
esac' sh {} \; -print0
Maintenant, avec -print0
, c'est post-processable, mais si vous avez l'intention de faire quoi que ce soit avec ces chemins, notez que tout appel système sur des chemins de fichier supérieurs à PATH_MAX échouera toujours et les composants de répertoire auraient pu être renommés dans l'intervalle.
Si nous voulons obtenir un rapport fiable sur une arborescence de répertoires potentiellement accessible en écriture par d'autres, il y a quelques autres problèmes inhérents à la lsattr
commande elle-même que nous devons mentionner:
- le chemin
lsattr -R .
traverse l'arborescence des répertoires, il est soumis à des conditions de concurrence. On peut le faire descendre dans des répertoires en dehors de l'arborescence de répertoires routés .
en remplaçant certains répertoires par des liens symboliques au bon moment.
- a même
lsattr -d file
une condition de course. Ces attributs ne s'appliquent qu'aux fichiers ou répertoires standard. Alors , lsattr
fait un lstat()
premier à vérifier que le fichier est des bons types et ne open()
suivi ioctl()
pour récupérer les attributs. Mais il appelle open()
sans O_NOFOLLOW
(ni O_NOCTTY). Quelqu'un pourrait remplacer file
par un lien symbolique /dev/watchdog
par exemple entre le lstat()
et open()
et provoquer le redémarrage du système. Il faut le faire open(O_PATH|O_NOFOLLOW)
suivi fstat()
, openat()
et ioctl()
ici pour éviter les conditions de course.