|
@@ -0,0 +1,104 @@
|
|
|
|
+/* Distilled from issue found with tar and symlinks.
|
|
|
|
+ * Make sure that the whole stat struct between runs
|
|
|
|
+ * is agreeable.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#ifndef _GNU_SOURCE
|
|
|
|
+# define _GNU_SOURCE
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#include <stdio.h>
|
|
|
|
+#include <stdlib.h>
|
|
|
|
+#include <string.h>
|
|
|
|
+#include <errno.h>
|
|
|
|
+#include <sys/types.h>
|
|
|
|
+#include <sys/stat.h>
|
|
|
|
+#include <fcntl.h>
|
|
|
|
+#include <unistd.h>
|
|
|
|
+#include <assert.h>
|
|
|
|
+#include <time.h>
|
|
|
|
+
|
|
|
|
+void show_stat(struct stat *st)
|
|
|
|
+{
|
|
|
|
+ printf(
|
|
|
|
+ "------------------\n"
|
|
|
|
+ "st_dev = %li\n"
|
|
|
|
+ "st_ino = %li\n"
|
|
|
|
+ "st_mode = %li\n"
|
|
|
|
+ "st_nlink = %li\n"
|
|
|
|
+ "st_uid = %li\n"
|
|
|
|
+ "st_gid = %li\n"
|
|
|
|
+ "st_rdev = %li\n"
|
|
|
|
+ "st_size = %li\n"
|
|
|
|
+ "st_blksize = %li\n"
|
|
|
|
+ "st_blocks = %li\n"
|
|
|
|
+ "st_atime = %li\n"
|
|
|
|
+ "st_ansec = %li\n"
|
|
|
|
+ "st_mtime = %li\n"
|
|
|
|
+ "st_mnsec = %li\n"
|
|
|
|
+ "st_ctime = %li\n"
|
|
|
|
+ "st_cnsec = %li\n",
|
|
|
|
+ (long int)st->st_dev,
|
|
|
|
+ (long int)st->st_ino,
|
|
|
|
+ (long int)st->st_mode,
|
|
|
|
+ (long int)st->st_nlink,
|
|
|
|
+ (long int)st->st_uid,
|
|
|
|
+ (long int)st->st_gid,
|
|
|
|
+ (long int)st->st_rdev,
|
|
|
|
+ (long int)st->st_size,
|
|
|
|
+ (long int)st->st_blksize,
|
|
|
|
+ (long int)st->st_blocks,
|
|
|
|
+#ifndef __UCLIBC__
|
|
|
|
+ (long int)st->st_atime,
|
|
|
|
+ (long int)st->st_atim.tv_nsec,
|
|
|
|
+ (long int)st->st_mtime,
|
|
|
|
+ (long int)st->st_mtim.tv_nsec,
|
|
|
|
+ (long int)st->st_ctime,
|
|
|
|
+ (long int)st->st_ctim.tv_nsec
|
|
|
|
+#else
|
|
|
|
+ (long int)st->st_atime,
|
|
|
|
+ (long int)st->st_atimensec,
|
|
|
|
+ (long int)st->st_mtime,
|
|
|
|
+ (long int)st->st_mtimensec,
|
|
|
|
+ (long int)st->st_ctime,
|
|
|
|
+ (long int)st->st_ctimensec
|
|
|
|
+#endif
|
|
|
|
+ );
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int main()
|
|
|
|
+{
|
|
|
|
+ int ret;
|
|
|
|
+ int fd;
|
|
|
|
+ struct stat fst, st;
|
|
|
|
+
|
|
|
|
+ unlink(".testfile");
|
|
|
|
+ fd = open(".testfile", O_WRONLY | O_CREAT | O_EXCL, 0);
|
|
|
|
+ if (fd < 0) {
|
|
|
|
+ perror("open(.testfile) failed");
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+ ret = fstat(fd, &fst);
|
|
|
|
+ if (ret != 0) {
|
|
|
|
+ perror("fstat(.testfile) failed");
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+ close(fd);
|
|
|
|
+
|
|
|
|
+ ret = stat(".testfile", &st);
|
|
|
|
+ if (ret != 0) {
|
|
|
|
+ perror("stat(.testfile) failed");
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ret = memcmp(&fst, &st, sizeof(fst));
|
|
|
|
+ if (ret != 0) {
|
|
|
|
+ printf("FAILED: memcmp() = %i\n", ret);
|
|
|
|
+ show_stat(&fst);
|
|
|
|
+ show_stat(&st);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ unlink(".testfile");
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|