$30
TREE
Points 100
Introduction
In this assignment, you will practice using system calls to access the
filesystem, navigate the directory structure, and parse file stats.
Learning Outcomes
Describe the API for different operations related to files (Module 3
MLO 3)
Describe the API for different operations related to directories
(Module 3 MLO 6)
How to define and use structures in C? (Module 2 MLO 3)
Specifications
NAME
tree - recursively list files and directories
SYNOPSIS
tree [OPTION]... [DIRECTORY]...
DESCRIPTION
Recursively list all files found in DIRECTORYs. If no DIRECTORY is provided, the current direc
tory is used.
By default, output is sorted alphabetically.
LISTING OPTIONS
-a Print hidden files. By default, tree does not print hidden files beginning with a dot
('.') character.
The filesystem constructs `.' and `..' are never printed even with the -a option.
-d Print only directories, no files.
FILE OPTIONS
-p Print permissions according to the mode string format specified for `ls' according to
POSIX.
-u Print the username, or UID # if no username is available, of the file.
-g Print the group name, or GID # if no group name is available, of the file.
-s Print the size of each file in bytes.
SORTING OPTIONS (default: alphabetic sorting)
-r Sort the output in reverse alphabetic order.
-t Sort the output by last modification time instead of alphabetically.
-U Do not sort. List files according to directory order.
-h Print this message
AUTHOR
You, again!
NOTES
Source code must compile without errors againt the c99 standard on os1 to receive ANY credi
t. Example:
gcc -std=c99 ...
Source code must compile without errors for FULL credit, with the following flags:
gcc -std=c99 -Wall -Wextra -Wpedantic -Werror ...
Detailed instructions
In this assignment, you will write a small library that parses files and
directory structures to list files and directory contents recursively in
a tree format, where each subdirectory is indented from the last. You
will implement basic sorting and print the file permissions, username,
group, and file size.
Example output
$./tree -pugs /usr/share/man/en
[drwxr-xr-x root root 66] /usr/share/man/en
[drwxr-xr-x root root 148] man2
[-rw-r--r-- root root 2407] close.2.gz
[-rw-r--r-- root root 1808] getdomainname.2.gz
[-rw-r--r-- root root 7736] getrlimit.2.gz
[-rw-r--r-- root root 4852] madvise.2.gz
[-rw-r--r-- root root 5949] mount.2.gz
[-rw-r--r-- root root 1445] sysinfo.2.gz
[-rw-r--r-- root root 1962] umask.2.gz
[drwxr-xr-x root root 158] man3
[-rw-r--r-- root root 2141] encrypt.3.gz
[-rw-r--r-- root root 2004] fclose.3.gz
[-rw-r--r-- root root 2143] fflush.3.gz
[-rw-r--r-- root root 2214] lockf.3.gz
[-rw-r--r-- root root 2700] rand.3.gz
[-rw-r--r-- root root 3157] strtok.3.gz
[-rw-r--r-- root root 1359] toupper.3.gz
[-rw-r--r-- root root 1502] updwtmp.3.gz
[drwxr-xr-x root root 21] man4
[-rw-r--r-- root root 10229] st.4.gz
[drwxr-xr-x root root 23] man5
[-rw-r--r-- root root 4761] utmp.5.gz
[drwxr-xr-x root root 64] man7
[-rw-r--r-- root root 3165] environ.7.gz
[-rw-r--r-- root root 4731] hier.7.gz
[-rw-r--r-- root root 4278] suffixes.7.gz
Guidance
In this assignment, you will be working with two source files, one of
which will produce a library (shared object) and the other which acts as
a test-bench to model a third party using your library.
What is a shared library? It's just a collection of symbol definitions
(functions, objects) that are packaged into a shared object (.so) file
format. If your program is linked against a shared library, any symbols
that you use, which are part of that library, will have undefined values
when your program starts. A program called the loader comes along during
the initialization process (before main() is called), and it loads the
shared library into memory, and the linker updates the table of symbols
to point to the appropriate locations in that library. This is actually
how all of the functions and symbols you use from the standard C library
work. If your program calls printf, the libc.so file is loaded into your
program's virtual memory space, and the printf symbol is resolved at
runtime by the linker.
Shared libraries are really useful. For one, since they contain mostly
read-only information (function instructions, constants), shared
libraries can be, well, shared. There is one copy of the shared library
in memory, and every program that is using it simply has it mapped into
each of their private virtual memory address spaces. From the
perspective of the program, it's the only one using that library. From
the perspective of the kernel, it just save a bunch of memory! It also
means your program is a lot smaller, since the instructions and data for
common things are actually stored already in the system, separate from
your program.
Another great thing about shared libraries is that they can be updated
with bugfixes. Since the code for "printf" isn't actually in your
program, if a bug in printf is found, libc can be updated, and it will
immediately propagate to all programs that link to it. That's pretty
nifty!
Unlike other programming assignments, you will not be writing a main()
function, since that's already been done for you. Instead, you'll be
writing the code for the library, where you'll be learning more about
the very basics of projects larger than a single source file. Every
library comes with header file(s) which declare the symbols present in
the library for ease of use. Technically, you could declare these
yourself without #including anything, if you know what they are, and
everything would work fine, but it's much better to just include the
library's header file! Plus, if the API ever changes, the header will be
updated, but your hardcoded declarations won't.
You should read this header file!
You can find the skeleton code and makefile to start your project under
/class/cs344/assignments/01-tree/skeleton-code. You should copy these
files (cp -r) to your own working directory. You can run the `make`
command to build an executable and take it for a spin; it will build
both a debug and release builds, or you can select a different target
manually. You might notice it's a little bit broken. Look for comments
that say "TODO" in the skeleton code. Have fun!
An example implementation is available as a system utility called
`tree`.
What to turn in
Submit your source code to Canvas Gradescope as a single source file.
The name of the file you submit is not important, but only submit one
single document that can be compiled with the makefile provided in the
assignment skeleton code. You only need to submit the libtree.c file. I
will provide the other files when testing your code!
Rubric
Note: $BASE is /class/cs344/assignments/01-tree/test-dirs/
All examples shown are illustrative only. The test-dirs on os1
are for testing, but are not identical to what will be used on
gradescope.
Failure (F)
0%
No submission
0-60%
Instructor's discretion
60%
Compiles (-std=gnu99) (less strict than "debug" build of makefile)
gcc -std=gnu99 -o tree [...]
Correct output:
tree -- $BASE/test_02
Produces error on stderr and exits with non-zero exit status:
tree -- '' # Explicitly illegal empty/zero-length path argument
63%
Correct output (non-recursive):
tree -r -- $BASE/test_02
And either (non-recursive dirsonly):
tree -d -- $BASE/test_03
or (non-recursive hidden):
tree -a -- $BASE/test_07
tree -- $BASE/test_07
or (non-recursive file size):
tree -s -- $BASE/test_08
67%
Correct output (partially recursive):
tree -- $BASE/test_03
70%
Compiles (-std=c99) ("debug" build of makefile)
gcc -std=c99 -o tree [...]
73%
Correct output (recursive):
tree -- $BASE/test_04
Correct output (non-recursive dirsonly and hidden):
tree -d -- $BASE/test_03
tree -a -- $BASE/test_07
tree -- $BASE/test_07
77%
Correct output (recursive hidden and dirsonly):
tree -d -- $BASE/test_09
tree -a -- $BASE/test_09
tree -- $BASE/test_09
80%
EITHER
Correct output:
for OPTS in a d ad
do
tree -$OPTS -- $BASE/test_10
done
OR
Correct output:
for OPTS in p u g s
do
tree -$OPTS -- $BASE/test_10
done
83%
Correct output:
for OPTS in p u g s a d ad
do
tree -$OPTS -- $BASE/test_10
done
87%
Correct output (file info and hidden files):
tree -pugs -- $BASE/test_10
tree -pugs -a -- $BASE/test_10
90%
Compiles strictly: ("release" build of makefile)
gcc -std=c99 -Wall -Werror -o tree [...]
93%
Correct output with sorting and hidden files:
tree -pugs -r -- $BASE/test_10
tree -pugs -U -- $BASE/test_10
tree -pugs -t -- $BASE/test_10
tree -pugs -a -r -- $BASE/test_10
tree -pugs -a -U -- $BASE/test_10
tree -pugs -a -t -- $BASE/test_10
97%
Correct output on all valid combinations of options:
for OPTS in {p,}{u,}{g,}{s,}{a,}{d,}{U,r,t,}
do
tree "${OPTS:+"-$OPTS"}" -- $BASE/test_10
done
100%
Valgrind reports no memory leaks
valgrind tree -pugsa -r -- $BASE/test_10
Final point modifications:
Jul 10 at 9:00AM
Jul 03 at 9:00AM
Jun 16 at 9:00AM
CS 344 Summer 2023
Course ID: 549755
Name Status Released
Small Shell No Submission
Tree No Submission
Base 64 Encoder Submitted
Submit Programming Assignment
Upload all files for your submission
Drag & Drop
Any file(s) including .zip. Click to browse.
Submission Method
Upload GitHub
Crashes during testing: Grade reduced by 10%, but not below 73%
Inappropriately produces error messages or exits with nonzero status:
Grade reduced by 10%, but not below 83%
Malfunctions when print_tree is called multiple times (e.g. tree --
$BASE/test_10 $BASE/test_10 ): Grade reduced by 10% but not below 87%