/*
* Copyright ©2026 Soham Pardeshi. All rights reserved.
* Permission is hereby granted to students registered for University of
* Washington CSE 333 for use solely during Summer Quarter 2026 for
* purposes of the course. No other use, copying, distribution, or
* modification is permitted without prior written consent. Copyrights
* for third-party components of this work must be honored. Instructors
* interested in reusing these course materials should contact the author.
*/
#include <cstdlib> // for EXIT_SUCCESS, EXIT_FAILURE
#include <iostream> // for cout, cerr, endl
#include <string> // for string
#include "dirutil.h"
#include "fileutil.h"
using std::cerr;
using std::cout;
using std::endl;
using std::string;
#define NUM_BYTES_TO_PRINT 256
#define HEADER_SIZE 50
/*
* This program:
* - Takes the name of a directory as its single command-line argument.
* - Prints "Contents of <dir>:", then, for each entry in the directory,
* prints the entry's name and size, an "=" divider line, and up to
* NUM_BYTES_TO_PRINT bytes of its contents, using the dirutil and fileutil
* modules.
* - On any error (wrong usage, an unopenable directory, or an unreadable
* file), prints a useful message to std::cerr and exits with
* EXIT_FAILURE.
*/
int main(int argc, char** argv) {
// This program takes exactly one argument: the directory to list.
if (argc != 2) {
cerr << "Usage: " << argv[0] << " <directory>" << endl;
return EXIT_FAILURE;
}
string dirname = argv[1];
// Open the directory for iteration over its entries.
DirIter* iter = DirIter_Allocate(dirname.c_str());
if (iter == nullptr) {
cerr << "Could not open directory: " << dirname << endl;
return EXIT_FAILURE;
}
cout << "Contents of " << dirname << ":" << endl;
// Walk every entry, printing its size and the first NUM_BYTES_TO_PRINT bytes
// of its contents.
char buf[NUM_BYTES_TO_PRINT];
while (DirIter_IsValid(iter)) {
const char* name = DirIter_Get(iter);
// Build the full path to the entry: "<dirname>/<name>".
string path = dirname;
if (!path.empty() && path.back() != '/') {
path += '/';
}
path += name;
ssize_t size = FileSize(path.c_str());
// Read the whole buffer in one chunk (chunk_size == buflen).
ssize_t bytes_read = ReadFile(path.c_str(), buf, NUM_BYTES_TO_PRINT,
NUM_BYTES_TO_PRINT);
if (size < 0 || bytes_read < 0) {
cerr << "Could not read file: " << path << endl;
DirIter_Free(iter);
return EXIT_FAILURE;
}
// Blank line, then "<name> (<size> bytes):", then the raw contents.
cout << endl
<< name << " (" << size << " bytes):" << endl;
cout << std::string(HEADER_SIZE, '=') << endl;
cout.write(buf, bytes_read);
cout << endl;
DirIter_Next(iter);
}
DirIter_Free(iter);
return EXIT_SUCCESS;
}