Sunday, August 24, 2014

Unix Prog: Files -- Time

1. Three time fields
At struct stat, it maintains 3 time fields:

st_atime: lass-access time of file data, like read system call. Note: this is not the last access time of i-node information, like "stat" or "lstat" system call. Unix doesn't maintain the last access time of i-node information.

st_mtime: last-modification time of file data, like "write" system call.

st_ctime: last-change time of i-node status, like "chmod" "chown" system call.

Get above 3 times:
1) List 3 times of io.out
2) Change the permission of io.out
3) List 3 times again, and it changed "last-change" status time since it is related with i-node informatoin.
4) Run the io.out which needs reading its binary content.
5) List 3 times again, and it changed the "last-access" file content time since running needs reading all file content from disk data block.
 ubuntu@ip-172-31-23-227:~$ stat io.out  
  File: ‘io.out’  
  Size: 9889      Blocks: 24     IO Block: 4096  regular file  
 Device: ca01h/51713d  Inode: 271668   Links: 1  
 Access: (0775/-rwxrwxr-x) Uid: ( 1000/ ubuntu)  Gid: ( 1000/ ubuntu)  
 Access: 2014-08-24 14:08:00.874584999 +0000  
 Modify: 2014-08-24 14:07:51.946584999 +0000  
 Change: 2014-08-24 14:07:51.946584999 +0000  
  Birth: -  
 ubuntu@ip-172-31-23-227:~$ chmod o-r io.out  
 ubuntu@ip-172-31-23-227:~$ stat io.out  
  File: ‘io.out’  
  Size: 9889      Blocks: 24     IO Block: 4096  regular file  
 Device: ca01h/51713d  Inode: 271668   Links: 1  
 Access: (0771/-rwxrwx--x) Uid: ( 1000/ ubuntu)  Gid: ( 1000/ ubuntu)  
 Access: 2014-08-24 14:08:00.874584999 +0000  
 Modify: 2014-08-24 14:07:51.946584999 +0000  
 Change: 2014-08-24 14:30:05.522584999 +0000  
  Birth: -  
 ubuntu@ip-172-31-23-227:~$ ./io.out  
 symlink error!  
 ubuntu@ip-172-31-23-227:~$ stat io.out  
  File: ‘io.out’  
  Size: 9889      Blocks: 24     IO Block: 4096  regular file  
 Device: ca01h/51713d  Inode: 271668   Links: 1  
 Access: (0771/-rwxrwx--x) Uid: ( 1000/ ubuntu)  Gid: ( 1000/ ubuntu)  
 Access: 2014-08-24 14:30:57.770584999 +0000  
 Modify: 2014-08-24 14:07:51.946584999 +0000  
 Change: 2014-08-24 14:30:05.522584999 +0000  
  Birth: -  

ls command:
1) List 3 times of fileio.c
2) By default, ls command will use last-modification time
3) -u option will make ls command use last-access time
4) -c option will make ls command use last-change status time.
 ubuntu@ip-172-31-23-227:~$ stat fileio.c  
  File: ‘fileio.c’  
  Size: 352       Blocks: 8     IO Block: 4096  regular file  
 Device: ca01h/51713d  Inode: 271669   Links: 1  
 Access: (0660/-rw-rw----) Uid: ( 1000/ ubuntu)  Gid: ( 1000/ ubuntu)  
 Access: 2014-08-24 14:40:08.966584999 +0000  
 Modify: 2014-08-24 14:07:42.226584999 +0000  
 Change: 2014-08-24 14:36:00.002584999 +0000  
  Birth: -  
 ubuntu@ip-172-31-23-227:~$ ls -l fileio.c  
 -rw-rw---- 1 ubuntu ubuntu 352 Aug 24 14:07 fileio.c  
 ubuntu@ip-172-31-23-227:~$ ls -lu fileio.c  
 -rw-rw---- 1 ubuntu ubuntu 352 Aug 24 14:40 fileio.c  
 ubuntu@ip-172-31-23-227:~$ ls -lc fileio.c  
 -rw-rw---- 1 ubuntu ubuntu 352 Aug 24 14:36 fileio.c  

2. Change the file times
We can use system utime to change the file time by ourselves.

Definition:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/utime.h  
 ......  
 /* Structure describing file times. */  
 struct utimbuf  
  {  
   __time_t actime;      /* Access time. */  
   __time_t modtime;      /* Modification time. */  
  };  
   
 /* Set the access and modification times of FILE to those given in  
   *FILE_TIMES. If FILE_TIMES is NULL, set them to the current time. */  
 extern int utime (const char *__file,  
          const struct utimbuf *__file_times)  
    __THROW __nonnull ((1));  
 ......  

fileio.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<utime.h>  
 #include<unistd.h>  
 #include<fcntl.h>  
 #include<sys/stat.h>  
   
 int main(int argc, char* argv[])  
 {  
  int fd;  
  struct stat buff;  
  struct utimbuf tbf;  
   
  // Fetch the existing time on argv[1] file  
  if(lstat(argv[1], &buff) < 0) {  
   printf("lstat error!\n");  
   exit(1);  
  }  
   
  tbf.actime = buff.st_atime;  
  tbf.modtime = buff.st_mtime;  
   
  // Truncate the argv[1] file to change the  
  // last-access time and last-modification time  
  // to the current time.  
  if(open(argv[1], O_RDWR | O_TRUNC) < 0) {  
   printf("open error!\n");  
   exit(2);  
  }  
   
  // Change the lass access time and last modification  
  // time back to original time  
  if(utime(argv[1], &tbf) < 0) {  
   printf("utime error!\n");  
   exit(3);  
  }  
   
  exit(0);  
 }  

shell:
1) List 3 times of t1
2) Run date command to know the current time: 14:59:26
3) Run the program against t1, it truncated file t1, which is supposed to change the last access time and the last modification time to 14:59:26(current time), but it used utime to change time back, so both of time should be still: 14:55:42
4) List 3 times of t1, both last access time and last modification time don't change. But last-change status time get changed to current time: 14:59:31, this is because, "utime" system call will automatically update the "last-change-status time", since it changes the i-node information. This is also why "struct utimbuf" only contains last-access time and last-modification time.
 ubuntu@ip-172-31-23-227:~$ stat t1  
  File: ‘t1’  
  Size: 0        Blocks: 0     IO Block: 4096  regular empty file  
 Device: ca01h/51713d  Inode: 271668   Links: 1  
 Access: (0664/-rw-rw-r--) Uid: ( 1000/ ubuntu)  Gid: ( 1000/ ubuntu)  
 Access: 2014-08-24 14:55:42.150584999 +0000  
 Modify: 2014-08-24 14:55:42.150584999 +0000  
 Change: 2014-08-24 14:55:42.150584999 +0000  
  Birth: -  
 ubuntu@ip-172-31-23-227:~$ date  
 Sun Aug 24 14:59:26 UTC 2014  
 ubuntu@ip-172-31-23-227:~$ ./io.out t1  
 ubuntu@ip-172-31-23-227:~$ stat t1  
  File: ‘t1’  
  Size: 0        Blocks: 0     IO Block: 4096  regular empty file  
 Device: ca01h/51713d  Inode: 271668   Links: 1  
 Access: (0664/-rw-rw-r--) Uid: ( 1000/ ubuntu)  Gid: ( 1000/ ubuntu)  
 Access: 2014-08-24 14:55:42.000000000 +0000  
 Modify: 2014-08-24 14:55:42.000000000 +0000  
 Change: 2014-08-24 14:59:31.462584999 +0000  
  Birth: -  

Note: Use "utime" system call to change the time of file needs the process's effective user id be owner of file or super user.

If "struct utimebuf" is null-pointer when calling the "utime" system call, it will setup both time to be current time, this needs process's effective user id be owner of file or must have write permission.

No comments:

Post a Comment