Something Simple?

Something Simple?

Post by ncc1701 » Fri, 01 Jan 1999 04:00:00



NNTP-Posting-Date: Wed, 30 Dec 1998 22:32:41 PDT

Hi Gurus....
I'm just getting started in programming for Linux(My goal? Help out the
Linux movement of course :)  Something that I was working on was a small
program that uses fstat to get file statistics on a file specified at the
command line.  However when I go to print out the information something is
wrong.  I'm using printf in the normal format (I think) to print out data to
the screen,

printf("screeninfo: %d\n",st.st_size);

if I use this command and specify each of the returned structure information
I don't have the problem.  But if I put in all the data in one big long
printf statement I start to get data that isn't correct.  I'm using the
following code for my printf statement in my program:

 printf("File Statistics:\n");
 printf("          Device: %d\n"
        "      Protection: %d\n"
        " Hard Link Count: %d\n"
        "      Owner's ID: %d\n"
        "      Group's ID: %d\n"
        "     Device Type: %d\n"
               "       File Size: %d\n"
             "FileSysBlocksize: %d\n"
        "Allocated blocks: %d\n"
        "Last Accessed on: %d\n"
        "Last Modified on: %d\n"
        " Last Changed on: %d\n"
"Inode:
%d\n",st.st_dev,st.st_mode,st.st_nlink,st.st_uid,st.st_gid,st.st_rdev,st.st_
size,st.st_blksize,st.st_blocks,st.st_atime,st.st_mtime,st.st_ctime,st.st_in
o);

The above statement is my actual command for printing the file information.
And I'm getting zeros in places that should be actual numbers.  The
following code is just another set of printf statements all of which return
the correct data:

 printf("%d\n",st.st_dev);
 printf("%d\n",st.st_ino);
 printf("%d\n",st.st_mode);

This works great.  The following fails though:

 printf("%d\n%d\n%d\n",st.st_dev,st.st_ino,st.st_mode);

I'm getting a zero in place of st.st_ino, and the actual data that should be
in st.st_mode is displaying the data that belongs to st.st_ino. Plus I never
see the data that should be in st.st_mode.  I'm sure that I have everything
specified correctly.  At the bottom of this message is the actual program
itself that I'm using to compile.  The program is basically a copy program
with statistics on the copy.  I have tried spaces after all of the commas.

RedHat 5.2 and I have upgraded the kernel to 2.1.130.  If I'm doing
something that is completely incorrect please let me know like I said I'm a
beginner....

Thanks in advance,

Jason

Here is the actual code I'm compiling on my Linux box...

#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    char block[8192];
    int in, out;
    int nread;
    int a;
    int stats=8192;
    int filestats;
    struct stat st;

    if(argc != 3) {
 if (argc == 1) printf("Only %d option detected\n",argc);
 else printf("Only %d options detected\n",argc);
 printf("Options detected as:\n");
 for(a=0; a < argc; a++){
     printf("%s\n",argv[a]);
 }
 return;
    }

    in = open(argv[1], O_RDONLY);

    if (fstat(in, &st) != -1) {
 printf("File Statistics:\n");
 printf("          Device: %d\n"
        "      Protection: %d\n"
        " Hard Link Count: %d\n"
        "      Owner's ID: %d\n"
        "      Group's ID: %d\n"
        "     Device Type: %d\n"
               "       File Size: %d\n"
             "FileSysBlocksize: %d\n"
        "Allocated blocks: %d\n"
        "Last Accessed on: %d\n"
        "Last Modified on: %d\n"
        " Last Changed on: %d\n"
        "           Inode:
%d\n",st.st_dev,st.st_mode,st.st_nlink,st.st_uid,st.st_gid,st.st_rdev,st.st_
size,st.st_blksize,st.st_blocks,st.st_atime,st.st_mtime,st.st_ctime,st.st_in
o);  <This Fails
 printf("%d\n", st.st_dev);
 printf("%d\n", st.st_ino);
 printf("%d\n", st.st_mode);  The above three lines work correctly
 printf("%d\n%d\n%d\n",st.st_dev, st.st_ino, st.st_mode);  Even this line
fails
 printf("\nCopy Progress\n");

        out = open(argv[2], O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);

 while((nread = read(in,block,sizeof(block))) > 0) {
     write(out,block,nread);
     stats=stats+nread;
     printf("%i bytes copied so far",stats);
     printf("  --  %i bytes left to be copied",st.st_size-stats);
         printf("\r");
 }
    } else {
 printf("File Problem\n");
    }
    printf("\n");
    exit(0);

Quote:}

 
 
 

Something Simple?

Post by Andi Kle » Fri, 01 Jan 1999 04:00:00



> printf("File Statistics:\n");
> printf("          Device: %d\n"
>        "      Protection: %d\n"
>        " Hard Link Count: %d\n"
>        "      Owner's ID: %d\n"
>        "      Group's ID: %d\n"
>        "     Device Type: %d\n"
>               "       File Size: %d\n"
>             "FileSysBlocksize: %d\n"
>        "Allocated blocks: %d\n"
>        "Last Accessed on: %d\n"
>        "Last Modified on: %d\n"
>        " Last Changed on: %d\n"
>"Inode:
>%d\n",st.st_dev,st.st_mode,st.st_nlink,st.st_uid,st.st_gid,st.st_rdev,st.st_
>size,st.st_blksize,st.st_blocks,st.st_atime,st.st_mtime,st.st_ctime,st.st_in
>o);

Compile with -Wall and the compiler will tell you.

-Andi

 
 
 

Something Simple?

Post by Terr » Fri, 01 Jan 1999 04:00:00



[snip]
> following code for my printf statement in my program:

>  printf("File Statistics:\n");
>  printf("          Device: %d\n"
>         "      Protection: %d\n"
>         " Hard Link Count: %d\n"
>         "      Owner's ID: %d\n"
>         "      Group's ID: %d\n"
>         "     Device Type: %d\n"
>                "       File Size: %d\n"
>              "FileSysBlocksize: %d\n"
>         "Allocated blocks: %d\n"
>         "Last Accessed on: %d\n"
>         "Last Modified on: %d\n"
>         " Last Changed on: %d\n"
> "Inode:
> %d\n",st.st_dev,st.st_mode,st.st_nlink,st.st_uid,st.st_gid,st.st_rdev,st.st_
> size,st.st_blksize,st.st_blocks,st.st_atime,st.st_mtime,st.st_ctime,st.st_in
> o);

> The above statement is my actual command for printing the file information.
> And I'm getting zeros in places that should be actual numbers.  The
> following code is just another set of printf statements all of which return
> the correct data:

>  printf("%d\n",st.st_dev);
>  printf("%d\n",st.st_ino);
>  printf("%d\n",st.st_mode);

> This works great.  The following fails though:

>  printf("%d\n%d\n%d\n",st.st_dev,st.st_ino,st.st_mode);

> I'm getting a zero in place of st.st_ino, and the actual data that should be
> in st.st_mode is displaying the data that belongs to st.st_ino. Plus I never
> see the data that should be in st.st_mode.  I'm sure that I have everything
> specified correctly.  At the bottom of this message is the actual program
> itself that I'm using to compile.  The program is basically a copy program
> with statistics on the copy.  I have tried spaces after all of the commas.

Sounds like the type for "st.st_dev","st.st_ino", etc is NOT integer
(more precisely, not the same size of integer).  Therefore you cannot
use "%d" in the printf statement.  I haven't looked at the
structure but some of its' members may be SHORT or LONG LONG.
The reason it's ok when printed separately is that only the first
four bytes (assuming 4 bytes for size of integer) is converted.

If you change the printf statement to:
   printf("%d\n%d\n%d\n",(int)st.st_dev, (int)st.st_ino,
         (int)st.st_mode);

It will (probably) work.

You could dig around in the include files to find out the true
size and then use the correct printf conversion specifier.

Hope this helps.

Terry

 
 
 

Something Simple?

Post by David D. Gitchel » Fri, 01 Jan 1999 04:00:00


Yes, the problem is something simple:  Not all of the elements of the
stat struct are of size integer, yet you used the "%d" (integer) format
specification for all of the parameters to printf.  This should put you
out of alignment with the remaining parameters after you hit the first
long in the parameter string.


> I'm using the
> following code for my printf statement in my program:

>  printf("File Statistics:\n");
>  printf("          Device: %d\n"
>         "      Protection: %d\n"
>         " Hard Link Count: %d\n"
>         "      Owner's ID: %d\n"
>         "      Group's ID: %d\n"
>         "     Device Type: %d\n"
>                "       File Size: %d\n"
>              "FileSysBlocksize: %d\n"
>         "Allocated blocks: %d\n"
>         "Last Accessed on: %d\n"
>         "Last Modified on: %d\n"
>         " Last Changed on: %d\n"
> "Inode:
> %d\n",st.st_dev,st.st_mode,st.st_nlink,st.st_uid,st.st_gid,st.st_rdev,st.st_
> size,st.st_blksize,st.st_blocks,st.st_atime,st.st_mtime,st.st_ctime,st.st_in
> o);

Here's a simple program to display the sizes of each of the elements of
the stat structure, followed by the results of its execution:

#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

/* ********************************************************* */
void main() {
  printf("Sizes of 'struct stat' elements:\n");
  printf("st_dev:  \t%d\n",sizeof(dev_t));
  printf("st_ino:  \t%d\n",sizeof(ino_t));
  printf("st_mode:\t%d\n",sizeof(mode_t));
  printf("st_nlink:\t%d\n",sizeof(nlink_t));
  printf("st_uid:  \t%d\n",sizeof(uid_t));
  printf("st_gid:  \t%d\n",sizeof(gid_t));
  printf("st_rdev:\t%d\n",sizeof(dev_t));
  printf("st_size:\t%d\n",sizeof(off_t));
  printf("st_blksize:\t%d\n",sizeof(unsigned long));
  printf("st_blocks:\t%d\n",sizeof(unsigned long));
  printf("st_atime:\t%d\n",sizeof(time_t));
  printf("st_mtime:\t%d\n",sizeof(time_t));
  printf("st_ctime:\t%d\n",sizeof(time_t));

Quote:}

/* ********************************************************* */

Sizes of 'struct stat' elements:
st_dev:         8
st_ino:         4
st_mode:        4
st_nlink:       4
st_uid:         4
st_gid:         4
st_rdev:        8
st_size:        4
st_blksize:     4
st_blocks:      4
st_atime:       4
st_mtime:       4
st_ctime:       4

Note that st_dev is EIGHT bytes long.  Since you passed the %d format
specification to printf, printf will take the first four bytes off the
stack as an integer parameter, and print that result.  The next four
bytes of that same parameter will be used for the NEXT %d format
specification, and each of your entries will be displaced by one entry
for the rest of the printf statement.

Note also that you will have the same problem when you hit st_rdev.

You have to give the correct format specifications to printf; it can't
second-guess what you're passing it.

From this you should be able to figure out on your own why it works when
you print them individually, but doesn't when you stack them into one
printf statement.

Enjoy!
-- Dave
------------------------------------------------------------
#include <std_disclaimer.h> /* I speak for myself, only. */|
------------------------------------------------------------
LCDR David D. Gitchell, USN (Retired),   Hutchinson, KS, USA

 
 
 

Something Simple?

Post by ncc1701 » Fri, 01 Jan 1999 04:00:00


NNTP-Posting-Date: Thu, 31 Dec 1998 13:12:21 PDT

Thanks for all the postings guys.  You have helped me out considerably.  Now
I just have to figure out how to use the printf command to print out a
"Special" type variable.  The ST_RDEV variable for instance I believe is
defined as a long long, looked at the include files features.h and
statbuf.h.  The st_ctime, st_mtime, and st_atime are also defined as special
types in the include files.  Do I have to do something special to specify a
type conversion in printf if the variable is an object of a structure?  Did
I even ask that right?

Thanks in advance....

Jason

 
 
 

Something Simple?

Post by Stephen Lee - Post replies pleas » Tue, 05 Jan 1999 04:00:00




Quote:>Here's a simple program to display the sizes of each of the elements of
>the stat structure, followed by the results of its execution:

<pedantic>

Quote:>void main() {

main() returns int.

Quote:>  printf("Sizes of 'struct stat' elements:\n");
>  printf("st_dev:  \t%d\n",sizeof(dev_t));

sizeof returns an unsigned type so %d is definitely not correct.  Since you
do not know the size of size_t you should typecast here.  The type te
typecast to is left as an exercise to the reader...

</pedantic>

Stephen

 
 
 

1. I am missing something simple

Hey all!

The newbie got the complilers to work, even found the <stdio.h> header
in one of the redhat 5.1 rpm's.  I am able to compile a simple "hello
world" c source file but I cannot get it to execute (a.out).  I am
running the bash shell.  I change the permissions tochmos 777 a.out (rwx
to all groups), but when I try to run it, I get "bash: a.out unknown
command"

Can you help?  I think is is something so simple that it is under my
nose!

JL
remove the underlines and "nospam" to email

2. I need a box-drawing font (or a font editor(

3. need help doing something simple(?)

4. File systems corrupt!

5. Samba - m I forgetting something simple

6. Q: restricting user from logging in certain tty's

7. ksh arrays: missing something simple

8. DecAlpha box failing to start. Urgent help required Please!

9. natd HELP! Probley something simple

10. Something Seemingly Simple.

11. Probably something really simple but...

12. Need something portable to write a simple menu

13. qualitylinks, need something, find something