¿Por qué open() crea mi archivo con los permisos incorrectos?

8 minutos de lectura

avatar de usuario
Chaitanya

Estoy tratando de leer un texto de un archivo y escribirlo en otro usando open(), read() y write().

Este es mi open() para el archivo en el que escribir (quiero crear un nuevo archivo y escribir en él):

fOut = open ("test-1", O_RDWR | O_CREAT | O_SYNC);

Esto es establecer permisos de archivo para algo que no entiendo en absoluto. Esta es la salida de ls -l:

---------T 1 chaitanya chaitanya 0 2010-02-11 09:38 test-1

Incluso el permiso de lectura está bloqueado. Intenté buscar esto, pero no pude encontrar NADA. Extrañamente, write() todavía escribe correctamente los datos en el archivo.

Además, si hago una ‘prueba chmod 777-1’, las cosas comienzan a funcionar correctamente nuevamente.

¿Podría alguien decirme dónde me estoy equivocando en mi convocatoria abierta?

¡Gracias!

Para su referencia, he pegado el programa completo a continuación:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main () {

    char buffer[512], ch;

    int fIn, fOut, i;
    ssize_t bytes;
    FILE *fp = NULL;

    //open a file
    fIn = open ("test", O_RDONLY);
    if (fIn == -1) {
        printf("\nfailed to open file.");
        return 1;
    }

    //read from file
    bytes =  read (fIn, buffer, sizeof(buffer));
    //and close it
    close (fIn);

    printf("\nSuccessfully read %d bytes.\n", bytes);

    //Create a new file
    fOut = open ("test-1", O_RDWR | O_CREAT | O_SYNC);

    printf("\nThese are the permissions for test-1\n");
    fflush(stdout);
    system("ls -l test-1");

    //write to it and close it.
    write (fOut, buffer, bytes);
    close (fOut);


    //write is somehow locking even the read permission to the file. Change it.
    system("chmod 777 test-1");

    fp = fopen ("test-1", "r");
    if (fp == NULL) {
        printf("\nCan't open test-1");
        return 1;
    }

    while (1)
    {
        ch = fgetc(fp);
        if (ch == EOF)
            break;
        printf("\n%c", ch);
    }

    fclose (fp);

    return 0;
}

  • Probablemente no necesite el permiso 777; probablemente solo necesite 666 como máximo y, por lo general, tampoco desea el permiso de escritura pública. No desea que las personas ejecuten sus archivos de datos.

    –Jonathan Leffler

    11 de febrero de 2010 a las 15:12

avatar de usuario
antti huima

open() toma un tercer argumento que es el conjunto de permisos, es decir

open(filename, O_RDWR|O_CREAT, 0666)

0666 es un número octal, es decir, cada uno de los 6 corresponde a tres bits de permiso

6 = rw

7 = rx

los primeros tres bits para el permiso del propietario, los siguientes tres bits para el permiso del grupo y el siguiente es para el mundo el primer dígito: representa que es un archivo o directorio. (0 – archivo, d – directorio) aquí usamos 0 significa archivo

Es una trampa típica. El compilador le permite omitir el argumento de permiso porque cuando abre un archivo existente, los bits de permiso no tienen sentido. Pero cuando olvida el argumento cuando crea un archivo, obtiene un conjunto aleatorio de permisos, por ejemplo, 0000 en su caso (—).

  • Para completar, octal 4 = r

    – Mensaje de Sam

    11 de febrero de 2010 a las 14:55

  • @Adam Liss: hex 4 = octal 4. Octal es conveniente para los permisos porque cada grupo de 3 bits constituye una unidad de permisos y un dígito octal. 0644 = 0x1A4, pero es mucho más fácil ver los permisos en notación octal que en hexadecimal. (En parte experiencia, pero principalmente la agrupación adecuada de bits).

    –Jonathan Leffler

    11 de febrero de 2010 a las 15:10

  • 0666 suele ser una buena configuración, incluso si no tiene la intención de que “otro” pueda escribir en él. umask generalmente se establece en 0022, lo que elimina los permisos de escritura para todos excepto para el propietario.

    – Jay Conrod

    11 de febrero de 2010 a las 16:09

  • No entiendo cómo se obtiene el último argumento, ¿esto no está en las páginas de manual?

    – PyWalker2797

    12 de abril de 2020 a las 1:16

avatar de usuario
ZeissS

Leer http://linux.die.net/man/2/open parece que te perdiste el mode parámetro para abrir:

El modo debe especificarse cuando O_CREAT está en las banderas y, de lo contrario, se ignora. El modo de argumento especifica los permisos que se utilizarán en caso de que se cree un nuevo archivo.

avatar de usuario
Porra

Esta pregunta me ayudó recientemente, así que quería hacer mi parte para agregar un poco más de profundidad a lo que está sucediendo. Como se dijo antes, te faltaba el tercer argumento para open(). Sin embargo, los permisos que ve no son aleatorios; vienen de la pila. Mira el siguiente fragmento de código:

    asm("push $0");
    asm("push $0");
    asm("push $0");
    fd = open("base", O_RDWR|O_CREAT);

Tenga en cuenta el siguiente resultado:

    ----------. 1 user user 4 Feb 26 08:21 base

Cambiemos el primer impulso a 1, es decir, permiso de ejecución:

    asm("push $1;push $0;push $0");
    fd = open("base", O_RDWR|O_CREAT);

y obtenemos:

    ---------x. 1 user user 4 Feb 26 08:25 base

Cambie el empuje a 4, es decir, permiso de lectura, y juegue con los otros dos valores:

    asm("push $4;push $5;push $6");
    fd = open("base", O_RDWR|O_CREAT);

y obtenemos:

    -------r--. 1 user user 4 Feb 26 08:27 base

Por lo tanto, podemos ver que el tercer valor extraído de la pila (primero empujado) es lo que realmente importa. Finalmente, por diversión, podemos probar 5 y luego 50, que dan como resultado respectivamente:

    -------r-x. 1 user user 4 Feb 26 08:27 base
    ----rw----. 1 user user 4 Feb 26 08:28 base

¡Espero que esto añada algo de claridad!

  • Lo siento, ¿qué quieres decir con hacer que C use esa versión de open? De la página del manual: “Este argumento debe proporcionarse cuando se especifica O_CREAT en los indicadores; si no se especifica O_CREAT, entonces se ignora el modo. Los permisos efectivos son modificados por el umask del proceso de la manera habitual: Los permisos del archivo creado son (modo y ~máscara)”. Los argumentos se pasan a la pila; al usar el ensamblado en línea para configurar manualmente la pila, podemos demostrar de dónde provienen los permisos aparentemente “aleatorios”.

    – billy

    7 de junio de 2018 a las 6:16


avatar de usuario
rgt

Realmente umask() solo filtra los permisos y no los establece. Lo tipico umask() el valor es 0002 (“no le des permiso de escritura al mundo”) y si tu valor de modo en el open( "file", O_CREAT, 0777) dio todos los permisos, el archivo resultante tendría 775 como sus permisos.

Puedes llamar umask(0); llamada al sistema antes de usar open(); llamada al sistema para configurar sus opciones de permisos para archivar correctamente.

  • vale la pena señalar que umask out tiene un efecto en todo el proceso y, por lo tanto, representa un riesgo para las condiciones de carrera en un programa de subprocesos múltiples

    – Alexei

    25 de marzo de 2018 a las 9:37

avatar de usuario
evan

No es estrictamente relevante para la pregunta, pero la respuesta aceptada podría usar este punto de aclaración:

Existe una relación entre rwx y su representación numérica que se puede ver al tratar la presencia de una letra como un 1 binario y su ausencia como un 0 binario.

p.ej

rwx  <-->  111 (binary) <-->  7 (octal)

r--  <-->  100 (binary) <-->  4 (octal)

-wx  <-->  011 (binary) <-->  3 (octal) 

Como un apéndice adicional, ahora puede considerar el comando chmod:

chmod 777 nombre de archivo.extensión –> permisos rwxrwxrwx

777 <--> 111 111 111 <--> rwx rwx rwx

o: chmod 654 nombre de archivo.extensión –> rw-rxr–

654 <--> 110 101 100 <--> rw- r-x r--

¡Espero que esto sea informativo!

  • vale la pena señalar que umask out tiene un efecto en todo el proceso y, por lo tanto, representa un riesgo para las condiciones de carrera en un programa de subprocesos múltiples

    – Alexei

    25 de marzo de 2018 a las 9:37

avatar de usuario
Meevs

Este es un hilo antiguo, pero creo que la gente debería estar al tanto de la biblioteca “sys/stat.h”. Esto incluye un montón de constantes simbólicas para establecer bits de permiso.

Por ejemplo: para abrir un archivo con permisos de lectura/escritura habilitados para el usuario

#include <fcntl.h>
#include <sys/stat.h>

open("Your/File/Path", O_RDWR | O_CREAT, S_IWUSR | S_IRUSR);

donde:

S_IWUSR // Sets the Users Write bit
S_IRUSR // Sets the Users Read bit

Esta biblioteca incluye un montón de otras, no las enumeraré todas aquí, pero puedes leerlas todas. aquí.

Por supuesto, puede ingresar los valores octales para configurar estos bits, sin embargo, algunos pueden argumentar que es una mala práctica de codificación.

  • Creo que lo que está diciendo es algo subjetivo general y la pregunta es que incluso después de establecer el permiso, no podemos ver los bits de permiso establecidos. Esto es válido tanto para stdlb api como para system apis.

    – Pantalón Bhupesh

    26 de marzo de 2018 a las 11:49

  • @BhupeshPant La pregunta es por qué los bits de permiso del archivo se establecen en “———T 1 chaitanya chaitanya 0 2010-02-11 09:38 test-1” Es decir, ¿por qué el archivo no tienen bits de permiso establecidos. En su llamada abierta, es decir.) “fOut = abierto (“prueba-1″, O_RDWR | O_CREAT | O_SYNC);” Tiene el indicador O_CREAT, que creará el archivo “test-1” si no existe. Suponiendo que este sea el caso (que el archivo se crea en la convocatoria abierta), también debe especificar los bits de permiso que se asociarán con el archivo. Corrige esto más adelante en su código con la llamada del sistema a chmod.

    – Meevs

    26 de marzo de 2018 a las 17:20

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad