wolfcw / libfaketime

libfaketime modifies the system time for a single application
https://github.com/wolfcw/libfaketime
GNU General Public License v2.0
2.71k stars 324 forks source link

Build broken with Alpine 3.19 #446

Closed peterthomassen closed 9 months ago

peterthomassen commented 9 months ago

When building with gcc 12 (e.g. Alpine 3.18), all is fine. With gcc 13 (e.g. Alpine 3.19), the following happens:

make  -C src all
make[1]: Entering directory '/usr/local/src/libfaketime/src'
cc -o libfaketime.o -c -std=gnu99 -Wall -Wextra -Werror -DFAKE_PTHREAD -DFAKE_STAT -DFAKE_UTIME -DFAKE_SLEEP -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'/usr/local'"' -DLIBDIRNAME='"'/lib/faketime'"'  -Wno-nonnull-compare   libfaketime.c
libfaketime.c:191:72: error: 'struct stat64' declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
  191 | static int          (*real_xstat64)         (int, const char *, struct stat64 *);
      |                                                                        ^~~~~~
libfaketime.c:192:64: error: 'struct stat64' declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
  192 | static int          (*real_fxstat64)        (int, int , struct stat64 *);
      |                                                                ^~~~~~
libfaketime.c:193:78: error: 'struct stat64' declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
  193 | static int          (*real_fxstatat64)      (int, int , const char *, struct stat64 *, int);
      |                                                                              ^~~~~~
libfaketime.c:194:72: error: 'struct stat64' declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
  194 | static int          (*real_lxstat64)        (int, const char *, struct stat64 *);
      |                                                                        ^~~~~~
libfaketime.c:960:43: error: 'struct stat64' declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
  960 | static inline void fake_stat64buf (struct stat64 *buf) {
      |                                           ^~~~~~
libfaketime.c: In function 'fake_stat64buf':
libfaketime.c:970:42: error: invalid use of undefined type 'struct stat64'
  970 |   fake_clock_gettime(CLOCK_REALTIME, &buf->st_ctim);
      |                                          ^~
libfaketime.c:971:42: error: invalid use of undefined type 'struct stat64'
  971 |   fake_clock_gettime(CLOCK_REALTIME, &buf->st_atim);
      |                                          ^~
libfaketime.c:972:42: error: invalid use of undefined type 'struct stat64'
  972 |   fake_clock_gettime(CLOCK_REALTIME, &buf->st_mtim);
      |                                          ^~
libfaketime.c: At top level:
libfaketime.c:1094:50: error: 'struct stat64' declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
 1094 | int __xstat64 (int ver, const char *path, struct stat64 *buf)
      |                                                  ^~~~~~
libfaketime.c: In function '__xstat64':
libfaketime.c:1096:43: error: passing argument 3 of 'real_xstat64' from incompatible pointer type [-Werror=incompatible-pointer-types]
 1096 |   STAT64_HANDLER(xstat64, buf, ver, path, buf);
      |                                           ^~~
      |                                           |
      |                                           struct stat64 *
libfaketime.c:179:5: note: in definition of macro 'DONT_FAKE_TIME'
  179 |     call;                             \
      |     ^~~~
libfaketime.c:1029:3: note: in expansion of macro 'STAT_HANDLER_COMMON'
 1029 |   STAT_HANDLER_COMMON(name, buf, fake_stat64buf, __VA_ARGS__)
      |   ^~~~~~~~~~~~~~~~~~~
libfaketime.c:1096:3: note: in expansion of macro 'STAT64_HANDLER'
 1096 |   STAT64_HANDLER(xstat64, buf, ver, path, buf);
      |   ^~~~~~~~~~~~~~
libfaketime.c:1096:43: note: expected 'struct stat64 *' but argument is of type 'struct stat64 *'
 1096 |   STAT64_HANDLER(xstat64, buf, ver, path, buf);
      |                                           ^~~
libfaketime.c:179:5: note: in definition of macro 'DONT_FAKE_TIME'
  179 |     call;                             \
      |     ^~~~
libfaketime.c:1029:3: note: in expansion of macro 'STAT_HANDLER_COMMON'
 1029 |   STAT_HANDLER_COMMON(name, buf, fake_stat64buf, __VA_ARGS__)
      |   ^~~~~~~~~~~~~~~~~~~
libfaketime.c:1096:3: note: in expansion of macro 'STAT64_HANDLER'
 1096 |   STAT64_HANDLER(xstat64, buf, ver, path, buf);
      |   ^~~~~~~~~~~~~~
libfaketime.c:1096:27: error: passing argument 1 of 'fake_stat64buf' from incompatible pointer type [-Werror=incompatible-pointer-types]
 1096 |   STAT64_HANDLER(xstat64, buf, ver, path, buf);
      |                           ^~~
      |                           |
      |                           struct stat64 *
libfaketime.c:1020:36: note: in definition of macro 'STAT_HANDLER_COMMON'
 1020 |       if (!dont_fake) fake_statbuf(buf); \
      |                                    ^~~
libfaketime.c:1096:3: note: in expansion of macro 'STAT64_HANDLER'
 1096 |   STAT64_HANDLER(xstat64, buf, ver, path, buf);
      |   ^~~~~~~~~~~~~~
libfaketime.c:960:51: note: expected 'struct stat64 *' but argument is of type 'struct stat64 *'
  960 | static inline void fake_stat64buf (struct stat64 *buf) {
      |                                    ~~~~~~~~~~~~~~~^~~
libfaketime.c: At top level:
libfaketime.c:1102:45: error: 'struct stat64' declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
 1102 | int __fxstat64 (int ver, int fildes, struct stat64 *buf)
      |                                             ^~~~~~
libfaketime.c: In function '__fxstat64':
libfaketime.c:1104:46: error: passing argument 3 of 'real_fxstat64' from incompatible pointer type [-Werror=incompatible-pointer-types]
 1104 |   STAT64_HANDLER(fxstat64, buf, ver, fildes, buf);
      |                                              ^~~
      |                                              |
      |                                              struct stat64 *
libfaketime.c:179:5: note: in definition of macro 'DONT_FAKE_TIME'
  179 |     call;                             \
      |     ^~~~
libfaketime.c:1029:3: note: in expansion of macro 'STAT_HANDLER_COMMON'
 1029 |   STAT_HANDLER_COMMON(name, buf, fake_stat64buf, __VA_ARGS__)
      |   ^~~~~~~~~~~~~~~~~~~
libfaketime.c:1104:3: note: in expansion of macro 'STAT64_HANDLER'
 1104 |   STAT64_HANDLER(fxstat64, buf, ver, fildes, buf);
      |   ^~~~~~~~~~~~~~
libfaketime.c:1104:46: note: expected 'struct stat64 *' but argument is of type 'struct stat64 *'
 1104 |   STAT64_HANDLER(fxstat64, buf, ver, fildes, buf);
      |                                              ^~~
libfaketime.c:179:5: note: in definition of macro 'DONT_FAKE_TIME'
  179 |     call;                             \
      |     ^~~~
libfaketime.c:1029:3: note: in expansion of macro 'STAT_HANDLER_COMMON'
 1029 |   STAT_HANDLER_COMMON(name, buf, fake_stat64buf, __VA_ARGS__)
      |   ^~~~~~~~~~~~~~~~~~~
libfaketime.c:1104:3: note: in expansion of macro 'STAT64_HANDLER'
 1104 |   STAT64_HANDLER(fxstat64, buf, ver, fildes, buf);
      |   ^~~~~~~~~~~~~~
libfaketime.c:1104:28: error: passing argument 1 of 'fake_stat64buf' from incompatible pointer type [-Werror=incompatible-pointer-types]
 1104 |   STAT64_HANDLER(fxstat64, buf, ver, fildes, buf);
      |                            ^~~
      |                            |
      |                            struct stat64 *
libfaketime.c:1020:36: note: in definition of macro 'STAT_HANDLER_COMMON'
 1020 |       if (!dont_fake) fake_statbuf(buf); \
      |                                    ^~~
libfaketime.c:1104:3: note: in expansion of macro 'STAT64_HANDLER'
 1104 |   STAT64_HANDLER(fxstat64, buf, ver, fildes, buf);
      |   ^~~~~~~~~~~~~~
libfaketime.c:960:51: note: expected 'struct stat64 *' but argument is of type 'struct stat64 *'
  960 | static inline void fake_stat64buf (struct stat64 *buf) {
      |                                    ~~~~~~~~~~~~~~~^~~
libfaketime.c: At top level:
libfaketime.c:1111:69: error: 'struct stat64' declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
 1111 | int __fxstatat64 (int ver, int fildes, const char *filename, struct stat64 *buf, int flag)
      |                                                                     ^~~~~~
libfaketime.c: In function '__fxstatat64':
libfaketime.c:1113:58: error: passing argument 4 of 'real_fxstatat64' from incompatible pointer type [-Werror=incompatible-pointer-types]
 1113 |   STAT64_HANDLER(fxstatat64, buf, ver, fildes, filename, buf, flag);
      |                                                          ^~~
      |                                                          |
      |                                                          struct stat64 *
libfaketime.c:179:5: note: in definition of macro 'DONT_FAKE_TIME'
  179 |     call;                             \
      |     ^~~~
libfaketime.c:1029:3: note: in expansion of macro 'STAT_HANDLER_COMMON'
 1029 |   STAT_HANDLER_COMMON(name, buf, fake_stat64buf, __VA_ARGS__)
      |   ^~~~~~~~~~~~~~~~~~~
libfaketime.c:1113:3: note: in expansion of macro 'STAT64_HANDLER'
 1113 |   STAT64_HANDLER(fxstatat64, buf, ver, fildes, filename, buf, flag);
      |   ^~~~~~~~~~~~~~
libfaketime.c:1113:58: note: expected 'struct stat64 *' but argument is of type 'struct stat64 *'
 1113 |   STAT64_HANDLER(fxstatat64, buf, ver, fildes, filename, buf, flag);
      |                                                          ^~~
libfaketime.c:179:5: note: in definition of macro 'DONT_FAKE_TIME'
  179 |     call;                             \
      |     ^~~~
libfaketime.c:1029:3: note: in expansion of macro 'STAT_HANDLER_COMMON'
 1029 |   STAT_HANDLER_COMMON(name, buf, fake_stat64buf, __VA_ARGS__)
      |   ^~~~~~~~~~~~~~~~~~~
libfaketime.c:1113:3: note: in expansion of macro 'STAT64_HANDLER'
 1113 |   STAT64_HANDLER(fxstatat64, buf, ver, fildes, filename, buf, flag);
      |   ^~~~~~~~~~~~~~
libfaketime.c:1113:30: error: passing argument 1 of 'fake_stat64buf' from incompatible pointer type [-Werror=incompatible-pointer-types]
 1113 |   STAT64_HANDLER(fxstatat64, buf, ver, fildes, filename, buf, flag);
      |                              ^~~
      |                              |
      |                              struct stat64 *
libfaketime.c:1020:36: note: in definition of macro 'STAT_HANDLER_COMMON'
 1020 |       if (!dont_fake) fake_statbuf(buf); \
      |                                    ^~~
libfaketime.c:1113:3: note: in expansion of macro 'STAT64_HANDLER'
 1113 |   STAT64_HANDLER(fxstatat64, buf, ver, fildes, filename, buf, flag);
      |   ^~~~~~~~~~~~~~
libfaketime.c:960:51: note: expected 'struct stat64 *' but argument is of type 'struct stat64 *'
  960 | static inline void fake_stat64buf (struct stat64 *buf) {
      |                                    ~~~~~~~~~~~~~~~^~~
libfaketime.c: At top level:
libfaketime.c:1120:51: error: 'struct stat64' declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
 1120 | int __lxstat64 (int ver, const char *path, struct stat64 *buf)
      |                                                   ^~~~~~
libfaketime.c: In function '__lxstat64':
libfaketime.c:1122:44: error: passing argument 3 of 'real_lxstat64' from incompatible pointer type [-Werror=incompatible-pointer-types]
 1122 |   STAT64_HANDLER(lxstat64, buf, ver, path, buf);
      |                                            ^~~
      |                                            |
      |                                            struct stat64 *
libfaketime.c:179:5: note: in definition of macro 'DONT_FAKE_TIME'
  179 |     call;                             \
      |     ^~~~
libfaketime.c:1029:3: note: in expansion of macro 'STAT_HANDLER_COMMON'
 1029 |   STAT_HANDLER_COMMON(name, buf, fake_stat64buf, __VA_ARGS__)
      |   ^~~~~~~~~~~~~~~~~~~
libfaketime.c:1122:3: note: in expansion of macro 'STAT64_HANDLER'
 1122 |   STAT64_HANDLER(lxstat64, buf, ver, path, buf);
      |   ^~~~~~~~~~~~~~
libfaketime.c:1122:44: note: expected 'struct stat64 *' but argument is of type 'struct stat64 *'
 1122 |   STAT64_HANDLER(lxstat64, buf, ver, path, buf);
      |                                            ^~~
libfaketime.c:179:5: note: in definition of macro 'DONT_FAKE_TIME'
  179 |     call;                             \
      |     ^~~~
libfaketime.c:1029:3: note: in expansion of macro 'STAT_HANDLER_COMMON'
 1029 |   STAT_HANDLER_COMMON(name, buf, fake_stat64buf, __VA_ARGS__)
      |   ^~~~~~~~~~~~~~~~~~~
libfaketime.c:1122:3: note: in expansion of macro 'STAT64_HANDLER'
 1122 |   STAT64_HANDLER(lxstat64, buf, ver, path, buf);
      |   ^~~~~~~~~~~~~~
libfaketime.c:1122:28: error: passing argument 1 of 'fake_stat64buf' from incompatible pointer type [-Werror=incompatible-pointer-types]
 1122 |   STAT64_HANDLER(lxstat64, buf, ver, path, buf);
      |                            ^~~
      |                            |
      |                            struct stat64 *
libfaketime.c:1020:36: note: in definition of macro 'STAT_HANDLER_COMMON'
 1020 |       if (!dont_fake) fake_statbuf(buf); \
      |                                    ^~~
libfaketime.c:1122:3: note: in expansion of macro 'STAT64_HANDLER'
 1122 |   STAT64_HANDLER(lxstat64, buf, ver, path, buf);
      |   ^~~~~~~~~~~~~~
libfaketime.c:960:51: note: expected 'struct stat64 *' but argument is of type 'struct stat64 *'
  960 | static inline void fake_stat64buf (struct stat64 *buf) {
      |                                    ~~~~~~~~~~~~~~~^~~
cc1: all warnings being treated as errors
make[1]: Leaving directory '/usr/local/src/libfaketime/src'
make[1]: *** [Makefile:161: libfaketime.o] Error 1
make: *** [Makefile:8: all] Error 2
wolfcw commented 9 months ago

Thanks for the report. I don't have this problem with gcc (Debian 13.2.0-7) 13.2.0 so I'm not sure yet it's really related to gcc13.

Does it work on the same Alpine version when you force the use of gcc12?

I'd rather guess that maybe the definition of struct stat64 has moved somewhere else on the newer Alpine version, so gcc13 thinks it's declared within libfaketime when it is just used by it. All the errors you get seem to be somehow related to this.

On my Debian machine, both stat and stat64 are defined in /usr/include/asm-generic/stat.h. How does this look on Alpine?

Does it compile without errors if you remove -DFAKE_STAT from libfaketime's src/Makefile?

peterthomassen commented 9 months ago

Thank you for the pointers; indeed, it's an Alpine problem. For context, see this discussion and this commit, which seems to trigger the issue.

On my Debian machine, both stat and stat64 are defined in /usr/include/asm-generic/stat.h. How does this look on Alpine?

It's in /usr/include/sys/stat.h, which is modified by the above commit.

Does it compile without errors if you remove -DFAKE_STAT from libfaketime's src/Makefile?

No, but there are significantly less errors then:

# make 
make  -C src all
make[1]: Entering directory '/usr/local/src/libfaketime/src'
cc -o libfaketime.o -c -std=gnu99 -Wall -Wextra -Werror -DFAKE_PTHREAD -DFAKE_UTIME -DFAKE_SLEEP -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'/usr/local'"' -DLIBDIRNAME='"'/lib/faketime'"'  -Wno-nonnull-compare   libfaketime.c
libfaketime.c:191:72: error: 'struct stat64' declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
  191 | static int          (*real_xstat64)         (int, const char *, struct stat64 *);
      |                                                                        ^~~~~~
libfaketime.c:192:64: error: 'struct stat64' declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
  192 | static int          (*real_fxstat64)        (int, int , struct stat64 *);
      |                                                                ^~~~~~
libfaketime.c:193:78: error: 'struct stat64' declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
  193 | static int          (*real_fxstatat64)      (int, int , const char *, struct stat64 *, int);
      |                                                                              ^~~~~~
libfaketime.c:194:72: error: 'struct stat64' declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
  194 | static int          (*real_lxstat64)        (int, const char *, struct stat64 *);
      |                                                                        ^~~~~~
cc1: all warnings being treated as errors
make[1]: *** [Makefile:161: libfaketime.o] Error 1
make[1]: Leaving directory '/usr/local/src/libfaketime/src'
make: *** [Makefile:8: all] Error 2

Anyway, the solution is to not use Alpine 3.19 for building. Thanks!

martinetd commented 8 months ago

I'm not quite sure how that qualifies as "a solution" for people actually using alpine 3.19/recent musl... But anyway, it looks like that while musl didn't keep the _FILE_OFFSET_BITS=64 glibc compat code, it kept _LARGEFILE64_SOURCE -- I've opened #453 that delays the problem by just adding that define for now.