tags:

views:

290

answers:

4

I have to write a program in C which returns file size in blocks just like ls -s command. Please help.

I tried using stat() function (st_blksize)...And I am unable to implement it.

My code looks like this

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>

void main(int argc, char **argv)
{
    DIR           *dp;
    struct dirent *dirp;
    struct stat    buf;

    if(argc < 2)
    {
        dp = opendir(".");
    }

    if(dp == NULL)
    {
        perror("Cannot open directory ");
        exit(2);
    }

    while ((dirp = readdir(dp)) != NULL)
    {
        printf("%s\n", dirp->d_name);
        if (stat(".", &buf))
        printf("%d ", buf.st_blksize);
    }

    closedir(dp);
    exit(0);
}

It is giving error buf size is not declared. Don't know what is the problem.

Addition

Thanks for the correction. I included the <sys/stat.h> header file. Now it is giving a warning:

warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘__blksize_t’

I am new to C so can't make out what should be the possible solution.

+1  A: 
ShinTakezou
The `ls` command does not open files - nor should its replacement.
Jonathan Leffler
The user's original post talked about just "like ls -s", not specifying he wanted a clone of `ls`, but just that he needed the info "returned". He could use fstat if he's already opened the file for whatever reason. If you prefer read my words like: Open the file and fstat or stat it... Btw, between opendir, readdir and closedir I should've put stat, otherwise here one can think I believe that opendir-readdir is enough to get files' struct stat... Later he posted the code, I am going to take a look at it now
ShinTakezou
ops the title maybe suggested that idea of a ls replacement...
ShinTakezou
+4  A: 

You need to include the correct header:

#incude <sys/stat.h>

That declares the structure and associated functions.

Note that stat() returns zero on success, so your test needs changing (and, as @jsmchmier pointed out in a comment, the call to stat should probably use dirp->d_name rather than the string literal "."). Also, st_blksize is the size of the disk blocks, not the size of the file - that is st_size (measured in bytes).

POSIX says:

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.

blksize_t st_blksize A file system-specific preferred I/O block size for this object. In some file system types, this may vary from file to file.

blkcnt_t st_blocks Number of blocks allocated for this object.

Note that old (very old) versions of Unix did not support st_blksize or st_blocks. I expect most current versions do.


Now it is giving a warning..warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘__blksize_t’

The chances are that __blksize_t is an unisgned integer type similar to size_t. I'd probably use a simple cast:

printf("Block size = %d\n", (int)buf.st_blksize);

Alternatively, if you have C99 available, you could use the facilities from <inttypes.h> to use a bigger size:

printf("Block size = %" PRIu64 "\n", (uint64_t)buf.st_blksize);

In practice, this is overkill; the block size is unlikely to exceed 2 GB this decade, so int is likely to be sufficient for the foreseeable future.

Jonathan Leffler
If you are relying on `uint64_t` then you need C99; in which case you have `unsigned long long`, with the `%llu` format specifier, so you might as well use that (which is *at least* as big as `uint64_t`).
caf
+1  A: 

From man 2 stat on my Mac OS X box:

NAME
     fstat, fstat64, lstat, lstat64, stat, stat64 -- get file status  

SYNOPSIS  
     #include <sys/stat.h>  

     int
     fstat(int fildes, struct stat *buf);

Note the #include <sys/stat.h> which you have not done. No doubt the actual layout of struct stat is defined in there, which is what your compiler is complaining about.

This is one aspect of the man pages which is not always discussed with beginners but is very useful indeed: the whole unix API is documented in them. Oh, it is not always the easiest place to find a function when you know what it should do but don't know what it is called, but all the answers are there.

dmckee
A: 

Careful, one bug in your code is that dp points to garbage and is only initialised if argc is less than 2, but you still try to use it in your while loop and you also try to closedir it. If you invoke your application with any arguments at all, it will probably crash.

dreamlax