2 files are attached. the PDF is the assignment. The word document comprises the updates and corrections made to the assignment.
CSCI 4100 – Assignment 6 CSCI 4100 – Assignment 6 Instructions For this assignment you must implement a simple C version of the UNIX pwd program called pwned. The pwd program is used to display the absolute path name of the current working directory. The pwned program will do the same thing, but it doesn’t have to handle symbolic links or mount points or anything more complicated than a basic directory structure. You must implement the following functions: • The inum_to_filename function translates an inode number into the corresponding file name using the current working directory. It takes three arguments: the inode number to translate, a pointer to a buffer where the file name should be written, and the size of the buffer. There is no return value. It should do the following: a. Open the current working directory. If there is a problem, display the appropriate error message and exit the program. b. Read the first directory entry. c. If the inode number in the current directory entry matches the one passed to the function, copy the filename into the buffer and return frome the function. d. Otherwise read the next directory entry and repeat the previous step. e. If the inode number passed to the function is not in any of the directory entries, display the appropriate error message and exit the program. • The filename_to_inum function does the opposite of the previous function: it translates a filename to an inode number. It takes one argument, a char * representing the file name. It returns the corresponding inode number, if one can be found. It should do the following: a. Read the information from the file’s inode into a structure in memory. b. If there is any problem getting this information, display the appropriate error message and exit the program. c. Return the inode number from the structure in memory. • The display_path function is a recursive function that displays an absolute pathname for a given inode number. It takes one argument, an inode number for the current working directory whose pathname it will display. There is no return value. It should do the following: a. Create an array of characters to use as a buffer for the name of the directory. b. Get the inode number for the parent of the current directory using the filename_to_inode function. c. If the parent inode number is the same as the current inode number, this means we have reached the root and can return from the function. d. Otherwise, change to the parent directory and use the inum_to_filename function to find the file name for the inode number that was passed to the function. Use the buffer declared in step 1 to store the file name. e. Recursively call the display_path function to display the absolute path name of the parent directory. f. Display a / followed by the file name in the buffer. • Most of the functionality of the program is implemented in the previous functions, so the main function only has to do the following: a. Use the filename_to_inum function to get the inode number of the current working directory. b. Pass the inode number to display_path to display the absolute path name of the current working directory. c. Display a newline, so the command prompt appears on the next line. Working with Inodes There are two data types you need to be familiar with when you are dealing with inodes: • The ino_t datatype is used to represent inode numbers. • The stat structure is used to store the contents of an inode in memory. It has data members for all of the metadata contained in an inode, but you will only need to use the st_ino data member which contains the inode number for the inode. The information for an inode can be retrieved using the stat function, which takes a file name and a pointer to a stat structure where the information will be stored: struct stat info; int result = stat(filename, &info); If there is an error retrieving the metadata, the stat function will return -1. If this happens, you should execute the following statements: fprintf(stderr, "Cannot stat "); perror(filename); exit(EXIT_FAILURE); Note that the exit function requires the stdlib.h header file to be included and the fprintf and perror functions require the stdio.h header file. In order to use ino_t, the stat structure, and the stat function you will need the following additional preprocessor statements: #include
#include Working with Directories The POSIX interface to directories involves two additional data types: • The DIR data type represents a directory stream. • The dirent structure represents a directory entry. It has two data members: d_name is a char * that contains a file name and d_ino is a ino_t that contains an inode number. A directory can be opened using the opendir function, which takes a directory name as an argument and returns a DIR *: DIR *dir_ptr = opendir(dirname); If there is any problem opening the directory, the opendir function will return NULL, in which case you should execute the following statements: perror(dirname); exit(EXIT_FAILURE); To read the next directory entry in a directory, use the readdir function, which takes a DIR * as an argument and returns a pointer to a dirent structure: struct dirent *dirent_ptr = readdir(dir_ptr); If all of the directory entries have been read, readdir will return NULL. If this happens when you are looking for an inode number inum in a directory, you should execute the following statements: fprintf(stderr, "error looking for inum %d\n", (int)inum); exit(EXIT_FAILURE); To close a directory, use the closedir function, which takes a DIR * as an argument: closedir(dir_ptr); To change the current working directory, use the chdir function which takes a char * representing the name of the directory to change to. For example, if you want to change the the parent of the current working directory you would execute the following statement: chdir(".."); The following preprocessor statements are needed to use the structures and functions described above: #include #include Working with Strings The C programming language uses character arrays to represent strings. These arrays are usually passed around as variables of type char *, which is also the type for string literals. C strings must be handled very carefully as they are actually pointers to character arrays, not object like in C++. To statically allocate space for a string, just create a character array: char buffer[BUFSIZ]; The constant BUFSIZ is actually a preprocessor macro defined in stdio.h that is defined as the ideal size for a character buffer on a given operating system. To copy an existing C string str into a buffer, use the strncpy function defined in string.h: strncpy(buffer, str, BUFSIZ); buffer[BUFSIZ - 1] = '\0'; To display a string literal to the console use the printf function: printf("Hello World!"); To display a string variable str to the console use the printf function with the %s format code: printf("The string will appear here: %s", str); The printf function also requires the stdio.h header file. Compiling and Running Your Code Your source file should be called yourname_assign6.c except with your actual last name. To create an executable file called pwned use the following command: gcc -o pwned yourname_assign6.c When you run your code it should produce the same output that the pwd produces. Make sure to try it from several different directories to make sure it works properly. What to Hand In Your source file, yourname_assign6.c should have comments at the top listing your name, CSCI 4100, Assignment 6, and a brief explanation of what the program does. Upload the source file to D2L in the assignment dropbox called Assignment 6. Instructions Working with Inodes Working with Directories Working with Strings Compiling and Running Your Code What to Hand In There was a mistake in the original version of Assignment 6. There is an additional header file you need in order to use the ino_t data type: #include I have updated the assignment to reflect this. Furthermore, the algorithm I described in the assignment will not work in parts of a file system that are accessible using virtual nodes. On replit, you should be able to get the program to work outside of the /home/runner directory. I managed to get it to work in /usr/local/bin for example. You will need to specify the entire pathname of your program to run it from another directory: ~/CSCI-4100-Demo$ ./pwned error looking for inum 256 ~/CSCI-4100-Demo$ cd /usr/local/bin .../local/bin$ /home/runner/CSCI-4100-Demo/pwned /usr/local/bin I was playing around with my solution for Assignment 6 and I realized there was a way to get it to work in any directory. The problem with the code as I designed it was relying on the d_ino field in the dirent structure to get the inode number for a file. That works on a traditional UNIX file system, but it doesn't work when the file system is more complicated (symbolic links, mounted devices, virtual nodes). However, the stat function will still get the correct inode number and it just so happens that I asked you to implement a function that uses stat to convert a file name into an inode number. So here's the fix. Before you check if the inode number in the directory entry is the one you are looking for, do this: // direntp is the pointer to the directory entry returned by readdir ino_t real_ino = filename_to_inum(direntp->d_name); Then instead of using direntp->d_ino to do the comparison, use real_ino. If you do this your code should work in any directory in the file system.