2015-06-05 5 views
0

Я пытался понять причину и не могу найти допустимую причину ошибки Invalid Argument при использовании perror. Может ли кто-нибудь предложить причину этой ошибки?«Недопустимый аргумент» об использовании fcntl в C

#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; 
} 

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

+0

Как долго (в байтах) находится файл, на котором вы его используете? – psmears

+0

о, подождите, это важно? – priyadarshi1729

+0

Это сработало, спасибо человеку! – priyadarshi1729

ответ

0

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

+0

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

1

Вы настраиваете:

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

Человек страница 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.
+0

Итак, ваша цель - не использовать SEEK_END-100 (или 50) и вместо этого использовать -100 или -50 для смещения, установленного на SEEK_END, или просто изменить смещение на SEEK_SET? Кроме того, почему я не могу использовать «SEEK_END-50» для lseek? Ваш вход был полезен. – priyadarshi1729

+0

Да, используйте '-100' или' -50' (или переключитесь на 'SEEK_SET'). Вы не можете использовать 'SEEK_END-50' для' lseek() ', потому что опять-таки это не работает' SEEK_END', вам нужно использовать 'SEEK_END' для параметра' whence', но просто '-50' для' offset'.Рад, что вы нашли ответ полезным :) – psmears