Bug 138849

Summary: unlink() misbehaviour/interaction with readdir()
Product: [Fedora] Fedora Reporter: Jonathan Allen <jonathan>
Component: glibcAssignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact: Brian Brock <bbrock>
Severity: medium Docs Contact:
Priority: medium    
Version: 2CC: drepper, roland
Target Milestone: ---   
Target Release: ---   
Hardware: i686   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2004-11-12 19:31:04 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
Test program to demonstrate bug none

Description Jonathan Allen 2004-11-11 16:39:46 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3)
Gecko/20040922

Description of problem:
unlink() doesn't seem to synchronise with readdir() while the
directory holding the file is open.

Test program (supplied as attachment) creates a directory, then two
files.  It then opens the directory and reads the entries, printing
the inode number and the filename.  When it finds the first entry, it
deletes the second file and immediately tries to fopen() it - as I
expected, the fopen() call fails [as it should].  However, the next
call to readdir() which is the deleted file, shows it with a non-zero
inode number as if the file still exists.



Version-Release number of selected component (if applicable):
glibc-2.3.3-27.1

How reproducible:
Always

Steps to Reproduce:
1. compile test program
2. run test program
3. observe output
4. do 'ls -al' on the created directory
    

Actual Results:  Dir = D16775
 5505650: .file
 5505651: file
 5410128: ..
 5505649: .


Expected Results:  Dir = D16775
 5505650: .file
       0: file
 5410128: ..
 5505649: .


Additional info:

Comment 1 Jonathan Allen 2004-11-11 16:43:46 UTC
Created attachment 106508 [details]
Test program to demonstrate bug

Compile simply as:

   cc z1.c

then run as:

   a.out

Comment 2 Jakub Jelinek 2004-11-11 20:08:25 UTC
Please cite which standard mandates the behaviour you are asking for.
To my knowledge POSIX doesn't require this and the current glibc behaviour
(caching directory entries).  If you want to see the effect on the next readdir,
you need to closedir and opendir again.

Comment 3 Jonathan Allen 2004-11-12 12:26:55 UTC
The behaviour I expected has 'standard' behaviour for Unices since 
version 5 (and I don't mean System V, either).  This behaviour 
destroys the ability to make a single clean pass through a directory 
and not get (misleading) error reports for files that have been 
removed as a part of processing others.

In this case, I read parameters and control information from an ASCII 
file starting with a '.' character and use it to process images held 
under their own (the same) filename without a preceding '.' as 
generated by some graphics program.  When processed, both files are 
unlinked.  This means that I then (later on in the pass) hit what 
looks to be an error: a filename without a dot which doesn't have a 
matching '.' file which speaks of another application program error.

It isn't that I want to see the effect on the next readdir(), it is 
that the readdir() is returning old and invalid information which 
needn't be because of the current program's activities.  All programs 
that process directories know to ignore entries with a zero inode 
value as being a file that has been deleted but the directory slot 
hasn't been re-used yet, but that a file with a non-zero inode value 
is a good file.  This behaviour breaks that long-standing assumption 
and calls into question the integrity of the file-system by 
presenting a program with what looks like a valid directory entry to 
a file that doesn't exist.

Comment 4 Ulrich Drepper 2004-11-12 19:31:04 UTC
If your program expects this behavior, fix it.  The glibc code is
correct and there will be no change.