1 /* 2 * Copyright (c) 2015 Dmitry V. Levin <ldv (at) altlinux.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #if defined TEST_SYSCALL_NAME \ 29 && defined HAVE_FTRUNCATE && defined HAVE_FUTIMENS 30 31 # ifndef TEST_SYSCALL_INVOKE 32 # error TEST_SYSCALL_INVOKE must be defined 33 # endif 34 # ifndef PRINT_SYSCALL_HEADER 35 # error PRINT_SYSCALL_HEADER must be defined 36 # endif 37 # ifndef PRINT_SYSCALL_FOOTER 38 # error PRINT_SYSCALL_FOOTER must be defined 39 # endif 40 41 # include <errno.h> 42 # include <stdio.h> 43 # include <stddef.h> 44 # include <time.h> 45 # include <unistd.h> 46 47 # if defined MAJOR_IN_SYSMACROS 48 # include <sys/sysmacros.h> 49 # elif defined MAJOR_IN_MKDEV 50 # include <sys/mkdev.h> 51 # else 52 # include <sys/types.h> 53 # endif 54 55 static void 56 print_time(const time_t t) 57 { 58 if (!t) { 59 printf("0"); 60 return; 61 } 62 63 struct tm *p = localtime(&t); 64 65 if (p) 66 printf("%02d/%02d/%02d-%02d:%02d:%02d", 67 p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, 68 p->tm_hour, p->tm_min, p->tm_sec); 69 else 70 printf("%llu", (unsigned long long) t); 71 } 72 73 typedef off_t libc_off_t; 74 75 # ifdef USE_ASM_STAT 76 # define stat libc_stat 77 # define stat64 libc_stat64 78 # endif 79 # include <fcntl.h> 80 # include <sys/stat.h> 81 # ifdef USE_ASM_STAT 82 # undef stat 83 # undef stat64 84 # endif 85 86 # ifdef USE_ASM_STAT 87 # undef st_atime 88 # undef st_mtime 89 # undef st_ctime 90 # undef dev_t 91 # undef gid_t 92 # undef ino_t 93 # undef loff_t 94 # undef mode_t 95 # undef nlink_t 96 # undef off64_t 97 # undef off_t 98 # undef time_t 99 # undef uid_t 100 # define dev_t __kernel_dev_t 101 # define gid_t __kernel_gid_t 102 # define ino_t __kernel_ino_t 103 # define loff_t __kernel_loff_t 104 # define mode_t __kernel_mode_t 105 # define nlink_t __kernel_nlink_t 106 # define off64_t __kernel_off64_t 107 # define off_t __kernel_off_t 108 # define time_t __kernel_time_t 109 # define uid_t __kernel_uid_t 110 # include "asm_stat.h" 111 # else 112 # undef HAVE_STRUCT_STAT_ST_ATIME_NSEC 113 # ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC 114 # define HAVE_STRUCT_STAT_ST_ATIME_NSEC 1 115 # undef st_atime_nsec 116 # define st_atime_nsec st_atim.tv_nsec 117 # endif 118 # undef HAVE_STRUCT_STAT_ST_MTIME_NSEC 119 # ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 120 # define HAVE_STRUCT_STAT_ST_MTIME_NSEC 1 121 # undef st_mtime_nsec 122 # define st_mtime_nsec st_mtim.tv_nsec 123 # endif 124 # undef HAVE_STRUCT_STAT_ST_CTIME_NSEC 125 # ifdef HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC 126 # define HAVE_STRUCT_STAT_ST_CTIME_NSEC 1 127 # undef st_ctime_nsec 128 # define st_ctime_nsec st_ctim.tv_nsec 129 # endif 130 # endif 131 132 # ifndef STRUCT_STAT 133 # define STRUCT_STAT struct stat 134 # endif 135 # ifndef SAMPLE_SIZE 136 # define SAMPLE_SIZE 43147718418 137 # endif 138 139 static void 140 print_ftype(const unsigned int mode) 141 { 142 if (S_ISREG(mode)) 143 printf("S_IFREG"); 144 else if (S_ISDIR(mode)) 145 printf("S_IFDIR"); 146 else if (S_ISCHR(mode)) 147 printf("S_IFCHR"); 148 else if (S_ISBLK(mode)) 149 printf("S_IFBLK"); 150 else 151 printf("%#o", mode & S_IFMT); 152 } 153 154 static void 155 print_perms(const unsigned int mode) 156 { 157 printf("%#o", mode & ~S_IFMT); 158 } 159 160 static void 161 print_stat(const STRUCT_STAT *st) 162 { 163 printf("{st_dev=makedev(%u, %u)", 164 (unsigned int) major(st->st_dev), 165 (unsigned int) minor(st->st_dev)); 166 printf(", st_ino=%llu", (unsigned long long) st->st_ino); 167 printf(", st_mode="); 168 print_ftype(st->st_mode); 169 printf("|"); 170 print_perms(st->st_mode); 171 printf(", st_nlink=%u", (unsigned int) st->st_nlink); 172 printf(", st_uid=%u", (unsigned int) st->st_uid); 173 printf(", st_gid=%u", (unsigned int) st->st_gid); 174 printf(", st_blksize=%u", (unsigned int) st->st_blksize); 175 printf(", st_blocks=%u", (unsigned int) st->st_blocks); 176 177 switch (st->st_mode & S_IFMT) { 178 case S_IFCHR: case S_IFBLK: 179 printf(", st_rdev=makedev(%u, %u)", 180 (unsigned int) major(st->st_rdev), 181 (unsigned int) minor(st->st_rdev)); 182 break; 183 default: 184 printf(", st_size=%llu", (unsigned long long) st->st_size); 185 } 186 187 printf(", st_atime="); 188 print_time(st->st_atime); 189 # ifdef HAVE_STRUCT_STAT_ST_ATIME_NSEC 190 if (st->st_atime_nsec) 191 printf(".%09lu", (unsigned long) st->st_atime_nsec); 192 # endif 193 printf(", st_mtime="); 194 print_time(st->st_mtime); 195 # ifdef HAVE_STRUCT_STAT_ST_MTIME_NSEC 196 if (st->st_mtime_nsec) 197 printf(".%09lu", (unsigned long) st->st_mtime_nsec); 198 # endif 199 printf(", st_ctime="); 200 print_time(st->st_ctime); 201 # ifdef HAVE_STRUCT_STAT_ST_CTIME_NSEC 202 if (st->st_ctime_nsec) 203 printf(".%09lu", (unsigned long) st->st_ctime_nsec); 204 # endif 205 printf("}"); 206 } 207 208 static int 209 create_sample(const char *fname, const libc_off_t size) 210 { 211 static const struct timespec ts[] = { 212 {-10843, 135}, {-10841, 246} 213 }; 214 215 (void) close(0); 216 if (open(fname, O_RDWR | O_CREAT | O_TRUNC, 0640)) { 217 perror(fname); 218 return 77; 219 } 220 if (ftruncate(0, size)) { 221 perror("ftruncate"); 222 return 77; 223 } 224 if (futimens(0, ts)) { 225 perror("futimens"); 226 return 77; 227 } 228 return 0; 229 } 230 231 # define stringify_(arg) #arg 232 # define stringify(arg) stringify_(arg) 233 # define TEST_SYSCALL_STR stringify(TEST_SYSCALL_NAME) 234 # define STRUCT_STAT_STR stringify(STRUCT_STAT) 235 236 int 237 main(void) 238 { 239 static const char sample[] = TEST_SYSCALL_STR ".sample"; 240 STRUCT_STAT st[2]; 241 242 int rc = create_sample(sample, SAMPLE_SIZE); 243 if (rc) { 244 (void) unlink(sample); 245 return rc; 246 } 247 248 if (TEST_SYSCALL_INVOKE(sample, st)) { 249 perror(TEST_SYSCALL_STR); 250 (void) unlink(sample); 251 return 77; 252 } 253 (void) unlink(sample); 254 if ((unsigned long long) SAMPLE_SIZE != 255 (unsigned long long) st[0].st_size) { 256 fprintf(stderr, "Size mismatch: " 257 "requested size(%llu) != st_size(%llu)\n", 258 (unsigned long long) SAMPLE_SIZE, 259 (unsigned long long) st[0].st_size); 260 fprintf(stderr, "The most likely reason for this is incorrect" 261 " definition of %s.\n" 262 "Here is some diagnostics that might help:\n", 263 STRUCT_STAT_STR); 264 fprintf(stderr, "offsetof(%s, st_dev) = %zu" 265 ", sizeof(st_dev) = %zu\n", 266 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_dev), 267 sizeof(st[0].st_dev)); 268 fprintf(stderr, "offsetof(%s, st_ino) = %zu" 269 ", sizeof(st_ino) = %zu\n", 270 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_ino), 271 sizeof(st[0].st_ino)); 272 fprintf(stderr, "offsetof(%s, st_mode) = %zu" 273 ", sizeof(st_mode) = %zu\n", 274 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_mode), 275 sizeof(st[0].st_mode)); 276 fprintf(stderr, "offsetof(%s, st_nlink) = %zu" 277 ", sizeof(st_nlink) = %zu\n", 278 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_nlink), 279 sizeof(st[0].st_nlink)); 280 fprintf(stderr, "offsetof(%s, st_uid) = %zu" 281 ", sizeof(st_uid) = %zu\n", 282 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_uid), 283 sizeof(st[0].st_uid)); 284 fprintf(stderr, "offsetof(%s, st_gid) = %zu" 285 ", sizeof(st_gid) = %zu\n", 286 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_gid), 287 sizeof(st[0].st_gid)); 288 fprintf(stderr, "offsetof(%s, st_rdev) = %zu" 289 ", sizeof(st_rdev) = %zu\n", 290 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_rdev), 291 sizeof(st[0].st_rdev)); 292 fprintf(stderr, "offsetof(%s, st_size) = %zu" 293 ", sizeof(st_size) = %zu\n", 294 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_size), 295 sizeof(st[0].st_size)); 296 fprintf(stderr, "offsetof(%s, st_blksize) = %zu" 297 ", sizeof(st_blksize) = %zu\n", 298 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_blksize), 299 sizeof(st[0].st_blksize)); 300 fprintf(stderr, "offsetof(%s, st_blocks) = %zu" 301 ", sizeof(st_blocks) = %zu\n", 302 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_blocks), 303 sizeof(st[0].st_blocks)); 304 return 77; 305 } 306 307 PRINT_SYSCALL_HEADER(sample); 308 print_stat(st); 309 PRINT_SYSCALL_FOOTER; 310 311 puts("+++ exited with 0 +++"); 312 return 0; 313 } 314 315 #else 316 317 int 318 main(void) 319 { 320 return 77; 321 } 322 323 #endif 324