Разница между rm my-symlink и rm my-symlink /

Моя ситуация была другой. Я устанавливал на новый ноут. На моей настроенной виртуальной машине было много памяти и диска, но эта проблема все еще оставалась у меня.

В конце концов я обнаружил, что, поскольку это был новый ноутбук, в конфигурации BIOS не была включена виртуализация.

Как только я включил это в BIOS, мои виртуальные машины работали должным образом.

3
01.06.2018, 14:42
2 ответа

Puede ver la diferencia comparando la salida de stat my-symlinky stat my-symlink/. my-symlink, sin la barra inclinada, es el enlace simbólico en sí mismo; my-symlink/, con la barra oblicua, es el directorio al que apunta el enlace simbólico, que puede verificar por separado comparando los inodos de my-symlink/y del directorio al que apunta.

Con esa información en la mano, el comportamiento que está viendo coincide con el descrito en la especificación derm:al procesar un enlace simbólico, rmelimina el enlace sin descender "a" él si apunta a un directorio; al procesar un directorio (con la opción -r), borra recursivamente su contenido. En el caso my-symlink/, rmintenta eliminar el "directorio", pero falla ya que no es un directorio sino un enlace simbólico; sin embargo, debido a la bandera -f, esto no provoca un error.

4
27.01.2020, 21:15

Pensé en investigar el comportamiento un poco más, así que aquí hay otra respuesta.

Internamente, rmusa FTS para recursivamente en jerarquías de archivos. fts_opentoma una matriz de rutas como parámetro y crea una estructura de árbol para cada ruta. Esto le permite al programador explorar varias ubicaciones sin problemas como si fueran parte de una jerarquía unificada.

Aquí hay un programa de prueba que puedes usar para jugar con FTS tú mismo.

#include <stdio.h>
#include <stdlib.h>
#include <fts.h>

int main(int argc, char* argv[])
{
    if(argc < 2) return EXIT_FAILURE;

    char* const* arr = argv + 1;
    FTS* hier = fts_open(arr, FTS_NOSTAT | FTS_PHYSICAL, NULL);

    FTSENT* ent;
    while((ent = fts_read(hier))) {
        printf("%s info=%d (D=%d DP=%d F=%d SL=%d)\n",
               ent->fts_accpath, ent->fts_info,
               ent->fts_info == FTS_D, ent->fts_info == FTS_DP,
               ent->fts_info == FTS_F || ent->fts_info == FTS_NSOK,
               ent->fts_info == FTS_SL);
    }

    fts_close(hier);
    return EXIT_SUCCESS;
}

Supongamos que hemos creado la siguiente estructura de directorios:

$ mkdir dir
$ touch dir/file
$ ln -s dir sym

Ahora, consideremos su primer caso y veamos cómo FTS lidera la exploración.

$ gcc fts.c 
$./a.out sym
sym info=12 (D=0 DP=0 F=0 SL=1)

Como puede ver, en este caso, symse ve como un archivo. Un enlace simbólico, para ser más exactos. Con esta información, rmlo trataría como un archivo y llamaría a unlinkat(AT_FDCWD, "sym", 0). El último parámetro (0 )hace que unlinkatse comporte como unlink. En otras palabras :simplemente borra un archivo. Como resultado, su enlace desaparece.

Ahora, echemos un vistazo a lo que sucede con sym/.

$./a.out sym/
sym/ info=1 (D=1 DP=0 F=0 SL=0)
file info=11 (D=0 DP=0 F=1 SL=0)
sym/ info=6 (D=0 DP=1 F=0 SL=0)

En este caso, symfue tratado como su directorio de destino. Primero iteramos a sym, luego sym/filey luego symnuevamente. Este último se debe a cómo funciona FTS :primero, itera sobre el contenido y luego regresa al nodo raíz. Esto es bastante conveniente para rm. En la primera pasada (D), puede borrar archivos, y en la segunda(DP)eliminar los directorios vacíos.

Como puede ver, en este caso, FTS informa sym/como un directorio en ambos casos. Esto se debe a que le dimos la ruta con una barra al final, lo que obliga al núcleo a interpretarla como un directorio. En el caso de un enlace, esto significa que lo seguirá sin importar nada. En términos más técnicos, las especificaciones dicen:

A pathname that contains at least one non-slash character and that ends with one or more trailing slashes shall be resolved as if a single dot character ( '.' ) were appended to the pathname.

Debido a que FTS informa sym/como un directorio, rmse comporta como si estuviera eliminando un directorio vacío. En consecuencia, llama unlinkat(AT_FDCWD, "sym/", AT_REMOVEDIR).Esto hace que unlinkatse comporte como rmdir.

Sin embargo, al resolver la ruta sym/, la llamada al sistema unlinkatse dará cuenta de que, de hecho, no se le está dando un directorio. Por lo tanto, informará ENOTDIR, lo que desencadena:

$ rm: cannot remove ‘sym/’: Not a directory

Y, de hecho, si elimina la marca -fde sus llamadas... Eso es exactamente lo que verá. Ahora, si esto es un error o una característica... No tengo idea.

1
27.01.2020, 21:15

Теги

Похожие вопросы