In all of the commentary on lseek, I have not seen anyone describe
what *really* happens.
The lseek() call normally just updates the kernel's file table offset
as needed, then returns. Older kernels also check to make sure that
the resulting offset is non-negative (as the documentation claims).
(In 4.4BSD this nonsense is gone; file offsets can be up to 2^63 anyway.)
Why, then, do some files accept negative offsets, while others reject
them? The answer lies in, of all places, /dev/null.
The null, memory, and kernel memory pseudo-devices in many UNIX kernels
share a major device number (on Suns, for instance, major device 3, under
both SunOS and 4.4BSD---I tried to number my devices the same as Sun's).
Now, as it happens, on the VAX, `kernel memory' is anything whose virtual
address is in [0x80000000 .. 0xbfffffff]. This is a property of the
hardware. These addresses, when treated as integers, are negative!
Now, most UNIX systems have *some* history that dates back to a VAX.
Even if your particular kernel has no VAX-specific code in its
ancestry, it probably has some VAX-influenced code. One of these
influences is that lseek must accept `negative' offsets for seeks on
/dev/kmem. Some kernels implement this by allowing negative seeks only
on the corresponding character major device; others allow it only on
all character devices; still others (such as 4.4BSD) eliminate all the
special-casing and just plain allow it.
Those systems that have special cases usually have bugs---sometimes
minor, sometimes serious---in which negative offsets on some devices
(such as ttys) cause mysterious behavior. (I vaguely recall one case
where I got a system to panic.) These bugs tend to creep in because
device-driver authors forget that negative offsets are possible. Thus,
odd as it may seem, eliminating this special case actually reduces
errors.
None of this helps any if you have a system that misbehaves when using
negative offsets, but to fix that, you must have kernel source.
--
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 510 486 5427)