diff --git a/Dockerfile b/Dockerfile index dd56d201d37704b134996beea1b08f21a8500352..1066c2c8841a23dc7cb0ecdedd4863a0433f72e7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,13 @@ FROM gitlab.cs.pub.ro:5050/so2/so2-assignments RUN echo "Hello from Docker" +RUN mkdir -p /linux/tools/labs/skels/assignments/0-list +RUN mkdir -p /linux/tools/labs/skels/assignments/0-list-checker + +COPY ./checker/0-list-checker /linux/tools/labs/skels/assignments/0-list-checker + +COPY ./checker/checker_daemons/so2_vm_checker_daemon.sh /linux/tools/labs/rootfs/etc/init.d +RUN chmod +x /linux/tools/labs/rootfs/etc/init.d/so2_vm_checker_daemon.sh +RUN chroot /linux/tools/labs/rootfs update-rc.d so2_vm_checker_daemon.sh defaults COPY ./checker ${CHECKER_DATA_DIRECTORY} diff --git a/checker/0-list-checker/_checker b/checker/0-list-checker/_checker new file mode 100644 index 0000000000000000000000000000000000000000..4f15f8846818ad6c85ae1f1b237de403fdf41b7b --- /dev/null +++ b/checker/0-list-checker/_checker @@ -0,0 +1,775 @@ +#!/bin/sh + +# +# List kernel API checker +# +# + +# Enable/disable debug (1/0). +DEBUG_=1 + +DEBUG() +{ + if test "x$DEBUG_" = "x1"; then + $@ 1>&2 + fi +} + +max_points=90 + +# Enable/disable exiting when program fails. +EXIT_IF_FAIL=0 + +test_do_fail() +{ + points=$1 + printf "failed [00/%02d]\n" "$max_points" + if test "x$EXIT_IF_FAIL" = "x1"; then + exit 1 + fi +} + +test_do_pass() +{ + points=$1 + printf "passed [%02d/%02d]\n" "$points" "$max_points" +} + +basic_test() +{ + message=$1 + points=$2 + shift 2 + test_command=$@ + + printf "%s" "$message" + + i=0 + limit=$((60 - ${#message})) + while test "$i" -lt "$limit"; do + printf "." + i=$(($i+1)) + done + + $test_command > /dev/null 2>&1 + if test $? -eq 0; then + test_do_pass "$points" + else + test_do_fail "$points" + fi +} + +module="list" +module_file="$module".ko +proc_folder="/proc/list" +preview="$proc_folder/preview" +management="$proc_folder/management" + +init_test() +{ + dmesg -c > /dev/null 2>&1 + insmod "$module_file" + if test $? -ne 0; then + echo "Error inserting module." 1>&2 + exit 1 + fi + sleep 1 +} + +cleanup_test() +{ + rmmod "$module" +} + +test_module_exists() +{ + init_test + + lsmod 2> /dev/null | grep -w list > /dev/null 2>&1 + basic_test "module_exists" 1 test "$?" -eq 0 + + cleanup_test +} + +test_proc_folder_exits() +{ + init_test + + basic_test "folder_exists" 1 test -d "$proc_folder" + + cleanup_test +} + +test_preview_exits() +{ + init_test + + basic_test "preview_exists" 1 test -f "$preview" + + cleanup_test +} + +test_management_exits() +{ + init_test + + basic_test "management_exists" 1 test -f "$management" + + cleanup_test +} + +test_preview_is_readable() +{ + init_test + + cat "$preview" > /dev/null 2>&1 + basic_test "preview_is_readable" 1 test $? -eq 0 + + cleanup_test +} + +test_preview_is_not_writable() +{ + init_test + + echo "hello" 2>&1 > "$preview" | grep "Input/output error" > /dev/null + basic_test "preview_is_not_writable" 1 test $? -eq 0 + + cleanup_test +} + +test_management_is_writable() +{ + init_test + + echo "hello" 2>&1 > "$management" | grep "Input/output error" > /dev/null + basic_test "management_is_writable" 1 test $? -ne 0 + + cleanup_test +} + +test_management_is_not_readable() +{ + init_test + + cat "$management" > /dev/null 2>&1 + basic_test "management_is_not_readable" 1 test $? -ne 0 + + cleanup_test +} + +test_addf_no_error() +{ + init_test + + echo "addf lorem" > "$management" 2> /dev/null + basic_test "addf_no_error" 2 test $? -eq 0 + + cleanup_test +} + +test_addf_print() +{ + init_test + + echo "addf lorem" > "$management" + cat "$preview" | grep "lorem" > /dev/null + basic_test "addf_print" 2 test $? -eq 0 + + cleanup_test +} + +test_addf_print_once() +{ + init_test + + echo "addf lorem" > "$management" + no=$(cat "$preview" | grep "lorem" | wc -l) + basic_test "addf_print_once" 2 test "$no" -eq 1 + + cleanup_test +} + +test_adde_no_error() +{ + init_test + + echo "adde lorem" > "$management" 2> /dev/null + basic_test "adde_no_error" 2 test $? -eq 0 + + cleanup_test +} + +test_adde_print() +{ + init_test + + echo "adde lorem" > "$management" + cat "$preview" | grep "lorem" > /dev/null + basic_test "adde_print" 2 test $? -eq 0 + + cleanup_test +} + +test_adde_print_once() +{ + init_test + + echo "adde lorem" > "$management" + no=$(cat "$preview" | grep "lorem" | wc -l) + basic_test "adde_print_once" 2 test "$no" -eq 1 + + cleanup_test +} + +test_addf_two_number() +{ + init_test + + echo "addf lorem" > "$management" + echo "addf ipsum" > "$management" + no=$(cat "$preview" | wc -l) + basic_test "addf_two_number" 2 test "$no" -eq 2 + + cleanup_test +} + +test_addf_two_content() +{ + init_test + + echo "addf lorem" > "$management" + echo "addf ipsum" > "$management" + cat "$preview" | grep "lorem" > /dev/null + ret1=$? + cat "$preview" | grep "ipsum" > /dev/null + ret2=$? + basic_test "addf_two_content" 2 test "$ret1" -eq 0 -a "$ret2" -eq 0 + + cleanup_test +} + +test_addf_same_twice_number() +{ + init_test + + echo "addf lorem" > "$management" + echo "addf lorem" > "$management" + no=$(cat "$preview" | wc -l) + basic_test "addf_same_twice_number" 2 test "$no" -eq 2 + + cleanup_test +} + +test_addf_same_twice_content() +{ + init_test + + echo "addf lorem" > "$management" + echo "addf lorem" > "$management" + cat "$preview" | grep "lorem" > /dev/null + basic_test "addf_same_twice_content" 2 test $? -eq 0 + + cleanup_test +} + +test_addf_same_twice_content_number() +{ + init_test + + echo "addf lorem" > "$management" + echo "addf lorem" > "$management" + no=$(cat "$preview" | grep "lorem" | wc -l) + basic_test "addf_same_twice_content_number" 2 test "$no" -eq 2 + + cleanup_test +} + +test_adde_two_number() +{ + init_test + + echo "adde lorem" > "$management" + echo "adde ipsum" > "$management" + no=$(cat "$preview" | wc -l) + basic_test "adde_two_number" 2 test "$no" -eq 2 + + cleanup_test +} + +test_adde_two_content() +{ + init_test + + echo "adde lorem" > "$management" + echo "adde ipsum" > "$management" + cat "$preview" | grep "lorem" > /dev/null + ret1=$? + cat "$preview" | grep "ipsum" > /dev/null + ret2=$? + basic_test "adde_two_content" 2 test "$ret1" -eq 0 -a "$ret2" -eq 0 + + cleanup_test +} + +test_adde_same_twice_number() +{ + init_test + + echo "adde lorem" > "$management" + echo "adde lorem" > "$management" + no=$(cat "$preview" | wc -l) + basic_test "adde_same_twice_number" 2 test "$no" -eq 2 + + cleanup_test +} + +test_adde_same_twice_content() +{ + init_test + + echo "adde lorem" > "$management" + echo "adde lorem" > "$management" + cat "$preview" | grep "lorem" > /dev/null + basic_test "adde_same_twice_content" 2 test $? -eq 0 + + cleanup_test +} + +test_adde_same_twice_content_number() +{ + init_test + + echo "adde lorem" > "$management" + echo "adde lorem" > "$management" + no=$(cat "$preview" | grep "lorem" | wc -l) + basic_test "adde_same_twice_content_number" 2 test "$no" -eq 2 + + cleanup_test +} + +test_addf_front_after_addf() +{ + init_test + + echo "addf lorem" > "$management" + echo "addf ipsum" > "$management" + + # "ipsum" must be first. + cat "$preview" | head -n 1 | grep "ipsum" > /dev/null + basic_test "addf_front_after_addf" 2 test $? -eq 0 + + cleanup_test +} + +test_addf_front_after_adde() +{ + init_test + + echo "adde lorem" > "$management" + echo "addf ipsum" > "$management" + + # "ipsum" must be first. + cat "$preview" | head -n 1 | grep "ipsum" > /dev/null + basic_test "addf_front_after_adde" 2 test $? -eq 0 + + cleanup_test +} + +test_addf_front_after_adde_addf() +{ + init_test + + echo "adde lorem" > "$management" + echo "addf ipsum" > "$management" + echo "addf dolor" > "$management" + + # "dolor" must be first. + cat "$preview" | head -n 1 | grep "dolor" > /dev/null + basic_test "addf_front_after_adde_addf" 2 test $? -eq 0 + + cleanup_test +} + +test_addf_front_after_addf_adde() +{ + init_test + + echo "addf lorem" > "$management" + echo "adde ipsum" > "$management" + echo "addf dolor" > "$management" + + # "dolor" must be first. + cat "$preview" | head -n 1 | grep "dolor" > /dev/null + basic_test "addf_front_after_addf_adde" 2 test $? -eq 0 + + cleanup_test +} + +test_adde_end_after_addf() +{ + init_test + + echo "addf lorem" > "$management" + echo "adde ipsum" > "$management" + + # "ipsum" must be last. + cat "$preview" | tail -n -1 | grep "ipsum" > /dev/null + basic_test "adde_end_after_addf" 2 test $? -eq 0 + + cleanup_test +} + +test_adde_end_after_adde() +{ + init_test + + echo "adde lorem" > "$management" + echo "adde ipsum" > "$management" + + # "ipsum" must be last. + cat "$preview" | tail -n -1 | grep "ipsum" > /dev/null + basic_test "addf_end_after_adde" 2 test $? -eq 0 + + cleanup_test +} + +test_adde_end_after_adde_addf() +{ + init_test + + echo "adde lorem" > "$management" + echo "addf ipsum" > "$management" + echo "adde dolor" > "$management" + + # "dolor" must be last. + cat "$preview" | tail -n -1 | grep "dolor" > /dev/null + basic_test "adde_end_after_adde_addf" 2 test $? -eq 0 + + cleanup_test +} + +test_adde_end_after_addf_adde() +{ + init_test + + echo "addf lorem" > "$management" + echo "adde ipsum" > "$management" + echo "adde dolor" > "$management" + + # "dolor" must be last. + cat "$preview" | tail -n -1 | grep "dolor" > /dev/null + basic_test "adde_end_after_addf_adde" 2 test $? -eq 0 + + cleanup_test +} + +test_delf_no_error() +{ + init_test + + echo "addf lorem" > "$management" + echo "delf lorem" > "$management" + basic_test "delf_no_error" 2 test $? -eq 0 + + cleanup_test +} + +test_delf_removes_front() +{ + init_test + + echo "addf lorem" > "$management" + echo "delf lorem" > "$management" + no=$(cat "$preview" | wc -l) + basic_test "delf_removes_front" 2 test "$no" -eq 0 + + cleanup_test +} + +test_delf_removes_end() +{ + init_test + + echo "adde lorem" > "$management" + echo "delf lorem" > "$management" + no=$(cat "$preview" | wc -l) + basic_test "delf_removes_end" 2 test "$no" -eq 0 + + cleanup_test +} + +test_delf_front_number() +{ + init_test + + echo "addf lorem" > "$management" + echo "addf ipsum" > "$management" + echo "addf dolor" > "$management" + echo "delf lorem" > "$management" + no=$(cat "$preview" | wc -l) + basic_test "delf_front_number" 2 test "$no" -eq 2 + + cleanup_test +} + +test_delf_front_content() +{ + init_test + + echo "addf lorem" > "$management" + echo "addf ipsum" > "$management" + echo "addf dolor" > "$management" + echo "delf lorem" > "$management" + cat "$preview" | grep "lorem" > /dev/null + basic_test "delf_front_content" 2 test $? -ne 0 + + cleanup_test +} + +test_delf_first() +{ + init_test + + echo "addf lorem" > "$management" + echo "addf ipsum" > "$management" + echo "addf dolor" > "$management" + echo "delf ipsum" > "$management" + cat "$preview" | grep "ipsum" > /dev/null + basic_test "delf_first" 2 test $? -ne 0 + + cleanup_test +} + +test_delf_none() +{ + init_test + + echo "addf lorem" > "$management" + echo "adde ipsum" > "$management" + echo "delf dolor" > "$management" 2> /dev/null + no=$(cat "$preview" | wc -l) + basic_test "delf_none" 2 test "$no" -eq 2 + + cleanup_test +} + +test_dela_one_number() +{ + init_test + + echo "addf lorem" > "$management" + echo "addf ipsum" > "$management" + echo "addf dolor" > "$management" + echo "dela ipsum" > "$management" + no=$(cat "$preview" | wc -l) + basic_test "dela_one_number" 2 test "$no" -eq 2 + + cleanup_test +} + +test_dela_one_content() +{ + init_test + + echo "addf lorem" > "$management" + echo "addf ipsum" > "$management" + echo "addf dolor" > "$management" + echo "dela ipsum" > "$management" + cat "$preview" | grep "ipsum" > /dev/null + basic_test "dela_one_content" 2 test $? -ne 0 + + cleanup_test +} + +test_dela_two_number() +{ + init_test + + echo "addf lorem" > "$management" + echo "addf ipsum" > "$management" + echo "addf dolor" > "$management" + echo "adde ipsum" > "$management" + echo "dela ipsum" > "$management" + no=$(cat "$preview" | wc -l) + basic_test "dela_one_number" 2 test "$no" -eq 2 + + cleanup_test +} + +test_dela_two_content() +{ + init_test + + echo "adde lorem" > "$management" + echo "addf ipsum" > "$management" + echo "addf dolor" > "$management" + echo "adde ipsum" > "$management" + echo "dela ipsum" > "$management" + cat "$preview" | grep "ipsum" > /dev/null + basic_test "dela_one_content" 2 test $? -ne 0 + + cleanup_test +} + +test_dela_all_five_number() +{ + init_test + + echo "addf lorem" > "$management" + echo "adde lorem" > "$management" + echo "addf lorem" > "$management" + echo "adde lorem" > "$management" + echo "addf lorem" > "$management" + echo "dela lorem" > "$management" + no=$(cat "$preview" | wc -l) + basic_test "dela_all_five_number" 2 test "$no" -eq 0 + + cleanup_test +} + +test_dela_all_five_content() +{ + init_test + + echo "addf lorem" > "$management" + echo "adde lorem" > "$management" + echo "addf lorem" > "$management" + echo "adde lorem" > "$management" + echo "addf lorem" > "$management" + echo "dela lorem" > "$management" + cat "$preview" | grep "lorem" > /dev/null + basic_test "dela_all_five_content" 2 test $? -ne 0 + + cleanup_test +} + +test_dela_none() +{ + init_test + + echo "adde lorem" > "$management" + echo "addf ipsum" > "$management" + echo "dela dolor" > "$management" 2> /dev/null + no=$(cat "$preview" | wc -l) + basic_test "dela_none" 2 test "$no" -eq 2 + + cleanup_test +} + +test_mix_number() +{ + init_test + + echo "addf lorem" > "$management" + echo "adde ipsum" > "$management" + echo "adde dolor" > "$management" + echo "addf sit" > "$management" + echo "adde sit" > "$management" + echo "addf sit" > "$management" + echo "addf lorem" > "$management" + echo "delf lorem" > "$management" + echo "delf dolor" > "$management" + echo "adde dolor" > "$management" + echo "dela sit" > "$management" + echo "delf ipsum" > "$management" + echo "delf ipsum" > "$management" + echo "dela dolor" > "$management" + no=$(cat "$preview" | wc -l) + basic_test "mix_number" 3 test "$no" -eq 1 + + cleanup_test +} + +test_mix_content() +{ + init_test + + echo "addf lorem" > "$management" + echo "adde ipsum" > "$management" + echo "adde dolor" > "$management" + echo "addf sit" > "$management" + echo "adde sit" > "$management" + echo "addf sit" > "$management" + echo "addf lorem" > "$management" + echo "delf lorem" > "$management" + echo "delf dolor" > "$management" + echo "adde dolor" > "$management" + echo "dela sit" > "$management" + echo "delf ipsum" > "$management" + echo "delf ipsum" > "$management" + echo "dela dolor" > "$management" + cat "$preview" | grep "lorem" > /dev/null + basic_test "mix_content" 3 test "$no" -eq 1 + + cleanup_test +} + +run_tests() +{ + test_module_exists + test_proc_folder_exits + test_preview_exits + test_management_exits + test_preview_is_readable + test_preview_is_not_writable + test_management_is_writable + test_management_is_not_readable + test_addf_no_error + test_addf_print + test_addf_print_once + test_adde_no_error + test_adde_print + test_adde_print_once + test_addf_two_number + test_addf_two_content + test_addf_same_twice_number + test_addf_same_twice_content + test_addf_same_twice_content_number + test_adde_two_number + test_adde_two_content + test_adde_same_twice_number + test_adde_same_twice_content + test_adde_same_twice_content_number + test_addf_front_after_addf + test_addf_front_after_adde + test_addf_front_after_adde_addf + test_addf_front_after_addf_adde + test_adde_end_after_addf + test_adde_end_after_adde + test_adde_end_after_adde_addf + test_adde_end_after_addf_adde + test_delf_no_error + test_delf_removes_front + test_delf_removes_end + test_delf_front_number + test_delf_front_content + test_delf_first + test_delf_none + test_dela_one_number + test_dela_one_content + test_dela_two_number + test_dela_two_content + test_dela_all_five_number + test_dela_all_five_content + test_dela_none + test_mix_number + test_mix_content +} + +run_tests | tee results.txt + +cat results.txt | grep '\[.*\]$' | awk -F '[] /[]+' ' +BEGIN { + sum=0 +} + +{ + sum += $(NF-2); +} + +END { + printf "\n%66s [%02d/90]\n", "Total:", sum; +}' + +rm results.txt diff --git a/checker/checker.sh b/checker/checker.sh index 12d97bb9a00a2b634dbbf4f08a32ec20167cab4b..a3a809760c4464fa390eb2365560ff4e7436cad1 100755 --- a/checker/checker.sh +++ b/checker/checker.sh @@ -1,108 +1,86 @@ #!/bin/bash -EXECUTABLE="../src/perfect" -TIMEOUT_DURATION=10 -SCORE=0 -TOTAL_SCORE=0 - -test_err() +TIMEOUT=300 # 5 min +SO2_WORKSPACE=/linux/tools/labs +ASSIGNMENT0_MOD=list.ko +ASSIGNMENT0_DIR=${SO2_WORKSPACE}/skels/assignments/0-list +ASSIGNMENT0_CHECKER_DIR=${SO2_WORKSPACE}/skels/assignments/0-list-checker +ASSIGNMENT0_OUTPUT=${SO2_WORKSPACE}/skels/0-list-output +ASSIGNMENT0_FINISHED=${SO2_WORKSPACE}/skels/0-list-finished + +usage() { - local temp_output='' - temp_output="$(mktemp)" - - timeout "$TIMEOUT_DURATION" bash -c "$EXECUTABLE {} > $temp_output 2>&1" - - diff -Zq "$temp_output" "./references/ref1" > /dev/null 2>&1 - return $? -} - -test_single() -{ - local temp_output='' - temp_output="$(mktemp)" - - timeout "$TIMEOUT_DURATION" xargs -a ./input/input2 -0 -I{} bash -c "$EXECUTABLE {} > $temp_output 2>&1" - - diff -Zq "$temp_output" "./references/ref2" > /dev/null 2>&1 - return $? + echo "Usage: $0 <assignment>" + exit 1 } -test_multiple() +timeout_exceeded() { - local temp_output='' - temp_output="$(mktemp)" - - timeout "$TIMEOUT_DURATION" xargs -a ./input/input3 -0 -I{} bash -c "$EXECUTABLE {} > $temp_output 2>&1" - - diff -Zq "$temp_output" "./references/ref3" > /dev/null 2>&1 - return $? + echo TIMEOUT EXCEEDED !!! killing the process + pkill -SIGKILL qemu + exit 1 } -test_edge() +run_checker() { - local temp_output='' - temp_output="$(mktemp)" - - timeout "$TIMEOUT_DURATION" xargs -a ./input/input4 -0 -I{} bash -c "$EXECUTABLE {} > $temp_output 2>&1" - - diff -Zq "$temp_output" "./references/ref4" > /dev/null 2>&1 - return $? -} - -setup() -{ - pushd ../src > /dev/null || exit 1 - make -s build - popd > /dev/null || exit 1 -} - -cleanup() -{ - pushd ../src > /dev/null || exit 1 - make -s clean - popd > /dev/null || exit 1 -} - -test_fun_array=( \ - test_err "Name 1" 25 \ - test_single "Name 2" 25 \ - test_multiple "Name 3" 25 \ - test_edge "Name 4" 25 \ -) - -run_test() -{ - test_index="$1" - test_func_index=$((test_index * 3)) - description=${test_fun_array[$((test_func_index + 1))]} - points=${test_fun_array[$((test_func_index + 2))]} - TOTAL_SCORE=$((TOTAL_SCORE + points)) - - echo -ne "Testing\t\t$description\t" - if ${test_fun_array["$test_func_index"]} ; then - SCORE=$((SCORE + points)) - echo "$points/$points" - return 0 - else - echo "0/$points" - return 1 - fi -} - -test_all() -{ - for i in $(seq 0 "$((${#test_fun_array[@]} / 3 - 1))") ; do - run_test "$i" - done - - echo -e "\nTotal: $SCORE/$TOTAL_SCORE" + local assignment_mod=$1 + local assignment_dir=$2 + local checker_dir=$3 + local output=$4 + local finished=$5 + local assignment=$6 + + local module_path="${assignment_dir}/${assignment_mod}" + + pushd /linux/tools/labs + if [ -f $module_path ]; then + echo "Removing ${module_path}" + fi + if [ -f $output ]; then + echo "Removing $output" + rm $output &> /dev/null + fi + if [ -f $finished ]; then + echo "Removing $finished" + rm $finished &> /dev/null + fi + + echo "Building..." + make build + + if [ ! -f $module_path ]; then + echo "Cannot find $assignment_mod" + exit 1 + fi + + # copy *.ko in checker + echo "Copying $module_path into $checker_dir" + cp $module_path $checker_dir + + LINUX_ADD_CMDLINE="so2=$assignment" ./qemu/run-qemu.sh &> /dev/null & + + echo -n "CHECKER IS RUNNING" + while [ ! -f $finished ] + do + if ((timeout >= TIMEOUT)); then + if [ -f $output ]; then + cat $output + fi + timeout_exceeded + fi + sleep 2 + (( timeout += 2 )) + echo -n . + done + cat $output + popd } -setup -if [ -z "$1" ] ; then - test_all -else - run_test "$1" - exit $? -fi -cleanup +case $1 in + 0-list) + run_checker $ASSIGNMENT0_MOD $ASSIGNMENT0_DIR $ASSIGNMENT0_CHECKER_DIR $ASSIGNMENT0_OUTPUT $ASSIGNMENT0_FINISHED $1 + ;; + *) + usage + ;; +esac diff --git a/checker/checker_daemons/so2_vm_checker_daemon.sh b/checker/checker_daemons/so2_vm_checker_daemon.sh new file mode 100644 index 0000000000000000000000000000000000000000..162bba828b1df65015196bfd5a3acf2b96d8015e --- /dev/null +++ b/checker/checker_daemons/so2_vm_checker_daemon.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +# THIS SCRIPT RUNS INSIDE THE SO2 VM + +ASSIGNMENT0_CHECKER=/home/root/skels/assignments/0-list-checker +ASSIGNMENT0_OUTPUT=/home/root/skels/0-list-output +ASSIGNMENT0_FINISHED=/home/root/skels/0-list-finished + +assign0_list() +{ + cd $ASSIGNMENT0_CHECKER + sh _checker &> $ASSIGNMENT0_OUTPUT + echo FINISHED &> $ASSIGNMENT0_FINISHED + cd - +} + +start() +{ + local arg=$(cat /proc/cmdline | grep -o 'so2=[^ ]*' | cut -d= -f2) + case "$arg" in + 0-list) + assign0_list + ;; + *) + echo "Unknown option" + exit 0 + ;; + esac +} + +# Carry out specific functions when asked to by the system +case "$1" in + start) + echo "Starting so2_vm_checker_daemon.sh..." + start + ;; + stop) + echo "Stopping so2_vm_checker_daemon.sh..." + sleep 2 + ;; + *) + echo "Usage: /etc/init.d/foo {start|stop}" + exit 1 + ;; + esac + +exit 0 + diff --git a/checker/input/input1 b/checker/input/input1 deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/checker/input/input2 b/checker/input/input2 deleted file mode 100644 index 56a6051ca2b02b04ef92d5150c9ef600403cb1de..0000000000000000000000000000000000000000 --- a/checker/input/input2 +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/checker/input/input3 b/checker/input/input3 deleted file mode 100644 index e440e5c842586965a7fb77deda2eca68612b1f53..0000000000000000000000000000000000000000 --- a/checker/input/input3 +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/checker/input/input4 b/checker/input/input4 deleted file mode 100644 index c227083464fb9af8955c90d2924774ee50abb547..0000000000000000000000000000000000000000 --- a/checker/input/input4 +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/checker/references/ref1 b/checker/references/ref1 deleted file mode 100644 index 8fac0de40be37c53e8a1d0ee97e6aa632c41b0b9..0000000000000000000000000000000000000000 --- a/checker/references/ref1 +++ /dev/null @@ -1 +0,0 @@ -Not enough arguments! diff --git a/checker/references/ref2 b/checker/references/ref2 deleted file mode 100644 index d00491fd7e5bb6fa28c517a0bb32b8b506539d4d..0000000000000000000000000000000000000000 --- a/checker/references/ref2 +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/checker/references/ref3 b/checker/references/ref3 deleted file mode 100644 index cc3759002bf5280e344eeadc5dbf9ea31b3e0b78..0000000000000000000000000000000000000000 --- a/checker/references/ref3 +++ /dev/null @@ -1 +0,0 @@ -1 1 1 diff --git a/checker/references/ref4 b/checker/references/ref4 deleted file mode 100644 index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000 --- a/checker/references/ref4 +++ /dev/null @@ -1 +0,0 @@ - diff --git a/local.sh b/local.sh index da63f8fc12b8e5885f04c5348e700b7e79fe549e..c68b2822be04c0a22f46272f713a8467be47219d 100755 --- a/local.sh +++ b/local.sh @@ -13,6 +13,12 @@ DEFAULT_IMAGE_NAME="so2/0-list" DEFAULT_TAG='latest' DEFAULT_REGISTRY='gitlab.cs.pub.ro:5050' +SRC_DIR="$(realpath ./src)" +CHECKER_BASE_DIR="$(realpath ./checker)" +ASSIGNMENT_CHECKER_DIR="$(realpath ./checker/0-list-checker)" +SO2_WORKSPACE=/linux/tools/labs +ASSIGNMENT_MOUNT_DIR="${SO2_WORKSPACE}/skels/assignments/0-list" +ASSIGNMENT_CHECKER_MOUNT_DIR="${SO2_WORKSPACE}/skels/assignments/0-list-checker" MOUNT_PROJECT_DIRECTORY="/build/$USER/$(basename "$(pwd)")" #============================================================================= @@ -61,10 +67,11 @@ print_help() { echo " --full_image_name <full_image_name> - the full name of the image (default: gitlab.cs.pub.ro:5050/<current_directory_name>:latest)" echo " argumets_for_checker - list of space separated arguments to be passed to the checker" echo "" - echo "local.sh docker interactive [--full_image_name <full_image_name>] [--use_executable <executbale>]" + echo "local.sh docker interactive [--full_image_name <full_image_name>] [--use_executable <executbale>] [--privileged]" echo "" echo " --full_image_name <full_image_name> - the full name of the image (default: gitlab.cs.pub.ro:5050/<current_directory_name>:latest)" echo " --use_executable <executable> - command to run inside the container (default: /bin/bash)" + echo " --privileged - run a privileged container. This allows the use of KVM" echo "" echo "local.sh checker [--remove_image] [--use_existing_image <image_name>] [--force_build] [argumets_for_checker]" echo "" @@ -179,16 +186,20 @@ docker_interactive() { shift executable="$1" ;; + --privileged) + privileged=--privileged esac shift done tmpdir="$(mktemp -d)" - cp -R ./* "$tmpdir" - - docker run --rm -it \ - --mount type=bind,source="$tmpdir",target="$MOUNT_PROJECT_DIRECTORY" \ - --workdir "$MOUNT_PROJECT_DIRECTORY" \ + set -x + cp -R ${ASSIGNMENT_CHECKER_DIR}/* "$tmpdir" + + docker run $privileged --rm -it \ + --mount type=bind,source="$SRC_DIR",target="$ASSIGNMENT_MOUNT_DIR" \ + --mount type=bind,source="$tmpdir",target="$ASSIGNMENT_CHECKER_MOUNT_DIR" \ + --workdir "$SO2_WORKSPACE" \ "$full_image_name" "$executable" } @@ -240,6 +251,12 @@ checker_main() { docker build "${extra_docker_args[@]}" -q -t "$image_name" . fi + assign_tmpdir="$(mktemp -d)" + cp -R ${SRC_DIR}/* "$assign_tmpdir" + + assign_check_tmpdir="$(mktemp -d)" + cp -R ${ASSIGNMENT_CHECKER_DIR}/* "$assign_check_tmpdir" + tmpdir="$(mktemp -d)" cp -R ./* "$tmpdir" @@ -249,6 +266,8 @@ checker_main() { # otherwise stick to relative paths. # It is guaranteed that the current working directory in which checker.sh will run is $CI_PROJECT_DIR/checker. docker run --rm \ + --mount type=bind,source="$assign_tmpdir",target="$ASSIGNMENT_MOUNT_DIR" \ + --mount type=bind,source="$assign_check_tmpdir",target="$ASSIGNMENT_CHECKER_MOUNT_DIR" \ --mount type=bind,source="$tmpdir",target="$MOUNT_PROJECT_DIRECTORY" \ "$image_name" /bin/bash -c "rm -rf /usr/local/bin/bash; cd \"$MOUNT_PROJECT_DIRECTORY/checker\"; \"$MOUNT_PROJECT_DIRECTORY/checker/checker.sh\" \"${script_args[@]}\"" # remove bash middleware script diff --git a/src/Kbuild b/src/Kbuild new file mode 100644 index 0000000000000000000000000000000000000000..5e45a816841549a017843600ee193089cabdb5c1 --- /dev/null +++ b/src/Kbuild @@ -0,0 +1 @@ +obj-m = list.o diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index 6e912480cca5dbb79e0aa01c5d509f22e1902f29..0000000000000000000000000000000000000000 --- a/src/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -build: main.c - gcc main.c -o perfect - -.PHONY: clean - -clean: - rm perfect diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000000000000000000000000000000000000..9584f21d3229ce9031bf6788a3f29a7b1898dc9d --- /dev/null +++ b/src/list.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * list.c - Linux kernel list API + * + * TODO 1/0: Fill in name / email + * Author: FirstName LastName <user@email.com> + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/list.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <linux/uaccess.h> + +#define PROCFS_MAX_SIZE 512 + +#define procfs_dir_name "list" +#define procfs_file_read "preview" +#define procfs_file_write "management" + +struct proc_dir_entry *proc_list; +struct proc_dir_entry *proc_list_read; +struct proc_dir_entry *proc_list_write; + +/* TODO 2: define your list! */ + +static int list_proc_show(struct seq_file *m, void *v) +{ + /* TODO 3: print your list. One element / line. */ + seq_puts(m, "Remove this line\n"); + + return 0; +} + +static int list_read_open(struct inode *inode, struct file *file) +{ + return single_open(file, list_proc_show, NULL); +} + +static int list_write_open(struct inode *inode, struct file *file) +{ + return single_open(file, list_proc_show, NULL); +} + +static ssize_t list_write(struct file *file, const char __user *buffer, + size_t count, loff_t *offs) +{ + char local_buffer[PROCFS_MAX_SIZE]; + unsigned long local_buffer_size = 0; + + local_buffer_size = count; + if (local_buffer_size > PROCFS_MAX_SIZE) + local_buffer_size = PROCFS_MAX_SIZE; + + memset(local_buffer, 0, PROCFS_MAX_SIZE); + if (copy_from_user(local_buffer, buffer, local_buffer_size)) + return -EFAULT; + + /* local_buffer contains your command written in /proc/list/management + * TODO 4/0: parse the command and add/delete elements. + */ + + return local_buffer_size; +} + +static const struct proc_ops r_pops = { + .proc_open = list_read_open, + .proc_read = seq_read, + .proc_release = single_release, +}; + +static const struct proc_ops w_pops = { + .proc_open = list_write_open, + .proc_write = list_write, + .proc_release = single_release, +}; + +static int list_init(void) +{ + proc_list = proc_mkdir(procfs_dir_name, NULL); + if (!proc_list) + return -ENOMEM; + + proc_list_read = proc_create(procfs_file_read, 0000, proc_list, + &r_pops); + if (!proc_list_read) + goto proc_list_cleanup; + + proc_list_write = proc_create(procfs_file_write, 0000, proc_list, + &w_pops); + if (!proc_list_write) + goto proc_list_read_cleanup; + + return 0; + +proc_list_read_cleanup: + proc_remove(proc_list_read); +proc_list_cleanup: + proc_remove(proc_list); + return -ENOMEM; +} + +static void list_exit(void) +{ + proc_remove(proc_list); +} + +module_init(list_init); +module_exit(list_exit); + +MODULE_DESCRIPTION("Linux kernel list API"); +/* TODO 5: Fill in your name / email address */ +MODULE_AUTHOR("FirstName LastName <your@email.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 4556184bc231930d22e9ff3c17b81cfdc93525e5..0000000000000000000000000000000000000000 --- a/src/main.c +++ /dev/null @@ -1,7 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char **argv) -{ - return 0; -} diff --git a/src/solution.c b/src/solution.c deleted file mode 100644 index ac5e990d44ffd6f848e80cd7a06dbf24c2a1d6a3..0000000000000000000000000000000000000000 --- a/src/solution.c +++ /dev/null @@ -1,18 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char **argv) -{ - if (argc != 2) { - fprintf(stderr, "Not enough arguments!\n"); - return 1; - } - - int number = atoi(argv[1]); - - for (int i = 0; i < number; i++) - printf("1 "); - - printf("\n"); - return 0; -}