Tuesday, August 19, 2014

Unix Prog: Files -- Types

1. File Types In Unix

1) Regular Files: most common type of file, containing the data of some form. Any interpretation of the file content is left to the application side.
2) Directory Files: a file containing the names of other files and pointers to information on these files. And processing having the read permission can read the contents of the directory, but only kernel can write directly to the directory file.
3) Block special file: a type of file providing the buffered I/O access in fixed-size units to devices such as disk drives.
4) Character special file: a type of file providing the unbuffered I/O access in variable-sized units to devices
5) FIFO: a type of file used for communication between processes, sometimes it is called a named pipe.
6) Socket: a type of file used for network communication between processes.
7) Symbolic Link: a type of file pointing to another file.

2. Macros determining the type of file
File type is saved at st_mode member of struct stat, we need to use one of following macros to determine the type of file:

S_IFMT turn on all bits belonging to file types
S_IFLNK, S_IFREG, S_IFDIR etc. only turn on bits belonging to own type.

Macros like S_ISLNK, S_ISREG will do the bit & operation and determine if the result is equal to related macro.
 ubuntu@ip-172-31-23-227:~$ less /usr/include/linux/stat.h  
 ......  
 #define S_IFMT 00170000  
 #define S_IFSOCK 0140000  
 #define S_IFLNK 0120000  
 #define S_IFREG 0100000  
 #define S_IFBLK 0060000  
 #define S_IFDIR 0040000  
 #define S_IFCHR 0020000  
 #define S_IFIFO 0010000  
 #define S_ISUID 0004000  
 #define S_ISGID 0002000  
 #define S_ISVTX 0001000  
   
 #define S_ISLNK(m)   (((m) & S_IFMT) == S_IFLNK)  
 #define S_ISREG(m)   (((m) & S_IFMT) == S_IFREG)  
 #define S_ISDIR(m)   (((m) & S_IFMT) == S_IFDIR)  
 #define S_ISCHR(m)   (((m) & S_IFMT) == S_IFCHR)  
 #define S_ISBLK(m)   (((m) & S_IFMT) == S_IFBLK)  
 #define S_ISFIFO(m)   (((m) & S_IFMT) == S_IFIFO)  
 #define S_ISSOCK(m)   (((m) & S_IFMT) == S_IFSOCK)  
 ......  

3. Determine the file type
fileio.c:
Inside <sys/stat.h>, there are some macros like S_ISSOCK, whose definition depends on compiling environment(some other macros), in this case, if we use:
gcc -g -std=c99 fileio.c -o.out
to compile the code(c99 mode), S_ISSOCK doesn't exist.
Historically, S_IS** macro is not defined, we have to use way mentioned above:
(((m) & S_IFMT) == S_IFLNK) to determine.

 #include<unistd.h>  
 #include<sys/stat.h>  
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<errno.h>  
   
 int main(int argc, char *argv[])  
 {  
  int fd;  
  struct stat buf;  
   
  int i;  
  for(i = 0; i < argc; i++) {  
   printf("%s: ", argv[i]);  
   
   if(lstat(argv[i], &buf) < 0) {  
    printf("lstat error!\n");  
    continue;  
   }  
   
   if(S_ISREG(buf.st_mode)) {  
    printf("regular\n");  
   }  
   
   if(S_ISDIR(buf.st_mode)) {  
    printf("directory\n");  
   }  
   
   if(S_ISCHR(buf.st_mode)) {  
    printf("character special\n");  
   }  
   
   if(S_ISBLK(buf.st_mode)) {  
    printf("block special\n");  
   }  
   
   if(S_ISFIFO(buf.st_mode)) {  
    printf("fifo\n");  
   }  
   
   if(S_ISLNK(buf.st_mode)) {  
    printf("symbolic link\n");  
   }  
   
   if(S_ISSOCK(buf.st_mode)) {  
    printf("socket\n");  
   }  
  }  
   
  exit(0);  
 }  

shell:
Given some files, and our code will iterate to give each file type.
 ubuntu@ip-172-31-23-227:~$ ./io.out /etc/passwd /dev/log /dev/tty /dev/disk/by-label/cloudimg-rootfs  
 ./io.out: regular  
 /etc/passwd: regular  
 /dev/log: socket  
 /dev/tty: character special  
 /dev/disk/by-label/cloudimg-rootfs: symbolic link  

No comments:

Post a Comment