12

I know, that there's the is_open() function in C++, but I want one program to check if a file hasn't been opened by another application. Is there any way to do it using standard library?

EDIT - Clarified in the answers that this is for a Linux application.

Angie Quijano
  • 4,167
  • 3
  • 25
  • 30

10 Answers10

5

Not only the standard library does not have this funcionality, it's not even possible in general. You could (on linux) check /proc/*/fd — but it is possible that your program does not have permission to do it on processes from other users (this is the default in Ubuntu, for instance).

CesarB
  • 43,947
  • 7
  • 63
  • 86
4

No, the standard library has no such functionality.

3

If you control the other process (have source code), the best plan is to use advisory locks in both processes. This locking is defined in POSIX, and will be portable across operating systems.

In Linux, you can use the utility lsof to see what files are opened by other processes.

This is limited to what you have permissions for - you have to do the check as a privileged user, or you'll only get results for files opened by the same user as the one doing the check.

I only know of the command line utility, not of any system call you can use directly from C code.

In Linux, it's also possible to turn on mandatory locking for a given filesystem (mount -o mand), and set special flags on the file (chmod g-x,g+s). Then when your process attempts to acquire a write lock, it will fail if another process has the file open. This is hardly ever used, but if you completely control the system in question, it may be an option.

jmanning2k
  • 9,297
  • 4
  • 31
  • 23
  • 1
    I tried looking at the lsof source code one time to see how they did it and my head almost exploded. The source to lsof is an web of insanity and black magic. – Tyler McHenry Jun 26 '09 at 16:30
  • 2
    I'd suggest using fuser over lsof. Parsing the results will be much simpler. – AFoglia Jun 26 '09 at 22:29
3

The following code may work.

int main(int argc, char ** argv)
{
    int fd = open(argv[1], O_RDONLY);
    if (fd < 0) {
        perror("open");
        return 1;
    }

    if (fcntl(fd, F_SETLEASE, F_WRLCK) && EAGAIN == errno) {
        puts("file has been opened");
    }
    else {
        fcntl(fd, F_SETLEASE, F_UNLCK);
        puts("file has not been opened");
    }

    close(fd);
    return 0;
}
tinytaro
  • 380
  • 2
  • 8
  • In my case, this example always returns 'file has not been opened' even though file is opened. ```ls -al /proc/21862/fd/47 l-wx------ 1 user user 64 1월 29 17:12 /proc/21862/fd/47 -> /home/user/data/201802201020.mp4```. (Ubuntu) – uthline Jan 29 '20 at 08:59
2

Perhaps you could just try and get a full write lock? It'll fail if anyone else has it open for reading or writing.

fopen("myfile.txt", "r+")

If it's not cross platform and is Win32, then you can request even more fine-grained set of locks.

See here and look at dwShareMode, value of 0, as well as the other parameters.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Pod
  • 3,938
  • 2
  • 37
  • 45
0

Nope. Unless other application uses advisory locks.

See http://docs.sun.com/app/docs/doc/816-0213/6m6ne37v5?a=view

Eugene Bujak
  • 1,591
  • 2
  • 14
  • 14
0

Non-natively, you could call out to Sysinternals' handle.exe as a last resort...

ZombieSheep
  • 29,603
  • 12
  • 67
  • 114
  • +1 I've been looking for an app which does exactly what handle.exe does. Thanks ZombieSheep. – Kei Jun 26 '09 at 11:31
0

As @Neil Butterworth says, the standard library doesnt.

In unix you can use fcntl to use file locks.

You could write a wrapper for your open function, that checks for a lock (and locks if none exists) a file if its open by no one else. You shold write a wrapper for close as well, that releases that lock on file close.

Tom
  • 43,810
  • 29
  • 138
  • 169
0

Seeing you have tagged linux -> there's a command-line too and API that have been added to the Linux kernel and do just that: inotify.

Here's the man page.

SpectreVert
  • 187
  • 2
  • 10
-1

In Windows this little and dirty trick will work (if the file exists and you have the right permissions)

  if (  0 != rename("c:/foo.txt", "c:/foo.txt")  ) {
     printf("already opened\n");
  }

It's likely to work also in Linux.

Nick Dandoulakis
  • 42,588
  • 16
  • 104
  • 136
  • I could easily imagine someone adding a "fix" to an os in the future that broke this trick. – Brian Jun 26 '09 at 13:13
  • 3
    In linux, you can rename the file while it's open. The files are tracked by inode, not name. You can even delete the file, and the process that has it open will keep reading it without errors. – jmanning2k Jun 26 '09 at 16:03
  • 1
    In the Explorer, you can also rename files that can't be removed because they are locked. Very useful when you want to copy files over existing ones, and can't overwrite a locked file. – Kevin Doyon Jul 06 '09 at 16:36
  • really really dirty :) and we get false info about opened file when we have not rights to rename this :P – Znik Dec 05 '14 at 10:34