"Неверный аргумент" об использовании fcntl в C

Я пытался понять причину и не могу найти вескую причину Invalid Argument ошибка при использовании perror, Кто-нибудь может подсказать причину этой ошибки?

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

int main(int argc,char *argv[])
{ 

    int fd;
    char buffer[255];
    struct flock fvar;

    if(argc==1)
    {
        printf("usage:./a.out filename\n");
        return -1;
    }

    if((fd=open(argv[1],O_RDWR))==-1)
    {
        perror("open");
        exit(1);
    }

    fvar.l_type=F_WRLCK;
    fvar.l_whence=SEEK_END;
    fvar.l_start=SEEK_END-100;
    fvar.l_len=100;

    printf("press enter to set lock\n");
    getchar();
    printf("trying to get lock..\n");

  **if((fcntl(fd,F_SETLK,&fvar))==-1)
    {
         perror("fcntl") ;
         fcntl(fd,F_GETLK,&fvar);**
         printf("\nFile already locked by process (pid): \t%d\n",fvar.l_pid);
         return -1;
    }

    printf("locked\n");

    if((lseek(fd,SEEK_END-50,SEEK_END))==-1)
    {
        perror("lseek");
        exit(1);
    }

    if((read(fd,buffer,100))==-1)
    {
        perror("read");
        exit(1);
    }

    printf("data read from file..\n");
    puts(buffer);
    printf("press enter to release lock\n");

    getchar();

    fvar.l_type = F_UNLCK;
    fvar.l_whence = SEEK_SET;
    fvar.l_start = 0;
    fvar.l_len = 0;

    if((fcntl(fd,F_UNLCK,&fvar))==-1)
    {
        perror("fcntl");
        exit(0);
    }

    printf("Unlocked\n");
    close(fd);

    return 0;
}

Я попытался проверить аргументы. Файловый дескриптор выглядит хорошо, и аргументы flock проверяются дважды, трижды, в четыре раза... раз. Я просто не могу понять, где проблема.

2 ответа

Вы устанавливаете:

fvar.l_type=F_WRLCK;
fvar.l_whence=SEEK_END;
fvar.l_start=SEEK_END-100;
fvar.l_len=100;

Страница man для fcntl (по крайней мере в Linux) говорит:

l_start является начальным смещением для блокировки, и интерпретируется относительно: начала файла (если l_whence SEEK_SET); текущее смещение файла (если l_whence является SEEK_CUR); или конец файла (если l_whence является SEEK_END). В последних двух случаях l_start может быть отрицательным числом, если смещение не лежит перед началом файла.

Вы устанавливаете l_start в SEEK_END-100, поскольку SEEK_END равно 2 (опять же, в Linux, хотя другие системы, вероятно, будут похожи), это означает, что вы устанавливаете l_start до -98. Если длина файла меньше 98 байт, это будет до начала файла - что, как говорится в справочной странице, недопустимо. Это может быть источником EINVAL,

Вместо этого вы должны:

  1. Убедитесь, что вы используете смещения, которые находятся в файле
  2. Не использовать SEEK_END-100 (или же SEEK_END-50) за fcntl или же lseek - это не так, как они работают - просто используйте -100 или же -50 вместо.

Если fvar.l_whence установлен в SEEK_END, fvar.l_start смещение от конца файла. Если вы хотите, чтобы блокировка начиналась за 100 байт до конца, l_start должно быть -100 (не SEEK_END-100).

Другие вопросы по тегам