undefined reference to `inotify_init1'

1.2k Views Asked by At

I am trying to integrate latest version 2.80 of dnsmasq application in my project. The platform is Linux 2.6.32. Compilation with cross compiler arm-none-linux-gnueabi-gcc is giving this error:

inotify.o: In function `inotify_dnsmasq_init':
inotify.c:(.text+0x514): undefined reference to `inotify_init1'

It seems that function inotify_init1() is not supported in this platform.

I'm wondering if I can write this function by myself.

int inotify_init1(int flags)
{
    int flags1 = 0;
    int inotify_fd = inotify_init();

    if ((inotify_fd != -1) && (flags != 0)) 
    {
        if((flags1 = fcntl(inotify_fd, F_GETFL)) != -1)
        {
            fcntl(inotify_fd, F_SETFL, flags1 | flags);
        }
    }
    return inotify_fd;
}

Would the piece of code do the job?

Update: according to inotify_init man page, inotify_init1() was added to glibc in version 2.9. I am working with glibc version 2.8 only

In an other hand I see that inotify_init1 is present in several files in Kernel:

1) /fs/notify/inotify/inotify_user.c
/* inotify syscalls */
SYSCALL_DEFINE1(inotify_init1, int, flags)
{ 
...
}
2) /kernel/sys_ni.c
cond_syscall(sys_inotify_init1);

I understand that I am missing something but I don't know if the appropriate library is built or properly linked on the dnsmasq building files.

Thank you for advising.

1

There are 1 best solutions below

2
On BEST ANSWER

You function looks ok and should work. I don't know however how your application defines the macros IN_NONBLOCK and IN_CLOEXEC. Looking at kernel srcrs they should be defined the same as O_NONBLOCK and O_CLOEXEC. Also would be nice to add if (flags & ~(IN_CLOEXEC | IN_NONBLOCK)) return -EINVAL; some checking.

I would add a file inotify.h to your project / to dnsmasq sources, which I would add to include path:

#ifndef MY_INOTIFY_H_
#define MY_INOTIFY_H_
#include_next <inotify.h>

// from https://github.molgen.mpg.de/git-mirror/glibc/blob/glibc-2.9/sysdeps/unix/sysv/linux/sys/inotify.h#L25
/* Flags for the parameter of inotify_init1.  */
enum
  {
    IN_CLOEXEC = 02000000,
#define IN_CLOEXEC IN_CLOEXEC
    IN_NONBLOCK = 04000
#define IN_NONBLOCK IN_NONBLOCK
  };

extern int inotify_init1 (int flags) __THROW;
// or just int inotify_init1(int flags); ...

#endif

Along with it your wrapper in a c file added to compilation / linking. The include_next serves as a simple overwrite of the glibc inotify.h.

If you kernel supports inotify_wait1 syscall and I think it does. You can even check if__NR_inotify_wait1 is defined in your unistd.h. You can just:

   #define _GNU_SOURCE
   #include <unistd.h>
   #include <sys/syscall.h>

   int inotify_init1(int flags) {
       return syscall(332, flags);
   }

To make a syscall just call a syscall() function.