itkin@mrspoc.UUCP (Steven M. List) (05/02/89)
I am trying to write a simple little program to swap bytes and/or words in a file. The program works great except for one little problem. When I try to do it in place, the file just keeps growing and growing and... The following fragment is the functional piece of code. When I've run it under sdb, I find that when the program should be reading zero bytes it is still returning 1024 in bytesread. It then writes out that 1k chunk and apparently thinks that it's read in another 1k block. From what I've been able to tell, the block that it locks in on is the first block in the file! That is, it keeps reading and writing the first 1k block in the file indefinitely. When I commented out the fseeks and ftells and changed it to write to stdout (as you see here), it worked great. This, needless to say, is happening on XENIX 2.3.1 with the 2.2.3 development system. I haven't a clue. fread appears to work properly under all other circumstances. I don't appear to be doing anything wrong with the ftell and fseek calls (I've checked as far as I can in sdb). Hmmmmm... Any suggestions? Please? ------------------------------------------------------------------------------ do_byte_swap (swabfile) register FILE *swabfile; { extern long ftell (); extern int fseek (); long startpos; char inbuf[1024]; char outbuf[1024]; int bytesread; int byteswritten; register int blocknum = 0; register int rc; rewind (swabfile); /* startpos = ftell (swabfile); */ bytesread = fread (inbuf, sizeof (char), sizeof inbuf, swabfile); while (bytesread > 0) { swab (inbuf, outbuf, bytesread); /* if ((rc = fseek (swabfile, startpos, 0)) != 0) */ /* { */ /* fprintf (stderr, "file seek error, status = %d\n", rc); */ /* exit (1); */ /* } */ /* byteswritten = fwrite (outbuf, sizeof (char), bytesread, swabfile); */ byteswritten = fwrite (outbuf, sizeof (char), bytesread, stdout); if (byteswritten != bytesread) { fprintf (stderr, "swabbit: write error: read %ld bytes, wrote %ld bytes\n", bytesread, byteswritten); fprintf (stderr, " restore file from backup - probably corrupted!\n"); exit (1); } /* fflush (swabfile); */ /* startpos = ftell (swabfile); */ bytesread = fread (inbuf, sizeof (char), sizeof inbuf, swabfile); fprintf (stderr, "%d", ++blocknum); if ((blocknum % 70) == 0) fprintf (stderr, "\n"); } fprintf (stderr, "\n"); return 0; } -- : Steven List @ Transact Software, Inc. :^>~ : Chairman, Unify User Group of Northern California : {apple,coherent,limbo,mips,pyramid,ubvax}!mrspoc!itkin : Voice: (415) 961-6112
maart@cs.vu.nl (Maarten Litmaath) (05/03/89)
itkin@mrspoc.UUCP (Steven M. List) writes:
\...
\ byteswritten = fwrite (outbuf, sizeof (char), bytesread, swabfile);
\...
\ bytesread = fread (inbuf, sizeof (char), sizeof inbuf, swabfile);
RTFM (fopen(3s)):
When a file is opened for update, both input and output may
be done on the resulting stream. However, output may not be
^^^^^^^^^^^^^^^^^^^^^^^^^^
directly followed by input without an intervening fseek [...] :-(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Solution: insert
fseek(swabfile, ftell(swabfile), 0);
At first sight this looks like a no-op, but there are some `interesting'
side-effects...
What to do if you f*ck things up? Just put it in the FM: it's a feature!
(Which will live on forever.)
BTW, whom can we sue for this? :-)
--
"If it isn't aesthetically pleasing, |Maarten Litmaath @ VU Amsterdam:
it's probably wrong." (jim@bilpin) |maart@cs.vu.nl, mcvax!botter!maart
chapman@sco.COM (Brian Chapman) (05/04/89)
In article <7327@mrspoc.UUCP> itkin@mrspoc.UUCP (Steven List) writes: >I am trying to write a simple little program to swap bytes and/or words >in a file. The program works great except for one little problem. When >I try to do it in place, the file just keeps growing and growing and... I think I can guess your problem. [ Although your code fragment was not sufficent to be sure ]. The old V7 and or BSD trick of opening a file for appending (eg. fopen(....."a");) and then rewinding it; doesn't work on System V compatibile systems. Open for appending inforces an implied seek() to EOF on writes. So you read from the front of the file and your writes get added to the end, to be read again and added as yet more data at the end of file to be read again.... Try just opening the file read|write. (fopen(....."r+");) [ I once chased this "feature" all the way to the exact line in ] [ in the kernel, and was about to report it as a bug. Until a ] [ co-worked pointed it out in the SVID. :-) ] -- Pay no attention to the man behind the curtain. Brian Chapman uunet!sco!chapman SCO UNIX 3.2 Development
davidsen@sungod.steinmetz (William Davidsen) (05/04/89)
In article <2445@solo3.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: |Solution: insert | | fseek(swabfile, ftell(swabfile), 0); | |At first sight this looks like a no-op, but there are some `interesting' |side-effects... I wasn't going to say anything, but this is a real kludge solution (it works, however). If you do fseek(swabfile, 0L, 1); It avoids the call to ftell. There's no reason to "tell me where I am and then seek back there," when "move me zero bytes from where I am" will suffice.
det@hawkmoon.MN.ORG (Derek E. Terveer) (05/12/89)
In article <7327@mrspoc.UUCP>, itkin@mrspoc.UUCP (Steven M. List) writes: > I am trying to write a simple little program to swap bytes and/or words > in a file. I'm not sure if this will do what you want, but you might want to check out the command: dd if=file_name conv=swab which swaps every pair of bytes in the input stream. dd(1m) derek -- Derek Terveer det@hawkmoon.MN.ORG || ..!uunet!rosevax!elric!hawkmoon!det w(612)681-6986 h(612)688-0667 "A proper king is crowned" -- Thomas B. Costain