Sender: rich AT phekda DOT freeserve DOT co DOT uk Message-ID: <3BC74CBE.EC9CBF9F@phekda.freeserve.co.uk> Date: Fri, 12 Oct 2001 21:04:14 +0100 From: Richard Dawe X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.2.19 i586) X-Accept-Language: de,fr MIME-Version: 1.0 To: djgpp-workers AT delorie DOT com Subject: Re: Resend: DJGPP and files > 2GB References: <200110120744 DOT JAA24662 AT lws256 DOT lu DOT erisoft DOT se> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Reply-To: djgpp-workers AT delorie DOT com Hello. Martin Stromberg wrote: > > Richard said: > > I'm not convinced by your argument. Consider relative seeks: > > > > lseek(fd, SEEK_SET, 2GB - 10); > > lseek(fd, SEEK_CUR, 1GB); > > > > Now I want to seek backwards 2.5GB. How would I do that? How does > > lseek > > lseek(fd, SEEK_CUR, -2.5GB) (or lseek(fd, SEEK_CUR, -2.5GB + 2^32), > it's the same thing). > > > know which direction I want to go for relative seeks with |offset| > > 2GB? > > It doesn't and doesn't need to as everything is done mod 2^32. _Or_ > perhaps it does and acts differently depending on current position and > seek offset. Ah, OK, I think I see what you're saying now. Sorry for being a little slow on the uptake. Relative seeks seem to be handled mod 2^32 too. Please find my test program below, that tests out relative seeks - it relies on the fact that lseek passes the offset directly to the DOS interrupt. Ralph Brown's interrupt list mentions that it's possible to set the file position before the start of the file (i.e. off_t is negative). With support for files greater than 2GB, I guess this isn't true with >2GB support, since the negative off_t values actually mean offsets >= 2GB. BTW I just discovered that 'du' is broken by stat's st_size member wrapping. I'll look at adding basic support for LFS this weekend. > > Incidentally, why does lseek check whether the file descriptor is a > > pipe or not, after it's done the INT21h call? Shouldn't it do it > > before the interrupt? > > Don't know. Mark, do you know why this is? It seems to be your change. Perhaps it was added here, because the fd properties code was already in that part of the function. This problem is also present in llseek. I think the check belongs after the FSEXT call, but before the DOS interrupt. Thanks, bye, Rich =] ---START bigseek.c--- /* * bigseek.c * Try big relative seeks with DJGPP CVS (aka 2.04?) * Written by Richard Dawe */ #include #include #include #include #include #include int main (int argc, char *argv[]) { char *filename; struct stat sbuf; unsigned long sz; ssize_t n; char buf[4]; off_t o; int fd; /* 2GB + 100MB */ const unsigned long big_offset = (1024UL * 1024UL * 1024UL * 2UL) + (1024UL * 1024UL * 100UL); /* 2GB + 10MB */ unsigned long big_offset2 = (1024UL * 1024UL * 1024UL * 2UL) + (1024UL * 1024UL * 10UL); assert(big_offset2 < big_offset); if (argc < 2) { fprintf(stderr, "Oi! Where's me file?\n"); return(EXIT_FAILURE); } /* Does the file exist? How big is it? */ filename = argv[1]; if (stat(filename, &sbuf) < 0) { perror(argv[0]); return(EXIT_FAILURE); } if (!S_ISREG(sbuf.st_mode)) { fprintf(stderr, "%s is not a regular file!\n", filename); return(EXIT_FAILURE); } /* Check the file's bigger than 2GB. */ sz = (unsigned long) sbuf.st_size; if (sz <= big_offset) { fprintf(stderr, "%s is not bigger than %lu (%luMB)!\n", filename, big_offset, big_offset / (1024UL * 1024UL)); return(EXIT_FAILURE); } /* Now open the file and try out some big relative seeks (> 2GB movement). */ fd = open(argv[1], O_RDONLY|O_BINARY); o = lseek(fd, big_offset, SEEK_SET); printf("Offset %lu (desired = %lu)\n", (unsigned long) o, big_offset); o = lseek(fd, big_offset2, SEEK_CUR); printf("Offset %lu (desired = %lu)\n", (unsigned long) o, big_offset + big_offset2); printf("big_offset - big_offset2 = %lu\n", big_offset - big_offset2); printf("big_offset + big_offset2 = %lu\n", big_offset + big_offset2); printf("(off_t) big_offset2 = %d\n", (off_t) big_offset2); /* Return to the start, seek to beyond 2GB, try a read. Then try * a large (2GB - 1) backwards seek. */ o = lseek(fd, 0, SEEK_SET); printf("Offset %d\n", o); o = lseek(fd, big_offset, SEEK_CUR); printf("Offset %d\n", o); n = read(fd, buf, sizeof(buf)); if (n < sizeof(buf)) { fprintf(stderr, "Read at offset %d (aka %lu?) failed\n", o, (unsigned long) o); close(fd); return(EXIT_FAILURE); } else { printf("Read at offset %d (aka %lu?) OK\n", o, (unsigned long) o); } o = lseek(fd, -sizeof(buf), SEEK_CUR); /* Return to pre-read position */ o = lseek(fd, -(off_t)((1024UL * 1024UL * 1024UL * 2UL) - 1UL), SEEK_CUR); printf("Offset %d\n", o); printf("big_offset - 2GB - 1 = %lu\n", big_offset - ((1024UL * 1024UL * 1024UL * 2UL) - 1UL)); /* Done with file */ close(fd); return(EXIT_SUCCESS); } ---END bigseek.c---