forked from Imagelibrary/rtems
336 lines
8.3 KiB
C
336 lines
8.3 KiB
C
/*
|
|
* COPYRIGHT (c) 1989-2011.
|
|
* On-Line Applications Research Corporation (OAR).
|
|
*
|
|
* The license and distribution terms for this file may be
|
|
* found in the file LICENSE in this distribution or at
|
|
* http://www.rtems.org/license/LICENSE.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <sys/stat.h>
|
|
#include <limits.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <utime.h>
|
|
|
|
#ifdef __rtems__
|
|
#include "fstest.h"
|
|
#include "fs_config.h"
|
|
#include "pmacros.h"
|
|
|
|
const char rtems_test_name[] = "FSTIME " FILESYSTEM;
|
|
#else
|
|
#include <assert.h>
|
|
#define rtems_test_assert(x) assert(x)
|
|
#define TIME_PRECISION (2)
|
|
#define TIME_EQUAL(x,y) (abs((x)-(y))<TIME_PRECISION)
|
|
#endif
|
|
|
|
static int do_create(const char *path, int oflag, mode_t mode)
|
|
{
|
|
int fd = open (path, O_CREAT | oflag, mode);
|
|
rtems_test_assert (fd >= 0);
|
|
|
|
return fd;
|
|
}
|
|
|
|
static int do_open(const char *path, int oflag)
|
|
{
|
|
int fd = open (path, O_CREAT | oflag);
|
|
rtems_test_assert (fd >= 0);
|
|
|
|
return fd;
|
|
}
|
|
|
|
static void time_test01 (void)
|
|
{
|
|
struct stat st;
|
|
struct utimbuf timbuf;
|
|
int status;
|
|
int fd;
|
|
time_t creation_time;
|
|
time_t truncation_time;
|
|
time_t dir01_creation_time;
|
|
char databuf[] = "TEST";
|
|
char readbuf[sizeof(databuf)];
|
|
const char *file01 = "test01";
|
|
const char *file02 = "test02";
|
|
const char *file03 = "test03";
|
|
const char *dir01 = "dir01";
|
|
|
|
int n;
|
|
int len = strlen (databuf);
|
|
|
|
const char *wd = __func__;
|
|
mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
|
|
/*
|
|
* Create a new directory and change to this
|
|
*/
|
|
status = mkdir (wd, mode);
|
|
rtems_test_assert (status == 0);
|
|
status = chdir (wd);
|
|
rtems_test_assert (status == 0);
|
|
|
|
/*
|
|
* Sleep a few seconds
|
|
*/
|
|
puts ("Sleep a few seconds");
|
|
sleep (3 * TIME_PRECISION);
|
|
|
|
/*
|
|
* Create the test files
|
|
*/
|
|
fd = do_create (file01, O_WRONLY, mode);
|
|
n = write (fd, databuf, len);
|
|
rtems_test_assert (n == len);
|
|
status = close (fd);
|
|
rtems_test_assert (status == 0);
|
|
|
|
fd = do_create (file02, O_WRONLY, mode);
|
|
n = write (fd, databuf, len);
|
|
rtems_test_assert (n == len);
|
|
status = close (fd);
|
|
rtems_test_assert (status == 0);
|
|
|
|
/* A simple C version of touch */
|
|
fd = do_create (file03, O_WRONLY, mode);
|
|
status = close (fd);
|
|
rtems_test_assert (status == 0);
|
|
|
|
/*
|
|
* If O_CREAT is set and the file did not previously exist, upon
|
|
* successful completion, open() shall mark for update the st_atime,
|
|
* st_ctime, and st_mtime fields of the file and the st_ctime and
|
|
* st_mtime fields of the parent directory.
|
|
*/
|
|
status = stat (file01, &st);
|
|
rtems_test_assert (status == 0);
|
|
|
|
/*
|
|
* Make sure they are the same
|
|
*/
|
|
rtems_test_assert (st.st_ctime == st.st_mtime);
|
|
|
|
creation_time = st.st_ctime;
|
|
|
|
status = stat (".", &st);
|
|
rtems_test_assert (status == 0);
|
|
|
|
/*
|
|
* Make sure they are the same
|
|
*/
|
|
rtems_test_assert (st.st_ctime == st.st_mtime);
|
|
rtems_test_assert (TIME_EQUAL (creation_time, st.st_mtime));
|
|
rtems_test_assert (TIME_EQUAL (creation_time, st.st_ctime));
|
|
|
|
status = stat (file02, &st);
|
|
rtems_test_assert (status == 0);
|
|
|
|
/*
|
|
* Make sure they are the same
|
|
*/
|
|
rtems_test_assert (st.st_ctime == st.st_mtime);
|
|
rtems_test_assert (TIME_EQUAL (creation_time, st.st_mtime));
|
|
rtems_test_assert (TIME_EQUAL (creation_time, st.st_ctime));
|
|
|
|
status = stat (file03, &st);
|
|
rtems_test_assert (status == 0);
|
|
|
|
/*
|
|
* Make sure they are the same
|
|
*/
|
|
rtems_test_assert (st.st_ctime == st.st_mtime);
|
|
rtems_test_assert (TIME_EQUAL (creation_time, st.st_mtime));
|
|
rtems_test_assert (TIME_EQUAL (creation_time, st.st_ctime));
|
|
|
|
/*
|
|
* Sleep a few seconds
|
|
*/
|
|
puts ("Sleep a few seconds");
|
|
sleep (3 * TIME_PRECISION);
|
|
|
|
/*
|
|
* Create an empty directory
|
|
*/
|
|
status = mkdir (dir01, mode);
|
|
rtems_test_assert (status == 0);
|
|
|
|
/*
|
|
* truncate file01 to len, so it does not changes the file size
|
|
*/
|
|
status = truncate (file01, len);
|
|
rtems_test_assert (status == 0);
|
|
|
|
/*
|
|
*truncate file02 to len+1, it changes the file size
|
|
*/
|
|
status = truncate (file02, len + 1);
|
|
rtems_test_assert (status == 0);
|
|
|
|
/*
|
|
* Truncate an empty file which does not change the length.
|
|
*/
|
|
fd = do_open (file03, O_TRUNC | O_WRONLY);
|
|
status = close (fd);
|
|
rtems_test_assert (status == 0);
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
|
|
/*
|
|
* file01 is currently unspecified
|
|
*/
|
|
status = stat (file01, &st);
|
|
rtems_test_assert (status == 0);
|
|
|
|
rtems_test_assert (st.st_ctime == st.st_mtime);
|
|
if (TIME_EQUAL (creation_time, st.st_ctime)) {
|
|
puts ("WARNING: truncate() behaviour may violate future POSIX standard");
|
|
}
|
|
|
|
truncation_time = st.st_ctime;
|
|
|
|
/*
|
|
* file02 shall update
|
|
*/
|
|
status = stat (file02, &st);
|
|
rtems_test_assert (status == 0);
|
|
|
|
rtems_test_assert (st.st_ctime == st.st_mtime);
|
|
rtems_test_assert (!TIME_EQUAL (creation_time, st.st_ctime));
|
|
|
|
/*
|
|
* file03 shall update
|
|
*/
|
|
status = stat (file03, &st);
|
|
rtems_test_assert (status == 0);
|
|
|
|
rtems_test_assert (st.st_ctime == st.st_mtime);
|
|
rtems_test_assert (!TIME_EQUAL (creation_time, st.st_ctime));
|
|
|
|
/*
|
|
* Upon successful completion, mkdir() shall mark for update the
|
|
* st_atime, st_ctime, and st_mtime fields of the directory.
|
|
* Also, the st_ctime and st_mtime fields of the directory that
|
|
* contains the new entry shall be marked for update.
|
|
*/
|
|
status = stat (dir01, &st);
|
|
rtems_test_assert (status == 0);
|
|
|
|
rtems_test_assert (st.st_ctime == st.st_mtime);
|
|
|
|
dir01_creation_time = st.st_ctime;
|
|
|
|
status = stat (".", &st);
|
|
rtems_test_assert (status == 0);
|
|
|
|
rtems_test_assert (st.st_ctime == st.st_mtime);
|
|
rtems_test_assert (TIME_EQUAL (dir01_creation_time, st.st_mtime));
|
|
|
|
/*
|
|
* Sleep a few seconds
|
|
*/
|
|
puts ("Sleep a few seconds");
|
|
sleep (3 * TIME_PRECISION);
|
|
|
|
/*
|
|
* Upon successful completion, where nbyte is greater than 0,
|
|
* write() shall mark for update the st_ctime and st_mtime fields of the file
|
|
*/
|
|
|
|
/*
|
|
* read file01, and this should not uptate st_mtime and st_ctime
|
|
*/
|
|
fd = do_open (file01, O_RDONLY);
|
|
n = read (fd, readbuf, len);
|
|
rtems_test_assert (n == len);
|
|
status = fstat (fd, &st);
|
|
rtems_test_assert (status == 0);
|
|
|
|
rtems_test_assert (st.st_ctime == st.st_mtime);
|
|
rtems_test_assert (TIME_EQUAL (truncation_time, st.st_mtime));
|
|
|
|
status = close (fd);
|
|
rtems_test_assert (status == 0);
|
|
/*
|
|
* write file01, and this should uptate st_mtime st_ctime
|
|
*/
|
|
fd = do_open (file01, O_WRONLY);
|
|
n = write (fd, databuf, len);
|
|
rtems_test_assert (n == len);
|
|
status = fstat (fd, &st);
|
|
|
|
rtems_test_assert (st.st_ctime == st.st_mtime);
|
|
rtems_test_assert (!TIME_EQUAL (truncation_time, st.st_mtime));
|
|
status = close (fd);
|
|
rtems_test_assert (status == 0);
|
|
|
|
/*
|
|
* The utime() function shall set the access and modification times
|
|
* of the file named by the path argument.
|
|
*/
|
|
timbuf.actime = creation_time;
|
|
timbuf.modtime = creation_time;
|
|
|
|
status = utime (file01, &timbuf);
|
|
rtems_test_assert (status == 0);
|
|
|
|
status = stat (file01, &st);
|
|
rtems_test_assert (status == 0);
|
|
|
|
rtems_test_assert (st.st_atime == st.st_mtime);
|
|
rtems_test_assert (TIME_EQUAL (creation_time, st.st_atime));
|
|
rtems_test_assert (!TIME_EQUAL (creation_time, st.st_ctime));
|
|
|
|
status = utime (dir01, &timbuf);
|
|
rtems_test_assert (status == 0);
|
|
|
|
status = stat (dir01, &st);
|
|
rtems_test_assert (status == 0);
|
|
|
|
rtems_test_assert (st.st_atime == st.st_mtime);
|
|
rtems_test_assert (TIME_EQUAL (creation_time, st.st_atime));
|
|
rtems_test_assert (!TIME_EQUAL (creation_time, st.st_ctime));
|
|
}
|
|
|
|
/*
|
|
* These tests only get time_t value, and test
|
|
* if they are changed. Thest tests don't check atime
|
|
*/
|
|
#ifdef __rtems__
|
|
void test (void)
|
|
#else
|
|
int main(int argc, char **argv)
|
|
#endif
|
|
{
|
|
|
|
time_test01();
|
|
|
|
#ifndef __rtems__
|
|
return 0;
|
|
#endif
|
|
}
|