fcntl call to check if a file is open - help needed

S

sa

Hi all,

Consider the script below. After reading some man and perldoc on
fcntl, open, etc, I'm obviously doing something wrong - it gives me
the same result regardless whether a file I'm checking is open or
not.

[root@willow tmp]# lsof disk.txt
[root@willow tmp]# ./fcntl_test disk.txt
flags: 4294964736
O_TRUNC
O_APPEND
O_SYNC
O_NOFOLLOW
O_DIRECTORY
O_DIRECT
O_ASYNC
O_LARGEFILE

Now a run when the file is open.

[root@willow tmp]# lsof disk.txt
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
perl 22877 username 4w REG 104,6 18480 508036 disk.txt
[root@willow tmp]# ./fcntl_test disk.txt
flags: 4294964736
O_TRUNC
O_APPEND
O_SYNC
O_NOFOLLOW
O_DIRECTORY
O_DIRECT
O_ASYNC
O_LARGEFILE


Here is the script. Any pointers will be greatly appreciated.
=============================================
#!/usr/bin/perl -w

use Fcntl;
use strict;
use Symbol;

my $fh = gensym;
sysopen $fh, $ARGV[0], O_RDONLY or die "$ARGV[0]: Cannot open ($!)
\n";
my $buf = '';
fcntl($fh, F_GETFL, $buf) or die "Cannot run fcntl\n";
my $flags = unpack 's', $buf;
printf "flags: %u\n", $flags;
for my $f (qw[O_CREAT O_EXCL O_NOCTTY O_TRUNC O_APPEND O_NONBLOCK
O_SYNC O_NOFOLLOW O_DIRECTORY O_DIRECT O_ASYNC
O_LARGEFILE]) {
no strict;
print "$f\n" if ($flags & &$f) == &$f;
}
=============================================

Thanks,
Alex.
 
S

sa

Hi all,

Consider the script below. After reading some man and perldoc on
fcntl, open, etc, I'm obviously doing something wrong - it gives me
the same result regardless whether a file I'm checking is open or
not.

[root@willow tmp]# lsof disk.txt
[root@willow tmp]# ./fcntl_test disk.txt
flags: 4294964736
O_TRUNC
O_APPEND
O_SYNC
O_NOFOLLOW
O_DIRECTORY
O_DIRECT
O_ASYNC
O_LARGEFILE

Now a run when the file is open.

[root@willow tmp]# lsof disk.txt
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
perl 22877 username 4w REG 104,6 18480 508036 disk.txt
[root@willow tmp]# ./fcntl_test disk.txt
flags: 4294964736
O_TRUNC
O_APPEND
O_SYNC
O_NOFOLLOW
O_DIRECTORY
O_DIRECT
O_ASYNC
O_LARGEFILE

Here is the script. Any pointers will be greatly appreciated.
=============================================
#!/usr/bin/perl -w

use Fcntl;
use strict;
use Symbol;

my $fh = gensym;
sysopen $fh, $ARGV[0], O_RDONLY or die "$ARGV[0]: Cannot open ($!)
\n";
my $buf = '';
fcntl($fh, F_GETFL, $buf) or die "Cannot run fcntl\n";
my $flags = unpack 's', $buf;
printf "flags: %u\n", $flags;
for my $f (qw[O_CREAT O_EXCL O_NOCTTY O_TRUNC O_APPEND O_NONBLOCK
O_SYNC O_NOFOLLOW O_DIRECTORY O_DIRECT O_ASYNC
O_LARGEFILE]) {
no strict;
print "$f\n" if ($flags & &$f) == &$f;
}
=============================================

Thanks,
Alex.

Sorry, forgot to tell about my system: RHEL 2.1, kernel 2.4.9-e.
59enterprise, perl v5.6.1
 
J

John W. Krahn

sa said:
Subject: fcntl call to check if a file is open - help needed

perldoc -f fileno
fileno FILEHANDLE
Returns the file descriptor for a filehandle, or undefined if the
filehandle is not open.


John
 
S

sa

perldoc -f fileno
fileno FILEHANDLE
Returns the file descriptor for a filehandle, or undefined if the
filehandle is not open.

I don't see how it's going to work for me - I need to check whether a
file is open by another process. Sorry if it wasn't clear. I need to
copy the file and I should not do it if there is another process
writing to it. To complicate things further, the file is located on a
CIFS share. I'm in the process of checking if fcntl can do it for a
network drive but I'm having problems using it on a local file.

Alex.
 
B

Brian McCauley

I don't see how it's going to work for me - I need to check whether a
file is open by another process. Sorry if it wasn't clear. I need to
copy the file and I should not do it if there is another process
writing to it. To complicate things further, the file is located on a
CIFS share. I'm in the process of checking if fcntl can do it for a
network drive but I'm having problems using it on a local file.

Well, the first thing to do would be to check that the CIFS protocol
is capable of conveying such a query (I don't think it is). If I'm
wrong then see if the particular server implementation implements it.
The look to see if the client implements it. Then, and only then,
should you consider how to get Perl to tell the CIFS client to ask the
CIFS server if the file is open.

I think this is probably XY. The safest, most portable and widely
accepted approach to having one process create a file and another read
it only after creation is complete is to rename the file upon
completion of creation.
 
S

sa

I don't see how it's going to work for me - I need to check whether a
Well, the first thing to do would be to check that the CIFS protocol
is capable of conveying such a query (I don't think it is). If I'm
wrong then see if the particular server implementation implements it.
The look to see if the client implements it. Then, and only then,
should you consider how to get Perl to tell the CIFS client to ask the
CIFS server if the file is open.

I think this is probably XY. The safest, most portable and widely
accepted approach to having one process create a file and another read
it only after creation is complete is to rename the file upon
completion of creation.

Ha! I wish I had control over the process of creating of those files!
Unfortunately, this is totally out of the question.

The CIFS protocol and client do know something - when I open a CIFS
file in say, notepad, and try mv'ing it from the shell prompt - I get
this:

[root@willow tmp]# mv test.txt test.txt_
mv: preserving ownership for `test.txt_': Operation not permitted
mv: cannot unlink `test.txt': Text file busy
mv: cannot remove `test.txt': Text file busy

I get $! of "Text file busy" from perl when I try to rename. It looks
like this info can be tapped into, I just don't know how.

Going back to the original question - I'd also like to be able to do
what lsof does using perl. lsof rocks but it's a bit slow.

Thanks,
Alex.
 
J

John W. Krahn

sa said:
Well, the first thing to do would be to check that the CIFS protocol
is capable of conveying such a query (I don't think it is). If I'm
wrong then see if the particular server implementation implements it.
The look to see if the client implements it. Then, and only then,
should you consider how to get Perl to tell the CIFS client to ask the
CIFS server if the file is open.

I think this is probably XY. The safest, most portable and widely
accepted approach to having one process create a file and another read
it only after creation is complete is to rename the file upon
completion of creation.

Ha! I wish I had control over the process of creating of those files!
Unfortunately, this is totally out of the question.

The CIFS protocol and client do know something - when I open a CIFS
file in say, notepad, and try mv'ing it from the shell prompt - I get
this:

[root@willow tmp]# mv test.txt test.txt_
mv: preserving ownership for `test.txt_': Operation not permitted
mv: cannot unlink `test.txt': Text file busy
mv: cannot remove `test.txt': Text file busy

I get $! of "Text file busy" from perl when I try to rename. It looks
like this info can be tapped into, I just don't know how.


#!/usr/bin/perl -w
use strict;

my $old_file = shift or die "usage: $0 filename\n";
my $new_file = "$old_file.$$";

do {
$! = '';
rename $old_file, $new_file;
} while $! =~ /Text file busy/;

open my $fh, '<', $new_file or die "$new_file: Cannot open ($!)\n";

# etc. ...




John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top