Assignment: Listing Directories

Assigned
  • October 7, 2024
Due
  • October 14, 2024 11:59pm
Collaboration
    All assignments in this class should be completed individually. You may ask for assistance from the instructor or mentor, but you may not discuss any aspect of your work on the assignment with other students in the class.
Submitting
    To submit this assignment, run make zip in the VSCode terminal to create a zip archive of your work. Log in to Gradescope at https://gradescope.com and upload it to the Listing Directories assignment on Gradescope. You can resubmit as many times as you like before the deadline.

Overview

For this assignment, you will implement a simple version of the ls command. Pay close attention to the man pages for the new functions you will use in this assignment.

Run the following commands on MathLAN to make a copy of the starter code for this assignment:

$ mkdir -p ~/csc213/assignments; git clone /home/curtsinger/csc213/assignments/myls ~/csc213/assignments/myls

Then run this command to open the project in VSCode:

$ code ~/csc213/assignments/myls

Requirements

You will be implementing your own version of the ls command. Your program will need to print the names of all the files and directories in a specified directory, along with the user and group that own the file, the file’s permissions, and its size. Your myls command will take one optional parameter; if this parameter is provided, it is the path to the directory that should be examined. If no parameter is provided myls should list the current directory. The provided starter code handles these two cases already. Here is example output for the myls program run in a directory with the starter code:

$ ./myls
-rw-r--r-- curtsinger mathfac 51 Makefile
drwxr-xr-x curtsinger mathfac 4096 .git
-rw-r--r-- curtsinger mathfac 8 .gitignore
drwxr-xr-x curtsinger mathfac 4096 .
drwxr-xr-x curtsinger curtsinger 4096 ..
drwxr-xr-x curtsinger mathfac 4096 .vscode
-rw-r--r-- curtsinger mathfac 582 .clang-format
-rw-r--r-- curtsinger mathfac 587 myls.c
-rwxr-xr-x curtsinger mathfac 8892 myls

As you can see, the files are not printed in sorted order. That’s perfectly fine; the autograder will just check for the presence of each line, not their order. The other items printed on each line are the permissions, user, group, and size of each file. You will need to use the opendir and readdir functions to list files in a directory, and the stat function to access information about each file in the directory.

Here are some more details about each of the pieces of an output line:

File Permissions
The first character of this item is a d if the entry is a directory, otherwise it is a -. The remaining nine characters show the file permissions for the owner, group, and all other users. These permissions are encoded in the st_mode field of struct stat. The documentation page for the chmod function (man 2 chmod) describes a series of constants you can use to access the bits for each permission type. In the first group of three, print an r if the owning user can read the file, or a - if the user cannot. Print a w if the user can write the file or - if the user cannot write, and likewise an x or - for execute permissions. Repeat these three characters again for the group permissions, and a third time for all other users. You should not print any permissions beyond read, write, and execute for the user, group, and others.
File Owner
The name of the user who owns this file. The stat function returns a user ID. Convert this to a username with the getpwuid function.
File Group
The name of the group associated with this file. The stat function returns a group ID. Convert this to a group name with the getgrgid function.
File Size
The size of the file in bytes.
File Name
The name of the file.

The built-in ls implementation will use spacing to align columns in its output; please do not do this for your implementation. Just print one space between each item on a line. Be careful not to print a space before the file permissions or after the filename.

Examples

Your output may differ slightly, since you will have access to different directories than I do. You can double-check your output by comparing it to ls -la with the same command line parameter, but ls sorts files alphabetically so the output order will almost certainly be different

You should be able to list the files in the directory for this assignment:

$ ./myls
-rw-r--r-- curtsinger mathfac 51 Makefile
drwxr-xr-x curtsinger mathfac 4096 .git
-rw-r--r-- curtsinger mathfac 8 .gitignore
drwxr-xr-x curtsinger mathfac 4096 .
drwxr-xr-x curtsinger curtsinger 4096 ..
drwxr-xr-x curtsinger mathfac 4096 .vscode
-rw-r--r-- curtsinger mathfac 582 .clang-format
-rw-r--r-- curtsinger mathfac 587 myls.c
-rwxr-xr-x curtsinger mathfac 8892 myls

You can also list files in your home directory:

$ ./myls ~
drwxr-xr-x curtsinger mathfac 4096 .
drwxr-xr-x root root 4096 ..
-rw------- curtsinger mathfac 17216 .bash_history
-rw------- curtsinger mathfac 735 .bash_profile
... many other files that begin with dots ...
drwx------ curtsinger mathfac 4096 Desktop
drwx------ curtsinger mathfac 4096 Documents
drwx------ curtsinger mathfac 4096 Downloads
drwx------ curtsinger mathfac 4096 Music
drwx------ curtsinger mathfac 4096 Pictures
drwx------ curtsinger mathfac 4096 Templates
drwx------ curtsinger mathfac 4096 Videos

Make sure you print some sort of error message if the argument does not reference a directory.

$ ./myls /some/imaginary/directory
Failed to open directory: no such file or directory

Questions & Answers

Does myls have to work if I pass a filename as a parameter instead of a directory?
No. I will only test myls with directories as parameters.
Does myls have to display symbolic links the same way as ls?
No. They will probably just appear as files, but I won’t test your implementation with symbolic links.
How do we actually access directories?
Use opendir to open a directory. This gives you a DIR*. Don’t look inside this value! Just pass it to readdir to get back a single entry in the directory. You’ll do this repeatedly until you’ve visited every file in the directory. Don’t forget to closedir when you’re finished.
Sometimes when I try to print a user or group ID I get a segmentation fault. What should I do?
Check your error codes! If you can’t get a string representation of a user or group name just print the number.
Does the output from myls have to be in the same order as ls’s output?
No. I will just make sure there is a corresponding line in your output.