Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

fseek versus lseek

Status
Not open for further replies.

dickiebird

Programmer
Feb 14, 2002
758
GB
Hi
I'm having problems fseeking on a binary file.
I tried lseek with similar problems.
Fseek works for about 200 records then I get :
16846 Memory fault(coredump)
Lseek works for 1 record and gives same problem
Relevant code is :

long pos,ddd;
char buff[40];
FILE *fd = fopen("fileix20","rb");
while(fgets(buff,40,stdin))
{
pos = strtoul(buff,NULL,10) - 10;
printf("Trace A\n");
ddd=lseek(fd,pos,0);
printf("Trace B ddd=%d\n",ddd);
}

With fseek:
Trace A and B show 200 times
Trace B always prints a value ( = offset position )
but doesn't print after failure

With lseek
Trace A shows 2 times
Trace B has a value = -1
then doesn't show after failure

Apart from my memory fault, what is the difference between
lseek & fseek anyway. I've read the manuals, but can't appreciate any difference.
Any ideas would be welcome
TIA ;-) Dickie Bird
Honi soit qui mal y pense
 
fseek is ANSI, lseek isn't. lseek exists in lots of the older libraries before ANSI fseek became the standard.
 
fseek works with file pointers and lseek with file descriptors.

hnd
hasso55@yahoo.com

 
Fseek() need a FILE *fd;
Lseek() need an int fd;
---------------------------
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#define MAX 40

main()
{
long pos,ddd;
char buff[MAX+1];

/***REM FILE *fd = fopen(&quot;fileix20&quot;,&quot;rb&quot;); ***/

int fd = open(&quot;fileix20&quot;,O_RDONLY);

if(0 >fd) exit(1);

while(fgets(buff,MAX,stdin))
{
pos = strtoul(buff,(char *)NULL,10) - 10;
if(0 >pos ) break;
printf(&quot;Trace A %d\n&quot;,pos);
ddd = lseek(fd,pos,SEEK_SET);
printf(&quot;Trace B ddd=%d\n&quot;,ddd);
}
close(fd);
exit(0);
}
-----------
when they don't ask you anymore, where they are come from, and they don't tell you anymore, where they go ... you'r getting older !
 
Hmmmmm
I changed the FIle *fd to int fd;
and opened as suggested above, but now, when I try
getc(fd) - my compiler objects :
/*FILE *fd = fopen(&quot;fileix20&quot;,&quot;rb&quot;);*/
int fd = open(&quot;fileix20&quot;,O_RDONLY);
while(fgets(buff,23,stdin))
{
pos = strtoul(buff,NULL,10) - 10;
if(0 >pos ) break;
ddd=lseek(fd,pos,0);
if(0 >ddd ) break;
memset(buff2,'\0',21);
for(nnn=0;nnn<20;nnn++) buff2[nnn]=getc(fd);
printf(buff2);
}

&quot;utget_write.c&quot;, line 64.42: 1506-122 (S) Expecting pointer to struct or union.

Can't I use getc now ?
Dickie Bird
Honi soit qui mal y pense
 
getc() needs a FILE *fd
-----------
when they don't ask you anymore, where they are come from, and they don't tell you anymore, where they go ... you'r getting older !
 
i prefer 'read()' -----------
when they don't ask you anymore, where they are come from, and they don't tell you anymore, where they go ... you'r getting older !
 
Ok - The story :
I need to examine and recreate data from a file with binary content. I can locate strings within the file and work out a position to start from, to load up a buffer with various strings, floats, ints etc. I will eventually use the output as the basis for a replacement for the original file.
All works well for the 1st 200 records, then I get a memory fault.
I can't post the data, its got 80% binary info, which will not show too well. There are null bytes too.
Here's the whole code :
#include <stdio.h>
#include <stdlib.h>
#include &quot;/usr/cg-index/include/ciutil.h&quot;
#include <sys/types.h>
#include <unistd.h>

static double to_power_of(double val, int power)
{
double num;
int c;

num = 1;
for (c=0; c < power; c++)
{
num = num * val;
}

return(num);
}


double cvt_bytes_to_num(char *value)
{
double num;
int loop;
int power = 5;
num = 0.0;

for (loop = 0; loop != 6; loop++)
num += (double)(value[loop] * to_power_of(2, 8 * (power--)));
return (num);
}


int main(int argc, char **argv)
{
int nnn;
ulong pos;
ulong rpos;
ulong chqno;
double dchqno;
int range;
int curiss;
char buff[24];
char fuff[21];
char nuff[21];
char fluff[30];
FILE *fd = fopen(&quot;lrlaix20&quot;,&quot;rb&quot;);
/*int fd = open(&quot;lrlaix20&quot;,O_RDONLY);*/
FILE *fout = fopen(&quot;lrlamn20&quot;,&quot;w&quot;);
while(fgets(buff,23,stdin))
{
pos = strtoul(buff,NULL,10) - 10;
fseek(fd,pos,0);
memset(fuff,'\0',21);
for(nnn=0;nnn<20;nnn++) fuff[nnn]=getc(fd);
if(fuff[0]=='ÿ') memcpy(nuff,fuff+1,20); else memcpy(nuff,fuff,20);
if((nuff[0]==0)&&(nuff[1]==0)) memcpy(fuff,nuff+1,20); else memcpy(fuff,nuff,20);
rpos=c_to_l(fuff+16,0);
curiss=c_to_s(fuff,0);
range=c_to_s(fuff+8,0);
if(curiss%10!=6)
{
chqno=c_to_l(fuff+4,0);
sprintf(fluff,&quot;%3d%c%c%09ld%04d%c%c%c%c%c%c%5d\n&quot;,curiss,fuff[2],fuff[3],chqno,range,fuff[
10],fuff[11],fuff[12],fuff[13],fuff[14],fuff[15],rpos);
}
else
{
dchqno=cvt_bytes_to_num(fuff+2);
sprintf(fluff,&quot;%3d|%013.0f|%04d|%c%c%c%c%c%c|%5d\n&quot;,curiss,dchqno,range,fuff[10],fuff[11],
fuff[12],fuff[13],fuff[14],fuff[15],rpos);
}

printf(fluff);
/*fwrite(fout,21,1,fluff);*/
}
fclose(fd);
fclose(fout);
}

here's the last lines of my output :

fuff=|0|110|73|84|2|103|65|126|0|9|83|48|51|52|32|32|0|0|41|10
F
G
H
110IT0403214060009S034 10506
A
C
D
E
fuff=|0|116|5|8|5|225|129|148|0|99|52|48|51|50|49|32|0|0|41|0
F
G
H
116|5532016542100|0099|40321 |10496
A
ksh: 17214 Memory fault(coredump)

Shows last 2 records processed OK, then start on the next (where I display A) and it falls over.
Now I'm stuck !!!!
;-)
Dickie Bird
Honi soit qui mal y pense
 
you are PROBABLY blowing up your double vars.
use dc|bc
i posted in this forum: pipe to dc (using c)
i will read your code this weekend.

-----------
when they don't ask you anymore, where they are come from, and they don't tell you anymore, where they go ... you'r getting older !
 
a first look:


for(nnn=0;nnn<20;nnn++) fuff[nnn]=getc(fd);
if(fuff[0]=='ÿ') memcpy(nuff,fuff+1, 20 );

should not be

for(nnn=0;nnn<20;nnn++) fuff[nnn]=getc(fd);
if(fuff[0]=='ÿ') memcpy(nuff,fuff+1, 19 );

??
post also the c_to_[ls]() functions.
-----------
when they don't ask you anymore, where they are come from, and they don't tell you anymore, where they go ... you'r getting older !
 
i don't understand, this code should crash on the fist

sprintf(fluff,&quot;%3d| %013.0f |%04d|%c%c%c%c%c%c|%5d\n&quot;,curiss, dchqno ,range,fuff[10],....

dchqno is a double !!! not a float -----------
when they don't ask you anymore, where they are come from, and they don't tell you anymore, where they go ... you'r getting older !
 
Thanks for your efforts, Jamisar
Here's the c_to_l/s code

Name:
long c_to_l( rec, cindex )
Parameters:
char *rec - char array to be converted into long.
int cindex - If true, long stored in char arrayis in cindex
format
Purpose:
Converts a char array into a long. If the IEEE format is
defined the top bit ( i.e. the bit that indicates the sign )
is toggled. This results in a byte by byte comparison of two
converted longs (one negative and one positive ) to return
the same result as if the two longs were compared.
Returns:
Long.
--------------------------------------------------------------------*/
long c_to_l( rec, cindex )
unsigned char *rec;
int cindex;
{
static char c[sizeof(long)];
static unsigned long l;
unsigned char t;
register int ii;

memcpy( c, rec, sizeof(long) );

if ( cindex )
{
/* a long integer is 4 bytes when stored in the file */
#ifdef IEEE

c[0] = ( c[0] & 0x80 ) ? (c[0] & 0x7F) : (c[0] | 0x80) ;

#ifdef RIEEE
t = c[0]; c[0] = c[3]; c[3] = t;
t = c[1]; c[1] = c[2]; c[2] = t;
#endif

memcpy( &l, c, 4);
#else
/*
Generalized number for which we do not know the
machine bit pattern.
*/

l = ( c[0] & 0x80 ) ? (c[0] & 0x7F) : -(c[0] & 0x7F);

for (ii = 1; ii < 4; )
{
l = l * 0x100 + c[ii++];
}
#endif
}
else
{
l = c[0];

for (ii = 1; ii < sizeof(long); ++ii )
{
l = l * 0x100 + c[ii];
}
}

return( (long)l );
}
/*--------------------------------------------------------------------
Name:
short c_to_s( c, cindex )
Parameters:
char *c - char array to be converted into long.
int cindex - If true, short stored in char array is in cindex
format
Purpose:
Converts a char array into a short. If the IEEE format is
defined the top bit ( i.e. the bit that indicates the sign )
is toggled. This results in a byte by byte comparison of two
converted shorts (one negative and one positive ) to return
the same result as if the two shorts were compared.
Returns:
Short.
--------------------------------------------------------------------*/
short c_to_s( rec, cindex )
unsigned char *rec;
int cindex;
{
char c[sizeof(short)];
static unsigned short s;
unsigned char t;
register int ii;


memcpy( c, rec, sizeof(short) );

if ( cindex )
{
/* a short integer is 2 bytes when stored in the file */
#ifdef IEEE
c[0] = ( c[0] & 0x80 ) ? c[0] & 0x7F : c[0] | 0x80;

#ifdef RIEEE
t = c[0]; c[0] = c[1]; c[1] = t;
#endif

memcpy( &s, c, 2 );
#else
/*
Generalized number for which we do not know the
machine bit pattern.
*/

s = ( c[0] & 0x80 ) ? (c[0] & 0x7F) : -(c[0] & 0x7F);
s = s * 0x100 + c[1];
#endif
}
else
{
s = c[0];

for (ii = 1; ii < sizeof(short); ++ii )
{
s = s * 0x100 + c[ii];
}
}

return( (short)s );
}

Though, as my trace seems to show, its the fseek that appears to be failing.
I'm losing it with this project ! ;-( Dickie Bird
Honi soit qui mal y pense
 
forget last remarque. -----------
when they don't ask you anymore, where they are come from, and they don't tell you anymore, where they go ... you'r getting older !
 
xwb: about ANSI or not ANSI, lock at the fseek-code
included below :))

dbird: i compiled your code, it's ok, questions:
how big is the input 'irlaix20'
exec a ls -l && wc on it
can you post lines 190-210 of the inputfile 'stdin'
for testing: can you e-mail the first 2-3000 chars
of the 'irlaix20'
my be you have to split it
to: priam@freenet.de
xwb -------------- fseek.c
/*LINTLIBRARY*/
/*
* Seek for standard library. Coordinates with buffering.
*/
#include <stdio.h>

extern long lseek();
/* aaaaaaannnnnnnssssssiiiii JAMISAR dixit*/
extern int fflush();

int
fseek(iop, offset, ptrname)
register FILE *iop;
long offset;
int ptrname;
{
register int resync, c;
long p = -1; /* can't happen? */

iop->_flag &= ~_IOEOF;
if(iop->_flag & _IOREAD) {
if(ptrname < 2 && iop->_base && !(iop->_flag&_IONBF)) {
c = iop->_cnt;
p = offset;
if(ptrname == 0) {
long curpos = lseek(fileno(iop), 0L, 1);
/* aaaaaaannnnnnnssssssiiiii JAMISAR dixit*/
if (curpos == -1)
return (-1);
p += c - curpos;
resync = offset&01;
} else {
offset -= (long)c;
resync = 0;
}
if(!(iop->_flag&_IORW) && c > 0 && p <= c &&
p >= iop->_base - iop->_ptr) {
iop->_ptr += (int)p;
iop->_cnt -= (int)p;
return(0);
}
} else
resync = 0;
if(iop->_flag & _IORW) {
iop->_ptr = iop->_base;
iop->_flag &= ~_IOREAD;
resync = 0;
}
p = lseek(fileno(iop), offset-resync, ptrname);
/* aaaaaaannnnnnnssssssiiiii JAMISAR dixit*/
iop->_cnt = 0;
if (resync && p != -1)
if (getc(iop) == EOF)
p = -1;
} else if(iop->_flag & (_IOWRT | _IORW)) {
p = fflush(iop);
iop->_cnt = 0;
if(iop->_flag & _IORW) {
iop->_flag &= ~_IOWRT;
iop->_ptr = iop->_base;
}
return(lseek(fileno(iop), offset, ptrname) == -1 || p == EOF ?
/* aaaaaaannnnnnnssssssiiiii JAMISAR dixit*/
-1 : 0);
}
return((p == -1)? -1: 0);
}

/* aaaaaaannnnnnnssssssiiiii JAMISAR dixit :)))))*/
-----------
when they don't ask you anymore, where they are come from, and they don't tell you anymore, where they go ... you'r getting older !
 
Jamisar
Found the error - char fluff[30] wasn't big enough for the sprintf !!!!!!!!!!!
Gross mistake on my part !!
Sorry to waste so much of your time.
Regards Dickie Bird
Honi soit qui mal y pense
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top