text: /*
   spwd.c:  a simplified version of pwd
   
   starts in current directory and recursively climbs up to
   root of filesystem.  prints top part then prints current
   part
   
   uses readdir() to get info about each thing
   
   bug:  prints an empty string if run from "/"
   */
  
  #define BUFSIZE 32
  
  #include <stdio.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <dirent.h>
  #include <unistd.h>
  #include <stdlib.h>
  #include <string.h>
  
  ino_t get_inode( const char* );
  void printpathto( ino_t );
  void inum_to_name( ino_t, char*, int );
  
  int main()
  {
      printpathto( get_inode( "." ) );    // print path to here
      putchar('\n');                      // then add newline
      return 0;
  }
  
  void printpathto( ino_t this_inode )
  /*
   prints path leading down to an object with this inode
   kind of recursive
   */
  {
      ino_t my_inode;
      char its_name[BUFSIZE];
      
      if ( get_inode( ".." ) != this_inode )
      {
          chdir( ".." );                                  // up one directory
          inum_to_name( this_inode, its_name, BUFSIZE );  // get its name
          my_inode = get_inode( "." );                    // print head
          printpathto( my_inode );                        // recursively
          printf("/%s", its_name );            // now print name of this
      }
  }
  
  void inum_to_name( ino_t inode_to_find, char* namebuf, int buflen )
  /*
   looks through current directory for a file with this inode number and
   copies its name into namebuf
   */
  {
      DIR*    dir_ptr;        // the directory
      struct dirent* direntp; // each entry
      dir_ptr = opendir( "." );
      if ( dir_ptr == NULL )
      {
          perror( "." );
          exit( 1 );
      }
      
      // search directory for a file with specified inum
      while( ( direntp = readdir( dir_ptr ) ) != NULL )
          if ( direntp->d_ino == inode_to_find )
          {
              strncpy( namebuf, direntp->d_name, buflen );
              namebuf[buflen-1] = '\0';  // just in case
              closedir( dir_ptr );
              return;
          }
      fprintf( stderr, "error looking for inum %llu\n", inode_to_find );
      exit( 1 );
  }
  
  ino_t get_inode( const char* fname )
  /*
   returns inode number of the file
   */
  {
      struct stat info;
      
      if ( stat( fname, &info ) == -1 )
      {
          fprintf( stderr, "Cannot stat " );
          perror( fname );
          exit( 1 );
      }
      return info.st_ino;
  }
  