Unit 1: Files, editing, and shells

Untitled

<aside> 📌 The command ls -lid / /.. . /usr/bin sparc* lists detailed information about the root (/) directory, its parent (the root again /.. ), the current directory(.), the /usr/bin directory, and any entries in the current directory matching the pattern sparc*.

For /usr/bin, the '4' in the third column represents the number of hard links to this directory. Since the inode of the current directory (denoted by .) and the inode of /usr/bin are the same, it confirms that we are in the /usr/bin directory.

To explain the 4 hard links:

  1. Self-Referential Link: Every directory in a Unix system has a hard link to itself (.), which counts as one link.
  2. Parent Directory Link: Every directory also has a hard link from its parent directory (..), which adds another link.

These two links account for the minimum of 2 hard links that every directory has.

  1. Subdirectory Links: Any subdirectory within a directory adds another hard link. In the case of /usr/bin, there are two additional subdirectories (sparcv7 and sparcv9), each contributing one more hard link.

We can identify these subdirectories because their file type starts with 'd' in the ls -l output. Therefore, the remaining two hard links are from the subdirectories sparcv7 and sparcv9.

</aside>

Untitled

<aside> 📌 Based on the second line, we see that the number of hard links to the root directory (/) is 35. Since the root directory has one self-referential link (.) and one link from its parent directory (.., which is itself), the remaining 33 links must correspond to subdirectories within the root directory. Therefore, / has 33 subdirectories, assuming all links are directories and there are no symbolic links.

</aside>

Unit 2: Commands and basic scripting

Untitled

<aside> 📌 Removing save-excursion will cause the point (cursor) to move during the execution of the function line-number-at-pos and not return to its original position, which can be confusing for the user. Removing save-restriction means that any narrowing applied to the buffer will not be restored after the function runs, causing the user's view of the buffer to change unexpectedly when widen is called. This alteration disrupts the user's context and buffer state.

Unit 3: Scripting and construction

Untitled

#!/bin/sh

if [ "$#" -lt 2 ]; then
 echo "Arguments are missing."
 exit 1
fi

dir_to_copy_from="$1"
exit_status=0

for f in "$@"; do
    if [ "$f" != "$dir_to_copy_from" ]; then
        base=$(basename "$f")  # gets the basename (i.e. C in A/B/C)
        #base="${f##*/}" #
        cp "$dir_to_copy_from/$base" "$f" 
        if [ "$?" -ne 0 ]; then
            exit_status=1
        fi
    fi
done
exit $exit_status

<aside> 📌 ${f##*/} extracts the basename from a full file path by removing everything up to and including the last slash (/), leaving only the filename.

Examples: Removing everything up to the last dot:

filename="archive.tar.gz"
extension="${filename##*.}"
echo "$extension"  # Output: gz

Removing a prefix and then removing a suffix:

file="backup-2021-12-01.tar.gz"
no_prefix="${file##backup-}"
no_suffix="${no_prefix%%.tar.gz}"
echo "$no_suffix"  # Output: 2021-12-01

</aside>

The instructor answer:

#!/bin/bash
status=ok
first=yes

for arg in "$@"; do  # "$@" is a list of the command line args, each quoted to take care of whitespace
    if [[ $first == yes ]]; then
        # Skip the first argument
        first=no
    else
        base=$(basename "$arg")  # gets the basename (i.e. C in A/B/C)
        if ! cp "$1/$base" "$arg"; then
            status=notok
        fi
    fi
done

if [[ $status == ok ]]; then
    exit 0
else
    exit 1
fi

*Unit : Makefiles and construction

Untitled

<aside> 📌 The first make call failed due to a circular dependency involving prog.h and prog. Specifically, prog.h depends on prog, but prog also depends on prog.h through prog.o. When make tried to generate prog.h by running ./prog <prog.in.h >prog.h, it failed because prog was not built yet. Despite the failure, prog.h was touched or created, updating its timestamp. On the second make call, make considered prog.h up-to-date because its timestamp was newer than its dependencies (prog.in.h and prog), and proceeded to compile prog.o and link it to create prog. The initial problem diagnosis was incorrect because it overlooked the circular dependency and the implications of make's timestamp-based dependency tracking.