5

GNU unistd.h has this bit of magic:

/* Move FD's file position to OFFSET bytes from the
   beginning of the file (if WHENCE is SEEK_SET),
   the current position (if WHENCE is SEEK_CUR),
   or the end of the file (if WHENCE is SEEK_END).
   Return the new file position.  */
#ifndef __USE_FILE_OFFSET64
extern __off_t lseek (int __fd, __off_t __offset, int __whence) __THROW;                                                                    
#else
# ifdef __REDIRECT_NTH
extern __off64_t __REDIRECT_NTH (lseek,
                              (int __fd, __off64_t __offset, int __whence),
                               lseek64);                                                                                                    
# else
#  define lseek lseek64
# endif
#endif
#ifdef __USE_LARGEFILE64
extern __off64_t lseek64 (int __fd, __off64_t __offset, int __whence) __THROW;                                                              
#endif

What does __REDIRECT_NTH mean?

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
vy32
  • 28,461
  • 37
  • 122
  • 246

3 Answers3

8

More detail on what REDIRECT_NTH means: The macro generates a function declaration that tells the compiler to use a specific symbol for the function in the compiler's ELF output. By default, the compiler uses the ELF symbol "lseek" for a C function named "lseek" (or, on some systems, "_lseek"). This macro expands to code that tells the compiler to use the symbol "lseek64" instead. So the C code has a function named "lseek", but when you look in the object code (e.g. with program 'nm'), you see "lseek64".

The purpose of that is that the function really is lseek64 at a binary level - it deals in 64 bit file offsets. But the source code has declared that it wants to call it lseek, for backward source compatibility reasons (that's what _FILE_OFFSET_BITS=64 says).

If the source program wants to call lseek64 by that name, and have lseek refer to the old 32 bit version, it must define _LARGEFILE64_SOURCE and not _FILE_OFFSET_BITS=64.

By the way, the "NTH" in "REDIRECT_NTH" refers to "no throw," which is an attribute of the function declaration the macro generates.

damienfrancois
  • 52,978
  • 9
  • 96
  • 110
giraffedata
  • 169
  • 1
  • 5
2

It is a macro in the namespace reserved to the implementation. It only appears on your platform; it does whatever is appropriate on your platform because the implementation decided it is correct.

If you can't find out easily, you probably shouldn't be using it directly. Even if you can find out, there's a good chance you should not be using it directly.

That said, it looks as though it arranges for calls to lseek() to be translated to lseek64(), presumably to provide support for large files (bigger than 2 GiB) on 32-bit machines (or under the 32-bit system API on your 64-bit machine).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • It's actually doing the reverse. Because of all of those squirlly #defines, it's actually defining `lseek()` to take a 64-bit number as the second argument and `lseek64` is not being prototyped. However `lseek64` is still in the library. My problem is that my code needs to run on many different systems, so I explicitly check to see if lseek64 is available and, if so, I use it. On this system (FC14) I'm getting the error that there is no prototype for lseek64. Of course, I could just create one myself. I'd rather not go through all of this nonsense... – vy32 Dec 19 '10 at 02:40
  • ... but if I don't do the nonsense, my program breaks on all sorts of legacy systems that are still in use. – vy32 Dec 19 '10 at 02:42
  • @vy32: OK - it is hard to tell which way round it is working without knowing the platform or seeing the macro definition. How are you doing your test for `lseek64()`? Are you using `autoconf` or one its relatives? If `lseek64()` is being defined (in the library) not prototyped, you have to make a judgement call - do you provide an appropriate declaration for it, or do you fall back on `lseek()`. Presumably, your code has appropriate mappable type definitions such that you can handle all the types you need (32-bit or 64-bit) and you can determine the correct values/names on this platform. – Jonathan Leffler Dec 19 '10 at 03:36
  • @jonathan leffler - Thanks for your comments. The unistd.h is the standard GNU unistd.h from FC14 (also present on Debian). My code won't work on a system without a 64-bit `lseek`. I guess I just need to prototype it. It's very frustrating. I wish there was some easy way to detect non-standard implementations. – vy32 Dec 19 '10 at 03:41
  • @vy32: FC14? Fedora Core version 14? And didn't you say that the macro ensures that `lseek()` is equipped with a 64-bit offset, so you should just use that, shouldn't you? There's no need for `lseek64()` when `lseek()` is equipped for 64-bit offsets. – Jonathan Leffler Dec 19 '10 at 03:49
  • @Jonathan, yes Fedora Core 14. The problem is that there is no obvious way to test lseek() in autoconf to see if it is a real 64-bit version of lseek (as it is on FC14), or an old, broken version of lseek() on systems that provide a 32-bit lseek() and a 64-bit lseek64() (there are many of these systems still in use). – vy32 Dec 19 '10 at 05:29
  • 1
    @vy32: Can't you just test for the length of `off_t`? – caf Dec 19 '10 at 12:55
  • Yes, you can test for length of off_t. That's going to be a runtime test that you can't do with an #ifdef. So what do you do if it turns out that off_t is 32 bits? And what do you do on systems that don't have off_t? The mingw cross-compiler defines lseek as `lseek(int,long,int)` and has a separate `lseek64`. – vy32 Dec 19 '10 at 16:39
  • Send a bug report to the mingw team. There's no excuse for them to export broken interfaces when the correct ones exist. In the mean time, adding your own hackish fixes (`#define lseek lseek64` etc.) **in a file that is isolated and will never be included on conformant systems** is probably the best bet. Forget `__REDIRECT_NTH`. It's a hack to make the ugly way glibc does large file support slightly less non-conformant than it would otherwise be. – R.. GitHub STOP HELPING ICE Dec 19 '10 at 16:59
  • @vy32: This is exactly the kind of problem that `configure` scripts were invented to solve. – caf Dec 22 '10 at 01:22
0

Never touch the largefile hacks yourself. Always include -D_FILE_OFFSET_BITS=64 in your CFLAGS and you can never go wrong.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • Well, actually, that's not true. I have -D_FILE_OFFSET_BITS=64 in my configure file. The problem is that people are using my code on versions of Unix that do not have _FILE_OFFSET_BITS. – vy32 Dec 19 '10 at 16:39
  • Do these versions of unix have a different way to enable a 64-bit file offset compilation environment? Try `sysconf _POSIX_V6_ILP32_OFFBIG` or similar. If they don't, then IMO you shouldn't try hacking the OS to force it. Just tell users of these broken systems they should complain to their vendor to fix large file support or switch to a decent OS. – R.. GitHub STOP HELPING ICE Dec 19 '10 at 16:54
  • your recommendation is really not an option in most environments. – vy32 Nov 28 '13 at 21:50
  • @vy32: Which part? I'm not aware of **any** implementation that makes you roll your own hacks copying and pasting macros from the glibc headers to get 64-bit off_t... – R.. GitHub STOP HELPING ICE Nov 29 '13 at 02:01
  • Telling my users that their systems are broken and they should fix or upgrade is not an option. They have their systems and my software has to work on them. Period, end of story. – vy32 Nov 29 '13 at 02:48