Why is stat::st_size 0 for devices but at the same time lseek defines the device size correctly?

The devil is in the detail... For starters, there is the fundamental principle of Unix design: everything is a file, Nicely explained here.

The second is that the stat(2) call is giving you inode statistics stored on the filesystem about the device-special file which has a size of zero (think of it as lstat(2)). If you have a block-device that has a filesystem on it you get information about it using statfs(2) or getfsstat(2) or statvfs(2) in a filesystem/device independent way.

Dealing with special files (usually residing in /dev) has always been system specific and the manual pages reside in section 4. So if you want to manipulate a device directly you should read up on the specifics there. For instance, in Linux man 4 hd will show you how to programmatically interact with IDE block devices. Whereas man 4 sd will give you how to interact with scsi discs, etc.

Third thing, system calls are not supposed to be inconsistent in their functionality NOR their limitations.

Hope this has helped.


from this Unix Stack Exchange question:

Device files are not files per se. They're an I/O interface to use the devices in Unix-like operating systems. They use no space on disk, however, they still use an inode as reported by the stat command:

$ stat /dev/sda
      File: /dev/sda
      Size: 0               Blocks: 0          IO Block: 4096   block special file
Device: 6h/6d   Inode: 14628       Links: 1     Device type: 8,0

That solves the stat part.

the fact that you can seek in this "file" is not related. This isn't really a file, but you can open it and read from it. You can seek to it too. It allows to read the disk at the lowest level, so seeking is necessary (that's why it works, and why wouldn't it return the new position like any "real" file?).

According to this other UnixSE answer, you can get the device size by reading this /dev/sda/size file.


The length of a "device" such as /dev/sda is not specifed by the POSIX struct stat:

off_t st_size       For regular files, the file size in bytes. 

                    For symbolic links, the length in bytes of the 
                    pathname contained in the symbolic link. 

                    For a shared memory object, the length in bytes. 

                    For a typed memory object, the length in bytes. 

                    For other file types, the use of this field is 
                    unspecified. 

So POSIX has no requirement for the "size" of a disk device.

Linux likewise does not specify that stat() shall return the size of a disk device:

st_size

This field gives the size of the file (if it is a regular file or a symbolic link) in bytes. The size of a symbolic link is the length of the pathname it contains, without a terminating null byte.

Tags:

Linux

C

Posix

Stat