Un androphone signale qu'il manque de mémoire de stockage (sdcard). L'analyse de l'occupation de la mémoire fait apparaître qu'un fichier appelé “.thumbnails” occupe plusieurs Go1). De nombreuses utilisatrices rapportent ce problème.
Le nom du fichier laisse entendre qu'il est dédié au stockage de vignettes pour des médias. Le cas le plus simple est celui de la vignette d'une image qui sera affichée dans plusieurs applications, particulièrement dans la galerie d'image. Or la taille de .thumbnails semble totalement décorrélée de la taille des médias réellement stockés sur l'androphone. La taille de .thumbnails peut même dépasser la taille des médias (en plein format) enregistrés dans la mémoire interne et la carte SD externe !
Selon les version d'Android et les applications utilisées, le nom et la localisation de ce conteneur encombrant peut varier. Dans le cas étudié, le fichier fautif est situé dans le répertoire “/sdcard/DCIM/.thumbnails/”. Le fichier lui-même s'appelle “.thumbdata4-1967290299”.
Comme indiqué dans l'énoncé du problème, l'objectif poursuivi est de récupérer de l'espace de stockage.
Internet regorge de propositions pour résoudre ce problème. Toutes passent par la suppression du fichier fautif. Mais cette opération semble vaine car le fichier est recréé par l'application. Certaines variantes proposent des astuces pour bloquer cette recréation. Mais aucune de ces “solutions” ne permet de récupérer l'espace considérable consommé par le fichier fautif.
Plusieurs explications peuvent être apportées à la non récupération de l'espace de stockage utilisé par le fichier fautif :
Commençons par la dernière hypothèse. Elle peut sembler la plus loufoque mais il n'en est rien. Certains types de fichiers peuvent avoir une taille déclarée bien supérieure à l'espace de stockage qu'ils consomment réellement. Ce type de fichier n'existe pas dans tous les systèmes de fichiers mais on le trouve dans les systèmes de fichiers courants sur Linux et donc Android (ext2, ext2, ext4…). On parle de fichiers “sparse”.
L'apparition d'un tel fichier n'est pas un signe de compromission de votre androphone. L'utilisation d'un fichier sparse unique pour y stocker des centaines de vignettes est l'un des cas où une telle implémentation peut se justifier2).
Le cas traité est celui d'un téléphone rooté. Le principe est d'ouvrir un shell sur l'androphone en cours d'utilisation sous Android et d'utiliser les commandes classiques pour analyser le contenu des systèmes de fichiers présents. Des applications permettent d'ouvrir un terminal sur l'androphone mais il est beaucoup plus confortable de connecter l'androphone à un ordi. C'est la voie qui sera suivie dans ce qui suit.
linux:~$ adb shell kiwi:/ $ su :/ # 130|:/ # whoami root :/ # uname -r 3.10.108-lineageos-g6e87014 :/ #
Après la connexion, on fait en sorte de devenir “root” et l'on constate que l'on est bien sur système Android (ici LineageOS). Pour une vue d'ensemble de l'espace disponible, on utilise la commande df (disk free) :
:/ # df Filesystem 1K-blocks Used Available Use% Mounted on tmpfs 921M 636K 920M 1% /dev tmpfs 921M 0 921M 0% /mnt /dev/block/mmcblk0p24 2.4G 1.5G 894M 65% /system /dev/block/mmcblk0p17 63M 3.7M 59M 6% /log /dev/block/mmcblk0p23 496M 477M 19M 97% /cust /dev/block/mmcblk0p22 248M 196K 248M 1% /cache /dev/block/mmcblk0p18 59M 344K 59M 1% /persist /dev/block/mmcblk0p14 200M 53M 146M 27% /firmware /dev/block/mmcblk0p26 7.5G 3.0G 72% /data /data/media 7.5G 3.0G 72% /mnt/runtime/default/emulated /dev/block/vold/public:179,65 30G 19G 11G 64% /mnt/media_rw/4B7E-1AC3 /mnt/media_rw/4B7E-1AC3 30G 19G 11G 64% /mnt/runtime/default/4B7E-1AC3
En se laissant guider par les noms et les tailles, on identifie rapidement la carte SD interne “/data/media” (émulée) et la carte SD externe “/mnt/media_rw/4B7E-1AC3”. Sans entrer dans les détails, il est normal que le même espace de stockage apparaisse deux fois, avec des noms de système de fichier différent, montés en des points différents. Les noms de référence sont ceux qui commencent par “/dev…” ; considérez les autres comme des alias. Soit :
On vérifie que le système de fichiers utilisé par le stockage interne est bien du type ext44) :
:/ # df -ht ext4 Filesystem Size Used Avail Use% Mounted on … /dev/block/mmcblk0p26 11G 7.5G 3.0G 72% /data
Ici, la carte SD externe est du type vfat :
:/ # df -ht vfat Filesystem Size Used Avail Use% Mounted on … /dev/block/vold/public:179,65 30G 19G 11G 64% /mnt/media_rw/4B7E-1AC3
Avant de foncer tête baissée pour éradiquer un fichier fautif, il n'est pas inutile d'avoir une vue d'ensemble de la consommation de l'espace de stockage interne5) :
:/ # du -a -d1 /data | sort -n -r | head -n 20 7922948 /data 3413868 /data/app 2133432 /data/data 1730308 /data/media 462580 /data/user_de 147700 /data/dalvik-cache 18744 /data/system 9660 /data/misc 2452 /data/system_ce 2328 /data/tombstones 880 /data/backup 380 /data/system_de 164 /data/misc_ce 72 /data/resource-cache 60 /data/vendor 60 /data/time 28 /data/mediadrm 28 /data/cache 20 /data/drm 20 /data/anr
La carte SD émulée sur la mémoire interne de l'androphone se trouve à l'intérieur du répertoire /data/media. Dans l'exemple, on constate qu'elle n'est qu'au troisième rang et consomme 1,65 Go.
Dans la suite, afin de simplifier l'affichage, on utilise le raccourci mis en place par Android qui associe le répertoire /sdcard à un sous-répertoire de /data/media (/data/media/0).
On affine la recherche en se focalisant sur ce répertoire :
:/ # cd sdcard :/sdcard # du -a -d1 | sort -n -r | head -n 10 1730288 . 637324 ./Android 372916 ./Music 368800 ./DCIM 243156 ./DictionariesNGHS 26684 ./.estrongs 22292 ./Download 12280 ./osmdroid 10224 ./HWThemes 9368 ./data
À ce stade, on dispose d'une photographie réaliste de l'utilisation de l'espace de stockage mis à notre disposition sous forme de carte SD émulée en mémoire interne.
La différence entre la taille déclarée et taille allouée est vérifiable à travers des commandes standard. Typiquement, la commande “ls”6) indiquera la taille déclarée tandis que la commande “du”7) indiquera l'espace de stockage utilisé.
Poussons l'exercice jusqu'au bout et assurons nous que le répertoire .thumbails et le fichier .thumbdata4–1967290299 qui nous préoccupaient sont rentrés dans le rang.
kiwi:/ $ cd sdcard/DCIM/.thumbnails/ kiwi:/sdcard/DCIM/.thumbnails $ ls -lh .thumbdata4--1967290299 -rw-rw---- 1 root sdcard_rw 8.9G 2020-08-02 13:35 .thumbdata4--1967290299 kiwi:/sdcard/DCIM/.thumbnails $ du -h .thumbdata4--1967290299 56K .thumbdata4--1967290299 /dev/block/mmcblk0p26 11G 7.6G 2.7G 74% /data
Dans le cas étudié, la démonstration est frappante :
Ne soyez pas surprise si vous observez le cas inverse à celui qui nous préoccupe ici. Oui, il est possible que la taille déclarée d'un fichier soit inférieure à la taille utilisée pour le conserver. Cela est particulièrement visible si on crée un fichier texte de 1 caractère. La commande ls indiquera que sa taille est de 1 octet alors qu'il occupera au minimum la taille d'un bloc d'allocation sur disque (par exemple, 4.0 Ko).
$ echo > test $ ls -lh test rw-rw---- 1 root sdcard_rw 1 2018-07-01 15:47 test $ du -h test 4.0K test
La première hypothèse est que la demande de suppression de fichier serait bien enregistrée mais qu'elle serait mise en attente ou simplement ignorée, de manière non visible. Cette incertitude vient notamment du fait que le système (ici Android) est en cours d'exécution et qu'en conséquences, certains programmes (app ou système) peuvent être en train de lire ou d'écrire dans le fichier.
Sur internet, on trouvera plusieurs propositions d'apps permettant de supprimer un fichier de manière fiable. La manière la plus fiable est encore de ne pas le faire depuis une application ni même depuis Android.
La solution consiste à démarrer l'androphone sur le recovery8) et à utiliser le navigateur de fichier du recovery pour supprimer le fichier fautif. Dans ce cas, la mémoire interne de stockage est traitée comme un vulgaire “disque externe”, sans lien avec le système (recovery) en cours d'exécution.
Sur l'androphone utilisé au cours de cette analyse, la suppression a porté sur tout le répertoire .thumbnails. Après redémarrage sous Android9), le répertoire a été recréé automatiquement, ainsi que le fichier “fautif”, mais avec une taille nulle.
:/sdcard # cd DCIM/.thumbnails :/sdcard/DCIM/.thumbnails # ls -alh total 4.0K drwxrwx--x 2 root sdcard_rw 4.0K 2020-07-26 13:05 . drwxrwx--x 5 root sdcard_rw 4.0K 2020-08-01 16:00 .. -rw-rw---- 1 root sdcard_rw 0 2020-07-26 13:05 .thumbdata4--1967290299 :/sdcard/DCIM/.thumbnails # du -ah 0 ./.thumbdata4--1967290299 4.0K .
Ces valeurs étant constantes après plusieurs jours d'utilisation de l'androphone10), on peut raisonnablement en conclure que l'opération de nettoyage a porté ses fruits.
Dans cet fiche, on utilise peu de commandes : ls, du, df. Il est toujours intéressant de consulter les pages du manuel mais l'implémentation de ces commandes n'est pas uniforme d'un système à l'autre. La recommandation “lisez le manuel” s'applique à la documentation installée sur le système où vous utilisez cette commande. Dans le cas d'espèce, il n'y a pas de documentation installée sur l'androphone. Heureusement, les commandes sont auto-documentées de manière minimale. Pour obtenir l'information on exécute la commande avec l'option “–help”, par exemple :
kiwi:/ $ df --help usage: df [-HPkhi] [-t type] [FILESYSTEM ...] The "disk free" command shows total/used/available disk space for each filesystem listed on the command line, or all currently mounted filesystems. -a Show all (including /proc and friends) -P The SUSv3 "Pedantic" option …
Les versions des commandes disponibles sur LineageOS 16 offrent bien moins d'options que celles que l'on trouve sur un système GNU-Linux courant.