0

I can't figure out why my fcntl keeps saying "Invalid argument". Please, help. If I understand it correctly I should fill my flock (the one that I pass to fcntl) with data that points to a byte I want to check.

  int byteno;
  printf(ANSI_COLOR_BLUE "Insert byte number: " ANSI_COLOR_RESET);
  scanf("%d\n", &byteno);

  struct flock* fl = malloc(sizeof(flock));
  fl -> l_type = F_GETLK;
  fl -> l_whence = SEEK_SET;
  fl -> l_start = byteno;
  fl -> l_len = 1;
  fl -> l_pid = getpid();

  if(fcntl(descr, F_GETLK, fl) == -1){
    perror(ANSI_COLOR_RED "Error while getting info about locks" ANSI_COLOR_RESET);
    free(fl);
    continue;
  }

  if(!(fl -> l_type == F_UNLCK)){
    printf(ANSI_COLOR_YELLOW "Other proccess has a lock here. PID = %d" ANSI_COLOR_RESET, fl -> l_pid);
    continue;
  }
Kanes115
  • 119
  • 6
  • The dot `.` and arrow `->` operators bind very tightly and should never be surrounded by spaces. – Jonathan Leffler Mar 19 '17 at 19:37
  • POSIX ([``](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fcntl.h.html)) says: _`short l_type` — Type of lock; F_RDLCK, F_WRLCK, F_UNLCK._ You're supplying `F_GETLK`; this is invalid. – Jonathan Leffler Mar 19 '17 at 19:45

1 Answers1

3

F_GETLK (struct flock *)

On input to this call, lock describes a lock we would like to place on the file. If the lock could be placed, fcntl() does not actually place it, but returns F_UNLCK in the l_type field of lock and leaves the other fields of the structure unchanged. If one or more incompatible locks would prevent this lock being placed, then fcntl() returns details about one of these locks in the l_type, l_whence, l_start, and l_len fields of lock and sets l_pid to be the PID of the process holding that lock.

F_GETLK is not used to get information about a lock, but rather to 'test whether applying the specified lock would work'.

Try the following example. Run it twice within the 5 second window.

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

void main(void) {
    int fd;
    struct flock fl_info;
    int ret;

    fd = open("./test.txt", O_RDWR | O_CREAT, 0600);
    if (fd == -1) {
        perror("open()");
        return;
    }

    memset(&fl_info, 0, sizeof(fl_info));

    /* try to get a WRITE lock on the entire file (l_len == zero) */
    fl_info.l_type = F_WRLCK;
    fl_info.l_whence = SEEK_SET;
    fl_info.l_start = 0;
    fl_info.l_len = 0;

    ret = fcntl(fd, F_GETLK, &fl_info);
    if (ret == -1) {
        perror("fcntl(F_GETLK)");
        return;
    }

    if (fl_info.l_type != F_UNLCK) {
        printf("Too bad... it's already locked... by pid=%d\n", fl_info.l_pid);
        return;
    }

    /* try to apply a write lock */
    fl_info.l_type = F_WRLCK;
    ret = fcntl(fd, F_SETLK, &fl_info);
    if (ret == -1) {
        perror("fcntl(F_SETLK)");
        return;
    }

    printf("Success!\n");

    sleep(5);

    printf("I'm done, bye!\n")

    return;
}

Note also that it is not necessary to malloc() storage for the struct flock.

Attie
  • 6,690
  • 2
  • 24
  • 34
  • Ok, but I still don't see the mistake here. I've tried to change fl -> l_type = F_SETLK, but still it is not running. – Kanes115 Mar 19 '17 at 19:38
  • 2
    `l_type` needs to be set to the type of lock you would like to apply... not to the operation you would like to carry out. Look at my example - `fl_info.l_type = F_WRLCK;` – Attie Mar 19 '17 at 19:40
  • Thanks a lot! It works now and I understand it now as well. – Kanes115 Mar 19 '17 at 19:45