Sunday, August 24, 2014

Unix Prog: Files -- Directories(2)

1. Read Directories System Calls

Definition:
opendir:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/dirent.h  
 ......  
 /* Open a directory stream on NAME.  
   Return a DIR stream on the directory, or NULL if it could not be opened.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern DIR *opendir (const char *__name) __nonnull ((1));  
 ......  

readdir:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/dirent.h  
 ......  
 /* Read a directory entry from DIRP. Return a pointer to a `struct  
   dirent' describing the entry, or NULL for EOF or error. The  
   storage returned may be overwritten by a later readdir call on the  
   same DIR stream.  
   
   If the Large File Support API is selected we have to use the  
   appropriate interface.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 #ifndef __USE_FILE_OFFSET64  
 extern struct dirent *readdir (DIR *__dirp) __nonnull ((1));  
 ......  

struct dirent:
This is implementation dependent. But at least it needs to include following 2 fields: d_ino: i-node number, d_name: directory entry name
 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! */  
  };  
 ......  

rewinddir:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/dirent.h  
 ......  
 /* Rewind DIRP to the beginning of the directory. */  
 extern void rewinddir (DIR *__dirp) __THROW __nonnull ((1));  
 ......  

closedir:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/dirent.h  
 ......  
 /* Close the directory stream DIRP.  
   Return 0 if successful, -1 if not.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern int closedir (DIR *__dirp) __nonnull ((1));  
 ......  

telldir:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/dirent.h  
 ......  
 /* Return the current position of DIRP. */  
 extern long int telldir (DIR *__dirp) __THROW __nonnull ((1));  
 ......  

seekdir:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/dirent.h  
 ......  
 /* Seek to position POS on DIRP. */  
 extern void seekdir (DIR *__dirp, long int __pos) __THROW __nonnull ((1));  
 ......  

fileio.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<dirent.h>  
   
 int main(int argc, char* argv[])  
 {  
  DIR *pdir;  
  struct dirent *pent;  
   
  // Open the directory  
  if((pdir = opendir(argv[1])) == NULL) {  
   printf("opendir error!\n");  
   exit(1);  
  }  
   
  // Read directory entry, whenver read in one entry, it will move  
  // the cursor position forward for one step, until reaching  
  // the end of directory, return NULL.  
  while((pent = readdir(pdir)) != NULL) {  
   int pos;  
   pos = telldir(pdir);  
   printf("position: %d entry name: %s entry i-node number: %d\n",  
       pos, pent->d_name, (int)pent->d_ino);  
  }  
   
  // Move the cursor position to beginning of directory  
  // It will affect the "readdir" system call on which entry should  
  // be extracted for the next step  
  rewinddir(pdir);  
  printf("\nRewind to the beginning of the directory: \n");  
  while((pent = readdir(pdir)) != NULL) {  
   int pos;  
   pos = telldir(pdir);  
   printf("position: %d entry name: %s entry i-node number: %d\n",  
       pos, pent->d_name, (int)pent->d_ino);  
  }  
   
  // Close the directory  
  if(closedir(pdir) < 0) {  
   printf("closedir error!\n");  
   exit(2);  
  }  
   
  exit(0);  
 }  

shell:
1) Run the program against "testdir", it will output all entries inside testdir, then rewind the cursor to the beginning of directory, then output all entries again.
2) List all directory entries of testdir.
 ubuntu@ip-172-31-23-227:~$ ./io.out testdir  
 position: 51774008 entry name: t1 entry i-node number: 271672  
 position: 1565902814 entry name: t2 entry i-node number: 271673  
 position: 1467405293 entry name: . entry i-node number: 271668  
 position: 1951718350 entry name: .. entry i-node number: 271653  
 position: -1880314050 entry name: d1 entry i-node number: 271675  
 position: -1 entry name: d2 entry i-node number: 271676  
   
 Rewind to the beginning of the directory:  
 position: 51774008 entry name: t1 entry i-node number: 271672  
 position: 1565902814 entry name: t2 entry i-node number: 271673  
 position: 1467405293 entry name: . entry i-node number: 271668  
 position: 1951718350 entry name: .. entry i-node number: 271653  
 position: -1880314050 entry name: d1 entry i-node number: 271675  
 position: -1 entry na: d2 entry i-node number: 271676  
 ubuntu@ip-172-31-23-227:~$ ls -lrt ./testdir
 total 8
 -rw-rw-r-- 1 ubuntu ubuntu    0 Aug 24 21:04 t2
 -rw-rw-r-- 1 ubuntu ubuntu    0 Aug 24 21:04 t1
 drwxrwxr-x 2 ubuntu ubuntu 4096 Aug 24 21:04 d1
 drwxrwxr-x 2 ubuntu ubuntu 4096 Aug 24 21:08 d2

No comments:

Post a Comment