This commit is contained in:
Ezri Zhu 2024-10-06 21:04:39 -04:00
commit 4e11b595a3
Signed by: ezri
SSH key fingerprint: SHA256:PjS2hKMfl3gJ5Furjjq+kXa4ZvS1c0gb4/djAxxAf6c
9 changed files with 508 additions and 0 deletions

82
.clang-format Normal file
View file

@ -0,0 +1,82 @@
# CS 631 - Advanced Programming in the Unix Environment
# clang-format source code format file
# Author: Anthony Webster
#
# I created this file based on the criteria specified at <https://stevens.netmeister.org/631/style>.
# I don't really care what you do with this file. I've just written this to (hopefully) be helpful.
# But, because it's "the right thing to do", this file is licensed under the MIT license.
#
# Copyright (c) 2024 Anthony Webster
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
BasedOnStyle: LLVM
# Despite my strong disagreement with using 80 columns, the style guide says we
# should try to keep code within 80 columns. So I guess we have to set this to 80.
ColumnLimit: 80
TabWidth: 4
IndentWidth: 4
UseTab: AlignWithSpaces
LineEnding: LF
InsertBraces: true
IndentCaseBlocks: false
BreakBeforeBraces: Linux
MaxEmptyLinesToKeep: 2
IncludeBlocks: Regroup
SortIncludes: CaseInsensitive
IncludeCategories:
# Kernel includes first
- Regex: '^<sys/'
Priority: 1
SortPriority: 1
CaseSensitive: false
# Network includes after kernel includes, without a blank line
- Regex: '^<(net|netinet|protocols)/'
Priority: 1
SortPriority: 2
CaseSensitive: false
# /usr includes next, separated by a blank line
- Regex: '^<'
Priority: 2
SortPriority: 3
CaseSensitive: false
# And other includes after /usr, separated by a blank line
- Regex: '^"'
Priority: 3
SortPriority: 4
CaseSensitive: false
# These aren't explicitly stated in the style guide but are derived from how the style guide is formatted.
BitFieldColonSpacing: None
SpaceAfterLogicalNot: false
SpaceBeforeAssignmentOperators: true
QualifierAlignment: Left
PointerAlignment: Right
AllowShortFunctionsOnASingleLine: None
AlwaysBreakAfterDefinitionReturnType: All
SeparateDefinitionBlocks: Always
SpaceAfterCStyleCast: false
AllowShortIfStatementsOnASingleLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
ContinuationIndentWidth: 4

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.o
ls

21
Makefile Normal file
View file

@ -0,0 +1,21 @@
CC = gcc
CFLAGS = -g -Wall -Werror -Wextra -Wformat=2 -Wjump-misses-init -Wlogical-op -Wpedantic -Wshadow
#CFLAGS = -ansi -g -Wall -Werror -Wextra -Wformat=2 -Wjump-misses-init -Wlogical-op -Wpedantic -Wshadow
#CFLAGS = -Wall -Werror -Wextra -Wpedantic
EXECUTABLE = ls
SOURCES = ls.c
OBJECTS = $(SOURCES:.c=.o)
all: $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) -o $(EXECUTABLE) $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJECTS) $(EXECUTABLE)
.PHONY: all clean

88
checklist Normal file
View file

@ -0,0 +1,88 @@
For each assignment, copy this file into your homework
submission directory and answer all questions.
Did I write all the code myself?
- Don't copy and paste code from the internet, your
classmates, sample solutions, or anywhere else.
Review https://stevens.netmeister.org/631/#plagiarism
Did I use any AI technologies? If so, did I properly
acknowledge this help?
- Review https://stevens.netmeister.org/631/use-of-ai.html
Does my code follow the style guide?
- Code is communication. Make sure your code is
readable, well-structured, properly indented,
with sensibily named variables and functions.
yes i use a clang formatter a classmate wrote
Does my code compile without warnings or errors on a
NetBSD 10.0 system?
- Always use *at least* 'cc -Wall -Werror -Wextra',
possibly
'cc -ansi -g -Wall -Werror -Wextra -Wformat=2 -Wjump-misses-init -Wlogical-op -Wpedantic -Wshadow'.
yes
Did I provide a Makefile?
- 'make' should use the above CFLAGS and produce an
executable
yup
Did I provide a README to explain any problems or
issues I encountered?
- Make sure that your text is well-formatted, plain
ASCII in proper English. Use a spell checker.
yes
Did I check the return value of all function calls?
- Yes, that does include but is not limited to malloc(3).
for non atomic / fillable ones yes
Did I send error messages to stderr? Did I use
strerror(3) or perror(3) etc. to print meaningful
error messages?
yeah we have a unified err interface!!
Did I use only meaningful and necessary comments?
- Your comments should explain the 'why', not the
'what'.
yes
Does my program only generate meaningful output?
Debugging information should be removed.
yes
Does my program return zero on success, non-zero otherwise?
yeah
Did I make sure that my .h files only include function
forward declarations, macros, etc., no function
implementations or other code?
n/a
Did I check that I have avoided code duplication?
Writing the same or very similar code multiple times
is a sign that my program could benefit from being
restructured.
yes
For any string manipulation, did I use size-bounded
functions?
- Use strlcat(3)/strlcpy(3) instead of
strcat(3)/strcpy(3) etc.
yeah

149
ls.c Normal file
View file

@ -0,0 +1,149 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
void ls_ent(const char *path);
void do_regfile(const char *path, const struct stat *sb);
void do_dir(const char *path, const struct stat *sb);
void do_symlink(const char *path, const struct stat *sb);
void do_blockdev(const char *path, const struct stat *sb);
void do_char(const char *path, const struct stat *sb);
void do_fifo(const char *path, const struct stat *sb);
void do_socket(const char *path, const struct stat *sb);
void do_unknown(const char *path, const struct stat *sb);
int
main(int argc, char *argv[])
{
int i;
if (argc == 1) {
ls_ent(".");
} else {
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
/* argparsing */
} else {
ls_ent(argv[i]);
}
}
}
return 0;
}
void
ls_ent(const char *path)
{
struct stat sb;
if (lstat(path, &sb) == -1) {
err(1, "Failed to stat %s", path);
}
switch (sb.st_mode & S_IFMT) {
case S_IFREG:
do_regfile(path, &sb);
break;
case S_IFDIR:
do_dir(path, &sb);
break;
case S_IFLNK:
do_symlink(path, &sb);
break;
case S_IFCHR:
do_char(path, &sb);
break;
case S_IFIFO:
do_fifo(path, &sb);
break;
case S_IFSOCK:
do_socket(path, &sb);
break;
default:
do_unknown(path, &sb);
break;
}
}
void
do_regfile(const char *path, const struct stat *sb)
{
(void)sb;
printf("reg: %s\n", path);
}
void
do_dir(const char *path, const struct stat *sb)
{
DIR *d;
struct dirent *dir;
char full_path[PATH_MAX];
(void)sb;
d = opendir(path);
if (!d) {
err(1, "Failed to open dir: %s", path);
}
printf("dir: %s\n", path);
while ((dir = readdir(d))) {
/* avoids infinite recursion :( */
if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) {
continue;
}
snprintf(full_path, sizeof(full_path), "%s/%s", path, dir->d_name);
ls_ent(full_path);
}
closedir(d);
}
void
do_symlink(const char *path, const struct stat *sb)
{
(void)sb;
printf("sym: %s\n", path);
}
void
do_blockdev(const char *path, const struct stat *sb)
{
(void)sb;
printf("blk: %s\n", path);
}
void
do_char(const char *path, const struct stat *sb)
{
(void)sb;
printf("char: %s\n", path);
}
void
do_fifo(const char *path, const struct stat *sb)
{
(void)sb;
printf("fifo: %s\n", path);
}
void
do_socket(const char *path, const struct stat *sb)
{
(void)sb;
printf("sock: %s\n", path);
}
void
do_unknown(const char *path, const struct stat *sb)
{
(void)sb;
printf("wtf: %s\n", path);
}

45
lstest.sh Normal file
View file

@ -0,0 +1,45 @@
#! /bin/sh
#set -e
COMMANDS="./ls
./ls -l
./ls -la
./ls -lai
./ls -lairt
./ls -lairtus
./ls -d
./ls -d .
./ls -d . .. /
./ls -n /home
./ls -l /dev
./ls -lsh
./ls -lF
./ls -A ~/testdir
./ls -w ~/testdir
./ls ~/testdir | more
./ls ~/testdir/d
./ls -l ~/testdir/d
./ls -la ~/testdir/d
BLOCKSIZE=bacon ./ls -ls
BLOCKSIZE=0 ./ls -ls
BLOCKSIZE=2048 ./ls -ls
BLOCKSIZE=-50 ./ls -ls
BLOCKSIZE=50 ./ls -ls
TZ=PST8PDT ./ls -lc
TZ=bacon ./ls -lc
./ls -lks
./ls / /tmp ~ .
./ls -?
./ls /does/not/exit
./ls /nowhere"
IFS="
"
for c in ${COMMANDS}; do
echo ${c}
timeout --foreground 60 sh -c "eval ${c}" || echo timed out
done
echo "./ls -lR /"
timeout 600 ./ls -lR / || echo timed out

107
mktestdir.sh Normal file
View file

@ -0,0 +1,107 @@
#! /bin/sh
set -e
mkdir -p testdir
cd testdir
mkdir d
touch empty
mkfifo fifo
echo file > file
ln file file2
ln -s "" emptylink
ln -s /nowhere
ln -s file2 symlink
touch -a -t 201810012222 atime
touch -t 196912010000 longago
touch -t 300011111111 inthefuture
mkdir subdir
chmod 1755 subdir
ln -s . subdir/loopdir
touch executable
chmod 755 executable
touch suid:sgid
chmod 6755 suid:sgid
touch missing-exec
chmod 4000 missing-exec
touch " "
touch " "
touch "foo bar"
su root -c "chown nobody:operator file"
su root -c "chown games:daemon d"
#sudo chown nobody:operator file
#sudo chown games:daemon d
#su root -c "cp /dev/wd0 ."
touch noowner
su root -c "chown 1234 noowner"
#sudo chown 1234 noowner
touch nogroup
su root -c "chown :1234 nogroup"
#sudo chown :1234 nogroup
ln -s / "ls-LR"
su root -c "cp -a /dev/null null"
#sudo cp -a /dev/null null
touch $(yes a | head -255 | tr -d '\n')
cat >hole.c <<EOF
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char buf1[] = "abcdefghij";
char buf2[] = "ABCDEFGHIJ";
#define BIGNUM 10240000
int
main(void) {
int fd;
if ((fd = creat("file.hole", S_IRUSR | S_IWUSR)) < 0) {
perror("creat error");
return EXIT_FAILURE;
}
if (write(fd, buf1, strlen(buf1)) != (ssize_t)strlen(buf1)) {
perror("error writing buf1");
return EXIT_FAILURE;
}
if (lseek(fd, BIGNUM, SEEK_CUR) == -1) {
perror("lseek error");
return EXIT_FAILURE;
}
if (write(fd, buf2, strlen(buf2)) != (ssize_t)strlen(buf2)) {
perror("error writing buf2");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
EOF
cc -Wall -Werror hole.c
./a.out
mkdir nested
cd nested
(
for i in `jot 512`; do
mkdir $i
cd $i
done
)
(
for i in `jot 30`; do
mkdir `yes a | head -255 | tr -d '\n'`
ln -s a* b
cd b
done
)

6
readme.rst Normal file
View file

@ -0,0 +1,6 @@
==
ls
==
above was spellchecked by claude3

8
shell.nix Normal file
View file

@ -0,0 +1,8 @@
{ pkgs ? import <nixpkgs> {}}:
pkgs.mkShell {
buildInputs = with pkgs; [
gcc
clang-tools
];
}