source: rtems/testsuites/fstests/fstime/test.c @ 736983f1

4.115
Last change on this file since 736983f1 was 736983f1, checked in by Sebastian Huber <sebastian.huber@…>, on 09/13/13 at 13:26:48

fstests/fstime: Fix according to POSIX

ftruncate() and open() with O_TRUNC shall upon successful completion
mark for update the st_ctime and st_mtime fields of the file.

truncate() shall upon successful completion, if the file size is
changed, mark for update the st_ctime and st_mtime fields of the file.

The POSIX standard "The Open Group Base Specifications Issue 7", IEEE
Std 1003.1, 2013 Edition says nothing about the behaviour of truncate()
if the file size remains unchanged.

Future directions of the standard may mandate the behaviour specified in
ftruncate():

http://austingroupbugs.net/view.php?id=489

  • Property mode set to 100644
File size: 8.3 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-2011.
3 *  On-Line Applications Research Corporation (OAR).
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.rtems.com/license/LICENSE.
8 */
9
10#ifdef HAVE_CONFIG_H
11#include "config.h"
12#endif
13
14#include <sys/stat.h>
15#include <limits.h>
16#include <fcntl.h>
17#include <errno.h>
18#include <stdio.h>
19#include <stdint.h>
20#include <stdlib.h>
21#include <string.h>
22#include <unistd.h>
23#include <utime.h>
24
25#ifdef __rtems__
26#include "fstest.h"
27#include "pmacros.h"
28#else
29#include <assert.h>
30#define rtems_test_assert(x) assert(x)
31#define TIME_PRECISION  (2)
32#define TIME_EQUAL(x,y) (abs((x)-(y))<TIME_PRECISION)
33#endif
34
35static int do_create(const char *path, int oflag, mode_t mode)
36{
37  int fd = open (path, O_CREAT | oflag, mode);
38  rtems_test_assert (fd >= 0);
39
40  return fd;
41}
42
43static int do_open(const char *path, int oflag)
44{
45  int fd = open (path, O_CREAT | oflag);
46  rtems_test_assert (fd >= 0);
47
48  return fd;
49}
50
51static void time_test01 (void)
52{
53  struct stat st;
54  struct utimbuf timbuf;
55  int status;
56  int fd;
57  time_t creation_time;
58  time_t truncation_time;
59  time_t dir01_creation_time;
60  char databuf[] = "TEST";
61  char readbuf[sizeof(databuf)];
62  const char *file01 = "test01";
63  const char *file02 = "test02";
64  const char *file03 = "test03";
65  const char *dir01 = "dir01";
66
67  int n;
68  int len = strlen (databuf);
69
70  const char *wd = __func__;
71  mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
72  /*
73   * Create a new directory and change to this
74   */
75  status = mkdir (wd, mode);
76  rtems_test_assert (status == 0);
77  status = chdir (wd);
78  rtems_test_assert (status == 0);
79
80  /*
81   * Sleep a few seconds
82   */
83  puts ("Sleep a few seconds");
84  sleep (3 * TIME_PRECISION);
85
86  /*
87   * Create the test files
88   */
89  fd = do_create (file01, O_WRONLY, mode);
90  n = write (fd, databuf, len);
91  rtems_test_assert (n == len);
92  status = close (fd);
93  rtems_test_assert (status == 0);
94
95  fd = do_create (file02, O_WRONLY, mode);
96  n = write (fd, databuf, len);
97  rtems_test_assert (n == len);
98  status = close (fd);
99  rtems_test_assert (status == 0);
100
101  /* A simple C version of touch */
102  fd = do_create (file03, O_WRONLY, mode);
103  status = close (fd);
104  rtems_test_assert (status == 0);
105
106  /*
107   * If O_CREAT is set and the file did not previously exist, upon
108   * successful completion, open() shall mark for update the st_atime,
109   * st_ctime, and st_mtime fields of the file and the st_ctime and
110   * st_mtime fields of the parent directory.
111   */
112  status = stat (file01, &st);
113  rtems_test_assert (status == 0);
114
115  /*
116   * Make sure they are the same
117   */
118  rtems_test_assert (st.st_ctime == st.st_mtime);
119
120  creation_time = st.st_ctime;
121
122  status = stat (".", &st);
123  rtems_test_assert (status == 0);
124
125  /*
126   * Make sure they are the same
127   */
128  rtems_test_assert (st.st_ctime == st.st_mtime);
129  rtems_test_assert (TIME_EQUAL (creation_time, st.st_mtime));
130  rtems_test_assert (TIME_EQUAL (creation_time, st.st_ctime));
131
132  status = stat (file02, &st);
133  rtems_test_assert (status == 0);
134
135  /*
136   * Make sure they are the same
137   */
138  rtems_test_assert (st.st_ctime == st.st_mtime);
139  rtems_test_assert (TIME_EQUAL (creation_time, st.st_mtime));
140  rtems_test_assert (TIME_EQUAL (creation_time, st.st_ctime));
141
142  status = stat (file03, &st);
143  rtems_test_assert (status == 0);
144
145  /*
146   * Make sure they are the same
147   */
148  rtems_test_assert (st.st_ctime == st.st_mtime);
149  rtems_test_assert (TIME_EQUAL (creation_time, st.st_mtime));
150  rtems_test_assert (TIME_EQUAL (creation_time, st.st_ctime));
151
152  /*
153   * Sleep a few seconds
154   */
155  puts ("Sleep a few seconds");
156  sleep (3 * TIME_PRECISION);
157
158  /*
159   * Create an empty directory
160   */
161  status = mkdir (dir01, mode);
162  rtems_test_assert (status == 0);
163
164  /*
165   * truncate file01 to len, so it does not changes the file size
166   */
167  status = truncate (file01, len);
168  rtems_test_assert (status == 0);
169
170  /*
171   *truncate file02 to len+1, it changes the file size
172   */
173  status = truncate (file02, len + 1);
174  rtems_test_assert (status == 0);
175
176  /*
177   * Truncate an empty file which does not change the length.
178   */
179  fd = do_open (file03, O_TRUNC | O_WRONLY);
180  status = close (fd);
181  rtems_test_assert (status == 0);
182
183  /*
184   * ftruncate() and open() with O_TRUNC shall upon successful completion mark
185   * for update the st_ctime and st_mtime fields of the file.
186   *
187   * truncate() shall upon successful completion, if the file size is changed,
188   * mark for update the st_ctime and st_mtime fields of the file.
189   *
190   * The POSIX standard "The Open Group Base Specifications Issue 7", IEEE Std
191   * 1003.1, 2013 Edition says nothing about the behaviour of truncate() if the
192   * file size remains unchanged.
193   *
194   * Future directions of the standard may mandate the behaviour specified in
195   * ftruncate():
196   *
197   * http://austingroupbugs.net/view.php?id=489
198   */
199
200  /*
201   * file01 is currently unspecified
202   */
203  status = stat (file01, &st);
204  rtems_test_assert (status == 0);
205
206  rtems_test_assert (st.st_ctime == st.st_mtime);
207  if (TIME_EQUAL (creation_time, st.st_ctime)) {
208    puts ("WARNING: truncate() behaviour may violate future POSIX standard");
209  }
210
211  truncation_time = st.st_ctime;
212
213  /*
214   * file02 shall update
215   */
216  status = stat (file02, &st);
217  rtems_test_assert (status == 0);
218
219  rtems_test_assert (st.st_ctime == st.st_mtime);
220  rtems_test_assert (!TIME_EQUAL (creation_time, st.st_ctime));
221
222  /*
223   * file03 shall update
224   */
225  status = stat (file03, &st);
226  rtems_test_assert (status == 0);
227
228  rtems_test_assert (st.st_ctime == st.st_mtime);
229  rtems_test_assert (!TIME_EQUAL (creation_time, st.st_ctime));
230
231  /*
232   *  Upon successful completion, mkdir() shall mark for update the
233   *  st_atime, st_ctime, and st_mtime fields of the directory.
234   *  Also, the st_ctime and st_mtime fields of the directory that
235   *  contains the new entry shall be marked for update.
236   */
237  status = stat (dir01, &st);
238  rtems_test_assert (status == 0);
239
240  rtems_test_assert (st.st_ctime == st.st_mtime);
241
242  dir01_creation_time = st.st_ctime;
243
244  status = stat (".", &st);
245  rtems_test_assert (status == 0);
246
247  rtems_test_assert (st.st_ctime == st.st_mtime);
248  rtems_test_assert (TIME_EQUAL (dir01_creation_time, st.st_mtime));
249
250  /*
251   * Sleep a few seconds
252   */
253  puts ("Sleep a few seconds");
254  sleep (3 * TIME_PRECISION);
255
256  /*
257   * Upon successful completion, where nbyte is greater than 0,
258   * write() shall mark for update the st_ctime and st_mtime fields of the file
259   */
260
261  /*
262   * read file01, and this should not uptate st_mtime and st_ctime
263   */
264  fd = do_open (file01, O_RDONLY);
265  n = read (fd, readbuf, len);
266  rtems_test_assert (n == len);
267  status = fstat (fd, &st);
268  rtems_test_assert (status == 0);
269
270  rtems_test_assert (st.st_ctime == st.st_mtime);
271  rtems_test_assert (TIME_EQUAL (truncation_time, st.st_mtime));
272
273  status = close (fd);
274  rtems_test_assert (status == 0);
275  /*
276   * write file01, and this should uptate st_mtime st_ctime
277   */
278  fd = do_open (file01, O_WRONLY);
279  n = write (fd, databuf, len);
280  rtems_test_assert (n == len);
281  status = fstat (fd, &st);
282
283  rtems_test_assert (st.st_ctime == st.st_mtime);
284  rtems_test_assert (!TIME_EQUAL (truncation_time, st.st_mtime));
285  status = close (fd);
286  rtems_test_assert (status == 0);
287
288  /*
289   * The utime() function shall set the access and modification times
290   *  of the file named by the path argument.
291   */
292  timbuf.actime = creation_time;
293  timbuf.modtime = creation_time;
294
295  status = utime (file01, &timbuf);
296  rtems_test_assert (status == 0);
297
298  status = stat (file01, &st);
299  rtems_test_assert (status == 0);
300
301  rtems_test_assert (st.st_atime == st.st_mtime);
302  rtems_test_assert (TIME_EQUAL (creation_time, st.st_atime));
303  rtems_test_assert (!TIME_EQUAL (creation_time, st.st_ctime));
304
305  status = utime (dir01, &timbuf);
306  rtems_test_assert (status == 0);
307
308  status = stat (dir01, &st);
309  rtems_test_assert (status == 0);
310
311  rtems_test_assert (st.st_atime == st.st_mtime);
312  rtems_test_assert (TIME_EQUAL (creation_time, st.st_atime));
313  rtems_test_assert (!TIME_EQUAL (creation_time, st.st_ctime));
314}
315
316/*
317 * These tests only get time_t value, and test
318 * if they are changed. Thest tests don't check atime
319 */
320#ifdef __rtems__
321void test (void)
322#else
323int main(int argc, char **argv)
324#endif
325{
326
327  puts( "\n\n*** TIME TEST ***" );
328  time_test01();
329  puts( "*** END OF TIME TEST ***" );
330
331#ifndef __rtems__
332  return 0;
333#endif
334}
Note: See TracBrowser for help on using the repository browser.