Home | History | Annotate | Download | only in tests
      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