Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:31

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  *  COPYRIGHT (c) 1989-2011.
0005  *  On-Line Applications Research Corporation (OAR).
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions and the following disclaimer.
0012  * 2. Redistributions in binary form must reproduce the above copyright
0013  *    notice, this list of conditions and the following disclaimer in the
0014  *    documentation and/or other materials provided with the distribution.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0017  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0019  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0020  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0021  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0022  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0024  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0025  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0026  * POSSIBILITY OF SUCH DAMAGE.
0027  */
0028 
0029 #ifdef HAVE_CONFIG_H
0030 #include "config.h"
0031 #endif
0032 
0033 #include <sys/stat.h>
0034 #include <limits.h>
0035 #include <fcntl.h>
0036 #include <errno.h>
0037 #include <stdio.h>
0038 #include <stdint.h>
0039 #include <stdlib.h>
0040 #include <string.h>
0041 #include <unistd.h>
0042 #include <utime.h>
0043 
0044 #ifdef __rtems__
0045 #include "fstest.h"
0046 #include "fs_config.h"
0047 #include <tmacros.h>
0048 
0049 const char rtems_test_name[] = "FSTIME " FILESYSTEM;
0050 const RTEMS_TEST_STATE rtems_test_state = TEST_STATE;
0051 #else
0052 #include <assert.h>
0053 #define rtems_test_assert(x) assert(x)
0054 #define TIME_PRECISION  (2)
0055 #define TIME_EQUAL(x,y) (abs((x)-(y))<TIME_PRECISION)
0056 #endif
0057 
0058 static int do_create(const char *path, int oflag, mode_t mode)
0059 {
0060   int fd = open (path, O_CREAT | oflag, mode);
0061   rtems_test_assert (fd >= 0);
0062 
0063   return fd;
0064 }
0065 
0066 static int do_open(const char *path, int oflag)
0067 {
0068   int fd = open (path, O_CREAT | oflag);
0069   rtems_test_assert (fd >= 0);
0070 
0071   return fd;
0072 }
0073 
0074 static void time_test01 (void)
0075 {
0076   struct stat st;
0077   struct utimbuf timbuf;
0078   int status;
0079   int fd;
0080   time_t creation_time;
0081   time_t truncation_time;
0082   time_t dir01_creation_time;
0083   char databuf[] = "TEST";
0084   char readbuf[sizeof(databuf)];
0085   const char *file01 = "test01";
0086   const char *file02 = "test02";
0087   const char *file03 = "test03";
0088   const char *dir01 = "dir01";
0089 
0090   int n;
0091   int len = strlen (databuf);
0092 
0093   const char *wd = __func__;
0094   mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
0095   /*
0096    * Create a new directory and change to this
0097    */
0098   status = mkdir (wd, mode);
0099   rtems_test_assert (status == 0);
0100   status = chdir (wd);
0101   rtems_test_assert (status == 0);
0102 
0103   /*
0104    * Sleep a few seconds
0105    */
0106   puts ("Sleep a few seconds");
0107   sleep (3 * TIME_PRECISION);
0108 
0109   /*
0110    * Create the test files
0111    */
0112   fd = do_create (file01, O_WRONLY, mode);
0113   n = write (fd, databuf, len);
0114   rtems_test_assert (n == len);
0115   status = close (fd);
0116   rtems_test_assert (status == 0);
0117 
0118   fd = do_create (file02, O_WRONLY, mode);
0119   n = write (fd, databuf, len);
0120   rtems_test_assert (n == len);
0121   status = close (fd);
0122   rtems_test_assert (status == 0);
0123 
0124   /* A simple C version of touch */
0125   fd = do_create (file03, O_WRONLY, mode);
0126   status = close (fd);
0127   rtems_test_assert (status == 0);
0128 
0129   /*
0130    * If O_CREAT is set and the file did not previously exist, upon
0131    * successful completion, open() shall mark for update the st_atime,
0132    * st_ctime, and st_mtime fields of the file and the st_ctime and
0133    * st_mtime fields of the parent directory.
0134    */
0135   status = stat (file01, &st);
0136   rtems_test_assert (status == 0);
0137 
0138   /*
0139    * Make sure they are the same
0140    */
0141   rtems_test_assert (st.st_ctime == st.st_mtime);
0142 
0143   creation_time = st.st_ctime;
0144 
0145   status = stat (".", &st);
0146   rtems_test_assert (status == 0);
0147 
0148   /*
0149    * Make sure they are the same
0150    */
0151   rtems_test_assert (st.st_ctime == st.st_mtime);
0152   rtems_test_assert (TIME_EQUAL (creation_time, st.st_mtime));
0153   rtems_test_assert (TIME_EQUAL (creation_time, st.st_ctime));
0154 
0155   status = stat (file02, &st);
0156   rtems_test_assert (status == 0);
0157 
0158   /*
0159    * Make sure they are the same
0160    */
0161   rtems_test_assert (st.st_ctime == st.st_mtime);
0162   rtems_test_assert (TIME_EQUAL (creation_time, st.st_mtime));
0163   rtems_test_assert (TIME_EQUAL (creation_time, st.st_ctime));
0164 
0165   status = stat (file03, &st);
0166   rtems_test_assert (status == 0);
0167 
0168   /*
0169    * Make sure they are the same
0170    */
0171   rtems_test_assert (st.st_ctime == st.st_mtime);
0172   rtems_test_assert (TIME_EQUAL (creation_time, st.st_mtime));
0173   rtems_test_assert (TIME_EQUAL (creation_time, st.st_ctime));
0174 
0175   /*
0176    * Sleep a few seconds
0177    */
0178   puts ("Sleep a few seconds");
0179   sleep (3 * TIME_PRECISION);
0180 
0181   /*
0182    * Create an empty directory
0183    */
0184   status = mkdir (dir01, mode);
0185   rtems_test_assert (status == 0);
0186 
0187   /*
0188    * truncate file01 to len, so it does not changes the file size
0189    */
0190   status = truncate (file01, len);
0191   rtems_test_assert (status == 0);
0192 
0193   /*
0194    *truncate file02 to len+1, it changes the file size
0195    */
0196   status = truncate (file02, len + 1);
0197   rtems_test_assert (status == 0);
0198 
0199   /*
0200    * Truncate an empty file which does not change the length.
0201    */
0202   fd = do_open (file03, O_TRUNC | O_WRONLY);
0203   status = close (fd);
0204   rtems_test_assert (status == 0);
0205 
0206   /*
0207    * ftruncate() and open() with O_TRUNC shall upon successful completion mark
0208    * for update the st_ctime and st_mtime fields of the file.
0209    *
0210    * truncate() shall upon successful completion, if the file size is changed,
0211    * mark for update the st_ctime and st_mtime fields of the file.
0212    *
0213    * The POSIX standard "The Open Group Base Specifications Issue 7", IEEE Std
0214    * 1003.1, 2013 Edition says nothing about the behaviour of truncate() if the
0215    * file size remains unchanged.
0216    *
0217    * Future directions of the standard may mandate the behaviour specified in
0218    * ftruncate():
0219    *
0220    * http://austingroupbugs.net/view.php?id=489
0221    */
0222 
0223   /*
0224    * file01 is currently unspecified
0225    */
0226   status = stat (file01, &st);
0227   rtems_test_assert (status == 0);
0228 
0229   rtems_test_assert (st.st_ctime == st.st_mtime);
0230   if (TIME_EQUAL (creation_time, st.st_ctime)) {
0231     puts ("WARNING: truncate() behaviour may violate future POSIX standard");
0232   }
0233 
0234   truncation_time = st.st_ctime;
0235 
0236   /*
0237    * file02 shall update
0238    */
0239   status = stat (file02, &st);
0240   rtems_test_assert (status == 0);
0241 
0242   rtems_test_assert (st.st_ctime == st.st_mtime);
0243   rtems_test_assert (!TIME_EQUAL (creation_time, st.st_ctime));
0244 
0245   /*
0246    * file03 shall update
0247    */
0248   status = stat (file03, &st);
0249   rtems_test_assert (status == 0);
0250 
0251   rtems_test_assert (st.st_ctime == st.st_mtime);
0252   rtems_test_assert (!TIME_EQUAL (creation_time, st.st_ctime));
0253 
0254   /*
0255    *  Upon successful completion, mkdir() shall mark for update the
0256    *  st_atime, st_ctime, and st_mtime fields of the directory.
0257    *  Also, the st_ctime and st_mtime fields of the directory that
0258    *  contains the new entry shall be marked for update.
0259    */
0260   status = stat (dir01, &st);
0261   rtems_test_assert (status == 0);
0262 
0263   rtems_test_assert (st.st_ctime == st.st_mtime);
0264 
0265   dir01_creation_time = st.st_ctime;
0266 
0267   status = stat (".", &st);
0268   rtems_test_assert (status == 0);
0269 
0270   rtems_test_assert (st.st_ctime == st.st_mtime);
0271   rtems_test_assert (TIME_EQUAL (dir01_creation_time, st.st_mtime));
0272 
0273   /*
0274    * Sleep a few seconds
0275    */
0276   puts ("Sleep a few seconds");
0277   sleep (3 * TIME_PRECISION);
0278 
0279   /*
0280    * Upon successful completion, where nbyte is greater than 0,
0281    * write() shall mark for update the st_ctime and st_mtime fields of the file
0282    */
0283 
0284   /*
0285    * read file01, and this should not uptate st_mtime and st_ctime
0286    */
0287   fd = do_open (file01, O_RDONLY);
0288   n = read (fd, readbuf, len);
0289   rtems_test_assert (n == len);
0290   status = fstat (fd, &st);
0291   rtems_test_assert (status == 0);
0292 
0293   rtems_test_assert (st.st_ctime == st.st_mtime);
0294   rtems_test_assert (TIME_EQUAL (truncation_time, st.st_mtime));
0295 
0296   status = close (fd);
0297   rtems_test_assert (status == 0);
0298   /*
0299    * write file01, and this should uptate st_mtime st_ctime
0300    */
0301   fd = do_open (file01, O_WRONLY);
0302   n = write (fd, databuf, len);
0303   rtems_test_assert (n == len);
0304   status = fstat (fd, &st);
0305 
0306   rtems_test_assert (st.st_ctime == st.st_mtime);
0307   rtems_test_assert (!TIME_EQUAL (truncation_time, st.st_mtime));
0308   status = close (fd);
0309   rtems_test_assert (status == 0);
0310 
0311   /*
0312    * The utime() function shall set the access and modification times
0313    *  of the file named by the path argument.
0314    */
0315   timbuf.actime = creation_time;
0316   timbuf.modtime = creation_time;
0317 
0318   status = utime (file01, &timbuf);
0319   rtems_test_assert (status == 0);
0320 
0321   status = stat (file01, &st);
0322   rtems_test_assert (status == 0);
0323 
0324   rtems_test_assert (st.st_atime == st.st_mtime);
0325   rtems_test_assert (TIME_EQUAL (creation_time, st.st_atime));
0326   rtems_test_assert (!TIME_EQUAL (creation_time, st.st_ctime));
0327 
0328   status = utime (dir01, &timbuf);
0329   rtems_test_assert (status == 0);
0330 
0331   status = stat (dir01, &st);
0332   rtems_test_assert (status == 0);
0333 
0334   rtems_test_assert (st.st_atime == st.st_mtime);
0335   rtems_test_assert (TIME_EQUAL (creation_time, st.st_atime));
0336   rtems_test_assert (!TIME_EQUAL (creation_time, st.st_ctime));
0337 }
0338 
0339 /*
0340  * These tests only get time_t value, and test
0341  * if they are changed. Thest tests don't check atime
0342  */
0343 #ifdef __rtems__
0344 void test (void)
0345 #else
0346 int main(int argc, char **argv)
0347 #endif
0348 {
0349 
0350   time_test01();
0351 
0352 #ifndef __rtems__
0353   return 0;
0354 #endif
0355 }