init
This commit is contained in:
commit
4e11b595a3
9 changed files with 508 additions and 0 deletions
82
.clang-format
Normal file
82
.clang-format
Normal 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
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*.o
|
||||||
|
ls
|
21
Makefile
Normal file
21
Makefile
Normal 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
88
checklist
Normal 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
149
ls.c
Normal 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
45
lstest.sh
Normal 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
107
mktestdir.sh
Normal 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
6
readme.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
==
|
||||||
|
ls
|
||||||
|
==
|
||||||
|
|
||||||
|
|
||||||
|
above was spellchecked by claude3
|
8
shell.nix
Normal file
8
shell.nix
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{ pkgs ? import <nixpkgs> {}}:
|
||||||
|
|
||||||
|
pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
gcc
|
||||||
|
clang-tools
|
||||||
|
];
|
||||||
|
}
|
Loading…
Reference in a new issue