Tuesday, August 26, 2014

Unix Prog: Files -- Directories(4)

1. chdir, fchdir, getcwd

chdir, fchdir can be used to change the current directory of current process.
Note: current directory is the property of process, each process has its own current directory.

Definition:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/unistd.h  
 ......  
 /* Change the process's working directory to PATH. */  
 extern int chdir (const char *__path) __THROW __nonnull ((1)) __wur;  
   
 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8  
 /* Change the process's working directory to the one FD is open on. */  
 extern int fchdir (int __fd) __THROW __wur;  
 ......  
 /* Get the pathname of the current working directory,
    and put it in SIZE bytes of BUF.  Returns NULL if the
    directory couldn't be determined or SIZE was too small.
    If successful, returns BUF.  In GNU, if BUF is NULL,
    an array is allocated with `malloc'; the array is SIZE
    bytes long, unless SIZE == 0, in which case it is as
    big as necessary.  */
 extern char *getcwd (char *__buf, size_t __size) __THROW __wur;
......

fileio.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
   
 int main(int argc, char* argv[])  
 {  
  char buff[256];  
   
  // Get the current working directory  
  if(getcwd(buff, 256) == NULL) {  
   printf("getcwd error!\n");  
   exit(1);  
  }  
   
  printf("Cwd=%s\n", buff);  
   
  // Change to another directory  
  if(chdir("testdir/slnk") < 0) {  
   printf("chdir error!\n");  
   exit(2);  
  }  
   
  // Output the current working directory again  
  if(getcwd(buff, 256) == NULL) {  
   printf("getcwd error!\n");  
   exit(3);  
  }  
   
  printf("Cwd=%s\n", buff);  
   
  exit(0);  
 }  

shell:
1) Run "pwd" command to list the current working directory
2) Run the io.out to change current working directory to /home/ubuntu/testdir/slnk", but it comes to the /home/ubuntu/testdir. The reason is: chdir follows symbolic link, and "testdir/slnk" is one symbolic link, which is pointing to its parent directory. Here is how getcwd works: it follows ".." entry in local directory to keep going up and output the entire chain, and it starts from /home/ubuntu/testdir, so the string it got is "/home/ubuntu/testdir".
3) Run the pwd again to list the current working directory. Since "current working directory" is the property of process, it only changed the working directory of the process where program was running, but not changed the working directory of the "shell" process.

 ubuntu@ip-172-31-23-227:~$ pwd  
 /home/ubuntu  
 ubuntu@ip-172-31-23-227:~$ ./io.out  
 Cwd=/home/ubuntu  
 Cwd=/home/ubuntu/testdir  
 ubuntu@ip-172-31-23-227:~$ pwd  
 /home/ubuntu  

2. Device Special Files

For each file system mounted on disk, it has both major device number and minor device number. We can use macros "major" and "minor" to get its major device number and minor device number by applying the macro on st_dev and st_rdev(for character special file and block special file) fields at "struct stat".

fileio.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<sys/sysmacros.h>  
 #include<sys/stat.h>  
   
 int main(int argc, char* argv[])  
 {  
  struct stat buf;  
   
  int i;  
  for(i=1; i < argc; i++) {  
   printf("%s: ", argv[i]);  
   
   // Get the i-node information  
   if(stat(argv[i], &buf) < 0) {  
    printf("stat error!\n");  
    exit(1);  
   }  
   
   // Print out device number  
   printf("dev = %d/%d ", major(buf.st_dev), minor(buf.st_dev));  
   
   // Print out device number for character special and block special files  
   if(S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode)) {  
    printf("(%s) rdev = %d/%d", (S_ISCHR(buf.st_mode))? "character" : "block",  
        major(buf.st_rdev), minor(buf.st_rdev));  
   }  
   
   printf("\n");  
  }  
   
  exit(0);  
 }  

shell:
1) Run the program against one block special file
2) Run the program against one character special file
3) Run the program against one regular directory.
 ubuntu@ip-172-31-23-227:~$ ./io.out /dev/xvda  
 /dev/xvda: dev = 0/5 (block) rdev = 202/0  
 ubuntu@ip-172-31-23-227:~$ ./io.out /dev/tty1  
 /dev/tty1: dev = 0/5 (character) rdev = 4/1  
 ubuntu@ip-172-31-23-227:~$ ./io.out /home/ubuntu  
 /home/ubuntu: dev = 202/1  

No comments:

Post a Comment