From Bugzilla Helper: User-Agent: Mozilla/5.0 Galeon/1.0.2 (X11; Linux i686; U;) Gecko/20011224 Description of problem: The reading file size from a pipe is set to 0 in fstat() of glibc 2.2.4. I was wondering that if you fstat the read end of a pipe, st_size no longer returns the number of bytes sitting in the buffer. In this case, glibc 2.2.4 surely returns 0. The following examinations were performed. Is this a BUG or proper behavior? Version-Release number of selected component (if applicable): How reproducible: Always Steps to Reproduce: 1. See following test. 2. 3. Additional info: -------- test.c ----------- #include <stdio.h> #include <fcntl.h> #include <sys/types.h> #include <sys/file.h> #include <sys/stat.h> #include <sys/errno.h> int main( int argc , char *argv[]) { struct stat buf; if (0 == fstat( fileno(stdin), &buf )) { printf( "size %d\n", buf.st_size ); } else { printf( "size %d\n", buf.st_size ); } exit( 0 ); } -------- test.c ----------- On Red Hat linux 7.1 with glibc 2.2.2 # gcc test.c # echo test > test # ./a.out < test # size 7 # cat test | ./a.out # size 7 On Red Hat linux 7.1 or 7.2 with glibc 2.2.4 # gcc test.c # echo test > test # ./a.out < test # size 7 # cat test | ./a.out # size 0
This has nothing to do with glibc, it is kernel that fills st_size.
Well, I tested by upgrading only glibc (version is 2.2.4) to Red Hat Linux 7.1 just installed. If it does so, this problem did not occur. Next, I updated kernel (kernel version is 2.4.9-12). The problem occurred. Please teach me the solution method.
Created attachment 45479 [details] This is quick hack of this issue. The difference between old kernel and new one, is only in linux/include/pipe_fs.h, PIPE_LEN(inode).
Yes - its a kernel happening. However its just luck it ever worked before. The standards say that i_size is undefined for a pipe. The value 2.4.old used was not always accurate, and with zero copy pipes in the future its going to be basically impossible to duplicate this behaviour. Really you need to fix the code up. For 2.4 there are good reasons to try and put the compatibility back for people which will hopefully occur in a future kernel errata (but no guarantee). After 2.4 all bets are off however.
This hack is dangerous.... setting i_size has on-disk concequences.......
This seems to be fixed on kernel-2.4.9-31, to add 2 lines patch to linux/fs/stat.c, however I'm not sure if this is nice method...
The patch for this is 1889 lines (there was quite a bit of infrastructure work needed for the "2 lines" to be possible). And indeed it's a hack. And yes this will go away in the future. NOTHING specifies what the value of stat should return, and once zero-copy pipes are implemented it'll go away again. Please fix all your applications that depend on this
As you know, if we don't have any source codes of applications we use(it is binary), we can't change them not to confirm the pipe size by using fstat(). To use them for a long time, this fix shouldn't go away, however POSIX doesn't specify it. AFAIK, there are many unix(s) have this feature, solaris, HP-UX, AIX etc. and many applications work on them by using one. If Linux doesn't have this, it may be trouble to port them into Linux without any changes of their sources.
In the long term things like zerocopy pipes mean that the whole question itself becomes meaningless. Obviously we'll do what we can to keep that - its not our desire to break stuff.
Summoning Uli for discussion...
I don't know what you expect to hear from me. Any program which relies on unspecified behavior is non-conforming. Non-conforming programs cannot expect to be unaffected by system changes. A feature is left unspecified if either no concensus about the behavior can be found or, as in this case, it would over-specify the implementation and prevent future development. Implementations will not break unspecified behavior without reason but if it happens and this causes problems its entirely the application's fault.
Reopen this bug - won't fix in errata.
Excuse me ?
After internal discussion, we decided we'll not fix or support this bug in our Red Hat Linux. - It's not disclaimed by POSIX. (We do not agree 100% POSIX, though) - Linux kernel rejects all backward compatibility in its history even if application needs lots of fixes to follow up. This should be marked as WONTFIX
- Linux kernel rejects all backward compatibility in its history even if application needs lots of fixes to follow up. Ehm if we're going to insult eachother here: The Linux kernel provides FULL backwards compatibility to defined behavior. It however does not and cannot provide compatibility to undefined behavior since it's exactly that, undefined. There's no idea what is a valid value in this case, so returning *any* value is like reading tealeaves about what each individual application expects.
But POSIX clearly says: in fstat(3): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [...] The buf argument is a pointer to a stat structure, as defined in <sys/stat.h>, into which information is placed concerning the file. [...] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ and in <sys/stat.h>: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [...] off_t st_size For regular files, the file size in bytes For symbolic links, the length in bytes of the pathname contained in the symbolic link. [...] Unless otherwise specified, the structure members st_mode, st_ino, st_dev, st_uid, st_gid, st_atime, st_ctime, and st_mtime shall have meaningful values for all file types defined in IEEE Std 1003.1-2001. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This means that the value of the st_size after a call to fstat() on the descriptor associated with a FIFO is undefined. Any program relying on a specific behavior is broken.