Why is stat::st_size 0 for devices but at the same time lseek defines the device size correctly?
I noticed that when I query the size of a device using open + lseek, everything is OK, but when I stat the device I get zero instead of the real device size. The device is clean without any file system and the first bytes of device start with some text like "1234567890ABC". What is wrong?
The code:
#include <sys/stat.h>
#include <dirent.h>
bool
GetFileSize(const char* pPath, uint64_t& Size)
{
pPath = "/home/sw/.bashrc";
pPath = "/dev/sda";
struct stat buffer;
if (stat(pPath, &buffer))
{
printf("Failed to stat file. Error: %s. FilePath: %sn", strerror(errno), pPath);
return false;
}
printf("File size by stat: %" PRIu64 " WTF?n", buffer.st_size);
//
// Note: It's strange, but stat::st_size from the stat call is zero for devices
//
int File = open(pPath, O_RDONLY);
if (File < 0)
{
printf("Failed to open file. Error: %s. FilePath: %sn", strerror(errno), pPath);
return false;
}
long off = lseek(File, 0, SEEK_END);
if (off == (off_t)-1)
{
printf("Failed to get file size. Error: %s. FilePath: %sn", strerror(errno), pPath);
close(File);
return false;
}
close(File);
printf("File size by lseek: %" PRIu64 "n", off);
fflush(stdout);
Size = off;
return true;
}
Output:
File size by stat: 0 WTF?
File size by lseek: 34359738368
If I use stat for a regular file then everything is OK (comment out the line with "/dev/sda"):
File size by stat: 4019 WTF?
File size by lseek: 4019
c linux posix stat
add a comment |
I noticed that when I query the size of a device using open + lseek, everything is OK, but when I stat the device I get zero instead of the real device size. The device is clean without any file system and the first bytes of device start with some text like "1234567890ABC". What is wrong?
The code:
#include <sys/stat.h>
#include <dirent.h>
bool
GetFileSize(const char* pPath, uint64_t& Size)
{
pPath = "/home/sw/.bashrc";
pPath = "/dev/sda";
struct stat buffer;
if (stat(pPath, &buffer))
{
printf("Failed to stat file. Error: %s. FilePath: %sn", strerror(errno), pPath);
return false;
}
printf("File size by stat: %" PRIu64 " WTF?n", buffer.st_size);
//
// Note: It's strange, but stat::st_size from the stat call is zero for devices
//
int File = open(pPath, O_RDONLY);
if (File < 0)
{
printf("Failed to open file. Error: %s. FilePath: %sn", strerror(errno), pPath);
return false;
}
long off = lseek(File, 0, SEEK_END);
if (off == (off_t)-1)
{
printf("Failed to get file size. Error: %s. FilePath: %sn", strerror(errno), pPath);
close(File);
return false;
}
close(File);
printf("File size by lseek: %" PRIu64 "n", off);
fflush(stdout);
Size = off;
return true;
}
Output:
File size by stat: 0 WTF?
File size by lseek: 34359738368
If I use stat for a regular file then everything is OK (comment out the line with "/dev/sda"):
File size by stat: 4019 WTF?
File size by lseek: 4019
c linux posix stat
2
welcome to "stat information is different from seeking+telling information".
– Jean-François Fabre♦
Mar 14 at 14:02
2
related: unix.stackexchange.com/questions/384488/…
– Jean-François Fabre♦
Mar 14 at 14:05
4
I don’t trust printing the size usingPRIu64
unless you cast the size touint64_t
. That said, you’d probably not get zero if it’s going wrong.
– Jonathan Leffler
Mar 14 at 14:08
add a comment |
I noticed that when I query the size of a device using open + lseek, everything is OK, but when I stat the device I get zero instead of the real device size. The device is clean without any file system and the first bytes of device start with some text like "1234567890ABC". What is wrong?
The code:
#include <sys/stat.h>
#include <dirent.h>
bool
GetFileSize(const char* pPath, uint64_t& Size)
{
pPath = "/home/sw/.bashrc";
pPath = "/dev/sda";
struct stat buffer;
if (stat(pPath, &buffer))
{
printf("Failed to stat file. Error: %s. FilePath: %sn", strerror(errno), pPath);
return false;
}
printf("File size by stat: %" PRIu64 " WTF?n", buffer.st_size);
//
// Note: It's strange, but stat::st_size from the stat call is zero for devices
//
int File = open(pPath, O_RDONLY);
if (File < 0)
{
printf("Failed to open file. Error: %s. FilePath: %sn", strerror(errno), pPath);
return false;
}
long off = lseek(File, 0, SEEK_END);
if (off == (off_t)-1)
{
printf("Failed to get file size. Error: %s. FilePath: %sn", strerror(errno), pPath);
close(File);
return false;
}
close(File);
printf("File size by lseek: %" PRIu64 "n", off);
fflush(stdout);
Size = off;
return true;
}
Output:
File size by stat: 0 WTF?
File size by lseek: 34359738368
If I use stat for a regular file then everything is OK (comment out the line with "/dev/sda"):
File size by stat: 4019 WTF?
File size by lseek: 4019
c linux posix stat
I noticed that when I query the size of a device using open + lseek, everything is OK, but when I stat the device I get zero instead of the real device size. The device is clean without any file system and the first bytes of device start with some text like "1234567890ABC". What is wrong?
The code:
#include <sys/stat.h>
#include <dirent.h>
bool
GetFileSize(const char* pPath, uint64_t& Size)
{
pPath = "/home/sw/.bashrc";
pPath = "/dev/sda";
struct stat buffer;
if (stat(pPath, &buffer))
{
printf("Failed to stat file. Error: %s. FilePath: %sn", strerror(errno), pPath);
return false;
}
printf("File size by stat: %" PRIu64 " WTF?n", buffer.st_size);
//
// Note: It's strange, but stat::st_size from the stat call is zero for devices
//
int File = open(pPath, O_RDONLY);
if (File < 0)
{
printf("Failed to open file. Error: %s. FilePath: %sn", strerror(errno), pPath);
return false;
}
long off = lseek(File, 0, SEEK_END);
if (off == (off_t)-1)
{
printf("Failed to get file size. Error: %s. FilePath: %sn", strerror(errno), pPath);
close(File);
return false;
}
close(File);
printf("File size by lseek: %" PRIu64 "n", off);
fflush(stdout);
Size = off;
return true;
}
Output:
File size by stat: 0 WTF?
File size by lseek: 34359738368
If I use stat for a regular file then everything is OK (comment out the line with "/dev/sda"):
File size by stat: 4019 WTF?
File size by lseek: 4019
c linux posix stat
c linux posix stat
edited Mar 15 at 12:39
Boann
37.3k1290121
37.3k1290121
asked Mar 14 at 14:00
Alexander SymonenkoAlexander Symonenko
14412
14412
2
welcome to "stat information is different from seeking+telling information".
– Jean-François Fabre♦
Mar 14 at 14:02
2
related: unix.stackexchange.com/questions/384488/…
– Jean-François Fabre♦
Mar 14 at 14:05
4
I don’t trust printing the size usingPRIu64
unless you cast the size touint64_t
. That said, you’d probably not get zero if it’s going wrong.
– Jonathan Leffler
Mar 14 at 14:08
add a comment |
2
welcome to "stat information is different from seeking+telling information".
– Jean-François Fabre♦
Mar 14 at 14:02
2
related: unix.stackexchange.com/questions/384488/…
– Jean-François Fabre♦
Mar 14 at 14:05
4
I don’t trust printing the size usingPRIu64
unless you cast the size touint64_t
. That said, you’d probably not get zero if it’s going wrong.
– Jonathan Leffler
Mar 14 at 14:08
2
2
welcome to "stat information is different from seeking+telling information".
– Jean-François Fabre♦
Mar 14 at 14:02
welcome to "stat information is different from seeking+telling information".
– Jean-François Fabre♦
Mar 14 at 14:02
2
2
related: unix.stackexchange.com/questions/384488/…
– Jean-François Fabre♦
Mar 14 at 14:05
related: unix.stackexchange.com/questions/384488/…
– Jean-François Fabre♦
Mar 14 at 14:05
4
4
I don’t trust printing the size using
PRIu64
unless you cast the size to uint64_t
. That said, you’d probably not get zero if it’s going wrong.– Jonathan Leffler
Mar 14 at 14:08
I don’t trust printing the size using
PRIu64
unless you cast the size to uint64_t
. That said, you’d probably not get zero if it’s going wrong.– Jonathan Leffler
Mar 14 at 14:08
add a comment |
5 Answers
5
active
oldest
votes
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.
1
it has, and I have the impression that the 3 existing answers complete each other.
– Jean-François Fabre♦
Mar 14 at 14:49
1
@Jean-FrançoisFabre they seem to don't they :)
– Ahmed Masud
Mar 14 at 15:02
@Jean-François Fabre Masud All answers are correct and complete each other. But this think seems is key: stat works with inodes and it gives information from existing FS, not device file. But in other side device file has size, has start and has the end (in case of block device) therefore lseek works without problem and returns correct device size. As Ahmed told "everything is a file", therefore I had used stat in place where it cannot be used. "The devil is in the detail.." - accurately describes this situation. Thank you guys!
– Alexander Symonenko
Mar 14 at 16:04
add a comment |
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.
add a comment |
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.
add a comment |
On Linux, the documented way to get the size of a raw disk device that you can open is with the BLKGETSIZE
ioctl. See the sd(4)
manpage.
Note that this returns the size of the device in sectors. You might think that, for size in bytes, you have to multiply by the value returned by the BLKSSZGET
ioctl, but if I'm reading the source code correctly, you actually have to multiply by 512 no matter what BLKSSZGET
returns.
add a comment |
lseek
is the backbone to C's fseek
, so it has similar semantics, matching fseek
- and quite detached from other areas of the Unix API. Provenance-wise, you'd expect lseek
to act like file-handle-taking fseek
, and fseek
is a C-library interface that came to be without being Unix-specific.
stat
is Unix-specific, though, and does its own thing. It's a reasonable difference to expect if you think about provenance. Of course the problem is, then, that C APIs have very weak type models because C is one step short of making true type safety possible.
Why is this important? Because, fundamentally, a seekable_size and a file_object_size are two fundamentally different concepts, and would demand different types – even the C++ standard library gets it wrong.
But while in C++ and with modern compilers it’s now an entirely gratuitous legacy shortcoming, there’s really no way in C to efficiently wrap integers into incompatible types without killing performance and code readability. And thus you end up with something like offs_t
or long
being used for wholly incompatible concepts. And this is the source of confusion: just because you get a size-related number out of a file-related function doesn’t mean that the number will have the same meaning. And meanings are usually captured in types… The only meaning a long
inherently has is “hey, I’m a number, you can do numeric things with me”… :(
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55164462%2fwhy-is-statst-size-0-for-devices-but-at-the-same-time-lseek-defines-the-device%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
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.
1
it has, and I have the impression that the 3 existing answers complete each other.
– Jean-François Fabre♦
Mar 14 at 14:49
1
@Jean-FrançoisFabre they seem to don't they :)
– Ahmed Masud
Mar 14 at 15:02
@Jean-François Fabre Masud All answers are correct and complete each other. But this think seems is key: stat works with inodes and it gives information from existing FS, not device file. But in other side device file has size, has start and has the end (in case of block device) therefore lseek works without problem and returns correct device size. As Ahmed told "everything is a file", therefore I had used stat in place where it cannot be used. "The devil is in the detail.." - accurately describes this situation. Thank you guys!
– Alexander Symonenko
Mar 14 at 16:04
add a comment |
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.
1
it has, and I have the impression that the 3 existing answers complete each other.
– Jean-François Fabre♦
Mar 14 at 14:49
1
@Jean-FrançoisFabre they seem to don't they :)
– Ahmed Masud
Mar 14 at 15:02
@Jean-François Fabre Masud All answers are correct and complete each other. But this think seems is key: stat works with inodes and it gives information from existing FS, not device file. But in other side device file has size, has start and has the end (in case of block device) therefore lseek works without problem and returns correct device size. As Ahmed told "everything is a file", therefore I had used stat in place where it cannot be used. "The devil is in the detail.." - accurately describes this situation. Thank you guys!
– Alexander Symonenko
Mar 14 at 16:04
add a comment |
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.
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.
answered Mar 14 at 14:23
Ahmed MasudAhmed Masud
15.8k32538
15.8k32538
1
it has, and I have the impression that the 3 existing answers complete each other.
– Jean-François Fabre♦
Mar 14 at 14:49
1
@Jean-FrançoisFabre they seem to don't they :)
– Ahmed Masud
Mar 14 at 15:02
@Jean-François Fabre Masud All answers are correct and complete each other. But this think seems is key: stat works with inodes and it gives information from existing FS, not device file. But in other side device file has size, has start and has the end (in case of block device) therefore lseek works without problem and returns correct device size. As Ahmed told "everything is a file", therefore I had used stat in place where it cannot be used. "The devil is in the detail.." - accurately describes this situation. Thank you guys!
– Alexander Symonenko
Mar 14 at 16:04
add a comment |
1
it has, and I have the impression that the 3 existing answers complete each other.
– Jean-François Fabre♦
Mar 14 at 14:49
1
@Jean-FrançoisFabre they seem to don't they :)
– Ahmed Masud
Mar 14 at 15:02
@Jean-François Fabre Masud All answers are correct and complete each other. But this think seems is key: stat works with inodes and it gives information from existing FS, not device file. But in other side device file has size, has start and has the end (in case of block device) therefore lseek works without problem and returns correct device size. As Ahmed told "everything is a file", therefore I had used stat in place where it cannot be used. "The devil is in the detail.." - accurately describes this situation. Thank you guys!
– Alexander Symonenko
Mar 14 at 16:04
1
1
it has, and I have the impression that the 3 existing answers complete each other.
– Jean-François Fabre♦
Mar 14 at 14:49
it has, and I have the impression that the 3 existing answers complete each other.
– Jean-François Fabre♦
Mar 14 at 14:49
1
1
@Jean-FrançoisFabre they seem to don't they :)
– Ahmed Masud
Mar 14 at 15:02
@Jean-FrançoisFabre they seem to don't they :)
– Ahmed Masud
Mar 14 at 15:02
@Jean-François Fabre Masud All answers are correct and complete each other. But this think seems is key: stat works with inodes and it gives information from existing FS, not device file. But in other side device file has size, has start and has the end (in case of block device) therefore lseek works without problem and returns correct device size. As Ahmed told "everything is a file", therefore I had used stat in place where it cannot be used. "The devil is in the detail.." - accurately describes this situation. Thank you guys!
– Alexander Symonenko
Mar 14 at 16:04
@Jean-François Fabre Masud All answers are correct and complete each other. But this think seems is key: stat works with inodes and it gives information from existing FS, not device file. But in other side device file has size, has start and has the end (in case of block device) therefore lseek works without problem and returns correct device size. As Ahmed told "everything is a file", therefore I had used stat in place where it cannot be used. "The devil is in the detail.." - accurately describes this situation. Thank you guys!
– Alexander Symonenko
Mar 14 at 16:04
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
edited Mar 14 at 15:05
answered Mar 14 at 14:13
Jean-François Fabre♦Jean-François Fabre
106k1057115
106k1057115
add a comment |
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Mar 14 at 14:16
Andrew HenleAndrew Henle
20.5k31435
20.5k31435
add a comment |
add a comment |
On Linux, the documented way to get the size of a raw disk device that you can open is with the BLKGETSIZE
ioctl. See the sd(4)
manpage.
Note that this returns the size of the device in sectors. You might think that, for size in bytes, you have to multiply by the value returned by the BLKSSZGET
ioctl, but if I'm reading the source code correctly, you actually have to multiply by 512 no matter what BLKSSZGET
returns.
add a comment |
On Linux, the documented way to get the size of a raw disk device that you can open is with the BLKGETSIZE
ioctl. See the sd(4)
manpage.
Note that this returns the size of the device in sectors. You might think that, for size in bytes, you have to multiply by the value returned by the BLKSSZGET
ioctl, but if I'm reading the source code correctly, you actually have to multiply by 512 no matter what BLKSSZGET
returns.
add a comment |
On Linux, the documented way to get the size of a raw disk device that you can open is with the BLKGETSIZE
ioctl. See the sd(4)
manpage.
Note that this returns the size of the device in sectors. You might think that, for size in bytes, you have to multiply by the value returned by the BLKSSZGET
ioctl, but if I'm reading the source code correctly, you actually have to multiply by 512 no matter what BLKSSZGET
returns.
On Linux, the documented way to get the size of a raw disk device that you can open is with the BLKGETSIZE
ioctl. See the sd(4)
manpage.
Note that this returns the size of the device in sectors. You might think that, for size in bytes, you have to multiply by the value returned by the BLKSSZGET
ioctl, but if I'm reading the source code correctly, you actually have to multiply by 512 no matter what BLKSSZGET
returns.
answered Mar 14 at 17:01
zwolzwol
99.2k24172273
99.2k24172273
add a comment |
add a comment |
lseek
is the backbone to C's fseek
, so it has similar semantics, matching fseek
- and quite detached from other areas of the Unix API. Provenance-wise, you'd expect lseek
to act like file-handle-taking fseek
, and fseek
is a C-library interface that came to be without being Unix-specific.
stat
is Unix-specific, though, and does its own thing. It's a reasonable difference to expect if you think about provenance. Of course the problem is, then, that C APIs have very weak type models because C is one step short of making true type safety possible.
Why is this important? Because, fundamentally, a seekable_size and a file_object_size are two fundamentally different concepts, and would demand different types – even the C++ standard library gets it wrong.
But while in C++ and with modern compilers it’s now an entirely gratuitous legacy shortcoming, there’s really no way in C to efficiently wrap integers into incompatible types without killing performance and code readability. And thus you end up with something like offs_t
or long
being used for wholly incompatible concepts. And this is the source of confusion: just because you get a size-related number out of a file-related function doesn’t mean that the number will have the same meaning. And meanings are usually captured in types… The only meaning a long
inherently has is “hey, I’m a number, you can do numeric things with me”… :(
add a comment |
lseek
is the backbone to C's fseek
, so it has similar semantics, matching fseek
- and quite detached from other areas of the Unix API. Provenance-wise, you'd expect lseek
to act like file-handle-taking fseek
, and fseek
is a C-library interface that came to be without being Unix-specific.
stat
is Unix-specific, though, and does its own thing. It's a reasonable difference to expect if you think about provenance. Of course the problem is, then, that C APIs have very weak type models because C is one step short of making true type safety possible.
Why is this important? Because, fundamentally, a seekable_size and a file_object_size are two fundamentally different concepts, and would demand different types – even the C++ standard library gets it wrong.
But while in C++ and with modern compilers it’s now an entirely gratuitous legacy shortcoming, there’s really no way in C to efficiently wrap integers into incompatible types without killing performance and code readability. And thus you end up with something like offs_t
or long
being used for wholly incompatible concepts. And this is the source of confusion: just because you get a size-related number out of a file-related function doesn’t mean that the number will have the same meaning. And meanings are usually captured in types… The only meaning a long
inherently has is “hey, I’m a number, you can do numeric things with me”… :(
add a comment |
lseek
is the backbone to C's fseek
, so it has similar semantics, matching fseek
- and quite detached from other areas of the Unix API. Provenance-wise, you'd expect lseek
to act like file-handle-taking fseek
, and fseek
is a C-library interface that came to be without being Unix-specific.
stat
is Unix-specific, though, and does its own thing. It's a reasonable difference to expect if you think about provenance. Of course the problem is, then, that C APIs have very weak type models because C is one step short of making true type safety possible.
Why is this important? Because, fundamentally, a seekable_size and a file_object_size are two fundamentally different concepts, and would demand different types – even the C++ standard library gets it wrong.
But while in C++ and with modern compilers it’s now an entirely gratuitous legacy shortcoming, there’s really no way in C to efficiently wrap integers into incompatible types without killing performance and code readability. And thus you end up with something like offs_t
or long
being used for wholly incompatible concepts. And this is the source of confusion: just because you get a size-related number out of a file-related function doesn’t mean that the number will have the same meaning. And meanings are usually captured in types… The only meaning a long
inherently has is “hey, I’m a number, you can do numeric things with me”… :(
lseek
is the backbone to C's fseek
, so it has similar semantics, matching fseek
- and quite detached from other areas of the Unix API. Provenance-wise, you'd expect lseek
to act like file-handle-taking fseek
, and fseek
is a C-library interface that came to be without being Unix-specific.
stat
is Unix-specific, though, and does its own thing. It's a reasonable difference to expect if you think about provenance. Of course the problem is, then, that C APIs have very weak type models because C is one step short of making true type safety possible.
Why is this important? Because, fundamentally, a seekable_size and a file_object_size are two fundamentally different concepts, and would demand different types – even the C++ standard library gets it wrong.
But while in C++ and with modern compilers it’s now an entirely gratuitous legacy shortcoming, there’s really no way in C to efficiently wrap integers into incompatible types without killing performance and code readability. And thus you end up with something like offs_t
or long
being used for wholly incompatible concepts. And this is the source of confusion: just because you get a size-related number out of a file-related function doesn’t mean that the number will have the same meaning. And meanings are usually captured in types… The only meaning a long
inherently has is “hey, I’m a number, you can do numeric things with me”… :(
edited Mar 15 at 13:31
answered Mar 14 at 19:24
Kuba OberKuba Ober
70.8k1083195
70.8k1083195
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55164462%2fwhy-is-statst-size-0-for-devices-but-at-the-same-time-lseek-defines-the-device%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
welcome to "stat information is different from seeking+telling information".
– Jean-François Fabre♦
Mar 14 at 14:02
2
related: unix.stackexchange.com/questions/384488/…
– Jean-François Fabre♦
Mar 14 at 14:05
4
I don’t trust printing the size using
PRIu64
unless you cast the size touint64_t
. That said, you’d probably not get zero if it’s going wrong.– Jonathan Leffler
Mar 14 at 14:08