Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Location: Northeastern Michigan, where Carhartt is a Designer Label
Distribution: Slackware 32- & 64-bit Stable
Posts: 3,541
Rep:
The stat, fstat and lstat library functions all return information about a file, including the total size in bytes (see the structure definition below); no calculation need take place.
man 2 stat displays the details along with the structure definition:
Quote:
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
The stat library functions are used extensively by many utilities, among others the stat utility (display file or file system status), cp (copy files) and ls (I'm pretty sure).
Below is a demonstration version, status.c, that can be used to display all the information about one file contained in the stat structure, thus it's not terribly useful for general purposes:
Code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <grp.h>
#include <pwd.h>
#include <time.h>
main (int argc, char *argv[])
{
time_t now;
struct group *grentry, *getgrgid (gid_t);
struct passwd *pwentry, *getpwuid (uid_t);
struct stat status;
struct tm *tstr, *localtime (const time_t *);
if (argc != 2) {
(void) fprintf (stderr, "usage:\t%s file\n", argv [0]);
return (1);
}
/* get stat structure for specified file */
if (stat (argv [1], &status) == -1) {
(void) fprintf (stderr, "%s:\tcan't stat %s\n",
argv [0], argv [1]);
return (2);
}
/* display the type of file */
if (status.st_mode & S_IFREG)
(void) fprintf (stdout, "Regular File:\t");
else if (status.st_mode & S_IFDIR)
(void) fprintf (stdout, "Directory:\t");
else if (status.st_mode & S_IFIFO)
(void) fprintf (stdout, "FIFO Special File:\t");
else if (status.st_mode & S_IFCHR)
(void) fprintf (stdout, "Character Special File:\t");
else if (status.st_mode & S_IFBLK)
(void) fprintf (stdout, "Block Special File:\t");
else if (status.st_mode & S_IFLNK)
(void) fprintf (stdout, "Symbolic Link:\t");
else
(void) fprintf (stdout, "Unknown File:\t");
(void) fprintf (stdout, "%s\n", argv [1]);
(void) fprintf (stdout, "Inode:\t\t%d\n", (int) status.st_ino);
(void) fprintf (stdout, "Mode:\t\t%d\n", (int) status.st_mode);
(void) fprintf (stdout, "Device:\t\t%d\n", (int) status.st_dev);
(void) fprintf (stdout, "Blocksize:\t%d\n", (int) status.st_blksize);
(void) fprintf (stdout, "Links:\t\t%d\n", (int) status.st_nlink);
(void) fprintf (stdout, "Owner (%d):\t", (int) status.st_uid);
/* look up owner in /etc/passwd */
if ((pwentry = getpwuid (status.st_uid)) == (struct passwd *) NULL) {
(void) fprintf (stdout, "not found\n");
} else {
(void) fprintf (stdout, "%s\n", pwentry->pw_name);
}
/* look up group name in /etc/group */
(void) fprintf (stdout, "Group (%d):\t", (int) status.st_gid);
if ((grentry = getgrgid (status.st_gid)) == (struct group *) NULL) {
(void) fprintf (stdout, "no found\n");
} else {
(void) fprintf (stdout, "%s\n", grentry->gr_name);
}
(void) fprintf (stdout, "Size:\t\t%d\n", (int) status.st_size);
now = status.st_atime;
tstr = localtime (&now);
(void) fprintf (stdout, "atime:\t\t%02d:%02d:%02d %02d/%02d/%02d\t",
tstr->tm_hour, tstr->tm_min, tstr->tm_sec,
tstr->tm_mon+1, tstr->tm_mday, tstr->tm_year);
(void) fprintf (stdout, "(Last Access)\n");
now = status.st_ctime;
tstr = localtime (&now);
(void) fprintf (stdout, "ctime:\t\t%02d:%02d:%02d %02d/%02d/%02d\t",
tstr->tm_hour, tstr->tm_min, tstr->tm_sec,
tstr->tm_mon+1, tstr->tm_mday, tstr->tm_year);
(void) fprintf (stdout, "(Last Data Modification)\n");
now = status.st_mtime;
tstr = localtime (&now);
(void) fprintf (stdout, "mtime:\t\t%02d:%02d:%02d %02d/%02d/%02d\t",
tstr->tm_hour, tstr->tm_min, tstr->tm_sec,
tstr->tm_mon+1, tstr->tm_mday, tstr->tm_year);
(void) fprintf (stdout, "(Last File Status Change)\n");
return (0);
}
If you save the above as, say, status.c, you can
Code:
make status
or
cc -o status status.c
Usage is
Code:
status file.name
or
for FILE in *
do
status ${FILE}
done
I know the du command recalculates file size by reading the file directly. Does the ls command do this or does it read the file size from the inode?
Where did you read this? And what does it mean? The file itself is just a stream. If the inode is "wrong" about the file size, there's nothing in the file that gives any better information.
(I'm including the inode pointer blocks in what I mean by the inode, even though some of them can be indirect. They're still part of the metadata not part of the file.)
((OK now I think I know what you mean. If the file is sparse (or in some other cases) it may use less disk space - fewer physical disk blocks - than its apparent size. The space used, as reported by du (and the Blocks: part of stat), is the combined size of all the disk blocks it uses ... but this is still recorded in the inode and indirect metadata, not in the "file itself". ls and the Size: part of stat report the actual or apparent size read from a single field in the inode. For most files, this will be a bit smaller than the space used, if the last disk block is not full. But either way these are different meanings, one is not more accurate than the other.))
Last edited by SecretCode; 09-15-2012 at 09:48 AM.
Reason: fallocate doesn't do what I thought. stat does both.
The file actually is taking that space on the drive. That space is reserved and can't be used so I guess we get to the question of what is the size. Size on disk or actual size of file.
10 terabytes works too. I promise i don't have that much disk.
Code:
$ dd of=takes-no-space bs=1 count=0 seek=10T
0+0 records in
0+0 records out
0 bytes (0 B) copied, 1.776e-05 s, 0.0 kB/s
[joe@sourdust: ~/tests] Sat Sep 15 18:36:48
$ ls -lh takes-no-space
-rw-rw-r-- 1 joe joe 10T 2012-09-15 18:36 takes-no-space
When I try 16T I get an error,
Code:
dd: failed to truncate to 17592186044416 bytes in output file `takes-no-space': File too large
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.