Summary
Highlights
The video introduces the concept of rewriting GNU core utilities like 'ls' in C, acknowledging a recent trend of rewriting them in Rust. The goal is to provide a guide for writing a basic 'ls' command in C, covering 'ls', 'ls -a', and 'ls -l'. It notes that the full implementation of 'ls' is about 5,000 lines, and this tutorial will focus on the basics.
The tutorial begins by creating a simple C program with an 'int main(void)' function that returns 0. It then demonstrates how to compile the program using 'gcc' and run it. The first functional addition is printing text to the console using 'printf' and including the 'stdio.h' header file.
The video explains how to get command-line arguments using 'int argc' and 'char *argv[]' in the main function. It shows how 'argv[0]' holds the program name and 'argv[1]' holds the first argument. A conditional is added to handle cases where no arguments are provided, defaulting to the current directory ('.').
The next step involves opening a directory using the 'opendir' function, which requires including 'dirent.h'. The video explains error handling with 'perror' and 'errno.h' to catch failures when opening directories. It then demonstrates reading directory entries one by one using 'readdir' within a loop, explaining the 'dirent' struct and its 'd_name' field.
The tutorial shows how to filter out hidden files (those starting with '.') by adding a conditional check within the 'readdir' loop. It also emphasizes the importance of closing the directory stream using 'closedir' to prevent file descriptor leaks, explaining it as good practice.
To implement the '-a' flag for showing all files, the video introduces the 'getopt' function for parsing command-line options, requiring 'unistd.h'. It explains how 'getopt' works in a loop to identify flags and sets global variables like 'optind' to manage argument parsing. A 'show_all' boolean is used to control whether dot files are filtered.
The most complex part, the '-l' (long format) flag, is tackled by using the 'stat' system call, which provides detailed file information and requires 'sys/stat.h'. A helper function 'mode_to_string' is developed to convert the 'st_mode' field from the 'stat' struct into the human-readable permission string (e.g., '-rw-r--r--').
The video explains how to get user and group names from UID/GID provided by 'stat' using 'getpwuid' (from 'pwd.h') and 'getgrgid' (from 'group.h'). It then demonstrates how to format the modification time using 'localtime' (from 'time.h') and 'strftime' for a custom date and time string. All these pieces are integrated into a 'print_long' helper function.
The '-l' flag is integrated into the 'getopt' logic by introducing a 'long_format' boolean. Depending on whether 'long_format' is enabled, the program calls either the simple 'printf' or the 'print_long' helper function to display directory entries. The result is a fully functional 'ls' command supporting '-a' and '-l'.