[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

st_dev and st_rdev members of 'stat struct' are not of dev_t type on mips/mipsel




Hi guys,

(I'm not subscribed to the list, so please CC)

After digging through the buildd logs of libisoburn, we found out interesting compiler warnings on mips and mipsel.

https://buildd.debian.org/status/fetch.php?pkg=libisoburn&arch=mips&ver=1.1.8-1&stamp=1321892998

xorriso/iso_tree.c: In function 'Xorriso_fake_stbuf':
xorriso/iso_tree.c:256:4: warning: passing argument 4 of 'Xorriso_node_get_dev' from incompatible pointer type [enabled by default] xorriso/iso_tree.c:204:5: note: expected 'dev_t *' but argument is of type 'long unsigned int *' xorriso/iso_tree.c:259:4: warning: passing argument 4 of 'Xorriso_node_get_dev' from incompatible pointer type [enabled by default] xorriso/iso_tree.c:204:5: note: expected 'dev_t *' but argument is of type 'long unsigned int *'


Which basically means that st_rdev member of stat struct is not of type dev_t on mips and mipsel, which of course deviates from man 2 stat, that prescribes that st_rdev member (as well as st_dev member) of stat struct must be of type dev_t.

I wonder what could be wrong with the definition of the stat struct on mips/mipsel, it is a known flaw in libc, and whether it has anything to do with the situation of having 64-bit kernel and 32 bit userland, usually met on misp/mipsel.

Yes, the issue could be solved in the application side if one knows about the problem on these particular architectures (mips/mipsel), but I believe this is not the general case.


A simplified code demonstrating the issue:
~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

void func(dev_t *dev) {
   *dev=2;
}

int main() {
        struct stat ss;
        ss.st_rdev = 1;
        printf("ss.st_rdev %ld\n", ss.st_rdev);
        func( & (ss.st_rdev) );           // protested on mips{el}
dev_t dummy = ss.st_rdev; // work-around with a temp dev_t object
        func(&dummy);
        printf("ss.st_rdev %ld\n", ss.st_rdev);

        printf("sizeof st_rdev %u\n", sizeof(ss.st_rdev));
        printf("sizeof dev_t   %u\n", sizeof(dev_t));
        printf("sizeof __dev_t %u\n", sizeof(__dev_t));
        printf("sizeof ul  int %u\n", sizeof(unsigned long int));
        printf("sizeof ull int %u\n", sizeof(unsigned long long int));
        printf("sizeof stat    %u\n", sizeof(ss));

        return 0;
}


mips{el}
~~~~~~
$ gcc test.c
test.c: In function ‘main’:
test.c:14:2: warning: passing argument 1 of ‘func’ from incompatible pointer type [enabled by default] test.c:6:6: note: expected ‘dev_t *’ but argument is of type ‘long unsigned int *’

$ ./a.out
ss.st_rdev 1
ss.st_rdev 2
sizeof st_rdev 4
sizeof dev_t   8
sizeof __dev_t 8
sizeof ul  int 4
sizeof ull int 8
sizeof stat    144


amd64
~~~~
$ gcc test.c
$ ./a.out
ss.st_rdev 1
ss.st_rdev 2
sizeof st_rdev 8
sizeof dev_t   8
sizeof __dev_t 8
sizeof ul  int 8
sizeof ull int 8
sizeof stat    144



I tried to trace this type deviation of the stat dev_t members in the headers, but gave up, and tried to look at gcc -E output, where I realize that dev_t type is 'unsigned long long int', where stat.st_rdev is of type 'unsigned long int'


$ grep dev_t gcc-E
__extension__ typedef __u_quad_t __dev_t;
typedef __dev_t dev_t;

$ grep quad_t gcc-E
__extension__ typedef long long int __quad_t;
__extension__ typedef unsigned long long int __u_quad_t;
__extension__ typedef __u_quad_t __dev_t;
__extension__ typedef __u_quad_t __ino64_t;
__extension__ typedef __quad_t __off64_t;
__extension__ typedef __u_quad_t __rlim64_t;
__extension__ typedef __quad_t __blkcnt64_t;
__extension__ typedef __u_quad_t __fsblkcnt64_t;
__extension__ typedef __u_quad_t __fsfilcnt64_t;
typedef __quad_t *__qaddr_t;
typedef __quad_t quad_t;
typedef __u_quad_t u_quad_t;


--
pub 4096R/0E4BD0AB <people.fccf.net/danchev/key pgp.mit.edu>


Reply to: