I noticed the following issue posted one month ago that this is
related with pipe implementation. Currently linux uses
inode->i_pipe->len to keep length of pipe data, but if you want to
detect the size of current pipe length, we cannot get any method.  I
think to keep compatibility using fstat like SysV is useful for some
applications.
I made the below patch which is cleanly applied for both 2.4.18-pre3
and 2.5.2-pre11. This patch simply substitutes i_pipe->len for
inode->i_size. To replace PIPE_LEN using inode->i_size instead of
inode->i_pipe->len is another way but I don't do that.
--- fs/pipe.c.vanilla	Wed Jan  2 04:20:01 2002
+++ fs/pipe.c	Fri Jan  4 02:34:55 2002
@@ -21,6 +21,9 @@
  * 
  * Reads with count = 0 should always return 0.
  * -- Julian Bradfield 1999-06-07.
+ *
+ * Substitute inode->i_size to follow SysV compatibility.
+ * -- GOTO Masanori 2002-01-12.
  */
 
 /* Drop the inode semaphore and wait for a pipe event, atomically */
@@ -101,6 +104,7 @@
 		PIPE_START(*inode) += chars;
 		PIPE_START(*inode) &= (PIPE_SIZE - 1);
 		PIPE_LEN(*inode) -= chars;
+		inode->i_size = PIPE_LEN(*inode);
 		count -= chars;
 		buf += chars;
 	}
@@ -197,6 +201,7 @@
 
 			written += chars;
 			PIPE_LEN(*inode) += chars;
+			inode->i_size = PIPE_LEN(*inode);
 			count -= chars;
 			buf += chars;
 			space = PIPE_FREE(*inode);
@@ -454,7 +459,7 @@
 
 	init_waitqueue_head(PIPE_WAIT(*inode));
 	PIPE_BASE(*inode) = (char*) page;
-	PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
+	PIPE_START(*inode) = PIPE_LEN(*inode) = inode->i_size = 0;
 	PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
 	PIPE_WAITING_READERS(*inode) = PIPE_WAITING_WRITERS(*inode) = 0;
 	PIPE_RCOUNTER(*inode) = PIPE_WCOUNTER(*inode) = 1;
Regards,
-- gotom
At Sat, 8 Dec 2001 13:17:04 -0500,
James Moss <moss@brutesquad.org> wrote:
> I noticed recently that the following no longer works.  I was wondering if
> this is internal to the kernel or if perhaps this is a glibc issue.  Also
> wondering if this was an intential change.  It did 'used to work' but I
> realize that may hold little to no ground since it does seem to be on a per
> implementation basis.  Anyway looking forward to hearing back, feel free to
> show a better way to go about doing what I'm attempting to do.
>      -James Moss
> 
> -------foo.c------------
> #include <stdio.h>
> #include <sys/types.h>
> #include <sys/file.h>
> #include <sys/stat.h>
> #include <sys/errno.h>
> #include <fcntl.h>
> 
> main(argc, argv)
> int argc;
> char **argv;
> {
>     struct stat sb;
>     if (0 == fstat( fileno(stdin), &sb )) {
>         printf( "size %d\n", sb.st_size );
>     } else {
>         printf( "size %d\n", sb.st_size );
>     }
>     exit( 0 );
> }
> 
> -------------------
> 				    
> On HP, Solaris, etc...
> cc foo.c
> echo "abc" > ftext.txt
> ./a.out < ftext.txt
> size 4
> cat ftext.txt | ./a.out
> size 4
> 			    
> On Debian Unstable, latest release of Suse, and latest release of Redhat...
> gcc foo.c
> echo "abc" > ftext.txt
> ./a.out < ftext.txt
> size 4
> cat ftext.txt | ./a.out
> size 0
> 
> Page 90, 4.12 "File Size"
> Advanced Programming in the UNIX Environment states that it's posix compliant
> in SVR4 to have the ability to read file size from a pipe and the st_size of
> the sb struct is defined.... does Linux break SVR4 compliance?  Is there a
> better or new way to do this?
> 
> SVID Vol: 1a Version 4
> 
> Since a pipe is bi-directional, there are two separate flows of data.
> Therefore, the size (st_size) returned by a call to fstat with argument
> fildes[0] or fildes[1] is the number of bytes available for reading from
> fildes[0] or fildes[1] respectively.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/