"Неверный аргумент" об использовании 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
,
Вместо этого вы должны:
- Убедитесь, что вы используете смещения, которые находятся в файле
- Не использовать
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
).