Saturday, August 2, 2014

Unix Prog: Unix System Overview - File System

1. Unix Architecture:

Kernel: the software controlling and managing the hardware resources while providing the environment where application can run.

System Call: the interface to the kernel.

2. Logging In

When logging into the unix system, user need to provide the user name and password. Unix system will verify the information from /etc/passwd file.

shell:
1) locate the /etc/passwd
2) print out the content of /etc/passwd file and retrieve only the first 5 lines. It shows multiple users. In sequence it is: login name, encrypted password, numeric user ID, numeric group ID, a comment field, home directory, and shell program.
 ubuntu@ip-172-31-23-227:~$ ls -lrt /etc/passwd  
 -rw-r--r-- 1 root root 1283 Aug 2 14:29 /etc/passwd  
 ubuntu@ip-172-31-23-227:~$ cat /etc/passwd | head -n 5  
 root:x:0:0:root:/root:/bin/bash  
 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin  
 bin:x:2:2:bin:/bin:/usr/sbin/nologin  
 sys:x:3:3:sys:/dev:/usr/sbin/nologin  
 sync:x:4:65534:sync:/bin:/bin/sync  

3. Files and Directories
File System: A hierarchical arrangement of directories and files.
Directory: a file containing the directory entries.
Directory Entry: a file name along with a structure describing the the attributes of the file
Absolute Path Name: path name starting with a slash (/)
Relative Path Name: path name starting without a slash (/), which is compared to current directory.
All path names are ended with a null terminator.

4. A Simple Implementation of ls function:
ls.c
DIR, struct dirent is defined at "dirent.h", which is used to describe the file and directory information
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <dirent.h>  
   
 void err_quit(const char* msg)  
 {  
  printf("%s\n", msg);  
  exit(1);  
 }  
   
 int main(int argc, char *argv[])  
 {  
  DIR *dp;  
  struct dirent *dirp;  
   
  #If the number of parameters is not 2, output warning
  if(argc != 2)  
   err_quit("usage: ls directory_name");  
   
  #Open the directory specified by parameter,and save the returning
  #DIR pointer to dp
  if((dp = opendir(argv[1]))==NULL)  
   err_quit("can't open the directory");  
   
  #Use a while loop to read information based on the DIR pointer
  while((dirp = readdir(dp))!=NULL)  
   printf("%s\n", dirp->d_name);  
   
  closedir(dp);  
  exit(0);  
 }  

shell:
1) Use gcc to compile the ls.c and output it to myls executable file
2) List local directory information
3) Use our own "myls" to list information of testdir directory.
 ubuntu@ip-172-31-23-227:~$ gcc ls.c -o myls  
 ubuntu@ip-172-31-23-227:~$ ls  
 #ls.c# ls.c ls.c~ myls testdir  
 ubuntu@ip-172-31-23-227:~$ ./myls testdir  
 t3  
 t1  
 t2  
 .  
 ..  

5. Explanation of "ls.c"

About the "DIR", "struct dirent":
shell:
DIR is the alias of "struct __dirstream", which is defined at other c file
so opendir is defined as one external declaration
 ubuntu@ip-172-31-23-227:~$ grep DIR /usr/include/dirent.h  

......

 typedef struct __dirstream DIR;  
   Return a DIR stream on the directory, or NULL if it could not be opened.  
 extern DIR *opendir (const char *__name) __nonnull ((1));  

......


shell:
1) Print out the content of /usr/include/dirent.h, and it indicates that bits/dirent.h define the struct dirent
2) use find command to look for the dirent.h, and it is listed at following places:
/usr/include/dirent.h
/usr/include/x86_64-linux-gnu/bits/dirent.h
3) Print out the content of /usr/include/x86_64-linux-gnu/bits/dirent.h, and it describes the definition of "struct dirent", besides d_name, it also includes d_type and d_reclen.

 ubuntu@ip-172-31-23-227:~$ less /usr/include/dirent.h

......

 /* This file defines `struct dirent'.  
   
   It defines the macro `_DIRENT_HAVE_D_NAMLEN' iff there is a `d_namlen'  
   member that gives the length of `d_name'.  
   
   It defines the macro `_DIRENT_HAVE_D_RECLEN' iff there is a `d_reclen'  
   member that gives the size of the entire directory entry.  
   
   It defines the macro `_DIRENT_HAVE_D_OFF' iff there is a `d_off'  
   member that gives the file offset of the next directory entry.  
   
   It defines the macro `_DIRENT_HAVE_D_TYPE' iff there is a `d_type'  
   member that gives the type of the file.  
  */  
   
 #include <bits/dirent.h>  
   
......

ubuntu@ip-172-31-23-227:~$ sudo find /usr/include -name dirent.h
/usr/include/dirent.h
/usr/include/x86_64-linux-gnu/bits/dirent.h
ubuntu@ip-172-31-23-227:~$ less /usr/include/x86_64-linux-gnu/bits/dirent.h

......

struct dirent
  {
#ifndef __USE_FILE_OFFSET64
    __ino_t d_ino;
    __off_t d_off;
#else
    __ino64_t d_ino;
    __off64_t d_off;
#endif
    unsigned short int d_reclen;
    unsigned char d_type;
    char d_name[256];           /* We must not include limits.h! */
  };

......


No comments:

Post a Comment