[comp.lang.c] lseek problem

gwyn@smoke.BRL.MIL (Doug Gwyn) (10/07/89)

In article <20065@mimsy.UUCP> lint@mimsy.umd.edu (The Lint Program) writes:
>In article <14657@uhnix1.uh.edu> jsmng@sysmgr.cs.uh.edu writes:
>[c code deleted]
>t.c:
>t.c(5): warning: argument argc unused in function main
>lseek, arg. 1 used inconsistently	llib-lc(90)  ::  t.c(19)
>lseek, arg. 2 used inconsistently	llib-lc(90)  ::  t.c(19)
>lseek value used inconsistently	llib-lc(90)  ::  t.c(19)
>lseek value declared inconsistently	llib-lc(90)  ::  t.c(19)
>printf returns value which is always ignored

"lint" missed some other problems:
exit() misdeclared
lseek() return comparison against NULL is wrong
fgetc() return not compared against EOF
<sys/file.h> L_SET should not be used in an application
...

"What is wrong with this program?" reminded me of the "What is wrong
with this picture?" puzzles in children's books.  Often my reaction
was, "What is RIGHT with this picture?".

jsmng@sysmgr.cs.uh.edu (10/08/89)

I have a small problem about lseek. I
tried to use the following program to
lseek a file ( with numbers 1 2 3 ).
I expect to get back 1, blank, and 1 again.
But my output was 1, blank and 2.
Initially I use fscanf(fp,"%f",&float_variable)
in place of fgetc and received 1 2 3 instead
of 1 2 1. Can anyone tell me what I did wrong?
Thanks. I think this is probably something
simple so please just send me a mail and
I will summarize it.


#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h> 
main(argc,argv)
int argc;
char *argv[];
{
  FILE *fp;
  char c1,c2,c3;

  if ((fp = fopen(argv[1],"r")) == NULL) {
    perror("cannot open file");
    exit(1);
  }
  c1 = fgetc(fp);
  printf("first number = %c\n",c1);
  c2 = fgetc(fp);
  printf("second number = %c\n",c2);
  if (lseek(fp,0,L_SET) == NULL) {
    perror("lseek error");
    exit(1);
  }
  c3 = fgetc(fp);
  printf("first number again = %c\n",c3);
}

lint@mimsy.umd.edu (The Lint Program) (10/09/89)

In article <14657@uhnix1.uh.edu> jsmng@sysmgr.cs.uh.edu writes:
[c code deleted]
t.c:
t.c(5): warning: argument argc unused in function main
lseek, arg. 1 used inconsistently	llib-lc(90)  ::  t.c(19)
lseek, arg. 2 used inconsistently	llib-lc(90)  ::  t.c(19)
lseek value used inconsistently	llib-lc(90)  ::  t.c(19)
lseek value declared inconsistently	llib-lc(90)  ::  t.c(19)
printf returns value which is always ignored

cpcahil@virtech.UUCP (Conor P. Cahill) (10/10/89)

In article <14657@uhnix1.uh.edu>, jsmng@sysmgr.cs.uh.edu writes:
>   if (lseek(fp,0,L_SET) == NULL) {
              ^^

lseek requires a file descriptor, not a file pointer.  Try fseek().


-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

jsmng@csuna.cs.uh.edu (10/10/89)

I posted a problem I encountered  with lseek mainly due to my own
defiency in C. The problem was I was aware of the difference in
buffered I/O and low lever I/O. I have received a lot of constructive
comments. They are all similar so I chose one which seems to be quite
informative to post. Thanks for the contribution.


From amdcad!cayman!tim@ames.arc.nasa.gov Mon Oct  9 09:08:10 1989
Return-Path: <amdcad!cayman!tim@ames.arc.nasa.gov@cs.uh.edu>
Received: from ames.arc.nasa.gov by sun1.cs.uh.edu (4.0/SMI-3.2)
	id AA05545; Mon, 9 Oct 89 09:08:07 CDT
Received: by ames.arc.nasa.gov (5.61/1.2); Mon, 9 Oct 89 07:06:51 -0700
Received: by amdcad.AMD.COM (5.51/2.6)
	 id AA13558; Mon, 9 Oct 89 06:56:33 PDT
Received: by cayman.AMD.COM (4.0/SMI-4.0)
	id AA13703; Mon, 9 Oct 89 08:59:11 CDT
Date: Mon, 9 Oct 89 08:59:11 CDT
From: amdcad!cayman!tim@ames.arc.nasa.gov (Tim Olson)
Message-Id: <8910091359.AA13703@cayman.AMD.COM>
To: jsmng@sysmgr.cs.uh.edu
Subject: Re: lseek problem
Newsgroups: comp.lang.c
In-Reply-To: <14657@uhnix1.uh.edu>
Organization: Advanced Micro Devices, Austin, TX
Cc: 
Status: RO

In article <14657@uhnix1.uh.edu> you write:
| I have a small problem about lseek. I
| tried to use the following program to
| lseek a file ( with numbers 1 2 3 ).
| I expect to get back 1, blank, and 1 again.
| But my output was 1, blank and 2.
| Initially I use fscanf(fp,"%f",&float_variable)
| in place of fgetc and received 1 2 3 instead
| of 1 2 1. Can anyone tell me what I did wrong?
| Thanks. I think this is probably something
| simple so please just send me a mail and
| I will summarize it.

You can't mix lseek and f{scan,get}f.  The later functions use the
buffered I/O provided in the stdio package.  What is happening is that
on your first fscanf, an attempt is made to read BUFSIZE bytes from
the file and place them into the _iob structure.  Once this is done,
the fscanf reads out of this buffer.  Lseeks do not affect this buffer
at all; they change the actual file pointer (affecting reads and
writes).  What you want to use is fseek, which works with the other
"f" functions.

-- 
	-- Tim Olson
	Advanced Micro Devices
	(tim@amd.com)

rns@se-sd.NCR.COM (Rick Schubert ) (10/13/89)

In article <14779@uhnix1.uh.edu> jsmng@csuna.cs.uh.edu () writes:
>I posted a problem I encountered  with lseek mainly due to my own
>defiency in C. The problem was I was aware of the difference in
>buffered I/O and low lever I/O. I have received a lot of constructive
>comments. They are all similar so I chose one which seems to be quite
>informative to post. Thanks for the contribution.

>>	-- Tim Olson
>>You can't mix lseek and f{scan,get}f.  The later functions use the
>>buffered I/O provided in the stdio package.  What is happening is that
>>on your first fscanf, an attempt is made to read BUFSIZE bytes from
>>the file and place them into the _iob structure.  Once this is done,
>>the fscanf reads out of this buffer.  Lseeks do not affect this buffer
>>at all; they change the actual file pointer (affecting reads and
>>writes).  What you want to use is fseek, which works with the other
>>"f" functions.

Unfortunately, you (jsmng@csuna.cs.uh.edu) chose the wrong response to post
as the right answer.  While much of what Tim said is correct (or at least
correct with traditional Unix implementations of |lseek|/|fseek| -- |lseek|
is not an ANSI library functions; POSIX owns |lseek|, but I don't
know what it says about the relationship between |lseek| and |fseek|), his
explanation doesn't explain why your example failed.  I'm pretty sure there
were correct responses posted, but they have expired on our system.

The immediate problem with your program is that (as I believe others have said)
|lseek| expects an |int| as an argument, and you passed it a |FILE *| argument.
|lseek| will try to interpret the bits of the |FILE *| argument as an integer
to determine what file to manipulate.  It will almost assuredly find garbage
and either do nothing or do something potentially destructive to your address
space.  It is very unlikely that it will do anything constructive regarding
the file you were trying to manipulate.

Now, if, instead of
        FILE    *fp;
        /*...*/
        lseek(fp,/*...*/);
you had,
        lseek(fileno(fp),/*...*/);

then Tim's explanation would have applied.

-- Rick Schubert (rns@se-sd.sandiego.NCR.COM)

Although correct explanations to the original problem were posted and I make
it a policy to not contribute to the problem of multiple correct solutions
being posted, the article I am following up to was posted as the final say
in this matter, and in the three days since the article appeared on my machine,
no articles have appeared here that have corrected this "final say".