ls.exe -n does not work on NFS filesystems

Abierto
#86 1 comentario 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
45/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Tranquilo
Stack tecnológico
rust

Línea de trabajo

Comience con la implementación en Rust del manejo de metadatos de ls.exe y siga cómo la opción -n obtiene los atributos de archivo en Windows. Compare ese recorrido con el ejemplo de NfsV3Attributes EA y ZwQueryEaFile del issue y, después, pruebe con uno de los controladores NFS de Windows enumerados. Se considera terminado cuando ls.exe -n informa de los metadatos numéricos esperados en sistemas de archivos NFS.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

C-bug

ls.exe -n does not work on NFS filesystems, e.g. Windows NFSv3 driver, OpenText/Exceed NFSv4 driver, ms-nfs41-client driver.

All these drivers implement the ServicesForUNIX API to obtain stat()-alike information.

The API is simply to get the EA "NfsV3Attributes" for for a file or directory, which contains a nfs3_attrs struct:

#define EA_NFSV3ATTRIBUTES "NfsV3Attributes"
#define EA_NFSV3ATTRIBUTES_LEN (15)

/*
 * "NfsV3Attributes" uses |nfs3_attrs| as content
 */
/*
 * Note that we cannot use <stdint.h> in the Windows kernel, so we
 * use Windows Types here
 */
typedef struct _nfs3_attrs_timestruc_t {
    INT32   tv_sec;
    UINT32  tv_nsec;
} nfs3_attrs_timestruc_t;

typedef struct _nfs3_attrs {
    UINT32 type, mode, nlink, uid, gid, filler1;
    UINT64 size, used;
    struct {
        UINT32 specdata1;
        UINT32 specdata2;
    } rdev;
    UINT64 fsid, fileid;
    nfs3_attrs_timestruc_t atime, mtime, ctime;
} nfs3_attrs;

enum ftype3 {
    NF3REG = 1,
    NF3DIR,
    NF3BLK,
    NF3CHR,
    NF3LNK,
    NF3SOCK,
    NF3FIFO
};

Example function, based on https://github.com/kofemann/ms-nfs41-client/blob/master/include/nfs_ea.h and https://github.com/kofemann/ms-nfs41-client/blob/master/tests/winfsinfo1/winfsinfo.c

int get_nfs3attr(const char *progname, const char *filename)
{
    int res = EXIT_FAILURE;

    HANDLE fileHandle = CreateFileA(filename,
        GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS, NULL);
    if (fileHandle == INVALID_HANDLE_VALUE) {
        (void)fprintf(stderr,
            "%s: Error opening file '%s'. Last error was %d.\n",
            progname,
            filename,
            (int)GetLastError());
        return EXIT_FAILURE;
    }

    struct {
        FILE_FULL_EA_INFORMATION ffeai;
        char buf[sizeof(EA_NFSV3ATTRIBUTES) + sizeof(nfs3_attrs)];
    } ffeai_buf;
    struct {
        FILE_GET_EA_INFORMATION fgeai;
        char buf[sizeof(EA_NFSV3ATTRIBUTES)];
    } fgeai_buf;

    NTSTATUS status;
    IO_STATUS_BLOCK io;

    fgeai_buf.fgeai.NextEntryOffset = 0;
    fgeai_buf.fgeai.EaNameLength = 15;
    (void)strcpy(fgeai_buf.fgeai.EaName, EA_NFSV3ATTRIBUTES);

    status = ZwQueryEaFile(fileHandle, &io,
        &ffeai_buf.ffeai, sizeof(ffeai_buf), TRUE,
        &fgeai_buf.fgeai, sizeof(fgeai_buf), NULL, TRUE);

    switch (status) {
        case STATUS_SUCCESS:
            break;
        case STATUS_NO_EAS_ON_FILE:
            (void)fprintf(stderr, "No EAs on file, status=0x%lx.\n", (long)status);
            res = EXIT_FAILURE;
            goto done;
        default:
            (void)fprintf(stderr, "ZwQueryEaFile() failed with 0x%lx\n", (long)status);
            res = EXIT_FAILURE;
            goto done;
    }

    if (ffeai_buf.ffeai.EaValueLength < sizeof(nfs3_attrs)) {
            (void)fprintf(stderr,
                "EA '%s' size too small (%ld bytes), "
                "expected at least %ld bytes for nfs3_attrs\n",
                EA_NFSV3ATTRIBUTES,
                (long)ffeai_buf.ffeai.EaValueLength,
                (long)sizeof(nfs3_attrs));
            res = EXIT_FAILURE;
            goto done;
    }

    nfs3_attrs *n3a = (nfs3_attrs *)(ffeai_buf.ffeai.EaName
        + ffeai_buf.ffeai.EaNameLength + 1);

    (void)printf("(\n");

    (void)printf("\tfilename='%s'\n"
        "\ttype=%d\n"
        "\tmode=0%o\n"
        "\tnlink=%d\n"
        "\tuid=%d\n\tgid=%d\n"
        "\tsize=%lld\n\tused=%lld\n"
        "\trdev=( specdata1=0x%x specdata2=0x%x )\n"
        "\tfsid=0x%llx\n\tfileid=0x%llx\n"
        "\tatime=( tv_sec=%ld tv_nsec=%lu )\n"
        "\tmtime=( tv_sec=%ld tv_nsec=%lu )\n"
        "\tctime=( tv_sec=%ld tv_nsec=%lu )\n"
        ")\n",
        filename,
        (int)n3a->type,
        (int)n3a->mode,
        (int)n3a->nlink,
        (int)n3a->uid,
        (int)n3a->gid,
        (long long)n3a->size,
        (long long)n3a->used,
        (int)n3a->rdev.specdata1,
        (int)n3a->rdev.specdata2,
        (unsigned long long)n3a->fsid,
        (unsigned long long)n3a->fileid,
        (long)n3a->atime.tv_sec, (unsigned long)n3a->atime.tv_nsec,
        (long)n3a->mtime.tv_sec, (unsigned long)n3a->mtime.tv_nsec,
        (long)n3a->ctime.tv_sec, (unsigned long)n3a->ctime.tv_nsec);
    res = EXIT_SUCCESS;

done:
    (void)CloseHandle(fileHandle);
    return res;
}
Lenguaje dominante
Rust
Estrellas
5.2k
Forks
107
Merge medio
2 d 19 h
PR fusionados (30 d)
4

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de microsoft/coreutils

Todos los issues de microsoft/coreutils

Issues similares

Más issues de Rust

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.