Saturday, August 16, 2014

Unix Prog: File I/O(3)

1. Create the file by "open" command
fileio.c:
By this way, we can successfuly solve the problem about file created can be used not only for "write", but also for "read"
 #include<unistd.h>  
 #include<fcntl.h>  
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<errno.h>  
   
 int main()  
 {  
  char buf[4096];  
  int fd;  
  int read_size;  
  int write_size;  
   
  fd = open("test.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU);  
  printf("file descriptor: %d\n", fd);  
  if(fd < 0) printf("Error!\n");  
   
  errno = 0;  
  write_size = write(fd, buf, 12);  
  printf("write size: %d errno: %d\n", write_size, errno);  
   
  errno = 0;  
  read_size = read(fd, buf, 12);  
  printf("read size: %d errno: %d\n", read_size, errno);  
   
  close(fd);  
 }  

shell:
Since the file is opened with "O_RDWR", so it can successfully create the file, write the file and read the file.
 ubuntu@ip-172-31-23-227:~$ ./io.out  
 file descriptor: 3  
 write size: 12 errno: 0  
 read size: 0 errno: 0  

2. create the file which is already existed
fileio.c:
 #include<unistd.h>  
 #include<fcntl.h>  
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<errno.h>  
   
 int main()  
 {  
  char buf[4096];  
  int fd;  
  int read_size;  
  int write_size;  
   
  errno = 0;  
  fd = open("test.txt", O_RDWR | O_CREAT | O_EXCL, S_IRWXU);  
  printf("file descriptor: %d\n", fd);  
  if(fd < 0) printf("Error! errno: %d\n", errno);  
   
  errno = 0;  
  write_size = write(fd, buf, 12);  
  printf("write size: %d errno: %d\n", write_size, errno);  
   
  errno = 0;  
  read_size = read(fd, buf, 12);  
  printf("read size: %d errno: %d\n", read_size, errno);  
   
  close(fd);  
 }  

shell:
It failed to create the file since the file is already existed. Because we used the O_EXCL mode, so when file exists, it will return error(-1) as file descriptor, and also set up the errno to 17.
 ubuntu@ip-172-31-23-227:~$ ./io.out  
 file descriptor: -1  
 Error! errno: 17  
 write size: -1 errno: 9  
 read size: -1 errno: 9  

errno.h:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/asm-generic/errno-base.h  
 ......  
 #define EEXIST     17   /* File exists */  
 ......  

3. Test if lseek can seek on standard input
fileio.c:
 #include<unistd.h>  
 #include<fcntl.h>  
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<errno.h>  
   
 int main()  
 {  
  errno = 0;  
  if(lseek(STDIN_FILENO, 0, SEEK_CUR) == -1)  
   printf("can not seek! errno: %d\n", errno);  
  else  
   printf("seek ok!\n");  
 }  

shell:
If standard input is regular file, it is ok to seek, but if it is the pipe, FIFO or socket, then we can't seek using lseek, while it will setup the errno as ESPIPE.
 ubuntu@ip-172-31-23-227:~$ ./io.out <test.txt  
 seek ok!  
 ubuntu@ip-172-31-23-227:~$ cat test.txt | ./io.out  
 can not seek! errno: 29  

Note: we should always test whether the return value of lseek is -1, instead of less than 0. Because lseek is allowed to return negative-offset, which is not an error.

errno.h:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/asm-generic/errno-base.h  
 ......  
 #define ESPIPE     29   /* Illegal seek */  
 ......  

4. lseek whence bit
SEEK_SET: set the file's offset from the beginning of the file
SEEK_CUR: set the file's offset from the current location of the file
SEEK_END: set the file's offset from the end of the file
 ubuntu@ip-172-31-23-227:~$ less /usr/include/unistd.h  
 ......  
 /* Values for the WHENCE argument to lseek. */  
 #ifndef _STDIO_H        /* <stdio.h> has the same definitions. */  
 # define SEEK_SET    0    /* Seek from beginning of file. */  
 # define SEEK_CUR    1    /* Seek from current position. */  
 # define SEEK_END    2    /* Seek from end of file. */  
 # ifdef __USE_GNU  
 # define SEEK_DATA   3    /* Seek to next data. */  
 # define SEEK_HOLE   4    /* Seek to next hole. */  
 # endif  
 #endif  
 ......  

No comments:

Post a Comment