I am trying to write a stub for the function stat() from <sys/stat.h>. I was able to successfully do this for fstat with the following code:
static int fstat_count;
static int fstat_fail_instance;
int my_fstat(const int fd, struct stat * st) {
fstat_count ++;
if (fstat_count == fstat_fail_instance) {
return EINVAL;
}
st->st_size = ST_SIZE;
return EOK;
}
#undef fstat
#define fstat my_fstat
When I try to do this with stat, I get errors like:
mkqfs_file_test.c:28:20: error: storage size of ‘sb’ isn’t known
const struct stat sb;
which i believe is because when I do the
#undef stat
#define stat my_stat
like i do for fstat, it is undefining the struct stat not the function.
Any idea how I can resolve this, ie only undefine/redefine function?
[...] I get errors like:
mkqfs_file_test.c:28:20: error: storage size of ‘sb’ isn’t known const struct stat sb;
which i believe is because when I do the
#undef stat
#define stat my_stat
like i do for fstat, it is undefining the struct stat not the function.
No, #undef stat
does not undefine any function or any struct type. It undefines any previous definition of a preprocessor macro with that name. As such, it is probably unnecessary, and at worst it is harmless. In the unlikely event that there were such an existing macro definition, however, a conforming program does need to undefine that before redefining it.
The problem is rather with the #define
. If the definition of the stat
macro is visible where your struct declaration appears then it will be expanded where that identifier is used as a structure tag. As a result, this ...
const struct stat sb;
... expands to ...
const struct my_stat sb;
. There being no definition of a type struct my_struct
visible in scope, that declaration is not permitted. As the compiler says, it doesn't know how much space to provide for a struct my_stat
, nor would it be usable anyway because the compiler doesn't know what any of its members are, either. Note that this does not prevent declaring or using pointers to a struct my_stat
, but that has its own issues.
Any idea how I can resolve this, ie only undefine/redefine function?
Again, you are not undefining any function. There is no completely clean way to use a macro to substitute your my_stat()
for stat()
on account of stat
being used for related purposes in different namespaces. There are three main things you could do:
Use a function-like macro instead:
#define stat(p,b) my_stat((p),(b))
In that event, you must ensure that there is no attempt to compute a pointer to stat
. This is probably your best option.
Omit the #undefine
and #define
altogether, and name your replacement function stat()
, the same as the original. This relies on the linker to choose your locally-defined version over the library version, which it probably will do. That risks having wider impact than you intend, however.
Before the #undefine
, declare a typedef
for struct stat
:
typedef struct stat struct_stat;
#undefine stat
#define stat my_stat
Then use the typedef
instead of type struct stat
everywhere that your macro definition is visible:
struct_stat sb;