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












10















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









share|improve this question




















  • 2





    welcome to "stat information is different from seeking+telling information".

    – Jean-François Fabre
    16 hours ago






  • 2





    related: unix.stackexchange.com/questions/384488/…

    – Jean-François Fabre
    16 hours ago






  • 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
    16 hours ago
















10















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









share|improve this question




















  • 2





    welcome to "stat information is different from seeking+telling information".

    – Jean-François Fabre
    16 hours ago






  • 2





    related: unix.stackexchange.com/questions/384488/…

    – Jean-François Fabre
    16 hours ago






  • 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
    16 hours ago














10












10








10








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









share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 14 hours ago









Boann

37.2k1290121




37.2k1290121










asked 16 hours ago









Alexander SymonenkoAlexander Symonenko

13411




13411








  • 2





    welcome to "stat information is different from seeking+telling information".

    – Jean-François Fabre
    16 hours ago






  • 2





    related: unix.stackexchange.com/questions/384488/…

    – Jean-François Fabre
    16 hours ago






  • 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
    16 hours ago














  • 2





    welcome to "stat information is different from seeking+telling information".

    – Jean-François Fabre
    16 hours ago






  • 2





    related: unix.stackexchange.com/questions/384488/…

    – Jean-François Fabre
    16 hours ago






  • 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
    16 hours ago








2




2





welcome to "stat information is different from seeking+telling information".

– Jean-François Fabre
16 hours ago





welcome to "stat information is different from seeking+telling information".

– Jean-François Fabre
16 hours ago




2




2





related: unix.stackexchange.com/questions/384488/…

– Jean-François Fabre
16 hours ago





related: unix.stackexchange.com/questions/384488/…

– Jean-François Fabre
16 hours ago




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
16 hours ago





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
16 hours ago












5 Answers
5






active

oldest

votes


















9














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.






share|improve this answer



















  • 1





    it has, and I have the impression that the 3 existing answers complete each other.

    – Jean-François Fabre
    15 hours ago






  • 1





    @Jean-FrançoisFabre they seem to don't they :)

    – Ahmed Masud
    15 hours ago











  • @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
    14 hours ago



















8














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.






share|improve this answer

































    5














    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.







    share|improve this answer































      0














      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.






      share|improve this answer































        0














        lseek is the backbone to C's fseek, so it has its own semantics, matching fseek - and quite detached from other areas of the Unix API. Provenance-wise, you'd expect lseek to act like 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. As it is, you can be type-safe as long as it is possible to fit the value into intptr_t - because then its real type can be a pointer type to a struct "tag", and those are the only "small" type-safe values in C - and even then, only if you enable -Werror, i.e. turn all warnings into errors. Passing structs by value would have been nicer since there the type mismatches are hard errors, but initializing those is a pain:



        typedef struct { const char *val; } file_path;
        typedef struct { const char *val; } file_mode;
        typedef FILE *file_handle;

        file_path path = { "foo/bar" };
        file_mode mode = { "w" };
        file_handle fh = fopen(path, mode);


        The path and mode arguments are type-safe, i.e. you couldn't pass a file_path to something that expects a date_string given as typedef struct { const char *val; } date_string. And although modern compilers do a wicked good job of optimizing the code above and essentially stripping the type-safe overhead, the ABIs lag behind this. And thus C is only mildly type-safe. Only with -Werror :)






        share|improve this answer























          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
          });


          }
          });














          draft saved

          draft discarded


















          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









          9














          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.






          share|improve this answer



















          • 1





            it has, and I have the impression that the 3 existing answers complete each other.

            – Jean-François Fabre
            15 hours ago






          • 1





            @Jean-FrançoisFabre they seem to don't they :)

            – Ahmed Masud
            15 hours ago











          • @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
            14 hours ago
















          9














          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.






          share|improve this answer



















          • 1





            it has, and I have the impression that the 3 existing answers complete each other.

            – Jean-François Fabre
            15 hours ago






          • 1





            @Jean-FrançoisFabre they seem to don't they :)

            – Ahmed Masud
            15 hours ago











          • @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
            14 hours ago














          9












          9








          9







          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.






          share|improve this answer













          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.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 15 hours ago









          Ahmed MasudAhmed Masud

          15.7k32537




          15.7k32537








          • 1





            it has, and I have the impression that the 3 existing answers complete each other.

            – Jean-François Fabre
            15 hours ago






          • 1





            @Jean-FrançoisFabre they seem to don't they :)

            – Ahmed Masud
            15 hours ago











          • @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
            14 hours ago














          • 1





            it has, and I have the impression that the 3 existing answers complete each other.

            – Jean-François Fabre
            15 hours ago






          • 1





            @Jean-FrançoisFabre they seem to don't they :)

            – Ahmed Masud
            15 hours ago











          • @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
            14 hours ago








          1




          1





          it has, and I have the impression that the 3 existing answers complete each other.

          – Jean-François Fabre
          15 hours ago





          it has, and I have the impression that the 3 existing answers complete each other.

          – Jean-François Fabre
          15 hours ago




          1




          1





          @Jean-FrançoisFabre they seem to don't they :)

          – Ahmed Masud
          15 hours ago





          @Jean-FrançoisFabre they seem to don't they :)

          – Ahmed Masud
          15 hours ago













          @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
          14 hours ago





          @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
          14 hours ago













          8














          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.






          share|improve this answer






























            8














            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.






            share|improve this answer




























              8












              8








              8







              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.






              share|improve this answer















              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.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited 15 hours ago

























              answered 16 hours ago









              Jean-François FabreJean-François Fabre

              106k956115




              106k956115























                  5














                  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.







                  share|improve this answer




























                    5














                    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.







                    share|improve this answer


























                      5












                      5








                      5







                      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.







                      share|improve this answer













                      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.








                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered 16 hours ago









                      Andrew HenleAndrew Henle

                      20.4k31335




                      20.4k31335























                          0














                          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.






                          share|improve this answer




























                            0














                            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.






                            share|improve this answer


























                              0












                              0








                              0







                              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.






                              share|improve this answer













                              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.







                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered 13 hours ago









                              zwolzwol

                              99k24172272




                              99k24172272























                                  0














                                  lseek is the backbone to C's fseek, so it has its own semantics, matching fseek - and quite detached from other areas of the Unix API. Provenance-wise, you'd expect lseek to act like 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. As it is, you can be type-safe as long as it is possible to fit the value into intptr_t - because then its real type can be a pointer type to a struct "tag", and those are the only "small" type-safe values in C - and even then, only if you enable -Werror, i.e. turn all warnings into errors. Passing structs by value would have been nicer since there the type mismatches are hard errors, but initializing those is a pain:



                                  typedef struct { const char *val; } file_path;
                                  typedef struct { const char *val; } file_mode;
                                  typedef FILE *file_handle;

                                  file_path path = { "foo/bar" };
                                  file_mode mode = { "w" };
                                  file_handle fh = fopen(path, mode);


                                  The path and mode arguments are type-safe, i.e. you couldn't pass a file_path to something that expects a date_string given as typedef struct { const char *val; } date_string. And although modern compilers do a wicked good job of optimizing the code above and essentially stripping the type-safe overhead, the ABIs lag behind this. And thus C is only mildly type-safe. Only with -Werror :)






                                  share|improve this answer




























                                    0














                                    lseek is the backbone to C's fseek, so it has its own semantics, matching fseek - and quite detached from other areas of the Unix API. Provenance-wise, you'd expect lseek to act like 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. As it is, you can be type-safe as long as it is possible to fit the value into intptr_t - because then its real type can be a pointer type to a struct "tag", and those are the only "small" type-safe values in C - and even then, only if you enable -Werror, i.e. turn all warnings into errors. Passing structs by value would have been nicer since there the type mismatches are hard errors, but initializing those is a pain:



                                    typedef struct { const char *val; } file_path;
                                    typedef struct { const char *val; } file_mode;
                                    typedef FILE *file_handle;

                                    file_path path = { "foo/bar" };
                                    file_mode mode = { "w" };
                                    file_handle fh = fopen(path, mode);


                                    The path and mode arguments are type-safe, i.e. you couldn't pass a file_path to something that expects a date_string given as typedef struct { const char *val; } date_string. And although modern compilers do a wicked good job of optimizing the code above and essentially stripping the type-safe overhead, the ABIs lag behind this. And thus C is only mildly type-safe. Only with -Werror :)






                                    share|improve this answer


























                                      0












                                      0








                                      0







                                      lseek is the backbone to C's fseek, so it has its own semantics, matching fseek - and quite detached from other areas of the Unix API. Provenance-wise, you'd expect lseek to act like 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. As it is, you can be type-safe as long as it is possible to fit the value into intptr_t - because then its real type can be a pointer type to a struct "tag", and those are the only "small" type-safe values in C - and even then, only if you enable -Werror, i.e. turn all warnings into errors. Passing structs by value would have been nicer since there the type mismatches are hard errors, but initializing those is a pain:



                                      typedef struct { const char *val; } file_path;
                                      typedef struct { const char *val; } file_mode;
                                      typedef FILE *file_handle;

                                      file_path path = { "foo/bar" };
                                      file_mode mode = { "w" };
                                      file_handle fh = fopen(path, mode);


                                      The path and mode arguments are type-safe, i.e. you couldn't pass a file_path to something that expects a date_string given as typedef struct { const char *val; } date_string. And although modern compilers do a wicked good job of optimizing the code above and essentially stripping the type-safe overhead, the ABIs lag behind this. And thus C is only mildly type-safe. Only with -Werror :)






                                      share|improve this answer













                                      lseek is the backbone to C's fseek, so it has its own semantics, matching fseek - and quite detached from other areas of the Unix API. Provenance-wise, you'd expect lseek to act like 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. As it is, you can be type-safe as long as it is possible to fit the value into intptr_t - because then its real type can be a pointer type to a struct "tag", and those are the only "small" type-safe values in C - and even then, only if you enable -Werror, i.e. turn all warnings into errors. Passing structs by value would have been nicer since there the type mismatches are hard errors, but initializing those is a pain:



                                      typedef struct { const char *val; } file_path;
                                      typedef struct { const char *val; } file_mode;
                                      typedef FILE *file_handle;

                                      file_path path = { "foo/bar" };
                                      file_mode mode = { "w" };
                                      file_handle fh = fopen(path, mode);


                                      The path and mode arguments are type-safe, i.e. you couldn't pass a file_path to something that expects a date_string given as typedef struct { const char *val; } date_string. And although modern compilers do a wicked good job of optimizing the code above and essentially stripping the type-safe overhead, the ABIs lag behind this. And thus C is only mildly type-safe. Only with -Werror :)







                                      share|improve this answer












                                      share|improve this answer



                                      share|improve this answer










                                      answered 10 hours ago









                                      Kuba OberKuba Ober

                                      70.6k983192




                                      70.6k983192






























                                          draft saved

                                          draft discarded




















































                                          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.




                                          draft saved


                                          draft discarded














                                          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





















































                                          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







                                          Popular posts from this blog

                                          How did Captain America manage to do this?

                                          迪纳利

                                          南乌拉尔铁路局